1
0
mirror of https://github.com/chylex/IntelliJ-IdeaVim.git synced 2024-11-24 22:42:53 +01:00

Compare commits

...

74 Commits

Author SHA1 Message Date
cc9385f2a9
Set plugin version to chylex-40 2024-08-25 10:17:38 +02:00
32a2384a46
Revert "VIM-2074 Backspace behaviour is incorrect in Replace mode"
This reverts commit 9bbeab80
2024-08-25 10:17:38 +02:00
fdd850de5a
Fix(VIM-3615): Escape closes dialog while waiting for more keys 2024-08-25 10:10:21 +02:00
0f7116b136
Add action to run last macro in all opened files 2024-08-25 06:11:12 +02:00
db8f0251fb
Stop macro execution after a failed search 2024-08-25 06:11:12 +02:00
2ca2c1e774
Revert per-caret registers 2024-08-25 06:11:10 +02:00
f3c32da4d1
Revert "Factor disposable objects on editor opening"
This reverts commit 1fa78935
2024-08-25 06:10:58 +02:00
1a3b34d457
Fix(VIM-3364): Exception with mapped Generate action 2024-08-25 06:10:58 +02:00
1f9159996d
Apply scrolloff after executing native IDEA actions 2024-08-25 06:10:58 +02:00
65c3acd891
Stay on same line after reindenting 2024-08-25 06:10:58 +02:00
223f65c003
Update search register when using f/t 2024-08-25 06:10:58 +02:00
293b854620
Automatically add unambiguous imports after running a macro 2024-08-25 06:10:58 +02:00
9e7c5fd603
Fix(VIM-3179): Respect virtual space below editor (imperfectly) 2024-08-25 06:10:58 +02:00
00c799595f
Fix(VIM-3178): Workaround to support "Jump to Source" action mapping 2024-08-25 06:10:58 +02:00
8577b5ed20
Add support for count for visual and line motion surround 2024-08-25 06:10:58 +02:00
3af7a991a0
Fix vim-surround not working with multiple cursors
Fixes multiple cursors with vim-surround commands `cs, ds, S` (but not `ys`).
2024-08-25 06:10:57 +02:00
212af1798d
Fix(VIM-696) Restore visual mode after undo/redo, and disable incompatible actions 2024-08-25 06:10:57 +02:00
002ef8f72f
Respect count with <Action> mappings 2024-08-25 06:10:57 +02:00
9115af6b3d
Change matchit plugin to use HTML patterns in unrecognized files 2024-08-25 06:10:57 +02:00
25ca42d371
Reset insert mode when switching active editor 2024-08-25 06:10:57 +02:00
408687c9b3
Disable switching to insert mode for some editors 2024-08-25 06:10:54 +02:00
85e00bf8fc
Remove update checker 2024-08-25 06:10:31 +02:00
bd6f2d4b2f
Set custom plugin version 2024-08-25 06:10:31 +02:00
IdeaVim Bot
e406885ec6 Add Igor Babko to contributors list 2024-08-24 09:01:39 +00:00
filipp
9bbeab8062 VIM-2074 Backspace behaviour is incorrect in Replace mode 2024-08-23 14:22:48 +03:00
filipp
373bfc4eab Add endOffset to LiveRange 2024-08-23 14:22:48 +03:00
filipp
050f2f7b97 Respect emojis and don't assume that every character is a single offset 2024-08-23 14:18:03 +03:00
Filipp Vakhitov
e30bc14843 Make closing command line safer 2024-08-23 14:18:03 +03:00
Filipp Vakhitov
76d590be11 Support more flexible command line restrictions for Fleet 2024-08-23 14:18:03 +03:00
Filipp Vakhitov
b005328b4a Exclude generated files from .gitignore
I've also added sorting to be more confident that the generated file will be persistent across different machines
2024-08-23 14:18:03 +03:00
Filipp Vakhitov
ad20021cee Remove currentAction and some unused code 2024-08-23 14:18:03 +03:00
Filipp Vakhitov
126de5c218 Remove package-info.java 2024-08-23 14:18:03 +03:00
Filipp Vakhitov
0f7aef3f15 Fix tests 2024-08-23 14:18:03 +03:00
Filipp Vakhitov
f352b84922 Move some Executor logic to its base class 2024-08-23 14:18:03 +03:00
Filipp Vakhitov
789faa7cb2 Add entry to history on <Esc> in COMMAND mode 2024-08-23 14:18:03 +03:00
Filipp Vakhitov
a338f5768a Better reset 2024-08-23 14:18:03 +03:00
Filipp Vakhitov
8205c74571 Remove some old bindings 2024-08-23 14:18:03 +03:00
Filipp Vakhitov
def40eb409 Save last entry on every command line text update 2024-08-23 14:18:03 +03:00
Filipp Vakhitov
010e8a7541 Support <C-U> in command mode 2024-08-23 14:18:03 +03:00
Filipp Vakhitov
46c6778b3a Support <Down>, <S-Down>, <C-N>, <PageDown> in command mode 2024-08-23 14:18:03 +03:00
Filipp Vakhitov
0977bd4400 Support <Up>, <S-Up>, <C-P>, <PageUp> in command mode 2024-08-23 14:18:03 +03:00
Filipp Vakhitov
db092e9b0a Support history in VimCommandLine 2024-08-23 14:18:03 +03:00
Filipp Vakhitov
5cfb98e188 Remove some old bindings 2024-08-23 14:18:03 +03:00
Filipp Vakhitov
3a95b62885 Support <Insert> in command mode 2024-08-23 14:18:03 +03:00
Filipp Vakhitov
93e6adf5a9 Support <C-W> in command mode 2024-08-23 14:18:03 +03:00
Filipp Vakhitov
37204398ff Support <C-Right>, <S-Right> in command mode 2024-08-23 14:18:03 +03:00
Filipp Vakhitov
b2f450d14d Support <C-Left>, <S-Left> in command mode 2024-08-23 14:18:03 +03:00
Filipp Vakhitov
61da888571 Fix failing tests 2024-08-23 14:18:03 +03:00
Filipp Vakhitov
fcda97cfb8 Update methods to support searching in any text, not just Editor content 2024-08-23 14:18:03 +03:00
Filipp Vakhitov
1dc7ea6363 Register all shortcuts without references on ExKeyBindings
All the shortcuts will be removed from ExKeyBindings, but they still need to be registered
2024-08-23 14:18:03 +03:00
Filipp Vakhitov
bb507db884 Remove swing bindings that are already implemented 2024-08-23 14:18:03 +03:00
Filipp Vakhitov
7b0482ed94 Fix unwanted beep when can't perform an action 2024-08-23 14:18:03 +03:00
Filipp Vakhitov
1c79b0d59a Support <Right> in command mode 2024-08-23 14:18:03 +03:00
Filipp Vakhitov
ff4eb31418 Support <Left> in command mode 2024-08-23 14:18:03 +03:00
Filipp Vakhitov
cb1078cf70 Support <C-H> in command mode 2024-08-23 14:18:03 +03:00
Filipp Vakhitov
da3e40eaf6 Support <C-E>, <End> in command mode 2024-08-23 14:18:03 +03:00
Filipp Vakhitov
17f77a9639 Support <C-B>, <Home> in command mode 2024-08-23 14:18:03 +03:00
Filipp Vakhitov
3d03494354 Support <DEL> in command mode 2024-08-23 14:18:03 +03:00
Filipp Vakhitov
642caddda7 Support <BS> in command mode 2024-08-23 14:18:03 +03:00
Filipp Vakhitov
1d97c43e30 Make ExEntryAction public
Fleet registers commands manually, so commands must be accessible
2024-08-23 14:18:03 +03:00
Igor Babko
7ed3e3b53c Update support-guide.md 2024-08-23 12:14:41 +03:00
IdeaVim Bot
aa39ca2006 Add shaun to contributors list 2024-08-19 09:01:43 +00:00
shaun
bb122903de remove Latest Fixes link 2024-08-19 10:23:23 +03:00
shaun
c84a3cf64d [changelog] add YouTrack link for version fixes 2024-08-19 10:23:23 +03:00
IdeaVim Bot
f4c9464b8a Add The1xDeveloper to contributors list 2024-08-17 09:01:38 +00:00
The1xDeveloper
3ba14d05b4 VIM-566: Add za motion support for toggling folds 2024-08-16 12:28:18 +03:00
Filipp Vakhitov
2189b70b87 Fix(VIM-3601): The escape characters in IdeaVim's configuration file are invalid 2024-08-14 18:18:55 +03:00
dependabot[bot]
ea2222f9d5 Bump org.junit.jupiter:junit-jupiter from 5.10.3 to 5.11.0
Bumps [org.junit.jupiter:junit-jupiter](https://github.com/junit-team/junit5) from 5.10.3 to 5.11.0.
- [Release notes](https://github.com/junit-team/junit5/releases)
- [Commits](https://github.com/junit-team/junit5/compare/r5.10.3...r5.11.0)

---
updated-dependencies:
- dependency-name: org.junit.jupiter:junit-jupiter
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-14 18:53:54 +03:00
Filipp Vakhitov
7d68d41888 Fix(VIM-3580): New terminal switches editor to insert mode 2024-08-12 13:44:24 +03:00
Alex Pláte
44749b6d8c
Update IdeaVim Plugins.md 2024-08-12 12:16:19 +03:00
Alex Pláte
1ce4dbc569
Update Home.md 2024-08-12 12:14:44 +03:00
Alex Pláte
db59513505
Update Home.md 2024-08-12 12:13:36 +03:00
Filipp Vakhitov
8c9ff9465f Fix(VIM-3584): com.maddyhome.idea.vim.KeyHandler requests com.maddyhome.idea.vim.api.VimKeyGroup instance. Class initialization must not depend on services 2024-08-11 01:12:59 +03:00
Filipp Vakhitov
1a2322ddec OutputPanel no longer ignores key events 2024-08-10 23:55:57 +03:00
138 changed files with 3986 additions and 1866 deletions

1
.gitattributes vendored Normal file
View File

@ -0,0 +1 @@
* text=auto eol=lf

3
.gitignore vendored
View File

@ -27,9 +27,6 @@
# Generated by gradle task "generateGrammarSource"
vim-engine/src/main/java/com/maddyhome/idea/vim/parser/generated
vim-engine/src/main/java/com/maddyhome/idea/vim/regexp/parser/generated
# Generated JSONs for lazy classloading
/vim-engine/src/main/resources/ksp-generated
/src/main/resources/ksp-generated
# Created by github automation
settings.xml

View File

@ -523,6 +523,18 @@ Contributors:
[![icon][github]](https://github.com/LazyScaper)
&nbsp;
Jake
* [![icon][mail]](mailto:the1xdeveloper@gmail.com)
[![icon][github]](https://github.com/The1xDeveloper)
&nbsp;
The1xDeveloper
* [![icon][mail]](mailto:shaunewilliams@gmail.com)
[![icon][github]](https://github.com/shaunlebron)
&nbsp;
shaun
* [![icon][mail]](mailto:i.i.babko@gmail.com)
[![icon][github]](https://github.com/igorbabko)
&nbsp;
Igor Babko
Previous contributors:

View File

@ -27,8 +27,8 @@ usual beta standards.
Since version 2.9.0, the changelog can be found on YouTrack
To Be Released: https://youtrack.jetbrains.com/issues/VIM?q=%23%7BReady%20To%20Release%7D%20
Latest Fixes: https://youtrack.jetbrains.com/issues/VIM?q=State:%20Fixed%20sort%20by:%20updated%20
* [To Be Released](https://youtrack.jetbrains.com/issues/VIM?q=%23%7BReady%20To%20Release%7D%20)
* [Version Fixes](https://youtrack.jetbrains.com/issues/VIM?q=State:%20Fixed%20sort%20by:%20%7BFix%20versions%7D%20asc)
## 2.9.0, 2024-02-20

View File

@ -62,12 +62,16 @@ for a few days or send it to a friend for testing.
If you are looking for:
- Vim commands (`w`, `<C-O>`, `p`, etc.):
- Any particular command: `package-info.java`.
- Any particular command:
- [Commands common for Fleet and IdeaVim](vim-engine/src/main/resources/ksp-generated/engine_commands.json)
- [IdeaVim only commands](src/main/resources/ksp-generated/intellij_commands.json)
- How commands are executed in common: `EditorActionHandlerBase`.
- Key mapping: `KeyHandler.handleKey()`.
- Ex commands (`:set`, `:s`, `:nohlsearch`):
- Any particular ex command: package `com.maddyhome.idea.vim.ex.handler`.
- Any particular command:
- [Commands common for Fleet and IdeaVim](vim-engine/src/main/resources/ksp-generated/engine_ex_commands.json)
- [IdeaVim only commands](src/main/resources/ksp-generated/intellij_ex_commands.json)
- Vim script grammar: `Vimscript.g4`.
- Vim script parsing: package `com.maddyhome.idea.vim.vimscript.parser`.
- Vim script executor: `Executor`.

View File

@ -109,7 +109,6 @@ etc
See also:
* [The list of all supported commands](src/main/java/com/maddyhome/idea/vim/package-info.java)
* [Top feature requests and bugs](https://youtrack.jetbrains.com/issues/VIM?q=%23Unresolved+sort+by%3A+votes)
* [Vimscript support roadmap](vimscript-info/VIMSCRIPT_ROADMAP.md)
* [List of supported in-build functions](vimscript-info/FUNCTIONS_INFO.MD)

View File

@ -37,7 +37,8 @@ class CommandOrMotionProcessor(private val environment: SymbolProcessorEnvironme
Files.createDirectories(generatedDirPath)
val filePath = generatedDirPath.resolve(environment.options["commands_file"]!!)
val fileContent = json.encodeToString(commands)
val sortedCommands = commands.sortedWith(compareBy({ it.keys }, { it.`class` }))
val fileContent = json.encodeToString(sortedCommands)
filePath.writeText(fileContent)
return emptyList()

View File

@ -37,7 +37,8 @@ class ExCommandProcessor(private val environment: SymbolProcessorEnvironment): S
Files.createDirectories(generatedDirPath)
val filePath = generatedDirPath.resolve(environment.options["ex_commands_file"]!!)
val fileContent = json.encodeToString(commandToClass)
val sortedCommandToClass = commandToClass.toList().sortedWith(compareBy({ it.first }, { it.second })).toMap()
val fileContent = json.encodeToString(sortedCommandToClass)
filePath.writeText(fileContent)
return emptyList()

View File

@ -37,7 +37,8 @@ class VimscriptFunctionProcessor(private val environment: SymbolProcessorEnviron
Files.createDirectories(generatedDirPath)
val filePath = generatedDirPath.resolve(environment.options["vimscript_functions_file"]!!)
val fileContent = json.encodeToString(nameToClass)
val sortedNameToClass = nameToClass.toList().sortedWith(compareBy({ it.first }, { it.second })).toMap()
val fileContent = json.encodeToString(sortedNameToClass)
filePath.writeText(fileContent)
return emptyList()

View File

@ -125,6 +125,7 @@ dependencies {
// AceJump is an optional dependency. We use their SessionManager class to check if it's active
plugin("AceJump", "3.8.19")
plugin("com.intellij.classic.ui", "242.20224.159")
}
moduleSources(project(":vim-engine", "sourcesJarArtifacts"))
@ -210,6 +211,8 @@ tasks {
}
compileTestKotlin {
enabled = false
kotlinOptions {
jvmTarget = javaVersion
apiVersion = "1.9"

View File

@ -1,6 +1,6 @@
Welcome to the IdeaVim wiki!
- List of IdeaVim plugins: [plugins](IdeaVim%20Plugins.md)
- Examples of `ideajoin` option (also known as "smart join"): ["ideajoin" examples](ideajoin-examples.md)
- List of "set" commands: ["set" commands](set-commands.md)
- Docs about "select" mode in vim: [select mode](Select-mode.md)
- List of IdeaVim plugins: [plugins](IdeaVim%20Plugins)
- Examples of `ideajoin` option (also known as "smart join"): ["ideajoin" examples](ideajoin-examples)
- List of "set" commands: ["set" commands](set-commands)
- Docs about "select" mode in vim: [select mode](Select-mode)

View File

@ -82,7 +82,7 @@ Original plugin: [NERDTree](https://github.com/preservim/nerdtree).
### Instructions
[See here](NERDTree-support.md).
[See here](NERDTree-support).
</details>

View File

@ -1,7 +1,7 @@
# Support Guide
This document is created to help our support team.
It's not intended to be read by the users as it brings to value to them.
It's not intended to be read by the users as it brings no value to them.
## Support channels

View File

@ -16,11 +16,11 @@
# https://data.services.jetbrains.com/products?code=IC
# Maven releases are here: https://www.jetbrains.com/intellij-repository/releases
# And snapshots: https://www.jetbrains.com/intellij-repository/snapshots
ideaVersion=2024.1.1
ideaVersion=2024.2
# Values for type: https://plugins.jetbrains.com/docs/intellij/tools-gradle-intellij-plugin.html#intellij-extension-type
ideaType=IC
instrumentPluginCode=true
version=SNAPSHOT
version=chylex-40
javaVersion=17
remoteRobotVersion=0.11.23
antlrVersion=4.10.1
@ -47,7 +47,6 @@ youtrackToken=
# Gradle settings
org.gradle.jvmargs='-Dfile.encoding=UTF-8'
org.gradle.configuration-cache=true
org.gradle.caching=true
# Disable warning from gradle-intellij-plugin. Kotlin stdlib is included as compileOnly, so the warning is unnecessary

View File

@ -19,7 +19,6 @@ exclude:
- src/test/java/org/jetbrains/plugins/ideavim/propertybased/samples/JavaText.kt
- src/test/java/org/jetbrains/plugins/ideavim/propertybased/samples/LoremText.kt
- src/test/java/org/jetbrains/plugins/ideavim/propertybased/samples/SimpleText.kt
- src/main/java/com/maddyhome/idea/vim/package-info.java
- vim-engine/src/main/java/com/maddyhome/idea/vim/regexp/parser/generated
- vim-engine/src/main/java/com/maddyhome/idea/vim/parser/generated
- src/main/java/com/maddyhome/idea/vim/group/SearchGroup.java

View File

@ -0,0 +1,52 @@
package com.maddyhome.idea.vim.action
import com.intellij.openapi.actionSystem.ActionUpdateThread
import com.intellij.openapi.actionSystem.AnActionEvent
import com.intellij.openapi.command.UndoConfirmationPolicy
import com.intellij.openapi.command.WriteCommandAction
import com.intellij.openapi.fileEditor.TextEditor
import com.intellij.openapi.fileEditor.ex.FileEditorManagerEx
import com.intellij.openapi.project.DumbAwareAction
import com.maddyhome.idea.vim.KeyHandler
import com.maddyhome.idea.vim.api.injector
import com.maddyhome.idea.vim.newapi.IjEditorExecutionContext
import com.maddyhome.idea.vim.newapi.vim
import com.maddyhome.idea.vim.state.mode.Mode
class VimRunLastMacroInOpenFiles : DumbAwareAction() {
override fun update(e: AnActionEvent) {
val lastRegister = injector.macro.lastRegister
val isEnabled = lastRegister != 0.toChar()
e.presentation.isEnabled = isEnabled
e.presentation.text = if (isEnabled) "Run Macro '${lastRegister}' in Open Files" else "Run Last Macro in Open Files"
}
override fun getActionUpdateThread(): ActionUpdateThread {
return ActionUpdateThread.EDT
}
override fun actionPerformed(e: AnActionEvent) {
val project = e.project ?: return
val fileEditorManager = FileEditorManagerEx.getInstanceExIfCreated(project) ?: return
val editors = fileEditorManager.allEditors.filterIsInstance<TextEditor>()
WriteCommandAction.writeCommandAction(project)
.withName(e.presentation.text)
.withGlobalUndo()
.withUndoConfirmationPolicy(UndoConfirmationPolicy.REQUEST_CONFIRMATION)
.run<RuntimeException> {
val reg = injector.macro.lastRegister
for (editor in editors) {
fileEditorManager.openFile(editor.file, true)
val vimEditor = editor.editor.vim
vimEditor.mode = Mode.NORMAL()
KeyHandler.getInstance().reset(vimEditor)
injector.macro.playbackRegister(vimEditor, IjEditorExecutionContext(e.dataContext), reg, 1)
}
}
}
}

View File

@ -69,7 +69,8 @@ object VimExtensionFacade {
@JvmStatic
@Deprecated("Use VimPlugin.getKey().putKeyMapping(modes, fromKeys, pluginOwner, extensionHandler, recursive)",
@Deprecated(
"Use VimPlugin.getKey().putKeyMapping(modes, fromKeys, pluginOwner, extensionHandler, recursive)",
ReplaceWith(
"VimPlugin.getKey().putKeyMapping(modes, fromKeys, pluginOwner, extensionHandler, recursive)",
"com.maddyhome.idea.vim.VimPlugin"
@ -195,7 +196,7 @@ object VimExtensionFacade {
@JvmStatic
fun getRegisterForCaret(register: Char, caret: VimCaret): List<KeyStroke>? {
val reg = caret.registerStorage.getRegister(register) ?: return null
val reg = injector.registerGroup.getRegister(register) ?: return null
return reg.keys
}
@ -208,7 +209,7 @@ object VimExtensionFacade {
/** Set the current contents of the given register */
@JvmStatic
fun setRegisterForCaret(register: Char, caret: ImmutableVimCaret, keys: List<KeyStroke?>?) {
caret.registerStorage.setKeys(register, keys?.filterNotNull() ?: emptyList())
injector.registerGroup.setKeys(register, keys?.filterNotNull() ?: emptyList())
}
/** Set the current contents of the given register */

View File

@ -21,10 +21,7 @@ import com.intellij.openapi.editor.markup.TextAttributes
import com.intellij.openapi.util.Disposer
import com.intellij.util.Alarm
import com.intellij.util.Alarm.ThreadToUse
import com.jetbrains.rd.util.first
import com.maddyhome.idea.vim.VimPlugin
import com.maddyhome.idea.vim.api.ImmutableVimCaret
import com.maddyhome.idea.vim.api.VimCaret
import com.maddyhome.idea.vim.api.VimEditor
import com.maddyhome.idea.vim.api.injector
import com.maddyhome.idea.vim.common.ModeChangeListener
@ -117,9 +114,9 @@ internal class VimHighlightedYank : VimExtension, VimYankListener, ModeChangeLis
initialised = false
}
override fun yankPerformed(caretToRange: Map<ImmutableVimCaret, TextRange>) {
override fun yankPerformed(editor: VimEditor, range: TextRange) {
ensureInitialised()
highlightHandler.highlightYankRange(caretToRange)
highlightHandler.highlightYankRange(editor.ij, range)
}
override fun modeChanged(editor: VimEditor, oldMode: Mode) {
@ -140,15 +137,13 @@ internal class VimHighlightedYank : VimExtension, VimYankListener, ModeChangeLis
private var lastEditor: Editor? = null
private val highlighters = mutableSetOf<RangeHighlighter>()
fun highlightYankRange(caretToRange: Map<ImmutableVimCaret, TextRange>) {
fun highlightYankRange(editor: Editor, range: TextRange) {
// from vim-highlightedyank docs: When a new text is yanked or user starts editing, the old highlighting would be deleted
clearYankHighlighters()
val editor = caretToRange.first().key.editor.ij
lastEditor = editor
val attributes = getHighlightTextAttributes(editor)
for (range in caretToRange.values) {
for (i in 0 until range.size()) {
val highlighter = editor.markupModel.addRangeHighlighter(
range.startOffsets[i],
@ -159,7 +154,6 @@ internal class VimHighlightedYank : VimExtension, VimYankListener, ModeChangeLis
)
highlighters.add(highlighter)
}
}
// from vim-highlightedyank docs: A negative number makes the highlight persistent.
val timeout = extractUsersHighlightDuration()

View File

@ -234,7 +234,7 @@ private object FileTypePatterns {
} else if (fileTypeName == "CMakeLists.txt" || fileName == "CMakeLists") {
this.cMakePatterns
} else {
return null
this.htmlPatterns
}
}

View File

@ -144,7 +144,7 @@ internal class ReplaceWithRegister : VimExtension {
private fun doReplace(editor: Editor, context: DataContext, caret: ImmutableVimCaret, visualSelection: PutData.VisualSelection) {
val registerGroup = injector.registerGroup
val lastRegisterChar = if (editor.caretModel.caretCount == 1) registerGroup.currentRegister else registerGroup.getCurrentRegisterForMulticaret()
val savedRegister = caret.registerStorage.getRegister(lastRegisterChar) ?: return
val savedRegister = registerGroup.getRegister(lastRegisterChar) ?: return
var usedType = savedRegister.type
var usedText = savedRegister.text

View File

@ -0,0 +1,30 @@
package com.maddyhome.idea.vim.extension.surround
import com.intellij.util.text.CharSequenceSubSequence
internal data class RepeatedCharSequence(val text: CharSequence, val count: Int) : CharSequence {
override val length = text.length * count
override fun get(index: Int): Char {
if (index < 0 || index >= length) throw IndexOutOfBoundsException()
return text[index % text.length]
}
override fun subSequence(startIndex: Int, endIndex: Int): CharSequence {
return CharSequenceSubSequence(this, startIndex, endIndex)
}
override fun toString(): String {
return text.repeat(count)
}
companion object {
fun of(text: CharSequence, count: Int): CharSequence {
return when (count) {
0 -> ""
1 -> text
else -> RepeatedCharSequence(text, count)
}
}
}
}

View File

@ -14,6 +14,7 @@ import com.intellij.openapi.editor.Editor
import com.maddyhome.idea.vim.VimPlugin
import com.maddyhome.idea.vim.api.ExecutionContext
import com.maddyhome.idea.vim.api.VimCaret
import com.maddyhome.idea.vim.api.VimChangeGroup
import com.maddyhome.idea.vim.api.VimEditor
import com.maddyhome.idea.vim.api.endsWithNewLine
import com.maddyhome.idea.vim.api.getLeadingCharacterOffset
@ -36,7 +37,10 @@ import com.maddyhome.idea.vim.extension.VimExtensionFacade.setRegisterForCaret
import com.maddyhome.idea.vim.extension.exportOperatorFunction
import com.maddyhome.idea.vim.group.findBlockRange
import com.maddyhome.idea.vim.helper.exitVisualMode
import com.maddyhome.idea.vim.helper.runWithEveryCaretAndRestore
import com.maddyhome.idea.vim.key.OperatorFunction
import com.maddyhome.idea.vim.newapi.IjVimCaret
import com.maddyhome.idea.vim.newapi.IjVimEditor
import com.maddyhome.idea.vim.newapi.ij
import com.maddyhome.idea.vim.newapi.vim
import com.maddyhome.idea.vim.options.helpers.ClipboardOptionHelper
@ -80,7 +84,7 @@ internal class VimSurroundExtension : VimExtension {
putKeyMappingIfMissing(MappingMode.XO, injector.parser.parseKeys("S"), owner, injector.parser.parseKeys("<Plug>VSurround"), true)
}
VimExtensionFacade.exportOperatorFunction(OPERATOR_FUNC, Operator())
VimExtensionFacade.exportOperatorFunction(OPERATOR_FUNC, Operator(supportsMultipleCursors = false, count = 1)) // TODO
}
private class YSurroundHandler : ExtensionHandler {
@ -108,7 +112,7 @@ internal class VimSurroundExtension : VimExtension {
val lastNonWhiteSpaceOffset = getLastNonWhitespaceCharacterOffset(editor.text(), lineStartOffset, lineEndOffset)
if (lastNonWhiteSpaceOffset != null) {
val range = TextRange(lineStartOffset, lastNonWhiteSpaceOffset + 1)
performSurround(pair, range, it)
performSurround(pair, range, it, count = operatorArguments.count1)
}
// it.moveToOffset(lineStartOffset)
}
@ -131,15 +135,13 @@ internal class VimSurroundExtension : VimExtension {
private class VSurroundHandler : ExtensionHandler {
override fun execute(editor: VimEditor, context: ExecutionContext, operatorArguments: OperatorArguments) {
val selectionStart = editor.ij.caretModel.primaryCaret.selectionStart
// NB: Operator ignores SelectionType anyway
if (!Operator().apply(editor, context, editor.mode.selectionType)) {
if (!Operator(supportsMultipleCursors = true, count = operatorArguments.count1).apply(editor, context, editor.mode.selectionType)) {
return
}
runWriteAction {
// Leave visual mode
editor.exitVisualMode()
editor.ij.caretModel.moveToOffset(selectionStart)
}
}
}
@ -160,6 +162,10 @@ internal class VimSurroundExtension : VimExtension {
companion object {
fun change(editor: VimEditor, context: ExecutionContext, charFrom: Char, newSurround: Pair<String, String>?) {
editor.ij.runWithEveryCaretAndRestore { changeAtCaret(editor, context, charFrom, newSurround) }
}
fun changeAtCaret(editor: VimEditor, context: ExecutionContext, charFrom: Char, newSurround: Pair<String, String>?) {
// Save old register values for carets
val surroundings = editor.sortedCarets()
.map {
@ -267,21 +273,42 @@ internal class VimSurroundExtension : VimExtension {
}
}
private class Operator : OperatorFunction {
override fun apply(editor: VimEditor, context: ExecutionContext, selectionType: SelectionType?): Boolean {
val ijEditor = editor.ij
private class Operator(private val supportsMultipleCursors: Boolean, private val count: Int) : OperatorFunction {
override fun apply(vimEditor: VimEditor, context: ExecutionContext, selectionType: SelectionType?): Boolean {
val ijEditor = vimEditor.ij
val c = getChar(ijEditor)
if (c.code == 0) return true
val pair = getOrInputPair(c, ijEditor, context.ij) ?: return false
// XXX: Will it work with line-wise or block-wise selections?
val range = getSurroundRange(editor.currentCaret()) ?: return false
performSurround(pair, range, editor.currentCaret(), selectionType == SelectionType.LINE_WISE)
runWriteAction {
val change = VimPlugin.getChange()
if (supportsMultipleCursors) {
ijEditor.runWithEveryCaretAndRestore {
applyOnce(ijEditor, change, pair, count)
}
}
else {
applyOnce(ijEditor, change, pair, count)
// Jump back to start
executeNormalWithoutMapping(injector.parser.parseKeys("`["), ijEditor)
}
}
return true
}
private fun applyOnce(editor: Editor, change: VimChangeGroup, pair: Pair<String, String>, count: Int) {
// XXX: Will it work with line-wise or block-wise selections?
val primaryCaret = editor.caretModel.primaryCaret
val range = getSurroundRange(primaryCaret.vim)
if (range != null) {
val start = RepeatedCharSequence.of(pair.first, count)
val end = RepeatedCharSequence.of(pair.second, count)
change.insertText(IjVimEditor(editor), IjVimCaret(primaryCaret), range.startOffset, start)
change.insertText(IjVimEditor(editor), IjVimCaret(primaryCaret), range.endOffset + start.length, end)
}
}
private fun getSurroundRange(caret: VimCaret): TextRange? {
val editor = caret.editor
if (editor.mode is Mode.CMD_LINE) {
@ -375,15 +402,15 @@ private fun getChar(editor: Editor): Char {
return res
}
private fun performSurround(pair: Pair<String, String>, range: TextRange, caret: VimCaret, tagsOnNewLines: Boolean = false) {
private fun performSurround(pair: Pair<String, String>, range: TextRange, caret: VimCaret, count: Int, tagsOnNewLines: Boolean = false) {
runWriteAction {
val editor = caret.editor
val change = VimPlugin.getChange()
val leftSurround = pair.first + if (tagsOnNewLines) "\n" else ""
val leftSurround = RepeatedCharSequence.of(pair.first + if (tagsOnNewLines) "\n" else "", count)
val isEOF = range.endOffset == editor.text().length
val hasNewLine = editor.endsWithNewLine()
val rightSurround = if (tagsOnNewLines) {
val rightSurround = (if (tagsOnNewLines) {
if (isEOF && !hasNewLine) {
"\n" + pair.second
} else {
@ -391,7 +418,7 @@ private fun performSurround(pair: Pair<String, String>, range: TextRange, caret:
}
} else {
pair.second
}
}).let { RepeatedCharSequence.of(it, count) }
change.insertText(editor, caret, range.startOffset, leftSurround)
change.insertText(editor, caret, range.endOffset + leftSurround.length, rightSurround)

View File

@ -39,7 +39,6 @@ import com.maddyhome.idea.vim.newapi.IjVimCaret
import com.maddyhome.idea.vim.newapi.IjVimEditor
import com.maddyhome.idea.vim.newapi.ij
import com.maddyhome.idea.vim.state.mode.Mode
import kotlin.math.min
/**
* Provides all the insert/replace related functionality
@ -125,6 +124,7 @@ class ChangeGroup : VimChangeGroupBase() {
context: ExecutionContext,
range: TextRange,
) {
val startPos = editor.offsetToBufferPosition(caret.offset)
val startOffset = editor.getLineStartForOffset(range.startOffset)
val endOffset = editor.getLineEndForOffset(range.endOffset)
val ijEditor = (editor as IjVimEditor).editor
@ -149,11 +149,7 @@ class ChangeGroup : VimChangeGroupBase() {
}
}
val afterAction = {
val firstLine = editor.offsetToBufferPosition(
min(startOffset.toDouble(), endOffset.toDouble()).toInt()
).line
val newOffset = injector.motion.moveCaretToLineStartSkipLeading(editor, firstLine)
caret.moveToOffset(newOffset)
caret.moveToOffset(injector.motion.moveCaretToLineStartSkipLeading(editor, startPos.line))
restoreCursor(editor, caret, (caret as IjVimCaret).caret.logicalPosition.line)
}
if (project != null) {

View File

@ -11,11 +11,14 @@ package com.maddyhome.idea.vim.group;
import com.intellij.openapi.diagnostic.Logger;
import com.maddyhome.idea.vim.api.VimDigraphGroupBase;
import com.maddyhome.idea.vim.api.VimEditor;
import com.maddyhome.idea.vim.api.VimOutputPanel;
import com.maddyhome.idea.vim.ex.ExOutputModel;
import com.maddyhome.idea.vim.helper.EditorHelper;
import com.maddyhome.idea.vim.newapi.IjVimEditor;
import org.jetbrains.annotations.NotNull;
import static com.maddyhome.idea.vim.api.VimInjectorKt.injector;
public class DigraphGroup extends VimDigraphGroupBase {
public void showDigraphs(@NotNull VimEditor editor) {
@ -71,7 +74,9 @@ public class DigraphGroup extends VimDigraphGroupBase {
}
}
ExOutputModel.getInstance(((IjVimEditor) editor).getEditor()).output(res.toString());
VimOutputPanel output = injector.getOutputPanel().getOrCreate(editor, injector.getExecutionContextManager().getEditorExecutionContext(editor));
output.addText(res.toString(), true );
output.show();
}
private static final Logger logger = Logger.getInstance(DigraphGroup.class.getName());

View File

@ -374,9 +374,9 @@ public class EditorGroup implements PersistentStateComponent<Element>, VimEditor
if (activeCommandLine != null) {
activeCommandLine.close(true, false);
}
ExOutputModel exOutputModel = ExOutputModel.tryGetInstance(editor);
if (exOutputModel != null) {
exOutputModel.close();
VimOutputPanel outputPanel = injector.getOutputPanel().getCurrentOutputPanel();
if (outputPanel != null) {
outputPanel.close();
}
VimModalInput modalInput = injector.getModalInput().getCurrentModalInput();
if (modalInput != null) {

View File

@ -14,9 +14,7 @@ import com.intellij.openapi.components.State;
import com.intellij.openapi.components.Storage;
import com.intellij.openapi.diagnostic.Logger;
import com.maddyhome.idea.vim.VimPlugin;
import com.maddyhome.idea.vim.history.HistoryBlock;
import com.maddyhome.idea.vim.history.HistoryEntry;
import com.maddyhome.idea.vim.history.VimHistoryBase;
import com.maddyhome.idea.vim.history.*;
import org.jdom.Element;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@ -35,21 +33,20 @@ public class HistoryGroup extends VimHistoryBase implements PersistentStateCompo
logger.debug("saveData");
Element hist = new Element("history");
saveData(hist, SEARCH);
saveData(hist, COMMAND);
saveData(hist, EXPRESSION);
saveData(hist, INPUT);
for (Type type : getHistories().keySet()) {
saveData(hist, type);
}
element.addContent(hist);
}
private void saveData(@NotNull Element element, String key) {
final HistoryBlock block = getHistories().get(key);
private void saveData(@NotNull Element element, VimHistory.Type type) {
final HistoryBlock block = getHistories().get(type);
if (block == null) {
return;
}
final Element root = new Element("history-" + key);
final Element root = new Element("history-" + typeToKey(type));
for (HistoryEntry entry : block.getEntries()) {
final Element entryElement = new Element("entry");
@ -67,10 +64,10 @@ public class HistoryGroup extends VimHistoryBase implements PersistentStateCompo
return;
}
readData(hist, SEARCH);
readData(hist, COMMAND);
readData(hist, EXPRESSION);
readData(hist, INPUT);
for (Element child : hist.getChildren()) {
String key = child.getName().replace("history-", "");
readData(hist, key);
}
}
private void readData(@NotNull Element element, String key) {
@ -80,7 +77,7 @@ public class HistoryGroup extends VimHistoryBase implements PersistentStateCompo
}
block = new HistoryBlock();
getHistories().put(key, block);
getHistories().put(getTypeForString(key), block);
final Element root = element.getChild("history-" + key);
if (root != null) {
@ -94,6 +91,25 @@ public class HistoryGroup extends VimHistoryBase implements PersistentStateCompo
}
}
private String typeToKey(VimHistory.Type type) {
if (type instanceof VimHistory.Type.Search) {
return SEARCH;
}
if (type instanceof VimHistory.Type.Command) {
return COMMAND;
}
if (type instanceof VimHistory.Type.Expression) {
return EXPRESSION;
}
if (type instanceof VimHistory.Type.Input) {
return INPUT;
}
if (type instanceof VimHistory.Type.Custom) {
return ((Type.Custom) type).getId();
}
return "unreachable";
}
@Nullable
@Override
public Element getState() {

View File

@ -139,7 +139,7 @@ object IjOptions {
// Temporary feature flags during development, not really intended for external use
val closenotebooks: ToggleOption = addOption(ToggleOption("closenotebooks", GLOBAL, "closenotebooks", true, isHidden = true))
val commandOrMotionAnnotation: ToggleOption = addOption(ToggleOption("commandormotionannotation", GLOBAL, "commandormotionannotation", true, isHidden = true))
val oldundo: ToggleOption = addOption(ToggleOption("oldundo", GLOBAL, "oldundo", false, isHidden = true))
val oldundo: ToggleOption = addOption(ToggleOption("oldundo", GLOBAL, "oldundo", true, isHidden = true))
val unifyjumps: ToggleOption = addOption(ToggleOption("unifyjumps", GLOBAL, "unifyjumps", true, isHidden = true))
val vimscriptFunctionAnnotation: ToggleOption = addOption(ToggleOption("vimscriptfunctionannotation", GLOBAL, "vimscriptfunctionannotation", true, isHidden = true))

View File

@ -26,10 +26,7 @@ import com.maddyhome.idea.vim.EventFacade;
import com.maddyhome.idea.vim.VimPlugin;
import com.maddyhome.idea.vim.action.VimShortcutKeyAction;
import com.maddyhome.idea.vim.action.change.LazyVimCommand;
import com.maddyhome.idea.vim.api.NativeAction;
import com.maddyhome.idea.vim.api.VimEditor;
import com.maddyhome.idea.vim.api.VimInjectorKt;
import com.maddyhome.idea.vim.api.VimKeyGroupBase;
import com.maddyhome.idea.vim.api.*;
import com.maddyhome.idea.vim.command.MappingMode;
import com.maddyhome.idea.vim.ex.ExOutputModel;
import com.maddyhome.idea.vim.key.*;
@ -80,25 +77,6 @@ public class KeyGroup extends VimKeyGroupBase implements PersistentStateComponen
((IjVimEditor)editor).getEditor().getComponent());
}
public boolean showKeyMappings(@NotNull Set<? extends MappingMode> modes, @NotNull Editor editor) {
List<Pair<EnumSet<MappingMode>, MappingInfo>> rows = getKeyMappingRows(modes);
final StringBuilder builder = new StringBuilder();
for (Pair<EnumSet<MappingMode>, MappingInfo> row : rows) {
MappingInfo mappingInfo = row.getSecond();
builder.append(StringsKt.padEnd(getModesStringCode(row.getFirst()), 2, ' '));
builder.append(" ");
builder.append(StringsKt.padEnd(VimInjectorKt.getInjector().getParser().toKeyNotation(mappingInfo.getFromKeys()), 11, ' '));
builder.append(" ");
builder.append(mappingInfo.isRecursive() ? " " : "*");
builder.append(" ");
builder.append(mappingInfo.getPresentableString());
builder.append("\n");
}
ExOutputModel.getInstance(editor).output(builder.toString());
return true;
}
@Override
public void updateShortcutKeysRegistration() {
for (VimEditor editor : injector.getEditorGroup().getEditors()) {
@ -358,6 +336,22 @@ public class KeyGroup extends VimKeyGroupBase implements PersistentStateComponen
@Override
public boolean showKeyMappings(@NotNull Set<? extends MappingMode> modes, @NotNull VimEditor editor) {
return showKeyMappings(modes, ((IjVimEditor) editor).getEditor());
List<Pair<EnumSet<MappingMode>, MappingInfo>> rows = getKeyMappingRows(modes);
final StringBuilder builder = new StringBuilder();
for (Pair<EnumSet<MappingMode>, MappingInfo> row : rows) {
MappingInfo mappingInfo = row.getSecond();
builder.append(StringsKt.padEnd(getModesStringCode(row.getFirst()), 2, ' '));
builder.append(" ");
builder.append(StringsKt.padEnd(VimInjectorKt.getInjector().getParser().toKeyNotation(mappingInfo.getFromKeys()), 11, ' '));
builder.append(" ");
builder.append(mappingInfo.isRecursive() ? " " : "*");
builder.append(" ");
builder.append(mappingInfo.getPresentableString());
builder.append("\n");
}
VimOutputPanel outputPanel = injector.getOutputPanel().getOrCreate(editor, injector.getExecutionContextManager().getEditorExecutionContext(editor));
outputPanel.addText(builder.toString(), true);
outputPanel.show();
return true;
}
}

View File

@ -0,0 +1,68 @@
package com.maddyhome.idea.vim.group
import com.intellij.codeInsight.daemon.ReferenceImporter
import com.intellij.openapi.actionSystem.CommonDataKeys
import com.intellij.openapi.actionSystem.DataContext
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.application.ReadAction
import com.intellij.openapi.command.WriteCommandAction
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.fileEditor.FileDocumentManager
import com.intellij.openapi.progress.ProgressIndicator
import com.intellij.openapi.progress.ProgressManager
import com.intellij.openapi.progress.Task
import com.intellij.psi.PsiDocumentManager
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiRecursiveElementWalkingVisitor
import java.util.function.BooleanSupplier
internal object MacroAutoImport {
fun run(editor: Editor, dataContext: DataContext) {
val project = CommonDataKeys.PROJECT.getData(dataContext) ?: return
val file = PsiDocumentManager.getInstance(project).getPsiFile(editor.document) ?: return
if (!FileDocumentManager.getInstance().requestWriting(editor.document, project)) {
return
}
val importers = ReferenceImporter.EP_NAME.extensionList
if (importers.isEmpty()) {
return
}
ProgressManager.getInstance().run(object : Task.Backgroundable(project, "Auto import", true) {
override fun run(indicator: ProgressIndicator) {
val fixes = ReadAction.nonBlocking<List<BooleanSupplier>> {
val fixes = mutableListOf<BooleanSupplier>()
file.accept(object : PsiRecursiveElementWalkingVisitor() {
override fun visitElement(element: PsiElement) {
for (reference in element.references) {
if (reference.resolve() != null) {
continue
}
for (importer in importers) {
importer.computeAutoImportAtOffset(editor, file, element.textRange.startOffset, true)
?.let(fixes::add)
}
}
super.visitElement(element)
}
})
return@nonBlocking fixes
}.executeSynchronously()
ApplicationManager.getApplication().invokeAndWait {
WriteCommandAction.writeCommandAction(project)
.withName("Auto Import")
.withGroupId("IdeaVimAutoImportAfterMacro")
.shouldRecordActionForActiveDocument(true)
.run<RuntimeException> {
fixes.forEach { it.asBoolean }
}
}
}
})
}
}

View File

@ -22,6 +22,7 @@ import com.maddyhome.idea.vim.api.injector
import com.maddyhome.idea.vim.helper.MessageHelper.message
import com.maddyhome.idea.vim.macro.VimMacroBase
import com.maddyhome.idea.vim.newapi.IjVimEditor
import com.maddyhome.idea.vim.newapi.ij
/**
* Used to handle playback of macros
@ -93,6 +94,9 @@ internal class MacroGroup : VimMacroBase() {
} finally {
keyStack.removeFirst()
}
if (!isInternalMacro) {
MacroAutoImport.run(editor.ij, context.ij)
}
}
if (isInternalMacro) {

View File

@ -317,7 +317,7 @@ internal class MotionGroup : VimMotionGroupBase() {
is Mode.CMD_LINE -> {
val commandLine = injector.commandLine.getActiveCommandLine() ?: return
commandLine.close(refocusOwningEditor = false, resetCaret = false)
ExOutputModel.tryGetInstance(editor)?.close()
injector.outputPanel.getCurrentOutputPanel()?.close()
}
else -> {}
}

View File

@ -218,13 +218,17 @@ internal class VimEnterHandler(nextHandler: EditorActionHandler?) : VimKeyHandle
internal class VimEscHandler(nextHandler: EditorActionHandler) : VimKeyHandler(nextHandler) {
override val key: String = "<Esc>"
override fun isHandlerEnabled(editor: Editor, dataContext: DataContext?): Boolean {
val ideaVimSupportDialog =
injector.globalIjOptions().ideavimsupport.contains(IjOptionConstants.ideavimsupport_dialog)
private val ideaVimSupportDialog
get() = injector.globalIjOptions().ideavimsupport.contains(IjOptionConstants.ideavimsupport_dialog)
override fun isHandlerEnabled(editor: Editor, dataContext: DataContext?): Boolean {
return editor.isPrimaryEditor() ||
EditorHelper.isFileEditor(editor) && !editor.vim.mode.inNormalMode ||
ideaVimSupportDialog && !editor.vim.mode.inNormalMode
EditorHelper.isFileEditor(editor) && vimStateNeedsToHandleEscape(editor) ||
ideaVimSupportDialog && vimStateNeedsToHandleEscape(editor)
}
private fun vimStateNeedsToHandleEscape(editor: Editor): Boolean {
return !editor.vim.mode.inNormalMode || KeyHandler.getInstance().keyHandlerState.mappingState.hasKeys
}
}

View File

@ -326,7 +326,7 @@ public class EditorHelper {
final int offset = y - ((screenHeight - lineHeight) / lineHeight / 2 * lineHeight);
@NotNull final VimEditor editor1 = new IjVimEditor(editor);
final int lastVisualLine = EngineEditorHelperKt.getVisualLineCount(editor1) - 1;
final int lastVisualLine = EngineEditorHelperKt.getVisualLineCount(editor1) + editor.getSettings().getAdditionalLinesCount();
final int offsetForLastLineAtBottom = getOffsetToScrollVisualLineToBottomOfScreen(editor, lastVisualLine);
// For `zz`, we want to use virtual space and move any line, including the last one, to the middle of the screen.

View File

@ -12,6 +12,7 @@ package com.maddyhome.idea.vim.helper
import com.intellij.codeWithMe.ClientId
import com.intellij.openapi.editor.Caret
import com.intellij.openapi.editor.CaretState
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.editor.ex.util.EditorUtil
import com.intellij.openapi.fileEditor.ex.FileEditorManagerEx
@ -20,6 +21,8 @@ import com.maddyhome.idea.vim.api.StringListOptionValue
import com.maddyhome.idea.vim.api.injector
import com.maddyhome.idea.vim.group.IjOptionConstants
import com.maddyhome.idea.vim.newapi.globalIjOptions
import com.maddyhome.idea.vim.newapi.vim
import com.maddyhome.idea.vim.state.mode.inBlockSelection
import java.awt.Component
import javax.swing.JComponent
import javax.swing.JTable
@ -96,3 +99,41 @@ internal val Caret.vimLine: Int
*/
internal val Editor.vimLine: Int
get() = this.caretModel.currentCaret.vimLine
internal inline fun Editor.runWithEveryCaretAndRestore(action: () -> Unit) {
val caretModel = this.caretModel
val carets = if (this.vim.inBlockSelection) null else caretModel.allCarets
if (carets == null || carets.size == 1) {
action()
}
else {
var initialDocumentSize = this.document.textLength
var documentSizeDifference = 0
val caretOffsets = carets.map { it.selectionStart to it.selectionEnd }
val restoredCarets = mutableListOf<CaretState>()
caretModel.removeSecondaryCarets()
for ((selectionStart, selectionEnd) in caretOffsets) {
if (selectionStart == selectionEnd) {
caretModel.primaryCaret.moveToOffset(selectionStart + documentSizeDifference)
}
else {
caretModel.primaryCaret.setSelection(
selectionStart + documentSizeDifference,
selectionEnd + documentSizeDifference
)
}
action()
restoredCarets.add(caretModel.caretsAndSelections.single())
val documentLength = this.document.textLength
documentSizeDifference += documentLength - initialDocumentSize
initialDocumentSize = documentLength
}
caretModel.caretsAndSelections = restoredCarets
}
}

View File

@ -20,6 +20,7 @@ import com.intellij.openapi.actionSystem.PlatformDataKeys
import com.intellij.openapi.actionSystem.ex.ActionUtil
import com.intellij.openapi.actionSystem.ex.ActionUtil.performDumbAwareWithCallbacks
import com.intellij.openapi.actionSystem.impl.ProxyShortcutSet
import com.intellij.openapi.actionSystem.impl.Utils
import com.intellij.openapi.application.ex.ApplicationManagerEx
import com.intellij.openapi.command.CommandProcessor
import com.intellij.openapi.command.UndoConfirmationPolicy
@ -60,6 +61,8 @@ internal class IjActionExecutor : VimActionExecutor {
get() = IdeActions.ACTION_EXPAND_REGION
override val ACTION_EXPAND_REGION_RECURSIVELY: String
get() = IdeActions.ACTION_EXPAND_REGION_RECURSIVELY
override val ACTION_EXPAND_COLLAPSE_TOGGLE: String
get() = "ExpandCollapseToggleAction"
/**
* Execute an action
@ -92,6 +95,7 @@ internal class IjActionExecutor : VimActionExecutor {
ActionManager.getInstance(),
0,
)
Utils.initUpdateSession(event)
// beforeActionPerformedUpdate should be called to update the action. It fixes some rider-specific problems.
// because rider use async update method. See VIM-1819.
// This method executes inside of lastUpdateAndCheckDumb

View File

@ -60,7 +60,7 @@ internal object ScrollViewHelper {
// that this needs to be replaced as a more or less dumb line for line rewrite.
val topLine = getVisualLineAtTopOfScreen(editor)
val bottomLine = getVisualLineAtBottomOfScreen(editor)
val lastLine = vimEditor.getVisualLineCount() - 1
val lastLine = vimEditor.getVisualLineCount() + editor.settings.additionalLinesCount
// We need the non-normalised value here, so we can handle cases such as so=999 to keep the current line centred
val scrollOffset = injector.options(vimEditor).scrolloff

View File

@ -28,6 +28,8 @@ import com.maddyhome.idea.vim.common.InsertSequence
import com.maddyhome.idea.vim.newapi.IjVimCaret
import com.maddyhome.idea.vim.newapi.globalIjOptions
import com.maddyhome.idea.vim.newapi.ij
import com.maddyhome.idea.vim.state.mode.SelectionType
import com.maddyhome.idea.vim.state.mode.inVisualMode
import com.maddyhome.idea.vim.undo.UndoRedoBase
/**
@ -66,15 +68,7 @@ internal class UndoRedoHelper : UndoRedoBase() {
// TODO refactor me after VIM-308 when restoring selection and caret movement will be ignored by undo
editor.runWithChangeTracking {
undoManager.undo(fileEditor)
// We execute undo one more time if the previous one just restored selection
if (!hasChanges && hasSelection(editor) && undoManager.isUndoAvailable(fileEditor)) {
undoManager.undo(fileEditor)
}
}
CommandProcessor.getInstance().runUndoTransparentAction {
removeSelections(editor)
restoreVisualMode(editor)
}
} else {
notifyAboutNewUndo(editor.ij.project)
@ -229,4 +223,21 @@ internal class UndoRedoHelper : UndoRedoBase() {
val hasChanges: Boolean
get() = changeListener.hasChanged || initialPath != editor.getPath()
}
private fun restoreVisualMode(editor: VimEditor) {
if (!editor.inVisualMode && editor.getSelectionModel().hasSelection()) {
val detectedMode = VimPlugin.getVisualMotion().autodetectVisualSubmode(editor)
// Visual block selection is restored into multiple carets, so multi-carets that form a block are always
// identified as visual block mode, leading to false positives.
// Since I use visual block mode much less often than multi-carets, this is a judgment call to never restore
// visual block mode.
val wantedMode = if (detectedMode == SelectionType.BLOCK_WISE)
SelectionType.CHARACTER_WISE
else
detectedMode
VimPlugin.getVisualMotion().enterVisualMode(editor, wantedMode)
}
}
}

View File

@ -18,15 +18,13 @@ import com.intellij.openapi.editor.VisualPosition
import com.intellij.openapi.editor.markup.RangeHighlighter
import com.intellij.openapi.util.Key
import com.intellij.openapi.util.UserDataHolder
import com.maddyhome.idea.vim.api.CaretRegisterStorageBase
import com.maddyhome.idea.vim.api.LocalMarkStorage
import com.maddyhome.idea.vim.api.SelectionInfo
import com.maddyhome.idea.vim.common.InsertSequence
import com.maddyhome.idea.vim.ex.ExOutputModel
import com.maddyhome.idea.vim.group.visual.VisualChange
import com.maddyhome.idea.vim.group.visual.vimLeadSelectionOffset
import com.maddyhome.idea.vim.common.InsertSequence
import com.maddyhome.idea.vim.newapi.vim
import com.maddyhome.idea.vim.state.VimStateMachine
import com.maddyhome.idea.vim.state.mode.Mode
import com.maddyhome.idea.vim.state.mode.SelectionType
import com.maddyhome.idea.vim.ui.ExOutputPanel
@ -96,7 +94,6 @@ internal var Caret.vimInsertStart: RangeMarker by userDataOr {
}
// TODO: Data could be lost during visual block motion
internal var Caret.registerStorage: CaretRegisterStorageBase? by userDataCaretToEditor()
internal var Caret.markStorage: LocalMarkStorage? by userDataCaretToEditor()
internal var Caret.lastSelectionInfo: SelectionInfo? by userDataCaretToEditor()

View File

@ -1,32 +0,0 @@
/*
* Copyright 2003-2023 The IdeaVim authors
*
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE.txt file or at
* https://opensource.org/licenses/MIT.
*/
package com.maddyhome.idea.vim.helper
import com.intellij.ide.plugins.StandalonePluginUpdateChecker
import com.intellij.openapi.components.Service
import com.intellij.openapi.components.service
import com.maddyhome.idea.vim.VimPlugin
import com.maddyhome.idea.vim.group.NotificationService
import com.maddyhome.idea.vim.icons.VimIcons
@Service(Service.Level.APP)
internal class VimStandalonePluginUpdateChecker : StandalonePluginUpdateChecker(
VimPlugin.getPluginId(),
updateTimestampProperty = PROPERTY_NAME,
NotificationService.IDEAVIM_STICKY_GROUP,
VimIcons.IDEAVIM,
) {
override fun skipUpdateCheck(): Boolean = VimPlugin.isNotEnabled() || "dev" in VimPlugin.getVersion()
companion object {
private const val PROPERTY_NAME = "ideavim.statistics.timestamp"
fun getInstance(): VimStandalonePluginUpdateChecker = service()
}
}

View File

@ -10,7 +10,6 @@ package com.maddyhome.idea.vim.listener
import com.intellij.execution.impl.ConsoleViewImpl
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.editor.EditorKind
import com.maddyhome.idea.vim.KeyHandler
import com.maddyhome.idea.vim.VimPlugin
import com.maddyhome.idea.vim.api.ExecutionContext
@ -18,7 +17,6 @@ import com.maddyhome.idea.vim.api.VimEditor
import com.maddyhome.idea.vim.api.injector
import com.maddyhome.idea.vim.command.OperatorArguments
import com.maddyhome.idea.vim.common.EditorListener
import com.maddyhome.idea.vim.helper.EditorHelper
import com.maddyhome.idea.vim.helper.inInsertMode
import com.maddyhome.idea.vim.newapi.ij
import com.maddyhome.idea.vim.state.mode.Mode
@ -63,13 +61,7 @@ class IJEditorFocusListener : EditorListener {
val context: ExecutionContext = injector.executionContextManager.getEditorExecutionContext(editor)
VimPlugin.getChange().insertBeforeCursor(editor, context)
}
if (!ijEditor.isViewer &&
!EditorHelper.isFileEditor(ijEditor) &&
ijEditor.document.isWritable &&
!ijEditor.inInsertMode && ijEditor.editorKind != EditorKind.DIFF
) {
switchToInsertMode.run()
} else if (!ijEditor.document.isWritable) {
if (!ijEditor.document.isWritable) {
val context: ExecutionContext = injector.executionContextManager.getEditorExecutionContext(editor)
val mode = injector.vimState.mode
when (mode) {

View File

@ -28,6 +28,7 @@ import com.intellij.openapi.actionSystem.CommonDataKeys
import com.intellij.openapi.actionSystem.ex.AnActionListener
import com.intellij.openapi.actionSystem.impl.ProxyShortcutSet
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.editor.impl.ScrollingModelImpl
import com.intellij.openapi.keymap.KeymapManager
import com.intellij.openapi.project.DumbAwareToggleAction
import com.intellij.openapi.util.TextRange
@ -58,6 +59,7 @@ internal object IdeaSpecifics {
private val surrounderAction =
"com.intellij.codeInsight.generation.surroundWith.SurroundWithHandler\$InvokeSurrounderAction"
private var editor: Editor? = null
private var caretOffset = -1
private var completionPrevDocumentLength: Int? = null
private var completionPrevDocumentOffset: Int? = null
@ -67,6 +69,7 @@ internal object IdeaSpecifics {
val hostEditor = event.dataContext.getData(CommonDataKeys.HOST_EDITOR)
if (hostEditor != null) {
editor = hostEditor
caretOffset = hostEditor.caretModel.offset
}
val isVimAction = (action as? AnActionWrapper)?.delegate is VimShortcutKeyAction
@ -115,7 +118,8 @@ internal object IdeaSpecifics {
if (VimPlugin.isNotEnabled()) return
val editor = editor
if (editor != null && action is ChooseItemAction && injector.registerGroup.isRecording) {
if (editor != null) {
if (action is ChooseItemAction && injector.registerGroup.isRecording) {
val prevDocumentLength = completionPrevDocumentLength
val prevDocumentOffset = completionPrevDocumentOffset
@ -150,7 +154,21 @@ internal object IdeaSpecifics {
}
//endregion
if (caretOffset != -1 && caretOffset != editor.caretModel.offset) {
val scrollModel = editor.scrollingModel as ScrollingModelImpl
if (scrollModel.isScrollingNow) {
val v = scrollModel.verticalScrollOffset
val h = scrollModel.horizontalScrollOffset
scrollModel.finishAnimation()
scrollModel.scroll(h, v)
scrollModel.finishAnimation()
}
injector.scroll.scrollCaretIntoView(editor.vim)
}
}
this.editor = null
this.caretOffset = -1
}
}

View File

@ -35,6 +35,7 @@ import com.intellij.openapi.editor.ex.DocumentEx
import com.intellij.openapi.editor.ex.EditorEventMulticasterEx
import com.intellij.openapi.editor.ex.FocusChangeListener
import com.intellij.openapi.editor.impl.EditorComponentImpl
import com.intellij.openapi.editor.impl.EditorImpl
import com.intellij.openapi.fileEditor.FileEditorManager
import com.intellij.openapi.fileEditor.FileEditorManagerEvent
import com.intellij.openapi.fileEditor.FileEditorManagerListener
@ -45,11 +46,14 @@ import com.intellij.openapi.fileEditor.ex.FileEditorWithProvider
import com.intellij.openapi.fileEditor.impl.EditorComposite
import com.intellij.openapi.fileEditor.impl.EditorWindow
import com.intellij.openapi.project.ProjectManager
import com.intellij.openapi.rd.createLifetime
import com.intellij.openapi.rd.createNestedDisposable
import com.intellij.openapi.util.Disposer
import com.intellij.openapi.util.Key
import com.intellij.openapi.util.removeUserData
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.util.ExceptionUtil
import com.jetbrains.rd.util.lifetime.Lifetime
import com.maddyhome.idea.vim.EventFacade
import com.maddyhome.idea.vim.KeyHandler
import com.maddyhome.idea.vim.VimKeyListener
@ -79,7 +83,6 @@ import com.maddyhome.idea.vim.handler.keyCheckRequests
import com.maddyhome.idea.vim.helper.CaretVisualAttributesListener
import com.maddyhome.idea.vim.helper.GuicursorChangeListener
import com.maddyhome.idea.vim.helper.StrictMode
import com.maddyhome.idea.vim.helper.VimStandalonePluginUpdateChecker
import com.maddyhome.idea.vim.helper.exitSelectMode
import com.maddyhome.idea.vim.helper.exitVisualMode
import com.maddyhome.idea.vim.helper.forceBarCursor
@ -95,6 +98,7 @@ import com.maddyhome.idea.vim.newapi.IjVimSearchGroup
import com.maddyhome.idea.vim.newapi.InsertTimeRecorder
import com.maddyhome.idea.vim.newapi.ij
import com.maddyhome.idea.vim.newapi.vim
import com.maddyhome.idea.vim.state.mode.Mode
import com.maddyhome.idea.vim.state.mode.inSelectMode
import com.maddyhome.idea.vim.state.mode.selectionType
import com.maddyhome.idea.vim.ui.ShowCmdOptionChangeListener
@ -103,7 +107,6 @@ import com.maddyhome.idea.vim.ui.widgets.macro.MacroWidgetListener
import com.maddyhome.idea.vim.ui.widgets.macro.macroWidgetOptionListener
import com.maddyhome.idea.vim.ui.widgets.mode.listeners.ModeWidgetListener
import com.maddyhome.idea.vim.ui.widgets.mode.modeWidgetOptionListener
import com.maddyhome.idea.vim.vimDisposable
import java.awt.event.MouseAdapter
import java.awt.event.MouseEvent
import javax.swing.SwingUtilities
@ -285,12 +288,10 @@ internal object VimListenerManager {
// TODO: If the user changes the 'ideavimsupport' option, existing editors won't be initialised
if (vimDisabled(editor)) return
// As I understand, there is no need to pass a disposable that also disposes on editor close
// because all editor resources will be garbage collected anyway on editor close
// Note that this uses the plugin's main disposable, rather than VimPlugin.onOffDisposable, because we don't need
// to - we explicitly call VimListenerManager.removeAll from VimPlugin.turnOffPlugin, and this disposes each
// editor's disposable individually.
val disposable = editor.project?.vimDisposable ?: return
val pluginLifetime = VimPlugin.getInstance().createLifetime()
val editorLifetime = (editor as EditorImpl).disposable.createLifetime()
val disposable =
Lifetime.intersect(pluginLifetime, editorLifetime).createNestedDisposable("MyLifetimedDisposable")
// Protect against double initialisation
if (editor.getUserData(editorListenersDisposableKey) != null) {
@ -387,6 +388,16 @@ internal object VimListenerManager {
// We can't rely on being passed a non-null editor, so check for Code With Me scenarios explicitly
if (VimPlugin.isNotEnabled() || !ClientId.isCurrentlyUnderLocalId) return
val newEditor = event.newEditor
if (newEditor is TextEditor) {
val editor = newEditor.editor
if (editor.isInsertMode) {
editor.vim.mode = Mode.NORMAL()
KeyHandler.getInstance().reset(editor.vim)
}
injector.scroll.scrollCaretIntoView(editor.vim)
}
MotionGroup.fileEditorManagerSelectionChangedCallback(event)
FileGroup.fileEditorManagerSelectionChangedCallback(event)
VimPlugin.getSearch().fileEditorManagerSelectionChangedCallback(event)
@ -458,8 +469,6 @@ internal object VimListenerManager {
event.editor.putUserData(openingEditorKey, OpeningEditor(openingEditor, owningEditorWindow, isPreview, canBeReused))
}
VimStandalonePluginUpdateChecker.getInstance().pluginUsed()
}
override fun editorReleased(event: EditorFactoryEvent) {
@ -739,7 +748,7 @@ internal object VimListenerManager {
injector.commandLine.getActiveCommandLine()?.close(refocusOwningEditor = true, resetCaret = false)
injector.modalInput.getCurrentModalInput()?.deactivate(refocusOwningEditor = true, resetCaret = false)
ExOutputModel.tryGetInstance(editor)?.close()
injector.outputPanel.getCurrentOutputPanel()?.close()
val caretModel = editor.caretModel
if (editor.vim.mode.selectionType != null) {
@ -768,7 +777,7 @@ internal object VimListenerManager {
injector.commandLine.getActiveCommandLine()?.close(refocusOwningEditor = true, resetCaret = false)
injector.modalInput.getCurrentModalInput()?.deactivate(refocusOwningEditor = true, resetCaret = false)
ExOutputModel.getInstance(event.editor).close()
injector.outputPanel.getCurrentOutputPanel()?.close()
}
}
}

View File

@ -14,6 +14,9 @@ import com.maddyhome.idea.vim.common.LiveRange
internal class IjLiveRange(val marker: RangeMarker) : LiveRange {
override val startOffset: Int
get() = marker.startOffset
override val endOffset: Int
get() = marker.endOffset
}
val RangeMarker.vim: LiveRange

View File

@ -12,8 +12,6 @@ import com.intellij.openapi.editor.Caret
import com.intellij.openapi.editor.LogicalPosition
import com.intellij.openapi.editor.VisualPosition
import com.maddyhome.idea.vim.api.BufferPosition
import com.maddyhome.idea.vim.api.CaretRegisterStorage
import com.maddyhome.idea.vim.api.CaretRegisterStorageBase
import com.maddyhome.idea.vim.api.ImmutableVimCaret
import com.maddyhome.idea.vim.api.LocalMarkStorage
import com.maddyhome.idea.vim.api.SelectionInfo
@ -29,7 +27,6 @@ import com.maddyhome.idea.vim.helper.insertHistory
import com.maddyhome.idea.vim.helper.lastSelectionInfo
import com.maddyhome.idea.vim.helper.markStorage
import com.maddyhome.idea.vim.helper.moveToInlayAwareOffset
import com.maddyhome.idea.vim.helper.registerStorage
import com.maddyhome.idea.vim.helper.resetVimLastColumn
import com.maddyhome.idea.vim.helper.vimInsertStart
import com.maddyhome.idea.vim.helper.vimLastColumn
@ -41,18 +38,6 @@ import com.maddyhome.idea.vim.state.mode.SelectionType
internal class IjVimCaret(val caret: Caret) : VimCaretBase() {
override val registerStorage: CaretRegisterStorage
get() {
var storage = this.caret.registerStorage
if (storage == null) {
initInjector() // To initialize injector used in CaretRegisterStorageBase
storage = CaretRegisterStorageBase(this)
this.caret.registerStorage = storage
} else if (storage.caret != this) {
storage.caret = this
}
return storage
}
override val markStorage: LocalMarkStorage
get() {
var storage = this.caret.markStorage

View File

@ -165,21 +165,38 @@ internal class IjVimEditor(editor: Editor) : MutableLinearEditor, VimEditorBase(
return editor.caretModel.allCarets.map { IjVimCaret(it) }
}
override var isFirstCaret = true
override var isReversingCarets = false
@Suppress("ideavimRunForEachCaret")
override fun forEachCaret(action: (VimCaret) -> Unit) {
if (editor.vim.inBlockSelection) {
action(IjVimCaret(editor.caretModel.primaryCaret))
} else {
try {
editor.caretModel.runForEachCaret({
if (it.isValid) {
action(IjVimCaret(it))
isFirstCaret = false
}
}, false)
} finally {
isFirstCaret = true
}
}
}
override fun forEachNativeCaret(action: (VimCaret) -> Unit, reverse: Boolean) {
editor.caretModel.runForEachCaret({ action(IjVimCaret(it)) }, reverse)
isReversingCarets = reverse
try {
editor.caretModel.runForEachCaret({
action(IjVimCaret(it))
isFirstCaret = false
}, reverse)
} finally {
isFirstCaret = true
isReversingCarets = false
}
}
override fun isInForEachCaretScope(): Boolean {

View File

@ -1,718 +0,0 @@
/*
* Copyright 2003-2023 The IdeaVim authors
*
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE.txt file or at
* https://opensource.org/licenses/MIT.
*/
/**
* IdeaVim command index.
*
*
* 1. Insert mode
*
* tag action
* -------------------------------------------------------------------------------------------------------------------
*
* |i_CTRL-@| {@link com.maddyhome.idea.vim.action.change.insert.InsertPreviousInsertExitAction}
* |i_CTRL-A| {@link com.maddyhome.idea.vim.action.change.insert.InsertPreviousInsertAction}
* |i_CTRL-C| {@link com.maddyhome.idea.vim.action.change.insert.InsertExitModeAction}
* |i_CTRL-D| {@link com.maddyhome.idea.vim.action.change.shift.ShiftLeftLinesAction}
* |i_CTRL-E| {@link com.maddyhome.idea.vim.action.change.insert.InsertCharacterBelowCursorAction}
* |i_CTRL-G_j| TO BE IMPLEMENTED
* |i_CTRL-G_k| TO BE IMPLEMENTED
* |i_CTRL-G_u| TO BE IMPLEMENTED
* |i_<BS>| {@link com.maddyhome.idea.vim.action.editor.VimEditorBackSpace}
* |i_digraph| IdeaVim enter digraph
* |i_CTRL-H| IntelliJ editor backspace
* |i_<Tab>| {@link com.maddyhome.idea.vim.action.editor.VimEditorTab}
* |i_CTRL-I| IntelliJ editor tab
* |i_<NL>| {@link com.maddyhome.idea.vim.action.change.insert.InsertEnterAction}
* |i_CTRL-J| TO BE IMPLEMENTED
* |i_CTRL-K| {@link com.maddyhome.idea.vim.action.change.insert.InsertCompletedDigraphAction}
* |i_CTRL-L| TO BE IMPLEMENTED
* |i_<CR>| {@link com.maddyhome.idea.vim.action.change.insert.InsertEnterAction}
* |i_CTRL-M| {@link com.maddyhome.idea.vim.action.change.insert.InsertEnterAction}
* |i_CTRL-N| {@link com.maddyhome.idea.vim.action.window.LookupDownAction}
* |i_CTRL-O| {@link com.maddyhome.idea.vim.action.change.insert.InsertSingleCommandAction}
* |i_CTRL-P| {@link com.maddyhome.idea.vim.action.window.LookupUpAction}
* |i_CTRL-Q| TO BE IMPLEMENTED
* |i_CTRL-R| {@link com.maddyhome.idea.vim.action.change.insert.InsertRegisterAction}
* |i_CTRL-R_CTRL-R| TO BE IMPLEMENTED
* |i_CTRL-R_CTRL-O| TO BE IMPLEMENTED
* |i_CTRL-R_CTRL-P| TO BE IMPLEMENTED
* |i_CTRL-T| {@link com.maddyhome.idea.vim.action.change.shift.ShiftRightLinesAction}
* |i_CTRL-U| {@link com.maddyhome.idea.vim.action.change.insert.InsertDeleteInsertedTextAction}
* |i_CTRL-V| {@link com.maddyhome.idea.vim.action.change.insert.InsertCompletedLiteralAction}
* |i_CTRL-V_digit| {@link com.maddyhome.idea.vim.action.change.insert.InsertCompletedLiteralAction}
* |i_CTRL-W| {@link com.maddyhome.idea.vim.action.change.insert.InsertDeletePreviousWordAction}
* |i_CTRL-X| TO BE IMPLEMENTED
* |i_CTRL-Y| {@link com.maddyhome.idea.vim.action.change.insert.InsertCharacterAboveCursorAction}
* |i_CTRL-Z| TO BE IMPLEMENTED
* |i_<Esc>| {@link com.maddyhome.idea.vim.action.change.insert.InsertExitModeAction}
* |i_CTRL-[| {@link com.maddyhome.idea.vim.action.change.insert.InsertExitModeAction}
* |i_CTRL-\_CTRL-N| {@link com.maddyhome.idea.vim.action.ResetModeAction}
* |i_CTRL-\_CTRL-G| TO BE IMPLEMENTED
* |i_CTRL-]} TO BE IMPLEMENTED
* |i_CTRL-^| TO BE IMPLEMENTED
* |i_CTRL-_| TO BE IMPLEMENTED
* |i_0_CTRL-D| TO BE IMPLEMENTED
* |i_^_CTRL-D| TO BE IMPLEMENTED
* |i_<Del>| {@link com.maddyhome.idea.vim.action.editor.VimEditorDelete}
* |i_<Left>| {@link com.maddyhome.idea.vim.action.motion.leftright.MotionLeftInsertModeAction}
* |i_<S-Left>| {@link com.maddyhome.idea.vim.action.motion.text.MotionWordLeftInsertAction}
* |i_<C-Left>| {@link com.maddyhome.idea.vim.action.motion.text.MotionWordLeftInsertAction}
* |i_<Right>| {@link com.maddyhome.idea.vim.action.motion.leftright.MotionRightInsertAction}
* |i_<S-Right>| {@link com.maddyhome.idea.vim.action.motion.text.MotionWordRightInsertAction}
* |i_<C-Right>| {@link com.maddyhome.idea.vim.action.motion.text.MotionWordRightInsertAction}
* |i_<Up>| {@link com.maddyhome.idea.vim.action.editor.VimEditorUp}
* |i_<S-Up>| {@link com.maddyhome.idea.vim.action.motion.scroll.MotionScrollPageUpInsertModeAction}
* |i_<Down>| {@link com.maddyhome.idea.vim.action.editor.VimEditorDown}
* |i_<S-Down>| {@link com.maddyhome.idea.vim.action.motion.scroll.MotionScrollPageDownInsertModeAction}
* |i_<Home>| {@link com.maddyhome.idea.vim.action.motion.leftright.MotionFirstColumnInsertModeAction}
* |i_<C-Home>| {@link com.maddyhome.idea.vim.action.motion.updown.MotionGotoLineFirstInsertAction}
* |i_<End>| {@link com.maddyhome.idea.vim.action.motion.leftright.MotionLastColumnInsertAction}
* |i_<C-End>| {@link com.maddyhome.idea.vim.action.motion.updown.MotionGotoLineLastEndInsertAction}
* |i_<Insert>| {@link com.maddyhome.idea.vim.action.change.insert.InsertInsertAction}
* |i_<PageUp>| {@link com.maddyhome.idea.vim.action.motion.scroll.MotionScrollPageUpInsertModeAction}
* |i_<PageDown>| {@link com.maddyhome.idea.vim.action.motion.scroll.MotionScrollPageDownInsertModeAction}
* |i_<F1>| IntelliJ help
* |i_<Insert>| IntelliJ editor toggle insert/replace
* |i_CTRL-X_index| TO BE IMPLEMENTED
*
*
* 2. Normal mode
*
* tag action
* -------------------------------------------------------------------------------------------------------------------
*
* |CTRL-A| {@link com.maddyhome.idea.vim.action.change.change.number.ChangeNumberIncAction}
* |CTRL-B| {@link com.maddyhome.idea.vim.action.motion.scroll.MotionScrollPageUpAction}
* |CTRL-C| TO BE IMPLEMENTED
* |CTRL-D| {@link com.maddyhome.idea.vim.action.motion.scroll.MotionScrollHalfPageDownAction}
* |CTRL-E| {@link com.maddyhome.idea.vim.action.motion.scroll.MotionScrollLineDownAction}
* |CTRL-F| {@link com.maddyhome.idea.vim.action.motion.scroll.MotionScrollPageDownAction}
* |CTRL-G| {@link com.maddyhome.idea.vim.action.file.FileGetFileInfoAction}
* |<BS>| {@link com.maddyhome.idea.vim.action.motion.leftright.MotionBackspaceAction}
* |CTRL-H| {@link com.maddyhome.idea.vim.action.motion.leftright.MotionBackspaceAction}
* |<Tab>| TO BE IMPLEMENTED
* |CTRL-I| {@link com.maddyhome.idea.vim.action.motion.mark.MotionJumpNextAction}
* |<NL>| {@link com.maddyhome.idea.vim.action.motion.updown.MotionDownNotLineWiseAction}
* |CTRL-J| TO BE IMPLEMENTED
* |CTRL-L| not applicable
* |<CR>| {@link com.maddyhome.idea.vim.action.motion.updown.EnterNormalAction}
* |CTRL-M| {@link com.maddyhome.idea.vim.action.motion.updown.MotionDownFirstNonSpaceAction}
* |CTRL-N| {@link com.maddyhome.idea.vim.action.motion.updown.MotionDownCtrlNAction}
* |CTRL-O| {@link com.maddyhome.idea.vim.action.motion.mark.MotionJumpPreviousAction}
* |CTRL-P| {@link com.maddyhome.idea.vim.action.motion.updown.MotionUpCtrlPAction}
* |CTRL-R| {@link com.maddyhome.idea.vim.action.change.RedoAction}
* |CTRL-T| TO BE IMPLEMENTED
* |CTRL-U| {@link com.maddyhome.idea.vim.action.motion.scroll.MotionScrollHalfPageUpAction}
* |CTRL-V| {@link com.maddyhome.idea.vim.action.motion.visual.VisualToggleBlockModeAction}
* |CTRL-W| see window commands
* |CTRL-X| {@link com.maddyhome.idea.vim.action.change.change.number.ChangeNumberDecAction}
* |CTRL-Y| {@link com.maddyhome.idea.vim.action.motion.scroll.MotionScrollLineUpAction}
* |CTRL-Z| TO BE IMPLEMENTED
* |CTRL-]| {@link com.maddyhome.idea.vim.action.motion.search.GotoDeclarationAction}
* |CTRL-6| {@link com.maddyhome.idea.vim.action.file.FilePreviousAction}
* |CTRL-\CTRL-N| {@link com.maddyhome.idea.vim.action.ResetModeAction}
* |<Space>| {@link com.maddyhome.idea.vim.action.motion.leftright.MotionSpaceAction}
* |!| {@link com.maddyhome.idea.vim.action.change.change.FilterMotionAction}
* |!!| translated to !_
* |quote| handled by command key parser
* |#| {@link com.maddyhome.idea.vim.action.motion.search.SearchWholeWordBackwardAction}
* |$| {@link com.maddyhome.idea.vim.action.motion.leftright.MotionLastColumnAction}
* |%| {@link com.maddyhome.idea.vim.action.motion.updown.MotionPercentOrMatchAction}
* |&| {@link com.maddyhome.idea.vim.action.change.change.ChangeLastSearchReplaceAction}
* |'| {@link com.maddyhome.idea.vim.action.motion.mark.MotionGotoMarkLineAction}
* |''| ?
* ...
* |(| {@link com.maddyhome.idea.vim.action.motion.text.MotionSentencePreviousStartAction}
* |)| {@link com.maddyhome.idea.vim.action.motion.text.MotionSentenceNextStartAction}
* |star| {@link com.maddyhome.idea.vim.action.motion.search.SearchWholeWordForwardAction}
* |+| {@link com.maddyhome.idea.vim.action.motion.updown.MotionDownFirstNonSpaceAction}
* |,| {@link com.maddyhome.idea.vim.action.motion.leftright.MotionLastMatchCharReverseAction}
* |-| {@link com.maddyhome.idea.vim.action.motion.updown.MotionUpFirstNonSpaceAction}
* |.| {@link com.maddyhome.idea.vim.action.change.RepeatChangeAction}
* |/| {@link com.maddyhome.idea.vim.action.motion.search.SearchEntryFwdAction}
* |:| {@link com.maddyhome.idea.vim.action.ex.ExEntryAction}
* |;| {@link com.maddyhome.idea.vim.action.motion.leftright.MotionLastMatchCharAction}
* |<| {@link com.maddyhome.idea.vim.action.change.shift.ShiftLeftMotionAction}
* |<<| translated to <_
* |=| {@link com.maddyhome.idea.vim.action.change.shift.AutoIndentMotionAction}
* |==| translated to =_
* |>| {@link com.maddyhome.idea.vim.action.change.shift.ShiftRightMotionAction}
* |>>| translated to >_
* |?| {@link com.maddyhome.idea.vim.action.motion.search.SearchEntryRevAction}
* |@| {@link com.maddyhome.idea.vim.action.macro.PlaybackRegisterAction}
* |A| {@link com.maddyhome.idea.vim.action.change.insert.InsertAfterLineEndAction}
* |B| {@link com.maddyhome.idea.vim.action.motion.text.MotionBigWordLeftAction}
* |C| {@link com.maddyhome.idea.vim.action.change.change.ChangeEndOfLineAction}
* |D| {@link com.maddyhome.idea.vim.action.change.delete.DeleteEndOfLineAction}
* |E| {@link com.maddyhome.idea.vim.action.motion.text.MotionBigWordEndRightAction}
* |F| {@link com.maddyhome.idea.vim.action.motion.leftright.MotionLeftMatchCharAction}
* |G| {@link com.maddyhome.idea.vim.action.motion.updown.MotionGotoLineLastAction}
* |H| {@link com.maddyhome.idea.vim.action.motion.screen.MotionFirstScreenLineAction}
* |H| {@link com.maddyhome.idea.vim.action.motion.screen.MotionOpPendingFirstScreenLineAction}
* |I| {@link com.maddyhome.idea.vim.action.change.insert.InsertBeforeFirstNonBlankAction}
* |J| {@link com.maddyhome.idea.vim.action.change.delete.DeleteJoinLinesSpacesAction}
* |K| {@link com.maddyhome.idea.vim.action.editor.VimQuickJavaDoc}
* |L| {@link com.maddyhome.idea.vim.action.motion.screen.MotionLastScreenLineAction}
* |L| {@link com.maddyhome.idea.vim.action.motion.screen.MotionOpPendingLastScreenLineAction}
* |M| {@link com.maddyhome.idea.vim.action.motion.screen.MotionMiddleScreenLineAction}
* |N| {@link com.maddyhome.idea.vim.action.motion.search.SearchAgainPreviousAction}
* |O| {@link com.maddyhome.idea.vim.action.change.insert.InsertNewLineAboveAction}
* |P| {@link com.maddyhome.idea.vim.action.copy.PutTextBeforeCursorAction}
* |Q| TO BE IMPLEMENTED
* |R| {@link com.maddyhome.idea.vim.action.change.change.ChangeReplaceAction}
* |S| {@link com.maddyhome.idea.vim.action.change.change.ChangeLineAction}
* |T| {@link com.maddyhome.idea.vim.action.motion.leftright.MotionLeftTillMatchCharAction}
* |U| ?
* |V| {@link com.maddyhome.idea.vim.action.motion.visual.VisualToggleLineModeAction}
* |W| {@link com.maddyhome.idea.vim.action.motion.text.MotionBigWordRightAction}
* |X| {@link com.maddyhome.idea.vim.action.change.delete.DeleteCharacterLeftAction}
* |Y| {@link com.maddyhome.idea.vim.action.copy.YankLineAction}
* |ZZ| {@link com.maddyhome.idea.vim.action.file.FileSaveCloseAction}
* |ZQ| {@link com.maddyhome.idea.vim.action.file.FileSaveCloseAction}
* |[| see bracket commands
* |]| see bracket commands
* |^| {@link com.maddyhome.idea.vim.action.motion.leftright.MotionFirstNonSpaceAction}
* |_| {@link com.maddyhome.idea.vim.action.motion.updown.MotionDownLess1FirstNonSpaceAction}
* |`| {@link com.maddyhome.idea.vim.action.motion.mark.MotionGotoMarkAction}
* |``| ?
* ...
* |0| {@link com.maddyhome.idea.vim.action.motion.leftright.MotionFirstColumnAction}
* |a| {@link com.maddyhome.idea.vim.action.change.insert.InsertAfterCursorAction}
* |b| {@link com.maddyhome.idea.vim.action.motion.text.MotionWordLeftAction}
* |c| {@link com.maddyhome.idea.vim.action.change.change.ChangeMotionAction}
* |cc| translated to c_
* |d| {@link com.maddyhome.idea.vim.action.change.delete.DeleteMotionAction}
* |dd| translated to d_
* |do| TO BE IMPLEMENTED
* |dp| TO BE IMPLEMENTED
* |e| {@link com.maddyhome.idea.vim.action.motion.text.MotionWordEndRightAction}
* |f| {@link com.maddyhome.idea.vim.action.motion.leftright.MotionRightMatchCharAction}
* |g| see commands starting with 'g'
* |h| {@link com.maddyhome.idea.vim.action.motion.leftright.MotionLeftAction}
* |i| {@link com.maddyhome.idea.vim.action.change.insert.InsertBeforeCursorAction}
* |j| {@link com.maddyhome.idea.vim.action.motion.updown.MotionDownAction}
* |k| {@link com.maddyhome.idea.vim.action.motion.updown.MotionUpAction}
* |l| {@link com.maddyhome.idea.vim.action.motion.leftright.MotionRightAction}
* |m| {@link com.maddyhome.idea.vim.action.motion.mark.MotionMarkAction}
* |n| {@link com.maddyhome.idea.vim.action.motion.search.SearchAgainNextAction}
* |o| {@link com.maddyhome.idea.vim.action.change.insert.InsertNewLineBelowAction}
* |p| {@link com.maddyhome.idea.vim.action.copy.PutTextAfterCursorAction}
* |q| {@link com.maddyhome.idea.vim.action.macro.ToggleRecordingAction}
* |r| {@link com.maddyhome.idea.vim.action.change.change.ChangeCharacterAction}
* |s| {@link com.maddyhome.idea.vim.action.change.change.ChangeCharactersAction}
* |t| {@link com.maddyhome.idea.vim.action.motion.leftright.MotionRightTillMatchCharAction}
* |u| {@link com.maddyhome.idea.vim.action.change.UndoAction}
* |v| {@link com.maddyhome.idea.vim.action.motion.visual.VisualToggleCharacterModeAction}
* |w| {@link com.maddyhome.idea.vim.action.motion.text.MotionWordRightAction}
* |x| {@link com.maddyhome.idea.vim.action.change.delete.DeleteCharacterRightAction}
* |y| {@link com.maddyhome.idea.vim.action.copy.YankMotionAction}
* |yy| translated to y_
* |z| see commands starting with 'z'
* |{| {@link com.maddyhome.idea.vim.action.motion.text.MotionParagraphPreviousAction}
* |bar| {@link com.maddyhome.idea.vim.action.motion.leftright.MotionColumnAction}
* |}| {@link com.maddyhome.idea.vim.action.motion.text.MotionParagraphNextAction}
* |~| {@link com.maddyhome.idea.vim.action.change.change.ChangeCaseToggleCharacterAction}
* |<C-End>| {@link com.maddyhome.idea.vim.action.motion.updown.MotionGotoLineLastEndAction}
* |<C-Home>| {@link com.maddyhome.idea.vim.action.motion.updown.MotionGotoLineFirstAction}
* |<C-Left>| {@link com.maddyhome.idea.vim.action.motion.text.MotionWordLeftAction}
* |<C-Right>| {@link com.maddyhome.idea.vim.action.motion.text.MotionWordRightAction}
* |<C-Down>| {@link com.maddyhome.idea.vim.action.motion.scroll.CtrlDownAction}
* |<C-Up>| {@link com.maddyhome.idea.vim.action.motion.scroll.CtrlUpAction}
* |<Del>| {@link com.maddyhome.idea.vim.action.change.delete.DeleteCharacterAction}
* |<Down>| {@link com.maddyhome.idea.vim.action.motion.updown.MotionArrowDownAction}
* |<End>| {@link com.maddyhome.idea.vim.action.motion.leftright.MotionEndAction}
* |<F1>| IntelliJ help
* |<Home>| {@link com.maddyhome.idea.vim.action.motion.leftright.MotionHomeAction}
* |<Insert>| {@link com.maddyhome.idea.vim.action.change.insert.InsertBeforeCursorAction}
* |<Left>| {@link com.maddyhome.idea.vim.action.motion.leftright.MotionArrowLeftAction}
* |<PageDown>| {@link com.maddyhome.idea.vim.action.motion.scroll.MotionScrollPageDownAction}
* |<PageUp>| {@link com.maddyhome.idea.vim.action.motion.scroll.MotionScrollPageUpAction}
* |<Right>| {@link com.maddyhome.idea.vim.action.motion.leftright.MotionArrowRightAction}
* |<S-Down>| {@link com.maddyhome.idea.vim.action.motion.updown.MotionShiftDownAction}
* |<S-Left>| {@link com.maddyhome.idea.vim.action.motion.leftright.MotionShiftLeftAction}
* |<S-Right>| {@link com.maddyhome.idea.vim.action.motion.leftright.MotionShiftRightAction}
* |<S-Up>| {@link com.maddyhome.idea.vim.action.motion.updown.MotionShiftUpAction}
* |<S-Home>| {@link com.maddyhome.idea.vim.action.motion.leftright.MotionShiftHomeAction}
* |<S-End>| {@link com.maddyhome.idea.vim.action.motion.leftright.MotionShiftEndAction}
* |<Up>| {@link com.maddyhome.idea.vim.action.motion.updown.MotionArrowUpAction}
*
*
* 2.1. Text objects
*
* Text object commands are listed in the visual mode section.
*
*
* 2.2. Window commands
*
* tag action
* -------------------------------------------------------------------------------------------------------------------
*
* |CTRL-W_+| TO BE IMPLEMENTED
* |CTRL-W_-| TO BE IMPLEMENTED
* |CTRL-W_<| TO BE IMPLEMENTED
* |CTRL-W_=| TO BE IMPLEMENTED
* |CTRL-W_>| TO BE IMPLEMENTED
* |CTRL-W_H| TO BE IMPLEMENTED
* |CTRL-W_J| TO BE IMPLEMENTED
* |CTRL-W_K| TO BE IMPLEMENTED
* |CTRL-W_L| TO BE IMPLEMENTED
* |CTRL-W_P| TO BE IMPLEMENTED
* |CTRL-W_R| TO BE IMPLEMENTED
* |CTRL-W_S| {@link com.maddyhome.idea.vim.action.window.HorizontalSplitAction}
* |CTRL-W_T| TO BE IMPLEMENTED
* |CTRL-W_W| {@link com.maddyhome.idea.vim.action.window.WindowPrevAction}
* |CTRL-W_]| TO BE IMPLEMENTED
* |CTRL-W_^| TO BE IMPLEMENTED
* |CTRL-W__| TO BE IMPLEMENTED
* |CTRL-W_b| TO BE IMPLEMENTED
* |CTRL-W_c| {@link com.maddyhome.idea.vim.action.window.CloseWindowAction}
* |CTRL-W_d| TO BE IMPLEMENTED
* |CTRL-W_f| TO BE IMPLEMENTED
* |CTRL-W-F| TO BE IMPLEMENTED
* |CTRL-W-g]| TO BE IMPLEMENTED
* |CTRL-W-g}| TO BE IMPLEMENTED
* |CTRL-W-gf| TO BE IMPLEMENTED
* |CTRL-W-gF| TO BE IMPLEMENTED
* |CTRL-W_h| {@link com.maddyhome.idea.vim.action.window.WindowLeftAction}
* |CTRL-W_i| TO BE IMPLEMENTED
* |CTRL-W_j| {@link com.maddyhome.idea.vim.action.window.WindowDownAction}
* |CTRL-W_k| {@link com.maddyhome.idea.vim.action.window.WindowUpAction}
* |CTRL-W_l| {@link com.maddyhome.idea.vim.action.window.WindowRightAction}
* |CTRL-W_n| TO BE IMPLEMENTED
* |CTRL-W_o| {@link com.maddyhome.idea.vim.action.window.WindowOnlyAction}
* |CTRL-W_p| TO BE IMPLEMENTED
* |CTRL-W_q| TO BE IMPLEMENTED
* |CTRL-W_r| TO BE IMPLEMENTED
* |CTRL-W_s| {@link com.maddyhome.idea.vim.action.window.HorizontalSplitAction}
* |CTRL-W_t| TO BE IMPLEMENTED
* |CTRL-W_v| {@link com.maddyhome.idea.vim.action.window.VerticalSplitAction}
* |CTRL-W_w| {@link com.maddyhome.idea.vim.action.window.WindowNextAction}
* |CTRL-W_x| TO BE IMPLEMENTED
* |CTRL-W_z| TO BE IMPLEMENTED
* |CTRL-W_bar| TO BE IMPLEMENTED
* |CTRL-W_}| TO BE IMPLEMENTED
* |CTRL-W_<Down>| {@link com.maddyhome.idea.vim.action.window.WindowDownAction}
* |CTRL-W_<Up>| {@link com.maddyhome.idea.vim.action.window.WindowUpAction}
* |CTRL-W_<Left>| {@link com.maddyhome.idea.vim.action.window.WindowLeftAction}
* |CTRL-W_<Right>| {@link com.maddyhome.idea.vim.action.window.WindowRightAction}
* |CTRL-W_CTRL-H| {@link com.maddyhome.idea.vim.action.window.WindowLeftAction}
* |CTRL-W_CTRL-J| {@link com.maddyhome.idea.vim.action.window.WindowDownAction}
* |CTRL-W_CTRL-K| {@link com.maddyhome.idea.vim.action.window.WindowUpAction}
* |CTRL-W_CTRL-L| {@link com.maddyhome.idea.vim.action.window.WindowRightAction}
*
*
* 2.3. Square bracket commands
*
* tag action
* -------------------------------------------------------------------------------------------------------------------
* |[_CTRL-D| TO BE IMPLEMENTED
* |[_CTRL-I| TO BE IMPLEMENTED
* |[#| TO BE IMPLEMENTED
* |['| TO BE IMPLEMENTED
* |[(| {@link com.maddyhome.idea.vim.action.motion.text.MotionUnmatchedParenOpenAction}
* |[star| TO BE IMPLEMENTED
* |[`| TO BE IMPLEMENTED
* |[/| TO BE IMPLEMENTED
* |[D| TO BE IMPLEMENTED
* |[I| TO BE IMPLEMENTED
* |[M| {@link com.maddyhome.idea.vim.action.motion.text.MotionMethodPreviousEndAction}
* |[P| {@link com.maddyhome.idea.vim.action.copy.PutVisualTextBeforeCursorNoIndentAction}
* |[P| {@link com.maddyhome.idea.vim.action.copy.PutTextBeforeCursorNoIndentAction}
* |[[| {@link com.maddyhome.idea.vim.action.motion.text.MotionSectionBackwardStartAction}
* |[]| {@link com.maddyhome.idea.vim.action.motion.text.MotionSectionBackwardEndAction}
* |[c| TO BE IMPLEMENTED
* |[d| TO BE IMPLEMENTED
* |[f| TO BE IMPLEMENTED
* |[i| TO BE IMPLEMENTED
* |[m| {@link com.maddyhome.idea.vim.action.motion.text.MotionMethodPreviousStartAction}
* |[p| {@link com.maddyhome.idea.vim.action.copy.PutVisualTextAfterCursorNoIndentAction}
* |[p| {@link com.maddyhome.idea.vim.action.copy.PutTextAfterCursorNoIndentAction}
* |[s| {@link com.maddyhome.idea.vim.action.motion.text.MotionMisspelledWordPreviousAction}
* |[z| TO BE IMPLEMENTED
* |[{| {@link com.maddyhome.idea.vim.action.motion.text.MotionUnmatchedBraceOpenAction}
* |]_CTRL-D| TO BE IMPLEMENTED
* |]_CTRL-I| TO BE IMPLEMENTED
* |]#| TO BE IMPLEMENTED
* |]'| TO BE IMPLEMENTED
* |])| {@link com.maddyhome.idea.vim.action.motion.text.MotionUnmatchedParenCloseAction}
* |]star| TO BE IMPLEMENTED
* |]`| TO BE IMPLEMENTED
* |]/| TO BE IMPLEMENTED
* |]D| TO BE IMPLEMENTED
* |]I| TO BE IMPLEMENTED
* |]M| {@link com.maddyhome.idea.vim.action.motion.text.MotionMethodNextEndAction}
* |]P| {@link com.maddyhome.idea.vim.action.copy.PutVisualTextBeforeCursorNoIndentAction}
* |]P| {@link com.maddyhome.idea.vim.action.copy.PutTextBeforeCursorNoIndentAction}
* |][| {@link com.maddyhome.idea.vim.action.motion.text.MotionSectionForwardEndAction}
* |]]| {@link com.maddyhome.idea.vim.action.motion.text.MotionSectionForwardStartAction}
* |]c| TO BE IMPLEMENTED
* |]d| TO BE IMPLEMENTED
* |]f| TO BE IMPLEMENTED
* |]i| TO BE IMPLEMENTED
* |]m| {@link com.maddyhome.idea.vim.action.motion.text.MotionMethodNextStartAction}
* |]p| {@link com.maddyhome.idea.vim.action.copy.PutVisualTextAfterCursorNoIndentAction}
* |]p| {@link com.maddyhome.idea.vim.action.copy.PutTextAfterCursorNoIndentAction}
* |]s| {@link com.maddyhome.idea.vim.action.motion.text.MotionMisspelledWordNextAction}
* |]z| TO BE IMPLEMENTED
* |]}| {@link com.maddyhome.idea.vim.action.motion.text.MotionUnmatchedBraceCloseAction}
*
*
* 2.4. Commands starting with 'g'
*
* tag action
* -------------------------------------------------------------------------------------------------------------------
*
* |g_CTRL-A| not applicable
* |g_CTRL-G| {@link com.maddyhome.idea.vim.action.file.FileGetLocationInfoAction}
* |g_CTRL-H| {@link com.maddyhome.idea.vim.action.motion.select.SelectEnableBlockModeAction}
* |g_CTRL-]| TO BE IMPLEMENTED
* |g#| {@link com.maddyhome.idea.vim.action.motion.search.SearchWordBackwardAction}
* |g$| {@link com.maddyhome.idea.vim.action.motion.leftright.MotionLastScreenColumnAction}
* |g&| {@link com.maddyhome.idea.vim.action.change.change.ChangeLastGlobalSearchReplaceAction}
* |v_g'| {@link com.maddyhome.idea.vim.action.motion.mark.MotionGotoFileMarkLineNoSaveJumpAction}
* |g'| {@link com.maddyhome.idea.vim.action.motion.mark.MotionGotoMarkLineNoSaveJumpAction}
* |g`| {@link com.maddyhome.idea.vim.action.motion.mark.MotionGotoMarkNoSaveJumpAction}
* |gstar| {@link com.maddyhome.idea.vim.action.motion.search.SearchWordForwardAction}
* |g+| TO BE IMPLEMENTED
* |g,| TO BE IMPLEMENTED
* |g-| TO BE IMPLEMENTED
* |g0| {@link com.maddyhome.idea.vim.action.motion.leftright.MotionFirstScreenColumnAction}
* |g8| {@link com.maddyhome.idea.vim.action.file.FileGetHexAction}
* |g;| TO BE IMPLEMENTED
* |g<| TO BE IMPLEMENTED
* |g?| TO BE IMPLEMENTED
* |g?g?| TO BE IMPLEMENTED
* |gD| {@link com.maddyhome.idea.vim.action.motion.search.GotoDeclarationAction}
* |gE| {@link com.maddyhome.idea.vim.action.motion.text.MotionBigWordEndLeftAction}
* |gF| TO BE IMPLEMENTED
* |gH| {@link com.maddyhome.idea.vim.action.motion.select.SelectEnableLineModeAction}
* |gI| {@link com.maddyhome.idea.vim.action.change.insert.InsertLineStartAction}
* |gJ| {@link com.maddyhome.idea.vim.action.change.delete.DeleteJoinLinesAction}
* |gN| {@link com.maddyhome.idea.vim.action.motion.gn.VisualSelectPreviousSearch}
* |gN| {@link com.maddyhome.idea.vim.action.motion.gn.GnPreviousTextObject}
* |gP| {@link com.maddyhome.idea.vim.action.copy.PutVisualTextBeforeCursorMoveCursorAction}
* |gP| {@link com.maddyhome.idea.vim.action.copy.PutTextBeforeCursorActionMoveCursor}
* |gQ| TO BE IMPLEMENTED
* |gR| TO BE IMPLEMENTED
* |gT| {@link com.maddyhome.idea.vim.action.window.tabs.PreviousTabAction}
* |gU| {@link com.maddyhome.idea.vim.action.change.change.ChangeCaseUpperMotionAction}
* |gV| TO BE IMPLEMENTED
* |g]| TO BE IMPLEMENTED
* |g^| {@link com.maddyhome.idea.vim.action.motion.leftright.MotionFirstScreenNonSpaceAction}
* |g_| {@link com.maddyhome.idea.vim.action.motion.leftright.MotionLastNonSpaceAction}
* |ga| {@link com.maddyhome.idea.vim.action.file.FileGetAsciiAction}
* |gd| {@link com.maddyhome.idea.vim.action.motion.search.GotoDeclarationAction}
* |ge| {@link com.maddyhome.idea.vim.action.motion.text.MotionWordEndLeftAction}
* |gf| TO BE IMPLEMENTED
* |gg| {@link com.maddyhome.idea.vim.action.motion.updown.MotionGotoLineFirstAction}
* |gh| {@link com.maddyhome.idea.vim.action.motion.select.SelectEnableCharacterModeAction}
* |gi| {@link com.maddyhome.idea.vim.action.change.insert.InsertAtPreviousInsertAction}
* |gj| TO BE IMPLEMENTED
* |gk| {@link com.maddyhome.idea.vim.action.motion.updown.MotionUpNotLineWiseAction}
* |gn| {@link com.maddyhome.idea.vim.action.motion.gn.VisualSelectNextSearch}
* |gn| {@link com.maddyhome.idea.vim.action.motion.gn.GnNextTextObject}
* |gm| {@link com.maddyhome.idea.vim.action.motion.leftright.MotionMiddleColumnAction}
* |go| {@link com.maddyhome.idea.vim.action.motion.text.MotionNthCharacterAction}
* |gp| {@link com.maddyhome.idea.vim.action.copy.PutVisualTextAfterCursorMoveCursorAction}
* |gp| {@link com.maddyhome.idea.vim.action.copy.PutTextAfterCursorActionMoveCursor}
* |gq| {@link com.maddyhome.idea.vim.action.change.change.ReformatCodeMotionAction}
* |gr| TO BE IMPLEMENTED
* |gs| TO BE IMPLEMENTED
* |gt| {@link com.maddyhome.idea.vim.action.window.tabs.NextTabAction}
* |gu| {@link com.maddyhome.idea.vim.action.change.change.ChangeCaseLowerMotionAction}
* |gv| {@link com.maddyhome.idea.vim.action.motion.visual.VisualSelectPreviousAction}
* |gw| TO BE IMPLEMENTED
* |g@| {@link com.maddyhome.idea.vim.action.change.OperatorAction}
* |g~| {@link com.maddyhome.idea.vim.action.change.change.ChangeCaseToggleMotionAction}
* |g<Down>| TO BE IMPLEMENTED
* |g<End>| {@link com.maddyhome.idea.vim.action.motion.leftright.MotionLastScreenColumnAction}
* |g<Home>| {@link com.maddyhome.idea.vim.action.motion.leftright.MotionFirstScreenColumnAction}
* |g<Up>| {@link com.maddyhome.idea.vim.action.motion.updown.MotionUpNotLineWiseAction}
*
*
* 2.5. Commands starting with 'z'
*
* tag action
* -------------------------------------------------------------------------------------------------------------------
* |z<CR>| {@link com.maddyhome.idea.vim.action.motion.scroll.MotionScrollFirstScreenLineStartAction}
* |z+| {@link com.maddyhome.idea.vim.action.motion.scroll.MotionScrollFirstScreenLinePageStartAction}
* |z-| {@link com.maddyhome.idea.vim.action.motion.scroll.MotionScrollLastScreenLineStartAction}
* |z.| {@link com.maddyhome.idea.vim.action.motion.scroll.MotionScrollMiddleScreenLineStartAction}
* |z=| TO BE IMPLEMENTED
* |zA| TO BE IMPLEMENTED
* |zC| {@link com.maddyhome.idea.vim.action.fold.VimCollapseRegionRecursively}
* |zD| TO BE IMPLEMENTED
* |zE| TO BE IMPLEMENTED
* |zF| TO BE IMPLEMENTED
* |zG| TO BE IMPLEMENTED
* |zH| {@link com.maddyhome.idea.vim.action.motion.scroll.MotionScrollHalfWidthLeftAction}
* |zL| {@link com.maddyhome.idea.vim.action.motion.scroll.MotionScrollHalfWidthRightAction}
* |zM| {@link com.maddyhome.idea.vim.action.fold.VimCollapseAllRegions}
* |zN| TO BE IMPLEMENTED
* |zO| {@link com.maddyhome.idea.vim.action.fold.VimExpandRegionRecursively}
* |zR| {@link com.maddyhome.idea.vim.action.fold.VimExpandAllRegions}
* |zW| TO BE IMPLEMENTED
* |zX| TO BE IMPLEMENTED
* |z^| {@link com.maddyhome.idea.vim.action.motion.scroll.MotionScrollLastScreenLinePageStartAction}
* |za| TO BE IMPLEMENTED
* |zb| {@link com.maddyhome.idea.vim.action.motion.scroll.MotionScrollLastScreenLineAction}
* |zc| {@link com.maddyhome.idea.vim.action.fold.VimCollapseRegion}
* |zd| not applicable
* |ze| {@link com.maddyhome.idea.vim.action.motion.scroll.MotionScrollLastScreenColumnAction}
* |zf| not applicable
* |zg| TO BE IMPLEMENTED
* |zh| {@link com.maddyhome.idea.vim.action.motion.scroll.MotionScrollColumnRightAction}
* |zi| TO BE IMPLEMENTED
* |zj| TO BE IMPLEMENTED
* |zk| TO BE IMPLEMENTED
* |zl| {@link com.maddyhome.idea.vim.action.motion.scroll.MotionScrollColumnLeftAction}
* |zm| TO BE IMPLEMENTED
* |zn| TO BE IMPLEMENTED
* |zo| {@link com.maddyhome.idea.vim.action.fold.VimExpandRegion}
* |zr| TO BE IMPLEMENTED
* |zs| {@link com.maddyhome.idea.vim.action.motion.scroll.MotionScrollFirstScreenColumnAction}
* |zt| {@link com.maddyhome.idea.vim.action.motion.scroll.MotionScrollFirstScreenLineAction}
* |zv| TO BE IMPLEMENTED
* |zw| TO BE IMPLEMENTED
* |zx| TO BE IMPLEMENTED
* |zz| {@link com.maddyhome.idea.vim.action.motion.scroll.MotionScrollMiddleScreenLineAction}
* |z<Left>| {@link com.maddyhome.idea.vim.action.motion.scroll.MotionScrollColumnRightAction}
* |z<Right>| {@link com.maddyhome.idea.vim.action.motion.scroll.MotionScrollColumnLeftAction}
*
*
* 3. Visual mode
*
* tag action
* -------------------------------------------------------------------------------------------------------------------
*
* |v_CTRL-\_CTRL-N| {@link com.maddyhome.idea.vim.action.motion.visual.VisualExitModeAction}
* |v_CTRL-\_CTRL-G| TO BE IMPLEMENTED
* |v_CTRL-A| {@link com.maddyhome.idea.vim.action.change.change.number.ChangeVisualNumberIncAction}
* |v_CTRL-C| {@link com.maddyhome.idea.vim.action.motion.visual.VisualExitModeAction}
* |v_CTRL-G| {@link com.maddyhome.idea.vim.action.motion.select.SelectToggleVisualMode}
* |v_<BS>| NVO mapping
* |v_CTRL-H| NVO mapping
* |v_CTRL-O| TO BE IMPLEMENTED
* |v_CTRL-V| NVO mapping
* |v_<Esc>| {@link com.maddyhome.idea.vim.action.motion.visual.VisualExitModeAction}
* |v_CTRL-X| {@link com.maddyhome.idea.vim.action.change.change.number.ChangeVisualNumberDecAction}
* |v_CTRL-]| TO BE IMPLEMENTED
* |v_!| {@link com.maddyhome.idea.vim.action.change.change.FilterVisualLinesAction}
* |v_:| NVO mapping
* |v_<| {@link com.maddyhome.idea.vim.action.change.shift.ShiftLeftVisualAction}
* |v_=| {@link com.maddyhome.idea.vim.action.change.change.AutoIndentLinesVisualAction}
* |v_>| {@link com.maddyhome.idea.vim.action.change.shift.ShiftRightVisualAction}
* |v_b_A| {@link com.maddyhome.idea.vim.action.change.insert.VisualBlockAppendAction}
* |v_C| {@link com.maddyhome.idea.vim.action.change.change.ChangeVisualLinesEndAction}
* |v_D| {@link com.maddyhome.idea.vim.action.change.delete.DeleteVisualLinesEndAction}
* |v_b_I| {@link com.maddyhome.idea.vim.action.change.insert.VisualBlockInsertAction}
* |v_J| {@link com.maddyhome.idea.vim.action.change.delete.DeleteJoinVisualLinesSpacesAction}
* |v_K| TO BE IMPLEMENTED
* |v_O| {@link com.maddyhome.idea.vim.action.motion.visual.VisualSwapEndsBlockAction}
* |v_P| {@link com.maddyhome.idea.vim.action.copy.PutVisualTextBeforeCursorAction}
* |v_R| {@link com.maddyhome.idea.vim.action.change.change.ChangeVisualLinesAction}
* |v_S| {@link com.maddyhome.idea.vim.action.change.change.ChangeVisualLinesAction}
* |v_U| {@link com.maddyhome.idea.vim.action.change.change.ChangeCaseUpperVisualAction}
* |v_V| NV mapping
* |v_X| {@link com.maddyhome.idea.vim.action.change.delete.DeleteVisualLinesAction}
* |v_Y| {@link com.maddyhome.idea.vim.action.copy.YankVisualLinesAction}
* |v_aquote| {@link com.maddyhome.idea.vim.action.motion.object.MotionOuterBlockDoubleQuoteAction}
* |v_a'| {@link com.maddyhome.idea.vim.action.motion.object.MotionOuterBlockSingleQuoteAction}
* |v_a(| {@link com.maddyhome.idea.vim.action.motion.object.MotionOuterBlockParenAction}
* |v_a)| {@link com.maddyhome.idea.vim.action.motion.object.MotionOuterBlockParenAction}
* |v_a<| {@link com.maddyhome.idea.vim.action.motion.object.MotionOuterBlockAngleAction}
* |v_a>| {@link com.maddyhome.idea.vim.action.motion.object.MotionOuterBlockAngleAction}
* |v_aB| {@link com.maddyhome.idea.vim.action.motion.object.MotionOuterBlockBraceAction}
* |v_aW| {@link com.maddyhome.idea.vim.action.motion.object.MotionOuterBigWordAction}
* |v_a[| {@link com.maddyhome.idea.vim.action.motion.object.MotionOuterBlockBracketAction}
* |v_a]| {@link com.maddyhome.idea.vim.action.motion.object.MotionOuterBlockBracketAction}
* |v_a`| {@link com.maddyhome.idea.vim.action.motion.object.MotionOuterBlockBackQuoteAction}
* |v_ab| {@link com.maddyhome.idea.vim.action.motion.object.MotionOuterBlockParenAction}
* |v_ap| {@link com.maddyhome.idea.vim.action.motion.object.MotionOuterParagraphAction}
* |v_as| {@link com.maddyhome.idea.vim.action.motion.object.MotionOuterSentenceAction}
* |v_at| {@link com.maddyhome.idea.vim.action.motion.object.MotionOuterBlockTagAction}
* |v_aw| {@link com.maddyhome.idea.vim.action.motion.object.MotionOuterWordAction}
* |v_a{| {@link com.maddyhome.idea.vim.action.motion.object.MotionOuterBlockBraceAction}
* |v_a}| {@link com.maddyhome.idea.vim.action.motion.object.MotionOuterBlockBraceAction}
* |v_c| {@link com.maddyhome.idea.vim.action.change.change.ChangeVisualAction}
* |v_d| {@link com.maddyhome.idea.vim.action.change.delete.DeleteVisualAction}
* |v_gCTRL-A| {@link com.maddyhome.idea.vim.action.change.change.number.ChangeVisualNumberAvalancheIncAction}
* |v_gCTRL-X| {@link com.maddyhome.idea.vim.action.change.change.number.ChangeVisualNumberAvalancheDecAction}
* |v_gJ| {@link com.maddyhome.idea.vim.action.change.delete.DeleteJoinVisualLinesAction}
* |v_gq| {@link com.maddyhome.idea.vim.action.change.change.ReformatCodeVisualAction}
* |v_gv| {@link com.maddyhome.idea.vim.action.motion.visual.VisualSwapSelectionsAction}
* |v_g`| {@link com.maddyhome.idea.vim.action.motion.mark.MotionGotoFileMarkNoSaveJumpAction}
* |v_g@| {@link com.maddyhome.idea.vim.action.change.VisualOperatorAction}
* |v_iquote| {@link com.maddyhome.idea.vim.action.motion.object.MotionInnerBlockDoubleQuoteAction}
* |v_i'| {@link com.maddyhome.idea.vim.action.motion.object.MotionInnerBlockSingleQuoteAction}
* |v_i(| {@link com.maddyhome.idea.vim.action.motion.object.MotionInnerBlockParenAction}
* |v_i)| {@link com.maddyhome.idea.vim.action.motion.object.MotionInnerBlockParenAction}
* |v_i<| {@link com.maddyhome.idea.vim.action.motion.object.MotionInnerBlockAngleAction}
* |v_i>| {@link com.maddyhome.idea.vim.action.motion.object.MotionInnerBlockAngleAction}
* |v_iB| {@link com.maddyhome.idea.vim.action.motion.object.MotionInnerBlockBraceAction}
* |v_iW| {@link com.maddyhome.idea.vim.action.motion.object.MotionInnerBigWordAction}
* |v_i[| {@link com.maddyhome.idea.vim.action.motion.object.MotionInnerBlockBracketAction}
* |v_i]| {@link com.maddyhome.idea.vim.action.motion.object.MotionInnerBlockBracketAction}
* |v_i`| {@link com.maddyhome.idea.vim.action.motion.object.MotionInnerBlockBackQuoteAction}
* |v_ib| {@link com.maddyhome.idea.vim.action.motion.object.MotionInnerBlockParenAction}
* |v_ip| {@link com.maddyhome.idea.vim.action.motion.object.MotionInnerParagraphAction}
* |v_is| {@link com.maddyhome.idea.vim.action.motion.object.MotionInnerSentenceAction}
* |v_it| {@link com.maddyhome.idea.vim.action.motion.object.MotionInnerBlockTagAction}
* |v_iw| {@link com.maddyhome.idea.vim.action.motion.object.MotionInnerWordAction}
* |v_i{| {@link com.maddyhome.idea.vim.action.motion.object.MotionInnerBlockBraceAction}
* |v_i}| {@link com.maddyhome.idea.vim.action.motion.object.MotionInnerBlockBraceAction}
* |v_o| {@link com.maddyhome.idea.vim.action.motion.visual.VisualSwapEndsAction}
* |v_p| {@link com.maddyhome.idea.vim.action.copy.PutVisualTextAfterCursorAction}
* |v_r| {@link com.maddyhome.idea.vim.action.change.change.ChangeVisualCharacterAction}
* |v_s| {@link com.maddyhome.idea.vim.action.change.change.ChangeVisualAction}
* |v_u| {@link com.maddyhome.idea.vim.action.change.change.ChangeCaseLowerVisualAction}
* |v_v| NV mapping
* |v_x| {@link com.maddyhome.idea.vim.action.change.delete.DeleteVisualAction}
* |v_y| {@link com.maddyhome.idea.vim.action.copy.YankVisualAction}
* |v_~| {@link com.maddyhome.idea.vim.action.change.change.ChangeCaseToggleVisualAction}
* |v_`| {@link com.maddyhome.idea.vim.action.motion.mark.MotionGotoFileMarkAction}
* |v_'| {@link com.maddyhome.idea.vim.action.motion.mark.MotionGotoFileMarkLineAction}
*
*
* 4. Select mode
*
* tag action
* -------------------------------------------------------------------------------------------------------------------
* |<BS>| {@link com.maddyhome.idea.vim.action.motion.select.SelectDeleteAction}
* |<CR>| {@link com.maddyhome.idea.vim.action.motion.select.SelectEnterAction}
* |<DEL>| {@link com.maddyhome.idea.vim.action.motion.select.SelectDeleteAction}
* |<ESC>| {@link com.maddyhome.idea.vim.action.motion.select.SelectEscapeAction}
* |<C-G>| {@link com.maddyhome.idea.vim.action.motion.select.SelectToggleVisualMode}
* |<S-Down>| {@link com.maddyhome.idea.vim.action.motion.updown.MotionShiftDownAction}
* |<S-Left>| {@link com.maddyhome.idea.vim.action.motion.leftright.MotionShiftLeftAction}
* |<S-Right>| {@link com.maddyhome.idea.vim.action.motion.leftright.MotionShiftRightAction}
* |<S-Up>| {@link com.maddyhome.idea.vim.action.motion.updown.MotionShiftUpAction}
* |<Down>| {@link com.maddyhome.idea.vim.action.motion.updown.MotionArrowDownAction}
* |<Left>| {@link com.maddyhome.idea.vim.action.motion.select.motion.SelectMotionLeftAction}
* |<Right>| {@link com.maddyhome.idea.vim.action.motion.select.motion.SelectMotionRightAction}
* |<Up>| {@link com.maddyhome.idea.vim.action.motion.updown.MotionArrowUpAction}
*
* 5. Command line editing
*
* tag action
* -------------------------------------------------------------------------------------------------------------------
*
* |c_CTRL-A| TO BE IMPLEMENTED
* |c_CTRL-B| {@link javax.swing.text.DefaultEditorKit#beginLineAction}
* |c_CTRL-C| {@link com.maddyhome.idea.vim.ui.ex.CancelEntryAction}
* |c_CTRL-D| TO BE IMPLEMENTED
* |c_CTRL-E| {@link javax.swing.text.DefaultEditorKit#endLineAction}
* |c_CTRL-G| TO BE IMPLEMENTED
* |c_CTRL-H| {@link com.maddyhome.idea.vim.ui.ex.DeletePreviousCharAction}
* |c_CTRL-I| TO BE IMPLEMENTED
* |c_CTRL-J| {@link com.maddyhome.idea.vim.ui.ex.CompleteEntryAction}
* |c_CTRL-K| Handled by KeyHandler
* |c_CTRL-L| TO BE IMPLEMENTED
* |c_CTRL-M| {@link com.maddyhome.idea.vim.action.ex.ProcessExEntryAction}
* |c_CTRL-N| {@link com.maddyhome.idea.vim.ui.ex.HistoryDownAction}
* |c_CTRL-P| {@link com.maddyhome.idea.vim.ui.ex.HistoryUpAction}
* |c_CTRL-Q| Handled by KeyHandler
* |c_CTRL-R_CTRL-A| TO BE IMPLEMENTED
* |c_CTRL-R_CTRL-F| TO BE IMPLEMENTED
* |c_CTRL-R_CTRL-L| TO BE IMPLEMENTED
* |c_CTRL-R_CTRL-O| TO BE IMPLEMENTED
* |c_CTRL-R_CTRL-P| TO BE IMPLEMENTED
* |c_CTRL-R_CTRL-R| TO BE IMPLEMENTED
* |c_CTRL-R_CTRL-W| TO BE IMPLEMENTED
* |c_CTRL-T| TO BE IMPLEMENTED
* |c_CTRL-U| {@link com.maddyhome.idea.vim.ui.ex.DeleteToCursorAction}
* |c_CTRL-V| Handled by KeyHandler
* |c_CTRL-W| {@link com.maddyhome.idea.vim.ui.ex.DeletePreviousWordAction}
* |c_CTRL-Y| TO BE IMPLEMENTED
* |c_CTRL-\_e| TO BE IMPLEMENTED
* |c_CTRL-\_CTRL-G| TO BE IMPLEMENTED
* |c_CTRL-\_CTRL-N| TO BE IMPLEMENTED
* |c_CTRL-_| not applicable
* |c_CTRL-^| not applicable
* |c_CTRL-]| TO BE IMPLEMENTED
* |c_CTRL-[| {@link com.maddyhome.idea.vim.ui.ex.EscapeCharAction}
* |c_<BS>| {@link com.maddyhome.idea.vim.ui.ex.DeletePreviousCharAction}
* |c_<CR>| {@link com.maddyhome.idea.vim.ui.ex.CompleteEntryAction}
* |c_<C-Left>| {@link javax.swing.text.DefaultEditorKit#previousWordAction}
* |c_<C-Right>| {@link javax.swing.text.DefaultEditorKit#nextWordAction}
* |c_<Del>| {@link javax.swing.text.DefaultEditorKit#deleteNextCharAction}
* |c_<Down>| {@link com.maddyhome.idea.vim.ui.ex.HistoryDownFilterAction}
* |c_<End>| {@link javax.swing.text.DefaultEditorKit#endLineAction}
* |c_<Esc>| {@link com.maddyhome.idea.vim.ui.ex.EscapeCharAction}
* |c_<Home>| {@link javax.swing.text.DefaultEditorKit#beginLineAction}
* |c_<Insert>| {@link com.maddyhome.idea.vim.ui.ex.ToggleInsertReplaceAction}
* |c_<Left>| {@link javax.swing.text.DefaultEditorKit#backwardAction}
* |c_<LeftMouse>| not applicable
* |c_<MiddleMouse>| TO BE IMPLEMENTED
* |c_<NL>| {@link com.maddyhome.idea.vim.ui.ex.CompleteEntryAction}
* |c_<PageUp>| {@link com.maddyhome.idea.vim.ui.ex.HistoryUpAction}
* |c_<PageDown>| {@link com.maddyhome.idea.vim.ui.ex.HistoryDownAction}
* |c_<Right>| {@link javax.swing.text.DefaultEditorKit#forwardAction}
* |c_<S-Down>| {@link com.maddyhome.idea.vim.ui.ex.HistoryDownAction}
* |c_<S-Left>| {@link javax.swing.text.DefaultEditorKit#previousWordAction}
* |c_<S-Right>| {@link javax.swing.text.DefaultEditorKit#nextWordAction}
* |c_<S-Tab>| TO BE IMPLEMENTED
* |c_<S-Up>| {@link com.maddyhome.idea.vim.ui.ex.HistoryUpAction}
* |c_<Tab>| TO BE IMPLEMENTED
* |c_<Up>| {@link com.maddyhome.idea.vim.ui.ex.HistoryUpFilterAction}
* |c_digraph| {char1} <BS> {char2}
* |c_wildchar| TO BE IMPLEMENTED
* |'cedit'| TO BE IMPLEMENTED
*
*
* 6. Ex commands
*
* tag handler
* -------------------------------------------------------------------------------------------------------------------
*
* |:map| {@link com.maddyhome.idea.vim.vimscript.model.commands.mapping.MapCommand}
* |:nmap| ...
* |:vmap| ...
* |:omap| ...
* |:imap| ...
* |:cmap| ...
* |:noremap| ...
* |:nnoremap| ...
* |:vnoremap| ...
* |:onoremap| ...
* |:inoremap| ...
* |:cnoremap| ...
* |:shell| {@link com.maddyhome.idea.vim.vimscript.model.commands.ShellCommand}
* |:sort| {@link com.maddyhome.idea.vim.vimscript.model.commands.SortCommand}
* |:source| {@link com.maddyhome.idea.vim.vimscript.model.commands.SourceCommand}
* |:qall| {@link com.maddyhome.idea.vim.vimscript.model.commands.ExitCommand}
* |:quitall| {@link com.maddyhome.idea.vim.vimscript.model.commands.ExitCommand}
* |:quitall| {@link com.maddyhome.idea.vim.vimscript.model.commands.ExitCommand}
* |:wqall| {@link com.maddyhome.idea.vim.vimscript.model.commands.ExitCommand}
* |:xall| {@link com.maddyhome.idea.vim.vimscript.model.commands.ExitCommand}
* |:command| {@link com.maddyhome.idea.vim.vimscript.model.commands.CmdCommand}
* |:delcommand| {@link com.maddyhome.idea.vim.vimscript.model.commands.DelCmdCommand}
* |:comclear| {@link com.maddyhome.idea.vim.vimscript.model.commands.CmdClearCommand}
* ...
*
* The list of supported Ex commands is incomplete.
*
*
* A. Misc commands
*
* tag handler
* -------------------------------------------------------------------------------------------------------------------
* |]b| {@link com.maddyhome.idea.vim.action.motion.text.MotionCamelEndLeftAction}
* |]w| {@link com.maddyhome.idea.vim.action.motion.text.MotionCamelEndRightAction}
* |[b| {@link com.maddyhome.idea.vim.action.motion.text.MotionCamelLeftAction}
* |[w| {@link com.maddyhome.idea.vim.action.motion.text.MotionCamelRightAction}
* |g(| {@link com.maddyhome.idea.vim.action.motion.text.MotionSentencePreviousEndAction}
* |g)| {@link com.maddyhome.idea.vim.action.motion.text.MotionSentenceNextEndAction}
*
*
* See also :help index.
*
* @author vlan
*/
package com.maddyhome.idea.vim;

View File

@ -1,263 +0,0 @@
/*
* Copyright 2003-2023 The IdeaVim authors
*
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE.txt file or at
* https://opensource.org/licenses/MIT.
*/
package com.maddyhome.idea.vim.ui.ex
import com.intellij.openapi.diagnostic.logger
import com.intellij.openapi.editor.textarea.TextComponentEditorImpl
import com.maddyhome.idea.vim.KeyHandler
import com.maddyhome.idea.vim.api.LocalOptionInitialisationScenario
import com.maddyhome.idea.vim.api.injector
import com.maddyhome.idea.vim.newapi.vim
import java.awt.event.ActionEvent
import java.awt.event.KeyEvent
import javax.swing.Action
import javax.swing.KeyStroke
import javax.swing.text.BadLocationException
import javax.swing.text.DefaultEditorKit
import javax.swing.text.Document
import javax.swing.text.TextAction
import kotlin.math.abs
import kotlin.math.min
@Deprecated("ExCommands should be migrated to KeyHandler like commands for other modes")
internal interface MultiStepAction : Action {
fun reset()
}
@Deprecated("ExCommands should be migrated to KeyHandler like commands for other modes")
internal class HistoryUpAction : TextAction(ExEditorKit.HistoryUp) {
override fun actionPerformed(actionEvent: ActionEvent) {
val target = getTextComponent(actionEvent) as ExTextField
target.selectHistory(true, false)
}
}
@Deprecated("ExCommands should be migrated to KeyHandler like commands for other modes")
internal class HistoryDownAction : TextAction(ExEditorKit.HistoryDown) {
override fun actionPerformed(actionEvent: ActionEvent) {
val target = getTextComponent(actionEvent) as ExTextField
target.selectHistory(false, false)
}
}
@Deprecated("ExCommands should be migrated to KeyHandler like commands for other modes")
internal class HistoryUpFilterAction : TextAction(ExEditorKit.HistoryUpFilter) {
override fun actionPerformed(actionEvent: ActionEvent) {
val target = getTextComponent(actionEvent) as ExTextField
target.selectHistory(true, true)
}
}
@Deprecated("ExCommands should be migrated to KeyHandler like commands for other modes")
internal class HistoryDownFilterAction : TextAction(ExEditorKit.HistoryDownFilter) {
override fun actionPerformed(actionEvent: ActionEvent) {
val target = getTextComponent(actionEvent) as ExTextField
target.selectHistory(false, true)
}
}
@Deprecated("ExCommands should be migrated to KeyHandler like commands for other modes")
internal class CompleteEntryAction : TextAction(ExEditorKit.CompleteEntry) {
override fun actionPerformed(actionEvent: ActionEvent) {
logger.debug("complete entry")
val stroke = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0)
// We send the <Enter> keystroke through the key handler rather than calling ProcessGroup#processExEntry directly.
// We do this for a couple of reasons:
// * The C mode mapping for ProcessExEntryAction handles the actual entry, and most importantly, it does so as a
// write action
// * The key handler routines get the chance to clean up and reset state
val entry = ExEntryPanel.getInstance().entry
val keyHandler = KeyHandler.getInstance()
keyHandler.handleKey(entry.editor!!.vim, stroke, entry.context.vim, keyHandler.keyHandlerState)
}
companion object {
private val logger = logger<CompleteEntryAction>()
}
}
@Deprecated("ExCommands should be migrated to KeyHandler like commands for other modes")
internal class CancelEntryAction : TextAction(ExEditorKit.CancelEntry) {
override fun actionPerformed(e: ActionEvent) {
val target = getTextComponent(e) as ExTextField
target.cancel()
}
}
@Deprecated("ExCommands should be migrated to KeyHandler like commands for other modes")
internal class EscapeCharAction : TextAction(ExEditorKit.EscapeChar) {
override fun actionPerformed(e: ActionEvent) {
val target = getTextComponent(e) as ExTextField
target.escape()
}
}
@Deprecated("ExCommands should be migrated to KeyHandler like commands for other modes")
internal abstract class DeleteCharAction internal constructor(name: String?) : TextAction(name) {
@kotlin.jvm.Throws(BadLocationException::class)
fun deleteSelection(doc: Document, dot: Int, mark: Int): Boolean {
if (dot != mark) {
doc.remove(min(dot, mark), abs(dot - mark))
return true
}
return false
}
@kotlin.jvm.Throws(BadLocationException::class)
fun deleteNextChar(doc: Document, dot: Int): Boolean {
if (dot < doc.length) {
var delChars = 1
if (dot < doc.length - 1) {
val dotChars = doc.getText(dot, 2)
val c0 = dotChars[0]
val c1 = dotChars[1]
if (c0 in '\uD800'..'\uDBFF' && c1 in '\uDC00'..'\uDFFF') {
delChars = 2
}
}
doc.remove(dot, delChars)
return true
}
return false
}
@kotlin.jvm.Throws(BadLocationException::class)
fun deletePrevChar(doc: Document, dot: Int): Boolean {
if (dot > 0) {
var delChars = 1
if (dot > 1) {
val dotChars = doc.getText(dot - 2, 2)
val c0 = dotChars[0]
val c1 = dotChars[1]
if (c0 in '\uD800'..'\uDBFF' && c1 in '\uDC00'..'\uDFFF') {
delChars = 2
}
}
doc.remove(dot - delChars, delChars)
return true
}
return false
}
}
@Deprecated("ExCommands should be migrated to KeyHandler like commands for other modes")
internal class DeleteNextCharAction : DeleteCharAction(DefaultEditorKit.deleteNextCharAction) {
override fun actionPerformed(e: ActionEvent) {
val target = getTextComponent(e) as ExTextField
target.saveLastEntry()
try {
val doc = target.document
val caret = target.caret
val dot = caret.dot
val mark = caret.mark
if (!deleteSelection(doc, dot, mark) && !deleteNextChar(doc, dot) && !deletePrevChar(doc, dot)) {
target.cancel()
}
} catch (ex: BadLocationException) {
// ignore
}
}
}
@Deprecated("ExCommands should be migrated to KeyHandler like commands for other modes")
internal class DeletePreviousCharAction : DeleteCharAction(DefaultEditorKit.deletePrevCharAction) {
override fun actionPerformed(e: ActionEvent) {
val target = getTextComponent(e) as ExTextField
target.saveLastEntry()
try {
val doc = target.document
val caret = target.caret
val dot = caret.dot
val mark = caret.mark
if (!deleteSelection(doc, dot, mark) && !deletePrevChar(doc, dot)) {
if (dot == 0 && doc.length == 0) {
target.cancel()
}
}
} catch (bl: BadLocationException) {
// ignore
}
}
}
@Deprecated("ExCommands should be migrated to KeyHandler like commands for other modes")
internal class DeletePreviousWordAction : TextAction(DefaultEditorKit.deletePrevWordAction) {
/**
* Invoked when an action occurs.
*/
override fun actionPerformed(e: ActionEvent) {
val target = getTextComponent(e) as ExTextField
target.saveLastEntry()
val doc = target.document
val caret = target.caret
val project = target.editor!!.project
// Create a VimEditor instance on the Swing text field which we can pass to the search helpers. We need an editor
// rather than just working on a buffer because the search helpers need local options (specifically the local to
// buffer 'iskeyword'). We use the CMD_LINE scenario to initialise local options from the main editor. The options
// service will copy all local-to-buffer and local-to-window options, effectively cloning the options.
// TODO: Over time, we should migrate all ex actions to be based on VimEditor
// This will mean we always have an editor that has been initialised for options, etc. But also means that we can
// share the command line entry actions between IdeaVim implementations
val editor = TextComponentEditorImpl(project, target).vim
injector.optionGroup.initialiseLocalOptions(editor, target.editor!!.vim, LocalOptionInitialisationScenario.CMD_LINE)
val offset = injector.searchHelper.findNextWord(editor, caret.dot, -1, bigWord = false, spaceWords = false)
if (logger.isDebugEnabled) logger.debug("offset=$offset")
try {
val pos = caret.dot
doc.remove(offset, pos - offset)
} catch (ex: BadLocationException) {
// ignore
}
}
companion object {
private val logger = logger<DeletePreviousWordAction>()
}
}
@Deprecated("ExCommands should be migrated to KeyHandler like commands for other modes")
internal class DeleteToCursorAction : TextAction(ExEditorKit.DeleteToCursor) {
/**
* Invoked when an action occurs.
*/
override fun actionPerformed(e: ActionEvent) {
val target = getTextComponent(e) as ExTextField
target.saveLastEntry()
val doc = target.document
val caret = target.caret
try {
doc.remove(0, caret.dot)
} catch (ex: BadLocationException) {
// ignore
}
}
}
@Deprecated("ExCommands should be migrated to KeyHandler like commands for other modes")
internal class ToggleInsertReplaceAction : TextAction(ExEditorKit.ToggleInsertReplace) {
/**
* Invoked when an action occurs.
*/
override fun actionPerformed(e: ActionEvent) {
logger.debug("actionPerformed")
val target = getTextComponent(e) as ExTextField
target.toggleInsertReplace()
}
init {
logger.debug("ToggleInsertReplaceAction()")
}
companion object {
private val logger = logger<ToggleInsertReplaceAction>()
}
}

View File

@ -34,7 +34,7 @@ public class ExDocument extends PlainDocument {
void toggleInsertReplace() {
VimCommandLine commandLine = injector.getCommandLine().getActiveCommandLine();
if (commandLine != null) {
commandLine.toggleReplaceMode();
((ExEntryPanel) commandLine).isReplaceMode = !((ExEntryPanel)commandLine).isReplaceMode;
}
overwrite = !overwrite;
}

View File

@ -7,7 +7,6 @@
*/
package com.maddyhome.idea.vim.ui.ex
import com.intellij.openapi.diagnostic.debug
import com.intellij.openapi.diagnostic.logger
import com.maddyhome.idea.vim.KeyHandler
import com.maddyhome.idea.vim.api.injector
@ -15,50 +14,12 @@ import com.maddyhome.idea.vim.newapi.vim
import org.jetbrains.annotations.NonNls
import java.awt.event.ActionEvent
import java.awt.event.KeyEvent
import javax.swing.Action
import javax.swing.KeyStroke
import javax.swing.text.DefaultEditorKit
import javax.swing.text.Document
import javax.swing.text.TextAction
@Deprecated("ExCommands should be migrated to KeyHandler like commands for other modes")
internal object ExEditorKit : DefaultEditorKit() {
@NonNls
val CancelEntry: String = "cancel-entry"
@NonNls
val CompleteEntry: String = "complete-entry"
@NonNls
val EscapeChar: String = "escape"
@NonNls
val DeleteToCursor: String = "delete-to-cursor"
@NonNls
val ToggleInsertReplace: String = "toggle-insert"
@NonNls
val HistoryUp: String = "history-up"
@NonNls
val HistoryDown: String = "history-down"
@NonNls
val HistoryUpFilter: String = "history-up-filter"
@NonNls
val HistoryDownFilter: String = "history-down-filter"
@NonNls
val StartDigraph: String = "start-digraph"
@NonNls
val StartLiteral: String = "start-literal"
private val logger = logger<ExEditorKit>()
/**
* Gets the MIME type of the data that this
* kit represents support for.
@ -70,19 +31,6 @@ internal object ExEditorKit : DefaultEditorKit() {
return "text/ideavim"
}
/**
* Fetches the set of commands that can be used
* on a text component that is using a model and
* view produced by this kit.
*
* @return the set of actions
*/
override fun getActions(): Array<Action> {
val res = TextAction.augmentList(super.getActions(), exActions)
logger.debug { "res.length=${res.size}" }
return res
}
/**
* Creates an uninitialized text storage model
* that is appropriate for this type of editor.
@ -93,28 +41,10 @@ internal object ExEditorKit : DefaultEditorKit() {
return ExDocument()
}
private val exActions = arrayOf<Action>(
CancelEntryAction(),
CompleteEntryAction(),
EscapeCharAction(),
DeleteNextCharAction(),
DeletePreviousCharAction(),
DeletePreviousWordAction(),
DeleteToCursorAction(),
HistoryUpAction(),
HistoryDownAction(),
HistoryUpFilterAction(),
HistoryDownFilterAction(),
ToggleInsertReplaceAction(),
)
class DefaultExKeyHandler : DefaultKeyTypedAction() {
override fun actionPerformed(e: ActionEvent) {
val target = getTextComponent(e) as ExTextField
val currentAction = target.currentAction
if (currentAction != null) {
currentAction.actionPerformed(e)
} else {
val key = convert(e)
if (key != null) {
val c = key.keyChar
@ -137,7 +67,6 @@ internal object ExEditorKit : DefaultEditorKit() {
}
}
}
}
fun convert(event: ActionEvent): KeyStroke? {
val cmd = event.actionCommand

View File

@ -23,7 +23,10 @@ import com.maddyhome.idea.vim.EventFacade;
import com.maddyhome.idea.vim.KeyHandler;
import com.maddyhome.idea.vim.VimPlugin;
import com.maddyhome.idea.vim.action.VimShortcutKeyAction;
import com.maddyhome.idea.vim.api.*;
import com.maddyhome.idea.vim.api.VimCommandLine;
import com.maddyhome.idea.vim.api.VimCommandLineCaret;
import com.maddyhome.idea.vim.api.VimEditor;
import com.maddyhome.idea.vim.api.VimKeyGroupBase;
import com.maddyhome.idea.vim.ex.ranges.LineRange;
import com.maddyhome.idea.vim.helper.SearchHighlightsHelper;
import com.maddyhome.idea.vim.helper.UiHelper;
@ -60,7 +63,7 @@ import static com.maddyhome.idea.vim.group.KeyGroup.toShortcutSet;
public class ExEntryPanel extends JPanel implements VimCommandLine {
public static ExEntryPanel instance;
public static ExEntryPanel instanceWithoutShortcuts;
private boolean isReplaceMode = false;
public boolean isReplaceMode = false;
private WeakReference<Editor> weakEditor = null;
private VimInputInterceptor myInputInterceptor = null;
@ -348,7 +351,7 @@ public class ExEntryPanel extends JPanel implements VimCommandLine {
// coerced to at least 1.
int count1 = KeyHandler.getInstance().getKeyHandlerState().getEditorCommandBuilder().getAggregatedUncommittedCount();
if (labelText.equals("/") || labelText.equals("?") || searchCommand) {
if ((labelText.equals("/") || labelText.equals("?") || searchCommand) && !injector.getMacro().isExecutingMacro()) {
final boolean forwards = !labelText.equals("?"); // :s, :g, :v are treated as forwards
int pattenEnd = injector.getSearchGroup().findEndOfPattern(searchText, separator, 0);
final String pattern = searchText.substring(0, pattenEnd);
@ -402,7 +405,7 @@ public class ExEntryPanel extends JPanel implements VimCommandLine {
@Override
public void toggleReplaceMode() {
isReplaceMode = !isReplaceMode;
entry.toggleInsertReplace();
}
/**
@ -535,10 +538,11 @@ public class ExEntryPanel extends JPanel implements VimCommandLine {
}
@Override
public void setText(@NotNull String string) {
public void setText(@NotNull String string, boolean updateLastEntry) {
// It's a feature of Swing that caret is moved when we set new text. However, our API is Swing independent and we do not expect this
int offset = getCaret().getOffset();
entry.updateText(string);
if (updateLastEntry) entry.saveLastEntry();
getCaret().setOffset(Math.min(offset, getVisibleText().length()));
}
@ -595,6 +599,27 @@ public class ExEntryPanel extends JPanel implements VimCommandLine {
return finishOn;
}
@Override
public int getHistIndex() {
return entry.histIndex;
}
@Override
public void setHistIndex(int i) {
entry.histIndex = i;
}
@NotNull
@Override
public String getLastEntry() {
return entry.lastEntry;
}
@Override
public void setLastEntry(@NotNull String s) {
entry.lastEntry = s;
}
public static class LafListener implements LafManagerListener {
@Override
public void lookAndFeelChanged(@NotNull LafManager source) {

View File

@ -21,57 +21,6 @@ internal object ExKeyBindings {
val bindings: Array<KeyBinding> by lazy {
arrayOf(
// Escape will cancel a pending insert digraph/register before cancelling
KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), ExEditorKit.EscapeChar),
KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_OPEN_BRACKET, KeyEvent.CTRL_DOWN_MASK), ExEditorKit.EscapeChar),
// Cancel entry, ignoring any pending actions such as digraph/registry entry
KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_C, KeyEvent.CTRL_DOWN_MASK), ExEditorKit.CancelEntry),
KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), ExEditorKit.CompleteEntry),
KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_J, KeyEvent.CTRL_DOWN_MASK), ExEditorKit.CompleteEntry),
KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_M, KeyEvent.CTRL_DOWN_MASK), ExEditorKit.CompleteEntry),
KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_B, KeyEvent.CTRL_DOWN_MASK), DefaultEditorKit.beginLineAction),
KeyBinding(KeyStroke.getKeyStroke(0x02.toChar().code, KeyEvent.CTRL_DOWN_MASK), DefaultEditorKit.beginLineAction),
KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_HOME, 0), DefaultEditorKit.beginLineAction),
KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_E, KeyEvent.CTRL_DOWN_MASK), DefaultEditorKit.endLineAction),
KeyBinding(KeyStroke.getKeyStroke(0x05.toChar().code, KeyEvent.CTRL_DOWN_MASK), DefaultEditorKit.endLineAction),
KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_END, 0), DefaultEditorKit.endLineAction),
KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_BACK_SPACE, 0), DefaultEditorKit.deletePrevCharAction),
KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_H, KeyEvent.CTRL_DOWN_MASK), DefaultEditorKit.deletePrevCharAction),
KeyBinding(KeyStroke.getKeyStroke(0x08.toChar().code, KeyEvent.CTRL_DOWN_MASK), DefaultEditorKit.deletePrevCharAction),
KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0), DefaultEditorKit.deleteNextCharAction),
KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_W, KeyEvent.CTRL_DOWN_MASK), DefaultEditorKit.deletePrevWordAction),
KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_U, KeyEvent.CTRL_DOWN_MASK), ExEditorKit.DeleteToCursor),
KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0), ExEditorKit.HistoryUpFilter),
KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_UP, KeyEvent.SHIFT_DOWN_MASK), ExEditorKit.HistoryUp),
KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_PAGE_UP, 0), ExEditorKit.HistoryUp),
KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_P, KeyEvent.CTRL_DOWN_MASK), ExEditorKit.HistoryUp),
KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0), ExEditorKit.HistoryDownFilter),
KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, KeyEvent.SHIFT_DOWN_MASK), ExEditorKit.HistoryDown),
KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_PAGE_DOWN, 0), ExEditorKit.HistoryDown),
KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_N, KeyEvent.CTRL_DOWN_MASK), ExEditorKit.HistoryDown),
KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_INSERT, 0), ExEditorKit.ToggleInsertReplace),
KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0), DefaultEditorKit.backwardAction),
KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, KeyEvent.SHIFT_DOWN_MASK), DefaultEditorKit.previousWordAction),
KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, KeyEvent.CTRL_DOWN_MASK), DefaultEditorKit.previousWordAction),
KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0), DefaultEditorKit.forwardAction),
KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, KeyEvent.SHIFT_DOWN_MASK), DefaultEditorKit.nextWordAction),
KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, KeyEvent.CTRL_DOWN_MASK), DefaultEditorKit.nextWordAction),
KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_K, KeyEvent.CTRL_DOWN_MASK), ExEditorKit.StartDigraph),
KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_V, KeyEvent.CTRL_DOWN_MASK), ExEditorKit.StartLiteral),
KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_Q, KeyEvent.CTRL_DOWN_MASK), ExEditorKit.StartLiteral),
// These appear to be non-Vim shortcuts
KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_V, KeyEvent.META_DOWN_MASK), DefaultEditorKit.pasteAction),
KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_INSERT, KeyEvent.SHIFT_DOWN_MASK), DefaultEditorKit.pasteAction),

View File

@ -59,9 +59,45 @@ internal class ExShortcutKeyAction(private val exEntryPanel: ExEntryPanel) : Dum
}
fun registerCustomShortcutSet() {
val shortcuts = ExKeyBindings.bindings.map {
KeyboardShortcut(it.key, null)
}.toTypedArray()
val shortcuts = listOf(
KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0),
KeyStroke.getKeyStroke(KeyEvent.VK_OPEN_BRACKET, KeyEvent.CTRL_DOWN_MASK),
KeyStroke.getKeyStroke(KeyEvent.VK_C, KeyEvent.CTRL_DOWN_MASK),
KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0),
KeyStroke.getKeyStroke(KeyEvent.VK_J, KeyEvent.CTRL_DOWN_MASK),
KeyStroke.getKeyStroke(KeyEvent.VK_M, KeyEvent.CTRL_DOWN_MASK),
KeyStroke.getKeyStroke(KeyEvent.VK_B, KeyEvent.CTRL_DOWN_MASK),
KeyStroke.getKeyStroke(KeyEvent.VK_HOME, 0),
KeyStroke.getKeyStroke(KeyEvent.VK_E, KeyEvent.CTRL_DOWN_MASK),
KeyStroke.getKeyStroke(KeyEvent.VK_END, 0),
KeyStroke.getKeyStroke(KeyEvent.VK_BACK_SPACE, 0),
KeyStroke.getKeyStroke(KeyEvent.VK_H, KeyEvent.CTRL_DOWN_MASK),
KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0),
KeyStroke.getKeyStroke(KeyEvent.VK_W, KeyEvent.CTRL_DOWN_MASK),
KeyStroke.getKeyStroke(KeyEvent.VK_U, KeyEvent.CTRL_DOWN_MASK),
KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0),
KeyStroke.getKeyStroke(KeyEvent.VK_UP, KeyEvent.SHIFT_DOWN_MASK),
KeyStroke.getKeyStroke(KeyEvent.VK_PAGE_UP, 0),
KeyStroke.getKeyStroke(KeyEvent.VK_P, KeyEvent.CTRL_DOWN_MASK),
KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0),
KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, KeyEvent.SHIFT_DOWN_MASK),
KeyStroke.getKeyStroke(KeyEvent.VK_PAGE_DOWN, 0),
KeyStroke.getKeyStroke(KeyEvent.VK_N, KeyEvent.CTRL_DOWN_MASK),
KeyStroke.getKeyStroke(KeyEvent.VK_INSERT, 0),
KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0),
KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, KeyEvent.SHIFT_DOWN_MASK),
KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, KeyEvent.CTRL_DOWN_MASK),
KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0),
KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, KeyEvent.SHIFT_DOWN_MASK),
KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, KeyEvent.CTRL_DOWN_MASK),
KeyStroke.getKeyStroke(KeyEvent.VK_K, KeyEvent.CTRL_DOWN_MASK),
KeyStroke.getKeyStroke(KeyEvent.VK_V, KeyEvent.CTRL_DOWN_MASK),
KeyStroke.getKeyStroke(KeyEvent.VK_Q, KeyEvent.CTRL_DOWN_MASK),
KeyStroke.getKeyStroke(KeyEvent.VK_V, KeyEvent.META_DOWN_MASK),
KeyStroke.getKeyStroke(KeyEvent.VK_INSERT, KeyEvent.SHIFT_DOWN_MASK),
)
.map { KeyboardShortcut(it, null) }
.toTypedArray()
registerCustomShortcutSet({ shortcuts }, exEntryPanel)
}

View File

@ -16,11 +16,9 @@ import com.intellij.util.ui.JBUI;
import com.maddyhome.idea.vim.VimPlugin;
import com.maddyhome.idea.vim.api.VimCommandLine;
import com.maddyhome.idea.vim.api.VimCommandLineCaret;
import com.maddyhome.idea.vim.api.VimEditor;
import com.maddyhome.idea.vim.helper.UiHelper;
import com.maddyhome.idea.vim.history.HistoryConstants;
import com.maddyhome.idea.vim.history.HistoryEntry;
import com.maddyhome.idea.vim.newapi.IjVimEditor;
import com.maddyhome.idea.vim.options.helpers.GuiCursorAttributes;
import com.maddyhome.idea.vim.options.helpers.GuiCursorMode;
import com.maddyhome.idea.vim.options.helpers.GuiCursorOptionHelper;
@ -67,9 +65,6 @@ public class ExTextField extends JTextField {
// If we're in the middle of an action (e.g. entering a register to paste, or inserting a digraph), cancel it if
// the mouse is clicked anywhere. Vim's behavior is to use the mouse click as an event, which can lead to
// something like : !%!C, which I don't believe is documented, or useful
if (currentAction != null) {
clearCurrentAction();
}
super.mouseClicked(e);
}
});
@ -240,10 +235,6 @@ public class ExTextField extends JTextField {
// This gets called for ALL events, before the IDE starts to process key events for the action system. We can add a
// dispatcher that checks that the plugin is enabled, checks that the component with the focus is ExTextField,
// dispatch to ExEntryPanel#handleKey and if it's processed, mark the event as consumed.
if (currentAction != null) {
currentAction.actionPerformed(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, String.valueOf(c), modifiers));
}
else {
KeyEvent event = new KeyEvent(this, keyChar != KeyEvent.CHAR_UNDEFINED ? KeyEvent.KEY_TYPED :
(stroke.isOnKeyRelease() ? KeyEvent.KEY_RELEASED : KeyEvent.KEY_PRESSED),
(new Date()).getTime(), modifiers, keyCode, c);
@ -251,11 +242,10 @@ public class ExTextField extends JTextField {
useHandleKeyFromEx = false;
try {
super.processKeyEvent(event);
}finally {
} finally {
useHandleKeyFromEx = true;
}
}
}
@Override
protected void processKeyEvent(KeyEvent e) {
@ -279,13 +269,8 @@ public class ExTextField extends JTextField {
* Cancels current action, if there is one. If not, cancels entry.
*/
void escape() {
if (currentAction != null) {
clearCurrentAction();
}
else {
cancel();
}
}
/**
* Cancels entry, including any current action.
@ -299,19 +284,10 @@ public class ExTextField extends JTextField {
}
public void clearCurrentAction() {
if (currentAction != null) {
currentAction.reset();
}
currentAction = null;
VimCommandLine commandLine = injector.getCommandLine().getActiveCommandLine();
if (commandLine != null) commandLine.clearPromptCharacter();
}
@Nullable
Action getCurrentAction() {
return currentAction;
}
private void setInsertMode() {
ExDocument doc = (ExDocument)getDocument();
if (doc.isOverwrite()) {
@ -542,10 +518,9 @@ public class ExTextField extends JTextField {
private DataContext context;
private final CommandLineCaret caret;
private String lastEntry;
String lastEntry;
private List<HistoryEntry> history;
private int histIndex = 0;
private @Nullable MultiStepAction currentAction;
int histIndex = 0;
int currentActionPromptCharacterOffset = -1;
private static final Logger logger = Logger.getInstance(ExTextField.class.getName());

View File

@ -8,114 +8,20 @@
package com.maddyhome.idea.vim.vimscript
import com.intellij.openapi.actionSystem.DataContext
import com.intellij.openapi.components.Service
import com.intellij.openapi.diagnostic.logger
import com.intellij.openapi.fileEditor.FileDocumentManager
import com.intellij.openapi.vfs.VirtualFileManager
import com.maddyhome.idea.vim.VimPlugin
import com.maddyhome.idea.vim.api.ExecutionContext
import com.maddyhome.idea.vim.api.VimEditor
import com.maddyhome.idea.vim.api.VimScriptExecutorBase
import com.maddyhome.idea.vim.api.injector
import com.maddyhome.idea.vim.ex.ExException
import com.maddyhome.idea.vim.ex.FinishException
import com.maddyhome.idea.vim.extension.VimExtensionRegistrar
import com.maddyhome.idea.vim.history.HistoryConstants
import com.maddyhome.idea.vim.newapi.vim
import com.maddyhome.idea.vim.register.RegisterConstants.LAST_COMMAND_REGISTER
import com.maddyhome.idea.vim.vimscript.model.CommandLineVimLContext
import com.maddyhome.idea.vim.vimscript.model.ExecutionResult
import com.maddyhome.idea.vim.vimscript.model.VimLContext
import com.maddyhome.idea.vim.vimscript.model.commands.Command
import com.maddyhome.idea.vim.vimscript.model.commands.RepeatCommand
import com.maddyhome.idea.vim.vimscript.parser.VimscriptParser
import java.io.File
import java.io.IOException
@Service
internal class Executor : VimScriptExecutorBase() {
private val logger = logger<Executor>()
override var executingVimscript = false
override var executingIdeaVimRcConfiguration = false
@Throws(ExException::class)
override fun execute(script: String, editor: VimEditor, context: ExecutionContext, skipHistory: Boolean, indicateErrors: Boolean, vimContext: VimLContext?): ExecutionResult {
try {
injector.vimscriptExecutor.executingVimscript = true
var finalResult: ExecutionResult = ExecutionResult.Success
val myScript = VimscriptParser.parse(script)
myScript.units.forEach { it.vimContext = vimContext ?: myScript }
for (unit in myScript.units) {
try {
val result = unit.execute(editor, context)
if (result is ExecutionResult.Error) {
finalResult = ExecutionResult.Error
if (indicateErrors) {
VimPlugin.indicateError()
}
}
} catch (e: ExException) {
if (e is FinishException) {
break
}
finalResult = ExecutionResult.Error
if (indicateErrors) {
VimPlugin.showMessage(e.message)
VimPlugin.indicateError()
} else {
logger.warn("Failed while executing $unit. " + e.message)
}
} catch (e: NotImplementedError) {
if (indicateErrors) {
VimPlugin.showMessage("Not implemented yet :(")
VimPlugin.indicateError()
}
} catch (e: Exception) {
logger.warn(e)
if (injector.application.isUnitTest()) {
throw e
}
}
}
if (!skipHistory) {
VimPlugin.getHistory().addEntry(HistoryConstants.COMMAND, script)
if (myScript.units.size == 1 && myScript.units[0] is Command && myScript.units[0] !is RepeatCommand) {
VimPlugin.getRegister().storeTextSpecial(LAST_COMMAND_REGISTER, script)
}
}
return finalResult
} finally {
injector.vimscriptExecutor.executingVimscript = false
// Initialize any extensions that were enabled during execution of this vimscript
// See the doc of this function for details
override fun enableDelayedExtensions() {
VimExtensionRegistrar.enableDelayedExtensions()
}
}
override fun executeFile(file: File, editor: VimEditor, fileIsIdeaVimRcConfig: Boolean, indicateErrors: Boolean) {
val context = DataContext.EMPTY_CONTEXT.vim
try {
if (fileIsIdeaVimRcConfig) {
injector.vimscriptExecutor.executingIdeaVimRcConfiguration = true
}
ensureFileIsSaved(file)
execute(file.readText(), editor, context, skipHistory = true, indicateErrors)
} catch (ignored: IOException) {
LOG.error(ignored)
} finally {
if (fileIsIdeaVimRcConfig) {
injector.vimrcFileState.saveFileState(file.absolutePath)
injector.vimscriptExecutor.executingIdeaVimRcConfiguration = false
}
}
}
private fun ensureFileIsSaved(file: File) {
override fun ensureFileIsSaved(file: File) {
val documentManager = FileDocumentManager.getInstance()
VirtualFileManager.getInstance().findFileByNioPath(file.toPath())
@ -123,16 +29,4 @@ internal class Executor : VimScriptExecutorBase() {
?.takeIf(documentManager::isDocumentUnsaved)
?.let(documentManager::saveDocumentAsIs)
}
@Throws(ExException::class)
override fun executeLastCommand(editor: VimEditor, context: ExecutionContext): Boolean {
val reg = VimPlugin.getRegister().getRegister(':') ?: return false
val text = reg.text ?: return false
execute(text, editor, context, skipHistory = false, indicateErrors = true, CommandLineVimLContext)
return true
}
companion object {
val LOG = logger<Executor>()
}
}

View File

@ -45,7 +45,9 @@ internal data class ActionListCommand(val range: Range, val argument: String) :
.filter { line -> searchPattern.all { it in line.lowercase(Locale.getDefault()) } }
.joinToString(lineSeparator)
ExOutputModel.getInstance(editor.ij).output(MessageHelper.message("ex.show.all.actions.0.1", lineSeparator, actions))
val outputPanel = injector.outputPanel.getOrCreate(editor, context)
outputPanel.addText(MessageHelper.message("ex.show.all.actions.0.1", lineSeparator, actions))
outputPanel.show()
return ExecutionResult.Success
}
}

View File

@ -17,8 +17,8 @@ import com.intellij.vim.annotations.ExCommand
import com.maddyhome.idea.vim.VimPlugin
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.command.OperatorArguments
import com.maddyhome.idea.vim.ex.ExOutputModel
import com.maddyhome.idea.vim.ex.ranges.Range
import com.maddyhome.idea.vim.helper.EditorHelper
import com.maddyhome.idea.vim.helper.vimLine
@ -45,7 +45,9 @@ internal data class BufferListCommand(val range: Range, val argument: String) :
val filter = pruneUnsupportedFilters(arg)
val bufferList = getBufferList(context, filter)
ExOutputModel.getInstance(editor.ij).output(bufferList.joinToString(separator = "\n"))
val outputPanel = injector.outputPanel.getOrCreate(editor, context)
outputPanel.addText(bufferList.joinToString(separator = "\n"))
outputPanel.show()
return ExecutionResult.Success
}

View File

@ -15,6 +15,7 @@ import com.intellij.vim.annotations.ExCommand
import com.maddyhome.idea.vim.VimPlugin
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.command.OperatorArguments
import com.maddyhome.idea.vim.ex.ExException
import com.maddyhome.idea.vim.ex.ExOutputModel
@ -74,7 +75,9 @@ internal data class CmdFilterCommand(val range: Range, val argument: String) : C
if (range.size() == 0) {
// Show command output in a window
VimPlugin.getProcess().executeCommand(editor, command, null, workingDirectory)?.let {
ExOutputModel.getInstance(editor.ij).output(it)
val outputPanel = injector.outputPanel.getOrCreate(editor, context)
outputPanel.addText(it)
outputPanel.show()
}
lastCommand = command
ExecutionResult.Success

View File

@ -1,12 +1,4 @@
<!--
~ Copyright 2003-2023 The IdeaVim authors
~
~ Use of this source code is governed by an MIT-style
~ license that can be found in the LICENSE.txt file or at
~ https://opensource.org/licenses/MIT.
-->
<idea-plugin url="https://plugins.jetbrains.com/plugin/164" xmlns:xi="http://www.w3.org/2001/XInclude">
<idea-plugin xmlns:xi="http://www.w3.org/2001/XInclude">
<name>IdeaVim</name>
<id>IdeaVIM</id>
<description><![CDATA[
@ -21,7 +13,7 @@
<li><a href="https://youtrack.jetbrains.com/issues/VIM">Issue tracker</a>: feature requests and bug reports</li>
</ul>
]]></description>
<version>SNAPSHOT</version>
<version>chylex</version>
<vendor>JetBrains</vendor>
<!-- Mark the plugin as compatible with RubyMine and other products based on the IntelliJ platform (including CWM) -->
@ -133,9 +125,11 @@
<xi:include href="/META-INF/includes/VimListeners.xml" xpointer="xpointer(/idea-plugin/*)"/>
<actions resource-bundle="messages.IdeaVimBundle">
<action id="VimPluginToggle" class="com.maddyhome.idea.vim.action.VimPluginToggleAction">
<group id="com.chylex.intellij.vim" text="Vim" popup="true">
<add-to-group group-id="ToolsMenu" anchor="last"/>
</action>
<action id="VimPluginToggle" class="com.maddyhome.idea.vim.action.VimPluginToggleAction"/>
<action id="VimRunLastMacroInOpenFiles" class="com.maddyhome.idea.vim.action.VimRunLastMacroInOpenFiles"/>
</group>
<!-- Internal -->
<!--suppress PluginXmlI18n -->
@ -154,5 +148,6 @@
</group>
<action id="VimFindActionIdAction" class="com.maddyhome.idea.vim.listener.FindActionIdAction"/>
<action id="VimJumpToSource" class="com.intellij.diff.actions.impl.OpenInEditorAction" />
</actions>
</idea-plugin>

View File

@ -0,0 +1,92 @@
[
{
"keys": ".",
"class": "com.maddyhome.idea.vim.action.change.RepeatChangeAction",
"modes": "N"
},
{
"keys": "<BS>",
"class": "com.maddyhome.idea.vim.action.editor.VimEditorBackSpace",
"modes": "I"
},
{
"keys": "<C-H>",
"class": "com.maddyhome.idea.vim.action.editor.VimEditorBackSpace",
"modes": "I"
},
{
"keys": "<C-I>",
"class": "com.maddyhome.idea.vim.action.editor.VimEditorTab",
"modes": "I"
},
{
"keys": "<C-L>",
"class": "com.maddyhome.idea.vim.action.RedrawAction",
"modes": "N"
},
{
"keys": "<Del>",
"class": "com.maddyhome.idea.vim.action.editor.VimEditorDelete",
"modes": "I"
},
{
"keys": "<Down>",
"class": "com.maddyhome.idea.vim.action.editor.VimEditorDown",
"modes": "I"
},
{
"keys": "<Tab>",
"class": "com.maddyhome.idea.vim.action.editor.VimEditorTab",
"modes": "I"
},
{
"keys": "<Up>",
"class": "com.maddyhome.idea.vim.action.editor.VimEditorUp",
"modes": "I"
},
{
"keys": "<kDown>",
"class": "com.maddyhome.idea.vim.action.editor.VimEditorDown",
"modes": "I"
},
{
"keys": "<kUp>",
"class": "com.maddyhome.idea.vim.action.editor.VimEditorUp",
"modes": "I"
},
{
"keys": "J",
"class": "com.maddyhome.idea.vim.action.change.delete.DeleteJoinLinesSpacesAction",
"modes": "N"
},
{
"keys": "J",
"class": "com.maddyhome.idea.vim.action.change.delete.DeleteJoinVisualLinesSpacesAction",
"modes": "X"
},
{
"keys": "K",
"class": "com.maddyhome.idea.vim.action.editor.VimQuickJavaDoc",
"modes": "N"
},
{
"keys": "g@",
"class": "com.maddyhome.idea.vim.action.change.OperatorAction",
"modes": "N"
},
{
"keys": "g@",
"class": "com.maddyhome.idea.vim.action.change.VisualOperatorAction",
"modes": "X"
},
{
"keys": "gJ",
"class": "com.maddyhome.idea.vim.action.change.delete.DeleteJoinLinesAction",
"modes": "N"
},
{
"keys": "gJ",
"class": "com.maddyhome.idea.vim.action.change.delete.DeleteJoinVisualLinesAction",
"modes": "X"
}
]

View File

@ -0,0 +1,9 @@
{
"!": "com.maddyhome.idea.vim.vimscript.model.commands.CmdFilterCommand",
"actionl[ist]": "com.maddyhome.idea.vim.vimscript.model.commands.ActionListCommand",
"b[uffer]": "com.maddyhome.idea.vim.vimscript.model.commands.BufferCommand",
"buffers": "com.maddyhome.idea.vim.vimscript.model.commands.BufferListCommand",
"files": "com.maddyhome.idea.vim.vimscript.model.commands.BufferListCommand",
"h[elp]": "com.maddyhome.idea.vim.vimscript.model.commands.HelpCommand",
"ls": "com.maddyhome.idea.vim.vimscript.model.commands.BufferListCommand"
}

View File

@ -0,0 +1,6 @@
{
"col": "com.maddyhome.idea.vim.vimscript.model.functions.handlers.ColFunctionHandler",
"has": "com.maddyhome.idea.vim.vimscript.model.functions.handlers.HasFunctionHandler",
"line": "com.maddyhome.idea.vim.vimscript.model.functions.handlers.LineFunctionHandler",
"submatch": "com.maddyhome.idea.vim.vimscript.model.functions.handlers.SubmatchFunctionHandler"
}

View File

@ -13,7 +13,6 @@ import com.maddyhome.idea.vim.action.motion.search.SearchWholeWordForwardAction
import com.maddyhome.idea.vim.api.injector
import com.maddyhome.idea.vim.common.TextRange
import com.maddyhome.idea.vim.newapi.IjVimEditor
import com.maddyhome.idea.vim.newapi.vim
import com.maddyhome.idea.vim.state.mode.SelectionType
import org.jetbrains.plugins.ideavim.VimBehaviorDiffers
import org.jetbrains.plugins.ideavim.VimTestCase
@ -2173,7 +2172,7 @@ rtyfg${c}hzxc"""
val editor = configureByText(before)
injector.registerGroup.storeText('*', "fgh")
VimPlugin.getRegister()
.storeText(IjVimEditor(editor), editor.vim.primaryCaret(), TextRange(16, 19), SelectionType.CHARACTER_WISE, false)
.storeText(IjVimEditor(editor), TextRange(16, 19), SelectionType.CHARACTER_WISE, false)
typeText(injector.parser.parseKeys("\"*P"))
val after = "fg${c}hqfg${c}hwe asd zxc rty fg${c}hfgh vbn"
assertState(after)

View File

@ -33,7 +33,7 @@ class IdeaPutNotificationsTest : VimTestCase() {
appReadySetup(false)
val vimEditor = fixture.editor.vim
VimPlugin.getRegister()
.storeText(vimEditor, vimEditor.primaryCaret(), before rangeOf "legendary", SelectionType.CHARACTER_WISE, false)
.storeText(vimEditor, before rangeOf "legendary", SelectionType.CHARACTER_WISE, false)
typeText(injector.parser.parseKeys("p"))
val notification = notifications().last()
@ -53,7 +53,7 @@ class IdeaPutNotificationsTest : VimTestCase() {
appReadySetup(false)
val vimEditor = fixture.editor.vim
VimPlugin.getRegister()
.storeText(vimEditor, vimEditor.primaryCaret(), before rangeOf "legendary", SelectionType.CHARACTER_WISE, false)
.storeText(vimEditor, before rangeOf "legendary", SelectionType.CHARACTER_WISE, false)
typeText(injector.parser.parseKeys("p"))
val notifications = notifications()
@ -71,7 +71,7 @@ class IdeaPutNotificationsTest : VimTestCase() {
appReadySetup(true)
val vimEditor = fixture.editor.vim
VimPlugin.getRegister()
.storeText(vimEditor, vimEditor.primaryCaret(), before rangeOf "legendary", SelectionType.CHARACTER_WISE, false)
.storeText(vimEditor, before rangeOf "legendary", SelectionType.CHARACTER_WISE, false)
typeText(injector.parser.parseKeys("p"))
val notifications = EventLog.getLogModel(fixture.project).notifications

View File

@ -88,7 +88,7 @@ class PutTestAfterCursorActionTest : VimTestCase() {
val editor = configureByText(before)
val vimEditor = editor.vim
VimPlugin.getRegister()
.storeText(vimEditor, vimEditor.primaryCaret(), before rangeOf "A Discovery\n", SelectionType.LINE_WISE, false)
.storeText(vimEditor, before rangeOf "A Discovery\n", SelectionType.LINE_WISE, false)
typeText(injector.parser.parseKeys("p"))
val after = """
A Discovery
@ -127,7 +127,6 @@ class PutTestAfterCursorActionTest : VimTestCase() {
val vimEditor = editor.vim
injector.registerGroup.storeText(
vimEditor,
vimEditor.primaryCaret(),
before rangeOf "I found it in a legendary land\n",
SelectionType.LINE_WISE,
false,
@ -157,7 +156,7 @@ class PutTestAfterCursorActionTest : VimTestCase() {
val editor = configureByText(before)
val vimEditor = editor.vim
VimPlugin.getRegister()
.storeText(vimEditor, vimEditor.primaryCaret(), before rangeOf "Discovery", SelectionType.CHARACTER_WISE, false)
.storeText(vimEditor, before rangeOf "Discovery", SelectionType.CHARACTER_WISE, false)
typeText(injector.parser.parseKeys("vep"))
val after = """
A Discovery

View File

@ -31,7 +31,7 @@ class PutTextBeforeCursorActionTest : VimTestCase() {
""".trimIndent()
val editor = configureByText(before)
val vimEditor = editor.vim
injector.registerGroup.storeText(vimEditor, vimEditor.primaryCaret(), before rangeOf "Discovery", SelectionType.CHARACTER_WISE, false)
injector.registerGroup.storeText(vimEditor, before rangeOf "Discovery", SelectionType.CHARACTER_WISE, false)
typeText(injector.parser.parseKeys("V" + "P"))
typeText(injector.parser.parseKeys("V" + "P"))
val after = """

View File

@ -54,7 +54,7 @@ class PutViaIdeaTest : VimTestCase() {
val vimEditor = fixture.editor.vim
VimPlugin.getRegister()
.storeText(vimEditor, vimEditor.primaryCaret(), before rangeOf "legendary", SelectionType.CHARACTER_WISE, false)
.storeText(vimEditor, before rangeOf "legendary", SelectionType.CHARACTER_WISE, false)
typeText("ppp")
val after = "Ilegendarylegendarylegendar${c}y found it in a legendary land"
@ -74,7 +74,6 @@ class PutViaIdeaTest : VimTestCase() {
VimPlugin.getRegister()
.storeText(
vimEditor,
vimEditor.primaryCaret(),
before rangeOf "legendary$randomUUID",
SelectionType.CHARACTER_WISE,
false,
@ -100,7 +99,6 @@ class PutViaIdeaTest : VimTestCase() {
val vimEditor = fixture.editor.vim
VimPlugin.getRegister().storeText(
vimEditor,
vimEditor.primaryCaret(),
before rangeOf "\nLorem ipsum dolor sit amet,\n",
SelectionType.CHARACTER_WISE,
false,

View File

@ -75,7 +75,7 @@ class PutVisualTextActionTest : VimTestCase() {
val before = "${c}I found it in a legendary land"
val editor = configureByText(before)
val vimEditor = editor.vim
VimPlugin.getRegister().storeText(vimEditor, vimEditor.primaryCaret(), before rangeOf "legendary", SelectionType.CHARACTER_WISE, false)
VimPlugin.getRegister().storeText(vimEditor, before rangeOf "legendary", SelectionType.CHARACTER_WISE, false)
typeText(injector.parser.parseKeys("ve" + "p"))
val after = "legendar${c}y it in a legendary land"
assertState(after)
@ -87,7 +87,7 @@ class PutVisualTextActionTest : VimTestCase() {
val before = "${c}I found it in a legendary land"
val editor = configureByText(before)
val vimEditor = editor.vim
VimPlugin.getRegister().storeText(vimEditor, vimEditor.primaryCaret(), before rangeOf "legendary", SelectionType.CHARACTER_WISE, false)
VimPlugin.getRegister().storeText(vimEditor, before rangeOf "legendary", SelectionType.CHARACTER_WISE, false)
typeText(injector.parser.parseKeys("v2e" + "2p"))
val after = "legendarylegendar${c}y in a legendary land"
assertState(after)
@ -99,7 +99,7 @@ class PutVisualTextActionTest : VimTestCase() {
val before = "${c}I found it in a legendary land"
val editor = configureByText(before)
val vimEditor = editor.vim
VimPlugin.getRegister().storeText(vimEditor, vimEditor.primaryCaret(), before rangeOf "legendary", SelectionType.CHARACTER_WISE, false)
VimPlugin.getRegister().storeText(vimEditor, before rangeOf "legendary", SelectionType.CHARACTER_WISE, false)
typeText(injector.parser.parseKeys("v$" + "2p"))
val after = "legendarylegendar${c}y"
assertState(after)
@ -133,7 +133,7 @@ class PutVisualTextActionTest : VimTestCase() {
val before = "I foun${c}d it in a legendary land"
val editor = configureByText(before)
val vimEditor = editor.vim
VimPlugin.getRegister().storeText(vimEditor, vimEditor.primaryCaret(), before rangeOf "legendary", SelectionType.CHARACTER_WISE, false)
VimPlugin.getRegister().storeText(vimEditor, before rangeOf "legendary", SelectionType.CHARACTER_WISE, false)
typeText(injector.parser.parseKeys("vb" + "p"))
val after = "I legendar${c}y it in a legendary land"
assertState(after)
@ -154,7 +154,7 @@ class PutVisualTextActionTest : VimTestCase() {
""".trimIndent()
val editor = configureByText(before)
val vimEditor = editor.vim
VimPlugin.getRegister().storeText(vimEditor, vimEditor.primaryCaret(), before rangeOf "A Discovery\n", SelectionType.LINE_WISE, false)
VimPlugin.getRegister().storeText(vimEditor, before rangeOf "A Discovery\n", SelectionType.LINE_WISE, false)
typeText(injector.parser.parseKeys("ve" + "p"))
val after = """
A Discovery
@ -182,7 +182,7 @@ class PutVisualTextActionTest : VimTestCase() {
""".trimIndent()
val editor = configureByText(before)
val vimEditor = editor.vim
VimPlugin.getRegister().storeText(vimEditor, vimEditor.primaryCaret(), before rangeOf "A Discovery\n", SelectionType.LINE_WISE, false)
VimPlugin.getRegister().storeText(vimEditor, before rangeOf "A Discovery\n", SelectionType.LINE_WISE, false)
typeText(injector.parser.parseKeys("ve" + "p"))
val after = """
A Discovery
@ -210,7 +210,7 @@ class PutVisualTextActionTest : VimTestCase() {
""".trimIndent()
val editor = configureByText(before)
val vimEditor = editor.vim
VimPlugin.getRegister().storeText(vimEditor, vimEditor.primaryCaret(), before rangeOf "A Discovery\n", SelectionType.LINE_WISE, false)
VimPlugin.getRegister().storeText(vimEditor, before rangeOf "A Discovery\n", SelectionType.LINE_WISE, false)
typeText(injector.parser.parseKeys("ve" + "p"))
val after = """
A Discovery
@ -238,7 +238,7 @@ class PutVisualTextActionTest : VimTestCase() {
""".trimIndent()
val editor = configureByText(before)
val vimEditor = editor.vim
VimPlugin.getRegister().storeText(vimEditor, vimEditor.primaryCaret(), before rangeOf "A Discovery\n", SelectionType.LINE_WISE, false)
VimPlugin.getRegister().storeText(vimEditor, before rangeOf "A Discovery\n", SelectionType.LINE_WISE, false)
typeText(injector.parser.parseKeys("v$" + "p"))
val after = """
A Discovery
@ -455,7 +455,7 @@ class PutVisualTextActionTest : VimTestCase() {
""".trimIndent()
val editor = configureByText(before)
val vimEditor = editor.vim
VimPlugin.getRegister().storeText(vimEditor, vimEditor.primaryCaret(), editor.rangeOf("|found|", 2), SelectionType.BLOCK_WISE, false)
VimPlugin.getRegister().storeText(vimEditor, editor.rangeOf("|found|", 2), SelectionType.BLOCK_WISE, false)
typeText(injector.parser.parseKeys("ve" + "p"))
val after = """
A Discovery
@ -491,7 +491,7 @@ class PutVisualTextActionTest : VimTestCase() {
""".trimIndent()
val editor = configureByText(before)
val vimEditor = editor.vim
VimPlugin.getRegister().storeText(vimEditor, vimEditor.primaryCaret(), editor.rangeOf("|found|", 2), SelectionType.BLOCK_WISE, false)
VimPlugin.getRegister().storeText(vimEditor, editor.rangeOf("|found|", 2), SelectionType.BLOCK_WISE, false)
typeText(injector.parser.parseKeys("ve" + "p"))
val after = """
A Discovery
@ -529,7 +529,7 @@ class PutVisualTextActionTest : VimTestCase() {
""".trimIndent()
val editor = configureByText(before)
val vimEditor = editor.vim
VimPlugin.getRegister().storeText(vimEditor, vimEditor.primaryCaret(), editor.rangeOf("|found|", 2), SelectionType.BLOCK_WISE, false)
VimPlugin.getRegister().storeText(vimEditor, editor.rangeOf("|found|", 2), SelectionType.BLOCK_WISE, false)
typeText(injector.parser.parseKeys("ve" + "2p"))
val after = """
A Discovery
@ -640,7 +640,7 @@ class PutVisualTextActionTest : VimTestCase() {
""".trimIndent()
val editor = configureByText(before)
val vimEditor = editor.vim
VimPlugin.getRegister().storeText(vimEditor, vimEditor.primaryCaret(), before rangeOf "Discovery", SelectionType.CHARACTER_WISE, false)
VimPlugin.getRegister().storeText(vimEditor, before rangeOf "Discovery", SelectionType.CHARACTER_WISE, false)
typeText(injector.parser.parseKeys("V" + "p"))
val after = """
A Discovery
@ -666,7 +666,7 @@ class PutVisualTextActionTest : VimTestCase() {
""".trimIndent()
val editor = configureByText(before)
val vimEditor = editor.vim
VimPlugin.getRegister().storeText(vimEditor, vimEditor.primaryCaret(), before rangeOf "Discovery", SelectionType.CHARACTER_WISE, false)
VimPlugin.getRegister().storeText(vimEditor, before rangeOf "Discovery", SelectionType.CHARACTER_WISE, false)
typeText(injector.parser.parseKeys("V" + "2p"))
val after = """
A Discovery
@ -703,7 +703,7 @@ class PutVisualTextActionTest : VimTestCase() {
""".trimIndent()
val editor = configureByText(before)
val vimEditor = editor.vim
VimPlugin.getRegister().storeText(vimEditor, vimEditor.primaryCaret(), before rangeOf "Discovery", SelectionType.CHARACTER_WISE, false)
VimPlugin.getRegister().storeText(vimEditor, before rangeOf "Discovery", SelectionType.CHARACTER_WISE, false)
typeText(injector.parser.parseKeys("V" + "p"))
val after = """
A Discovery
@ -876,7 +876,7 @@ class PutVisualTextActionTest : VimTestCase() {
""".trimIndent()
val editor = configureByText(before)
val vimEditor = editor.vim
VimPlugin.getRegister().storeText(vimEditor, vimEditor.primaryCaret(), before rangeOf "A Discovery\n", SelectionType.LINE_WISE, false)
VimPlugin.getRegister().storeText(vimEditor, before rangeOf "A Discovery\n", SelectionType.LINE_WISE, false)
typeText(injector.parser.parseKeys("V" + "p"))
val after = """
A Discovery
@ -902,7 +902,7 @@ class PutVisualTextActionTest : VimTestCase() {
""".trimIndent()
val editor = configureByText(before)
val vimEditor = editor.vim
VimPlugin.getRegister().storeText(vimEditor, vimEditor.primaryCaret(), before rangeOf "A Discovery\n", SelectionType.LINE_WISE, false)
VimPlugin.getRegister().storeText(vimEditor, before rangeOf "A Discovery\n", SelectionType.LINE_WISE, false)
typeText(injector.parser.parseKeys("V" + "2p"))
val after = """
A Discovery
@ -939,7 +939,7 @@ class PutVisualTextActionTest : VimTestCase() {
""".trimIndent()
val editor = configureByText(before)
val vimEditor = editor.vim
VimPlugin.getRegister().storeText(vimEditor, vimEditor.primaryCaret(), before rangeOf "A Discovery\n", SelectionType.LINE_WISE, false)
VimPlugin.getRegister().storeText(vimEditor, before rangeOf "A Discovery\n", SelectionType.LINE_WISE, false)
typeText(injector.parser.parseKeys("V" + "p"))
val after = """
A Discovery
@ -1117,7 +1117,7 @@ class PutVisualTextActionTest : VimTestCase() {
""".trimIndent()
val editor = configureByText(before)
val vimEditor = editor.vim
VimPlugin.getRegister().storeText(vimEditor, vimEditor.primaryCaret(), editor.rangeOf("|found|", 2), SelectionType.BLOCK_WISE, false)
VimPlugin.getRegister().storeText(vimEditor, editor.rangeOf("|found|", 2), SelectionType.BLOCK_WISE, false)
typeText(injector.parser.parseKeys("V" + "p"))
val after = """
A Discovery
@ -1172,7 +1172,7 @@ class PutVisualTextActionTest : VimTestCase() {
""".trimIndent()
val editor = configureByText(before)
val vimEditor = editor.vim
VimPlugin.getRegister().storeText(vimEditor, vimEditor.primaryCaret(), editor.rangeOf("|found|", 2), SelectionType.BLOCK_WISE, false)
VimPlugin.getRegister().storeText(vimEditor, editor.rangeOf("|found|", 2), SelectionType.BLOCK_WISE, false)
typeText(injector.parser.parseKeys("V" + "p"))
val after = """
A Discovery
@ -1233,7 +1233,7 @@ class PutVisualTextActionTest : VimTestCase() {
""".trimIndent()
val editor = configureByText(before)
val vimEditor = editor.vim
VimPlugin.getRegister().storeText(vimEditor, vimEditor.primaryCaret(), editor.rangeOf("|found|", 2), SelectionType.BLOCK_WISE, false)
VimPlugin.getRegister().storeText(vimEditor, editor.rangeOf("|found|", 2), SelectionType.BLOCK_WISE, false)
typeText(injector.parser.parseKeys("V" + "2p"))
val after = """
A Discovery
@ -1409,7 +1409,7 @@ class PutVisualTextActionTest : VimTestCase() {
""".trimIndent()
val editor = configureByText(before)
val vimEditor = editor.vim
VimPlugin.getRegister().storeText(vimEditor, vimEditor.primaryCaret(), before rangeOf "Discovery", SelectionType.CHARACTER_WISE, false)
VimPlugin.getRegister().storeText(vimEditor, before rangeOf "Discovery", SelectionType.CHARACTER_WISE, false)
typeText(injector.parser.parseKeys("<C-V>2e2j" + "p"))
val after = """
A Discovery
@ -1435,7 +1435,7 @@ class PutVisualTextActionTest : VimTestCase() {
""".trimIndent()
val editor = configureByText(before)
val vimEditor = editor.vim
VimPlugin.getRegister().storeText(vimEditor, vimEditor.primaryCaret(), before rangeOf "Discovery", SelectionType.CHARACTER_WISE, false)
VimPlugin.getRegister().storeText(vimEditor, before rangeOf "Discovery", SelectionType.CHARACTER_WISE, false)
typeText(injector.parser.parseKeys("<C-V>3e2k" + "p"))
val after = """
A Discovery
@ -1461,7 +1461,7 @@ class PutVisualTextActionTest : VimTestCase() {
""".trimIndent()
val editor = configureByText(before)
val vimEditor = editor.vim
VimPlugin.getRegister().storeText(vimEditor, vimEditor.primaryCaret(), before rangeOf "Discovery", SelectionType.CHARACTER_WISE, false)
VimPlugin.getRegister().storeText(vimEditor, before rangeOf "Discovery", SelectionType.CHARACTER_WISE, false)
typeText(injector.parser.parseKeys("<C-V>2e2j" + "2p"))
val after = """
A Discovery
@ -1487,7 +1487,7 @@ class PutVisualTextActionTest : VimTestCase() {
""".trimIndent()
val editor = configureByText(before)
val vimEditor = editor.vim
VimPlugin.getRegister().storeText(vimEditor, vimEditor.primaryCaret(), before rangeOf "Discovery", SelectionType.CHARACTER_WISE, false)
VimPlugin.getRegister().storeText(vimEditor, before rangeOf "Discovery", SelectionType.CHARACTER_WISE, false)
typeText(injector.parser.parseKeys("<C-V>3j$" + "p"))
val after = """
A Discovery
@ -1526,7 +1526,7 @@ class PutVisualTextActionTest : VimTestCase() {
""".trimIndent()
val editor = configureByText(before)
val vimEditor = editor.vim
VimPlugin.getRegister().storeText(vimEditor, vimEditor.primaryCaret(), before rangeOf "A Discovery\n", SelectionType.LINE_WISE, false)
VimPlugin.getRegister().storeText(vimEditor, before rangeOf "A Discovery\n", SelectionType.LINE_WISE, false)
typeText(injector.parser.parseKeys("<C-V>2e2j" + "p"))
val after = """
A Discovery
@ -1554,7 +1554,7 @@ class PutVisualTextActionTest : VimTestCase() {
""".trimIndent()
val editor = configureByText(before)
val vimEditor = editor.vim
VimPlugin.getRegister().storeText(vimEditor, vimEditor.primaryCaret(), before rangeOf "A Discovery\n", SelectionType.LINE_WISE, false)
VimPlugin.getRegister().storeText(vimEditor, before rangeOf "A Discovery\n", SelectionType.LINE_WISE, false)
typeText(injector.parser.parseKeys("<C-V>2e2j" + "P"))
val after = """
A Discovery
@ -1593,7 +1593,7 @@ class PutVisualTextActionTest : VimTestCase() {
""".trimIndent()
val editor = configureByText(before)
val vimEditor = editor.vim
VimPlugin.getRegister().storeText(vimEditor, vimEditor.primaryCaret(), before rangeOf "A Discovery\n", SelectionType.LINE_WISE, false)
VimPlugin.getRegister().storeText(vimEditor, before rangeOf "A Discovery\n", SelectionType.LINE_WISE, false)
typeText(injector.parser.parseKeys("<C-V>2e2j" + "2p"))
val after = """
A Discovery
@ -1633,7 +1633,7 @@ class PutVisualTextActionTest : VimTestCase() {
""".trimIndent()
val editor = configureByText(before)
val vimEditor = editor.vim
VimPlugin.getRegister().storeText(vimEditor, vimEditor.primaryCaret(), before rangeOf "A Discovery\n", SelectionType.LINE_WISE, false)
VimPlugin.getRegister().storeText(vimEditor, before rangeOf "A Discovery\n", SelectionType.LINE_WISE, false)
typeText(injector.parser.parseKeys("<C-V>2e3j" + "p"))
val after = """
A Discovery
@ -1672,7 +1672,7 @@ class PutVisualTextActionTest : VimTestCase() {
""".trimIndent()
val editor = configureByText(before)
val vimEditor = editor.vim
VimPlugin.getRegister().storeText(vimEditor, vimEditor.primaryCaret(), before rangeOf "A Discovery\n", SelectionType.LINE_WISE, false)
VimPlugin.getRegister().storeText(vimEditor, before rangeOf "A Discovery\n", SelectionType.LINE_WISE, false)
typeText(injector.parser.parseKeys("<C-V>2j$" + "p"))
val after = """
A Discovery
@ -1707,7 +1707,7 @@ class PutVisualTextActionTest : VimTestCase() {
""".trimIndent()
val editor = configureByText(before)
val vimEditor = editor.vim
VimPlugin.getRegister().storeText(vimEditor, vimEditor.primaryCaret(), editor.rangeOf("|found|", 2), SelectionType.BLOCK_WISE, false)
VimPlugin.getRegister().storeText(vimEditor, editor.rangeOf("|found|", 2), SelectionType.BLOCK_WISE, false)
typeText(injector.parser.parseKeys("<C-V>2e2j" + "p"))
val after = """
A Discovery
@ -1743,7 +1743,7 @@ class PutVisualTextActionTest : VimTestCase() {
""".trimIndent()
val editor = configureByText(before)
val vimEditor = editor.vim
VimPlugin.getRegister().storeText(vimEditor, vimEditor.primaryCaret(), editor.rangeOf("|found|", 2), SelectionType.BLOCK_WISE, false)
VimPlugin.getRegister().storeText(vimEditor, editor.rangeOf("|found|", 2), SelectionType.BLOCK_WISE, false)
typeText(injector.parser.parseKeys("<C-V>2e3j" + "p"))
val after = """
A Discovery
@ -1779,7 +1779,7 @@ class PutVisualTextActionTest : VimTestCase() {
""".trimIndent()
val editor = configureByText(before)
val vimEditor = editor.vim
VimPlugin.getRegister().storeText(vimEditor, vimEditor.primaryCaret(), editor.rangeOf("|found|", 2), SelectionType.BLOCK_WISE, false)
VimPlugin.getRegister().storeText(vimEditor, editor.rangeOf("|found|", 2), SelectionType.BLOCK_WISE, false)
typeText(injector.parser.parseKeys("<C-V>2ej" + "p"))
val after = """
A Discovery
@ -1815,7 +1815,7 @@ class PutVisualTextActionTest : VimTestCase() {
""".trimIndent()
val editor = configureByText(before)
val vimEditor = editor.vim
VimPlugin.getRegister().storeText(vimEditor, vimEditor.primaryCaret(), editor.rangeOf("|found|", 2), SelectionType.BLOCK_WISE, false)
VimPlugin.getRegister().storeText(vimEditor, editor.rangeOf("|found|", 2), SelectionType.BLOCK_WISE, false)
typeText(injector.parser.parseKeys("<C-V>elj" + "p"))
val after = """
A Discovery
@ -1852,7 +1852,7 @@ class PutVisualTextActionTest : VimTestCase() {
""".trimIndent()
val editor = configureByText(before)
val vimEditor = editor.vim
VimPlugin.getRegister().storeText(vimEditor, vimEditor.primaryCaret(), editor.rangeOf("|found|", 2), SelectionType.BLOCK_WISE, false)
VimPlugin.getRegister().storeText(vimEditor, editor.rangeOf("|found|", 2), SelectionType.BLOCK_WISE, false)
typeText(injector.parser.parseKeys("<C-V>2j$" + "p"))
val after = """
A Discovery

View File

@ -33,7 +33,7 @@ class PutVisualTextMoveCursorActionTest : VimTestCase() {
val before = "${c}I found it in a legendary land"
val editor = configureByText(before)
val vimEditor = editor.vim
VimPlugin.getRegister().storeText(vimEditor, vimEditor.primaryCaret(), TextRange(16, 25), SelectionType.CHARACTER_WISE, false)
VimPlugin.getRegister().storeText(vimEditor, TextRange(16, 25), SelectionType.CHARACTER_WISE, false)
typeText(injector.parser.parseKeys("v2e" + "2gp"))
val after = "legendarylegendary$c in a legendary land"
assertState(after)
@ -45,7 +45,7 @@ class PutVisualTextMoveCursorActionTest : VimTestCase() {
val before = "${c}I found it in a legendary land"
val editor = configureByText(before)
val vimEditor = editor.vim
VimPlugin.getRegister().storeText(vimEditor, vimEditor.primaryCaret(), TextRange(16, 25), SelectionType.LINE_WISE, false)
VimPlugin.getRegister().storeText(vimEditor, TextRange(16, 25), SelectionType.LINE_WISE, false)
typeText(injector.parser.parseKeys("v2e" + "gp"))
val after = """
@ -61,7 +61,7 @@ class PutVisualTextMoveCursorActionTest : VimTestCase() {
val before = "${c}I found it in a legendary land"
val editor = configureByText(before)
val vimEditor = editor.vim
VimPlugin.getRegister().storeText(vimEditor, vimEditor.primaryCaret(), TextRange(16, 25), SelectionType.CHARACTER_WISE, false)
VimPlugin.getRegister().storeText(vimEditor, TextRange(16, 25), SelectionType.CHARACTER_WISE, false)
typeText(injector.parser.parseKeys("V" + "gp"))
val after = "legendary\n$c"
assertState(after)
@ -88,7 +88,7 @@ class PutVisualTextMoveCursorActionTest : VimTestCase() {
""".trimIndent()
val editor = configureByText(file)
val vimEditor = editor.vim
VimPlugin.getRegister().storeText(vimEditor, vimEditor.primaryCaret(), TextRange(2, 11), SelectionType.LINE_WISE, false)
VimPlugin.getRegister().storeText(vimEditor, TextRange(2, 11), SelectionType.LINE_WISE, false)
typeText(injector.parser.parseKeys("V" + "gp"))
assertState(newFile)
}
@ -134,7 +134,7 @@ class PutVisualTextMoveCursorActionTest : VimTestCase() {
val before = "${c}I found it in a legendary land"
val editor = configureByText(before)
val vimEditor = editor.vim
VimPlugin.getRegister().storeText(vimEditor, vimEditor.primaryCaret(), TextRange(16, 25), SelectionType.LINE_WISE, false)
VimPlugin.getRegister().storeText(vimEditor, TextRange(16, 25), SelectionType.LINE_WISE, false)
typeText(injector.parser.parseKeys("v2e" + "gP"))
val after = """
@ -150,7 +150,7 @@ class PutVisualTextMoveCursorActionTest : VimTestCase() {
val before = "${c}I found it in a legendary land"
val editor = configureByText(before)
val vimEditor = editor.vim
VimPlugin.getRegister().storeText(vimEditor, vimEditor.primaryCaret(), TextRange(16, 25), SelectionType.CHARACTER_WISE, false)
VimPlugin.getRegister().storeText(vimEditor, TextRange(16, 25), SelectionType.CHARACTER_WISE, false)
typeText(injector.parser.parseKeys("v2e" + "2gP"))
val after = "legendarylegendary$c in a legendary land"
assertState(after)
@ -162,7 +162,7 @@ class PutVisualTextMoveCursorActionTest : VimTestCase() {
val before = "${c}I found it in a legendary land"
val editor = configureByText(before)
val vimEditor = editor.vim
VimPlugin.getRegister().storeText(vimEditor, vimEditor.primaryCaret(), TextRange(16, 25), SelectionType.CHARACTER_WISE, false)
VimPlugin.getRegister().storeText(vimEditor, TextRange(16, 25), SelectionType.CHARACTER_WISE, false)
typeText(injector.parser.parseKeys("v$" + "2gP"))
val after = "legendarylegendar${c}y"
assertState(after)
@ -174,7 +174,7 @@ class PutVisualTextMoveCursorActionTest : VimTestCase() {
val before = "${c}I found it in a legendary land"
val editor = configureByText(before)
val vimEditor = editor.vim
VimPlugin.getRegister().storeText(vimEditor, vimEditor.primaryCaret(), TextRange(16, 25), SelectionType.CHARACTER_WISE, false)
VimPlugin.getRegister().storeText(vimEditor, TextRange(16, 25), SelectionType.CHARACTER_WISE, false)
typeText(injector.parser.parseKeys("V" + "gP"))
val after = "legendary\n$c"
assertState(after)
@ -273,7 +273,7 @@ class PutVisualTextMoveCursorActionTest : VimTestCase() {
""".trimIndent()
val editor = configureByText(before)
val vimEditor = editor.vim
VimPlugin.getRegister().storeText(vimEditor, vimEditor.primaryCaret(), TextRange(16, 19), SelectionType.BLOCK_WISE, false)
VimPlugin.getRegister().storeText(vimEditor, TextRange(16, 19), SelectionType.BLOCK_WISE, false)
typeText(injector.parser.parseKeys("<S-v>" + "gp"))
val after = """
${c}fgh
@ -299,7 +299,7 @@ class PutVisualTextMoveCursorActionTest : VimTestCase() {
""".trimIndent()
val editor = configureByText(before)
val vimEditor = editor.vim
VimPlugin.getRegister().storeText(vimEditor, vimEditor.primaryCaret(), TextRange(16, 19), SelectionType.LINE_WISE, false)
VimPlugin.getRegister().storeText(vimEditor, TextRange(16, 19), SelectionType.LINE_WISE, false)
typeText(injector.parser.parseKeys("<C-v>" + "h" + "gp"))
val after = """
q
@ -320,7 +320,7 @@ class PutVisualTextMoveCursorActionTest : VimTestCase() {
val before = "${c}qwe asd ${c}zxc rty ${c}fgh vbn"
val editor = configureByText(before)
val vimEditor = editor.vim
VimPlugin.getRegister().storeText(vimEditor, vimEditor.primaryCaret(), TextRange(16, 19), SelectionType.CHARACTER_WISE, false)
VimPlugin.getRegister().storeText(vimEditor, TextRange(16, 19), SelectionType.CHARACTER_WISE, false)
typeText(injector.parser.parseKeys("v2e" + "2gp"))
val after = "fghfgh$c fghfgh$c fghfgh$c"
assertState(after)

View File

@ -91,7 +91,7 @@ class YankVisualActionTest : VimTestCase() {
typeText(injector.parser.parseKeys("viw" + "y"))
val editor = fixture.editor.vim
val lastRegister = injector.registerGroup.lastRegisterChar
val registers = editor.carets().map { it.registerStorage.getRegister(lastRegister)?.rawText }
val registers = editor.carets().map { injector.registerGroup.getRegister(lastRegister)?.rawText }
kotlin.test.assertEquals(listOf("found", "was"), registers)
}
@ -172,7 +172,7 @@ class YankVisualActionTest : VimTestCase() {
typeText(injector.parser.parseKeys("V" + "y"))
val editor = fixture.editor.vim
val lastRegister = injector.registerGroup.lastRegisterChar
val registers = editor.carets().map { it.registerStorage.getRegister(lastRegister)?.rawText }
val registers = editor.carets().map { injector.registerGroup.getRegister(lastRegister)?.rawText }
kotlin.test.assertEquals(
listOf("all rocks and lavender and tufted grass,\n", "hard by the torrent of a mountain pass.\n"),
registers,

View File

@ -294,20 +294,20 @@ class ExEntryTest : VimTestCase() {
// assertExText("set incsearch")
typeExInput(":<S-Up>")
assertExText("set digraph")
typeText("<Up>")
assertExText("set incsearch")
typeText("<Up>")
assertExText("digraph")
typeText("<Up>")
assertExText("set digraph")
deactivateExEntry()
typeExInput(":<PageUp>")
assertExText("set incsearch")
typeText("<PageUp>")
assertExText("digraph")
typeText("<PageUp>")
assertExText("set digraph")
typeText("<PageUp>")
assertExText("set incsearch")
}
@TestWithoutNeovim(SkipNeovimReason.CMD)
@ -325,20 +325,20 @@ class ExEntryTest : VimTestCase() {
deactivateExEntry()
typeExInput(":set<S-Up>")
assertExText("set digraph")
typeText("<S-Up>")
assertExText("set incsearch")
typeText("<S-Up>")
assertExText("digraph")
typeText("<S-Up>")
assertExText("set digraph")
deactivateExEntry()
typeExInput(":set<PageUp>")
assertExText("set incsearch")
typeText("<PageUp>")
assertExText("digraph")
typeText("<PageUp>")
assertExText("set digraph")
typeText("<PageUp>")
assertExText("set incsearch")
}
@Test
@ -357,20 +357,20 @@ class ExEntryTest : VimTestCase() {
deactivateExEntry()
typeExInput("/<S-Up>")
assertExText("something cool")
typeText("<S-Up>")
assertExText("so cool")
typeText("<S-Up>")
assertExText("not cool")
typeText("<S-Up>")
assertExText("something cool")
deactivateExEntry()
typeExInput("/<PageUp>")
assertExText("so cool")
typeText("<PageUp>")
assertExText("not cool")
typeText("<PageUp>")
assertExText("something cool")
typeText("<PageUp>")
assertExText("so cool")
}
@VimBehaviorDiffers(description = "Vim reorders history even when cancelling entry")
@ -394,20 +394,20 @@ class ExEntryTest : VimTestCase() {
// assertEquals("set incsearch", exEntryPanel.text)
typeExInput("/so<S-Up>")
assertExText("something cool")
typeText("<S-Up>")
assertExText("so cool")
typeText("<S-Up>")
assertExText("not cool")
typeText("<S-Up>")
assertExText("something cool")
deactivateExEntry()
typeExInput("/so<PageUp>")
assertExText("so cool")
typeText("<PageUp>")
assertExText("not cool")
typeText("<PageUp>")
assertExText("something cool")
typeText("<PageUp>")
assertExText("so cool")
}
@Test

View File

@ -130,7 +130,7 @@ class MultipleCaretsTest : VimTestCase() {
val editor = configureByText(before)
val vimEditor = editor.vim
VimPlugin.getRegister()
.storeText(vimEditor, vimEditor.primaryCaret(), TextRange(16, 19), SelectionType.CHARACTER_WISE, false)
.storeText(vimEditor, TextRange(16, 19), SelectionType.CHARACTER_WISE, false)
typeText(commandToKeys("pu"))
val after = """
qwe
@ -165,7 +165,7 @@ class MultipleCaretsTest : VimTestCase() {
val editor = configureByText(before)
val vimEditor = editor.vim
VimPlugin.getRegister()
.storeText(vimEditor, vimEditor.primaryCaret(), TextRange(16, 19), SelectionType.CHARACTER_WISE, false)
.storeText(vimEditor, TextRange(16, 19), SelectionType.CHARACTER_WISE, false)
typeText(commandToKeys("pu"))
val after = """
qwe
@ -201,7 +201,7 @@ class MultipleCaretsTest : VimTestCase() {
val editor = configureByText(before)
val vimEditor = editor.vim
VimPlugin.getRegister()
.storeText(vimEditor, vimEditor.primaryCaret(), TextRange(16, 19), SelectionType.CHARACTER_WISE, false)
.storeText(vimEditor, TextRange(16, 19), SelectionType.CHARACTER_WISE, false)
typeText(commandToKeys("4pu"))
val after = """
qwe
@ -237,7 +237,7 @@ class MultipleCaretsTest : VimTestCase() {
val editor = configureByText(before)
val vimEditor = editor.vim
VimPlugin.getRegister()
.storeText(vimEditor, vimEditor.primaryCaret(), TextRange(16, 19), SelectionType.CHARACTER_WISE, false)
.storeText(vimEditor, TextRange(16, 19), SelectionType.CHARACTER_WISE, false)
typeText(commandToKeys("4pu"))
val after = """
qwe
@ -258,7 +258,7 @@ class MultipleCaretsTest : VimTestCase() {
val before = "${c}qwe\n" + "rty\n" + "as${c}d\n" + "fgh\n" + "zxc\n" + "vbn\n"
val editor = configureByText(before)
VimPlugin.getRegister()
.storeText(editor.vim, editor.vim.primaryCaret(), TextRange(16, 19), SelectionType.CHARACTER_WISE, false)
.storeText(editor.vim, TextRange(16, 19), SelectionType.CHARACTER_WISE, false)
typeText("vj")
typeText(commandToKeys("pu"))

View File

@ -26,6 +26,7 @@ import org.junit.jupiter.api.Disabled
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.assertThrows
import kotlin.test.assertEquals
import kotlin.test.assertNull
import kotlin.test.assertTrue
/**
@ -267,7 +268,7 @@ class MapCommandTest : VimTestCase() {
configureByText("${c}foo\n")
typeText(commandToKeys("imap a b \\| c"))
typeText(injector.parser.parseKeys("ia"))
assertState("b \\| cfoo\n")
assertState("b | cfoo\n")
}
// VIM-666 |:imap|
@ -277,7 +278,7 @@ class MapCommandTest : VimTestCase() {
configureByText("${c}foo\n")
typeText(commandToKeys("imap a b \\| c |"))
typeText(injector.parser.parseKeys("ia"))
assertState("b \\| c foo\n")
assertState("b | c foo\n")
}
// VIM-670 |:map|
@ -754,4 +755,23 @@ class MapCommandTest : VimTestCase() {
assertTrue(KeyHandler.getInstance().keyStack.isEmpty())
}
@TestFor(issues = ["VIM-3601"])
@Test
fun `mapping to something with bars`() {
configureByText(
"""
Lorem Ipsum
Lorem ipsum dolor sit amet,
${c}consectetur adipiscing elit
Sed in orci mauris.
Cras id tellus in ex imperdiet egestas.
""".trimIndent()
)
typeText(commandToKeys("map k :echo 4<CR> \\| :echo 42<CR>"))
assertNull(injector.outputPanel.getCurrentOutputPanel())
typeText("k")
assertEquals("4\n42", injector.outputPanel.getCurrentOutputPanel()!!.text)
}
}

View File

@ -32,7 +32,7 @@ class PrintCommandTest : VimTestCase() {
// We should be waiting for a keypress now, such as <Enter> or <Esc> to close the output panel. But that's handled
// by a separate key event loop which doesn't operate in tests.
// Simulate closing the output panel in the same way as if we'd entered the right key
ExOutputModel.getInstance(fixture.editor).close()
injector.outputPanel.getCurrentOutputPanel()?.close()
typeText(commandToKeys("p"))
assertExOutput(" Lorem Ipsum")
}

View File

@ -9,7 +9,6 @@
package org.jetbrains.plugins.ideavim.ex.implementation.commands
import com.maddyhome.idea.vim.VimPlugin
import com.maddyhome.idea.vim.newapi.vim
import com.maddyhome.idea.vim.register.RegisterConstants
import org.jetbrains.plugins.ideavim.VimTestCase
import org.junit.jupiter.api.Test
@ -303,33 +302,4 @@ class YankLinesCommandTest : VimTestCase() {
|Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.
|""".trimMargin())
}
@Test
fun `test multicaret yank`() {
configureByText(
"""
|Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|${c}Morbi nec luctus tortor, id venenatis lacus.
|${c}Nunc sit amet tellus vel purus cursus posuere et at purus.
|${c}Ut id dapibus augue.
|Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.
|Pellentesque orci dolor, tristique quis rutrum non, scelerisque id dui.
""".trimMargin()
)
enterCommand("y")
val carets = fixture.editor.vim.carets()
assertEquals(3, carets.size)
assertEquals(
"Morbi nec luctus tortor, id venenatis lacus.\n",
carets[0].registerStorage.getRegister(RegisterConstants.UNNAMED_REGISTER)?.text
)
assertEquals(
"Nunc sit amet tellus vel purus cursus posuere et at purus.\n",
carets[1].registerStorage.getRegister(RegisterConstants.UNNAMED_REGISTER)?.text
)
assertEquals(
"Ut id dapibus augue.\n",
carets[2].registerStorage.getRegister(RegisterConstants.UNNAMED_REGISTER)?.text
)
}
}

View File

@ -50,7 +50,7 @@ class ReplaceWithRegisterTest : VimTestCase() {
configureByText(text)
val vimEditor = fixture.editor.vim
VimPlugin.getRegister()
.storeText(vimEditor, vimEditor.primaryCaret(), text rangeOf "one", SelectionType.CHARACTER_WISE, false)
.storeText(vimEditor, text rangeOf "one", SelectionType.CHARACTER_WISE, false)
typeText(injector.parser.parseKeys("griw"))
assertState("one on${c}e three")
assertEquals("one", VimPlugin.getRegister().lastRegister?.text)
@ -170,7 +170,7 @@ class ReplaceWithRegisterTest : VimTestCase() {
configureByText(text)
val vimEditor = fixture.editor.vim
VimPlugin.getRegister()
.storeText(vimEditor, vimEditor.primaryCaret(), text rangeOf "one", SelectionType.CHARACTER_WISE, false)
.storeText(vimEditor, text rangeOf "one", SelectionType.CHARACTER_WISE, false)
typeText(injector.parser.parseKeys("3griw"))
assertState("one on${c}e four")
assertEquals("one", VimPlugin.getRegister().lastRegister?.text)
@ -184,7 +184,7 @@ class ReplaceWithRegisterTest : VimTestCase() {
configureByText(text)
val vimEditor = fixture.editor.vim
VimPlugin.getRegister()
.storeText(vimEditor, vimEditor.primaryCaret(), text rangeOf "one", SelectionType.CHARACTER_WISE, false)
.storeText(vimEditor, text rangeOf "one", SelectionType.CHARACTER_WISE, false)
typeText(injector.parser.parseKeys("griw"))
assertState("one two one four")
assertEquals("one", VimPlugin.getRegister().lastRegister?.text)
@ -197,7 +197,7 @@ class ReplaceWithRegisterTest : VimTestCase() {
configureByText(text)
val vimEditor = fixture.editor.vim
VimPlugin.getRegister()
.storeText(vimEditor, vimEditor.primaryCaret(), text rangeOf "one", SelectionType.CHARACTER_WISE, false)
.storeText(vimEditor, text rangeOf "one", SelectionType.CHARACTER_WISE, false)
typeText(injector.parser.parseKeys("griw" + "w" + "."))
assertState("one one on${c}e four")
assertEquals("one", VimPlugin.getRegister().lastRegister?.text)
@ -247,7 +247,7 @@ class ReplaceWithRegisterTest : VimTestCase() {
configureByText(text)
val vimEditor = fixture.editor.vim
VimPlugin.getRegister()
.storeText(vimEditor, vimEditor.primaryCaret(), text rangeOf "legendary", SelectionType.CHARACTER_WISE, false)
.storeText(vimEditor, text rangeOf "legendary", SelectionType.CHARACTER_WISE, false)
typeText(injector.parser.parseKeys("grr"))
assertState(
"""
@ -414,7 +414,7 @@ class ReplaceWithRegisterTest : VimTestCase() {
configureByText(text)
val vimEditor = fixture.editor.vim
VimPlugin.getRegister()
.storeText(vimEditor, vimEditor.primaryCaret(), text rangeOf "legendary", SelectionType.CHARACTER_WISE, false)
.storeText(vimEditor, text rangeOf "legendary", SelectionType.CHARACTER_WISE, false)
typeText(injector.parser.parseKeys("viw" + "gr"))
assertState(
"""
@ -485,7 +485,7 @@ class ReplaceWithRegisterTest : VimTestCase() {
configureByText(text)
val vimEditor = fixture.editor.vim
VimPlugin.getRegister()
.storeText(vimEditor, vimEditor.primaryCaret(), text rangeOf "legendary", SelectionType.CHARACTER_WISE, false)
.storeText(vimEditor, text rangeOf "legendary", SelectionType.CHARACTER_WISE, false)
typeText(injector.parser.parseKeys("V" + "gr"))
assertState(
"""

View File

@ -660,7 +660,7 @@ abstract class VimTestCase {
}
fun assertExOutput(expected: String, clear: Boolean = true) {
val actual = ExOutputModel.getInstance(fixture.editor).text
val actual = injector.outputPanel.getCurrentOutputPanel()?.text
assertNotNull(actual, "No Ex output")
assertEquals(expected, actual)
NeovimTesting.typeCommand("<esc>", testInfo, fixture.editor)

View File

@ -16,6 +16,7 @@ import org.jetbrains.plugins.ideavim.TestWithoutNeovim
import org.jetbrains.plugins.ideavim.VimBehaviorDiffers
import org.jetbrains.plugins.ideavim.VimJavaTestCase
import org.junit.jupiter.api.Test
import kotlin.test.assertEquals
class ChangeActionJavaTest : VimJavaTestCase() {
// VIM-511 |.|
@ -120,6 +121,28 @@ and some text after""",
)
}
// VIM-566
@TestWithoutNeovim(SkipNeovimReason.FOLDING)
@Test
fun testInsertAfterToggleFold() {
configureByJavaText(
"""
$c/**
* I should be fold
* a little more text
* and final fold
*/
and some text after
""".trimIndent(),
)
CodeFoldingManager.getInstance(fixture.project).updateFoldRegions(fixture.editor)
assertEquals(FoldingUtil.findFoldRegionStartingAtLine(fixture.editor, 0)!!.isExpanded, true)
typeText(injector.parser.parseKeys("za"))
assertEquals(FoldingUtil.findFoldRegionStartingAtLine(fixture.editor, 0)!!.isExpanded, false)
typeText(injector.parser.parseKeys("za"))
assertEquals(FoldingUtil.findFoldRegionStartingAtLine(fixture.editor, 0)!!.isExpanded, true)
}
// VIM-287 |zc| |o|
@TestWithoutNeovim(SkipNeovimReason.FOLDING)
@Test

View File

@ -15,7 +15,7 @@ val javaVersion: String by project
val remoteRobotVersion: String by project
dependencies {
testFixturesImplementation("org.junit.jupiter:junit-jupiter:5.10.3")
testFixturesImplementation("org.junit.jupiter:junit-jupiter:5.11.0")
compileOnly("org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion")
testFixturesImplementation("org.jetbrains.kotlin:kotlin-test:$kotlinVersion")
testFixturesImplementation(testFixtures(project(":"))) // The root project

View File

@ -55,8 +55,15 @@ class KeyHandler {
private val keyConsumers: List<KeyConsumer> = listOf(ModalInputConsumer(), MappingProcessor, CommandCountConsumer(), DeleteCommandConsumer(), EditorResetConsumer(), CharArgumentConsumer(), RegisterConsumer(), DigraphConsumer(), CommandConsumer(), SelectRegisterConsumer(), ModeInputConsumer())
private var handleKeyRecursionCount = 0
var keyHandlerState: KeyHandlerState = KeyHandlerState()
private set
// KeyHandlerState requires injector.keyGroup to be initialized and that's why we don't create it immediately and have this here
// TODO figure out a better solution
private val defaultKeyHandlerState by lazy { KeyHandlerState() }
private var mutableKeyHandlerState: KeyHandlerState? = null
var keyHandlerState: KeyHandlerState
get() = mutableKeyHandlerState ?: defaultKeyHandlerState
private set(value) {
mutableKeyHandlerState = value
}
val keyStack: KeyStack = KeyStack()
val modalEntryKeys: MutableList<KeyStroke> = ArrayList()
@ -283,6 +290,7 @@ class KeyHandler {
// TODO we should have a single reset method
fun reset(keyState: KeyHandlerState, mode: Mode) {
logger.trace { "Reset is executed" }
injector.commandLine.getActiveCommandLine()?.clearCurrentAction()
keyHandlerState.partialReset(mode)
keyState.commandBuilder.resetAll(getKeyRoot(mode.toMappingMode()))
}

View File

@ -16,7 +16,7 @@ import com.maddyhome.idea.vim.command.Command
import com.maddyhome.idea.vim.command.OperatorArguments
import com.maddyhome.idea.vim.handler.VimActionHandler
@CommandOrMotion(keys = ["<C-R>"], modes = [Mode.NORMAL])
@CommandOrMotion(keys = ["U", "<C-R>"], modes = [Mode.NORMAL, Mode.VISUAL])
class RedoAction : VimActionHandler.SingleExecution() {
override val type: Command.Type = Command.Type.OTHER_SELF_SYNCHRONIZED

View File

@ -16,7 +16,7 @@ import com.maddyhome.idea.vim.command.Command
import com.maddyhome.idea.vim.command.OperatorArguments
import com.maddyhome.idea.vim.handler.VimActionHandler
@CommandOrMotion(keys = ["u", "<Undo>"], modes = [Mode.NORMAL])
@CommandOrMotion(keys = ["u", "<Undo>"], modes = [Mode.NORMAL, Mode.VISUAL])
class UndoAction : VimActionHandler.SingleExecution() {
override val type: Command.Type = Command.Type.OTHER_SELF_SYNCHRONIZED

View File

@ -8,7 +8,6 @@
package com.maddyhome.idea.vim.action.change.change
import com.intellij.vim.annotations.CommandOrMotion
import com.intellij.vim.annotations.Mode
import com.maddyhome.idea.vim.api.ExecutionContext
import com.maddyhome.idea.vim.api.VimCaret
import com.maddyhome.idea.vim.api.VimChangeGroup
@ -23,7 +22,7 @@ import com.maddyhome.idea.vim.helper.CharacterHelper
/**
* @author vlan
*/
@CommandOrMotion(keys = ["u"], modes = [Mode.VISUAL])
@CommandOrMotion(keys = [], modes = [])
class ChangeCaseLowerVisualAction : VisualOperatorActionHandler.ForEachCaret() {
override val type: Command.Type = Command.Type.CHANGE

View File

@ -8,7 +8,6 @@
package com.maddyhome.idea.vim.action.change.change
import com.intellij.vim.annotations.CommandOrMotion
import com.intellij.vim.annotations.Mode
import com.maddyhome.idea.vim.api.ExecutionContext
import com.maddyhome.idea.vim.api.VimCaret
import com.maddyhome.idea.vim.api.VimChangeGroup
@ -23,7 +22,7 @@ import com.maddyhome.idea.vim.helper.CharacterHelper
/**
* @author vlan
*/
@CommandOrMotion(keys = ["U"], modes = [Mode.VISUAL])
@CommandOrMotion(keys = [], modes = [])
class ChangeCaseUpperVisualAction : VisualOperatorActionHandler.ForEachCaret() {
override val type: Command.Type = Command.Type.CHANGE

View File

@ -10,7 +10,6 @@ package com.maddyhome.idea.vim.action.copy
import com.intellij.vim.annotations.CommandOrMotion
import com.intellij.vim.annotations.Mode
import com.maddyhome.idea.vim.api.ExecutionContext
import com.maddyhome.idea.vim.api.ImmutableVimCaret
import com.maddyhome.idea.vim.api.VimEditor
import com.maddyhome.idea.vim.api.injector
import com.maddyhome.idea.vim.command.Argument
@ -36,7 +35,15 @@ sealed class PutTextBaseAction(
val count = operatorArguments.count1
val sortedCarets = editor.sortedCarets()
return if (sortedCarets.size > 1) {
val caretToPutData = sortedCarets.associateWith { getPutDataForCaret(it, count) }
val putData = getPutData(count)
val splitText = putData.textData?.rawText?.split('\n')?.dropLastWhile(String::isEmpty)
val caretToPutData = if (splitText != null && splitText.size == sortedCarets.size) {
sortedCarets.mapIndexed { index, caret -> caret to putData.copy(textData = putData.textData.copy(rawText = splitText[splitText.lastIndex - index])) }.toMap()
} else {
sortedCarets.associateWith { putData }
}
var result = true
injector.application.runWriteAction {
caretToPutData.forEach {
@ -45,20 +52,18 @@ sealed class PutTextBaseAction(
}
result
} else {
val putData = getPutDataForCaret(sortedCarets.single(), count)
injector.put.putText(editor, context, putData, operatorArguments)
injector.put.putText(editor, context, getPutData(count), operatorArguments)
}
}
private fun getPutDataForCaret(caret: ImmutableVimCaret, count: Int): PutData {
val registerService = injector.registerGroup
val registerChar = if (caret.editor.carets().size == 1) {
registerService.currentRegister
} else {
registerService.getCurrentRegisterForMulticaret()
private fun getPutData(count: Int): PutData {
return PutData(getRegisterTextData(), null, count, insertTextBeforeCaret, indent, caretAfterInsertedText, -1)
}
val register = caret.registerStorage.getRegister(registerChar)
val textData = register?.let {
}
fun getRegisterTextData(): TextData? {
val register = injector.registerGroup.getRegister(injector.registerGroup.currentRegister)
return register?.let {
TextData(
register.text ?: injector.parser.toPrintableString(register.keys),
register.type,
@ -66,8 +71,6 @@ sealed class PutTextBaseAction(
register.name,
)
}
return PutData(textData, null, count, insertTextBeforeCaret, indent, caretAfterInsertedText, -1)
}
}
@CommandOrMotion(keys = ["p"], modes = [Mode.NORMAL])

View File

@ -41,7 +41,21 @@ sealed class PutVisualTextBaseAction(
): Boolean {
if (caretsAndSelections.isEmpty()) return false
val count = cmd.count
val caretToPutData = editor.sortedCarets().associateWith { getPutDataForCaret(it, caretsAndSelections[it], count) }
val sortedCarets = editor.sortedCarets()
val textData = getRegisterTextData()
val splitText = textData?.rawText?.split('\n')?.dropLastWhile(String::isEmpty)
val caretToTextData = if (splitText != null && splitText.size == sortedCarets.size) {
sortedCarets.mapIndexed { index, caret -> caret to textData.copy(rawText = splitText[splitText.lastIndex - index]) }.toMap()
} else {
sortedCarets.associateWith { textData }
}
val caretToPutData = caretToTextData.mapValues { (caret, textData) ->
getPutDataForCaret(textData, caret, caretsAndSelections[caret], count)
}
injector.registerGroup.resetRegister()
var result = true
injector.application.runWriteAction {
@ -52,17 +66,7 @@ sealed class PutVisualTextBaseAction(
return result
}
private fun getPutDataForCaret(caret: VimCaret, selection: VimSelection?, count: Int): PutData {
val lastRegisterChar = injector.registerGroup.lastRegisterChar
val register = caret.registerStorage.getRegister(lastRegisterChar)
val textData = register?.let {
PutData.TextData(
register.text ?: injector.parser.toPrintableString(register.keys),
register.type,
register.transferableData,
register.name,
)
}
private fun getPutDataForCaret(textData: PutData.TextData?, caret: VimCaret, selection: VimSelection?, count: Int): PutData {
val visualSelection = selection?.let { PutData.VisualSelection(mapOf(caret to it), it.type) }
return PutData(textData, visualSelection, count, insertTextBeforeCaret, indent, caretAfterInsertedText)
}

View File

@ -0,0 +1,46 @@
/*
* Copyright 2003-2024 The IdeaVim authors
*
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE.txt file or at
* https://opensource.org/licenses/MIT.
*/
package com.maddyhome.idea.vim.action.ex
import com.intellij.vim.annotations.CommandOrMotion
import com.intellij.vim.annotations.Mode
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.command.Command
import com.maddyhome.idea.vim.command.OperatorArguments
import com.maddyhome.idea.vim.common.Graphemes
import com.maddyhome.idea.vim.handler.VimActionHandler
@CommandOrMotion(keys = ["<DEL>"], modes = [Mode.CMD_LINE])
class DeleteNextCharAction : VimActionHandler.SingleExecution() {
override val type: Command.Type = Command.Type.OTHER_SELF_SYNCHRONIZED
override fun execute(editor: VimEditor, context: ExecutionContext, cmd: Command, operatorArguments: OperatorArguments): Boolean {
val commandLine = injector.commandLine.getActiveCommandLine() ?: return false
val caretOffset = commandLine.caret.offset
val oldText = commandLine.actualText
if (oldText.isEmpty()) {
commandLine.close(refocusOwningEditor = true, resetCaret = false)
return true
}
val newText = if (caretOffset == oldText.length) {
val preEndOffset = Graphemes.prev(oldText, oldText.length) ?: return true
oldText.substring(0, preEndOffset)
} else {
val nextOffset = Graphemes.next(oldText, caretOffset) ?: return true
oldText.substring(0, caretOffset) + oldText.substring(nextOffset)
}
commandLine.setText(newText)
return true
}
}

View File

@ -0,0 +1,44 @@
/*
* Copyright 2003-2024 The IdeaVim authors
*
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE.txt file or at
* https://opensource.org/licenses/MIT.
*/
package com.maddyhome.idea.vim.action.ex
import com.intellij.vim.annotations.CommandOrMotion
import com.intellij.vim.annotations.Mode
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.command.Command
import com.maddyhome.idea.vim.command.OperatorArguments
import com.maddyhome.idea.vim.handler.Motion
import com.maddyhome.idea.vim.handler.VimActionHandler
@CommandOrMotion(keys = ["<C-W>"], modes = [Mode.CMD_LINE])
class DeletePrevWordAction : VimActionHandler.SingleExecution() {
override val type: Command.Type = Command.Type.OTHER_SELF_SYNCHRONIZED
override fun execute(editor: VimEditor, context: ExecutionContext, cmd: Command, operatorArguments: OperatorArguments): Boolean {
val commandLine = injector.commandLine.getActiveCommandLine() ?: return false
val caretOffset = commandLine.caret.offset
if (caretOffset == 0) return true
val oldText = commandLine.actualText
val motion = injector.motion.findOffsetOfNextWord(oldText, oldText.length, commandLine.caret.offset, -1, true, editor)
when (motion) {
is Motion.AbsoluteOffset -> {
val newText = oldText.substring(0, motion.offset) + oldText.substring(caretOffset)
commandLine.caret.offset = motion.offset
commandLine.setText(newText)
}
else -> {}
}
return true
}
}

View File

@ -0,0 +1,44 @@
/*
* Copyright 2003-2024 The IdeaVim authors
*
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE.txt file or at
* https://opensource.org/licenses/MIT.
*/
package com.maddyhome.idea.vim.action.ex
import com.intellij.vim.annotations.CommandOrMotion
import com.intellij.vim.annotations.Mode
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.command.Command
import com.maddyhome.idea.vim.command.OperatorArguments
import com.maddyhome.idea.vim.common.Graphemes
import com.maddyhome.idea.vim.handler.VimActionHandler
@CommandOrMotion(keys = ["<BS>", "<C-H>"], modes = [Mode.CMD_LINE])
class DeletePreviousCharAction : VimActionHandler.SingleExecution() {
override val type: Command.Type = Command.Type.OTHER_SELF_SYNCHRONIZED
override fun execute(editor: VimEditor, context: ExecutionContext, cmd: Command, operatorArguments: OperatorArguments): Boolean {
val commandLine = injector.commandLine.getActiveCommandLine() ?: return false
val oldText = commandLine.actualText
if (oldText.isEmpty()) {
commandLine.close(refocusOwningEditor = true, resetCaret = false)
return true
}
val caretOffset = commandLine.caret.offset
if (caretOffset == 0) return true
val prevOffset = Graphemes.prev(oldText, caretOffset) ?: 0
commandLine.caret.offset = prevOffset
val newText = oldText.substring(0, prevOffset) + oldText.substring(caretOffset)
commandLine.setText(newText)
return true
}
}

View File

@ -0,0 +1,32 @@
/*
* Copyright 2003-2024 The IdeaVim authors
*
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE.txt file or at
* https://opensource.org/licenses/MIT.
*/
package com.maddyhome.idea.vim.action.ex
import com.intellij.vim.annotations.CommandOrMotion
import com.intellij.vim.annotations.Mode
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.command.Command
import com.maddyhome.idea.vim.command.OperatorArguments
import com.maddyhome.idea.vim.handler.VimActionHandler
@CommandOrMotion(keys = ["<C-U>"], modes = [Mode.CMD_LINE])
class DeleteToCaretAction : VimActionHandler.SingleExecution() {
override val type: Command.Type = Command.Type.OTHER_SELF_SYNCHRONIZED
override fun execute(editor: VimEditor, context: ExecutionContext, cmd: Command, operatorArguments: OperatorArguments): Boolean {
val commandLine = injector.commandLine.getActiveCommandLine() ?: return false
val oldText = commandLine.actualText
val newText = oldText.substring(commandLine.caret.offset)
commandLine.setText(newText)
commandLine.caret.offset = 0
return true
}
}

View File

@ -20,7 +20,7 @@ import com.maddyhome.idea.vim.helper.enumSetOf
import java.util.*
@CommandOrMotion(keys = [":"], modes = [Mode.NORMAL, Mode.VISUAL, Mode.OP_PENDING])
internal class ExEntryAction : VimActionHandler.SingleExecution() {
class ExEntryAction : VimActionHandler.SingleExecution() {
override val flags: EnumSet<CommandFlags> = enumSetOf(CommandFlags.FLAG_START_EX)
override val type: Command.Type = Command.Type.OTHER_READONLY

View File

@ -0,0 +1,29 @@
/*
* Copyright 2003-2024 The IdeaVim authors
*
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE.txt file or at
* https://opensource.org/licenses/MIT.
*/
package com.maddyhome.idea.vim.action.ex
import com.intellij.vim.annotations.CommandOrMotion
import com.intellij.vim.annotations.Mode
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.command.Command
import com.maddyhome.idea.vim.command.OperatorArguments
import com.maddyhome.idea.vim.handler.VimActionHandler
@CommandOrMotion(keys = ["<S-Down>", "<C-N>", "<PageDown>"], modes = [Mode.CMD_LINE])
class HistoryDownAction : VimActionHandler.SingleExecution() {
override val type: Command.Type = Command.Type.OTHER_SELF_SYNCHRONIZED
override fun execute(editor: VimEditor, context: ExecutionContext, cmd: Command, operatorArguments: OperatorArguments): Boolean {
val commandLine = injector.commandLine.getActiveCommandLine() ?: return false
commandLine.selectHistory(isUp = false, filter = false)
return true
}
}

View File

@ -0,0 +1,29 @@
/*
* Copyright 2003-2024 The IdeaVim authors
*
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE.txt file or at
* https://opensource.org/licenses/MIT.
*/
package com.maddyhome.idea.vim.action.ex
import com.intellij.vim.annotations.CommandOrMotion
import com.intellij.vim.annotations.Mode
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.command.Command
import com.maddyhome.idea.vim.command.OperatorArguments
import com.maddyhome.idea.vim.handler.VimActionHandler
@CommandOrMotion(keys = ["<Down>"], modes = [Mode.CMD_LINE])
class HistoryDownFilterAction : VimActionHandler.SingleExecution() {
override val type: Command.Type = Command.Type.OTHER_SELF_SYNCHRONIZED
override fun execute(editor: VimEditor, context: ExecutionContext, cmd: Command, operatorArguments: OperatorArguments): Boolean {
val commandLine = injector.commandLine.getActiveCommandLine() ?: return false
commandLine.selectHistory(isUp = false, filter = true)
return true
}
}

View File

@ -0,0 +1,29 @@
/*
* Copyright 2003-2024 The IdeaVim authors
*
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE.txt file or at
* https://opensource.org/licenses/MIT.
*/
package com.maddyhome.idea.vim.action.ex
import com.intellij.vim.annotations.CommandOrMotion
import com.intellij.vim.annotations.Mode
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.command.Command
import com.maddyhome.idea.vim.command.OperatorArguments
import com.maddyhome.idea.vim.handler.VimActionHandler
@CommandOrMotion(keys = ["<S-Up>", "<C-P>", "<PageUp>"], modes = [Mode.CMD_LINE])
class HistoryUpAction : VimActionHandler.SingleExecution() {
override val type: Command.Type = Command.Type.OTHER_SELF_SYNCHRONIZED
override fun execute(editor: VimEditor, context: ExecutionContext, cmd: Command, operatorArguments: OperatorArguments): Boolean {
val commandLine = injector.commandLine.getActiveCommandLine() ?: return false
commandLine.selectHistory(isUp = true, filter = false)
return true
}
}

View File

@ -0,0 +1,30 @@
/*
* Copyright 2003-2024 The IdeaVim authors
*
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE.txt file or at
* https://opensource.org/licenses/MIT.
*/
package com.maddyhome.idea.vim.action.ex
import com.intellij.vim.annotations.CommandOrMotion
import com.intellij.vim.annotations.Mode
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.command.Command
import com.maddyhome.idea.vim.command.OperatorArguments
import com.maddyhome.idea.vim.handler.VimActionHandler
@CommandOrMotion(keys = ["<Up>"], modes = [Mode.CMD_LINE])
class HistoryUpFilterAction : VimActionHandler.SingleExecution() {
override val type: Command.Type = Command.Type.OTHER_SELF_SYNCHRONIZED
override fun execute(editor: VimEditor, context: ExecutionContext, cmd: Command, operatorArguments: OperatorArguments): Boolean {
val commandLine = injector.commandLine.getActiveCommandLine() ?: return false
commandLine.selectHistory(isUp = true, filter = true)
return true
}
}

View File

@ -12,11 +12,13 @@ import com.intellij.vim.annotations.CommandOrMotion
import com.intellij.vim.annotations.Mode
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.command.Command
import com.maddyhome.idea.vim.command.CommandFlags
import com.maddyhome.idea.vim.command.OperatorArguments
import com.maddyhome.idea.vim.handler.VimActionHandler
import com.maddyhome.idea.vim.helper.enumSetOf
import com.maddyhome.idea.vim.history.VimHistory
import java.util.*
@CommandOrMotion(keys = ["<Esc>", "<C-[>", "<C-C>"], modes = [Mode.CMD_LINE])
@ -25,6 +27,9 @@ class LeaveCommandLineAction : VimActionHandler.SingleExecution() {
override val type: Command.Type = Command.Type.OTHER_READONLY
override fun execute(editor: VimEditor, context: ExecutionContext, cmd: Command, operatorArguments: OperatorArguments): Boolean {
val argument = cmd.argument ?: return true
val historyType = VimHistory.Type.getTypeByLabel(argument.character.toString())
injector.historyGroup.addEntry(historyType, argument.string)
return true
}
}

View File

@ -0,0 +1,34 @@
/*
* Copyright 2003-2024 The IdeaVim authors
*
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE.txt file or at
* https://opensource.org/licenses/MIT.
*/
package com.maddyhome.idea.vim.action.ex
import com.intellij.vim.annotations.CommandOrMotion
import com.intellij.vim.annotations.Mode
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.command.Command
import com.maddyhome.idea.vim.command.OperatorArguments
import com.maddyhome.idea.vim.common.Graphemes
import com.maddyhome.idea.vim.handler.VimActionHandler
@CommandOrMotion(keys = ["<Left>"], modes = [Mode.CMD_LINE])
class MoveCaretLeftAction : VimActionHandler.SingleExecution() {
override val type: Command.Type = Command.Type.OTHER_SELF_SYNCHRONIZED
override fun execute(editor: VimEditor, context: ExecutionContext, cmd: Command, operatorArguments: OperatorArguments): Boolean {
val commandLine = injector.commandLine.getActiveCommandLine() ?: return false
val caret = commandLine.caret
val prevOffset = Graphemes.prev(commandLine.actualText, caret.offset) ?: return true
caret.offset = prevOffset
return true
}
}

View File

@ -0,0 +1,34 @@
/*
* Copyright 2003-2024 The IdeaVim authors
*
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE.txt file or at
* https://opensource.org/licenses/MIT.
*/
package com.maddyhome.idea.vim.action.ex
import com.intellij.vim.annotations.CommandOrMotion
import com.intellij.vim.annotations.Mode
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.command.Command
import com.maddyhome.idea.vim.command.OperatorArguments
import com.maddyhome.idea.vim.common.Graphemes
import com.maddyhome.idea.vim.handler.VimActionHandler
@CommandOrMotion(keys = ["<Right>"], modes = [Mode.CMD_LINE])
class MoveCaretRightAction : VimActionHandler.SingleExecution() {
override val type: Command.Type = Command.Type.OTHER_SELF_SYNCHRONIZED
override fun execute(editor: VimEditor, context: ExecutionContext, cmd: Command, operatorArguments: OperatorArguments): Boolean {
val commandLine = injector.commandLine.getActiveCommandLine() ?: return false
val caret = commandLine.caret
val nextOffset = Graphemes.next(commandLine.actualText, caret.offset) ?: return true
caret.offset = nextOffset
return true
}
}

View File

@ -0,0 +1,29 @@
/*
* Copyright 2003-2024 The IdeaVim authors
*
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE.txt file or at
* https://opensource.org/licenses/MIT.
*/
package com.maddyhome.idea.vim.action.ex
import com.intellij.vim.annotations.CommandOrMotion
import com.intellij.vim.annotations.Mode
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.command.Command
import com.maddyhome.idea.vim.command.OperatorArguments
import com.maddyhome.idea.vim.handler.VimActionHandler
@CommandOrMotion(keys = ["<C-E>", "<End>"], modes = [Mode.CMD_LINE])
class MoveCaretToLineEnd : VimActionHandler.SingleExecution() {
override val type: Command.Type = Command.Type.OTHER_SELF_SYNCHRONIZED
override fun execute(editor: VimEditor, context: ExecutionContext, cmd: Command, operatorArguments: OperatorArguments): Boolean {
val commandLine = injector.commandLine.getActiveCommandLine() ?: return false
commandLine.caret.offset = commandLine.actualText.length
return true
}
}

View File

@ -0,0 +1,29 @@
/*
* Copyright 2003-2024 The IdeaVim authors
*
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE.txt file or at
* https://opensource.org/licenses/MIT.
*/
package com.maddyhome.idea.vim.action.ex
import com.intellij.vim.annotations.CommandOrMotion
import com.intellij.vim.annotations.Mode
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.command.Command
import com.maddyhome.idea.vim.command.OperatorArguments
import com.maddyhome.idea.vim.handler.VimActionHandler
@CommandOrMotion(keys = ["<C-B>", "<Home>"], modes = [Mode.CMD_LINE])
class MoveCaretToLineStart : VimActionHandler.SingleExecution() {
override val type: Command.Type = Command.Type.OTHER_SELF_SYNCHRONIZED
override fun execute(editor: VimEditor, context: ExecutionContext, cmd: Command, operatorArguments: OperatorArguments): Boolean {
val commandLine = injector.commandLine.getActiveCommandLine() ?: return false
commandLine.caret.offset = 0
return true
}
}

View File

@ -0,0 +1,38 @@
/*
* Copyright 2003-2024 The IdeaVim authors
*
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE.txt file or at
* https://opensource.org/licenses/MIT.
*/
package com.maddyhome.idea.vim.action.ex
import com.intellij.vim.annotations.CommandOrMotion
import com.intellij.vim.annotations.Mode
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.command.Command
import com.maddyhome.idea.vim.command.OperatorArguments
import com.maddyhome.idea.vim.handler.Motion
import com.maddyhome.idea.vim.handler.VimActionHandler
@CommandOrMotion(keys = ["<C-Right>", "<S-Right>"], modes = [Mode.CMD_LINE])
class MoveToNextWordAction : VimActionHandler.SingleExecution() {
override val type: Command.Type = Command.Type.OTHER_SELF_SYNCHRONIZED
override fun execute(editor: VimEditor, context: ExecutionContext, cmd: Command, operatorArguments: OperatorArguments): Boolean {
val commandLine = injector.commandLine.getActiveCommandLine() ?: return false
val text = commandLine.actualText
val motion = injector.motion.findOffsetOfNextWord(text, text.length, commandLine.caret.offset, 1, true, editor)
when (motion) {
is Motion.AbsoluteOffset -> {
commandLine.caret.offset = motion.offset
}
else -> {}
}
return true
}
}

Some files were not shown because too many files have changed in this diff Show More