mirror of
https://github.com/chylex/IntelliJ-AceJump.git
synced 2025-09-17 10:24:48 +02:00
Compare commits
2 Commits
5979579042
...
broken-ide
Author | SHA1 | Date | |
---|---|---|---|
82de69d53c
|
|||
ffb4573eda
|
@@ -8,7 +8,7 @@ plugins {
|
|||||||
}
|
}
|
||||||
|
|
||||||
group = "org.acejump"
|
group = "org.acejump"
|
||||||
version = "chylex-22"
|
version = "chylex-21"
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
|
@@ -14,9 +14,13 @@ enum class KeyLayout(
|
|||||||
COLEMK(arrayOf("1234567890", "qwfpgjluy", "arstdhneio", "zxcvbkm"), priority = "tndhseriaovkcmbxzgjplfuwyq5849673210"),
|
COLEMK(arrayOf("1234567890", "qwfpgjluy", "arstdhneio", "zxcvbkm"), priority = "tndhseriaovkcmbxzgjplfuwyq5849673210"),
|
||||||
WORKMN(arrayOf("1234567890", "qdrwbjfup", "ashtgyneoi", "zxmcvkl"), priority = "tnhegysoaiclvkmxzwfrubjdpq5849673210"),
|
WORKMN(arrayOf("1234567890", "qdrwbjfup", "ashtgyneoi", "zxmcvkl"), priority = "tnhegysoaiclvkmxzwfrubjdpq5849673210"),
|
||||||
DVORAK(arrayOf("1234567890", "pyfgcrl", "aoeuidhtns", "qjkxbmwvz"), priority = "uhetidonasxkbjmqwvzgfycprl5849673210"),
|
DVORAK(arrayOf("1234567890", "pyfgcrl", "aoeuidhtns", "qjkxbmwvz"), priority = "uhetidonasxkbjmqwvzgfycprl5849673210"),
|
||||||
QWERTY(arrayOf("1234567890", "qwertyuiop", "asdfghjkl", "zxcvbnm"), priority = "fjghdkslavncmbxzrutyeiwoqp5849673210", characterSides = sides(listOf("123456", "qwert", "asdfg", "zxcvb"), listOf("7890", "yuiop", "hjkl", "nm"))),
|
QWERTY(arrayOf("1234567890", "qwertyuiop", "asdfghjkl", "zxcvbnm"), priority = "fjghdkslavncmbxzrutyeiwoqp5849673210"),
|
||||||
QWERTZ(arrayOf("1234567890", "qwertzuiop", "asdfghjkl", "yxcvbnm"), priority = "fjghdkslavncmbxyrutzeiwoqp5849673210", characterSides = sides(listOf("123456", "qwert", "asdfg", "yxcvb"), listOf("7890", "zuiop", "hjkl", "nm"))),
|
QWERTZ(arrayOf("1234567890", "qwertzuiop", "asdfghjkl", "yxcvbnm"), priority = "fjghdkslavncmbxyrutzeiwoqp5849673210"),
|
||||||
QWERTZ_CZ(arrayOf("1234567890", "qwertzuiop", "asdfghjkl", "yxcvbnm"), priority = "fjghdkslavncmbxyrutzeiwoqp5849673210", characterSides = sides(listOf("123456", "qwert", "asdfg", "yxcvb"), listOf("7890", "zuiop", "hjkl", "nm")), characterRemapping = mapOf(
|
QWERTZ_CZ(
|
||||||
|
arrayOf("1234567890", "qwertzuiop", "asdfghjkl", "yxcvbnm"),
|
||||||
|
priority = "fjghdkslavncmbxyrutzeiwoqp5849673210",
|
||||||
|
characterSides = sides("", ""),
|
||||||
|
characterRemapping = mapOf(
|
||||||
'+' to '1',
|
'+' to '1',
|
||||||
'ě' to '2',
|
'ě' to '2',
|
||||||
'š' to '3',
|
'š' to '3',
|
||||||
@@ -27,7 +31,8 @@ enum class KeyLayout(
|
|||||||
'á' to '8',
|
'á' to '8',
|
||||||
'í' to '9',
|
'í' to '9',
|
||||||
'é' to '0'
|
'é' to '0'
|
||||||
)),
|
)
|
||||||
|
),
|
||||||
QGMLWY(arrayOf("1234567890", "qgmlwyfub", "dstnriaeoh", "zxcvjkp"), priority = "naterisodhvkcpjxzlfmuwygbq5849673210"),
|
QGMLWY(arrayOf("1234567890", "qgmlwyfub", "dstnriaeoh", "zxcvjkp"), priority = "naterisodhvkcpjxzlfmuwygbq5849673210"),
|
||||||
QGMLWB(arrayOf("1234567890", "qgmlwbyuv", "dstnriaeoh", "zxcfjkp"), priority = "naterisodhfkcpjxzlymuwbgvq5849673210"),
|
QGMLWB(arrayOf("1234567890", "qgmlwbyuv", "dstnriaeoh", "zxcfjkp"), priority = "naterisodhfkcpjxzlymuwbgvq5849673210"),
|
||||||
NORMAN(arrayOf("1234567890", "qwdfkjurl", "asetgynioh", "zxcvbpm"), priority = "tneigysoahbvpcmxzjkufrdlwq5849673210");
|
NORMAN(arrayOf("1234567890", "qwdfkjurl", "asetgynioh", "zxcvbpm"), priority = "tneigysoahbvpcmxzjkufrdlwq5849673210");
|
||||||
@@ -35,18 +40,11 @@ enum class KeyLayout(
|
|||||||
internal val allChars = rows.joinToString("").toCharArray().apply(CharArray::sort).joinToString("")
|
internal val allChars = rows.joinToString("").toCharArray().apply(CharArray::sort).joinToString("")
|
||||||
private val allPriorities = priority.mapIndexed { index, char -> char to index }.toMap()
|
private val allPriorities = priority.mapIndexed { index, char -> char to index }.toMap()
|
||||||
|
|
||||||
fun priority(char: Char): Int {
|
internal fun priority(): (Char) -> Int {
|
||||||
return allPriorities[char] ?: allChars.length
|
return { allPriorities.getOrDefault(it, Int.MAX_VALUE) }
|
||||||
}
|
|
||||||
|
|
||||||
fun areOnSameSide(c1: Char, c2: Char): Boolean {
|
|
||||||
return (c1 in characterSides.first && c2 in characterSides.first) || (c1 in characterSides.second && c2 in characterSides.second)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun sides(left: List<String>, right: List<String>): Pair<Set<Char>, Set<Char>> {
|
private fun sides(left: String, right: String): Pair<Set<Char>, Set<Char>> {
|
||||||
return Pair(
|
return Pair(left.toCharArray().toSet(), right.toCharArray().toSet())
|
||||||
left.flatMapTo(mutableSetOf()) { it.toCharArray().toSet() },
|
|
||||||
right.flatMapTo(mutableSetOf()) { it.toCharArray().toSet() }
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
@@ -1,22 +1,20 @@
|
|||||||
package org.acejump.input
|
package org.acejump.input
|
||||||
|
|
||||||
import org.acejump.config.AceSettings
|
import org.acejump.config.AceSettings
|
||||||
import kotlin.math.pow
|
|
||||||
import kotlin.math.roundToInt
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stores data specific to the selected keyboard layout. We want to assign tags with easily reachable keys first, and ideally have tags
|
* Stores data specific to the selected keyboard layout. We want to assign tags with easily reachable keys first, and ideally have tags
|
||||||
* with repeated keys (ex. FF, JJ) or adjacent keys (ex. GH, UJ).
|
* with repeated keys (ex. FF, JJ) or adjacent keys (ex. GH, UJ).
|
||||||
*/
|
*/
|
||||||
internal object KeyLayoutCache {
|
internal object KeyLayoutCache {
|
||||||
lateinit var allowedTagsSorted: List<String>
|
lateinit var allowedCharsSorted: List<Char>
|
||||||
private set
|
private set
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called before any lazily initialized properties are used, to ensure that they are initialized even if the settings are missing.
|
* Called before any lazily initialized properties are used, to ensure that they are initialized even if the settings are missing.
|
||||||
*/
|
*/
|
||||||
fun ensureInitialized(settings: AceSettings) {
|
fun ensureInitialized(settings: AceSettings) {
|
||||||
if (!::allowedTagsSorted.isInitialized) {
|
if (!::allowedCharsSorted.isInitialized) {
|
||||||
reset(settings)
|
reset(settings)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -25,38 +23,17 @@ internal object KeyLayoutCache {
|
|||||||
* Re-initializes cached data according to updated settings.
|
* Re-initializes cached data according to updated settings.
|
||||||
*/
|
*/
|
||||||
fun reset(settings: AceSettings) {
|
fun reset(settings: AceSettings) {
|
||||||
val allowedChars = processCharList(settings.allowedChars).ifEmpty { processCharList(settings.layout.allChars) }
|
val allowedCharList = processCharList(settings.allowedChars)
|
||||||
val allowedTags = mutableSetOf<String>()
|
|
||||||
|
|
||||||
for (c1 in allowedChars) {
|
allowedCharsSorted = if (allowedCharList.isEmpty()) {
|
||||||
allowedTags.add("$c1")
|
processCharList(settings.layout.allChars)
|
||||||
|
|
||||||
for (c2 in allowedChars) {
|
|
||||||
if (c1 != c2) {
|
|
||||||
allowedTags.add("$c1$c2")
|
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
allowedCharList.sortedWith(compareBy(settings.layout.priority()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
allowedTagsSorted = allowedTags.sortedBy { rankPriority(settings.layout, it) }
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun processCharList(charList: String): List<Char> {
|
private fun processCharList(charList: String): List<Char> {
|
||||||
return charList.toCharArray().map(Char::lowercaseChar).distinct()
|
return charList.toCharArray().map(Char::lowercaseChar).distinct()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun rankPriority(layout: KeyLayout, tag: String): Int {
|
|
||||||
val c1 = tag.first()
|
|
||||||
val p1 = (1.0 + layout.priority(c1)).pow(3)
|
|
||||||
|
|
||||||
if (tag.length == 1) {
|
|
||||||
return p1.roundToInt()
|
|
||||||
}
|
|
||||||
|
|
||||||
val c2 = tag.last()
|
|
||||||
val p2 = (1.0 + layout.priority(c2)).pow(3)
|
|
||||||
|
|
||||||
val multiplier = if (layout.areOnSameSide(c1, c2)) 2 else 1
|
|
||||||
return (((p1 * 50) + p2 + 1000) * multiplier).roundToInt()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@@ -62,33 +62,28 @@ class Tagger(private val editors: List<Editor>, results: Map<Editor, IntList>) {
|
|||||||
|
|
||||||
private companion object {
|
private companion object {
|
||||||
private fun generateTags(tagSites: List<Tag>): List<String> {
|
private fun generateTags(tagSites: List<Tag>): List<String> {
|
||||||
|
val allowedChars = KeyLayoutCache.allowedCharsSorted
|
||||||
|
|
||||||
val tags = mutableListOf<String>()
|
val tags = mutableListOf<String>()
|
||||||
|
var remainingTagCount = tagSites.size
|
||||||
|
|
||||||
val containedSingleCharTags = mutableSetOf<Char>()
|
outer@ for (i in allowedChars.indices) {
|
||||||
val blockedSingleCharTags = mutableSetOf<Char>()
|
val c1 = allowedChars[i]
|
||||||
|
|
||||||
for (tag in KeyLayoutCache.allowedTagsSorted) {
|
if (remainingTagCount <= allowedChars.size - i) {
|
||||||
val firstChar = tag.first()
|
tags.add(c1.toString())
|
||||||
|
if (--remainingTagCount <= 0) {
|
||||||
if (tag.length == 1) {
|
break@outer
|
||||||
if (firstChar in blockedSingleCharTags) {
|
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
|
|
||||||
containedSingleCharTags.add(firstChar)
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (containedSingleCharTags.remove(firstChar)) {
|
for (c2 in allowedChars) {
|
||||||
tags.remove(firstChar.toString())
|
tags.add("$c1$c2")
|
||||||
|
|
||||||
|
if (--remainingTagCount <= 0) {
|
||||||
|
break@outer
|
||||||
}
|
}
|
||||||
|
|
||||||
blockedSingleCharTags.add(firstChar)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tags.add(tag)
|
|
||||||
|
|
||||||
if (tags.size >= tagSites.size) {
|
|
||||||
return tags
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -12,13 +12,10 @@ import java.awt.Rectangle
|
|||||||
* Describes a 1 or 2 character shortcut that points to a specific character in the editor.
|
* Describes a 1 or 2 character shortcut that points to a specific character in the editor.
|
||||||
*/
|
*/
|
||||||
internal class TagMarker(
|
internal class TagMarker(
|
||||||
private val firstChar: String,
|
private val tag: CharArray,
|
||||||
private val secondChar: String,
|
|
||||||
val offset: Int
|
val offset: Int
|
||||||
) {
|
) {
|
||||||
private constructor(tag: String, offset: Int) : this(tag.first().toString(), tag.drop(1), offset)
|
private val length = tag.size
|
||||||
|
|
||||||
private val length = firstChar.length + secondChar.length
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
/**
|
/**
|
||||||
@@ -31,7 +28,7 @@ internal class TagMarker(
|
|||||||
* character ([typedTag]) matches the first [tag] character, only the second [tag] character is displayed.
|
* character ([typedTag]) matches the first [tag] character, only the second [tag] character is displayed.
|
||||||
*/
|
*/
|
||||||
fun create(tag: String, offset: Int, typedTag: String): TagMarker {
|
fun create(tag: String, offset: Int, typedTag: String): TagMarker {
|
||||||
return TagMarker(tag.drop(typedTag.length), offset)
|
return TagMarker(tag.drop(typedTag.length).toCharArray(), offset)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -68,11 +65,11 @@ internal class TagMarker(
|
|||||||
|
|
||||||
g.font = font.tagFont
|
g.font = font.tagFont
|
||||||
g.color = font.foregroundColor1
|
g.color = font.foregroundColor1
|
||||||
g.drawString(firstChar, x, y)
|
g.drawChars(tag, 0, 1, x, y)
|
||||||
|
|
||||||
if (secondChar.isNotEmpty()) {
|
if (tag.size > 1) {
|
||||||
g.color = font.foregroundColor2
|
g.color = font.foregroundColor2
|
||||||
g.drawString(secondChar, x + font.tagCharWidth, y)
|
g.drawChars(tag, 1, length - 1, x + font.tagCharWidth, y)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user