From 4622fbb20b4a84dcceb16fa0c19c3f54b60396c9 Mon Sep 17 00:00:00 2001 From: breandan Date: Sat, 17 Apr 2021 15:44:08 -0400 Subject: [PATCH] pass back necessary info instead of reconstructing Merge branch 'listener_update' of https://github.com/AlexPl292/AceJump into AlexPl292-listener_update # Conflicts: # src/test/kotlin/ExternalUsageTest.kt --- .../org/acejump/action/AceEditorAction.kt | 2 - src/main/kotlin/org/acejump/search/Tagger.kt | 3 +- .../org/acejump/search/TaggingResult.kt | 4 +- .../org/acejump/session/AceJumpListener.kt | 2 +- .../kotlin/org/acejump/session/Session.kt | 16 +++-- .../org/acejump/session/SessionManager.kt | 6 +- src/main/kotlin/org/acejump/view/Tag.kt | 2 +- src/main/kotlin/org/acejump/view/TagFont.kt | 2 +- src/test/kotlin/ExternalUsageTest.kt | 69 +++++++++++++++++-- 9 files changed, 85 insertions(+), 21 deletions(-) diff --git a/src/main/kotlin/org/acejump/action/AceEditorAction.kt b/src/main/kotlin/org/acejump/action/AceEditorAction.kt index 1d2a5b3f..3c5b6470 100644 --- a/src/main/kotlin/org/acejump/action/AceEditorAction.kt +++ b/src/main/kotlin/org/acejump/action/AceEditorAction.kt @@ -4,9 +4,7 @@ import com.intellij.openapi.actionSystem.DataContext import com.intellij.openapi.editor.Caret import com.intellij.openapi.editor.Editor import com.intellij.openapi.editor.actionSystem.EditorActionHandler -import org.acejump.boundaries.StandardBoundaries import org.acejump.boundaries.StandardBoundaries.* -import org.acejump.search.Pattern import org.acejump.search.Pattern.* import org.acejump.session.Session import org.acejump.session.SessionManager diff --git a/src/main/kotlin/org/acejump/search/Tagger.kt b/src/main/kotlin/org/acejump/search/Tagger.kt index 5c10f0d3..eae32950 100644 --- a/src/main/kotlin/org/acejump/search/Tagger.kt +++ b/src/main/kotlin/org/acejump/search/Tagger.kt @@ -53,7 +53,8 @@ internal class Tagger(private val editor: Editor) { if (!isRegex) { for (entry in tagMap.entries) - if (entry solves queryText) return TaggingResult.Jump(entry.value) + if (entry solves queryText) + return TaggingResult.Jump(query = queryText.substringBefore(entry.key), tag = entry.key, offset = entry.value) if (queryText.length == 1) removeResultsWithOverlappingTags(results) } diff --git a/src/main/kotlin/org/acejump/search/TaggingResult.kt b/src/main/kotlin/org/acejump/search/TaggingResult.kt index 9773f7c8..2a229a96 100644 --- a/src/main/kotlin/org/acejump/search/TaggingResult.kt +++ b/src/main/kotlin/org/acejump/search/TaggingResult.kt @@ -2,7 +2,7 @@ package org.acejump.search import org.acejump.view.Tag -internal sealed class TaggingResult { - class Jump(val offset: Int): TaggingResult() +sealed class TaggingResult { + class Jump(val query: String, val tag: String, val offset: Int): TaggingResult() class Mark(val tags: List): TaggingResult() } diff --git a/src/main/kotlin/org/acejump/session/AceJumpListener.kt b/src/main/kotlin/org/acejump/session/AceJumpListener.kt index 7fde3527..eaf49540 100644 --- a/src/main/kotlin/org/acejump/session/AceJumpListener.kt +++ b/src/main/kotlin/org/acejump/session/AceJumpListener.kt @@ -1,5 +1,5 @@ package org.acejump.session interface AceJumpListener { - fun finished() + fun finished(mark: String?, query: String?) } diff --git a/src/main/kotlin/org/acejump/session/Session.kt b/src/main/kotlin/org/acejump/session/Session.kt index 61c6408f..fe5b933e 100644 --- a/src/main/kotlin/org/acejump/session/Session.kt +++ b/src/main/kotlin/org/acejump/session/Session.kt @@ -12,7 +12,6 @@ import org.acejump.action.TagJumper import org.acejump.action.TagVisitor import org.acejump.boundaries.Boundaries import org.acejump.boundaries.EditorOffsetCache -import org.acejump.boundaries.StandardBoundaries import org.acejump.boundaries.StandardBoundaries.* import org.acejump.config.AceConfig import org.acejump.input.EditorKeyListener @@ -126,7 +125,7 @@ class Session(private val editor: Editor) { is TaggingResult.Jump -> { tagJumper.jump(result.offset, shiftMode) tagCanvas.removeMarkers() - end() + end(result) } is TaggingResult.Mark -> { @@ -217,12 +216,14 @@ class Session(private val editor: Editor) { /** * See [TagVisitor.visitNext]. If there are no tags, nothing happens. */ - fun visitNextTag() = if (tagVisitor?.visitNext() == true) end() else Unit + fun visitNextTag() = + if (tagVisitor?.visitNext() == true) end() else Unit /** * Ends this session. */ - fun end() = SessionManager.end(editor) + fun end(taggingResult: TaggingResult? = null) = + SessionManager.end(editor, taggingResult) /** * Clears any currently active search, tags, and highlights. @@ -239,13 +240,16 @@ class Session(private val editor: Editor) { * Should only be used from [SessionManager] to dispose a * successfully ended session. */ - internal fun dispose() { + internal fun dispose(taggingResult: TaggingResult?) { tagger = Tagger(editor) EditorKeyListener.detach(editor) tagCanvas.unbind() textHighlighter.reset() EditorCache.invalidate() - listeners.forEach(AceJumpListener::finished) + + val (tag, query) = (taggingResult as TaggingResult.Jump?) + .let { it?.tag to it?.query } + listeners.forEach { it.finished(tag, query) } if (!editor.isDisposed) { originalSettings.restore(editor) diff --git a/src/main/kotlin/org/acejump/session/SessionManager.kt b/src/main/kotlin/org/acejump/session/SessionManager.kt index 23addcdc..13e9be3a 100644 --- a/src/main/kotlin/org/acejump/session/SessionManager.kt +++ b/src/main/kotlin/org/acejump/session/SessionManager.kt @@ -2,6 +2,7 @@ package org.acejump.session import com.intellij.openapi.editor.Editor import org.acejump.ExternalUsage +import org.acejump.search.TaggingResult /** * Manages active [Session]s in [Editor]s. There may only be @@ -35,8 +36,9 @@ object SessionManager { * Ends the active [Session] in the specified [Editor], * or does nothing if the [Editor] has no active session. */ - fun end(editor: Editor) = sessions.remove(editor)?.dispose() ?: Unit + fun end(editor: Editor, taggingResult: TaggingResult?) = + sessions.remove(editor)?.dispose(taggingResult) ?: Unit private fun cleanup() = sessions.keys.filter { it.isDisposed } - .forEach { disposedEditor -> sessions.remove(disposedEditor)?.dispose() } + .forEach { disposedEditor -> sessions.remove(disposedEditor)?.dispose(null) } } diff --git a/src/main/kotlin/org/acejump/view/Tag.kt b/src/main/kotlin/org/acejump/view/Tag.kt index b0de2162..cb4dd8dd 100644 --- a/src/main/kotlin/org/acejump/view/Tag.kt +++ b/src/main/kotlin/org/acejump/view/Tag.kt @@ -17,7 +17,7 @@ import kotlin.math.max /** * Describes a 1 or 2 character shortcut that points to a specific character in the editor. */ -internal class Tag( +class Tag( private val tag: String, val offsetL: Int, val offsetR: Int, diff --git a/src/main/kotlin/org/acejump/view/TagFont.kt b/src/main/kotlin/org/acejump/view/TagFont.kt index ad38e396..e8428fc6 100644 --- a/src/main/kotlin/org/acejump/view/TagFont.kt +++ b/src/main/kotlin/org/acejump/view/TagFont.kt @@ -9,7 +9,7 @@ import java.awt.FontMetrics /** * Stores font metrics for aligning and rendering [Tag]s. */ -internal class TagFont(editor: Editor) { +class TagFont(editor: Editor) { val tagFont: Font = editor.colorsScheme.getFont(BOLD) val tagCharWidth = editor.component.getFontMetrics(tagFont).charWidth('W') diff --git a/src/test/kotlin/ExternalUsageTest.kt b/src/test/kotlin/ExternalUsageTest.kt index db711894..896f3a5b 100644 --- a/src/test/kotlin/ExternalUsageTest.kt +++ b/src/test/kotlin/ExternalUsageTest.kt @@ -1,12 +1,12 @@ import com.intellij.openapi.editor.Editor +import com.intellij.util.ui.UIUtil import junit.framework.TestCase -import org.acejump.boundaries.Boundaries -import org.acejump.boundaries.EditorOffsetCache +import org.acejump.action.AceAction +import org.acejump.boundaries.* import org.acejump.boundaries.StandardBoundaries.WHOLE_FILE import org.acejump.input.JumpMode import org.acejump.search.Pattern.ALL_WORDS -import org.acejump.session.AceJumpListener -import org.acejump.session.SessionManager +import org.acejump.session.* import org.acejump.test.util.BaseTest /** @@ -24,7 +24,7 @@ class ExternalUsageTest: BaseTest() { var shouldBeTrueAfterFinished = false session.addAceJumpListener(object: AceJumpListener { - override fun finished() { + override fun finished(mark: String?, query: String?) { shouldBeTrueAfterFinished = true } }) @@ -71,4 +71,63 @@ class ExternalUsageTest: BaseTest() { TestCase.assertEquals(1, session.tags.size) TestCase.assertEquals(14, session.tags.single().value) } + + fun `test listener query and mark`() { + "testing 1234".search("g") + + var detectedMark: String? = null + var detectedQuery: String? = null + session.addAceJumpListener(object: AceJumpListener { + override fun finished(mark: String?, query: String?) { + detectedMark = mark + detectedQuery = query + } + }) + + val mark = session.tags[0].key + typeAndWaitForResults(mark) + + TestCase.assertEquals(mark, detectedMark) + TestCase.assertEquals("g", detectedQuery) + } + + fun `test listener after escape`() { + "testing 1234".search("g") + + var detectedMark: String? = null + var detectedQuery: String? = null + session.addAceJumpListener(object: AceJumpListener { + override fun finished(mark: String?, query: String?) { + detectedMark = mark + detectedQuery = query + } + }) + + myFixture.performEditorAction("EditorEscape") + UIUtil.dispatchAllInvocationEvents() + + TestCase.assertEquals(null, detectedMark) + TestCase.assertEquals(null, detectedQuery) + } + + fun `test listener for word motion`() { + makeEditor("test word action") + + takeAction(AceAction.StartAllWordsMode()) + + var detectedMark: String? = null + var detectedQuery: String? = null + session.addAceJumpListener(object: AceJumpListener { + override fun finished(mark: String?, query: String?) { + detectedMark = mark + detectedQuery = query + } + }) + + val mark = session.tags[1].key + typeAndWaitForResults(mark) + + TestCase.assertEquals(mark, detectedMark) + TestCase.assertEquals("", detectedQuery) + } }