diff options
Diffstat (limited to 'src/main/kotlin/me/kyren223')
12 files changed, 152 insertions, 276 deletions
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 + ) +} |
