summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKyren223 <ulmliad223@gmail.com>2024-05-09 18:09:24 +0300
committerKyren223 <ulmliad223@gmail.com>2024-05-09 18:09:24 +0300
commit9b9c0f0594209b8c4ecdb7901293734ccf567437 (patch)
tree0843cb07aa00ce80418f01a1ad083f72e45d7d93
parent1e30fa7ded9939fa45a45f82f84c1e8cd95d68aa (diff)
Finished implementing all the settings, mapping menu, trident list menu, and fixed all the bugs/issues.
Added more index actions for a total of 10 actions (compared to the original 4). Updated README.md and TODO.md. Changed version to 2.0.0. Versions now follow the semver standard. which means that for each major version there will be backwards incompatible changes. for minor versions there will be new features and bug fixes. and for patch versions there will be bug fixes only.
-rw-r--r--README.md105
-rw-r--r--TODO.md5
-rw-r--r--build.gradle.kts4
-rw-r--r--src/main/kotlin/me/kyren223/trident/actions/TridentAppendAction.kt (renamed from src/main/kotlin/me/kyren223/trident/actions/AppendAction.kt)2
-rw-r--r--src/main/kotlin/me/kyren223/trident/actions/TridentListAction.kt20
-rw-r--r--src/main/kotlin/me/kyren223/trident/actions/TridentListSelectAction.kt5
-rw-r--r--src/main/kotlin/me/kyren223/trident/actions/TridentSelectAction.kt (renamed from src/main/kotlin/me/kyren223/trident/actions/SelectAction.kt)4
-rw-r--r--src/main/kotlin/me/kyren223/trident/data/Settings.kt (renamed from src/main/kotlin/me/kyren223/trident/data/SettingsState.kt)30
-rw-r--r--src/main/kotlin/me/kyren223/trident/data/SettingsData.kt27
-rw-r--r--src/main/kotlin/me/kyren223/trident/data/TridentState.kt181
-rw-r--r--src/main/kotlin/me/kyren223/trident/ui/SettingsConfigurable.kt11
-rw-r--r--src/main/kotlin/me/kyren223/trident/ui/TridentListMenu.kt36
-rw-r--r--src/main/kotlin/me/kyren223/trident/ui/TridentMappingsMenu.kt12
-rw-r--r--src/main/kotlin/me/kyren223/trident/utils/TridentUtils.kt88
-rw-r--r--src/main/kotlin/me/kyren223/trident/utils/Utils.kt12
-rw-r--r--src/main/resources/META-INF/plugin.xml52
16 files changed, 265 insertions, 329 deletions
diff --git a/README.md b/README.md
index 15886bc..391f180 100644
--- a/README.md
+++ b/README.md
@@ -3,14 +3,14 @@
# Trident
##### Effortless file traversal to minimize keystrokes and maximize productivity
-[![GitHub release](https://img.shields.io/github/v/release/Kyren223/Trident?style=for-the-badge)](https://github.com/Kyren223/Trident/releases/tag/1.0)
+[![GitHub release](https://img.shields.io/github/v/release/Kyren223/Trident?style=for-the-badge)](https://github.com/Kyren223/Trident/releases/tag/2.0.0)
</div>
## Table of Contents
* [Features](#features)
* [Installation](#installation)
* [Getting Started](#getting-started)
-* [Settings](#settings)
+* [Configuration](#configuration)
* [Contribution](#contribution)
* [License](#license)
* [Contact](#contact)
@@ -34,24 +34,29 @@ The plugin is inspired by the [Harpoon](https://github.com/ThePrimeagen/harpoon)
## Installation
* Version 2023.1 or later of any IntelliJ-based IDE is required.
+* Install the plugin through the IDE's plugin manager by searching for "Trident".
* Install the plugin from the [JetBrains Marketplace](https://plugins.jetbrains.com/plugin/23818-trident).
+* Install the plugin from the [GitHub Releases](https://github.com/Kyren223/Trident/releases).
## Getting Started
-* All actions can be mapped to IDE keymaps like usual, the examples below are for IdeaVim only.
-* Make sure to download IdeaVim if you want to configure the keymaps via .ideavimrc
+* The default settings are sensible, but you can customize them if you wish.
+
+* Actions can be mapped to IDE keymaps, search for "Trident" in the IDE's keymap settings.
+* If you are using IdeaVim, you can configure the keymaps through .ideavimrc
### Example .ideavimrc Configuration
```vimrc
" Append the current file to the list
-map <leader>a :action TridentAppend<CR>
+map <leader>a :action TridentAppend<cr>
-" Open the quick menu
-map <C-h> :action TridentToggleQuickMenu<CR>
+" Open the Trident list
+map <C-h> :action TridentList<cr>
-" Select the given file (from the Quick Menu) and open it
-map <leader>o :action TridentQuickMenuSelect<CR>
+" Select the given file (from the Trident list) and open it
+map <leader>o :action TridentListSelect<cr>
-" Hotkeys to open the first 4 items in the list
+" You can assign up to 10 hotkeys using TridentSelect[1-10]
+" This is an example for the first 4 items in the list
map <C-h> :action TridentSelect1<CR>
map <C-t> :action TridentSelect2<CR>
map <C-n> :action TridentSelect3<CR>
@@ -62,49 +67,89 @@ map <C-S-P> :action TridentSelectPrev<CR>
map <C-S-N> :action TridentSelectNext<CR>
```
-### My .ideavimrc Configuration
+## Configuration
+
+### Settings
+* Search for "Trident Settings" in the IDE's settings
+* You can customize the width, height, font size of the Trident list
+* You can also customize other settings, each setting has an explanation under it
+
+* All actions can be mapped to IDE keymaps
+* Keymaps can also be configured through .ideavimrc (requires IdeaVim)
+
+### Full .ideavimrc Configuration with all keymaps
+* The comments explain the keymaps and their functionality
```vimrc
-map <leader>a :action TridentAppend<CR>
-map <C-e> :action TridentToggleQuickMenu<CR>
-" I am Using "Enter" from settings so no need to map it here
+" Append the current file to the list
+map <leader>a :action TridentAppend<cr>
+
+" Open the Trident list
+map <C-h> :action TridentList<cr>
+
+" Select the given file (from the Trident list) and open it
+map <leader>o :action TridentListSelect<cr>
+" You can assign up to 10 hotkeys using TridentSelect[1-10]
+" These hotkeys are used to quickly navigate to the corresponding Trident list item
map <C-1> :action TridentSelect1<CR>
map <C-2> :action TridentSelect2<CR>
map <C-3> :action TridentSelect3<CR>
map <C-4> :action TridentSelect4<CR>
-```
-
-### Settings
+map <C-5> :action TridentSelect5<CR>
+map <C-6> :action TridentSelect6<CR>
+map <C-7> :action TridentSelect7<CR>
+map <C-8> :action TridentSelect8<CR>
+map <C-9> :action TridentSelect9<CR>
+map <C-0> :action TridentSelect10<CR>
-**Descriptions**
-* Width - Describes how wide the Quick Menu should be.
-* Height - Describes how tall the Quick Menu
-* Font Size - Describes the font size of the Quick Menu
-* Enter to select - When checked the Quick Menu will open the file when you press enter, otherwise it will look for your .ideavimrc file for the keybinding.
+" Toggle previous & next buffers stored within the list
+map <C-S-P> :action TridentSelectPrev<CR>
+map <C-S-N> :action TridentSelectNext<CR>
+```
-**Defaults**
+### My settings values
* Width - 800
* Height - 400
-* Font Size - 20
-* Enter to select - true
+* Font Size - 30
+
+* Enter to select item - true
+* Automatic Mappings - true
+* Recursive Mappings - true
+* Remember last line - false
+* Index Cycling - true
+
+### My .ideavimrc Configuration
+```vimrc
+map <leader>a :action TridentAppend<cr>
+map <C-e> :action TridentToggleQuickMenu<cr>
+" I am Using "Enter to select" from settings
+" so I don't need to map a TridentListSelect keymap here
+
+map <C-1> :action TridentSelect1<cr>
+map <C-2> :action TridentSelect2<cr>
+map <C-3> :action TridentSelect3<cr>
+map <C-4> :action TridentSelect4<cr>
+```
## Contribution
This plugin is open-source and contributions are welcome.
-I recommend looking at the issues tab or the [TODO.md](TODO.md) file for ideas on what to work on.
+If you are looking for what to work on, see the [issues tab](https://github.com/Kyren223/Trident/issues)
+
+It's recommended to first open an issue before starting to work on a feature.
### Steps to contribute
1. Fork the repository.
-2. Make your changes.
+2. Make your changes and commit them.
3. Push your changes to your fork.
4. Create a pull request.
-5. Wait for the pull request to be reviewed.
+5. Wait for the pull request to be reviewed and merged.
## License
-This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
+This project is licensed under the MIT License, see the [LICENSE](LICENSE) file for details.
-The logo was design by me and is copyrighted.
+The logo was designed by me and is copyrighted.
You may not use it without my permission.
## Contact
diff --git a/TODO.md b/TODO.md
deleted file mode 100644
index bbb6f1f..0000000
--- a/TODO.md
+++ /dev/null
@@ -1,5 +0,0 @@
-
-* Add a Global Quick Menu (and maybe actions too?) for global files like .ideavimrc
-* Add a menu to configure path replacements, ex: `$src -> src/main/kotlin/me/kyren223/trident` will replace `$src` with `src/main/kotlin/me/kyren223/trident` in the quick menu similar to how `...` already works
-* Add an option (or an action) to create a shortcut automatically when adding a file, so "path/to/file.java" -> "$file"
-* Keep track on the current line of the quick menu, make it persist (while the IDE runs but not after restart) and have an option to jump to the saved line next time the quick menu is opened \ No newline at end of file
diff --git a/build.gradle.kts b/build.gradle.kts
index 82c2db0..0c8c48e 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -5,7 +5,7 @@ plugins {
}
group = "me.kyren223"
-version = "1.2.0"
+version = "2.0.0"
repositories {
mavenCentral()
@@ -17,7 +17,7 @@ intellij {
version.set("2024.1")
type.set("IC") // Target IDE Platform
updateSinceUntilBuild.set(false)
- plugins.set(listOf("IdeaVim:2.7.5"))
+ plugins.set(listOf("IdeaVim:2.11.0"))
}
tasks {
diff --git a/src/main/kotlin/me/kyren223/trident/actions/AppendAction.kt b/src/main/kotlin/me/kyren223/trident/actions/TridentAppendAction.kt
index 1b9a2b4..1b0d33a 100644
--- a/src/main/kotlin/me/kyren223/trident/actions/AppendAction.kt
+++ b/src/main/kotlin/me/kyren223/trident/actions/TridentAppendAction.kt
@@ -7,7 +7,7 @@ import com.intellij.openapi.project.Project
import com.intellij.openapi.vfs.VirtualFile
import me.kyren223.trident.utils.TridentList
-class AppendAction : AnAction() {
+class TridentAppendAction : AnAction() {
override fun actionPerformed(e: AnActionEvent) {
val project: Project = e.project ?: return
val file: VirtualFile = e.getData(PlatformDataKeys.VIRTUAL_FILE) ?: return
diff --git a/src/main/kotlin/me/kyren223/trident/actions/TridentListAction.kt b/src/main/kotlin/me/kyren223/trident/actions/TridentListAction.kt
index cef0bf2..0d733f3 100644
--- a/src/main/kotlin/me/kyren223/trident/actions/TridentListAction.kt
+++ b/src/main/kotlin/me/kyren223/trident/actions/TridentListAction.kt
@@ -2,32 +2,12 @@ package me.kyren223.trident.actions
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
-import me.kyren223.trident.data.SettingsState
import me.kyren223.trident.ui.TridentListMenu
class TridentListAction : AnAction() {
override fun actionPerformed(e: AnActionEvent) {
- if (!remapped) remap()
val project = e.project ?: return
TridentListMenu.open(project)
}
- // TODO move the remap to somewhere else
- private fun remap() {
- if (!SettingsState.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
- }
}
diff --git a/src/main/kotlin/me/kyren223/trident/actions/TridentListSelectAction.kt b/src/main/kotlin/me/kyren223/trident/actions/TridentListSelectAction.kt
index d1dfd2d..1b68a59 100644
--- a/src/main/kotlin/me/kyren223/trident/actions/TridentListSelectAction.kt
+++ b/src/main/kotlin/me/kyren223/trident/actions/TridentListSelectAction.kt
@@ -3,12 +3,9 @@ package me.kyren223.trident.actions
import com.intellij.openapi.actionSystem.AnAction
import com.intellij.openapi.actionSystem.AnActionEvent
import me.kyren223.trident.ui.TridentListMenu
-import me.kyren223.trident.utils.TridentList
class TridentListSelectAction : AnAction() {
override fun actionPerformed(e: AnActionEvent) {
- val project = e.project ?: return
- TridentList.select(project, TridentListMenu.line)
+ TridentListMenu.instance?.select()
}
-
}
diff --git a/src/main/kotlin/me/kyren223/trident/actions/SelectAction.kt b/src/main/kotlin/me/kyren223/trident/actions/TridentSelectAction.kt
index 37617c4..60973f2 100644
--- a/src/main/kotlin/me/kyren223/trident/actions/SelectAction.kt
+++ b/src/main/kotlin/me/kyren223/trident/actions/TridentSelectAction.kt
@@ -6,10 +6,10 @@ import com.intellij.openapi.actionSystem.PlatformDataKeys
import com.intellij.openapi.fileEditor.FileEditorManager
import me.kyren223.trident.utils.TridentList
-class SelectAction : AnAction() {
+class TridentSelectAction : AnAction() {
override fun actionPerformed(e: AnActionEvent) {
val project = e.project ?: return
- var index = when (val actionId = e.actionManager.getId(this)) {
+ val index = when (val actionId = e.actionManager.getId(this)) {
NEXT -> {
val file = e.getData(PlatformDataKeys.VIRTUAL_FILE) ?: return
val current = TridentList.getIndexOfFile(project, file) ?: return
diff --git a/src/main/kotlin/me/kyren223/trident/data/SettingsState.kt b/src/main/kotlin/me/kyren223/trident/data/Settings.kt
index 16ec372..27a7d2a 100644
--- a/src/main/kotlin/me/kyren223/trident/data/SettingsState.kt
+++ b/src/main/kotlin/me/kyren223/trident/data/Settings.kt
@@ -1,15 +1,21 @@
package me.kyren223.trident.data
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
+import com.intellij.openapi.components.*
// 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.
+@Service
@State(name = "me.kyren223.trident.data.SettingsState", storages = [Storage("SdkSettingsPlugin.xml")])
-class SettingsState : PersistentStateComponent<SettingsState?> {
+class Settings : SimplePersistentStateComponent<SettingsState>(SettingsState()) {
+ companion object {
+ val instance: Settings
+ get() = ApplicationManager.getApplication().getService(Settings::class.java)
+ val state: SettingsState
+ get() = instance.state
+ }
+}
+class SettingsState : BaseState() {
var width = 800
var height = 400
var fontSize = 20
@@ -17,17 +23,5 @@ class SettingsState : PersistentStateComponent<SettingsState?> {
var automaticMapping = false
var recursiveMapping = false
var rememberLine = false
-
- override fun getState(): SettingsState {
- return this
- }
-
- override fun loadState(state: SettingsState) {
- XmlSerializerUtil.copyBean(state, this)
- }
-
- companion object {
- val instance: SettingsState
- get() = ApplicationManager.getApplication().getService(SettingsState::class.java)
- }
+ var indexCycling = false
}
diff --git a/src/main/kotlin/me/kyren223/trident/data/SettingsData.kt b/src/main/kotlin/me/kyren223/trident/data/SettingsData.kt
index 2c5c467..eed655e 100644
--- a/src/main/kotlin/me/kyren223/trident/data/SettingsData.kt
+++ b/src/main/kotlin/me/kyren223/trident/data/SettingsData.kt
@@ -16,14 +16,15 @@ class SettingsData {
val panel: JPanel
- private val width = JBIntSpinner(SettingsState.instance.width, minValue, maxValue, step)
- private val height = JBIntSpinner(SettingsState.instance.height, minValue, maxValue, step)
- private val fontSize = JBIntSpinner(SettingsState.instance.fontSize, minValue, maxValue, step)
+ private val width = JBIntSpinner(Settings.state.width, minValue, maxValue, step)
+ private val height = JBIntSpinner(Settings.state.height, minValue, maxValue, step)
+ private val fontSize = JBIntSpinner(Settings.state.fontSize, minValue, maxValue, step)
- private val enterToSelect = JBCheckBox(null, SettingsState.instance.enterToSelect)
- private val rememberLine = JBCheckBox(null, SettingsState.instance.rememberLine)
- private val automaticMapping = JBCheckBox(null, SettingsState.instance.automaticMapping)
- private val recursiveMapping = JBCheckBox(null, SettingsState.instance.recursiveMapping)
+ private val enterToSelect = JBCheckBox(null, Settings.state.enterToSelect)
+ private val rememberLine = JBCheckBox(null, Settings.state.rememberLine)
+ private val automaticMapping = JBCheckBox(null, Settings.state.automaticMapping)
+ private val recursiveMapping = JBCheckBox(null, Settings.state.recursiveMapping)
+ private val indexCycling = JBCheckBox(null, Settings.state.indexCycling)
init {
panel = FormBuilder.createFormBuilder()
@@ -56,6 +57,10 @@ class SettingsData {
"and will be selected when the TridentList is opened."))
.addComponent(desc("Note, this does not persist across restarts, it's run-time only."))
+ .addLabeledComponent("Index cycling", indexCycling)
+ .addComponent(desc("If enabled, indexes will be cyclic, " +
+ "For example if you have 3 files and hotkey to 4, it'll cycle to 1."))
+
.addComponentFillVertically(JPanel(), 0)
.panel
}
@@ -121,4 +126,12 @@ class SettingsData {
fun setRecursiveMapping(recursiveMapping: Boolean) {
this.recursiveMapping.isSelected = recursiveMapping
}
+
+ fun getIndexCycling(): Boolean {
+ return indexCycling.isSelected
+ }
+
+ fun setIndexCycling(indexCycling: Boolean) {
+ this.indexCycling.isSelected = indexCycling
+ }
}
diff --git a/src/main/kotlin/me/kyren223/trident/data/TridentState.kt b/src/main/kotlin/me/kyren223/trident/data/TridentState.kt
deleted file mode 100644
index 54529e9..0000000
--- a/src/main/kotlin/me/kyren223/trident/data/TridentState.kt
+++ /dev/null
@@ -1,181 +0,0 @@
-package me.kyren223.trident.data
-
-//object TridentState {
-// private const val TRIDENT_LIST_KEY = "TridentList"
-// private const val TRIDENT_MAPPINGS_KEY = "TridentMappings"
-//
-// private var list: MutableMap<String, MutableList<VirtualFile>> = mutableMapOf()
-// private var mappings: MutableMap<String, MutableMap<String, String>> = mutableMapOf()
-//
-// private var quickMenu: QuickMenu? = null
-// var quickMenuSelectedIndex: Int? = null
-// var quickMenuContent: String = ""
-// private var pathMappingsMenu: PathMappingsMenu? = null
-// var pathMappingsContent: String = ""
-//
-//// fun appendFile(project: Project, file: VirtualFile) {
-//// if (!file.isValid) return
-//// loadProject(project)
-//// val files = list[project.name]
-//// files!!.add(file)
-//// saveProject(project)
-//// }
-//
-//// fun selectFile(project: Project, index: Int): VirtualFile? {
-//// if (index < 0) return null
-//// loadProject(project)
-//// val files = list[project.name]
-//// if (files!!.size <= index) return null
-//// return files[index]
-//// }
-//
-//// private fun loadProject(project: Project) {
-//// if (project.name in list) return
-//// val properties = PropertiesComponent.getInstance(project)
-////
-//// val pathMappingsList = properties.getList(TRIDENT_MAPPINGS_KEY)
-//// var map = mutableMapOf<String, String>()
-//// if (pathMappingsList == null) {
-//// map["..."] = project.basePath!!
-//// } else {
-//// for (entry in pathMappingsList) {
-//// val split = entry.split("=")
-//// if (split.size != 2) continue
-//// map[split[0]] = split[1]
-//// }
-//// }
-//// mappings[project.name] = map
-////
-//// val list = properties.getList(TRIDENT_LIST_KEY)
-//// if (list == null) {
-//// this.list[project.name] = mutableListOf()
-//// } else {
-//// val fs = LocalFileSystem.getInstance()
-//// val files = list.stream()
-//// .map { fs.findFileByPath(it) }
-//// .toList()
-//// .filterNotNull()
-//// .filter { it.isValid }
-//// .toMutableList()
-//// this.list[project.name] = files
-//// }
-//// }
-//
-//// private fun saveProject(project: Project) {
-//// if (project.name !in list) return
-//// val files = list[project.name]
-//// val properties = PropertiesComponent.getInstance(project)
-////
-//// val stringList = files!!.stream()
-//// .filter { it.isValid }
-//// .map { it.path }
-//// .toList()
-//// properties.setList(TRIDENT_LIST_KEY, stringList)
-////
-//// val pathMappingsString = mappings[project.name]!!.entries
-//// .joinToString("\n") { "${it.key}=${it.value}" }
-//// .split("\n")
-//// properties.setList(TRIDENT_MAPPINGS_KEY, pathMappingsString)
-//// }
-//
-//// fun getIndexOfFile(project: Project, data: VirtualFile?): Int {
-//// loadProject(project)
-//// val files = list[project.name]
-//// if (files == null || data == null) return -1
-//// return files.indexOfFirst { it.path == data.path }
-//// }
-//
-//// fun getFileCount(project: Project): Int {
-//// loadProject(project)
-//// return list[project.name]!!.size
-//// }
-//
-// fun toggleQuickMenu(project: Project) {
-// if (quickMenu != null && quickMenu!!.isShowing) {
-// quickMenu!!.doCancelAction()
-// return
-// }
-//
-//// loadProject(project)
-// val content = TridentList.get(project).joinToString("\n")
-// quickMenu = QuickMenu(content)
-// val result = quickMenu!!.showAndGet()
-//
-// if (content != quickMenuContent) {
-// retrieveProjectFiles(project, quickMenuContent)
-//// saveProject(project)
-// }
-//
-// if (!result) return
-// val index = quickMenuSelectedIndex ?: return
-// quickMenuSelectedIndex = null
-// val file = TridentList.select(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 {
-//// loadProject(project)
-//// val map = mappings[project.name] ?: throw IllegalStateException("Path mappings not found")
-//// println("map: $map")
-//// var content = list[project.name]!!
-//// .joinToString("\n") { it.path }
-//// .trim()
-//// println("content: $content")
-//// for ((key, value) in map) {
-//// println("key: $key | value: $value")
-//// content = content.replace(value, key)
-//// }
-//// println("content: $content")
-//// return content
-//// }
-//
-//// private fun retrieveProjectFiles(project: Project, content: String) {
-//// loadProject(project)
-//// val files = content
-//// .split("\n")
-//// .asSequence()
-//// .map { it.trim() }
-//// .map { line ->
-//// mappings[project.name]!!.entries.fold(line) { acc, (key, value) ->
-//// acc.replace(key, value)
-//// }
-//// }
-////// .map {
-////// pathMappings[project.name]!!.entries.forEach { (key, value) -> it.replace(key, value) }
-////// it
-////// }
-//// .filter { it.isNotBlank() }
-//// .map { LocalFileSystem.getInstance().findFileByPath(it) }
-//// .filterNotNull()
-//// .filter { it.isValid }
-//// .toMutableList()
-//// list[project.name] = files
-//// }
-//
-// fun togglePathMappingsMenu(project: Project) {
-// if (pathMappingsMenu != null && pathMappingsMenu!!.isShowing) {
-// pathMappingsMenu!!.doCancelAction()
-// return
-// }
-//
-//// loadProject(project)
-// val content = mappings[project.name]!!.entries
-// .joinToString("\n") { "${it.key}=${it.value}" }
-// pathMappingsMenu = PathMappingsMenu(content)
-// pathMappingsMenu!!.showAndGet()
-//
-// if (content != pathMappingsContent) {
-// pathMappingsContent.split("\n").forEach {
-// val split = it.split("=")
-// if (split.size != 2) return@forEach
-// mappings[project.name]!![split[0]] = split[1]
-// }
-//// saveProject(project)
-// }
-// }
-//} \ No newline at end of file
diff --git a/src/main/kotlin/me/kyren223/trident/ui/SettingsConfigurable.kt b/src/main/kotlin/me/kyren223/trident/ui/SettingsConfigurable.kt
index 6283a29..79c4fdc 100644
--- a/src/main/kotlin/me/kyren223/trident/ui/SettingsConfigurable.kt
+++ b/src/main/kotlin/me/kyren223/trident/ui/SettingsConfigurable.kt
@@ -4,7 +4,7 @@ package me.kyren223.trident.ui
import com.intellij.openapi.options.Configurable
import com.intellij.openapi.util.NlsContexts.ConfigurableName
import me.kyren223.trident.data.SettingsData
-import me.kyren223.trident.data.SettingsState
+import me.kyren223.trident.data.Settings
import javax.swing.JComponent
class SettingsConfigurable : Configurable {
@@ -21,7 +21,7 @@ class SettingsConfigurable : Configurable {
}
override fun isModified(): Boolean {
- val settings = SettingsState.instance
+ val settings = Settings.state
if (settings.width != this.settings!!.getWidth()) return true
if (settings.height != this.settings!!.getHeight()) return true
if (settings.fontSize != this.settings!!.getFontSize()) return true
@@ -29,11 +29,12 @@ class SettingsConfigurable : Configurable {
if (settings.automaticMapping != this.settings!!.getAutomaticMapping()) return true
if (settings.recursiveMapping != this.settings!!.getRecursiveMapping()) return true
if (settings.rememberLine != this.settings!!.getRememberLine()) return true
+ if (settings.indexCycling != this.settings!!.getIndexCycling()) return true
return false
}
override fun apply() {
- val settings = SettingsState.instance
+ val settings = Settings.state
settings.width = this.settings!!.getWidth()
settings.height = this.settings!!.getHeight()
settings.fontSize = this.settings!!.getFontSize()
@@ -41,10 +42,11 @@ class SettingsConfigurable : Configurable {
settings.automaticMapping = this.settings!!.getAutomaticMapping()
settings.recursiveMapping = this.settings!!.getRecursiveMapping()
settings.rememberLine = this.settings!!.getRememberLine()
+ settings.indexCycling = this.settings!!.getIndexCycling()
}
override fun reset() {
- val settings = SettingsState.instance
+ val settings = Settings.state
if (this.settings == null) {
this.settings = SettingsData()
}
@@ -55,6 +57,7 @@ class SettingsConfigurable : Configurable {
this.settings!!.setAutomaticMapping(settings.automaticMapping)
this.settings!!.setRecursiveMapping(settings.recursiveMapping)
this.settings!!.setRememberLine(settings.rememberLine)
+ this.settings!!.setIndexCycling(settings.indexCycling)
}
override fun disposeUIResources() {
diff --git a/src/main/kotlin/me/kyren223/trident/ui/TridentListMenu.kt b/src/main/kotlin/me/kyren223/trident/ui/TridentListMenu.kt
index 4062837..af04b7c 100644
--- a/src/main/kotlin/me/kyren223/trident/ui/TridentListMenu.kt
+++ b/src/main/kotlin/me/kyren223/trident/ui/TridentListMenu.kt
@@ -1,5 +1,3 @@
-@file:Suppress("SameParameterValue")
-
package me.kyren223.trident.ui
import com.intellij.openapi.editor.EditorSettings
@@ -10,8 +8,9 @@ import com.intellij.openapi.ui.DialogWrapper
import com.intellij.ui.EditorTextField
import com.maddyhome.idea.vim.newapi.vim
import com.maddyhome.idea.vim.state.mode.Mode
-import me.kyren223.trident.data.SettingsState
+import me.kyren223.trident.data.Settings
import me.kyren223.trident.utils.TridentList
+import me.kyren223.trident.utils.injectEnterToSelectMapping
import me.kyren223.trident.utils.setEditorMode
import java.awt.event.FocusEvent
import java.awt.event.FocusListener
@@ -23,7 +22,7 @@ class TridentListMenu(private val content: String) : DialogWrapper(true) {
init {
this.title = "Trident List"
- val settings = SettingsState.instance
+ val settings = Settings.state
setSize(settings.width, settings.height)
super.init()
}
@@ -32,9 +31,9 @@ class TridentListMenu(private val content: String) : DialogWrapper(true) {
editor = EditorTextField(this.content)
editor.setOneLineMode(false)
editor.addSettingsProvider {
- it.setFontSize(SettingsState.instance.fontSize)
+ it.setFontSize(Settings.state.fontSize)
it.isInsertMode = false
- val lineNumber = if (SettingsState.instance.rememberLine) line else 0
+ val lineNumber = if (Settings.state.rememberLine) line else 0
it.caretModel.moveToLogicalPosition(LogicalPosition(lineNumber, 0))
it.settings.isLineNumbersShown = true
it.settings.lineNumerationType = EditorSettings.LineNumerationType.ABSOLUTE
@@ -46,7 +45,8 @@ class TridentListMenu(private val content: String) : DialogWrapper(true) {
setEditorMode(editor, Mode.NORMAL())
}
- override fun focusLost(e: FocusEvent?) { /* Do nothing */ }
+ override fun focusLost(e: FocusEvent?) { /* Do nothing */
+ }
})
return editor
@@ -58,10 +58,7 @@ class TridentListMenu(private val content: String) : DialogWrapper(true) {
}
fun select() {
- val project = editor.project
doOKAction()
- val file = TridentList.select(project, line) ?: return
- FileEditorManager.getInstance(project).openFile(file, true)
}
override fun doOKAction() {
@@ -75,8 +72,9 @@ class TridentListMenu(private val content: String) : DialogWrapper(true) {
}
private fun save() {
- TridentList.set(editor.project, editor.text.split("\n"))
- line = editor.editor!!.caretModel.logicalPosition.line
+ instance = null
+ files = editor.text.split("\n")
+ line = editor.editor?.caretModel?.logicalPosition?.line ?: 0
}
override fun createSouthPanel(): JComponent? {
@@ -84,11 +82,21 @@ class TridentListMenu(private val content: String) : DialogWrapper(true) {
}
companion object {
+ var instance: TridentListMenu? = null
+ var files: List<String>? = null
var line = 0
fun open(project: Project) {
val content = TridentList.get(project).joinToString("\n")
- val menu = TridentListMenu(content)
- menu.show()
+ instance = TridentListMenu(content)
+ injectEnterToSelectMapping()
+ val selected = instance!!.showAndGet()
+
+ files?.let { TridentList.set(project, it) }
+ files = null
+
+ if (!selected) return
+ val file = TridentList.select(project, line) ?: return
+ FileEditorManager.getInstance(project).openFile(file, true)
}
}
}
diff --git a/src/main/kotlin/me/kyren223/trident/ui/TridentMappingsMenu.kt b/src/main/kotlin/me/kyren223/trident/ui/TridentMappingsMenu.kt
index a84b561..4a6d859 100644
--- a/src/main/kotlin/me/kyren223/trident/ui/TridentMappingsMenu.kt
+++ b/src/main/kotlin/me/kyren223/trident/ui/TridentMappingsMenu.kt
@@ -7,7 +7,7 @@ import com.intellij.openapi.ui.DialogWrapper
import com.intellij.ui.EditorTextField
import com.maddyhome.idea.vim.newapi.vim
import com.maddyhome.idea.vim.state.mode.Mode
-import me.kyren223.trident.data.SettingsState
+import me.kyren223.trident.data.Settings
import me.kyren223.trident.utils.TridentMappings
import me.kyren223.trident.utils.setEditorMode
import java.awt.event.FocusEvent
@@ -18,7 +18,7 @@ class TridentMappingsMenu(private val content: String) : DialogWrapper(true) {
private lateinit var editor: EditorTextField
init {
- val settings = SettingsState.instance
+ val settings = Settings.state
this.title = "Trident Mappings"
setSize(settings.width, settings.height)
super.init()
@@ -28,7 +28,7 @@ class TridentMappingsMenu(private val content: String) : DialogWrapper(true) {
editor = EditorTextField(this.content)
editor.setOneLineMode(false)
editor.addSettingsProvider {
- it.setFontSize(SettingsState.instance.fontSize)
+ it.setFontSize(Settings.state.fontSize)
it.isInsertMode = false
it.caretModel.moveToLogicalPosition(LogicalPosition(0, 0))
it.settings.isLineNumbersShown = true
@@ -62,11 +62,10 @@ class TridentMappingsMenu(private val content: String) : DialogWrapper(true) {
}
private fun save() {
- val map = editor.text.split("\n")
+ map = editor.text.split("\n")
.map { entry -> entry.split("=") }
.filter { entry -> entry.size == 2 }
.associate { it[0] to it[1] }
- TridentMappings.set(editor.project, map)
}
override fun createSouthPanel(): JComponent? {
@@ -74,11 +73,14 @@ class TridentMappingsMenu(private val content: String) : DialogWrapper(true) {
}
companion object {
+ var map: Map<String, String>? = null
fun open(project: Project) {
val content = TridentMappings.get(project).entries
.joinToString("\n") { "${it.key}=${it.value}" }
val menu = TridentMappingsMenu(content)
menu.show()
+ map?.let { TridentMappings.set(project, it) }
+ map = null
}
}
}
diff --git a/src/main/kotlin/me/kyren223/trident/utils/TridentUtils.kt b/src/main/kotlin/me/kyren223/trident/utils/TridentUtils.kt
index b7e19ac..b2302d7 100644
--- a/src/main/kotlin/me/kyren223/trident/utils/TridentUtils.kt
+++ b/src/main/kotlin/me/kyren223/trident/utils/TridentUtils.kt
@@ -2,9 +2,10 @@ package me.kyren223.trident.utils
import com.intellij.ide.util.PropertiesComponent
import com.intellij.openapi.project.Project
+import com.intellij.openapi.project.guessProjectDir
import com.intellij.openapi.vfs.LocalFileSystem
import com.intellij.openapi.vfs.VirtualFile
-import me.kyren223.trident.data.SettingsState
+import me.kyren223.trident.data.Settings
object TridentList {
private const val PROPERTIES_KEY = "TridentList"
@@ -16,12 +17,41 @@ object TridentList {
return expandedPath.isNotBlank() && LocalFileSystem.getInstance().findFileByPath(expandedPath) != null
}
+ private fun getShortPath(path: String): String? {
+ // For path `/path/to/file.ext` the result should be `$file`
+ // Unless for dot files, in which case it should be `$ext`
+ // Examples:
+ // - `/path/to/TridentUtils.kt` -> `$TridentUtils`
+ // - `/path/to/someBinary` -> `$someBinary`
+ // - `/path/to/.ideavimrc` -> `$ideavimrc`
+ return path.split("/")
+ .lastOrNull()
+ ?.let {
+ it.split(".")
+ .let { parts ->
+ when (parts.size) {
+ 0 -> it
+ 1, 2 -> parts.firstOrNull()
+ else -> return null
+ }
+ }
+ }
+ ?.let { "\$${it}" }
+ }
+
fun append(project: Project, file: VirtualFile) {
- // TODO add a setting to automatically add an expansion to mappings if it doesn't exist
- // Should be `$<file>` for `<path>/<file>.<extension>`
- // Unless if the file starts with a dot, in which case it should be `$<extension>`
val files = get(project).toMutableList()
- files.add(file.path)
+
+ val automaticMapping = Settings.state.automaticMapping
+ val path = if (automaticMapping) {
+ val shortPath = getShortPath(file.path) ?: file.path
+ if (TridentMappings.exists(project, shortPath)) file.path else {
+ TridentMappings.append(project, shortPath, file.path)
+ shortPath
+ }
+ } else file.path
+
+ files.add(path)
set(project, files)
}
@@ -37,7 +67,9 @@ object TridentList {
}
private fun getFiles(project: Project): List<VirtualFile> {
- return get(project).mapNotNull { LocalFileSystem.getInstance().findFileByPath(it) }
+ return get(project)
+ .map { TridentMappings.expand(project, it) }
+ .mapNotNull { LocalFileSystem.getInstance().findFileByPath(it) }
}
fun getIndexOfFile(project: Project, file: VirtualFile): Int? {
@@ -46,9 +78,9 @@ object TridentList {
}
fun select(project: Project, index: Int): VirtualFile? {
- // TODO make this a setting if it should "cycle" or not
+ val cycle = Settings.state.indexCycling
val count = getFiles(project).size
- val i = ((index % count) + count) % count
+ val i = if (cycle) ((index % count) + count) % count else index
val files = getFiles(project)
return files.getOrNull(i)
}
@@ -58,14 +90,13 @@ object TridentMappings {
private const val PROPERTIES_KEY = "TridentMappings"
private fun isValidEntry(key: String, value: String): Boolean {
- // TODO change requirements, key should be alphanumeric and must only have 1 $ as the first character
// Requirements:
// - Key and value must not be blank
- // - key must only contain alphanumeric characters and $
+ // - key must only contain alphanumeric characters and start with $
// - value must not contain =
return key.isNotBlank() && value.isNotBlank() &&
- key.matches(Regex("^[a-zA-Z0-9\$]+$")) &&
- value.matches(Regex("^[^=]+$"))
+ key.matches(Regex("""^\$[a-zA-Z0-9]+$""")) &&
+ value.matches(Regex("""^[^=]+$"""))
}
fun append(project: Project, key: String, value: String, overwrite: Boolean = false) {
@@ -89,18 +120,37 @@ object TridentMappings {
fun get(project: Project): Map<String, String> {
val properties = PropertiesComponent.getInstance(project)
val list = properties.getList(PROPERTIES_KEY) ?: return emptyMap()
- return list.map { it.split("=") }.associate { it[0] to it[1] }
+ val map = list
+ .map { it.split("=") }
+ .associate { it[0] to it[1] }
+ .toMutableMap()
+ project.guessProjectDir()?.let {
+ map["..."] = it.path
+ map["\$project"] = it.path
+ }
+ return map
}
fun expand(project: Project, path: String): String {
- val recursive = SettingsState.instance.recursiveMapping
+ val recursive = Settings.state.recursiveMapping
val mappings = get(project).toList().sortedByDescending { it.first.length }
- var expanded = path
-
- mappings.forEach { (key, value) ->
- expanded = expanded.replace(key, if (recursive) expand(project, value) else value)
+ var expandedPath = path
+ while (true) {
+ var expanded = false
+ mappings.forEach { (key, value) ->
+ val expansion = expandedPath.replace(key, value)
+ if (expansion != expandedPath) {
+ expandedPath = expansion
+ expanded = true
+ }
+ }
+ if (!recursive || !expanded) break
}
- return expanded
+ return expandedPath
+ }
+
+ fun exists(project: Project, key: String): Boolean {
+ return get(project).containsKey(key)
}
} \ No newline at end of file
diff --git a/src/main/kotlin/me/kyren223/trident/utils/Utils.kt b/src/main/kotlin/me/kyren223/trident/utils/Utils.kt
index 7e6b80c..e688dd8 100644
--- a/src/main/kotlin/me/kyren223/trident/utils/Utils.kt
+++ b/src/main/kotlin/me/kyren223/trident/utils/Utils.kt
@@ -2,7 +2,9 @@ package me.kyren223.trident.utils
import com.maddyhome.idea.vim.api.VimEditor
import com.maddyhome.idea.vim.api.injector
+import com.maddyhome.idea.vim.command.MappingMode
import com.maddyhome.idea.vim.command.OperatorArguments
+import com.maddyhome.idea.vim.key.MappingOwner
import com.maddyhome.idea.vim.state.mode.Mode
fun setEditorMode(editor: VimEditor, mode: Mode) {
@@ -12,5 +14,13 @@ fun setEditorMode(editor: VimEditor, mode: Mode) {
editor.vimChangeActionSwitchMode = Mode.NORMAL()
}
-
+fun injectEnterToSelectMapping() {
+ injector.keyGroup.putKeyMapping(
+ MappingMode.NV,
+ injector.parser.parseKeys("<cr>"),
+ MappingOwner.Plugin.get("Trident"),
+ injector.parser.parseKeys(":action TridentListSelect<cr>"),
+ false
+ )
+}
diff --git a/src/main/resources/META-INF/plugin.xml b/src/main/resources/META-INF/plugin.xml
index 4a171ee..1d3455f 100644
--- a/src/main/resources/META-INF/plugin.xml
+++ b/src/main/resources/META-INF/plugin.xml
@@ -31,7 +31,7 @@
<!-- Product and plugin compatibility requirements.
Read more: https://plugins.jetbrains.com/docs/intellij/plugin-compatibility.html -->
<depends>com.intellij.modules.platform</depends>
- <depends optional="true" config-file="Trident-IdeaVim.xml">IdeaVIM</depends>
+ <depends optional="true" config-file="Trident-IdeaVim.xml">IdeaVIM</depends>
<!-- Extension points defined by the plugin.
Read more: https://plugins.jetbrains.com/docs/intellij/plugin-extension-points.html -->
<extensions defaultExtensionNs="com.intellij">
@@ -40,7 +40,7 @@
instance="me.kyren223.trident.ui.SettingsConfigurable"
id="me.kyren223.trident.ui.SettingsConfigurable"
displayName="Trident Settings"/>
- <applicationService serviceImplementation="me.kyren223.trident.data.SettingsState"/>
+ <applicationService serviceImplementation="me.kyren223.trident.data.Settings"/>
</extensions>
<actions>
@@ -50,60 +50,80 @@
</group>
<!-- Trident Select Buffer -->
- <action id="TridentSelect1"
- class="me.kyren223.trident.actions.SelectAction"
+ <action id="TridentSelect1" class="me.kyren223.trident.actions.TridentSelectAction"
text="Select Buffer 1">
<add-to-group group-id="me.kyren223.trident.mainGroup"/>
</action>
- <action id="TridentSelect2"
- class="me.kyren223.trident.actions.SelectAction"
+ <action id="TridentSelect2" class="me.kyren223.trident.actions.TridentSelectAction"
text="Select Buffer 2">
<add-to-group group-id="me.kyren223.trident.mainGroup"/>
</action>
- <action id="TridentSelect3"
- class="me.kyren223.trident.actions.SelectAction"
+ <action id="TridentSelect3" class="me.kyren223.trident.actions.TridentSelectAction"
text="Select Buffer 3">
<add-to-group group-id="me.kyren223.trident.mainGroup"/>
</action>
- <action id="TridentSelect4"
- class="me.kyren223.trident.actions.SelectAction"
+ <action id="TridentSelect4" class="me.kyren223.trident.actions.TridentSelectAction"
text="Select Buffer 4">
<add-to-group group-id="me.kyren223.trident.mainGroup"/>
</action>
+ <action id="TridentSelect5" class="me.kyren223.trident.actions.TridentSelectAction"
+ text="Select Buffer 5">
+ <add-to-group group-id="me.kyren223.trident.mainGroup"/>
+ </action>
+ <action id="TridentSelect6" class="me.kyren223.trident.actions.TridentSelectAction"
+ text="Select Buffer 6">
+ <add-to-group group-id="me.kyren223.trident.mainGroup"/>
+ </action>
+ <action id="TridentSelect7" class="me.kyren223.trident.actions.TridentSelectAction"
+ text="Select Buffer 7">
+ <add-to-group group-id="me.kyren223.trident.mainGroup"/>
+ </action>
+ <action id="TridentSelect8" class="me.kyren223.trident.actions.TridentSelectAction"
+ text="Select Buffer 8">
+ <add-to-group group-id="me.kyren223.trident.mainGroup"/>
+ </action>
+ <action id="TridentSelect9" class="me.kyren223.trident.actions.TridentSelectAction"
+ text="Select Buffer 9">
+ <add-to-group group-id="me.kyren223.trident.mainGroup"/>
+ </action>
+ <action id="TridentSelect10" class="me.kyren223.trident.actions.TridentSelectAction"
+ text="Select Buffer 10">
+ <add-to-group group-id="me.kyren223.trident.mainGroup"/>
+ </action>
<!-- Select Previous & Next Buffer -->
<action id="TridentSelectPrev"
- class="me.kyren223.trident.actions.SelectAction"
+ class="me.kyren223.trident.actions.TridentSelectAction"
text="Select Previous Buffer">
<add-to-group group-id="me.kyren223.trident.mainGroup"/>
</action>
<action id="TridentSelectNext"
- class="me.kyren223.trident.actions.SelectAction"
+ class="me.kyren223.trident.actions.TridentSelectAction"
text="Select Next Buffer">
<add-to-group group-id="me.kyren223.trident.mainGroup"/>
</action>
<!-- Append -->
<action id="TridentAppend"
- class="me.kyren223.trident.actions.AppendAction"
+ class="me.kyren223.trident.actions.TridentAppendAction"
text="Append File">
<add-to-group group-id="me.kyren223.trident.mainGroup"/>
</action>
<!-- UI Actions -->
- <action id="TridentToggleQuickMenu"
+ <action id="TridentList"
class="me.kyren223.trident.actions.TridentListAction"
text="Toggle Quick Menu">
<add-to-group group-id="me.kyren223.trident.mainGroup"/>
</action>
- <action id="TridentQuickMenuSelect"
+ <action id="TridentListSelect"
class="me.kyren223.trident.actions.TridentListSelectAction"
text="Quick Menu Select">
<add-to-group group-id="me.kyren223.trident.mainGroup"/>
</action>
- <action id="TridentPathMappingsMenu"
+ <action id="TridentMappings"
class="me.kyren223.trident.actions.TridentMappingsAction"
text="Toggle Path Mappings Menu">
<add-to-group group-id="me.kyren223.trident.mainGroup"/>