From 91693b6c8195c566d627eb48595b434522e2f8d2 Mon Sep 17 00:00:00 2001 From: Mitja Date: Fri, 5 Jun 2026 11:06:46 +0300 Subject: [PATCH 1/4] Add list rollover --- build.gradle.kts | 12 +--- changelog.md | 4 ++ .../com/mituuz/fuzzier/actions/FuzzyAction.kt | 26 +++++-- .../mituuz/fuzzier/FuzzyActionRolloverTest.kt | 69 +++++++++++++++++++ 4 files changed, 94 insertions(+), 17 deletions(-) create mode 100644 src/test/kotlin/com/mituuz/fuzzier/FuzzyActionRolloverTest.kt diff --git a/build.gradle.kts b/build.gradle.kts index d4943384..c367bd58 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -27,7 +27,7 @@ import org.jetbrains.kotlin.gradle.dsl.JvmTarget import org.jetbrains.kotlin.gradle.tasks.KotlinCompile // Use the same version and group for the jar and the plugin -val currentVersion = "2.4.0" +val currentVersion = "2.5.0" val myGroup = "com.mituuz" version = currentVersion group = myGroup @@ -41,15 +41,7 @@ intellijPlatform {

Version $currentVersion

""".trimIndent() diff --git a/changelog.md b/changelog.md index 8f4472f7..0f40ecbd 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,9 @@ # Changelog +## Version 2.5.0 + +- Add list rollover support + ## Version 2.4.0 - Add file recency scoring diff --git a/src/main/kotlin/com/mituuz/fuzzier/actions/FuzzyAction.kt b/src/main/kotlin/com/mituuz/fuzzier/actions/FuzzyAction.kt index 799d953c..36dd91c4 100644 --- a/src/main/kotlin/com/mituuz/fuzzier/actions/FuzzyAction.kt +++ b/src/main/kotlin/com/mituuz/fuzzier/actions/FuzzyAction.kt @@ -59,6 +59,7 @@ import java.awt.Font import java.awt.event.ActionEvent import java.util.concurrent.ConcurrentHashMap import javax.swing.* +import kotlin.time.Duration.Companion.milliseconds abstract class FuzzyAction : AnAction() { companion object { @@ -160,7 +161,7 @@ abstract class FuzzyAction : AnAction() { debounceJob?.cancel() val debouncePeriod = globalState.debouncePeriod debounceJob = actionScope?.launch { - delay(debouncePeriod.toLong()) + delay(debouncePeriod.toLong().milliseconds) updateListContents(project, component.searchField.text) } } @@ -226,18 +227,29 @@ abstract class FuzzyAction : AnAction() { fun moveListUp() { val selectedIndex = component.fileList.selectedIndex - if (selectedIndex > 0) { - component.fileList.selectedIndex = selectedIndex - 1 - component.fileList.ensureIndexIsVisible(selectedIndex - 1) + val length = component.fileList.model.size + if (length > 0) { + if (selectedIndex > 0) { + component.fileList.selectedIndex = selectedIndex - 1 + component.fileList.ensureIndexIsVisible(selectedIndex - 1) + } else { + component.fileList.selectedIndex = length - 1 + component.fileList.ensureIndexIsVisible(length - 1) + } } } fun moveListDown() { val selectedIndex = component.fileList.selectedIndex val length = component.fileList.model.size - if (selectedIndex < length - 1) { - component.fileList.selectedIndex = selectedIndex + 1 - component.fileList.ensureIndexIsVisible(selectedIndex + 1) + if (length > 0) { + if (selectedIndex != -1 && selectedIndex < length - 1) { + component.fileList.selectedIndex = selectedIndex + 1 + component.fileList.ensureIndexIsVisible(selectedIndex + 1) + } else { + component.fileList.selectedIndex = 0 + component.fileList.ensureIndexIsVisible(0) + } } } diff --git a/src/test/kotlin/com/mituuz/fuzzier/FuzzyActionRolloverTest.kt b/src/test/kotlin/com/mituuz/fuzzier/FuzzyActionRolloverTest.kt new file mode 100644 index 00000000..f9e28542 --- /dev/null +++ b/src/test/kotlin/com/mituuz/fuzzier/FuzzyActionRolloverTest.kt @@ -0,0 +1,69 @@ +package com.mituuz.fuzzier + +import com.intellij.openapi.actionSystem.AnActionEvent +import com.intellij.openapi.project.Project +import com.intellij.testFramework.TestApplicationManager +import com.mituuz.fuzzier.actions.FuzzyAction +import com.mituuz.fuzzier.components.SimpleFinderComponent +import com.mituuz.fuzzier.entities.FuzzyContainer +import com.mituuz.fuzzier.entities.FuzzyMatchContainer +import com.mituuz.fuzzier.entities.FuzzyMatchContainer.FileType.FILE +import com.mituuz.fuzzier.entities.FuzzyMatchContainer.FuzzyScore +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Test +import javax.swing.DefaultListModel + +class FuzzyActionRolloverTest { + @Suppress("unused") + private val testApplicationManager: TestApplicationManager = TestApplicationManager.getInstance() + + @Test + fun `Test moveListUp rollover`() { + val action = getAction() + action.component = SimpleFinderComponent() + val model = DefaultListModel() + model.addElement(FuzzyMatchContainer(FuzzyScore(), "/src/asd1", "asd1", "", FILE)) + model.addElement(FuzzyMatchContainer(FuzzyScore(), "/src/asd2", "asd2", "", FILE)) + model.addElement(FuzzyMatchContainer(FuzzyScore(), "/src/asd3", "asd3", "", FILE)) + action.component.fileList.model = model + action.component.fileList.selectedIndex = 0 + + action.moveListUp() + assertEquals(2, action.component.fileList.selectedIndex) + + action.moveListUp() + assertEquals(1, action.component.fileList.selectedIndex) + + action.moveListUp() + assertEquals(0, action.component.fileList.selectedIndex) + } + + @Test + fun `Test moveListDown rollover`() { + val action = getAction() + action.component = SimpleFinderComponent() + val model = DefaultListModel() + model.addElement(FuzzyMatchContainer(FuzzyScore(), "/src/asd1", "asd1", "", FILE)) + model.addElement(FuzzyMatchContainer(FuzzyScore(), "/src/asd2", "asd2", "", FILE)) + model.addElement(FuzzyMatchContainer(FuzzyScore(), "/src/asd3", "asd3", "", FILE)) + action.component.fileList.model = model + action.component.fileList.selectedIndex = 2 + + action.moveListDown() + assertEquals(0, action.component.fileList.selectedIndex) + + action.moveListDown() + assertEquals(1, action.component.fileList.selectedIndex) + + action.moveListDown() + assertEquals(2, action.component.fileList.selectedIndex) + } + + private fun getAction(): FuzzyAction { + return object : FuzzyAction() { + override fun actionPerformed(actionEvent: AnActionEvent) {} + override fun runAction(project: Project, actionEvent: AnActionEvent) {} + override fun updateListContents(project: Project, searchString: String) {} + } + } +} From e22bfa468feb92517999d1b06fb908b80f73a1be Mon Sep 17 00:00:00 2001 From: Mitja Date: Fri, 5 Jun 2026 11:18:44 +0300 Subject: [PATCH 2/4] Update readme --- readme.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/readme.md b/readme.md index 22576af9..71579c6f 100644 --- a/readme.md +++ b/readme.md @@ -45,7 +45,8 @@ List movement can be remapped from settings -> keymaps, but do not support chord - Fuzzy file search - Search all except excluded files - Search only from VCS-tracked files -- Text search leveraging [ripgrep](https://github.com/BurntSushi/ripgrep "Link to GitHub - ripgrep"), grep or findstr +- Text search leveraging [ripgrep](https://github.com/BurntSushi/ripgrep "Link to GitHub - ripgrep") or a native + implementation - Support for searching from the whole project, within open tabs or the current buffer - With file extension support for ripgrep in the secondary search field - File mover From 7c9308fdb850e2e1a7c75f1fbf3528c86ee66a53 Mon Sep 17 00:00:00 2001 From: Mitja Date: Fri, 5 Jun 2026 11:28:57 +0300 Subject: [PATCH 3/4] Remove unnecessary file --- .../mituuz/fuzzier/FuzzyActionRolloverTest.kt | 69 ------------------- .../com/mituuz/fuzzier/FuzzyActionTest.kt | 48 +++++++++++-- 2 files changed, 44 insertions(+), 73 deletions(-) delete mode 100644 src/test/kotlin/com/mituuz/fuzzier/FuzzyActionRolloverTest.kt diff --git a/src/test/kotlin/com/mituuz/fuzzier/FuzzyActionRolloverTest.kt b/src/test/kotlin/com/mituuz/fuzzier/FuzzyActionRolloverTest.kt deleted file mode 100644 index f9e28542..00000000 --- a/src/test/kotlin/com/mituuz/fuzzier/FuzzyActionRolloverTest.kt +++ /dev/null @@ -1,69 +0,0 @@ -package com.mituuz.fuzzier - -import com.intellij.openapi.actionSystem.AnActionEvent -import com.intellij.openapi.project.Project -import com.intellij.testFramework.TestApplicationManager -import com.mituuz.fuzzier.actions.FuzzyAction -import com.mituuz.fuzzier.components.SimpleFinderComponent -import com.mituuz.fuzzier.entities.FuzzyContainer -import com.mituuz.fuzzier.entities.FuzzyMatchContainer -import com.mituuz.fuzzier.entities.FuzzyMatchContainer.FileType.FILE -import com.mituuz.fuzzier.entities.FuzzyMatchContainer.FuzzyScore -import org.junit.jupiter.api.Assertions.assertEquals -import org.junit.jupiter.api.Test -import javax.swing.DefaultListModel - -class FuzzyActionRolloverTest { - @Suppress("unused") - private val testApplicationManager: TestApplicationManager = TestApplicationManager.getInstance() - - @Test - fun `Test moveListUp rollover`() { - val action = getAction() - action.component = SimpleFinderComponent() - val model = DefaultListModel() - model.addElement(FuzzyMatchContainer(FuzzyScore(), "/src/asd1", "asd1", "", FILE)) - model.addElement(FuzzyMatchContainer(FuzzyScore(), "/src/asd2", "asd2", "", FILE)) - model.addElement(FuzzyMatchContainer(FuzzyScore(), "/src/asd3", "asd3", "", FILE)) - action.component.fileList.model = model - action.component.fileList.selectedIndex = 0 - - action.moveListUp() - assertEquals(2, action.component.fileList.selectedIndex) - - action.moveListUp() - assertEquals(1, action.component.fileList.selectedIndex) - - action.moveListUp() - assertEquals(0, action.component.fileList.selectedIndex) - } - - @Test - fun `Test moveListDown rollover`() { - val action = getAction() - action.component = SimpleFinderComponent() - val model = DefaultListModel() - model.addElement(FuzzyMatchContainer(FuzzyScore(), "/src/asd1", "asd1", "", FILE)) - model.addElement(FuzzyMatchContainer(FuzzyScore(), "/src/asd2", "asd2", "", FILE)) - model.addElement(FuzzyMatchContainer(FuzzyScore(), "/src/asd3", "asd3", "", FILE)) - action.component.fileList.model = model - action.component.fileList.selectedIndex = 2 - - action.moveListDown() - assertEquals(0, action.component.fileList.selectedIndex) - - action.moveListDown() - assertEquals(1, action.component.fileList.selectedIndex) - - action.moveListDown() - assertEquals(2, action.component.fileList.selectedIndex) - } - - private fun getAction(): FuzzyAction { - return object : FuzzyAction() { - override fun actionPerformed(actionEvent: AnActionEvent) {} - override fun runAction(project: Project, actionEvent: AnActionEvent) {} - override fun updateListContents(project: Project, searchString: String) {} - } - } -} diff --git a/src/test/kotlin/com/mituuz/fuzzier/FuzzyActionTest.kt b/src/test/kotlin/com/mituuz/fuzzier/FuzzyActionTest.kt index 20b6f242..8bbccfc9 100644 --- a/src/test/kotlin/com/mituuz/fuzzier/FuzzyActionTest.kt +++ b/src/test/kotlin/com/mituuz/fuzzier/FuzzyActionTest.kt @@ -33,6 +33,7 @@ import com.intellij.testFramework.TestApplicationManager import com.intellij.testFramework.fixtures.CodeInsightTestFixture import com.mituuz.fuzzier.actions.FuzzyAction import com.mituuz.fuzzier.components.SimpleFinderComponent +import com.mituuz.fuzzier.entities.FuzzyContainer import com.mituuz.fuzzier.entities.FuzzyContainer.FilenameType.* import com.mituuz.fuzzier.entities.FuzzyMatchContainer import com.mituuz.fuzzier.entities.FuzzyMatchContainer.FileType.FILE @@ -41,10 +42,7 @@ import org.junit.jupiter.api.Assertions.* import org.junit.jupiter.api.Test import java.awt.event.InputEvent import java.awt.event.KeyEvent -import javax.swing.JComponent -import javax.swing.JLabel -import javax.swing.JList -import javax.swing.KeyStroke +import javax.swing.* class FuzzyActionTest { @Suppress("unused") @@ -185,6 +183,48 @@ class FuzzyActionTest { assertEquals(expectedIcon, component.icon) } + @Test + fun `Test moveListUp rollover`() { + val action = getAction() + action.component = SimpleFinderComponent() + val model = DefaultListModel() + model.addElement(FuzzyMatchContainer(FuzzyScore(), "/src/asd1", "asd1", "", FILE)) + model.addElement(FuzzyMatchContainer(FuzzyScore(), "/src/asd2", "asd2", "", FILE)) + model.addElement(FuzzyMatchContainer(FuzzyScore(), "/src/asd3", "asd3", "", FILE)) + action.component.fileList.model = model + action.component.fileList.selectedIndex = 0 + + action.moveListUp() + assertEquals(2, action.component.fileList.selectedIndex) + + action.moveListUp() + assertEquals(1, action.component.fileList.selectedIndex) + + action.moveListUp() + assertEquals(0, action.component.fileList.selectedIndex) + } + + @Test + fun `Test moveListDown rollover`() { + val action = getAction() + action.component = SimpleFinderComponent() + val model = DefaultListModel() + model.addElement(FuzzyMatchContainer(FuzzyScore(), "/src/asd1", "asd1", "", FILE)) + model.addElement(FuzzyMatchContainer(FuzzyScore(), "/src/asd2", "asd2", "", FILE)) + model.addElement(FuzzyMatchContainer(FuzzyScore(), "/src/asd3", "asd3", "", FILE)) + action.component.fileList.model = model + action.component.fileList.selectedIndex = 2 + + action.moveListDown() + assertEquals(0, action.component.fileList.selectedIndex) + + action.moveListDown() + assertEquals(1, action.component.fileList.selectedIndex) + + action.moveListDown() + assertEquals(2, action.component.fileList.selectedIndex) + } + private fun getAction(): FuzzyAction { return object : FuzzyAction() { override fun actionPerformed(actionEvent: AnActionEvent) { From b4e30744ad9571b28e38e1ab82c186282ff995fe Mon Sep 17 00:00:00 2001 From: Mitja Date: Sun, 7 Jun 2026 11:39:22 +0300 Subject: [PATCH 4/4] Refactor to a more readable function and make this a minor bump --- build.gradle.kts | 16 ++++++- changelog.md | 2 +- .../com/mituuz/fuzzier/actions/FuzzyAction.kt | 46 +++++++++++-------- 3 files changed, 42 insertions(+), 22 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index c367bd58..6403475e 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -27,7 +27,7 @@ import org.jetbrains.kotlin.gradle.dsl.JvmTarget import org.jetbrains.kotlin.gradle.tasks.KotlinCompile // Use the same version and group for the jar and the plugin -val currentVersion = "2.5.0" +val currentVersion = "2.4.1" val myGroup = "com.mituuz" version = currentVersion group = myGroup @@ -44,6 +44,20 @@ intellijPlatform { Add list rollover support +

Version 2.4.0

+
    +
  • + Add file recency scoring +
      +
    • + LRU cache for file paths +
    • +
    • + Scoring is based on the recency of the file access and the frequency of the file access +
    • +
    +
  • +
""".trimIndent() ideaVersion { diff --git a/changelog.md b/changelog.md index 0f40ecbd..981b9373 100644 --- a/changelog.md +++ b/changelog.md @@ -1,6 +1,6 @@ # Changelog -## Version 2.5.0 +## Version 2.4.1 - Add list rollover support diff --git a/src/main/kotlin/com/mituuz/fuzzier/actions/FuzzyAction.kt b/src/main/kotlin/com/mituuz/fuzzier/actions/FuzzyAction.kt index 36dd91c4..a4ae220b 100644 --- a/src/main/kotlin/com/mituuz/fuzzier/actions/FuzzyAction.kt +++ b/src/main/kotlin/com/mituuz/fuzzier/actions/FuzzyAction.kt @@ -226,31 +226,37 @@ abstract class FuzzyAction : AnAction() { } fun moveListUp() { - val selectedIndex = component.fileList.selectedIndex - val length = component.fileList.model.size - if (length > 0) { - if (selectedIndex > 0) { - component.fileList.selectedIndex = selectedIndex - 1 - component.fileList.ensureIndexIsVisible(selectedIndex - 1) - } else { - component.fileList.selectedIndex = length - 1 - component.fileList.ensureIndexIsVisible(length - 1) - } + val fileList = component.fileList + val listSize = fileList.model.size + + if (listSize == 0) return + + val currentIndex = fileList.selectedIndex + val newIndex = if (currentIndex in 1 until listSize) { + currentIndex - 1 + } else { + listSize - 1 } + + fileList.selectedIndex = newIndex + fileList.ensureIndexIsVisible(newIndex) } fun moveListDown() { - val selectedIndex = component.fileList.selectedIndex - val length = component.fileList.model.size - if (length > 0) { - if (selectedIndex != -1 && selectedIndex < length - 1) { - component.fileList.selectedIndex = selectedIndex + 1 - component.fileList.ensureIndexIsVisible(selectedIndex + 1) - } else { - component.fileList.selectedIndex = 0 - component.fileList.ensureIndexIsVisible(0) - } + val fileList = component.fileList + val listSize = fileList.model.size + + if (listSize == 0) return + + val currentIndex = fileList.selectedIndex + val newIndex = if (currentIndex < listSize - 1) { + currentIndex + 1 + } else { + 0 } + + fileList.selectedIndex = newIndex + fileList.ensureIndexIsVisible(newIndex) } fun getCellRenderer(): ListCellRenderer {