Compare commits

...

2 Commits

6 changed files with 132 additions and 12 deletions

View File

@ -5,7 +5,7 @@ plugins {
} }
group = "com.chylex.intellij.keyboardmaster" group = "com.chylex.intellij.keyboardmaster"
version = "0.1.1" version = "0.1.2"
repositories { repositories {
mavenCentral() mavenCentral()

View File

@ -0,0 +1,46 @@
package com.chylex.intellij.keyboardmaster.configuration
import com.intellij.openapi.options.Configurable
import com.intellij.ui.components.JBTextField
import com.intellij.ui.layout.panel
import javax.swing.JComponent
class PluginConfigurable : Configurable {
private lateinit var component: JComponent
private val codeCompletionItemShortcuts = JBTextField(20)
private val codeCompletionNextPageShortcut = JBTextField(2)
override fun getDisplayName(): String {
return "Keyboard Master"
}
override fun createComponent(): JComponent {
component = panel {
titledRow("Code Completion") {
row("Item shortcuts:") { component(codeCompletionItemShortcuts) }
row("Next page shortcut:") { component(codeCompletionNextPageShortcut) }
}
}
return component
}
override fun isModified(): Boolean {
return true
}
override fun apply() {
PluginConfiguration.modify {
it.codeCompletionItemShortcuts = codeCompletionItemShortcuts.text
it.codeCompletionNextPageShortcut = codeCompletionNextPageShortcut.text.firstOrNull()?.code ?: 0
}
}
override fun reset() {
PluginConfiguration.read {
codeCompletionItemShortcuts.text = it.codeCompletionItemShortcuts
codeCompletionNextPageShortcut.text = it.codeCompletionNextPageShortcut.let { code -> if (code == 0) "" else code.toChar().toString() }
}
}
}

View File

@ -0,0 +1,46 @@
package com.chylex.intellij.keyboardmaster.configuration
import com.chylex.intellij.keyboardmaster.lookup.ProjectLookupListener
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.xmlb.XmlSerializerUtil
@State(
name = "com.chylex.intellij.keyboardmaster.configuration.PluginConfiguration",
storages = [Storage("KeyboardMaster.xml")]
)
class PluginConfiguration : PersistentStateComponent<PluginConfiguration> {
var codeCompletionItemShortcuts = "123456789"
var codeCompletionNextPageShortcut: Int = '0'.code
companion object {
private val instance: PluginConfiguration
get() = ApplicationManager.getApplication().getService(PluginConfiguration::class.java)
init {
instance.apply(this::update)
}
fun read(callback: (PluginConfiguration) -> Unit) {
instance.apply(callback)
}
fun modify(callback: (PluginConfiguration) -> Unit) {
instance.apply(callback).apply(this::update)
}
private fun update(instance: PluginConfiguration) {
ProjectLookupListener.updateShortcuts(instance)
}
}
override fun getState(): PluginConfiguration {
return this
}
override fun loadState(state: PluginConfiguration) {
XmlSerializerUtil.copyBean(state, this)
}
}

View File

@ -20,7 +20,8 @@ class LookupTypedActionHandler(originalHandler: TypedActionHandler?) : TypedActi
} }
private fun executeImpl(editor: Editor, charTyped: Char): Boolean { private fun executeImpl(editor: Editor, charTyped: Char): Boolean {
if (charTyped !in '0'..'9') { val shortcutItem = ProjectLookupListener.getShortcut(charTyped)
if (shortcutItem == -1) {
return false return false
} }
@ -31,19 +32,21 @@ class LookupTypedActionHandler(originalHandler: TypedActionHandler?) : TypedActi
val offset = ProjectLookupListener.getLookupOffset(lookup) val offset = ProjectLookupListener.getLookupOffset(lookup)
if (charTyped == '0') { if (shortcutItem == 0) {
val list = lookup.list val list = lookup.list
val itemCount = list.model.size val itemCount = list.model.size
val topIndex = (offset + 9).let { if (it >= itemCount) 0 else it }
val shortcutCount = ProjectLookupListener.itemShortcutCount
val topIndex = (offset + shortcutCount).let { if (it >= itemCount) 0 else it }
ProjectLookupListener.setLookupOffset(lookup, topIndex) ProjectLookupListener.setLookupOffset(lookup, topIndex)
lookup.selectedIndex = topIndex lookup.selectedIndex = topIndex
ScrollingUtil.ensureRangeIsVisible(list, topIndex, topIndex + 8) ScrollingUtil.ensureRangeIsVisible(list, topIndex, topIndex + shortcutCount - 1)
lookup.markSelectionTouched() lookup.markSelectionTouched()
lookup.refreshUi(false, true) lookup.refreshUi(false, true)
} }
else { else {
lookup.selectedIndex = offset + (charTyped - '1') lookup.selectedIndex = offset + shortcutItem - 1
} }
return true return true

View File

@ -1,10 +1,12 @@
package com.chylex.intellij.keyboardmaster.lookup package com.chylex.intellij.keyboardmaster.lookup
import com.chylex.intellij.keyboardmaster.configuration.PluginConfiguration
import com.intellij.codeInsight.lookup.Lookup import com.intellij.codeInsight.lookup.Lookup
import com.intellij.codeInsight.lookup.LookupElementPresentation import com.intellij.codeInsight.lookup.LookupElementPresentation
import com.intellij.codeInsight.lookup.LookupManagerListener import com.intellij.codeInsight.lookup.LookupManagerListener
import com.intellij.codeInsight.lookup.impl.LookupImpl import com.intellij.codeInsight.lookup.impl.LookupImpl
import com.intellij.openapi.util.Key import com.intellij.openapi.util.Key
import com.intellij.util.containers.IntIntHashMap
/** /**
* Adds hints to code completion items with the digit that selects it. * Adds hints to code completion items with the digit that selects it.
@ -14,7 +16,28 @@ class ProjectLookupListener : LookupManagerListener {
private val OFFSET_KEY = Key.create<Int>("chylexKeyboardMasterOffset") private val OFFSET_KEY = Key.create<Int>("chylexKeyboardMasterOffset")
private val IS_MODIFIED_KEY = Key.create<Boolean>("chylexKeyboardMasterModified") private val IS_MODIFIED_KEY = Key.create<Boolean>("chylexKeyboardMasterModified")
private val HINT_TEXT = Array(9) { " [${it + 1}]" } private var hintTexts = mutableListOf<String>()
private val charToShortcutMap = IntIntHashMap(16, -1)
val itemShortcutCount
get() = hintTexts.size
fun updateShortcuts(configuration: PluginConfiguration) {
hintTexts.clear()
for (char in configuration.codeCompletionItemShortcuts) {
hintTexts.add(" [$char]")
}
charToShortcutMap.clear()
configuration.codeCompletionNextPageShortcut.takeUnless { it == 0 }?.let { charToShortcutMap[it] = 0 }
for ((index, char) in configuration.codeCompletionItemShortcuts.withIndex()) {
charToShortcutMap[char.code] = index + 1
}
}
fun getShortcut(char: Char): Int {
return charToShortcutMap[char.code]
}
fun getLookupOffset(lookup: LookupImpl): Int { fun getLookupOffset(lookup: LookupImpl): Int {
val offset = lookup.getUserData(OFFSET_KEY) val offset = lookup.getUserData(OFFSET_KEY)
@ -32,7 +55,7 @@ class ProjectLookupListener : LookupManagerListener {
} }
override fun activeLookupChanged(oldLookup: Lookup?, newLookup: Lookup?) { override fun activeLookupChanged(oldLookup: Lookup?, newLookup: Lookup?) {
if (newLookup !is LookupImpl || newLookup.getUserData(IS_MODIFIED_KEY) == true) { if (newLookup !is LookupImpl || newLookup.getUserData(IS_MODIFIED_KEY) == true || itemShortcutCount == 0) {
return return
} }
@ -44,8 +67,8 @@ class ProjectLookupListener : LookupManagerListener {
val itemCount = itemList.size val itemCount = itemList.size
val offset = getLookupOffset(newLookup) val offset = getLookupOffset(newLookup)
for (digitIndex in 0 until 9) { for (index in hintTexts.indices) {
val itemIndex = offset + digitIndex val itemIndex = offset + index
if (itemIndex >= itemCount) { if (itemIndex >= itemCount) {
break break
} }
@ -53,7 +76,7 @@ class ProjectLookupListener : LookupManagerListener {
if (item === itemList.getElementAt(itemIndex)) { if (item === itemList.getElementAt(itemIndex)) {
val customized = LookupElementPresentation() val customized = LookupElementPresentation()
customized.copyFrom(presentation) customized.copyFrom(presentation)
customized.appendTailTextItalic(HINT_TEXT[digitIndex], true) customized.appendTailTextItalic(hintTexts[index], true)
return@addPresentationCustomizer customized return@addPresentationCustomizer customized
} }
} }

View File

@ -6,7 +6,7 @@
<description><![CDATA[ <description><![CDATA[
Collection of keyboard-centric additions. Collection of keyboard-centric additions.
<ul> <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> </ul>
]]></description> ]]></description>
@ -17,6 +17,8 @@
</projectListeners> </projectListeners>
<extensions defaultExtensionNs="com.intellij"> <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 --> <!--suppress PluginXmlValidity, PluginXmlDynamicPlugin -->
<editorTypedHandler implementationClass="com.chylex.intellij.keyboardmaster.lookup.LookupTypedActionHandler" /> <editorTypedHandler implementationClass="com.chylex.intellij.keyboardmaster.lookup.LookupTypedActionHandler" />
</extensions> </extensions>