Compare commits
2 Commits
619aa49b42
...
2f3780bdfc
Author | SHA1 | Date |
---|---|---|
chylex | 2f3780bdfc | |
chylex | 28c3d80c6e |
|
@ -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()
|
||||||
|
|
|
@ -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() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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)
|
||||||
|
}
|
||||||
|
}
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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>
|
||||||
|
|
Loading…
Reference in New Issue