diff options
| author | Kyren223 <ulmliad223@gmail.com> | 2024-02-22 22:34:10 +0200 |
|---|---|---|
| committer | Kyren223 <ulmliad223@gmail.com> | 2024-02-22 22:34:10 +0200 |
| commit | 02b1533ff4002f1015b9c26cf69256d821ddb6b1 (patch) | |
| tree | a53ba1aed8abd703eb6c47164f1b5a553d3b09c0 /src/main/kotlin/me/kyren223/trident | |
| parent | 883fd7f58b2ef0254cb3c3fa79cc24f6dcdf9efd (diff) | |
Rebranded to "Trident"
Diffstat (limited to 'src/main/kotlin/me/kyren223/trident')
9 files changed, 439 insertions, 0 deletions
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<AppSettingsState?> { + + 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("<ESC>", 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<String, MutableList<VirtualFile>> = 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<cr>") + val keyGroup = injector.keyGroup + keyGroup.putKeyMapping(MappingMode.NVO, + injector.parser.parseKeys("<cr>"), + MappingOwner.Plugin.get("Trident"), keys, false + ) + remapped = true + } + + companion object { + var remapped = false + } +} |
