Compare commits
7 Commits
c9fd077253
...
ab314d2071
Author | SHA1 | Date |
---|---|---|
chylex | ab314d2071 | |
chylex | e0bd7778df | |
chylex | f95fd49da1 | |
chylex | f6f65557e2 | |
chylex | a496b253ba | |
chylex | 16df8a3150 | |
chylex | a2b79d4f52 |
|
@ -2,6 +2,7 @@
|
||||||
/.idea/inspectionProfiles
|
/.idea/inspectionProfiles
|
||||||
/.idea/jarRepositories.xml
|
/.idea/jarRepositories.xml
|
||||||
/.idea/misc.xml
|
/.idea/misc.xml
|
||||||
|
/.idea/*.iml
|
||||||
|
|
||||||
/.gradle/
|
/.gradle/
|
||||||
/build/
|
/build/
|
||||||
|
|
|
@ -1,8 +1,11 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project version="4">
|
<project version="4">
|
||||||
|
<component name="GradleMigrationSettings" migrationVersion="1" />
|
||||||
<component name="GradleSettings">
|
<component name="GradleSettings">
|
||||||
<option name="linkedExternalProjectsSettings">
|
<option name="linkedExternalProjectsSettings">
|
||||||
<GradleProjectSettings>
|
<GradleProjectSettings>
|
||||||
|
<option name="delegatedBuild" value="true" />
|
||||||
|
<option name="testRunner" value="GRADLE" />
|
||||||
<option name="distributionType" value="DEFAULT_WRAPPED" />
|
<option name="distributionType" value="DEFAULT_WRAPPED" />
|
||||||
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
||||||
<option name="modules">
|
<option name="modules">
|
||||||
|
@ -13,4 +16,4 @@
|
||||||
</GradleProjectSettings>
|
</GradleProjectSettings>
|
||||||
</option>
|
</option>
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
<component name="ProjectRunConfigurationManager">
|
||||||
|
<configuration default="false" name="Plugin" type="GradleRunConfiguration" factoryName="Gradle">
|
||||||
|
<ExternalSystemSettings>
|
||||||
|
<option name="executionName" />
|
||||||
|
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
||||||
|
<option name="externalSystemIdString" value="GRADLE" />
|
||||||
|
<option name="scriptParameters" value=":runIde" />
|
||||||
|
<option name="taskDescriptions">
|
||||||
|
<list />
|
||||||
|
</option>
|
||||||
|
<option name="taskNames">
|
||||||
|
<list />
|
||||||
|
</option>
|
||||||
|
<option name="vmOptions" />
|
||||||
|
</ExternalSystemSettings>
|
||||||
|
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
|
||||||
|
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
|
||||||
|
<DebugAllEnabled>false</DebugAllEnabled>
|
||||||
|
<method v="2" />
|
||||||
|
</configuration>
|
||||||
|
</component>
|
|
@ -0,0 +1,26 @@
|
||||||
|
<component name="ProjectRunConfigurationManager">
|
||||||
|
<configuration default="false" name="Plugin + IdeaVIM" type="GradleRunConfiguration" factoryName="Gradle">
|
||||||
|
<ExternalSystemSettings>
|
||||||
|
<option name="env">
|
||||||
|
<map>
|
||||||
|
<entry key="IDEAVIM" value="1" />
|
||||||
|
</map>
|
||||||
|
</option>
|
||||||
|
<option name="executionName" />
|
||||||
|
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
||||||
|
<option name="externalSystemIdString" value="GRADLE" />
|
||||||
|
<option name="scriptParameters" value=":runIde" />
|
||||||
|
<option name="taskDescriptions">
|
||||||
|
<list />
|
||||||
|
</option>
|
||||||
|
<option name="taskNames">
|
||||||
|
<list />
|
||||||
|
</option>
|
||||||
|
<option name="vmOptions" />
|
||||||
|
</ExternalSystemSettings>
|
||||||
|
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
|
||||||
|
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
|
||||||
|
<DebugAllEnabled>false</DebugAllEnabled>
|
||||||
|
<method v="2" />
|
||||||
|
</configuration>
|
||||||
|
</component>
|
|
@ -1,11 +1,11 @@
|
||||||
plugins {
|
plugins {
|
||||||
kotlin("jvm") version "1.5.10"
|
kotlin("jvm") version "1.5.10"
|
||||||
id("org.jetbrains.intellij") version "1.1.4"
|
id("org.jetbrains.intellij") version "1.2.0"
|
||||||
java
|
java
|
||||||
}
|
}
|
||||||
|
|
||||||
group = "com.chylex.intellij.keyboardmaster"
|
group = "com.chylex.intellij.keyboardmaster"
|
||||||
version = "0.1.3"
|
version = "0.1.4"
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
|
@ -18,5 +18,9 @@ dependencies {
|
||||||
}
|
}
|
||||||
|
|
||||||
intellij {
|
intellij {
|
||||||
version.set("2021.2")
|
version.set("2021.2.2")
|
||||||
|
|
||||||
|
if (System.getenv("IDEAVIM") == "1") {
|
||||||
|
plugins.add("IdeaVIM:0.66")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
package com.chylex.intellij.keyboardmaster
|
||||||
|
|
||||||
|
import com.chylex.intellij.keyboardmaster.feature.codeCompletion.CodeCompletionPopupKeyHandler
|
||||||
|
import com.intellij.openapi.application.ApplicationManager
|
||||||
|
import com.intellij.openapi.project.Project
|
||||||
|
import com.intellij.openapi.startup.StartupActivity
|
||||||
|
|
||||||
|
class PluginStartup : StartupActivity.DumbAware {
|
||||||
|
private var isInitialized = false
|
||||||
|
|
||||||
|
override fun runActivity(project: Project) {
|
||||||
|
if (!isInitialized) {
|
||||||
|
isInitialized = true
|
||||||
|
|
||||||
|
val application = ApplicationManager.getApplication()
|
||||||
|
if (application.isUnitTestMode) {
|
||||||
|
CodeCompletionPopupKeyHandler.registerRawHandler()
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
application.invokeLater(CodeCompletionPopupKeyHandler.Companion::registerRawHandler)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -10,6 +10,7 @@ class PluginConfigurable : Configurable {
|
||||||
|
|
||||||
private val codeCompletionItemShortcuts = JBTextField(20)
|
private val codeCompletionItemShortcuts = JBTextField(20)
|
||||||
private val codeCompletionNextPageShortcut = JBTextField(2)
|
private val codeCompletionNextPageShortcut = JBTextField(2)
|
||||||
|
private val codeCompletionPrevPageShortcut = JBTextField(2)
|
||||||
|
|
||||||
override fun getDisplayName(): String {
|
override fun getDisplayName(): String {
|
||||||
return "Keyboard Master"
|
return "Keyboard Master"
|
||||||
|
@ -20,6 +21,7 @@ class PluginConfigurable : Configurable {
|
||||||
titledRow("Code Completion") {
|
titledRow("Code Completion") {
|
||||||
row("Item shortcuts:") { component(codeCompletionItemShortcuts) }
|
row("Item shortcuts:") { component(codeCompletionItemShortcuts) }
|
||||||
row("Next page shortcut:") { component(codeCompletionNextPageShortcut) }
|
row("Next page shortcut:") { component(codeCompletionNextPageShortcut) }
|
||||||
|
row("Prev page shortcut:") { component(codeCompletionPrevPageShortcut) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,6 +36,7 @@ class PluginConfigurable : Configurable {
|
||||||
PluginConfiguration.modify {
|
PluginConfiguration.modify {
|
||||||
it.codeCompletionItemShortcuts = codeCompletionItemShortcuts.text
|
it.codeCompletionItemShortcuts = codeCompletionItemShortcuts.text
|
||||||
it.codeCompletionNextPageShortcut = codeCompletionNextPageShortcut.text.firstOrNull()?.code ?: 0
|
it.codeCompletionNextPageShortcut = codeCompletionNextPageShortcut.text.firstOrNull()?.code ?: 0
|
||||||
|
it.codeCompletionPrevPageShortcut = codeCompletionPrevPageShortcut.text.firstOrNull()?.code ?: 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,6 +44,7 @@ class PluginConfigurable : Configurable {
|
||||||
PluginConfiguration.read {
|
PluginConfiguration.read {
|
||||||
codeCompletionItemShortcuts.text = it.codeCompletionItemShortcuts
|
codeCompletionItemShortcuts.text = it.codeCompletionItemShortcuts
|
||||||
codeCompletionNextPageShortcut.text = it.codeCompletionNextPageShortcut.let { code -> if (code == 0) "" else code.toChar().toString() }
|
codeCompletionNextPageShortcut.text = it.codeCompletionNextPageShortcut.let { code -> if (code == 0) "" else code.toChar().toString() }
|
||||||
|
codeCompletionPrevPageShortcut.text = it.codeCompletionPrevPageShortcut.let { code -> if (code == 0) "" else code.toChar().toString() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package com.chylex.intellij.keyboardmaster.configuration
|
package com.chylex.intellij.keyboardmaster.configuration
|
||||||
|
|
||||||
import com.chylex.intellij.keyboardmaster.lookup.ProjectLookupListener
|
import com.chylex.intellij.keyboardmaster.feature.codeCompletion.CodeCompletionPopupConfiguration
|
||||||
import com.intellij.openapi.application.ApplicationManager
|
import com.intellij.openapi.application.ApplicationManager
|
||||||
import com.intellij.openapi.components.PersistentStateComponent
|
import com.intellij.openapi.components.PersistentStateComponent
|
||||||
import com.intellij.openapi.components.State
|
import com.intellij.openapi.components.State
|
||||||
|
@ -14,6 +14,7 @@ import com.intellij.util.xmlb.XmlSerializerUtil
|
||||||
class PluginConfiguration : PersistentStateComponent<PluginConfiguration> {
|
class PluginConfiguration : PersistentStateComponent<PluginConfiguration> {
|
||||||
var codeCompletionItemShortcuts = "123456789"
|
var codeCompletionItemShortcuts = "123456789"
|
||||||
var codeCompletionNextPageShortcut: Int = '0'.code
|
var codeCompletionNextPageShortcut: Int = '0'.code
|
||||||
|
var codeCompletionPrevPageShortcut: Int = 0
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private val instance: PluginConfiguration
|
private val instance: PluginConfiguration
|
||||||
|
@ -31,8 +32,8 @@ class PluginConfiguration : PersistentStateComponent<PluginConfiguration> {
|
||||||
instance.apply(callback).apply(this::update)
|
instance.apply(callback).apply(this::update)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun update(instance: PluginConfiguration) {
|
private fun update(instance: PluginConfiguration) = with(instance) {
|
||||||
ProjectLookupListener.updateShortcuts(instance)
|
CodeCompletionPopupConfiguration.updateShortcuts(codeCompletionItemShortcuts, codeCompletionNextPageShortcut, codeCompletionPrevPageShortcut)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
package com.chylex.intellij.keyboardmaster.feature.codeCompletion
|
||||||
|
|
||||||
|
import com.chylex.intellij.keyboardmaster.configuration.PluginConfiguration
|
||||||
|
import com.intellij.util.containers.IntIntHashMap
|
||||||
|
|
||||||
|
object CodeCompletionPopupConfiguration {
|
||||||
|
const val SHORTCUT_NONE = -1
|
||||||
|
const val SHORTCUT_NEXT_PAGE = -2
|
||||||
|
const val SHORTCUT_PREV_PAGE = -3
|
||||||
|
|
||||||
|
private val charToShortcutMap = IntIntHashMap(16, SHORTCUT_NONE)
|
||||||
|
private var hintTexts = mutableListOf<String>()
|
||||||
|
|
||||||
|
val itemShortcutCount
|
||||||
|
get() = hintTexts.size
|
||||||
|
|
||||||
|
init {
|
||||||
|
PluginConfiguration.load()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun updateShortcuts(itemShortcutChars: String, nextPageShortcutCode: Int, previousPageShortcutCode: Int) {
|
||||||
|
charToShortcutMap.clear()
|
||||||
|
|
||||||
|
if (nextPageShortcutCode != 0) {
|
||||||
|
charToShortcutMap[nextPageShortcutCode] = SHORTCUT_NEXT_PAGE
|
||||||
|
}
|
||||||
|
|
||||||
|
if (previousPageShortcutCode != 0) {
|
||||||
|
charToShortcutMap[previousPageShortcutCode] = SHORTCUT_PREV_PAGE
|
||||||
|
}
|
||||||
|
|
||||||
|
for ((index, char) in itemShortcutChars.withIndex()) {
|
||||||
|
charToShortcutMap[char.code] = index
|
||||||
|
}
|
||||||
|
|
||||||
|
hintTexts.clear()
|
||||||
|
for (char in itemShortcutChars) {
|
||||||
|
hintTexts.add(" [$char]")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getShortcut(char: Char): Int {
|
||||||
|
return charToShortcutMap[char.code]
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getHintText(index: Int): String {
|
||||||
|
return hintTexts[index]
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,84 @@
|
||||||
|
package com.chylex.intellij.keyboardmaster.feature.codeCompletion
|
||||||
|
|
||||||
|
import com.intellij.codeInsight.lookup.LookupFocusDegree
|
||||||
|
import com.intellij.codeInsight.lookup.LookupManager
|
||||||
|
import com.intellij.codeInsight.lookup.impl.LookupImpl
|
||||||
|
import com.intellij.codeInsight.template.impl.editorActions.TypedActionHandlerBase
|
||||||
|
import com.intellij.openapi.actionSystem.DataContext
|
||||||
|
import com.intellij.openapi.editor.Editor
|
||||||
|
import com.intellij.openapi.editor.actionSystem.TypedAction
|
||||||
|
import com.intellij.openapi.editor.actionSystem.TypedActionHandler
|
||||||
|
import com.intellij.ui.ScrollingUtil
|
||||||
|
import javax.swing.ListModel
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles configured key bindings inside a code completion popup menu.
|
||||||
|
*/
|
||||||
|
class CodeCompletionPopupKeyHandler private constructor(originalHandler: TypedActionHandler?) : TypedActionHandlerBase(originalHandler) {
|
||||||
|
companion object {
|
||||||
|
/**
|
||||||
|
* Registers the key handler as a raw handler, because IdeaVIM steals keys from Keyboard Master when renaming an element in normal mode.
|
||||||
|
*/
|
||||||
|
fun registerRawHandler() {
|
||||||
|
TypedAction.getInstance().let { it.setupRawHandler(CodeCompletionPopupKeyHandler(it.rawHandler)) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun execute(editor: Editor, charTyped: Char, dataContext: DataContext) {
|
||||||
|
if (!executeImpl(editor, charTyped)) {
|
||||||
|
myOriginalHandler?.execute(editor, charTyped, dataContext)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun executeImpl(editor: Editor, charTyped: Char): Boolean {
|
||||||
|
val shortcutItem = CodeCompletionPopupConfiguration.getShortcut(charTyped)
|
||||||
|
if (shortcutItem == CodeCompletionPopupConfiguration.SHORTCUT_NONE) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
val lookup = LookupManager.getActiveLookup(editor)
|
||||||
|
if (lookup !is LookupImpl) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
val offset = CodeCompletionPopupListener.getPageOffset(lookup)
|
||||||
|
|
||||||
|
if (shortcutItem == CodeCompletionPopupConfiguration.SHORTCUT_NEXT_PAGE) {
|
||||||
|
setPageOffset(lookup) {
|
||||||
|
val newTopIndex = offset + CodeCompletionPopupConfiguration.itemShortcutCount
|
||||||
|
if (newTopIndex >= it.size) offset else newTopIndex
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (shortcutItem == CodeCompletionPopupConfiguration.SHORTCUT_PREV_PAGE) {
|
||||||
|
setPageOffset(lookup) {
|
||||||
|
val newTopIndex = offset - CodeCompletionPopupConfiguration.itemShortcutCount
|
||||||
|
if (newTopIndex < 0) 0 else newTopIndex
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
selectItem(lookup, offset + shortcutItem)
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
private inline fun setPageOffset(lookup: LookupImpl, getNewTopIndex: (ListModel<*>) -> Int) {
|
||||||
|
val list = lookup.list
|
||||||
|
val newTopIndex = getNewTopIndex(list.model)
|
||||||
|
|
||||||
|
CodeCompletionPopupListener.setPageOffset(lookup, newTopIndex)
|
||||||
|
lookup.selectedIndex = newTopIndex
|
||||||
|
ScrollingUtil.ensureRangeIsVisible(list, newTopIndex, newTopIndex + CodeCompletionPopupConfiguration.itemShortcutCount - 1)
|
||||||
|
lookup.markSelectionTouched()
|
||||||
|
lookup.refreshUi(false, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun selectItem(lookup: LookupImpl, index: Int) {
|
||||||
|
if (!lookup.isFocused) {
|
||||||
|
lookup.lookupFocusDegree = LookupFocusDegree.FOCUSED
|
||||||
|
lookup.refreshUi(false, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
lookup.selectedIndex = index
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,49 +1,20 @@
|
||||||
package com.chylex.intellij.keyboardmaster.lookup
|
package com.chylex.intellij.keyboardmaster.feature.codeCompletion
|
||||||
|
|
||||||
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 popup items with the character that selects the item.
|
||||||
*/
|
*/
|
||||||
class ProjectLookupListener : LookupManagerListener {
|
class CodeCompletionPopupListener : LookupManagerListener {
|
||||||
companion object {
|
companion object {
|
||||||
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 var hintTexts = mutableListOf<String>()
|
fun getPageOffset(lookup: LookupImpl): Int {
|
||||||
private val charToShortcutMap = IntIntHashMap(16, -1)
|
|
||||||
|
|
||||||
val itemShortcutCount
|
|
||||||
get() = hintTexts.size
|
|
||||||
|
|
||||||
init {
|
|
||||||
PluginConfiguration.load()
|
|
||||||
}
|
|
||||||
|
|
||||||
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 {
|
|
||||||
val offset = lookup.getUserData(OFFSET_KEY)
|
val offset = lookup.getUserData(OFFSET_KEY)
|
||||||
if (offset == null || offset >= lookup.list.model.size) {
|
if (offset == null || offset >= lookup.list.model.size) {
|
||||||
return 0
|
return 0
|
||||||
|
@ -53,13 +24,13 @@ class ProjectLookupListener : LookupManagerListener {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setLookupOffset(lookup: LookupImpl, newOffset: Int) {
|
fun setPageOffset(lookup: LookupImpl, newOffset: Int) {
|
||||||
lookup.putUserData(OFFSET_KEY, newOffset)
|
lookup.putUserData(OFFSET_KEY, newOffset)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun activeLookupChanged(oldLookup: Lookup?, newLookup: Lookup?) {
|
override fun activeLookupChanged(oldLookup: Lookup?, newLookup: Lookup?) {
|
||||||
if (newLookup !is LookupImpl || newLookup.getUserData(IS_MODIFIED_KEY) == true || itemShortcutCount == 0) {
|
if (newLookup !is LookupImpl || newLookup.getUserData(IS_MODIFIED_KEY) == true || CodeCompletionPopupConfiguration.itemShortcutCount == 0) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,9 +40,9 @@ class ProjectLookupListener : LookupManagerListener {
|
||||||
newLookup.addPresentationCustomizer { item, presentation ->
|
newLookup.addPresentationCustomizer { item, presentation ->
|
||||||
val itemList = newLookup.list.model
|
val itemList = newLookup.list.model
|
||||||
val itemCount = itemList.size
|
val itemCount = itemList.size
|
||||||
val offset = getLookupOffset(newLookup)
|
val offset = getPageOffset(newLookup)
|
||||||
|
|
||||||
for (index in hintTexts.indices) {
|
for (index in 0 until CodeCompletionPopupConfiguration.itemShortcutCount) {
|
||||||
val itemIndex = offset + index
|
val itemIndex = offset + index
|
||||||
if (itemIndex >= itemCount) {
|
if (itemIndex >= itemCount) {
|
||||||
break
|
break
|
||||||
|
@ -80,7 +51,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(hintTexts[index], true)
|
customized.appendTailTextItalic(CodeCompletionPopupConfiguration.getHintText(index), true)
|
||||||
return@addPresentationCustomizer customized
|
return@addPresentationCustomizer customized
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,60 +0,0 @@
|
||||||
package com.chylex.intellij.keyboardmaster.lookup
|
|
||||||
|
|
||||||
import com.intellij.codeInsight.lookup.LookupFocusDegree
|
|
||||||
import com.intellij.codeInsight.lookup.LookupManager
|
|
||||||
import com.intellij.codeInsight.lookup.impl.LookupImpl
|
|
||||||
import com.intellij.codeInsight.template.impl.editorActions.TypedActionHandlerBase
|
|
||||||
import com.intellij.openapi.actionSystem.DataContext
|
|
||||||
import com.intellij.openapi.editor.Editor
|
|
||||||
import com.intellij.openapi.editor.actionSystem.TypedActionHandler
|
|
||||||
import com.intellij.ui.ScrollingUtil
|
|
||||||
|
|
||||||
/**
|
|
||||||
* When typing digits 1-9 inside a code completion popup menu, selects the n-th item in the list.
|
|
||||||
* When typing the digit 0, moves down the list by 9 items, wrapping around if needed.
|
|
||||||
*/
|
|
||||||
class LookupTypedActionHandler(originalHandler: TypedActionHandler?) : TypedActionHandlerBase(originalHandler) {
|
|
||||||
override fun execute(editor: Editor, charTyped: Char, dataContext: DataContext) {
|
|
||||||
if (!executeImpl(editor, charTyped)) {
|
|
||||||
myOriginalHandler?.execute(editor, charTyped, dataContext)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun executeImpl(editor: Editor, charTyped: Char): Boolean {
|
|
||||||
val shortcutItem = ProjectLookupListener.getShortcut(charTyped)
|
|
||||||
if (shortcutItem == -1) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
val lookup = LookupManager.getActiveLookup(editor)
|
|
||||||
if (lookup !is LookupImpl) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
val offset = ProjectLookupListener.getLookupOffset(lookup)
|
|
||||||
|
|
||||||
if (shortcutItem == 0) {
|
|
||||||
val list = lookup.list
|
|
||||||
val itemCount = list.model.size
|
|
||||||
|
|
||||||
val shortcutCount = ProjectLookupListener.itemShortcutCount
|
|
||||||
val topIndex = (offset + shortcutCount).let { if (it >= itemCount) 0 else it }
|
|
||||||
|
|
||||||
ProjectLookupListener.setLookupOffset(lookup, topIndex)
|
|
||||||
lookup.selectedIndex = topIndex
|
|
||||||
ScrollingUtil.ensureRangeIsVisible(list, topIndex, topIndex + shortcutCount - 1)
|
|
||||||
lookup.markSelectionTouched()
|
|
||||||
lookup.refreshUi(false, true)
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (!lookup.isFocused) {
|
|
||||||
lookup.lookupFocusDegree = LookupFocusDegree.FOCUSED
|
|
||||||
lookup.refreshUi(false, true)
|
|
||||||
}
|
|
||||||
|
|
||||||
lookup.selectedIndex = offset + shortcutItem - 1
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -13,13 +13,12 @@
|
||||||
<depends>com.intellij.modules.platform</depends>
|
<depends>com.intellij.modules.platform</depends>
|
||||||
|
|
||||||
<projectListeners>
|
<projectListeners>
|
||||||
<listener class="com.chylex.intellij.keyboardmaster.lookup.ProjectLookupListener" topic="com.intellij.codeInsight.lookup.LookupManagerListener" />
|
<listener class="com.chylex.intellij.keyboardmaster.feature.codeCompletion.CodeCompletionPopupListener" topic="com.intellij.codeInsight.lookup.LookupManagerListener" />
|
||||||
</projectListeners>
|
</projectListeners>
|
||||||
|
|
||||||
<extensions defaultExtensionNs="com.intellij">
|
<extensions defaultExtensionNs="com.intellij">
|
||||||
<applicationService serviceImplementation="com.chylex.intellij.keyboardmaster.configuration.PluginConfiguration" />
|
<applicationService serviceImplementation="com.chylex.intellij.keyboardmaster.configuration.PluginConfiguration" />
|
||||||
<applicationConfigurable parentId="tools" instance="com.chylex.intellij.keyboardmaster.configuration.PluginConfigurable" id="com.chylex.keyboardmaster" />
|
<applicationConfigurable parentId="tools" instance="com.chylex.intellij.keyboardmaster.configuration.PluginConfigurable" id="com.chylex.keyboardmaster" />
|
||||||
<!--suppress PluginXmlValidity, PluginXmlDynamicPlugin -->
|
<postStartupActivity implementation="com.chylex.intellij.keyboardmaster.PluginStartup" order="last" />
|
||||||
<editorTypedHandler implementationClass="com.chylex.intellij.keyboardmaster.lookup.LookupTypedActionHandler" />
|
|
||||||
</extensions>
|
</extensions>
|
||||||
</idea-plugin>
|
</idea-plugin>
|
||||||
|
|
Loading…
Reference in New Issue