Compare commits

...

2 Commits

10 changed files with 222 additions and 0 deletions

View File

@ -19,6 +19,8 @@ intellij {
version.set("2023.2")
updateSinceUntilBuild.set(false)
plugins.add("com.intellij.java")
if (System.getenv("IDEAVIM") == "1") {
plugins.add("IdeaVIM:0.66")
}

View File

@ -0,0 +1,21 @@
package com.chylex.intellij.keyboardmaster.feature.action.gotoError
import com.intellij.codeInsight.daemon.DaemonCodeAnalyzerSettings
import com.intellij.codeInsight.daemon.impl.GotoNextErrorHandler
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiFile
class GotoErrorInOtherModeHandler(forward: Boolean) : GotoNextErrorHandler(forward) {
override fun invoke(project: Project, editor: Editor, file: PsiFile) {
val settings = DaemonCodeAnalyzerSettings.getInstance()
val oldMode = settings.isNextErrorActionGoesToErrorsFirst
settings.isNextErrorActionGoesToErrorsFirst = !oldMode
try {
super.invoke(project, editor, file)
} finally {
settings.isNextErrorActionGoesToErrorsFirst = oldMode
}
}
}

View File

@ -0,0 +1,10 @@
package com.chylex.intellij.keyboardmaster.feature.action.gotoError
import com.intellij.codeInsight.CodeInsightActionHandler
import com.intellij.codeInsight.daemon.impl.actions.GotoNextErrorAction
class GotoNextErrorInOtherModeAction : GotoNextErrorAction() {
override fun getHandler(): CodeInsightActionHandler {
return GotoErrorInOtherModeHandler(forward = true)
}
}

View File

@ -0,0 +1,10 @@
package com.chylex.intellij.keyboardmaster.feature.action.gotoError
import com.intellij.codeInsight.CodeInsightActionHandler
import com.intellij.codeInsight.daemon.impl.actions.GotoPreviousErrorAction
class GotoPreviousErrorInOtherModeAction : GotoPreviousErrorAction() {
override fun getHandler(): CodeInsightActionHandler {
return GotoErrorInOtherModeHandler(forward = false)
}
}

View File

@ -0,0 +1,34 @@
package com.chylex.intellij.keyboardmaster.feature.action.gotoType
import com.intellij.codeInsight.actions.BaseCodeInsightAction
import com.intellij.ide.structureView.TreeBasedStructureViewBuilder
import com.intellij.lang.LanguageStructureViewBuilder
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.project.DumbAware
import com.intellij.openapi.project.IndexNotReadyException
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiFile
abstract class AbstractGotoTypeInFileAction : BaseCodeInsightAction(), DumbAware {
init {
isEnabledInModalContext = true
}
final override fun isValidForLookup(): Boolean {
return true
}
final override fun isValidForFile(project: Project, editor: Editor, file: PsiFile): Boolean {
return checkValidForFile(file)
}
private companion object {
fun checkValidForFile(file: PsiFile): Boolean {
return try {
LanguageStructureViewBuilder.INSTANCE.getStructureViewBuilder(file) is TreeBasedStructureViewBuilder
} catch (e: IndexNotReadyException) {
false
}
}
}
}

View File

@ -0,0 +1,9 @@
package com.chylex.intellij.keyboardmaster.feature.action.gotoType
import com.intellij.codeInsight.CodeInsightActionHandler
class GotoNextTypeInFileAction : AbstractGotoTypeInFileAction() {
override fun getHandler(): CodeInsightActionHandler {
return GotoTypeInFileHandler(forward = true)
}
}

View File

@ -0,0 +1,9 @@
package com.chylex.intellij.keyboardmaster.feature.action.gotoType
import com.intellij.codeInsight.CodeInsightActionHandler
class GotoPreviousTypeInFileAction : AbstractGotoTypeInFileAction() {
override fun getHandler(): CodeInsightActionHandler {
return GotoTypeInFileHandler(forward = false)
}
}

View File

@ -0,0 +1,97 @@
package com.chylex.intellij.keyboardmaster.feature.action.gotoType
import com.intellij.codeInsight.CodeInsightActionHandler
import com.intellij.codeInsight.lookup.LookupManager
import com.intellij.ide.structureView.StructureViewTreeElement
import com.intellij.ide.structureView.TreeBasedStructureViewBuilder
import com.intellij.lang.LanguageStructureViewBuilder
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.editor.ScrollType
import com.intellij.openapi.fileEditor.ex.IdeDocumentHistory
import com.intellij.openapi.project.Project
import com.intellij.openapi.util.Disposer
import com.intellij.psi.PsiClass
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiFile
import it.unimi.dsi.fastutil.ints.IntArrayList
class GotoTypeInFileHandler(private val forward: Boolean) : CodeInsightActionHandler {
override fun invoke(project: Project, editor: Editor, file: PsiFile) {
LookupManager.getInstance(project).hideActiveLookup()
val caretOffset = editor.caretModel.offset
val caretLine = editor.caretModel.logicalPosition.line
val searchedOffsetRange = if (forward)
caretOffset + 1..file.textLength
else
0 until caretOffset
val navigationOffsets = getNavigationOffsets(file, searchedOffsetRange)
if (!forward) {
navigationOffsets.reverse()
}
val direction = if (forward) 1 else -1
for (offset in navigationOffsets) {
val line = editor.offsetToLogicalPosition(offset).line
if (line.compareTo(caretLine) * direction > 0) {
editor.caretModel.removeSecondaryCarets()
editor.caretModel.moveToOffset(offset)
editor.selectionModel.removeSelection()
editor.scrollingModel.scrollToCaret(if (forward) ScrollType.CENTER_DOWN else ScrollType.CENTER_UP)
IdeDocumentHistory.getInstance(project).includeCurrentCommandAsNavigation()
break
}
}
}
override fun getElementToMakeWritable(currentFile: PsiFile): PsiElement? {
return null
}
private companion object {
fun getNavigationOffsets(file: PsiFile, searchedOffsetRange: IntRange): IntArray {
val structureViewBuilder = LanguageStructureViewBuilder.INSTANCE.getStructureViewBuilder(file)
if (structureViewBuilder !is TreeBasedStructureViewBuilder) {
return intArrayOf()
}
val elements = mutableSetOf<PsiElement>()
val model = structureViewBuilder.createStructureViewModel(null)
try {
addStructureViewElements(elements, model.root, file)
} finally {
Disposer.dispose(model)
}
return offsetsFromElements(elements, searchedOffsetRange)
}
private fun addStructureViewElements(result: MutableSet<PsiElement>, parent: StructureViewTreeElement, file: PsiFile) {
for (child in parent.children) {
val value = (child as StructureViewTreeElement).value
if (value is PsiClass && file == value.containingFile) {
result.add(value)
}
addStructureViewElements(result, child, file)
}
}
private fun offsetsFromElements(elements: Collection<PsiElement>, searchedOffsetRange: IntRange): IntArray {
val offsets = IntArrayList(elements.size)
for (element in elements) {
val offset = element.textOffset
if (offset in searchedOffsetRange) {
offsets.add(offset)
}
}
offsets.sort(null)
return offsets.toIntArray()
}
}
}

View File

@ -0,0 +1,15 @@
<idea-plugin>
<actions>
<!-- Go to Type in File -->
<action id="KM.GotoNextTypeInFile"
text="Next Type"
class="com.chylex.intellij.keyboardmaster.feature.action.gotoType.GotoNextTypeInFileAction">
<add-to-group group-id="NavigateInFileGroup" anchor="after" relative-to-action="MethodUp" />
</action>
<action id="KM.GotoPreviousTypeInFile"
text="Previous Type"
class="com.chylex.intellij.keyboardmaster.feature.action.gotoType.GotoPreviousTypeInFileAction">
<add-to-group group-id="NavigateInFileGroup" anchor="after" relative-to-action="KM.GotoNextTypeInFile" />
</action>
</actions>
</idea-plugin>

View File

@ -12,6 +12,7 @@
]]></description>
<depends>com.intellij.modules.platform</depends>
<depends optional="true" config-file="KeyboardMaster-Java.xml">com.intellij.java</depends>
<projectListeners>
<listener class="com.chylex.intellij.keyboardmaster.feature.codeCompletion.CodeCompletionPopupListener" topic="com.intellij.codeInsight.lookup.LookupManagerListener" />
@ -22,4 +23,18 @@
<applicationConfigurable parentId="tools" instance="com.chylex.intellij.keyboardmaster.configuration.PluginConfigurable" id="com.chylex.keyboardmaster" displayName="Keyboard Master" />
<postStartupActivity implementation="com.chylex.intellij.keyboardmaster.PluginStartup" order="last" />
</extensions>
<actions>
<!-- Go to Highlighted Error -->
<action id="KM.GotoNextErrorInOtherMode"
text="Next Highlighted Error in Other Mode"
class="com.chylex.intellij.keyboardmaster.feature.action.gotoError.GotoNextErrorInOtherModeAction">
<add-to-group group-id="GoToErrorGroup" anchor="after" relative-to-action="GotoNextError" />
</action>
<action id="KM.GotoPreviousErrorInOtherMode"
text="Previous Highlighted Error in Other Mode"
class="com.chylex.intellij.keyboardmaster.feature.action.gotoError.GotoPreviousErrorInOtherModeAction">
<add-to-group group-id="GoToErrorGroup" anchor="after" relative-to-action="GotoPreviousError" />
</action>
</actions>
</idea-plugin>