From 8e5d67614e1946dc89fe4d19589c43dfed8b14db Mon Sep 17 00:00:00 2001 From: breandan Date: Wed, 31 Oct 2018 19:50:35 -0400 Subject: [PATCH] generify keyboard layout, start implementing #172 --- .../kotlin/org/acejump/config/AceConfig.kt | 5 +-- .../kotlin/org/acejump/config/AceSettings.kt | 7 +-- .../org/acejump/config/AceSettingsPanel.kt | 28 +++++++----- src/main/kotlin/org/acejump/label/Pattern.kt | 44 +++++++++---------- src/main/kotlin/org/acejump/label/Solver.kt | 7 +-- src/main/kotlin/org/acejump/label/Tagger.kt | 4 +- src/main/kotlin/org/acejump/search/AceUtil.kt | 2 + src/main/kotlin/org/acejump/view/Model.kt | 2 + src/main/resources/AceResources.properties | 4 +- src/main/resources/META-INF/plugin.xml | 6 ++- 10 files changed, 59 insertions(+), 50 deletions(-) diff --git a/src/main/kotlin/org/acejump/config/AceConfig.kt b/src/main/kotlin/org/acejump/config/AceConfig.kt index bc4b8c72..17058489 100644 --- a/src/main/kotlin/org/acejump/config/AceConfig.kt +++ b/src/main/kotlin/org/acejump/config/AceConfig.kt @@ -5,7 +5,6 @@ import com.intellij.openapi.components.State import com.intellij.openapi.components.Storage import com.intellij.openapi.diagnostic.Logger import com.intellij.openapi.options.Configurable -import org.acejump.label.Pattern import javax.swing.JComponent /* Persists the state of the AceJump IDE settings across IDE restarts. @@ -40,12 +39,12 @@ object AceConfig : Configurable, PersistentStateComponent { panel.tagBackgroundColor != settings.tagBackgroundColor private fun String.distinctAlphanumerics() = toList().distinct().run { - if (isEmpty()) Pattern.defaultChars else filter { it.isLetterOrDigit() } + if (isEmpty()) settings.keyLayout.chars else filter { it.isLetterOrDigit() } }.joinToString("") override fun apply() { settings.allowedChars = panel.allowedChars.distinctAlphanumerics() - settings.keyboardChars = panel.keyboardChars.distinctAlphanumerics() + settings.keyboardChars = panel.keyboardChars panel.jumpModeColor?.let { settings.jumpModeRGB = it.rgb } panel.targetModeColor?.let { settings.targetModeRGB = it.rgb } panel.textHighlightColor?.let { settings.textHighlightRGB = it.rgb } diff --git a/src/main/kotlin/org/acejump/config/AceSettings.kt b/src/main/kotlin/org/acejump/config/AceSettings.kt index 48f372d9..6712d137 100644 --- a/src/main/kotlin/org/acejump/config/AceSettings.kt +++ b/src/main/kotlin/org/acejump/config/AceSettings.kt @@ -1,12 +1,13 @@ package org.acejump.config -import org.acejump.label.Pattern +import org.acejump.label.Pattern.Companion.KeyLayout import java.awt.Color import java.awt.Color.* import kotlin.reflect.KProperty -data class AceSettings(var allowedChars: String = Pattern.defaultChars.joinToString(""), - var keyboardChars: String = Pattern.keyboardKeys, +data class AceSettings(var keyLayout: KeyLayout = KeyLayout.QWERTY, + var allowedChars: String = keyLayout.toString(), + var keyboardChars: String = keyLayout.keyboard(), // These must be primitives in order to be serializable internal var jumpModeRGB: Int = BLUE.rgb, internal var targetModeRGB: Int = RED.rgb, diff --git a/src/main/kotlin/org/acejump/config/AceSettingsPanel.kt b/src/main/kotlin/org/acejump/config/AceSettingsPanel.kt index fbe66a09..296da084 100644 --- a/src/main/kotlin/org/acejump/config/AceSettingsPanel.kt +++ b/src/main/kotlin/org/acejump/config/AceSettingsPanel.kt @@ -1,12 +1,14 @@ package org.acejump.config import com.intellij.ui.ColorPanel +import com.intellij.ui.SeparatorComponent import com.intellij.ui.layout.Cell import com.intellij.ui.layout.GrowPolicy.MEDIUM_TEXT import com.intellij.ui.layout.GrowPolicy.SHORT_TEXT import com.intellij.ui.layout.panel import org.acejump.search.aceString import java.awt.Color +import java.awt.Font import javax.swing.JComponent import javax.swing.JPanel import javax.swing.JTextArea @@ -14,23 +16,27 @@ import javax.swing.JTextField import kotlin.reflect.KProperty class AceSettingsPanel { - private var tagCharactersField = JTextField() - private var jumpModeColorWheel = ColorPanel() - private var targetModeColorWheel = ColorPanel() - private var textHighlightColorWheel = ColorPanel() - private var tagForegroundColorWheel = ColorPanel() - private var tagBackgroundColorWheel = ColorPanel() - private var keyboardCharsLayout = JTextArea() + private val tagCharactersField = + JTextField().apply { font = Font("monospaced", font.style, font.size) } + private val jumpModeColorWheel = ColorPanel() + private val targetModeColorWheel = ColorPanel() + private val textHighlightColorWheel = ColorPanel() + private val tagForegroundColorWheel = ColorPanel() + private val tagBackgroundColorWheel = ColorPanel() + private val keyboardCharsLayout = JTextArea() + .apply { + font = Font("monospaced", font.style, font.size) + isEditable = false + } internal val rootPanel: JPanel = panel { fun Cell.short(component: JComponent) = component(growPolicy = SHORT_TEXT) fun Cell.medium(component: JComponent) = component(growPolicy = MEDIUM_TEXT) - noteRow(aceString("tagCharsToBeUsedHeading")) + noteRow(aceString("tagCharsToBeUsedHeading")) { SeparatorComponent() } row(aceString("tagCharsToBeUsedLabel")) { medium(tagCharactersField) } - noteRow("Alphanumeric Keyboard Characters from top to bottom") - row("Keyboard keys") { medium(keyboardCharsLayout) } - noteRow(aceString("colorsToBeUsedHeading")) + row("Keyboard layout") { medium(keyboardCharsLayout) } + noteRow(aceString("colorsToBeUsedHeading")) { SeparatorComponent() } row(aceString("jumpModeColorLabel")) { short(jumpModeColorWheel) } row(aceString("tagBackgroundColorLabel")) { short(tagBackgroundColorWheel) } row(aceString("tagForegroundColorLabel")) { short(tagForegroundColorWheel) } diff --git a/src/main/kotlin/org/acejump/label/Pattern.kt b/src/main/kotlin/org/acejump/label/Pattern.kt index 3305d056..514f7592 100644 --- a/src/main/kotlin/org/acejump/label/Pattern.kt +++ b/src/main/kotlin/org/acejump/label/Pattern.kt @@ -1,6 +1,7 @@ package org.acejump.label import org.acejump.config.AceConfig +import org.acejump.search.mapIndices /** * Patterns related to key priority, separation, and regexps for line mode. @@ -18,8 +19,6 @@ enum class Pattern(val string: String) { companion object { private fun distance(fromKey: Char, toKey: Char) = nearby[fromKey]!![toKey] - fun priority(char: Char) = priority[char] - private var allBigrams = emptyList() get() = AceConfig.settings.allowedChars .run { flatMap { e -> map { c -> "$e$c" } } } @@ -31,21 +30,12 @@ enum class Pattern(val string: String) { var NUM_CHARS: Int = 36 get() = AceConfig.settings.allowedChars.length - private val priority: Map = - "fjghdkslavncmbxzrutyeiwoqp5849673210".mapIndices() - - val defaultChars = ('a'..'z').plus('0'..'9').sortedBy { priority[it] } - val keyboardKeys = """ - 12345890 - qwertyuiop - asdfghjkl - zxcvbnm - """.trimIndent() - - val defaultOrder: Comparator = compareBy( + val defaultTagOrder: Comparator = compareBy( { it[0].isDigit() || it[1].isDigit() }, { Pattern.distance(it[0], it.last()) }, - { Pattern.priority(it[0]) }) + AceConfig.settings.keyLayout.priority { it[0] }) + + fun filterTags(query: String) = allBigrams.filter { !query.endsWith(it[0]) } /** * Sorts available tags by key distance. Tags which are ergonomically easier @@ -54,14 +44,22 @@ enum class Pattern(val string: String) { * keys (ex. 12, 21) to keys that are located further apart on the keyboard. */ - fun filterTags(query: String) = allBigrams.filter { !query.endsWith(it[0]) } + enum class KeyLayout(val text: Array) { + COLEMAK(arrayOf("1234567890", "qwfpgjluy", "arstdhneio", "zxcvbkm")), + DVORAK(arrayOf("1234567890", "pyfgcrl", "aoeuidhtns", "qjkxbmwvz")), + QWERTY(arrayOf("1234567890", "qwertyuiop", "asdfghjkl", "zxcvbnm")), + WORKMAN(arrayOf("1234567890", "qdrwbjfup", "ashtgyneoi", "zxmcvkl")); + + // TODO: Currently specialized to QWERTY, need to make this more generic + private val priority = "fjghdkslavncmbxzrutyeiwoqp5849673210".mapIndices() + val chars = text.flatMap { it.toList() }.sortedBy { priority[it] } - private val defaultKeyboardLayout = arrayOf( - "1234567890", - "qwertyuiop", - "asdfghjkl", - "zxcvbnm" - ) + fun priority(tagToChar: (String) -> Char): (String) -> Int? = + { priority[tagToChar(it)] } + + fun keyboard() = text.joinToString("\n") + override fun toString() = chars.joinToString("") + } private val nearby: Map> = mapOf( // Values are QWERTY keys sorted by physical proximity to the map key @@ -102,7 +100,5 @@ enum class Pattern(val string: String) { '9' to "9807654321ioujklpyhnmtgbrfvedcwsxqaz", '0' to "0987654321opiklujmyhntgbrfvedcwsxqaz") .mapValues { it.value.mapIndices() } - - private fun String.mapIndices() = mapIndexed { i, c -> Pair(c, i) }.toMap() } } \ No newline at end of file diff --git a/src/main/kotlin/org/acejump/label/Solver.kt b/src/main/kotlin/org/acejump/label/Solver.kt index 806a5820..1bc1e28b 100644 --- a/src/main/kotlin/org/acejump/label/Solver.kt +++ b/src/main/kotlin/org/acejump/label/Solver.kt @@ -5,7 +5,8 @@ import com.google.common.collect.Multimaps import com.google.common.collect.Ordering import com.google.common.collect.TreeMultimap import com.intellij.openapi.diagnostic.Logger -import org.acejump.label.Pattern.Companion.defaultOrder +import org.acejump.config.AceConfig +import org.acejump.label.Pattern.Companion.defaultTagOrder import org.acejump.search.wordBoundsPlus import org.acejump.view.Model.editorText import org.acejump.view.Model.viewBounds @@ -69,9 +70,9 @@ object Solver { return true } - private val tagOrder = defaultOrder + private val tagOrder = defaultTagOrder .thenBy { eligibleSitesByTag[it].size } - .thenBy { Pattern.priority(it.last()) } + .thenBy(AceConfig.settings.keyLayout.priority { it.last() }) /** * Sorts jump targets to determine which positions get first choice for tags, diff --git a/src/main/kotlin/org/acejump/label/Tagger.kt b/src/main/kotlin/org/acejump/label/Tagger.kt index a3010760..8791862c 100755 --- a/src/main/kotlin/org/acejump/label/Tagger.kt +++ b/src/main/kotlin/org/acejump/label/Tagger.kt @@ -1,7 +1,7 @@ package org.acejump.label import com.intellij.openapi.diagnostic.Logger -import org.acejump.label.Pattern.Companion.defaultOrder +import org.acejump.label.Pattern.Companion.defaultTagOrder import org.acejump.label.Pattern.Companion.filterTags import org.acejump.search.* import org.acejump.search.Jumper.hasJumped @@ -236,7 +236,7 @@ object Tagger : Resettable { } private fun solveRegex(vacantResults: List, availableTags: Set) = - availableTags.sortedWith(defaultOrder).zip(vacantResults).toMap() + availableTags.sortedWith(defaultTagOrder).zip(vacantResults).toMap() /** * Adds pre-existing tags where search string and tag overlap. For example, diff --git a/src/main/kotlin/org/acejump/search/AceUtil.kt b/src/main/kotlin/org/acejump/search/AceUtil.kt index 49952f84..7b013218 100755 --- a/src/main/kotlin/org/acejump/search/AceUtil.kt +++ b/src/main/kotlin/org/acejump/search/AceUtil.kt @@ -24,6 +24,8 @@ interface Resettable { fun aceString(s: String) = ResourceBundle.getBundle("AceResources").getString(s) +fun String.mapIndices() = mapIndexed { i, c -> Pair(c, i) }.toMap() + fun

applyTo(vararg ps: P, fx: P.() -> Unit) = ps.forEach { it.fx() } operator fun Point.component1() = x diff --git a/src/main/kotlin/org/acejump/view/Model.kt b/src/main/kotlin/org/acejump/view/Model.kt index 8f1a0492..06aaf88f 100644 --- a/src/main/kotlin/org/acejump/view/Model.kt +++ b/src/main/kotlin/org/acejump/view/Model.kt @@ -20,6 +20,8 @@ import java.awt.Font.PLAIN /** * Data holder for all settings and IDE components needed by AceJump. + * + * TODO: Integrate this class with AceSettings. */ object Model { diff --git a/src/main/resources/AceResources.properties b/src/main/resources/AceResources.properties index 4de71a0f..e08c95e0 100644 --- a/src/main/resources/AceResources.properties +++ b/src/main/resources/AceResources.properties @@ -1,5 +1,5 @@ -tagCharsToBeUsedHeading=Characters to be used when tagging (only alphanumeric characters, sorted from highest to lowest priority): -tagCharsToBeUsedLabel=Characters to be use: +tagCharsToBeUsedHeading=Characters to be used when tagging +tagCharsToBeUsedLabel=Priority (highest to lowest): colorsToBeUsedHeading=Colors to be used when tagging jumpModeColorLabel=Jump mode color: tagBackgroundColorLabel=Tag background color: diff --git a/src/main/resources/META-INF/plugin.xml b/src/main/resources/META-INF/plugin.xml index dcb453cb..c03612de 100755 --- a/src/main/resources/META-INF/plugin.xml +++ b/src/main/resources/META-INF/plugin.xml @@ -33,8 +33,10 @@ Bug fix: AceJump settings should now properly persist after restarting the IDE. - - + +