1
0
mirror of https://github.com/chylex/IntelliJ-AceJump.git synced 2025-05-01 17:34:08 +02:00

Redo tag generation (eliminate explicit prefix chars)

This commit is contained in:
chylex 2024-09-03 20:46:21 +02:00
parent 01c38df82a
commit ffb4573eda
Signed by: chylex
GPG Key ID: 4DE42C8F19A80548
6 changed files with 43 additions and 30 deletions

View File

@ -13,7 +13,6 @@ class AceConfigurable : Configurable {
override fun isModified() =
panel.allowedChars != settings.allowedChars ||
panel.prefixChars != settings.prefixChars ||
panel.keyboardLayout != settings.layout ||
panel.minQueryLengthInt != settings.minQueryLength ||
panel.editorFadeOpacityPercent != settings.editorFadeOpacity ||
@ -24,7 +23,6 @@ class AceConfigurable : Configurable {
override fun apply() {
settings.allowedChars = panel.allowedChars
settings.prefixChars = panel.prefixChars
settings.layout = panel.keyboardLayout
settings.minQueryLength = panel.minQueryLengthInt ?: settings.minQueryLength
settings.editorFadeOpacity = panel.editorFadeOpacityPercent

View File

@ -8,7 +8,6 @@ import java.awt.Color
data class AceSettings(
var layout: KeyLayout = QWERTY,
var allowedChars: String = layout.allChars,
var prefixChars: String = ";",
var minQueryLength: Int = 1,
var editorFadeOpacity: Int = 70,

View File

@ -26,7 +26,6 @@ import kotlin.reflect.KProperty
@Suppress("UsePropertyAccessSyntax")
internal class AceSettingsPanel {
private val tagAllowedCharsField = JBTextField()
private val tagPrefixCharsField = JBTextField()
private val keyboardLayoutCombo = ComboBox<KeyLayout>()
private val keyboardLayoutArea = JBTextArea().apply { isEditable = false }
private val minQueryLengthField = JBTextField()
@ -45,7 +44,6 @@ internal class AceSettingsPanel {
init {
tagAllowedCharsField.apply { font = Font("monospaced", font.style, font.size) }
tagPrefixCharsField.apply { font = Font("monospaced", font.style, font.size) }
keyboardLayoutArea.apply { font = Font("monospaced", font.style, font.size) }
keyboardLayoutCombo.setupEnumItems { keyChars = it.rows.joinToString("\n") }
}
@ -53,7 +51,6 @@ internal class AceSettingsPanel {
internal val rootPanel: JPanel = panel {
group("Characters and Layout") {
row("Allowed characters in tags:") { cell(tagAllowedCharsField).columns(COLUMNS_LARGE) }
row("Allowed prefix characters in tags:") { cell(tagPrefixCharsField).columns(COLUMNS_MEDIUM) }
row("Keyboard layout:") { cell(keyboardLayoutCombo).columns(COLUMNS_SHORT) }
row("Keyboard design:") { cell(keyboardLayoutArea).columns(COLUMNS_SHORT) }
}
@ -81,7 +78,6 @@ internal class AceSettingsPanel {
// Property-to-property delegation: https://stackoverflow.com/q/45074596/1772342
internal var allowedChars by tagAllowedCharsField
internal var prefixChars by tagPrefixCharsField
internal var keyboardLayout by keyboardLayoutCombo
internal var keyChars by keyboardLayoutArea
internal var minQueryLength by minQueryLengthField
@ -101,7 +97,6 @@ internal class AceSettingsPanel {
fun reset(settings: AceSettings) {
allowedChars = settings.allowedChars
prefixChars = settings.prefixChars
keyboardLayout = settings.layout
minQueryLength = settings.minQueryLength.toString()
editorFadeOpacityPercent = settings.editorFadeOpacity

View File

@ -30,7 +30,7 @@ enum class KeyLayout(internal val rows: Array<String>, priority: String, interna
internal val allChars = rows.joinToString("").toCharArray().apply(CharArray::sort).joinToString("")
internal val allPriorities = priority.mapIndexed { index, char -> char to index }.toMap()
internal inline fun priority(crossinline tagToChar: (String) -> Char): (String) -> Int {
return { allPriorities.getOrDefault(tagToChar(it), Int.MAX_VALUE) }
internal fun priority(): (Char) -> Int {
return { allPriorities.getOrDefault(it, Int.MAX_VALUE) }
}
}

View File

@ -7,17 +7,14 @@ import org.acejump.config.AceSettings
* with repeated keys (ex. FF, JJ) or adjacent keys (ex. GH, UJ).
*/
internal object KeyLayoutCache {
/**
* Returns all possible two key tags, pre-sorted according to [tagOrder].
*/
lateinit var allPossibleTagsLowercase: List<String>
lateinit var allowedCharsSorted: List<Char>
private set
/**
* Called before any lazily initialized properties are used, to ensure that they are initialized even if the settings are missing.
*/
fun ensureInitialized(settings: AceSettings) {
if (!::allPossibleTagsLowercase.isInitialized) {
if (!::allowedCharsSorted.isInitialized) {
reset(settings)
}
}
@ -26,22 +23,17 @@ internal object KeyLayoutCache {
* Re-initializes cached data according to updated settings.
*/
fun reset(settings: AceSettings) {
@Suppress("ConvertLambdaToReference")
val allSuffixChars = processCharList(settings.allowedChars).ifEmpty { processCharList(settings.layout.allChars).toList() }
val allPrefixChars = processCharList(settings.prefixChars).filterNot(allSuffixChars::contains).plus("")
val allowedCharList = processCharList(settings.allowedChars)
val tagOrder = compareBy(
String::length,
{ if (it.length == 1) Int.MIN_VALUE else allPrefixChars.indexOf(it.first().toString()) },
settings.layout.priority(String::last)
)
allPossibleTagsLowercase = allSuffixChars
.flatMap { suffix -> allPrefixChars.map { prefix -> "$prefix$suffix" } }
.sortedWith(tagOrder)
allowedCharsSorted = if (allowedCharList.isEmpty()) {
processCharList(settings.layout.allChars)
}
else {
allowedCharList.sortedWith(compareBy(settings.layout.priority()))
}
}
private fun processCharList(charList: String): Set<String> {
return charList.toCharArray().map(Char::lowercase).toSet()
private fun processCharList(charList: String): List<Char> {
return charList.toCharArray().map(Char::lowercaseChar).distinct()
}
}

View File

@ -40,7 +40,7 @@ class Tagger(private val editors: List<Editor>, results: Map<Editor, IntList>) {
.flatMap { (editor, sites) -> sites.map { site -> Tag(editor, site) } }
.sortedWith(siteOrder(editors, caches))
tagMap = KeyLayoutCache.allPossibleTagsLowercase.zip(tagSites).toMap()
tagMap = generateTags(tagSites).zip(tagSites).toMap()
}
internal fun type(char: Char): TaggingResult {
@ -61,6 +61,35 @@ class Tagger(private val editors: List<Editor>, results: Map<Editor, IntList>) {
}
private companion object {
private fun generateTags(tagSites: List<Tag>): List<String> {
val allowedChars = KeyLayoutCache.allowedCharsSorted
val tags = mutableListOf<String>()
var remainingTagCount = tagSites.size
outer@ for (i in allowedChars.indices) {
val c1 = allowedChars[i]
if (remainingTagCount <= allowedChars.size - i) {
tags.add(c1.toString())
if (--remainingTagCount <= 0) {
break@outer
}
}
else {
for (c2 in allowedChars) {
tags.add("$c1$c2")
if (--remainingTagCount <= 0) {
break@outer
}
}
}
}
return tags
}
private fun sortResults(results: Map<Editor, IntList>, caches: Map<Editor, EditorOffsetCache>) {
for ((editor, offsets) in results) {
val cache = caches.getValue(editor)