Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions src/main/kotlin/com/mituuz/fuzzier/actions/FuzzyAction.kt
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,6 @@ abstract class FuzzyAction : AnAction() {
protected val globalState = service<FuzzierGlobalSettingsService>().state
protected var defaultDoc: Document? = null
private val fileTypeManager = FileTypeManager.getInstance()

val fuzzierUtil = FuzzierUtil()
protected open var currentUpdateListContentJob: Job? = null
protected open var actionScope: CoroutineScope? = null

Expand Down Expand Up @@ -104,7 +102,7 @@ abstract class FuzzyAction : AnAction() {
val project = actionEvent.project
if (project != null) {
projectState = project.service<FuzzierSettingsService>().state
fuzzierUtil.parseModules(project)
FuzzierUtil.parseModules(project)
setCustomHandlers()
actionScope?.cancel()
actionScope = CoroutineScope(SupervisorJob() + Dispatchers.Default)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,7 @@ class TestBenchComponent : JPanel(), Disposable {
val project = ProjectManager.getInstance().openProjects[0]
projectState = project.service<FuzzierSettingsService>().state

val fuzzierUtil = FuzzierUtil()
fuzzierUtil.parseModules(project)
FuzzierUtil.parseModules(project)

liveSettingsComponent = settingsComponent
layout = GridLayoutManager(2, 1)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ import com.intellij.openapi.vfs.VfsUtil
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.psi.search.GlobalSearchScope
import com.intellij.psi.search.PsiSearchHelper
import com.intellij.openapi.components.service
import com.intellij.util.Processor
import com.mituuz.fuzzier.entities.CaseMode
import com.mituuz.fuzzier.entities.FuzzyContainer
Expand All @@ -50,7 +49,6 @@ import javax.swing.DefaultListModel

object FuzzierGrep : BackendStrategy {
override val name = "fuzzier"
private val fuzzierUtil = FuzzierUtil()
private val searchMatcher = SearchMatcher()

override suspend fun handleSearch(
Expand All @@ -67,6 +65,7 @@ object FuzzierGrep : BackendStrategy {

val maxResults = service<FuzzierGlobalSettingsService>().state.fileListLimit
val batcher = ResultBatcher<FuzzyContainer>()
val modules = project.service<FuzzierSettingsService>().state.modules

for (file in files) {
currentCoroutineContext().ensureActive()
Expand All @@ -83,7 +82,8 @@ object FuzzierGrep : BackendStrategy {
val found = searchMatcher.matchesLine(line, searchString, grepConfig.caseMode)

if (found) {
val (filePath, basePath) = fuzzierUtil.extractModulePath(file.path, project)
val (filePath, basePath) =
FuzzierUtil.extractModulePath(file.path, modules)
fileMatches.add(
RowContainer(
filePath,
Expand Down
42 changes: 18 additions & 24 deletions src/main/kotlin/com/mituuz/fuzzier/search/Fuzzier.kt
Original file line number Diff line number Diff line change
Expand Up @@ -28,21 +28,21 @@ import com.intellij.openapi.actionSystem.AnActionEvent
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.editor.EditorFactory
import com.intellij.openapi.fileEditor.FileEditorManager
import com.intellij.openapi.fileEditor.impl.EditorHistoryManager
import com.intellij.openapi.project.Project
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.openapi.vfs.VirtualFileManager
import com.intellij.util.SingleAlarm
import com.mituuz.fuzzier.actions.filesystem.FilesystemAction
import com.mituuz.fuzzier.components.FuzzyFinderComponent
import com.mituuz.fuzzier.entities.FuzzyContainer
import com.mituuz.fuzzier.intellij.files.FileOpeningUtil
import com.mituuz.fuzzier.intellij.iteration.IntelliJIterationFileCollector
import com.mituuz.fuzzier.intellij.iteration.IterationFileCollector
import com.mituuz.fuzzier.search.initialview.DefaultInitialListModelProvider
import com.mituuz.fuzzier.search.initialview.InitialListModelProvider
import com.mituuz.fuzzier.search.initialview.addFileToRecentlySearchedFiles
import com.mituuz.fuzzier.settings.FuzzierGlobalSettingsService
import com.mituuz.fuzzier.ui.bindings.ActivationBindings
import com.mituuz.fuzzier.ui.popup.PopupConfig
import com.mituuz.fuzzier.util.InitialViewHandler
import javax.swing.DefaultListModel

open class Fuzzier : FilesystemAction() {
Expand All @@ -54,6 +54,14 @@ open class Fuzzier : FilesystemAction() {
return IntelliJIterationFileCollector(projectState)
}

protected open fun getInitialViewProvider(project: Project): InitialListModelProvider {
return DefaultInitialListModelProvider(
project,
globalState,
projectState,
)
}

override fun buildFileFilter(project: Project): (VirtualFile) -> Boolean =
{ vf -> !vf.isDirectory }

Expand Down Expand Up @@ -133,7 +141,11 @@ open class Fuzzier : FilesystemAction() {
globalState.newTab
) {
if (selectedValue != null) {
InitialViewHandler.addFileToRecentlySearchedFiles(selectedValue, projectState, globalState)
addFileToRecentlySearchedFiles(
selectedValue,
projectState,
globalState
)
}
popup.cancel()
}
Expand All @@ -144,27 +156,9 @@ open class Fuzzier : FilesystemAction() {
component.fileList.setPaintBusy(true)
ApplicationManager.getApplication().executeOnPooledThread {
try {
val editorHistoryManager = EditorHistoryManager.getInstance(project)

val listModel = when (globalState.recentFilesMode) {
FuzzierGlobalSettingsService.RecentFilesMode.RECENT_PROJECT_FILES -> InitialViewHandler.getRecentProjectFiles(
globalState,
fuzzierUtil,
editorHistoryManager,
project
)

FuzzierGlobalSettingsService.RecentFilesMode.RECENTLY_SEARCHED_FILES -> InitialViewHandler.Companion.getRecentlySearchedFiles(
projectState
)

else -> {
DefaultListModel<FuzzyContainer>()
}
}

val initialListModel = getInitialViewProvider(project).invoke()
ApplicationManager.getApplication().invokeLater {
component.refreshModel(listModel, getCellRenderer())
component.refreshModel(initialListModel, getCellRenderer())
}
} finally {
component.fileList.setPaintBusy(false)
Expand Down
10 changes: 10 additions & 0 deletions src/main/kotlin/com/mituuz/fuzzier/search/FuzzierOpenTabs.kt
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,22 @@

package com.mituuz.fuzzier.search

import com.intellij.openapi.fileEditor.FileEditorManager
import com.intellij.openapi.project.Project
import com.mituuz.fuzzier.intellij.iteration.IterationFileCollector
import com.mituuz.fuzzier.intellij.iteration.OpenTabsCollector
import com.mituuz.fuzzier.search.initialview.InitialListModelProvider
import com.mituuz.fuzzier.search.initialview.OpenTabsInitialListModelProvider

class FuzzierOpenTabs : Fuzzier() {
override var popupTitle: String = "Fuzzy Search (Open Tabs)"

override fun getInitialViewProvider(project: Project): InitialListModelProvider {
val modules = projectState.modules
val openFiles = FileEditorManager.getInstance(project).openFiles
return OpenTabsInitialListModelProvider(modules, openFiles)
}

override fun createCollector(): IterationFileCollector {
return OpenTabsCollector()
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
/*
* MIT License
*
* Copyright (c) 2025 Mitja Leino
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/

package com.mituuz.fuzzier.search.initialview

import com.intellij.openapi.fileEditor.impl.EditorHistoryManager
import com.intellij.openapi.project.Project
import com.mituuz.fuzzier.entities.FuzzyContainer
import com.mituuz.fuzzier.entities.OrderedContainer
import com.mituuz.fuzzier.settings.FuzzierGlobalSettingsService
import com.mituuz.fuzzier.settings.FuzzierSettingsService
import com.mituuz.fuzzier.util.FuzzierUtil
import javax.swing.DefaultListModel

class DefaultInitialListModelProvider(
val project: Project,
val globalState: FuzzierGlobalSettingsService.State,
val projectState: FuzzierSettingsService.State,
) : InitialListModelProvider {
override fun invoke(): DefaultListModel<FuzzyContainer> {
return when (globalState.recentFilesMode) {
FuzzierGlobalSettingsService.RecentFilesMode.RECENT_PROJECT_FILES -> {
getRecentProjectFiles(project)
}

FuzzierGlobalSettingsService.RecentFilesMode.RECENTLY_SEARCHED_FILES -> {
getRecentlySearchedFiles()
}

else -> {
DefaultListModel()
}
}
}

fun getRecentProjectFiles(
project: Project,
): DefaultListModel<FuzzyContainer> {
val editorHistoryManager = EditorHistoryManager.getInstance(project)
val editorHistory = editorHistoryManager.fileList
val listModel = DefaultListModel<FuzzyContainer>()
val limit = globalState.fileListLimit

// Start from the end of editor history (most recent file)
var i = editorHistory.size - 1
while (i >= 0 && listModel.size() < limit) {
val file = editorHistory[i]
val filePathAndModule = FuzzierUtil.extractModulePath(file.path, projectState.modules)
// Don't add files that do not have a module path in the project
if (filePathAndModule.second == "") {
i--
continue
}
val orderedContainer = OrderedContainer(
filePathAndModule.first, filePathAndModule.second, file.name
)
listModel.addElement(orderedContainer)
i--
}

return listModel
}

fun getRecentlySearchedFiles(): DefaultListModel<FuzzyContainer> {
val result = DefaultListModel<FuzzyContainer>()
projectState.getRecentlySearchedFilesAsFuzzyMatchContainer()
.elements()
.toList()
.filterNotNull()
.reversed()
.let {
result.addAll(it)
}
return result
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* MIT License
*
* Copyright (c) 2025 Mitja Leino
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/

package com.mituuz.fuzzier.search.initialview

import com.mituuz.fuzzier.entities.FuzzyContainer
import javax.swing.DefaultListModel

typealias InitialListModelProvider = () -> DefaultListModel<FuzzyContainer>
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
* MIT License
*
* Copyright (c) 2025 Mitja Leino
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/

package com.mituuz.fuzzier.search.initialview

import com.intellij.openapi.vfs.VirtualFile
import com.mituuz.fuzzier.entities.FuzzyContainer
import com.mituuz.fuzzier.entities.OrderedContainer
import com.mituuz.fuzzier.util.FuzzierUtil
import javax.swing.DefaultListModel

class OpenTabsInitialListModelProvider(
private val modules: Map<String, String>,
private val openFiles: Array<VirtualFile>
) : InitialListModelProvider {
override fun invoke(): DefaultListModel<FuzzyContainer> {
val listModel = DefaultListModel<FuzzyContainer>()

for (vf in openFiles) {
if (!vf.isDirectory) {
val filePathAndModule = FuzzierUtil.extractModulePath(vf.path, modules)
// Don't add files that do not have a module path in the project
if (filePathAndModule.second == "") {
continue
}
val orderedContainer = OrderedContainer(
filePathAndModule.first, filePathAndModule.second, vf.name
)
listModel.add(0, orderedContainer)
}
}

return listModel
}
}
Loading
Loading