1
0
mirror of https://github.com/chylex/IntelliJ-AceJump.git synced 2025-04-09 17:15:43 +02:00

Fix algorithm

This commit is contained in:
Breandan Considine 2016-10-04 11:40:52 -04:00
parent 8177c75fe9
commit 85a55694b0
3 changed files with 72 additions and 65 deletions
src/main/kotlin/com/johnlindquist/acejump

View File

@ -11,6 +11,7 @@ import com.intellij.openapi.editor.impl.DocumentImpl
import com.intellij.openapi.editor.impl.EditorImpl
import com.intellij.util.EventDispatcher
import com.johnlindquist.acejump.keycommands.AceJumper
import com.johnlindquist.acejump.ui.JumpInfo
import java.awt.event.KeyEvent
import java.util.*
import javax.swing.event.ChangeEvent
@ -20,7 +21,7 @@ class AceFinder(val findManager: FindManager, val editor: EditorImpl) {
val document = editor.document as DocumentImpl
val eventDispatcher = EventDispatcher.create(ChangeListener::class.java)
val findModel: FindModel = findManager.findInFileModel.clone()
var jumpLocations: Collection<Int> = emptyList()
var jumpLocations: Collection<JumpInfo> = emptyList()
var tagMap: BiMap<String, Int> = HashBiMap.create()
val maxTags = 26
var unusedDigraphs: LinkedHashSet<String> = linkedSetOf()
@ -49,11 +50,14 @@ class AceFinder(val findManager: FindManager, val editor: EditorImpl) {
fun findText(text: String, keyEvent: KeyEvent?) {
findModel.stringToFind = text
if (keyEvent != null && keyEvent.keyChar.isLetter()) {
findModel.stringToFind += keyEvent.keyChar
}
unusedDigraphs = ('a'..'z').mapTo(linkedSetOf(), { "$it" })
tagLocations = HashSet(maxTags)
val application = ApplicationManager.getApplication()
application.runReadAction(jump(keyEvent, text))
application.runReadAction(jump(keyEvent))
application.invokeLater({
if (text.isNotEmpty())
@ -61,43 +65,36 @@ class AceFinder(val findManager: FindManager, val editor: EditorImpl) {
})
}
val aceJumper = AceJumper(editor, document)
private fun jump(keyEvent: KeyEvent?, text: String): () -> Unit {
fun jumpToOffset(keyEvent: KeyEvent, offset: Int?) {
if (offset == null)
return
var targetModeEnabled = false
fun toggleTargetMode(): Boolean {
targetModeEnabled = !targetModeEnabled
return targetModeEnabled
}
val aceJumper = AceJumper(editor, document)
private fun jump(keyEvent: KeyEvent?): () -> Unit {
fun jumpTo(keyEvent: KeyEvent, jumpInfo: JumpInfo) {
if (keyEvent.isShiftDown && !keyEvent.isMetaDown) {
aceJumper.setSelectionFromCaretToOffset(offset)
aceJumper.moveCaret(offset)
} else {
aceJumper.moveCaret(offset)
aceJumper.setSelectionFromCaretToOffset(jumpInfo.offset)
}
aceJumper.moveCaret(jumpInfo.offset)
if (targetModeEnabled) {
aceJumper.selectWordAtCaret()
}
tagMap = HashBiMap.create()
}
fun isReadyToJump(text: String): Boolean {
return (text.isNotEmpty() && !findModel.isRegularExpressions &&
tagMap.containsKey(text.last().toString()) &&
!tagMap.containsKey(text))
reset()
}
return {
jumpLocations = determineJumpLocations()
if (isReadyToJump(text)) {
jumpToOffset(keyEvent!!, tagMap[text.last().toString()]!! - text.length)
} else if (jumpLocations.size == 1) {
jumpToOffset(keyEvent!!, jumpLocations.first() - text.length)
if (jumpLocations.size == 1) {
jumpTo(keyEvent!!, jumpLocations.first())
}
}
}
private fun determineJumpLocations(): Collection<Int> {
private fun determineJumpLocations(): Collection<JumpInfo> {
fun getSitesToCheck(window: String): Iterable<Int> {
if (findModel.stringToFind.isEmpty())
return 0..(window.length - 2)
@ -112,22 +109,32 @@ class AceFinder(val findManager: FindManager, val editor: EditorImpl) {
return indicesToCheck
}
//todo: refactor this mess
val text = findModel.stringToFind
if (text.isNotEmpty()) {
if (tagMap.containsKey(text))
return listOf(JumpInfo(text, text, tagMap[text]!!, editor))
if (1 < text.length) {
val last1: String = text.substring(text.length - 1)
if (tagMap.containsKey(last1))
return listOf(JumpInfo(last1, text, tagMap[last1]!!, editor))
if (2 < text.length) {
val last2: String = text.substring(text.length - 2)
if (tagMap.containsKey(last2))
return listOf(JumpInfo(last2, text, tagMap[last2]!!, editor))
}
}
}
val (startIndex, endIndex) = getVisibleRange(editor)
val fullText = document.charsSequence
val fullText = document.charsSequence.toString().toLowerCase()
val window = fullText.substring(startIndex, endIndex)
val sitesToCheck = getSitesToCheck(window).map { it + startIndex }
if (sitesToCheck.size <= 1)
return sitesToCheck
val existingDigraphs = makeMap(fullText, sitesToCheck)
tagMap = mapUniqueDigraphs(existingDigraphs)
return tagMap.values
return plotJumpLocations()
}
var targetModeEnabled = false
fun toggleTargetMode(): Boolean {
targetModeEnabled = !targetModeEnabled
return targetModeEnabled
}
fun makeMap(text: CharSequence, sites: Iterable<Int>): Multimap<String, Int> {
val stringToIndex = LinkedListMultimap.create<String, Int>()
@ -179,10 +186,20 @@ class AceFinder(val findManager: FindManager, val editor: EditorImpl) {
return newTagMap
}
fun findText(text: Regexp, keyEvent: KeyEvent? = null) {
findModel.isRegularExpressions = true
findText(text.pattern, keyEvent)
findModel.isRegularExpressions = false
}
fun plotJumpLocations(): List<JumpInfo> {
return tagMap.values.map {
JumpInfo(tagMap.inverse()[it]!!, findModel.stringToFind, it, editor)
}
}
fun reset() {
tagMap = HashBiMap.create()
unusedDigraphs = linkedSetOf()
}
}

View File

@ -10,7 +10,7 @@ class JumpInfo(private val tag: String, val search: String, val index: Int, val
val tagOffset = editor.offsetToVisualPosition(index)
val tagPoint = getPointFromVisualPosition(editor, tagOffset).originalPoint
val searchOffset = editor.offsetToVisualPosition(index - search.length)
val searchPoint = getPointFromVisualPosition(editor, searchOffset).originalPoint
val offset = index - search.length
fun renderTag(): String {
return tag.mapIndexed { i, c -> if (source.isEmpty() || source[i] == c) ' ' else c }

View File

@ -31,7 +31,7 @@ class SearchBox(val aceFinder: AceFinder, val editor: EditorImpl) : JTextField()
popupContainer = configurePopup()
aceFinder.eventDispatcher.addListener(ChangeListener {
aceCanvas.jumpInfos = plotJumpLocations(aceFinder.tagMap)
aceCanvas.jumpInfos = aceFinder.plotJumpLocations()
if (aceCanvas.jumpInfos.isEmpty() || aceCanvas.jumpInfos.size == 1) {
popupContainer?.cancel()
exit()
@ -40,12 +40,6 @@ class SearchBox(val aceFinder: AceFinder, val editor: EditorImpl) : JTextField()
})
}
fun plotJumpLocations(tagMap: BiMap<String, Int>): List<JumpInfo> {
return tagMap.values.map {
JumpInfo(tagMap.inverse()[it]!!, this@SearchBox.text, it, editor)
}
}
private fun configurePopup(): AbstractPopup? {
val scheme = EditorColorsManager.getInstance().globalScheme
val font = Font(scheme.editorFontName, Font.BOLD, scheme.editorFontSize)
@ -98,33 +92,29 @@ class SearchBox(val aceFinder: AceFinder, val editor: EditorImpl) : JTextField()
//todo: I need to really rethink this entire approach
override fun processKeyEvent(keyEvent: KeyEvent) {
if (keyEvent.id == KeyEvent.KEY_PRESSED &&
(keyEvent.isMetaDown || keyEvent.isControlDown)) {
if (aceFinder.toggleTargetMode()) {
background = Color.RED
} else {
background = Color.WHITE
if (keyEvent.id == KEY_PRESSED) {
if ((keyEvent.isMetaDown || keyEvent.isControlDown)) {
if (aceFinder.toggleTargetMode())
background = Color.RED
else
background = Color.WHITE
}
if (keyEvent.keyCode == VK_BACK_SPACE) {
if (text.isNotEmpty())
text = text.substring(0, text.length - 1)
return
}
defaultKeyCommand.execute(keyEvent, text)
if (keyMap.contains(keyEvent.keyCode)) {
keyEvent.consume()
keyMap[keyEvent.keyCode]?.execute(keyEvent)
return
}
}
if (keyEvent.keyCode == VK_BACK_SPACE) {
if (text.isNotEmpty())
text = text.substring(0, text.length - 1)
return
}
defaultKeyCommand.execute(keyEvent, text)
if (keyMap.contains(keyEvent.keyCode)) {
keyEvent.consume()
keyMap[keyEvent.keyCode]?.execute(keyEvent)
return
}
super.processKeyEvent(keyEvent)
if (keyEvent.id != KeyEvent.KEY_TYPED) return
}
fun addAceCanvas() {