diff --git a/build.gradle.kts b/build.gradle.kts index 3a55072..aed2e5f 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -5,7 +5,7 @@ plugins { } group = "com.chylex.intellij.keyboardmaster" -version = "0.1.1" +version = "0.1.2" repositories { mavenCentral() diff --git a/src/main/kotlin/com/chylex/intellij/keyboardmaster/configuration/PluginConfigurable.kt b/src/main/kotlin/com/chylex/intellij/keyboardmaster/configuration/PluginConfigurable.kt new file mode 100644 index 0000000..af1eb34 --- /dev/null +++ b/src/main/kotlin/com/chylex/intellij/keyboardmaster/configuration/PluginConfigurable.kt @@ -0,0 +1,75 @@ +package com.chylex.intellij.keyboardmaster.configuration + +import com.intellij.openapi.options.Configurable +import com.intellij.ui.components.JBTextField +import com.intellij.util.ui.FormBuilder +import javax.swing.JComponent +import javax.swing.JPanel + +class PluginConfigurable : Configurable { + private lateinit var component: JComponent + + private val charFields = Array(10) { + JBTextField(5) + } + + override fun getDisplayName(): String { + return "Keyboard Master" + } + + override fun createComponent(): JComponent { + var builder = FormBuilder.createFormBuilder() + + for (index in 1..9) { + builder = builder.addLabeledComponent("Code completion char $index: ", charFields[index]) + } + + builder = builder.addLabeledComponent("Code completion next page char: ", charFields[0]) + builder = builder.addComponentFillVertically(JPanel(), 0) + component = builder.panel + + return component + } + + override fun isModified(): Boolean { + return true + } + + override fun apply() { + fun getChar(index: Int): Int { + return charFields[index].text.firstOrNull()?.code ?: 0 + } + + val instance = PluginConfiguration.instance + instance.charOption1 = getChar(1) + instance.charOption2 = getChar(2) + instance.charOption3 = getChar(3) + instance.charOption4 = getChar(4) + instance.charOption5 = getChar(5) + instance.charOption6 = getChar(6) + instance.charOption7 = getChar(7) + instance.charOption8 = getChar(8) + instance.charOption9 = getChar(9) + instance.charNextPage = getChar(0) + + PluginConfiguration.update() + } + + override fun reset() { + fun setChar(index: Int, char: Int) { + charFields[index].text = if (char == 0) "" else char.toChar().toString() + } + + val instance = PluginConfiguration.instance + setChar(1, instance.charOption1) + setChar(2, instance.charOption2) + setChar(3, instance.charOption3) + setChar(4, instance.charOption4) + setChar(5, instance.charOption5) + setChar(6, instance.charOption6) + setChar(7, instance.charOption7) + setChar(8, instance.charOption8) + setChar(9, instance.charOption9) + setChar(0, instance.charNextPage) + } +} diff --git a/src/main/kotlin/com/chylex/intellij/keyboardmaster/configuration/PluginConfiguration.kt b/src/main/kotlin/com/chylex/intellij/keyboardmaster/configuration/PluginConfiguration.kt new file mode 100644 index 0000000..1e75dac --- /dev/null +++ b/src/main/kotlin/com/chylex/intellij/keyboardmaster/configuration/PluginConfiguration.kt @@ -0,0 +1,69 @@ +package com.chylex.intellij.keyboardmaster.configuration + +import com.intellij.openapi.application.ApplicationManager +import com.intellij.openapi.components.PersistentStateComponent +import com.intellij.openapi.components.State +import com.intellij.openapi.components.Storage +import com.intellij.util.containers.IntIntHashMap +import com.intellij.util.xmlb.XmlSerializerUtil +import it.unimi.dsi.fastutil.ints.Int2IntMap + +@State( + name = "com.chylex.intellij.keyboardmaster.configuration.PluginConfiguration", + storages = [Storage("KeyboardMaster.xml")] +) +class PluginConfiguration : PersistentStateComponent<PluginConfiguration> { + var charOption1: Int = '1'.code + var charOption2: Int = '2'.code + var charOption3: Int = '3'.code + var charOption4: Int = '4'.code + var charOption5: Int = '5'.code + var charOption6: Int = '6'.code + var charOption7: Int = '7'.code + var charOption8: Int = '8'.code + var charOption9: Int = '9'.code + var charNextPage: Int = '0'.code + + companion object { + val instance: PluginConfiguration + get() = ApplicationManager.getApplication().getService(PluginConfiguration::class.java) + + val charToIndexMap: Int2IntMap = IntIntHashMap(10, -1) + val hintText = Array(10) { "" } + + init { + instance + update() + } + + fun update() { + val instance = instance + + charToIndexMap.clear() + charToIndexMap[instance.charOption1] = 1 + charToIndexMap[instance.charOption2] = 2 + charToIndexMap[instance.charOption3] = 3 + charToIndexMap[instance.charOption4] = 4 + charToIndexMap[instance.charOption5] = 5 + charToIndexMap[instance.charOption6] = 6 + charToIndexMap[instance.charOption7] = 7 + charToIndexMap[instance.charOption8] = 8 + charToIndexMap[instance.charOption9] = 9 + charToIndexMap[instance.charNextPage] = 0 + + for (entry in charToIndexMap.int2IntEntrySet()) { + val hintIndex = if (entry.intValue == 0) 9 else entry.intValue - 1 + val charText = if (entry.intKey == 0) "" else " [${entry.intKey.toChar()}]" + hintText[hintIndex] = charText + } + } + } + + override fun getState(): PluginConfiguration { + return this + } + + override fun loadState(state: PluginConfiguration) { + XmlSerializerUtil.copyBean(state, this) + } +} diff --git a/src/main/kotlin/com/chylex/intellij/keyboardmaster/lookup/LookupTypedActionHandler.kt b/src/main/kotlin/com/chylex/intellij/keyboardmaster/lookup/LookupTypedActionHandler.kt index 202b159..5e19f0e 100644 --- a/src/main/kotlin/com/chylex/intellij/keyboardmaster/lookup/LookupTypedActionHandler.kt +++ b/src/main/kotlin/com/chylex/intellij/keyboardmaster/lookup/LookupTypedActionHandler.kt @@ -1,5 +1,6 @@ package com.chylex.intellij.keyboardmaster.lookup +import com.chylex.intellij.keyboardmaster.configuration.PluginConfiguration import com.intellij.codeInsight.lookup.LookupManager import com.intellij.codeInsight.lookup.impl.LookupImpl import com.intellij.codeInsight.template.impl.editorActions.TypedActionHandlerBase @@ -20,7 +21,8 @@ class LookupTypedActionHandler(originalHandler: TypedActionHandler?) : TypedActi } private fun executeImpl(editor: Editor, charTyped: Char): Boolean { - if (charTyped !in '0'..'9') { + val mappedIndex = PluginConfiguration.charToIndexMap[charTyped.code] + if (mappedIndex == -1) { return false } @@ -31,7 +33,7 @@ class LookupTypedActionHandler(originalHandler: TypedActionHandler?) : TypedActi val offset = ProjectLookupListener.getLookupOffset(lookup) - if (charTyped == '0') { + if (mappedIndex == 0) { val list = lookup.list val itemCount = list.model.size val topIndex = (offset + 9).let { if (it >= itemCount) 0 else it } @@ -43,7 +45,7 @@ class LookupTypedActionHandler(originalHandler: TypedActionHandler?) : TypedActi lookup.refreshUi(false, true) } else { - lookup.selectedIndex = offset + (charTyped - '1') + lookup.selectedIndex = offset + mappedIndex - 1 } return true diff --git a/src/main/kotlin/com/chylex/intellij/keyboardmaster/lookup/ProjectLookupListener.kt b/src/main/kotlin/com/chylex/intellij/keyboardmaster/lookup/ProjectLookupListener.kt index ddeb65a..1c5b133 100644 --- a/src/main/kotlin/com/chylex/intellij/keyboardmaster/lookup/ProjectLookupListener.kt +++ b/src/main/kotlin/com/chylex/intellij/keyboardmaster/lookup/ProjectLookupListener.kt @@ -1,5 +1,6 @@ package com.chylex.intellij.keyboardmaster.lookup +import com.chylex.intellij.keyboardmaster.configuration.PluginConfiguration import com.intellij.codeInsight.lookup.Lookup import com.intellij.codeInsight.lookup.LookupElementPresentation import com.intellij.codeInsight.lookup.LookupManagerListener @@ -14,8 +15,6 @@ class ProjectLookupListener : LookupManagerListener { private val OFFSET_KEY = Key.create<Int>("chylexKeyboardMasterOffset") private val IS_MODIFIED_KEY = Key.create<Boolean>("chylexKeyboardMasterModified") - private val HINT_TEXT = Array(9) { " [${it + 1}]" } - fun getLookupOffset(lookup: LookupImpl): Int { val offset = lookup.getUserData(OFFSET_KEY) if (offset == null || offset >= lookup.list.model.size) { @@ -44,17 +43,20 @@ class ProjectLookupListener : LookupManagerListener { val itemCount = itemList.size val offset = getLookupOffset(newLookup) - for (digitIndex in 0 until 9) { - val itemIndex = offset + digitIndex + for (index in 0 until 9) { + val itemIndex = offset + index if (itemIndex >= itemCount) { break } if (item === itemList.getElementAt(itemIndex)) { - val customized = LookupElementPresentation() - customized.copyFrom(presentation) - customized.appendTailTextItalic(HINT_TEXT[digitIndex], true) - return@addPresentationCustomizer customized + val hint = PluginConfiguration.hintText[index] + if (hint != "") { + val customized = LookupElementPresentation() + customized.copyFrom(presentation) + customized.appendTailTextItalic(hint, true) + return@addPresentationCustomizer customized + } } } diff --git a/src/main/resources/META-INF/plugin.xml b/src/main/resources/META-INF/plugin.xml index 29f736b..1b7bf88 100644 --- a/src/main/resources/META-INF/plugin.xml +++ b/src/main/resources/META-INF/plugin.xml @@ -6,7 +6,7 @@ <description><![CDATA[ Collection of keyboard-centric additions. <ul> - <li>Code completion items can be jumped to using numbers.</li> + <li>Code completion items can be jumped to using customizable characters (numbers by default).</li> </ul> ]]></description> @@ -17,6 +17,8 @@ </projectListeners> <extensions defaultExtensionNs="com.intellij"> + <applicationService serviceImplementation="com.chylex.intellij.keyboardmaster.configuration.PluginConfiguration" /> + <applicationConfigurable parentId="tools" instance="com.chylex.intellij.keyboardmaster.configuration.PluginConfigurable" id="com.chylex.keyboardmaster" /> <!--suppress PluginXmlValidity, PluginXmlDynamicPlugin --> <editorTypedHandler implementationClass="com.chylex.intellij.keyboardmaster.lookup.LookupTypedActionHandler" /> </extensions>