From 02b1533ff4002f1015b9c26cf69256d821ddb6b1 Mon Sep 17 00:00:00 2001 From: Kyren223 Date: Thu, 22 Feb 2024 22:34:10 +0200 Subject: Rebranded to "Trident" --- .../harpoonforjb/AppSettingsConfigurable.kt | 50 -------- .../me/kyren223/harpoonforjb/AppSettingsState.kt | 30 ----- .../kyren223/harpoonforjb/HarpoonAppendAction.kt | 15 --- .../me/kyren223/harpoonforjb/HarpoonQuickMenu.kt | 78 ------------ .../harpoonforjb/HarpoonQuickMenuSelectAction.kt | 14 --- .../kyren223/harpoonforjb/HarpoonSelectAction.kt | 44 ------- .../me/kyren223/harpoonforjb/HarpoonState.kt | 131 --------------------- .../harpoonforjb/HarpoonToggleQuickMenuAction.kt | 31 ----- .../me/kyren223/harpoonforjb/SettingsData.kt | 58 --------- .../me/kyren223/trident/AppSettingsConfigurable.kt | 50 ++++++++ .../kotlin/me/kyren223/trident/AppSettingsState.kt | 30 +++++ .../kotlin/me/kyren223/trident/SettingsData.kt | 58 +++++++++ .../me/kyren223/trident/TridentAppendAction.kt | 15 +++ .../kotlin/me/kyren223/trident/TridentQuickMenu.kt | 78 ++++++++++++ .../trident/TridentQuickMenuSelectAction.kt | 11 ++ .../me/kyren223/trident/TridentSelectAction.kt | 43 +++++++ .../kotlin/me/kyren223/trident/TridentState.kt | 123 +++++++++++++++++++ .../trident/TridentToggleQuickMenuAction.kt | 31 +++++ 18 files changed, 439 insertions(+), 451 deletions(-) delete mode 100644 src/main/kotlin/me/kyren223/harpoonforjb/AppSettingsConfigurable.kt delete mode 100644 src/main/kotlin/me/kyren223/harpoonforjb/AppSettingsState.kt delete mode 100644 src/main/kotlin/me/kyren223/harpoonforjb/HarpoonAppendAction.kt delete mode 100644 src/main/kotlin/me/kyren223/harpoonforjb/HarpoonQuickMenu.kt delete mode 100644 src/main/kotlin/me/kyren223/harpoonforjb/HarpoonQuickMenuSelectAction.kt delete mode 100644 src/main/kotlin/me/kyren223/harpoonforjb/HarpoonSelectAction.kt delete mode 100644 src/main/kotlin/me/kyren223/harpoonforjb/HarpoonState.kt delete mode 100644 src/main/kotlin/me/kyren223/harpoonforjb/HarpoonToggleQuickMenuAction.kt delete mode 100644 src/main/kotlin/me/kyren223/harpoonforjb/SettingsData.kt create mode 100644 src/main/kotlin/me/kyren223/trident/AppSettingsConfigurable.kt create mode 100644 src/main/kotlin/me/kyren223/trident/AppSettingsState.kt create mode 100644 src/main/kotlin/me/kyren223/trident/SettingsData.kt create mode 100644 src/main/kotlin/me/kyren223/trident/TridentAppendAction.kt create mode 100644 src/main/kotlin/me/kyren223/trident/TridentQuickMenu.kt create mode 100644 src/main/kotlin/me/kyren223/trident/TridentQuickMenuSelectAction.kt create mode 100644 src/main/kotlin/me/kyren223/trident/TridentSelectAction.kt create mode 100644 src/main/kotlin/me/kyren223/trident/TridentState.kt create mode 100644 src/main/kotlin/me/kyren223/trident/TridentToggleQuickMenuAction.kt (limited to 'src/main/kotlin/me/kyren223') diff --git a/src/main/kotlin/me/kyren223/harpoonforjb/AppSettingsConfigurable.kt b/src/main/kotlin/me/kyren223/harpoonforjb/AppSettingsConfigurable.kt deleted file mode 100644 index 4ece20e..0000000 --- a/src/main/kotlin/me/kyren223/harpoonforjb/AppSettingsConfigurable.kt +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright 2000-2022 JetBrains s.r.o. and other contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. -package me.kyren223.harpoonforjb - -import com.intellij.openapi.options.Configurable -import com.intellij.openapi.util.NlsContexts.ConfigurableName -import javax.swing.JComponent - -class AppSettingsConfigurable : Configurable { - private var settings: SettingsData? = null - override fun getDisplayName(): @ConfigurableName String { - return "HarpoonForJB Settings" - } - - override fun createComponent(): JComponent { - settings = SettingsData() - return settings!!.panel - } - - override fun isModified(): Boolean { - val settings = AppSettingsState.instance - if (settings.harpoonWidth != this.settings!!.getHarpoonWidth()) return true - if (settings.harpoonHeight != this.settings!!.getHarpoonHeight()) return true - if (settings.harpoonFontSize != this.settings!!.getHarpoonFontSize()) return true - if (settings.harpoonEnterToSelect != this.settings!!.getHarpoonEnterToSelect()) return true - return false - } - - override fun apply() { - val settings = AppSettingsState.instance - settings.harpoonWidth = this.settings!!.getHarpoonWidth() - settings.harpoonHeight = this.settings!!.getHarpoonHeight() - settings.harpoonFontSize = this.settings!!.getHarpoonFontSize() - settings.harpoonEnterToSelect = this.settings!!.getHarpoonEnterToSelect() - } - - override fun reset() { - val settings = AppSettingsState.instance - if (this.settings == null) { - this.settings = SettingsData() - } - this.settings!!.setHarpoonWidth(settings.harpoonWidth) - this.settings!!.setHarpoonHeight(settings.harpoonHeight) - this.settings!!.setHarpoonFontSize(settings.harpoonFontSize) - this.settings!!.setHarpoonEnterToSelect(settings.harpoonEnterToSelect) - } - - override fun disposeUIResources() { - settings = null - } -} diff --git a/src/main/kotlin/me/kyren223/harpoonforjb/AppSettingsState.kt b/src/main/kotlin/me/kyren223/harpoonforjb/AppSettingsState.kt deleted file mode 100644 index ea3eabd..0000000 --- a/src/main/kotlin/me/kyren223/harpoonforjb/AppSettingsState.kt +++ /dev/null @@ -1,30 +0,0 @@ -package me.kyren223.harpoonforjb - -import com.intellij.openapi.application.ApplicationManager -import com.intellij.openapi.components.PersistentStateComponent -import com.intellij.openapi.components.State -import com.intellij.openapi.components.Storage -import com.intellij.util.xmlb.XmlSerializerUtil - -// Copyright 2000-2022 JetBrains s.r.o. and other contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. -@State(name = "me.kyren223.harpoonforjb.AppSettingsState", storages = [Storage("SdkSettingsPlugin.xml")]) -class AppSettingsState : PersistentStateComponent { - - var harpoonEnterToSelect = true - var harpoonWidth = 800 - var harpoonHeight = 400 - var harpoonFontSize = 20 - - override fun getState(): AppSettingsState { - return this - } - - override fun loadState(state: AppSettingsState) { - XmlSerializerUtil.copyBean(state, this) - } - - companion object { - val instance: AppSettingsState - get() = ApplicationManager.getApplication().getService(AppSettingsState::class.java) - } -} diff --git a/src/main/kotlin/me/kyren223/harpoonforjb/HarpoonAppendAction.kt b/src/main/kotlin/me/kyren223/harpoonforjb/HarpoonAppendAction.kt deleted file mode 100644 index 724f6c8..0000000 --- a/src/main/kotlin/me/kyren223/harpoonforjb/HarpoonAppendAction.kt +++ /dev/null @@ -1,15 +0,0 @@ -package me.kyren223.harpoonforjb - -import com.intellij.openapi.actionSystem.AnAction -import com.intellij.openapi.actionSystem.AnActionEvent -import com.intellij.openapi.actionSystem.PlatformDataKeys -import com.intellij.openapi.project.Project -import com.intellij.openapi.vfs.VirtualFile - -class HarpoonAppendAction : AnAction() { - override fun actionPerformed(e: AnActionEvent) { - val project: Project = e.project ?: return - val file: VirtualFile = e.getData(PlatformDataKeys.VIRTUAL_FILE) ?: return - HarpoonState.appendFile(project, file) - } -} diff --git a/src/main/kotlin/me/kyren223/harpoonforjb/HarpoonQuickMenu.kt b/src/main/kotlin/me/kyren223/harpoonforjb/HarpoonQuickMenu.kt deleted file mode 100644 index 3417d7c..0000000 --- a/src/main/kotlin/me/kyren223/harpoonforjb/HarpoonQuickMenu.kt +++ /dev/null @@ -1,78 +0,0 @@ -@file:Suppress("SameParameterValue") - -package me.kyren223.harpoonforjb - -import com.intellij.openapi.editor.LogicalPosition -import com.intellij.openapi.ui.DialogWrapper -import com.intellij.ui.EditorTextField -import com.maddyhome.idea.vim.KeyHandler -import com.maddyhome.idea.vim.api.ExecutionContext -import com.maddyhome.idea.vim.api.VimEditor -import com.maddyhome.idea.vim.api.injector -import com.maddyhome.idea.vim.newapi.vim -import java.awt.event.FocusEvent -import java.awt.event.FocusListener -import javax.swing.JComponent - -class HarpoonQuickMenu(private val content: String) : DialogWrapper(true) { - private lateinit var editorTextField: EditorTextField - - init { - val settings = AppSettingsState.instance - this.title = "Harpoon Quick Menu" - setSize(settings.harpoonWidth, settings.harpoonHeight) - super.init() - } - - override fun createCenterPanel(): JComponent { - val settings = AppSettingsState.instance - editorTextField = EditorTextField(this.content) - editorTextField.setOneLineMode(false) - editorTextField.addSettingsProvider { - it.setFontSize(settings.harpoonFontSize) - it.isInsertMode = true - it.caretModel.moveToLogicalPosition(LogicalPosition(0, 0)) - it.settings.isLineNumbersShown = true - } - - editorTextField.addFocusListener(object : FocusListener { - override fun focusGained(e: FocusEvent?) { - val editor = editorTextField.editor!!.vim - val context = injector.executionContextManager.onEditor(editor, null) - simulateKeyPress("", editor, context) - } - - override fun focusLost(e: FocusEvent?) { /* Do nothing */ } - }) - - return editorTextField - } - - private fun simulateKeyPress(key: String, editor: VimEditor, context: ExecutionContext.Editor) { - KeyHandler.getInstance().handleKey(editor, injector.parser.parseKeys(key)[0], context) - } - - override fun getPreferredFocusedComponent(): JComponent { - return this.editorTextField - } - - fun select() { - if (this.editorTextField.editor == null) return - HarpoonState.quickMenuSelectedIndex = this.editorTextField.editor!!.caretModel.logicalPosition.line - doOKAction() - } - - override fun doOKAction() { - HarpoonState.quickMenuContent = editorTextField.text - super.doOKAction() - } - - override fun doCancelAction() { - HarpoonState.quickMenuContent = editorTextField.text - super.doCancelAction() - } - - override fun createSouthPanel(): JComponent? { - return null - } -} diff --git a/src/main/kotlin/me/kyren223/harpoonforjb/HarpoonQuickMenuSelectAction.kt b/src/main/kotlin/me/kyren223/harpoonforjb/HarpoonQuickMenuSelectAction.kt deleted file mode 100644 index 8ba8c6c..0000000 --- a/src/main/kotlin/me/kyren223/harpoonforjb/HarpoonQuickMenuSelectAction.kt +++ /dev/null @@ -1,14 +0,0 @@ -package me.kyren223.harpoonforjb - -import com.intellij.openapi.actionSystem.AnAction -import com.intellij.openapi.actionSystem.AnActionEvent -import com.maddyhome.idea.vim.api.injector -import com.maddyhome.idea.vim.command.MappingMode -import com.maddyhome.idea.vim.key.MappingOwner.Plugin.Companion.get - -class HarpoonQuickMenuSelectAction : AnAction() { - override fun actionPerformed(e: AnActionEvent) { - HarpoonState.quickMenuSelect() - } - -} diff --git a/src/main/kotlin/me/kyren223/harpoonforjb/HarpoonSelectAction.kt b/src/main/kotlin/me/kyren223/harpoonforjb/HarpoonSelectAction.kt deleted file mode 100644 index 3c196b8..0000000 --- a/src/main/kotlin/me/kyren223/harpoonforjb/HarpoonSelectAction.kt +++ /dev/null @@ -1,44 +0,0 @@ -package me.kyren223.harpoonforjb - -import com.intellij.openapi.actionSystem.AnAction -import com.intellij.openapi.actionSystem.AnActionEvent -import com.intellij.openapi.actionSystem.PlatformDataKeys -import com.intellij.openapi.fileEditor.FileEditorManager - -class HarpoonSelectAction : AnAction() { - override fun actionPerformed(e: AnActionEvent) { - val project = e.project ?: return - val actionId = e.actionManager.getId(this) - var index = when (actionId) { - NEXT -> { - val current = HarpoonState.getIndexOfFile(project, e.getData(PlatformDataKeys.VIRTUAL_FILE)) - if (current == -1) return - current + 1 - } - PREV -> { - val current = HarpoonState.getIndexOfFile(project, e.getData(PlatformDataKeys.VIRTUAL_FILE)) - if (current == -1) return - current - 1 - } - else -> { - getIndex(actionId) - } - } - - val count = HarpoonState.getFileCount(project) - index = ((index % count) + count) % count - val file = HarpoonState.selectFile(project, index) ?: return - FileEditorManager.getInstance(project).openFile(file, true) - } - - private fun getIndex(actionId: String): Int { - return actionId.substring(SELECT.length).toInt() - 1 - } - - companion object { - const val NEXT = "HarpoonSelectNext" - const val PREV = "HarpoonSelectPrev" - const val SELECT = "HarpoonSelect" - } -} - diff --git a/src/main/kotlin/me/kyren223/harpoonforjb/HarpoonState.kt b/src/main/kotlin/me/kyren223/harpoonforjb/HarpoonState.kt deleted file mode 100644 index 3b476c2..0000000 --- a/src/main/kotlin/me/kyren223/harpoonforjb/HarpoonState.kt +++ /dev/null @@ -1,131 +0,0 @@ -package me.kyren223.harpoonforjb - -import com.intellij.ide.util.PropertiesComponent -import com.intellij.openapi.fileEditor.FileEditorManager -import com.intellij.openapi.project.Project -import com.intellij.openapi.vfs.LocalFileSystem -import com.intellij.openapi.vfs.VirtualFile - -object HarpoonState { - private var projectFiles: MutableMap> = mutableMapOf() - private const val HARPOON_LIST_KEY = "HarpoonList" - private var quickMenu: HarpoonQuickMenu? = null - var quickMenuSelectedIndex: Int? = null - var quickMenuContent: String? = "" - - - fun appendFile(project: Project, file: VirtualFile) { - if (!file.isValid) return - loadProject(project) - val files = projectFiles[project.name] - files!!.add(file) - saveProject(project) - } - - fun selectFile(project: Project, index: Int): VirtualFile? { - if (index < 0) return null - loadProject(project) - val files = projectFiles[project.name] - if (files!!.size <= index) return null - return files[index] - } - - private fun loadProject(project: Project) { - if (project.name in projectFiles) return - val properties = PropertiesComponent.getInstance(project) - val list = properties.getList(HARPOON_LIST_KEY) - if (list == null) { - projectFiles[project.name] = mutableListOf() - return - } - val fs = LocalFileSystem.getInstance() - val files = list.stream() - .map { fs.findFileByPath(it) } - .toList() - .filterNotNull() - .filter { it.isValid } - .toMutableList() - projectFiles[project.name] = files - } - - private fun saveProject(project: Project) { - if (project.name !in projectFiles) return - val files = projectFiles[project.name] - val properties = PropertiesComponent.getInstance(project) - val stringList = files!!.stream() - .filter { it.isValid } - .map { it.path } - .toList() - properties.setList(HARPOON_LIST_KEY, stringList) - } - - fun getIndexOfFile(project: Project, data: VirtualFile?): Int { - loadProject(project) - val files = projectFiles[project.name] - if (files == null || data == null) return -1 - return files.indexOfFirst { it.path == data.path } - } - - fun getFileCount(project: Project): Int { - loadProject(project) - return projectFiles[project.name]!!.size - } - - fun toggleQuickMenu(project: Project) { - if (quickMenu != null && quickMenu!!.isShowing) { - println("Canceling quick menu") - quickMenu!!.doCancelAction() - return - } - - loadProject(project) - val content = getProjectContent(project) - quickMenu = HarpoonQuickMenu(content) - val result = quickMenu!!.showAndGet() - - if (quickMenuContent != null && content != quickMenuContent) { - // Update the content -// println("Content Before:\n${quickMenuContent}") - retrieveProjectFiles(project, quickMenuContent!!) -// val contentAfter = projectFiles[project.name]!! -// .joinToString("\n") { it.path } -// .trim() -// println("Content After:\n${contentAfter}") - saveProject(project) - } - - if (!result) return - val index = quickMenuSelectedIndex ?: return - quickMenuSelectedIndex = null - val file = selectFile(project, index) ?: return - FileEditorManager.getInstance(project).openFile(file, true) - } - - fun quickMenuSelect() { - if (quickMenu == null || !quickMenu!!.isShowing) return - quickMenu!!.select() - } - - private fun getProjectContent(project: Project): String { - val content = projectFiles[project.name]!! - .joinToString("\n") { it.path } - .replace(project.basePath!!, "...") - .trim() - return content - } - - private fun retrieveProjectFiles(project: Project, content: String) { - loadProject(project) - val files = content - .split("\n") - .asSequence() - .map { it.trim() } - .map { it.replace("...", project.basePath!!) } - .filter { it.isNotBlank() } - .map { LocalFileSystem.getInstance().findFileByPath(it) } - .filterNotNull() - .filter { it.isValid } - .toMutableList() - projectFiles[project.name] = files - } -} \ No newline at end of file diff --git a/src/main/kotlin/me/kyren223/harpoonforjb/HarpoonToggleQuickMenuAction.kt b/src/main/kotlin/me/kyren223/harpoonforjb/HarpoonToggleQuickMenuAction.kt deleted file mode 100644 index 66e58b0..0000000 --- a/src/main/kotlin/me/kyren223/harpoonforjb/HarpoonToggleQuickMenuAction.kt +++ /dev/null @@ -1,31 +0,0 @@ -package me.kyren223.harpoonforjb - -import com.intellij.openapi.actionSystem.AnAction -import com.intellij.openapi.actionSystem.AnActionEvent -import com.maddyhome.idea.vim.api.injector -import com.maddyhome.idea.vim.command.MappingMode -import com.maddyhome.idea.vim.key.MappingOwner - -class HarpoonToggleQuickMenuAction : AnAction() { - override fun actionPerformed(e: AnActionEvent) { - if (!remapped) remap() - if (e.project != null) { - HarpoonState.toggleQuickMenu(e.project!!) - } - } - - private fun remap() { - if (!AppSettingsState.instance.harpoonEnterToSelect) return - val keys = injector.parser.parseKeys(":action HarpoonQuickMenuSelect") - val keyGroup = injector.keyGroup - keyGroup.putKeyMapping(MappingMode.NVO, - injector.parser.parseKeys(""), - MappingOwner.Plugin.get("HarpoonForJB"), keys, false - ) - remapped = true - } - - companion object { - var remapped = false - } -} diff --git a/src/main/kotlin/me/kyren223/harpoonforjb/SettingsData.kt b/src/main/kotlin/me/kyren223/harpoonforjb/SettingsData.kt deleted file mode 100644 index 3e0c60f..0000000 --- a/src/main/kotlin/me/kyren223/harpoonforjb/SettingsData.kt +++ /dev/null @@ -1,58 +0,0 @@ -package me.kyren223.harpoonforjb - -import com.intellij.ui.JBIntSpinner -import com.intellij.ui.components.JBCheckBox -import com.intellij.ui.components.JBLabel -import com.intellij.util.ui.FormBuilder -import javax.swing.JPanel - -class SettingsData { - - val panel: JPanel - private val harpoonWidth: JBIntSpinner = JBIntSpinner(800, 1, 5000, 10) - private val harpoonHeight: JBIntSpinner = JBIntSpinner(400, 1, 5000, 10) - private val harpoonFontSize: JBIntSpinner = JBIntSpinner(20, 1, 100) - private val harpoonEnter: JBCheckBox = JBCheckBox() - - init { - panel = FormBuilder.createFormBuilder() - .addLabeledComponent(JBLabel("Harpoon width"), harpoonWidth, 1, false) - .addLabeledComponent(JBLabel("Harpoon height"), harpoonHeight, 1, false) - .addLabeledComponent(JBLabel("Harpoon font size"), harpoonFontSize, 1, false) - .addLabeledComponent(JBLabel("Press enter to select item in the QuickMenu"), harpoonEnter, 1, false) - .addComponentFillVertically(JPanel(), 0) - .panel - } - - fun getHarpoonWidth(): Int { - return harpoonWidth.number - } - - fun getHarpoonHeight(): Int { - return harpoonHeight.number - } - - fun getHarpoonFontSize(): Int { - return harpoonFontSize.number - } - - fun getHarpoonEnterToSelect(): Boolean { - return harpoonEnter.isSelected - } - - fun setHarpoonWidth(width: Int) { - harpoonWidth.number = width - } - - fun setHarpoonHeight(height: Int) { - harpoonHeight.number = height - } - - fun setHarpoonFontSize(fontSize: Int) { - harpoonFontSize.number = fontSize - } - - fun setHarpoonEnterToSelect(enter: Boolean) { - harpoonEnter.isSelected = enter - } -} diff --git a/src/main/kotlin/me/kyren223/trident/AppSettingsConfigurable.kt b/src/main/kotlin/me/kyren223/trident/AppSettingsConfigurable.kt new file mode 100644 index 0000000..e04b3b8 --- /dev/null +++ b/src/main/kotlin/me/kyren223/trident/AppSettingsConfigurable.kt @@ -0,0 +1,50 @@ +// Copyright 2000-2022 JetBrains s.r.o. and other contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package me.kyren223.trident + +import com.intellij.openapi.options.Configurable +import com.intellij.openapi.util.NlsContexts.ConfigurableName +import javax.swing.JComponent + +class AppSettingsConfigurable : Configurable { + private var settings: SettingsData? = null + override fun getDisplayName(): @ConfigurableName String { + return "Trident Settings" + } + + override fun createComponent(): JComponent { + settings = SettingsData() + return settings!!.panel + } + + override fun isModified(): Boolean { + val settings = AppSettingsState.instance + if (settings.width != this.settings!!.getWidth()) return true + if (settings.height != this.settings!!.getHeight()) return true + if (settings.fontSize != this.settings!!.getFontSize()) return true + if (settings.enterToSelect != this.settings!!.getEnterToSelect()) return true + return false + } + + override fun apply() { + val settings = AppSettingsState.instance + settings.width = this.settings!!.getWidth() + settings.height = this.settings!!.getHeight() + settings.fontSize = this.settings!!.getFontSize() + settings.enterToSelect = this.settings!!.getEnterToSelect() + } + + override fun reset() { + val settings = AppSettingsState.instance + if (this.settings == null) { + this.settings = SettingsData() + } + this.settings!!.setWidth(settings.width) + this.settings!!.setHeight(settings.height) + this.settings!!.setFontSize(settings.fontSize) + this.settings!!.setEnterToSelect(settings.enterToSelect) + } + + override fun disposeUIResources() { + settings = null + } +} diff --git a/src/main/kotlin/me/kyren223/trident/AppSettingsState.kt b/src/main/kotlin/me/kyren223/trident/AppSettingsState.kt new file mode 100644 index 0000000..6d61ea0 --- /dev/null +++ b/src/main/kotlin/me/kyren223/trident/AppSettingsState.kt @@ -0,0 +1,30 @@ +package me.kyren223.trident + +import com.intellij.openapi.application.ApplicationManager +import com.intellij.openapi.components.PersistentStateComponent +import com.intellij.openapi.components.State +import com.intellij.openapi.components.Storage +import com.intellij.util.xmlb.XmlSerializerUtil + +// Copyright 2000-2022 JetBrains s.r.o. and other contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +@State(name = "me.kyren223.trident.AppSettingsState", storages = [Storage("SdkSettingsPlugin.xml")]) +class AppSettingsState : PersistentStateComponent { + + var enterToSelect = true + var width = 800 + var height = 400 + var fontSize = 20 + + override fun getState(): AppSettingsState { + return this + } + + override fun loadState(state: AppSettingsState) { + XmlSerializerUtil.copyBean(state, this) + } + + companion object { + val instance: AppSettingsState + get() = ApplicationManager.getApplication().getService(AppSettingsState::class.java) + } +} diff --git a/src/main/kotlin/me/kyren223/trident/SettingsData.kt b/src/main/kotlin/me/kyren223/trident/SettingsData.kt new file mode 100644 index 0000000..89ca91a --- /dev/null +++ b/src/main/kotlin/me/kyren223/trident/SettingsData.kt @@ -0,0 +1,58 @@ +package me.kyren223.trident + +import com.intellij.ui.JBIntSpinner +import com.intellij.ui.components.JBCheckBox +import com.intellij.ui.components.JBLabel +import com.intellij.util.ui.FormBuilder +import javax.swing.JPanel + +class SettingsData { + + val panel: JPanel + private val width: JBIntSpinner = JBIntSpinner(800, 1, 5000, 10) + private val height: JBIntSpinner = JBIntSpinner(400, 1, 5000, 10) + private val fontSize: JBIntSpinner = JBIntSpinner(20, 1, 100) + private val enterToSelect: JBCheckBox = JBCheckBox() + + init { + panel = FormBuilder.createFormBuilder() + .addLabeledComponent(JBLabel("QuickMenu width"), width, 1, false) + .addLabeledComponent(JBLabel("QuickMenu height"), height, 1, false) + .addLabeledComponent(JBLabel("QuickMenu font size"), fontSize, 1, false) + .addLabeledComponent(JBLabel("Enter to select item in the QuickMenu"), enterToSelect, 1, false) + .addComponentFillVertically(JPanel(), 0) + .panel + } + + fun getWidth(): Int { + return width.number + } + + fun getHeight(): Int { + return height.number + } + + fun getFontSize(): Int { + return fontSize.number + } + + fun getEnterToSelect(): Boolean { + return enterToSelect.isSelected + } + + fun setWidth(width: Int) { + this.width.number = width + } + + fun setHeight(height: Int) { + this.height.number = height + } + + fun setFontSize(fontSize: Int) { + this.fontSize.number = fontSize + } + + fun setEnterToSelect(enter: Boolean) { + this.enterToSelect.isSelected = enter + } +} diff --git a/src/main/kotlin/me/kyren223/trident/TridentAppendAction.kt b/src/main/kotlin/me/kyren223/trident/TridentAppendAction.kt new file mode 100644 index 0000000..621b9cd --- /dev/null +++ b/src/main/kotlin/me/kyren223/trident/TridentAppendAction.kt @@ -0,0 +1,15 @@ +package me.kyren223.trident + +import com.intellij.openapi.actionSystem.AnAction +import com.intellij.openapi.actionSystem.AnActionEvent +import com.intellij.openapi.actionSystem.PlatformDataKeys +import com.intellij.openapi.project.Project +import com.intellij.openapi.vfs.VirtualFile + +class TridentAppendAction : AnAction() { + override fun actionPerformed(e: AnActionEvent) { + val project: Project = e.project ?: return + val file: VirtualFile = e.getData(PlatformDataKeys.VIRTUAL_FILE) ?: return + TridentState.appendFile(project, file) + } +} diff --git a/src/main/kotlin/me/kyren223/trident/TridentQuickMenu.kt b/src/main/kotlin/me/kyren223/trident/TridentQuickMenu.kt new file mode 100644 index 0000000..e7903e0 --- /dev/null +++ b/src/main/kotlin/me/kyren223/trident/TridentQuickMenu.kt @@ -0,0 +1,78 @@ +@file:Suppress("SameParameterValue") + +package me.kyren223.trident + +import com.intellij.openapi.editor.LogicalPosition +import com.intellij.openapi.ui.DialogWrapper +import com.intellij.ui.EditorTextField +import com.maddyhome.idea.vim.KeyHandler +import com.maddyhome.idea.vim.api.ExecutionContext +import com.maddyhome.idea.vim.api.VimEditor +import com.maddyhome.idea.vim.api.injector +import com.maddyhome.idea.vim.newapi.vim +import java.awt.event.FocusEvent +import java.awt.event.FocusListener +import javax.swing.JComponent + +class TridentQuickMenu(private val content: String) : DialogWrapper(true) { + private lateinit var editorTextField: EditorTextField + + init { + val settings = AppSettingsState.instance + this.title = "Trident Quick Menu" + setSize(settings.width, settings.height) + super.init() + } + + override fun createCenterPanel(): JComponent { + val settings = AppSettingsState.instance + editorTextField = EditorTextField(this.content) + editorTextField.setOneLineMode(false) + editorTextField.addSettingsProvider { + it.setFontSize(settings.fontSize) + it.isInsertMode = true + it.caretModel.moveToLogicalPosition(LogicalPosition(0, 0)) + it.settings.isLineNumbersShown = true + } + + editorTextField.addFocusListener(object : FocusListener { + override fun focusGained(e: FocusEvent?) { + val editor = editorTextField.editor!!.vim + val context = injector.executionContextManager.onEditor(editor, null) + simulateKeyPress("", editor, context) + } + + override fun focusLost(e: FocusEvent?) { /* Do nothing */ } + }) + + return editorTextField + } + + private fun simulateKeyPress(key: String, editor: VimEditor, context: ExecutionContext.Editor) { + KeyHandler.getInstance().handleKey(editor, injector.parser.parseKeys(key)[0], context) + } + + override fun getPreferredFocusedComponent(): JComponent { + return this.editorTextField + } + + fun select() { + if (this.editorTextField.editor == null) return + TridentState.quickMenuSelectedIndex = this.editorTextField.editor!!.caretModel.logicalPosition.line + doOKAction() + } + + override fun doOKAction() { + TridentState.quickMenuContent = editorTextField.text + super.doOKAction() + } + + override fun doCancelAction() { + TridentState.quickMenuContent = editorTextField.text + super.doCancelAction() + } + + override fun createSouthPanel(): JComponent? { + return null + } +} diff --git a/src/main/kotlin/me/kyren223/trident/TridentQuickMenuSelectAction.kt b/src/main/kotlin/me/kyren223/trident/TridentQuickMenuSelectAction.kt new file mode 100644 index 0000000..f9db35a --- /dev/null +++ b/src/main/kotlin/me/kyren223/trident/TridentQuickMenuSelectAction.kt @@ -0,0 +1,11 @@ +package me.kyren223.trident + +import com.intellij.openapi.actionSystem.AnAction +import com.intellij.openapi.actionSystem.AnActionEvent + +class TridentQuickMenuSelectAction : AnAction() { + override fun actionPerformed(e: AnActionEvent) { + TridentState.quickMenuSelect() + } + +} diff --git a/src/main/kotlin/me/kyren223/trident/TridentSelectAction.kt b/src/main/kotlin/me/kyren223/trident/TridentSelectAction.kt new file mode 100644 index 0000000..3122650 --- /dev/null +++ b/src/main/kotlin/me/kyren223/trident/TridentSelectAction.kt @@ -0,0 +1,43 @@ +package me.kyren223.trident + +import com.intellij.openapi.actionSystem.AnAction +import com.intellij.openapi.actionSystem.AnActionEvent +import com.intellij.openapi.actionSystem.PlatformDataKeys +import com.intellij.openapi.fileEditor.FileEditorManager + +class TridentSelectAction : AnAction() { + override fun actionPerformed(e: AnActionEvent) { + val project = e.project ?: return + var index = when (val actionId = e.actionManager.getId(this)) { + NEXT -> { + val current = TridentState.getIndexOfFile(project, e.getData(PlatformDataKeys.VIRTUAL_FILE)) + if (current == -1) return + current + 1 + } + PREV -> { + val current = TridentState.getIndexOfFile(project, e.getData(PlatformDataKeys.VIRTUAL_FILE)) + if (current == -1) return + current - 1 + } + else -> { + getIndex(actionId) + } + } + + val count = TridentState.getFileCount(project) + index = ((index % count) + count) % count + val file = TridentState.selectFile(project, index) ?: return + FileEditorManager.getInstance(project).openFile(file, true) + } + + private fun getIndex(actionId: String): Int { + return actionId.substring(SELECT.length).toInt() - 1 + } + + companion object { + const val NEXT = "TridentSelectNext" + const val PREV = "TridentSelectPrev" + const val SELECT = "TridentSelect" + } +} + diff --git a/src/main/kotlin/me/kyren223/trident/TridentState.kt b/src/main/kotlin/me/kyren223/trident/TridentState.kt new file mode 100644 index 0000000..7c60d4b --- /dev/null +++ b/src/main/kotlin/me/kyren223/trident/TridentState.kt @@ -0,0 +1,123 @@ +package me.kyren223.trident + +import com.intellij.ide.util.PropertiesComponent +import com.intellij.openapi.fileEditor.FileEditorManager +import com.intellij.openapi.project.Project +import com.intellij.openapi.vfs.LocalFileSystem +import com.intellij.openapi.vfs.VirtualFile + +object TridentState { + private var projectFiles: MutableMap> = mutableMapOf() + private const val TRIDENT_LIST_KEY = "TridentList" + private var quickMenu: TridentQuickMenu? = null + var quickMenuSelectedIndex: Int? = null + var quickMenuContent: String? = "" + + fun appendFile(project: Project, file: VirtualFile) { + if (!file.isValid) return + loadProject(project) + val files = projectFiles[project.name] + files!!.add(file) + saveProject(project) + } + + fun selectFile(project: Project, index: Int): VirtualFile? { + if (index < 0) return null + loadProject(project) + val files = projectFiles[project.name] + if (files!!.size <= index) return null + return files[index] + } + + private fun loadProject(project: Project) { + if (project.name in projectFiles) return + val properties = PropertiesComponent.getInstance(project) + val list = properties.getList(TRIDENT_LIST_KEY) + if (list == null) { + projectFiles[project.name] = mutableListOf() + return + } + val fs = LocalFileSystem.getInstance() + val files = list.stream() + .map { fs.findFileByPath(it) } + .toList() + .filterNotNull() + .filter { it.isValid } + .toMutableList() + projectFiles[project.name] = files + } + + private fun saveProject(project: Project) { + if (project.name !in projectFiles) return + val files = projectFiles[project.name] + val properties = PropertiesComponent.getInstance(project) + val stringList = files!!.stream() + .filter { it.isValid } + .map { it.path } + .toList() + properties.setList(TRIDENT_LIST_KEY, stringList) + } + + fun getIndexOfFile(project: Project, data: VirtualFile?): Int { + loadProject(project) + val files = projectFiles[project.name] + if (files == null || data == null) return -1 + return files.indexOfFirst { it.path == data.path } + } + + fun getFileCount(project: Project): Int { + loadProject(project) + return projectFiles[project.name]!!.size + } + + fun toggleQuickMenu(project: Project) { + if (quickMenu != null && quickMenu!!.isShowing) { + quickMenu!!.doCancelAction() + return + } + + loadProject(project) + val content = getProjectContent(project) + quickMenu = TridentQuickMenu(content) + val result = quickMenu!!.showAndGet() + + if (quickMenuContent != null && content != quickMenuContent) { + retrieveProjectFiles(project, quickMenuContent!!) + saveProject(project) + } + + if (!result) return + val index = quickMenuSelectedIndex ?: return + quickMenuSelectedIndex = null + val file = selectFile(project, index) ?: return + FileEditorManager.getInstance(project).openFile(file, true) + } + + fun quickMenuSelect() { + if (quickMenu == null || !quickMenu!!.isShowing) return + quickMenu!!.select() + } + + private fun getProjectContent(project: Project): String { + val content = projectFiles[project.name]!! + .joinToString("\n") { it.path } + .replace(project.basePath!!, "...") + .trim() + return content + } + + private fun retrieveProjectFiles(project: Project, content: String) { + loadProject(project) + val files = content + .split("\n") + .asSequence() + .map { it.trim() } + .map { it.replace("...", project.basePath!!) } + .filter { it.isNotBlank() } + .map { LocalFileSystem.getInstance().findFileByPath(it) } + .filterNotNull() + .filter { it.isValid } + .toMutableList() + projectFiles[project.name] = files + } +} \ No newline at end of file diff --git a/src/main/kotlin/me/kyren223/trident/TridentToggleQuickMenuAction.kt b/src/main/kotlin/me/kyren223/trident/TridentToggleQuickMenuAction.kt new file mode 100644 index 0000000..a3f8cc7 --- /dev/null +++ b/src/main/kotlin/me/kyren223/trident/TridentToggleQuickMenuAction.kt @@ -0,0 +1,31 @@ +package me.kyren223.trident + +import com.intellij.openapi.actionSystem.AnAction +import com.intellij.openapi.actionSystem.AnActionEvent +import com.maddyhome.idea.vim.api.injector +import com.maddyhome.idea.vim.command.MappingMode +import com.maddyhome.idea.vim.key.MappingOwner + +class TridentToggleQuickMenuAction : AnAction() { + override fun actionPerformed(e: AnActionEvent) { + if (!remapped) remap() + if (e.project != null) { + TridentState.toggleQuickMenu(e.project!!) + } + } + + private fun remap() { + if (!AppSettingsState.instance.enterToSelect) return + val keys = injector.parser.parseKeys(":action TridentQuickMenuSelect") + val keyGroup = injector.keyGroup + keyGroup.putKeyMapping(MappingMode.NVO, + injector.parser.parseKeys(""), + MappingOwner.Plugin.get("Trident"), keys, false + ) + remapped = true + } + + companion object { + var remapped = false + } +} -- cgit v1.3.1