summaryrefslogtreecommitdiff
path: root/src/main/kotlin/me/kyren223/trident
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/kotlin/me/kyren223/trident')
-rw-r--r--src/main/kotlin/me/kyren223/trident/AppSettingsConfigurable.kt50
-rw-r--r--src/main/kotlin/me/kyren223/trident/AppSettingsState.kt30
-rw-r--r--src/main/kotlin/me/kyren223/trident/SettingsData.kt58
-rw-r--r--src/main/kotlin/me/kyren223/trident/TridentAppendAction.kt15
-rw-r--r--src/main/kotlin/me/kyren223/trident/TridentQuickMenu.kt78
-rw-r--r--src/main/kotlin/me/kyren223/trident/TridentQuickMenuSelectAction.kt11
-rw-r--r--src/main/kotlin/me/kyren223/trident/TridentSelectAction.kt43
-rw-r--r--src/main/kotlin/me/kyren223/trident/TridentState.kt123
-rw-r--r--src/main/kotlin/me/kyren223/trident/TridentToggleQuickMenuAction.kt31
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
+ }
+}