1
0
mirror of https://github.com/chylex/IntelliJ-AceJump.git synced 2025-09-15 14:32:08 +02:00

2 Commits

11 changed files with 190 additions and 100 deletions

View File

@@ -37,6 +37,7 @@ class AceConfig: PersistentStateComponent<AceSettings> {
val cycleMode3: JumpMode get() = settings.cycleMode3
val cycleMode4: JumpMode get() = settings.cycleMode4
val jumpModeColor: Color get() = settings.jumpModeColor
val jumpEndModeColor: Color get() = settings.jumpEndModeColor
val targetModeColor: Color get() = settings.targetModeColor
val definitionModeColor: Color get() = settings.definitionModeColor
val textHighlightColor: Color get() = settings.textHighlightColor

View File

@@ -22,6 +22,7 @@ class AceConfigurable: Configurable {
panel.cycleMode3 != settings.cycleMode3 ||
panel.cycleMode4 != settings.cycleMode4 ||
panel.jumpModeColor != settings.jumpModeColor ||
panel.jumpEndModeColor != settings.jumpEndModeColor ||
panel.targetModeColor != settings.targetModeColor ||
panel.definitionModeColor != settings.definitionModeColor ||
panel.textHighlightColor != settings.textHighlightColor ||
@@ -47,6 +48,7 @@ class AceConfigurable: Configurable {
settings.cycleMode3 = panel.cycleMode3
settings.cycleMode4 = panel.cycleMode4
panel.jumpModeColor ?.let { settings.jumpModeColor = it }
panel.jumpEndModeColor?.let { settings.jumpEndModeColor = it }
panel.targetModeColor ?.let { settings.targetModeColor = it }
panel.definitionModeColor ?.let { settings.definitionModeColor = it }
panel.textHighlightColor ?.let { settings.textHighlightColor = it }

View File

@@ -17,11 +17,14 @@ data class AceSettings(
var cycleMode1: JumpMode = JumpMode.JUMP,
var cycleMode2: JumpMode = JumpMode.DEFINE,
var cycleMode3: JumpMode = JumpMode.TARGET,
var cycleMode4: JumpMode = JumpMode.DISABLED,
var cycleMode4: JumpMode = JumpMode.JUMP_END,
@OptionTag("jumpModeRGB", converter = ColorConverter::class)
var jumpModeColor: Color = Color.BLUE,
@OptionTag("jumpEndModeRGB", converter = ColorConverter::class)
var jumpEndModeColor: Color = Color.CYAN,
@OptionTag("targetModeRGB", converter = ColorConverter::class)
var targetModeColor: Color = Color.RED,

View File

@@ -33,6 +33,7 @@ internal class AceSettingsPanel {
private val cycleModeCombo3 = ComboBox<JumpMode>()
private val cycleModeCombo4 = ComboBox<JumpMode>()
private val jumpModeColorWheel = ColorPanel()
private val jumpEndModeColorWheel = ColorPanel()
private val targetModeColorWheel = ColorPanel()
private val definitionModeColorWheel = ColorPanel()
private val textHighlightColorWheel = ColorPanel()
@@ -100,6 +101,7 @@ internal class AceSettingsPanel {
titledRow(aceString("colorsHeading")) {
row(aceString("jumpModeColorLabel")) { short(jumpModeColorWheel) }
row(aceString("jumpEndModeColorLabel")) { short(jumpEndModeColorWheel) }
row(aceString("targetModeColorLabel")) { short(targetModeColorWheel) }
row(aceString("definitionModeColorLabel")) { short(definitionModeColorWheel) }
row(aceString("textHighlightColorLabel")) { short(textHighlightColorWheel) }
@@ -128,6 +130,7 @@ internal class AceSettingsPanel {
internal var cycleMode3 by cycleModeCombo3
internal var cycleMode4 by cycleModeCombo4
internal var jumpModeColor by jumpModeColorWheel
internal var jumpEndModeColor by jumpEndModeColorWheel
internal var targetModeColor by targetModeColorWheel
internal var definitionModeColor by definitionModeColorWheel
internal var textHighlightColor by textHighlightColorWheel
@@ -146,6 +149,7 @@ internal class AceSettingsPanel {
cycleMode3 = settings.cycleMode3
cycleMode4 = settings.cycleMode4
jumpModeColor = settings.jumpModeColor
jumpEndModeColor = settings.jumpEndModeColor
targetModeColor = settings.targetModeColor
definitionModeColor = settings.definitionModeColor
textHighlightColor = settings.textHighlightColor

View File

@@ -1,90 +1,132 @@
package org.acejump.control
import com.intellij.codeInsight.editorActions.SelectWordUtil
import com.intellij.openapi.actionSystem.AnActionEvent
import com.intellij.openapi.actionSystem.CommonDataKeys.EDITOR
import com.intellij.openapi.diagnostic.Logger
import com.intellij.openapi.diagnostic.debug
import com.intellij.openapi.editor.CaretState
import com.intellij.openapi.editor.ScrollType
import com.intellij.openapi.fileEditor.FileDocumentManager
import com.intellij.openapi.project.DumbAwareAction
import com.intellij.openapi.util.TextRange
import org.acejump.control.Handler.regexSearch
import org.acejump.label.Pattern
import org.acejump.label.Pattern.ALL_WORDS
import org.acejump.search.Finder
import org.acejump.search.JumpMode
import org.acejump.search.Jumper
import org.acejump.search.getNameOfFileInEditor
import org.acejump.view.Boundary.*
import org.acejump.view.Model
import org.acejump.view.Model.boundaries
import org.acejump.view.Model.defaultBoundary
import org.acejump.view.Model.editor
import org.acejump.view.Model.viewBounds
/**
* Entry point for all actions. The IntelliJ Platform calls AceJump here.
*/
open class AceAction: DumbAwareAction() {
open val logger = Logger.getInstance(javaClass)
override fun update(action: AnActionEvent) {
sealed class AceAction: DumbAwareAction() {
val logger = Logger.getInstance(javaClass)
final override fun update(action: AnActionEvent) {
action.presentation.isEnabled = action.getData(EDITOR) != null
}
override fun actionPerformed(e: AnActionEvent) {
final override fun actionPerformed(e: AnActionEvent) {
editor = e.getData(EDITOR) ?: return
boundaries = defaultBoundary
val textLength = editor.document.textLength
logger.info("Invoked on ${editor.getNameOfFileInEditor()} ($textLength)")
logger.debug { "Invoked on ${FileDocumentManager.getInstance().getFile(editor.document)?.presentableName} (${editor.document.textLength})" }
Handler.activate()
customize()
invoke()
}
open fun customize() = Jumper.cycleMode()
}
/**
* When target mode is activated, selecting a tag will highlight an entire word.
*/
class AceTargetAction: AceAction() {
override fun customize() = Jumper.toggleMode(JumpMode.TARGET)
}
/*
* When line mode is activated, we will tag the beginning and end of each line.
*
* TODO: https://github.com/acejump/AceJump/issues/327
* TODO: https://github.com/acejump/AceJump/issues/340
*/
class AceLineAction: AceAction() {
override fun customize() = regexSearch(Pattern.LINE_MARK)
}
/**
* When declaration mode is activated, selecting a tag will take us to the
* definition (i.e. declaration) of the token in the editor, if it exists.
*/
class AceDefinitionAction: AceAction() {
override fun customize() = Jumper.toggleMode(JumpMode.DEFINE)
}
/**
* When word mode is activated, we will tag all words on the screen.
*/
class AceWordAction: AceAction() {
override fun customize() = regexSearch(ALL_WORDS, SCREEN_BOUNDARY)
}
/**
* Search for words from the start of the screen to the caret
*/
class AceWordForwardAction: AceAction() {
override fun customize() = regexSearch(ALL_WORDS, AFTER_CARET_BOUNDARY)
}
/**
* Search for words from the caret position to the start of the screen
*/
class AceWordBackwardsAction: AceAction() {
override fun customize() = regexSearch(ALL_WORDS, BEFORE_CARET_BOUNDARY)
abstract fun invoke()
object ActivateOrCycleMode : AceAction() {
override fun invoke() = Jumper.cycleMode()
}
object ToggleJumpMode: AceAction() {
override fun invoke() = Jumper.toggleMode(JumpMode.JUMP)
}
object ToggleJumpEndMode: AceAction() {
override fun invoke() = Jumper.toggleMode(JumpMode.JUMP_END)
}
object ToggleSelectWordMode: AceAction() {
override fun invoke() = Jumper.toggleMode(JumpMode.TARGET)
}
object ToggleDefinitionMode: AceAction() {
override fun invoke() = Jumper.toggleMode(JumpMode.DEFINE)
}
object ToggleAllLinesMode: AceAction() {
override fun invoke() = regexSearch(Pattern.LINE_MARK)
}
object ToggleAllWordsMode: AceAction() {
override fun invoke() = regexSearch(ALL_WORDS, SCREEN_BOUNDARY)
}
object ToggleAllWordsForwardMode: AceAction() {
override fun invoke() = regexSearch(ALL_WORDS, AFTER_CARET_BOUNDARY)
}
object ToggleAllWordsBackwardsMode: AceAction() {
override fun invoke() = regexSearch(ALL_WORDS, BEFORE_CARET_BOUNDARY)
}
object ActOnHighlightedWords: AceAction() {
override fun invoke() = when(JumpMode.mode) {
JumpMode.DISABLED -> {}
JumpMode.JUMP -> if (editor.caretModel.supportsMultipleCarets()) jumpToAll() else Unit
JumpMode.JUMP_END -> if (editor.caretModel.supportsMultipleCarets()) jumpToWordEnds() else Unit
JumpMode.TARGET -> if (editor.caretModel.supportsMultipleCarets()) selectAllWords() else Unit
JumpMode.DEFINE -> {}
}
private fun jumpToAll() {
val carets = Finder.allResults().map {
CaretState(editor.offsetToLogicalPosition(it), null, null)
}
if (carets.isEmpty()) return
Handler.reset()
editor.caretModel.caretsAndSelections = carets
editor.scrollingModel.scrollToCaret(ScrollType.MAKE_VISIBLE)
}
private fun jumpToWordEnds() {
val ranges = ArrayList<TextRange>()
for (offset in Finder.allResults()) {
SelectWordUtil.addWordSelection(editor.settings.isCamelWords, Model.editorText, offset, ranges)
}
if (ranges.isEmpty()) return
Handler.reset()
editor.caretModel.caretsAndSelections = ranges.map {
CaretState(editor.offsetToLogicalPosition(it.endOffset), null, null)
}
editor.scrollingModel.scrollToCaret(ScrollType.MAKE_VISIBLE)
}
private fun selectAllWords() {
val ranges = ArrayList<TextRange>()
for (offset in Finder.allResults()) {
SelectWordUtil.addWordSelection(editor.settings.isCamelWords, Model.editorText, offset, ranges)
}
if (ranges.isEmpty()) return
Handler.reset()
editor.caretModel.caretsAndSelections = ranges.map {
val start = editor.offsetToLogicalPosition(it.startOffset)
val end = editor.offsetToLogicalPosition(it.endOffset)
CaretState(end, start, end)
}
editor.scrollingModel.scrollToCaret(ScrollType.MAKE_VISIBLE)
}
}
}

View File

@@ -19,7 +19,8 @@ interface Resettable {
fun reset()
}
fun aceString(s: String) = ResourceBundle.getBundle("AceResources").getString(s)
fun aceString(s: String): String =
ResourceBundle.getBundle("AceResources").getString(s)
fun <P> applyTo(vararg ps: P, fx: P.() -> Unit) = ps.forEach { it.fx() }

View File

@@ -201,6 +201,8 @@ object Finder : Resettable {
return kept
}
fun allResults() = results
fun visibleResults() = results.filter { it in viewBounds }
private fun String.isValidQuery() =

View File

@@ -9,15 +9,17 @@ import org.acejump.view.Model.editor
import java.awt.Color
enum class JumpMode {
DISABLED, JUMP, TARGET, DEFINE;
DISABLED, JUMP, JUMP_END, TARGET, DEFINE;
companion object: Resettable {
private var modeIndex = 0
private var mode: JumpMode = DISABLED
set(value) {
var mode: JumpMode = DISABLED
private set(value) {
field = value
setCaretColor(when (field) {
JUMP -> AceConfig.jumpModeColor
JUMP_END -> AceConfig.jumpEndModeColor
DEFINE -> AceConfig.definitionModeColor
TARGET -> AceConfig.targetModeColor
DISABLED -> Model.naturalCaretColor
@@ -81,7 +83,8 @@ enum class JumpMode {
override fun toString() = when(this) {
DISABLED -> aceString("jumpModeDisabled")
JUMP -> aceString("jumpModeJump")
JUMP_END -> aceString("jumpModeJumpEnd")
TARGET -> aceString("jumpModeTarget")
DEFINE -> aceString("jumpModeDefine")
} ?: "Unknown"
}
}

View File

@@ -11,8 +11,8 @@ import com.intellij.openapi.fileEditor.ex.IdeDocumentHistory
import com.intellij.openapi.fileEditor.impl.IdeDocumentHistoryImpl
import com.intellij.openapi.ui.playback.commands.ActionCommand
import com.intellij.openapi.util.TextRange
import org.acejump.search.JumpMode.DEFINE
import org.acejump.search.JumpMode.TARGET
import org.acejump.label.Tagger
import org.acejump.search.JumpMode.*
import org.acejump.view.Model.editor
import org.acejump.view.Model.editorText
import org.acejump.view.Model.project
@@ -38,7 +38,14 @@ object Jumper: Resettable {
logger.debug("Jumping to line ${logPos.line}, column ${logPos.column}...")
val oldOffset = caretModel.offset
when {
JumpMode.equals(JUMP_END) ->
moveCaretToEnd(newOffset + countMatchingCharacters(newOffset, Tagger.query))
else ->
moveCaretTo(newOffset)
}
when {
Finder.isShiftSelectEnabled && done -> selectRange(oldOffset, newOffset)
@@ -65,12 +72,32 @@ object Jumper: Resettable {
aceJumpHistoryAppender, "AceJumpHistoryAppender",
DocCommandGroupId.noneGroupId(document), document)
private fun moveCaretTo(offset: Int) = editor.run {
private fun Editor.moveCaretTo(offset: Int) {
appendCaretPositionToEditorNavigationHistory()
selectionModel.removeSelection()
caretModel.moveToOffset(offset)
}
private fun Editor.moveCaretToEnd(offset: Int) {
val ranges = ArrayList<TextRange>()
addWordSelection(settings.isCamelWords, editorText, offset, ranges)
if (ranges.isEmpty()) {
moveCaretTo(offset)
}
else {
moveCaretTo(min(ranges[0].endOffset, editorText.length))
}
}
private fun countMatchingCharacters(offset: Int, query: String): Int {
var count = 0
while (offset + count < editorText.length && count < query.length && editorText[offset + count] == query[count]) {
count++
}
return count
}
/**
* Selects a sequence of contiguous characters adjacent to the target offset
* matching [Character.isJavaIdentifierPart], or nothing at all.

View File

@@ -6,10 +6,12 @@ modesHeading=Modes
cycleModeOrderLabel=Cycle order:
jumpModeDisabled=(Skip)
jumpModeJump=Jump
jumpModeJumpEnd=Jump to End
jumpModeTarget=Target
jumpModeDefine=Definition
colorsHeading=Colors
jumpModeColorLabel=Jump mode caret background:
jumpEndModeColorLabel=Jump to End mode caret background:
targetModeColorLabel=Target mode caret background:
definitionModeColorLabel=Definition mode caret background:
textHighlightColorLabel=Searched text background:

View File

@@ -22,44 +22,47 @@
<actions>
<action id="AceAction"
class="org.acejump.control.AceAction"
text="Activate AceJump Mode"
description="Targets a character in AceJump">
class="org.acejump.control.AceAction$ActivateOrCycleMode"
text="Activate / Cycle AceJump Mode">
<keyboard-shortcut keymap="Mac OS X" first-keystroke="ctrl SEMICOLON"/>
<keyboard-shortcut keymap="Mac OS X 10.5+" first-keystroke="ctrl SEMICOLON"/>
<keyboard-shortcut keymap="$default" first-keystroke="ctrl SEMICOLON"/>
</action>
<action id="AceWordStartAction"
class="org.acejump.control.AceAction$ToggleJumpMode"
text="Start AceJump in Word Start Mode"/>
<action id="AceWordEndAction"
class="org.acejump.control.AceAction$ToggleJumpEndMode"
text="Start AceJump in Word End Mode"/>
<action id="AceTargetAction"
class="org.acejump.control.AceAction$ToggleSelectWordMode"
text="Start AceJump in Word Select Mode">
<keyboard-shortcut keymap="Mac OS X" first-keystroke="ctrl alt SEMICOLON"/>
<keyboard-shortcut keymap="Mac OS X 10.5+" first-keystroke="ctrl alt SEMICOLON"/>
<keyboard-shortcut keymap="$default" first-keystroke="ctrl alt SEMICOLON"/>
</action>
<action id="AceDeclarationAction"
class="org.acejump.control.AceAction$ToggleDefinitionMode"
text="Start AceJump in Declaration Mode"/>
<action id="AceLineAction"
class="org.acejump.control.AceLineAction"
text="Display Line Markers"
class="org.acejump.control.AceAction$ToggleAllLinesMode"
text="Start AceJump in All Lines Mode"
description="Targets line markers in AceJump">
<keyboard-shortcut keymap="Mac OS X" first-keystroke="ctrl shift SEMICOLON"/>
<keyboard-shortcut keymap="Mac OS X 10.5+" first-keystroke="ctrl shift SEMICOLON"/>
<keyboard-shortcut keymap="$default" first-keystroke="ctrl shift SEMICOLON"/>
</action>
<action id="AceTargetAction"
class="org.acejump.control.AceTargetAction"
text="Start in Target Mode"
description="Targets a whole word in AceJump">
<keyboard-shortcut keymap="Mac OS X" first-keystroke="ctrl alt SEMICOLON"/>
<keyboard-shortcut keymap="Mac OS X 10.5+" first-keystroke="ctrl alt SEMICOLON"/>
<keyboard-shortcut keymap="$default" first-keystroke="ctrl alt SEMICOLON"/>
</action>
<action id="AceWordAction"
class="org.acejump.control.AceWordAction"
text="Start in Word Mode"
description="Searches for all words on the screen in AceJump"/>
class="org.acejump.control.AceAction$ToggleAllWordsMode"
text="Start AceJump in All Words Mode"/>
<action id="AceWordForwardAction"
class="org.acejump.control.AceWordForwardAction"
text="Start in Word Forward Mode"
description="Searches for all visible words after the caret in AceJump"/>
class="org.acejump.control.AceAction$ToggleAllWordsForwardMode"
text="Start in All Words After Caret Mode"/>
<action id="AceWordBackwardsAction"
class="org.acejump.control.AceWordBackwardsAction"
text="Start in Word Backward Mode"
description="Searches for all visible words before the caret in AceJump"/>
<action id="AceDeclarationAction"
class="org.acejump.control.AceDefinitionAction"
text="Start in Declaration Mode"
description="AceJump will invoke the 'Navigate To' action after jumping"/>
class="org.acejump.control.AceAction$ToggleAllWordsBackwardsMode"
text="Start in All Words Before Caret Mode"/>
<action id="AceActOnHighlightedWords"
class="org.acejump.control.AceAction$ActOnHighlightedWords"
text="Act on Highlighted Words"/>
</actions>
</idea-plugin>