1
0
mirror of https://github.com/chylex/IntelliJ-IdeaVim.git synced 2024-10-17 07:42:46 +02: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" # 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/parser/generated
vim-engine/src/main/java/com/maddyhome/idea/vim/regexp/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 # Created by github automation
settings.xml settings.xml

View File

@ -523,6 +523,18 @@ Contributors:
[![icon][github]](https://github.com/LazyScaper) [![icon][github]](https://github.com/LazyScaper)
&nbsp; &nbsp;
Jake 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: Previous contributors:

View File

@ -27,8 +27,8 @@ usual beta standards.
Since version 2.9.0, the changelog can be found on YouTrack 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 * [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 * [Version Fixes](https://youtrack.jetbrains.com/issues/VIM?q=State:%20Fixed%20sort%20by:%20%7BFix%20versions%7D%20asc)
## 2.9.0, 2024-02-20 ## 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: If you are looking for:
- Vim commands (`w`, `<C-O>`, `p`, etc.): - 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`. - How commands are executed in common: `EditorActionHandlerBase`.
- Key mapping: `KeyHandler.handleKey()`. - Key mapping: `KeyHandler.handleKey()`.
- Ex commands (`:set`, `:s`, `:nohlsearch`): - 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 grammar: `Vimscript.g4`.
- Vim script parsing: package `com.maddyhome.idea.vim.vimscript.parser`. - Vim script parsing: package `com.maddyhome.idea.vim.vimscript.parser`.
- Vim script executor: `Executor`. - Vim script executor: `Executor`.

View File

@ -109,7 +109,6 @@ etc
See also: 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) * [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) * [Vimscript support roadmap](vimscript-info/VIMSCRIPT_ROADMAP.md)
* [List of supported in-build functions](vimscript-info/FUNCTIONS_INFO.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) Files.createDirectories(generatedDirPath)
val filePath = generatedDirPath.resolve(environment.options["commands_file"]!!) 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) filePath.writeText(fileContent)
return emptyList() return emptyList()

View File

@ -37,7 +37,8 @@ class ExCommandProcessor(private val environment: SymbolProcessorEnvironment): S
Files.createDirectories(generatedDirPath) Files.createDirectories(generatedDirPath)
val filePath = generatedDirPath.resolve(environment.options["ex_commands_file"]!!) 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) filePath.writeText(fileContent)
return emptyList() return emptyList()

View File

@ -37,7 +37,8 @@ class VimscriptFunctionProcessor(private val environment: SymbolProcessorEnviron
Files.createDirectories(generatedDirPath) Files.createDirectories(generatedDirPath)
val filePath = generatedDirPath.resolve(environment.options["vimscript_functions_file"]!!) 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) filePath.writeText(fileContent)
return emptyList() 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 // AceJump is an optional dependency. We use their SessionManager class to check if it's active
plugin("AceJump", "3.8.19") plugin("AceJump", "3.8.19")
plugin("com.intellij.classic.ui", "242.20224.159")
} }
moduleSources(project(":vim-engine", "sourcesJarArtifacts")) moduleSources(project(":vim-engine", "sourcesJarArtifacts"))
@ -210,6 +211,8 @@ tasks {
} }
compileTestKotlin { compileTestKotlin {
enabled = false
kotlinOptions { kotlinOptions {
jvmTarget = javaVersion jvmTarget = javaVersion
apiVersion = "1.9" apiVersion = "1.9"

View File

@ -1,6 +1,6 @@
Welcome to the IdeaVim wiki! Welcome to the IdeaVim wiki!
- List of IdeaVim plugins: [plugins](IdeaVim%20Plugins.md) - List of IdeaVim plugins: [plugins](IdeaVim%20Plugins)
- Examples of `ideajoin` option (also known as "smart join"): ["ideajoin" examples](ideajoin-examples.md) - Examples of `ideajoin` option (also known as "smart join"): ["ideajoin" examples](ideajoin-examples)
- List of "set" commands: ["set" commands](set-commands.md) - List of "set" commands: ["set" commands](set-commands)
- Docs about "select" mode in vim: [select mode](Select-mode.md) - 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 ### Instructions
[See here](NERDTree-support.md). [See here](NERDTree-support).
</details> </details>

View File

@ -1,7 +1,7 @@
# Support Guide # Support Guide
This document is created to help our support team. 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 ## Support channels
@ -35,4 +35,4 @@ IdeaVim has multiple YouTrack statuses, main are:
# ~.ideavimrc file # ~.ideavimrc file
`~/.ideavimrc` is the file that is used for IdeaVim configuration. It may affect behaviour of the program, `~/.ideavimrc` is the file that is used for IdeaVim configuration. It may affect behaviour of the program,
so it makes sense to additionally request this file in case the issues can't be reproduced. so it makes sense to additionally request this file in case the issues can't be reproduced.

View File

@ -16,11 +16,11 @@
# https://data.services.jetbrains.com/products?code=IC # https://data.services.jetbrains.com/products?code=IC
# Maven releases are here: https://www.jetbrains.com/intellij-repository/releases # Maven releases are here: https://www.jetbrains.com/intellij-repository/releases
# And snapshots: https://www.jetbrains.com/intellij-repository/snapshots # 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 # Values for type: https://plugins.jetbrains.com/docs/intellij/tools-gradle-intellij-plugin.html#intellij-extension-type
ideaType=IC ideaType=IC
instrumentPluginCode=true instrumentPluginCode=true
version=SNAPSHOT version=chylex-40
javaVersion=17 javaVersion=17
remoteRobotVersion=0.11.23 remoteRobotVersion=0.11.23
antlrVersion=4.10.1 antlrVersion=4.10.1
@ -47,7 +47,6 @@ youtrackToken=
# Gradle settings # Gradle settings
org.gradle.jvmargs='-Dfile.encoding=UTF-8' org.gradle.jvmargs='-Dfile.encoding=UTF-8'
org.gradle.configuration-cache=true
org.gradle.caching=true org.gradle.caching=true
# Disable warning from gradle-intellij-plugin. Kotlin stdlib is included as compileOnly, so the warning is unnecessary # 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/JavaText.kt
- src/test/java/org/jetbrains/plugins/ideavim/propertybased/samples/LoremText.kt - src/test/java/org/jetbrains/plugins/ideavim/propertybased/samples/LoremText.kt
- src/test/java/org/jetbrains/plugins/ideavim/propertybased/samples/SimpleText.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/regexp/parser/generated
- vim-engine/src/main/java/com/maddyhome/idea/vim/parser/generated - vim-engine/src/main/java/com/maddyhome/idea/vim/parser/generated
- src/main/java/com/maddyhome/idea/vim/group/SearchGroup.java - 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 @JvmStatic
@Deprecated("Use VimPlugin.getKey().putKeyMapping(modes, fromKeys, pluginOwner, extensionHandler, recursive)", @Deprecated(
"Use VimPlugin.getKey().putKeyMapping(modes, fromKeys, pluginOwner, extensionHandler, recursive)",
ReplaceWith( ReplaceWith(
"VimPlugin.getKey().putKeyMapping(modes, fromKeys, pluginOwner, extensionHandler, recursive)", "VimPlugin.getKey().putKeyMapping(modes, fromKeys, pluginOwner, extensionHandler, recursive)",
"com.maddyhome.idea.vim.VimPlugin" "com.maddyhome.idea.vim.VimPlugin"
@ -195,7 +196,7 @@ object VimExtensionFacade {
@JvmStatic @JvmStatic
fun getRegisterForCaret(register: Char, caret: VimCaret): List<KeyStroke>? { 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 return reg.keys
} }
@ -208,7 +209,7 @@ object VimExtensionFacade {
/** Set the current contents of the given register */ /** Set the current contents of the given register */
@JvmStatic @JvmStatic
fun setRegisterForCaret(register: Char, caret: ImmutableVimCaret, keys: List<KeyStroke?>?) { 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 */ /** Set the current contents of the given register */
@ -277,4 +278,4 @@ fun VimExtensionFacade.exportOperatorFunction(name: String, function: OperatorFu
fun interface ScriptFunction { fun interface ScriptFunction {
fun execute(editor: VimEditor, context: ExecutionContext, args: Map<String, VimDataType>): ExecutionResult fun execute(editor: VimEditor, context: ExecutionContext, args: Map<String, VimDataType>): ExecutionResult
} }

View File

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

View File

@ -234,7 +234,7 @@ private object FileTypePatterns {
} else if (fileTypeName == "CMakeLists.txt" || fileName == "CMakeLists") { } else if (fileTypeName == "CMakeLists.txt" || fileName == "CMakeLists") {
this.cMakePatterns this.cMakePatterns
} else { } 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) { private fun doReplace(editor: Editor, context: DataContext, caret: ImmutableVimCaret, visualSelection: PutData.VisualSelection) {
val registerGroup = injector.registerGroup val registerGroup = injector.registerGroup
val lastRegisterChar = if (editor.caretModel.caretCount == 1) registerGroup.currentRegister else registerGroup.getCurrentRegisterForMulticaret() 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 usedType = savedRegister.type
var usedText = savedRegister.text var usedText = savedRegister.text
@ -180,4 +180,4 @@ private fun doReplace(editor: Editor, context: DataContext, caret: ImmutableVimC
saveToRegister = false saveToRegister = false
) )
} }
} }

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.VimPlugin
import com.maddyhome.idea.vim.api.ExecutionContext import com.maddyhome.idea.vim.api.ExecutionContext
import com.maddyhome.idea.vim.api.VimCaret 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.VimEditor
import com.maddyhome.idea.vim.api.endsWithNewLine import com.maddyhome.idea.vim.api.endsWithNewLine
import com.maddyhome.idea.vim.api.getLeadingCharacterOffset 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.extension.exportOperatorFunction
import com.maddyhome.idea.vim.group.findBlockRange import com.maddyhome.idea.vim.group.findBlockRange
import com.maddyhome.idea.vim.helper.exitVisualMode 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.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.ij
import com.maddyhome.idea.vim.newapi.vim import com.maddyhome.idea.vim.newapi.vim
import com.maddyhome.idea.vim.options.helpers.ClipboardOptionHelper 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) 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 { private class YSurroundHandler : ExtensionHandler {
@ -108,7 +112,7 @@ internal class VimSurroundExtension : VimExtension {
val lastNonWhiteSpaceOffset = getLastNonWhitespaceCharacterOffset(editor.text(), lineStartOffset, lineEndOffset) val lastNonWhiteSpaceOffset = getLastNonWhitespaceCharacterOffset(editor.text(), lineStartOffset, lineEndOffset)
if (lastNonWhiteSpaceOffset != null) { if (lastNonWhiteSpaceOffset != null) {
val range = TextRange(lineStartOffset, lastNonWhiteSpaceOffset + 1) val range = TextRange(lineStartOffset, lastNonWhiteSpaceOffset + 1)
performSurround(pair, range, it) performSurround(pair, range, it, count = operatorArguments.count1)
} }
// it.moveToOffset(lineStartOffset) // it.moveToOffset(lineStartOffset)
} }
@ -131,15 +135,13 @@ internal class VimSurroundExtension : VimExtension {
private class VSurroundHandler : ExtensionHandler { private class VSurroundHandler : ExtensionHandler {
override fun execute(editor: VimEditor, context: ExecutionContext, operatorArguments: OperatorArguments) { override fun execute(editor: VimEditor, context: ExecutionContext, operatorArguments: OperatorArguments) {
val selectionStart = editor.ij.caretModel.primaryCaret.selectionStart
// NB: Operator ignores SelectionType anyway // 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 return
} }
runWriteAction { runWriteAction {
// Leave visual mode // Leave visual mode
editor.exitVisualMode() editor.exitVisualMode()
editor.ij.caretModel.moveToOffset(selectionStart)
} }
} }
} }
@ -160,6 +162,10 @@ internal class VimSurroundExtension : VimExtension {
companion object { companion object {
fun change(editor: VimEditor, context: ExecutionContext, charFrom: Char, newSurround: Pair<String, String>?) { 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 // Save old register values for carets
val surroundings = editor.sortedCarets() val surroundings = editor.sortedCarets()
.map { .map {
@ -267,20 +273,41 @@ internal class VimSurroundExtension : VimExtension {
} }
} }
private class Operator : OperatorFunction { private class Operator(private val supportsMultipleCursors: Boolean, private val count: Int) : OperatorFunction {
override fun apply(editor: VimEditor, context: ExecutionContext, selectionType: SelectionType?): Boolean { override fun apply(vimEditor: VimEditor, context: ExecutionContext, selectionType: SelectionType?): Boolean {
val ijEditor = editor.ij val ijEditor = vimEditor.ij
val c = getChar(ijEditor) val c = getChar(ijEditor)
if (c.code == 0) return true if (c.code == 0) return true
val pair = getOrInputPair(c, ijEditor, context.ij) ?: return false 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 runWriteAction {
performSurround(pair, range, editor.currentCaret(), selectionType == SelectionType.LINE_WISE) val change = VimPlugin.getChange()
// Jump back to start if (supportsMultipleCursors) {
executeNormalWithoutMapping(injector.parser.parseKeys("`["), ijEditor) ijEditor.runWithEveryCaretAndRestore {
applyOnce(ijEditor, change, pair, count)
}
}
else {
applyOnce(ijEditor, change, pair, count)
// Jump back to start
executeNormalWithoutMapping(injector.parser.parseKeys("`["), ijEditor)
}
}
return true 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? { private fun getSurroundRange(caret: VimCaret): TextRange? {
val editor = caret.editor val editor = caret.editor
@ -375,15 +402,15 @@ private fun getChar(editor: Editor): Char {
return res 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 { runWriteAction {
val editor = caret.editor val editor = caret.editor
val change = VimPlugin.getChange() 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 isEOF = range.endOffset == editor.text().length
val hasNewLine = editor.endsWithNewLine() val hasNewLine = editor.endsWithNewLine()
val rightSurround = if (tagsOnNewLines) { val rightSurround = (if (tagsOnNewLines) {
if (isEOF && !hasNewLine) { if (isEOF && !hasNewLine) {
"\n" + pair.second "\n" + pair.second
} else { } else {
@ -391,7 +418,7 @@ private fun performSurround(pair: Pair<String, String>, range: TextRange, caret:
} }
} else { } else {
pair.second pair.second
} }).let { RepeatedCharSequence.of(it, count) }
change.insertText(editor, caret, range.startOffset, leftSurround) change.insertText(editor, caret, range.startOffset, leftSurround)
change.insertText(editor, caret, range.endOffset + leftSurround.length, rightSurround) 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.IjVimEditor
import com.maddyhome.idea.vim.newapi.ij import com.maddyhome.idea.vim.newapi.ij
import com.maddyhome.idea.vim.state.mode.Mode import com.maddyhome.idea.vim.state.mode.Mode
import kotlin.math.min
/** /**
* Provides all the insert/replace related functionality * Provides all the insert/replace related functionality
@ -125,6 +124,7 @@ class ChangeGroup : VimChangeGroupBase() {
context: ExecutionContext, context: ExecutionContext,
range: TextRange, range: TextRange,
) { ) {
val startPos = editor.offsetToBufferPosition(caret.offset)
val startOffset = editor.getLineStartForOffset(range.startOffset) val startOffset = editor.getLineStartForOffset(range.startOffset)
val endOffset = editor.getLineEndForOffset(range.endOffset) val endOffset = editor.getLineEndForOffset(range.endOffset)
val ijEditor = (editor as IjVimEditor).editor val ijEditor = (editor as IjVimEditor).editor
@ -149,11 +149,7 @@ class ChangeGroup : VimChangeGroupBase() {
} }
} }
val afterAction = { val afterAction = {
val firstLine = editor.offsetToBufferPosition( caret.moveToOffset(injector.motion.moveCaretToLineStartSkipLeading(editor, startPos.line))
min(startOffset.toDouble(), endOffset.toDouble()).toInt()
).line
val newOffset = injector.motion.moveCaretToLineStartSkipLeading(editor, firstLine)
caret.moveToOffset(newOffset)
restoreCursor(editor, caret, (caret as IjVimCaret).caret.logicalPosition.line) restoreCursor(editor, caret, (caret as IjVimCaret).caret.logicalPosition.line)
} }
if (project != null) { if (project != null) {

View File

@ -11,11 +11,14 @@ package com.maddyhome.idea.vim.group;
import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.diagnostic.Logger;
import com.maddyhome.idea.vim.api.VimDigraphGroupBase; import com.maddyhome.idea.vim.api.VimDigraphGroupBase;
import com.maddyhome.idea.vim.api.VimEditor; 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.ex.ExOutputModel;
import com.maddyhome.idea.vim.helper.EditorHelper; import com.maddyhome.idea.vim.helper.EditorHelper;
import com.maddyhome.idea.vim.newapi.IjVimEditor; import com.maddyhome.idea.vim.newapi.IjVimEditor;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import static com.maddyhome.idea.vim.api.VimInjectorKt.injector;
public class DigraphGroup extends VimDigraphGroupBase { public class DigraphGroup extends VimDigraphGroupBase {
public void showDigraphs(@NotNull VimEditor editor) { 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()); 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) { if (activeCommandLine != null) {
activeCommandLine.close(true, false); activeCommandLine.close(true, false);
} }
ExOutputModel exOutputModel = ExOutputModel.tryGetInstance(editor); VimOutputPanel outputPanel = injector.getOutputPanel().getCurrentOutputPanel();
if (exOutputModel != null) { if (outputPanel != null) {
exOutputModel.close(); outputPanel.close();
} }
VimModalInput modalInput = injector.getModalInput().getCurrentModalInput(); VimModalInput modalInput = injector.getModalInput().getCurrentModalInput();
if (modalInput != null) { 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.components.Storage;
import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.diagnostic.Logger;
import com.maddyhome.idea.vim.VimPlugin; import com.maddyhome.idea.vim.VimPlugin;
import com.maddyhome.idea.vim.history.HistoryBlock; import com.maddyhome.idea.vim.history.*;
import com.maddyhome.idea.vim.history.HistoryEntry;
import com.maddyhome.idea.vim.history.VimHistoryBase;
import org.jdom.Element; import org.jdom.Element;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
@ -35,21 +33,20 @@ public class HistoryGroup extends VimHistoryBase implements PersistentStateCompo
logger.debug("saveData"); logger.debug("saveData");
Element hist = new Element("history"); Element hist = new Element("history");
saveData(hist, SEARCH); for (Type type : getHistories().keySet()) {
saveData(hist, COMMAND); saveData(hist, type);
saveData(hist, EXPRESSION); }
saveData(hist, INPUT);
element.addContent(hist); element.addContent(hist);
} }
private void saveData(@NotNull Element element, String key) { private void saveData(@NotNull Element element, VimHistory.Type type) {
final HistoryBlock block = getHistories().get(key); final HistoryBlock block = getHistories().get(type);
if (block == null) { if (block == null) {
return; return;
} }
final Element root = new Element("history-" + key); final Element root = new Element("history-" + typeToKey(type));
for (HistoryEntry entry : block.getEntries()) { for (HistoryEntry entry : block.getEntries()) {
final Element entryElement = new Element("entry"); final Element entryElement = new Element("entry");
@ -67,10 +64,10 @@ public class HistoryGroup extends VimHistoryBase implements PersistentStateCompo
return; return;
} }
readData(hist, SEARCH); for (Element child : hist.getChildren()) {
readData(hist, COMMAND); String key = child.getName().replace("history-", "");
readData(hist, EXPRESSION); readData(hist, key);
readData(hist, INPUT); }
} }
private void readData(@NotNull Element element, String key) { private void readData(@NotNull Element element, String key) {
@ -80,7 +77,7 @@ public class HistoryGroup extends VimHistoryBase implements PersistentStateCompo
} }
block = new HistoryBlock(); block = new HistoryBlock();
getHistories().put(key, block); getHistories().put(getTypeForString(key), block);
final Element root = element.getChild("history-" + key); final Element root = element.getChild("history-" + key);
if (root != null) { 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 @Nullable
@Override @Override
public Element getState() { public Element getState() {

View File

@ -139,7 +139,7 @@ object IjOptions {
// Temporary feature flags during development, not really intended for external use // Temporary feature flags during development, not really intended for external use
val closenotebooks: ToggleOption = addOption(ToggleOption("closenotebooks", GLOBAL, "closenotebooks", true, isHidden = true)) val closenotebooks: ToggleOption = addOption(ToggleOption("closenotebooks", GLOBAL, "closenotebooks", true, isHidden = true))
val commandOrMotionAnnotation: ToggleOption = addOption(ToggleOption("commandormotionannotation", GLOBAL, "commandormotionannotation", 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 unifyjumps: ToggleOption = addOption(ToggleOption("unifyjumps", GLOBAL, "unifyjumps", true, isHidden = true))
val vimscriptFunctionAnnotation: ToggleOption = addOption(ToggleOption("vimscriptfunctionannotation", GLOBAL, "vimscriptfunctionannotation", 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.VimPlugin;
import com.maddyhome.idea.vim.action.VimShortcutKeyAction; import com.maddyhome.idea.vim.action.VimShortcutKeyAction;
import com.maddyhome.idea.vim.action.change.LazyVimCommand; import com.maddyhome.idea.vim.action.change.LazyVimCommand;
import com.maddyhome.idea.vim.api.NativeAction; import com.maddyhome.idea.vim.api.*;
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.command.MappingMode; import com.maddyhome.idea.vim.command.MappingMode;
import com.maddyhome.idea.vim.ex.ExOutputModel; import com.maddyhome.idea.vim.ex.ExOutputModel;
import com.maddyhome.idea.vim.key.*; import com.maddyhome.idea.vim.key.*;
@ -80,25 +77,6 @@ public class KeyGroup extends VimKeyGroupBase implements PersistentStateComponen
((IjVimEditor)editor).getEditor().getComponent()); ((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 @Override
public void updateShortcutKeysRegistration() { public void updateShortcutKeysRegistration() {
for (VimEditor editor : injector.getEditorGroup().getEditors()) { for (VimEditor editor : injector.getEditorGroup().getEditors()) {
@ -358,6 +336,22 @@ public class KeyGroup extends VimKeyGroupBase implements PersistentStateComponen
@Override @Override
public boolean showKeyMappings(@NotNull Set<? extends MappingMode> modes, @NotNull VimEditor editor) { 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.helper.MessageHelper.message
import com.maddyhome.idea.vim.macro.VimMacroBase import com.maddyhome.idea.vim.macro.VimMacroBase
import com.maddyhome.idea.vim.newapi.IjVimEditor import com.maddyhome.idea.vim.newapi.IjVimEditor
import com.maddyhome.idea.vim.newapi.ij
/** /**
* Used to handle playback of macros * Used to handle playback of macros
@ -93,6 +94,9 @@ internal class MacroGroup : VimMacroBase() {
} finally { } finally {
keyStack.removeFirst() keyStack.removeFirst()
} }
if (!isInternalMacro) {
MacroAutoImport.run(editor.ij, context.ij)
}
} }
if (isInternalMacro) { if (isInternalMacro) {

View File

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

View File

@ -218,13 +218,17 @@ internal class VimEnterHandler(nextHandler: EditorActionHandler?) : VimKeyHandle
internal class VimEscHandler(nextHandler: EditorActionHandler) : VimKeyHandler(nextHandler) { internal class VimEscHandler(nextHandler: EditorActionHandler) : VimKeyHandler(nextHandler) {
override val key: String = "<Esc>" override val key: String = "<Esc>"
private val ideaVimSupportDialog
get() = injector.globalIjOptions().ideavimsupport.contains(IjOptionConstants.ideavimsupport_dialog)
override fun isHandlerEnabled(editor: Editor, dataContext: DataContext?): Boolean { override fun isHandlerEnabled(editor: Editor, dataContext: DataContext?): Boolean {
val ideaVimSupportDialog =
injector.globalIjOptions().ideavimsupport.contains(IjOptionConstants.ideavimsupport_dialog)
return editor.isPrimaryEditor() || return editor.isPrimaryEditor() ||
EditorHelper.isFileEditor(editor) && !editor.vim.mode.inNormalMode || EditorHelper.isFileEditor(editor) && vimStateNeedsToHandleEscape(editor) ||
ideaVimSupportDialog && !editor.vim.mode.inNormalMode 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); final int offset = y - ((screenHeight - lineHeight) / lineHeight / 2 * lineHeight);
@NotNull final VimEditor editor1 = new IjVimEditor(editor); @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); 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. // 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.codeWithMe.ClientId
import com.intellij.openapi.editor.Caret import com.intellij.openapi.editor.Caret
import com.intellij.openapi.editor.CaretState
import com.intellij.openapi.editor.Editor import com.intellij.openapi.editor.Editor
import com.intellij.openapi.editor.ex.util.EditorUtil import com.intellij.openapi.editor.ex.util.EditorUtil
import com.intellij.openapi.fileEditor.ex.FileEditorManagerEx 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.api.injector
import com.maddyhome.idea.vim.group.IjOptionConstants import com.maddyhome.idea.vim.group.IjOptionConstants
import com.maddyhome.idea.vim.newapi.globalIjOptions 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 java.awt.Component
import javax.swing.JComponent import javax.swing.JComponent
import javax.swing.JTable import javax.swing.JTable
@ -96,3 +99,41 @@ internal val Caret.vimLine: Int
*/ */
internal val Editor.vimLine: Int internal val Editor.vimLine: Int
get() = this.caretModel.currentCaret.vimLine 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
import com.intellij.openapi.actionSystem.ex.ActionUtil.performDumbAwareWithCallbacks import com.intellij.openapi.actionSystem.ex.ActionUtil.performDumbAwareWithCallbacks
import com.intellij.openapi.actionSystem.impl.ProxyShortcutSet 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.application.ex.ApplicationManagerEx
import com.intellij.openapi.command.CommandProcessor import com.intellij.openapi.command.CommandProcessor
import com.intellij.openapi.command.UndoConfirmationPolicy import com.intellij.openapi.command.UndoConfirmationPolicy
@ -60,6 +61,8 @@ internal class IjActionExecutor : VimActionExecutor {
get() = IdeActions.ACTION_EXPAND_REGION get() = IdeActions.ACTION_EXPAND_REGION
override val ACTION_EXPAND_REGION_RECURSIVELY: String override val ACTION_EXPAND_REGION_RECURSIVELY: String
get() = IdeActions.ACTION_EXPAND_REGION_RECURSIVELY get() = IdeActions.ACTION_EXPAND_REGION_RECURSIVELY
override val ACTION_EXPAND_COLLAPSE_TOGGLE: String
get() = "ExpandCollapseToggleAction"
/** /**
* Execute an action * Execute an action
@ -92,6 +95,7 @@ internal class IjActionExecutor : VimActionExecutor {
ActionManager.getInstance(), ActionManager.getInstance(),
0, 0,
) )
Utils.initUpdateSession(event)
// beforeActionPerformedUpdate should be called to update the action. It fixes some rider-specific problems. // beforeActionPerformedUpdate should be called to update the action. It fixes some rider-specific problems.
// because rider use async update method. See VIM-1819. // because rider use async update method. See VIM-1819.
// This method executes inside of lastUpdateAndCheckDumb // 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. // that this needs to be replaced as a more or less dumb line for line rewrite.
val topLine = getVisualLineAtTopOfScreen(editor) val topLine = getVisualLineAtTopOfScreen(editor)
val bottomLine = getVisualLineAtBottomOfScreen(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 // 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 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.IjVimCaret
import com.maddyhome.idea.vim.newapi.globalIjOptions import com.maddyhome.idea.vim.newapi.globalIjOptions
import com.maddyhome.idea.vim.newapi.ij 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 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 // TODO refactor me after VIM-308 when restoring selection and caret movement will be ignored by undo
editor.runWithChangeTracking { editor.runWithChangeTracking {
undoManager.undo(fileEditor) undoManager.undo(fileEditor)
restoreVisualMode(editor)
// 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)
} }
} else { } else {
notifyAboutNewUndo(editor.ij.project) notifyAboutNewUndo(editor.ij.project)
@ -108,7 +102,7 @@ internal class UndoRedoHelper : UndoRedoBase() {
private fun hasSelection(editor: VimEditor): Boolean { private fun hasSelection(editor: VimEditor): Boolean {
return editor.primaryCaret().ij.hasSelection() return editor.primaryCaret().ij.hasSelection()
} }
override fun redo(editor: VimEditor, context: ExecutionContext): Boolean { override fun redo(editor: VimEditor, context: ExecutionContext): Boolean {
val ijContext = context.context as DataContext val ijContext = context.context as DataContext
val project = PlatformDataKeys.PROJECT.getData(ijContext) ?: return false val project = PlatformDataKeys.PROJECT.getData(ijContext) ?: return false
@ -229,4 +223,21 @@ internal class UndoRedoHelper : UndoRedoBase() {
val hasChanges: Boolean val hasChanges: Boolean
get() = changeListener.hasChanged || initialPath != editor.getPath() 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.editor.markup.RangeHighlighter
import com.intellij.openapi.util.Key import com.intellij.openapi.util.Key
import com.intellij.openapi.util.UserDataHolder 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.LocalMarkStorage
import com.maddyhome.idea.vim.api.SelectionInfo 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.ex.ExOutputModel
import com.maddyhome.idea.vim.group.visual.VisualChange import com.maddyhome.idea.vim.group.visual.VisualChange
import com.maddyhome.idea.vim.group.visual.vimLeadSelectionOffset 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.newapi.vim
import com.maddyhome.idea.vim.state.VimStateMachine
import com.maddyhome.idea.vim.state.mode.Mode import com.maddyhome.idea.vim.state.mode.Mode
import com.maddyhome.idea.vim.state.mode.SelectionType import com.maddyhome.idea.vim.state.mode.SelectionType
import com.maddyhome.idea.vim.ui.ExOutputPanel 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 // 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.markStorage: LocalMarkStorage? by userDataCaretToEditor()
internal var Caret.lastSelectionInfo: SelectionInfo? 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.execution.impl.ConsoleViewImpl
import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.editor.EditorKind
import com.maddyhome.idea.vim.KeyHandler import com.maddyhome.idea.vim.KeyHandler
import com.maddyhome.idea.vim.VimPlugin import com.maddyhome.idea.vim.VimPlugin
import com.maddyhome.idea.vim.api.ExecutionContext 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.api.injector
import com.maddyhome.idea.vim.command.OperatorArguments import com.maddyhome.idea.vim.command.OperatorArguments
import com.maddyhome.idea.vim.common.EditorListener 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.helper.inInsertMode
import com.maddyhome.idea.vim.newapi.ij import com.maddyhome.idea.vim.newapi.ij
import com.maddyhome.idea.vim.state.mode.Mode import com.maddyhome.idea.vim.state.mode.Mode
@ -63,13 +61,7 @@ class IJEditorFocusListener : EditorListener {
val context: ExecutionContext = injector.executionContextManager.getEditorExecutionContext(editor) val context: ExecutionContext = injector.executionContextManager.getEditorExecutionContext(editor)
VimPlugin.getChange().insertBeforeCursor(editor, context) VimPlugin.getChange().insertBeforeCursor(editor, context)
} }
if (!ijEditor.isViewer && if (!ijEditor.document.isWritable) {
!EditorHelper.isFileEditor(ijEditor) &&
ijEditor.document.isWritable &&
!ijEditor.inInsertMode && ijEditor.editorKind != EditorKind.DIFF
) {
switchToInsertMode.run()
} else if (!ijEditor.document.isWritable) {
val context: ExecutionContext = injector.executionContextManager.getEditorExecutionContext(editor) val context: ExecutionContext = injector.executionContextManager.getEditorExecutionContext(editor)
val mode = injector.vimState.mode val mode = injector.vimState.mode
when (mode) { when (mode) {
@ -86,4 +78,4 @@ class IJEditorFocusListener : EditorListener {
} }
KeyHandler.getInstance().reset(editor) KeyHandler.getInstance().reset(editor)
} }
} }

View File

@ -28,6 +28,7 @@ import com.intellij.openapi.actionSystem.CommonDataKeys
import com.intellij.openapi.actionSystem.ex.AnActionListener import com.intellij.openapi.actionSystem.ex.AnActionListener
import com.intellij.openapi.actionSystem.impl.ProxyShortcutSet import com.intellij.openapi.actionSystem.impl.ProxyShortcutSet
import com.intellij.openapi.editor.Editor import com.intellij.openapi.editor.Editor
import com.intellij.openapi.editor.impl.ScrollingModelImpl
import com.intellij.openapi.keymap.KeymapManager import com.intellij.openapi.keymap.KeymapManager
import com.intellij.openapi.project.DumbAwareToggleAction import com.intellij.openapi.project.DumbAwareToggleAction
import com.intellij.openapi.util.TextRange import com.intellij.openapi.util.TextRange
@ -58,6 +59,7 @@ internal object IdeaSpecifics {
private val surrounderAction = private val surrounderAction =
"com.intellij.codeInsight.generation.surroundWith.SurroundWithHandler\$InvokeSurrounderAction" "com.intellij.codeInsight.generation.surroundWith.SurroundWithHandler\$InvokeSurrounderAction"
private var editor: Editor? = null private var editor: Editor? = null
private var caretOffset = -1
private var completionPrevDocumentLength: Int? = null private var completionPrevDocumentLength: Int? = null
private var completionPrevDocumentOffset: Int? = null private var completionPrevDocumentOffset: Int? = null
@ -67,6 +69,7 @@ internal object IdeaSpecifics {
val hostEditor = event.dataContext.getData(CommonDataKeys.HOST_EDITOR) val hostEditor = event.dataContext.getData(CommonDataKeys.HOST_EDITOR)
if (hostEditor != null) { if (hostEditor != null) {
editor = hostEditor editor = hostEditor
caretOffset = hostEditor.caretModel.offset
} }
val isVimAction = (action as? AnActionWrapper)?.delegate is VimShortcutKeyAction val isVimAction = (action as? AnActionWrapper)?.delegate is VimShortcutKeyAction
@ -115,42 +118,57 @@ internal object IdeaSpecifics {
if (VimPlugin.isNotEnabled()) return if (VimPlugin.isNotEnabled()) return
val editor = editor val editor = editor
if (editor != null && action is ChooseItemAction && injector.registerGroup.isRecording) { if (editor != null) {
val prevDocumentLength = completionPrevDocumentLength if (action is ChooseItemAction && injector.registerGroup.isRecording) {
val prevDocumentOffset = completionPrevDocumentOffset val prevDocumentLength = completionPrevDocumentLength
val prevDocumentOffset = completionPrevDocumentOffset
if (prevDocumentLength != null && prevDocumentOffset != null) { if (prevDocumentLength != null && prevDocumentOffset != null) {
val register = VimPlugin.getRegister() val register = VimPlugin.getRegister()
val addedTextLength = editor.document.textLength - prevDocumentLength val addedTextLength = editor.document.textLength - prevDocumentLength
val caretShift = addedTextLength - (editor.caretModel.primaryCaret.offset - prevDocumentOffset) val caretShift = addedTextLength - (editor.caretModel.primaryCaret.offset - prevDocumentOffset)
val leftArrow = KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0) val leftArrow = KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0)
register.recordText(editor.document.getText(TextRange(prevDocumentOffset, prevDocumentOffset + addedTextLength))) register.recordText(editor.document.getText(TextRange(prevDocumentOffset, prevDocumentOffset + addedTextLength)))
repeat(caretShift.coerceAtLeast(0)) { repeat(caretShift.coerceAtLeast(0)) {
register.recordKeyStroke(leftArrow) register.recordKeyStroke(leftArrow)
}
}
this.completionPrevDocumentLength = null
this.completionPrevDocumentOffset = null
}
//region Enter insert mode after surround with if
if (surrounderAction == action.javaClass.name && surrounderItems.any {
action.templatePresentation.text.endsWith(
it,
)
}
) {
editor?.let {
it.vim.mode = Mode.NORMAL()
VimPlugin.getChange().insertBeforeCursor(it.vim, event.dataContext.vim)
KeyHandler.getInstance().reset(it.vim)
} }
} }
//endregion
this.completionPrevDocumentLength = null if (caretOffset != -1 && caretOffset != editor.caretModel.offset) {
this.completionPrevDocumentOffset = null val scrollModel = editor.scrollingModel as ScrollingModelImpl
} if (scrollModel.isScrollingNow) {
val v = scrollModel.verticalScrollOffset
//region Enter insert mode after surround with if val h = scrollModel.horizontalScrollOffset
if (surrounderAction == action.javaClass.name && surrounderItems.any { scrollModel.finishAnimation()
action.templatePresentation.text.endsWith( scrollModel.scroll(h, v)
it, scrollModel.finishAnimation()
) }
} injector.scroll.scrollCaretIntoView(editor.vim)
) {
editor?.let {
it.vim.mode = Mode.NORMAL()
VimPlugin.getChange().insertBeforeCursor(it.vim, event.dataContext.vim)
KeyHandler.getInstance().reset(it.vim)
} }
} }
//endregion
this.editor = null 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.EditorEventMulticasterEx
import com.intellij.openapi.editor.ex.FocusChangeListener import com.intellij.openapi.editor.ex.FocusChangeListener
import com.intellij.openapi.editor.impl.EditorComponentImpl 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.FileEditorManager
import com.intellij.openapi.fileEditor.FileEditorManagerEvent import com.intellij.openapi.fileEditor.FileEditorManagerEvent
import com.intellij.openapi.fileEditor.FileEditorManagerListener 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.EditorComposite
import com.intellij.openapi.fileEditor.impl.EditorWindow import com.intellij.openapi.fileEditor.impl.EditorWindow
import com.intellij.openapi.project.ProjectManager 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.Disposer
import com.intellij.openapi.util.Key import com.intellij.openapi.util.Key
import com.intellij.openapi.util.removeUserData import com.intellij.openapi.util.removeUserData
import com.intellij.openapi.vfs.VirtualFile import com.intellij.openapi.vfs.VirtualFile
import com.intellij.util.ExceptionUtil import com.intellij.util.ExceptionUtil
import com.jetbrains.rd.util.lifetime.Lifetime
import com.maddyhome.idea.vim.EventFacade import com.maddyhome.idea.vim.EventFacade
import com.maddyhome.idea.vim.KeyHandler import com.maddyhome.idea.vim.KeyHandler
import com.maddyhome.idea.vim.VimKeyListener 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.CaretVisualAttributesListener
import com.maddyhome.idea.vim.helper.GuicursorChangeListener import com.maddyhome.idea.vim.helper.GuicursorChangeListener
import com.maddyhome.idea.vim.helper.StrictMode 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.exitSelectMode
import com.maddyhome.idea.vim.helper.exitVisualMode import com.maddyhome.idea.vim.helper.exitVisualMode
import com.maddyhome.idea.vim.helper.forceBarCursor 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.InsertTimeRecorder
import com.maddyhome.idea.vim.newapi.ij import com.maddyhome.idea.vim.newapi.ij
import com.maddyhome.idea.vim.newapi.vim 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.inSelectMode
import com.maddyhome.idea.vim.state.mode.selectionType import com.maddyhome.idea.vim.state.mode.selectionType
import com.maddyhome.idea.vim.ui.ShowCmdOptionChangeListener 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.macro.macroWidgetOptionListener
import com.maddyhome.idea.vim.ui.widgets.mode.listeners.ModeWidgetListener import com.maddyhome.idea.vim.ui.widgets.mode.listeners.ModeWidgetListener
import com.maddyhome.idea.vim.ui.widgets.mode.modeWidgetOptionListener import com.maddyhome.idea.vim.ui.widgets.mode.modeWidgetOptionListener
import com.maddyhome.idea.vim.vimDisposable
import java.awt.event.MouseAdapter import java.awt.event.MouseAdapter
import java.awt.event.MouseEvent import java.awt.event.MouseEvent
import javax.swing.SwingUtilities 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 // TODO: If the user changes the 'ideavimsupport' option, existing editors won't be initialised
if (vimDisabled(editor)) return if (vimDisabled(editor)) return
// As I understand, there is no need to pass a disposable that also disposes on editor close val pluginLifetime = VimPlugin.getInstance().createLifetime()
// because all editor resources will be garbage collected anyway on editor close val editorLifetime = (editor as EditorImpl).disposable.createLifetime()
// Note that this uses the plugin's main disposable, rather than VimPlugin.onOffDisposable, because we don't need val disposable =
// to - we explicitly call VimListenerManager.removeAll from VimPlugin.turnOffPlugin, and this disposes each Lifetime.intersect(pluginLifetime, editorLifetime).createNestedDisposable("MyLifetimedDisposable")
// editor's disposable individually.
val disposable = editor.project?.vimDisposable ?: return
// Protect against double initialisation // Protect against double initialisation
if (editor.getUserData(editorListenersDisposableKey) != null) { if (editor.getUserData(editorListenersDisposableKey) != null) {
@ -386,7 +387,17 @@ internal object VimListenerManager {
override fun selectionChanged(event: FileEditorManagerEvent) { override fun selectionChanged(event: FileEditorManagerEvent) {
// We can't rely on being passed a non-null editor, so check for Code With Me scenarios explicitly // 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 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) MotionGroup.fileEditorManagerSelectionChangedCallback(event)
FileGroup.fileEditorManagerSelectionChangedCallback(event) FileGroup.fileEditorManagerSelectionChangedCallback(event)
VimPlugin.getSearch().fileEditorManagerSelectionChangedCallback(event) VimPlugin.getSearch().fileEditorManagerSelectionChangedCallback(event)
@ -458,8 +469,6 @@ internal object VimListenerManager {
event.editor.putUserData(openingEditorKey, OpeningEditor(openingEditor, owningEditorWindow, isPreview, canBeReused)) event.editor.putUserData(openingEditorKey, OpeningEditor(openingEditor, owningEditorWindow, isPreview, canBeReused))
} }
VimStandalonePluginUpdateChecker.getInstance().pluginUsed()
} }
override fun editorReleased(event: EditorFactoryEvent) { override fun editorReleased(event: EditorFactoryEvent) {
@ -739,7 +748,7 @@ internal object VimListenerManager {
injector.commandLine.getActiveCommandLine()?.close(refocusOwningEditor = true, resetCaret = false) injector.commandLine.getActiveCommandLine()?.close(refocusOwningEditor = true, resetCaret = false)
injector.modalInput.getCurrentModalInput()?.deactivate(refocusOwningEditor = true, resetCaret = false) injector.modalInput.getCurrentModalInput()?.deactivate(refocusOwningEditor = true, resetCaret = false)
ExOutputModel.tryGetInstance(editor)?.close() injector.outputPanel.getCurrentOutputPanel()?.close()
val caretModel = editor.caretModel val caretModel = editor.caretModel
if (editor.vim.mode.selectionType != null) { if (editor.vim.mode.selectionType != null) {
@ -768,7 +777,7 @@ internal object VimListenerManager {
injector.commandLine.getActiveCommandLine()?.close(refocusOwningEditor = true, resetCaret = false) injector.commandLine.getActiveCommandLine()?.close(refocusOwningEditor = true, resetCaret = false)
injector.modalInput.getCurrentModalInput()?.deactivate(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 { internal class IjLiveRange(val marker: RangeMarker) : LiveRange {
override val startOffset: Int override val startOffset: Int
get() = marker.startOffset get() = marker.startOffset
override val endOffset: Int
get() = marker.endOffset
} }
val RangeMarker.vim: LiveRange 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.LogicalPosition
import com.intellij.openapi.editor.VisualPosition import com.intellij.openapi.editor.VisualPosition
import com.maddyhome.idea.vim.api.BufferPosition 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.ImmutableVimCaret
import com.maddyhome.idea.vim.api.LocalMarkStorage import com.maddyhome.idea.vim.api.LocalMarkStorage
import com.maddyhome.idea.vim.api.SelectionInfo 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.lastSelectionInfo
import com.maddyhome.idea.vim.helper.markStorage import com.maddyhome.idea.vim.helper.markStorage
import com.maddyhome.idea.vim.helper.moveToInlayAwareOffset 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.resetVimLastColumn
import com.maddyhome.idea.vim.helper.vimInsertStart import com.maddyhome.idea.vim.helper.vimInsertStart
import com.maddyhome.idea.vim.helper.vimLastColumn 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() { 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 override val markStorage: LocalMarkStorage
get() { get() {
var storage = this.caret.markStorage 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) } return editor.caretModel.allCarets.map { IjVimCaret(it) }
} }
override var isFirstCaret = true
override var isReversingCarets = false
@Suppress("ideavimRunForEachCaret") @Suppress("ideavimRunForEachCaret")
override fun forEachCaret(action: (VimCaret) -> Unit) { override fun forEachCaret(action: (VimCaret) -> Unit) {
if (editor.vim.inBlockSelection) { if (editor.vim.inBlockSelection) {
action(IjVimCaret(editor.caretModel.primaryCaret)) action(IjVimCaret(editor.caretModel.primaryCaret))
} else { } else {
editor.caretModel.runForEachCaret({ try {
if (it.isValid) { editor.caretModel.runForEachCaret({
action(IjVimCaret(it)) if (it.isValid) {
} action(IjVimCaret(it))
}, false) isFirstCaret = false
}
}, false)
} finally {
isFirstCaret = true
}
} }
} }
override fun forEachNativeCaret(action: (VimCaret) -> Unit, reverse: Boolean) { 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 { override fun isInForEachCaretScope(): Boolean {
@ -530,4 +547,4 @@ internal class InsertTimeRecorder: ModeChangeListener {
editor.forEachCaret { undo.endInsertSequence(it, it.offset, nanoTime) } editor.forEachCaret { undo.endInsertSequence(it, it.offset, nanoTime) }
} }
} }
} }

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() { void toggleInsertReplace() {
VimCommandLine commandLine = injector.getCommandLine().getActiveCommandLine(); VimCommandLine commandLine = injector.getCommandLine().getActiveCommandLine();
if (commandLine != null) { if (commandLine != null) {
commandLine.toggleReplaceMode(); ((ExEntryPanel) commandLine).isReplaceMode = !((ExEntryPanel)commandLine).isReplaceMode;
} }
overwrite = !overwrite; overwrite = !overwrite;
} }

View File

@ -7,7 +7,6 @@
*/ */
package com.maddyhome.idea.vim.ui.ex package com.maddyhome.idea.vim.ui.ex
import com.intellij.openapi.diagnostic.debug
import com.intellij.openapi.diagnostic.logger import com.intellij.openapi.diagnostic.logger
import com.maddyhome.idea.vim.KeyHandler import com.maddyhome.idea.vim.KeyHandler
import com.maddyhome.idea.vim.api.injector import com.maddyhome.idea.vim.api.injector
@ -15,50 +14,12 @@ import com.maddyhome.idea.vim.newapi.vim
import org.jetbrains.annotations.NonNls import org.jetbrains.annotations.NonNls
import java.awt.event.ActionEvent import java.awt.event.ActionEvent
import java.awt.event.KeyEvent import java.awt.event.KeyEvent
import javax.swing.Action
import javax.swing.KeyStroke import javax.swing.KeyStroke
import javax.swing.text.DefaultEditorKit import javax.swing.text.DefaultEditorKit
import javax.swing.text.Document import javax.swing.text.Document
import javax.swing.text.TextAction
@Deprecated("ExCommands should be migrated to KeyHandler like commands for other modes") @Deprecated("ExCommands should be migrated to KeyHandler like commands for other modes")
internal object ExEditorKit : DefaultEditorKit() { 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 * Gets the MIME type of the data that this
* kit represents support for. * kit represents support for.
@ -70,19 +31,6 @@ internal object ExEditorKit : DefaultEditorKit() {
return "text/ideavim" 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 * Creates an uninitialized text storage model
* that is appropriate for this type of editor. * that is appropriate for this type of editor.
@ -93,48 +41,29 @@ internal object ExEditorKit : DefaultEditorKit() {
return ExDocument() return ExDocument()
} }
private val exActions = arrayOf<Action>(
CancelEntryAction(),
CompleteEntryAction(),
EscapeCharAction(),
DeleteNextCharAction(),
DeletePreviousCharAction(),
DeletePreviousWordAction(),
DeleteToCursorAction(),
HistoryUpAction(),
HistoryDownAction(),
HistoryUpFilterAction(),
HistoryDownFilterAction(),
ToggleInsertReplaceAction(),
)
class DefaultExKeyHandler : DefaultKeyTypedAction() { class DefaultExKeyHandler : DefaultKeyTypedAction() {
override fun actionPerformed(e: ActionEvent) { override fun actionPerformed(e: ActionEvent) {
val target = getTextComponent(e) as ExTextField val target = getTextComponent(e) as ExTextField
val currentAction = target.currentAction
if (currentAction != null) { val key = convert(e)
currentAction.actionPerformed(e) if (key != null) {
} else { val c = key.keyChar
val key = convert(e) if (c.code > 0) {
if (key != null) { if (target.useHandleKeyFromEx) {
val c = key.keyChar val panel = ((injector.commandLine.getActiveCommandLine() as? ExEntryPanel) ?: (injector.modalInput.getCurrentModalInput() as? WrappedAsModalInputExEntryPanel)?.exEntryPanel) ?: return
if (c.code > 0) { val entry = panel.entry
if (target.useHandleKeyFromEx) { val editor = entry.editor
val panel = ((injector.commandLine.getActiveCommandLine() as? ExEntryPanel) ?: (injector.modalInput.getCurrentModalInput() as? WrappedAsModalInputExEntryPanel)?.exEntryPanel) ?: return val keyHandler = KeyHandler.getInstance()
val entry = panel.entry keyHandler.handleKey(editor!!.vim, key, entry.context.vim, keyHandler.keyHandlerState)
val editor = entry.editor } else {
val keyHandler = KeyHandler.getInstance() val event = ActionEvent(e.source, e.id, c.toString(), e.getWhen(), e.modifiers)
keyHandler.handleKey(editor!!.vim, key, entry.context.vim, keyHandler.keyHandlerState) super.actionPerformed(event)
} else {
val event = ActionEvent(e.source, e.id, c.toString(), e.getWhen(), e.modifiers)
super.actionPerformed(event)
}
target.saveLastEntry()
} }
} else {
super.actionPerformed(e)
target.saveLastEntry() target.saveLastEntry()
} }
} else {
super.actionPerformed(e)
target.saveLastEntry()
} }
} }
} }

View File

@ -23,7 +23,10 @@ import com.maddyhome.idea.vim.EventFacade;
import com.maddyhome.idea.vim.KeyHandler; import com.maddyhome.idea.vim.KeyHandler;
import com.maddyhome.idea.vim.VimPlugin; import com.maddyhome.idea.vim.VimPlugin;
import com.maddyhome.idea.vim.action.VimShortcutKeyAction; 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.ex.ranges.LineRange;
import com.maddyhome.idea.vim.helper.SearchHighlightsHelper; import com.maddyhome.idea.vim.helper.SearchHighlightsHelper;
import com.maddyhome.idea.vim.helper.UiHelper; 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 class ExEntryPanel extends JPanel implements VimCommandLine {
public static ExEntryPanel instance; public static ExEntryPanel instance;
public static ExEntryPanel instanceWithoutShortcuts; public static ExEntryPanel instanceWithoutShortcuts;
private boolean isReplaceMode = false; public boolean isReplaceMode = false;
private WeakReference<Editor> weakEditor = null; private WeakReference<Editor> weakEditor = null;
private VimInputInterceptor myInputInterceptor = null; private VimInputInterceptor myInputInterceptor = null;
@ -348,7 +351,7 @@ public class ExEntryPanel extends JPanel implements VimCommandLine {
// coerced to at least 1. // coerced to at least 1.
int count1 = KeyHandler.getInstance().getKeyHandlerState().getEditorCommandBuilder().getAggregatedUncommittedCount(); 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 final boolean forwards = !labelText.equals("?"); // :s, :g, :v are treated as forwards
int pattenEnd = injector.getSearchGroup().findEndOfPattern(searchText, separator, 0); int pattenEnd = injector.getSearchGroup().findEndOfPattern(searchText, separator, 0);
final String pattern = searchText.substring(0, pattenEnd); final String pattern = searchText.substring(0, pattenEnd);
@ -402,7 +405,7 @@ public class ExEntryPanel extends JPanel implements VimCommandLine {
@Override @Override
public void toggleReplaceMode() { public void toggleReplaceMode() {
isReplaceMode = !isReplaceMode; entry.toggleInsertReplace();
} }
/** /**
@ -535,10 +538,11 @@ public class ExEntryPanel extends JPanel implements VimCommandLine {
} }
@Override @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 // 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(); int offset = getCaret().getOffset();
entry.updateText(string); entry.updateText(string);
if (updateLastEntry) entry.saveLastEntry();
getCaret().setOffset(Math.min(offset, getVisibleText().length())); getCaret().setOffset(Math.min(offset, getVisibleText().length()));
} }
@ -595,6 +599,27 @@ public class ExEntryPanel extends JPanel implements VimCommandLine {
return finishOn; 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 { public static class LafListener implements LafManagerListener {
@Override @Override
public void lookAndFeelChanged(@NotNull LafManager source) { public void lookAndFeelChanged(@NotNull LafManager source) {

View File

@ -21,57 +21,6 @@ internal object ExKeyBindings {
val bindings: Array<KeyBinding> by lazy { val bindings: Array<KeyBinding> by lazy {
arrayOf( 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 // These appear to be non-Vim shortcuts
KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_V, KeyEvent.META_DOWN_MASK), DefaultEditorKit.pasteAction), KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_V, KeyEvent.META_DOWN_MASK), DefaultEditorKit.pasteAction),
KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_INSERT, KeyEvent.SHIFT_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() { fun registerCustomShortcutSet() {
val shortcuts = ExKeyBindings.bindings.map { val shortcuts = listOf(
KeyboardShortcut(it.key, null) KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0),
}.toTypedArray() 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) 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.VimPlugin;
import com.maddyhome.idea.vim.api.VimCommandLine; import com.maddyhome.idea.vim.api.VimCommandLine;
import com.maddyhome.idea.vim.api.VimCommandLineCaret; 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.helper.UiHelper;
import com.maddyhome.idea.vim.history.HistoryConstants; import com.maddyhome.idea.vim.history.HistoryConstants;
import com.maddyhome.idea.vim.history.HistoryEntry; 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.GuiCursorAttributes;
import com.maddyhome.idea.vim.options.helpers.GuiCursorMode; import com.maddyhome.idea.vim.options.helpers.GuiCursorMode;
import com.maddyhome.idea.vim.options.helpers.GuiCursorOptionHelper; 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 // 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 // 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 // something like : !%!C, which I don't believe is documented, or useful
if (currentAction != null) {
clearCurrentAction();
}
super.mouseClicked(e); super.mouseClicked(e);
} }
}); });
@ -240,20 +235,15 @@ 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 // 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, // 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. // dispatch to ExEntryPanel#handleKey and if it's processed, mark the event as consumed.
if (currentAction != null) { KeyEvent event = new KeyEvent(this, keyChar != KeyEvent.CHAR_UNDEFINED ? KeyEvent.KEY_TYPED :
currentAction.actionPerformed(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, String.valueOf(c), modifiers)); (stroke.isOnKeyRelease() ? KeyEvent.KEY_RELEASED : KeyEvent.KEY_PRESSED),
} (new Date()).getTime(), modifiers, keyCode, c);
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);
useHandleKeyFromEx = false; useHandleKeyFromEx = false;
try { try {
super.processKeyEvent(event); super.processKeyEvent(event);
}finally { } finally {
useHandleKeyFromEx = true; useHandleKeyFromEx = true;
}
} }
} }
@ -279,12 +269,7 @@ public class ExTextField extends JTextField {
* Cancels current action, if there is one. If not, cancels entry. * Cancels current action, if there is one. If not, cancels entry.
*/ */
void escape() { void escape() {
if (currentAction != null) { cancel();
clearCurrentAction();
}
else {
cancel();
}
} }
/** /**
@ -299,19 +284,10 @@ public class ExTextField extends JTextField {
} }
public void clearCurrentAction() { public void clearCurrentAction() {
if (currentAction != null) {
currentAction.reset();
}
currentAction = null;
VimCommandLine commandLine = injector.getCommandLine().getActiveCommandLine(); VimCommandLine commandLine = injector.getCommandLine().getActiveCommandLine();
if (commandLine != null) commandLine.clearPromptCharacter(); if (commandLine != null) commandLine.clearPromptCharacter();
} }
@Nullable
Action getCurrentAction() {
return currentAction;
}
private void setInsertMode() { private void setInsertMode() {
ExDocument doc = (ExDocument)getDocument(); ExDocument doc = (ExDocument)getDocument();
if (doc.isOverwrite()) { if (doc.isOverwrite()) {
@ -542,10 +518,9 @@ public class ExTextField extends JTextField {
private DataContext context; private DataContext context;
private final CommandLineCaret caret; private final CommandLineCaret caret;
private String lastEntry; String lastEntry;
private List<HistoryEntry> history; private List<HistoryEntry> history;
private int histIndex = 0; int histIndex = 0;
private @Nullable MultiStepAction currentAction;
int currentActionPromptCharacterOffset = -1; int currentActionPromptCharacterOffset = -1;
private static final Logger logger = Logger.getInstance(ExTextField.class.getName()); private static final Logger logger = Logger.getInstance(ExTextField.class.getName());

View File

@ -8,114 +8,20 @@
package com.maddyhome.idea.vim.vimscript package com.maddyhome.idea.vim.vimscript
import com.intellij.openapi.actionSystem.DataContext
import com.intellij.openapi.components.Service import com.intellij.openapi.components.Service
import com.intellij.openapi.diagnostic.logger
import com.intellij.openapi.fileEditor.FileDocumentManager import com.intellij.openapi.fileEditor.FileDocumentManager
import com.intellij.openapi.vfs.VirtualFileManager 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.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.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.File
import java.io.IOException
@Service @Service
internal class Executor : VimScriptExecutorBase() { internal class Executor : VimScriptExecutorBase() {
private val logger = logger<Executor>() override fun enableDelayedExtensions() {
override var executingVimscript = false VimExtensionRegistrar.enableDelayedExtensions()
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
VimExtensionRegistrar.enableDelayedExtensions()
}
} }
override fun executeFile(file: File, editor: VimEditor, fileIsIdeaVimRcConfig: Boolean, indicateErrors: Boolean) { override fun ensureFileIsSaved(file: File) {
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) {
val documentManager = FileDocumentManager.getInstance() val documentManager = FileDocumentManager.getInstance()
VirtualFileManager.getInstance().findFileByNioPath(file.toPath()) VirtualFileManager.getInstance().findFileByNioPath(file.toPath())
@ -123,16 +29,4 @@ internal class Executor : VimScriptExecutorBase() {
?.takeIf(documentManager::isDocumentUnsaved) ?.takeIf(documentManager::isDocumentUnsaved)
?.let(documentManager::saveDocumentAsIs) ?.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()) } } .filter { line -> searchPattern.all { it in line.lowercase(Locale.getDefault()) } }
.joinToString(lineSeparator) .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 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.VimPlugin
import com.maddyhome.idea.vim.api.ExecutionContext import com.maddyhome.idea.vim.api.ExecutionContext
import com.maddyhome.idea.vim.api.VimEditor 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.command.OperatorArguments
import com.maddyhome.idea.vim.ex.ExOutputModel
import com.maddyhome.idea.vim.ex.ranges.Range import com.maddyhome.idea.vim.ex.ranges.Range
import com.maddyhome.idea.vim.helper.EditorHelper import com.maddyhome.idea.vim.helper.EditorHelper
import com.maddyhome.idea.vim.helper.vimLine 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 filter = pruneUnsupportedFilters(arg)
val bufferList = getBufferList(context, filter) 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 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.VimPlugin
import com.maddyhome.idea.vim.api.ExecutionContext import com.maddyhome.idea.vim.api.ExecutionContext
import com.maddyhome.idea.vim.api.VimEditor 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.command.OperatorArguments
import com.maddyhome.idea.vim.ex.ExException import com.maddyhome.idea.vim.ex.ExException
import com.maddyhome.idea.vim.ex.ExOutputModel 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) { if (range.size() == 0) {
// Show command output in a window // Show command output in a window
VimPlugin.getProcess().executeCommand(editor, command, null, workingDirectory)?.let { 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 lastCommand = command
ExecutionResult.Success ExecutionResult.Success

View File

@ -1,12 +1,4 @@
<!-- <idea-plugin xmlns:xi="http://www.w3.org/2001/XInclude">
~ 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">
<name>IdeaVim</name> <name>IdeaVim</name>
<id>IdeaVIM</id> <id>IdeaVIM</id>
<description><![CDATA[ <description><![CDATA[
@ -21,7 +13,7 @@
<li><a href="https://youtrack.jetbrains.com/issues/VIM">Issue tracker</a>: feature requests and bug reports</li> <li><a href="https://youtrack.jetbrains.com/issues/VIM">Issue tracker</a>: feature requests and bug reports</li>
</ul> </ul>
]]></description> ]]></description>
<version>SNAPSHOT</version> <version>chylex</version>
<vendor>JetBrains</vendor> <vendor>JetBrains</vendor>
<!-- Mark the plugin as compatible with RubyMine and other products based on the IntelliJ platform (including CWM) --> <!-- Mark the plugin as compatible with RubyMine and other products based on the IntelliJ platform (including CWM) -->
@ -133,10 +125,12 @@
<xi:include href="/META-INF/includes/VimListeners.xml" xpointer="xpointer(/idea-plugin/*)"/> <xi:include href="/META-INF/includes/VimListeners.xml" xpointer="xpointer(/idea-plugin/*)"/>
<actions resource-bundle="messages.IdeaVimBundle"> <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"/> <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 --> <!-- Internal -->
<!--suppress PluginXmlI18n --> <!--suppress PluginXmlI18n -->
<action id="VimInternalAddBlockInlays" class="com.maddyhome.idea.vim.action.internal.AddBlockInlaysAction" text="Add Test Block Inlays | IdeaVim Internal" internal="true"/> <action id="VimInternalAddBlockInlays" class="com.maddyhome.idea.vim.action.internal.AddBlockInlaysAction" text="Add Test Block Inlays | IdeaVim Internal" internal="true"/>
@ -154,5 +148,6 @@
</group> </group>
<action id="VimFindActionIdAction" class="com.maddyhome.idea.vim.listener.FindActionIdAction"/> <action id="VimFindActionIdAction" class="com.maddyhome.idea.vim.listener.FindActionIdAction"/>
<action id="VimJumpToSource" class="com.intellij.diff.actions.impl.OpenInEditorAction" />
</actions> </actions>
</idea-plugin> </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.api.injector
import com.maddyhome.idea.vim.common.TextRange import com.maddyhome.idea.vim.common.TextRange
import com.maddyhome.idea.vim.newapi.IjVimEditor import com.maddyhome.idea.vim.newapi.IjVimEditor
import com.maddyhome.idea.vim.newapi.vim
import com.maddyhome.idea.vim.state.mode.SelectionType import com.maddyhome.idea.vim.state.mode.SelectionType
import org.jetbrains.plugins.ideavim.VimBehaviorDiffers import org.jetbrains.plugins.ideavim.VimBehaviorDiffers
import org.jetbrains.plugins.ideavim.VimTestCase import org.jetbrains.plugins.ideavim.VimTestCase
@ -2173,7 +2172,7 @@ rtyfg${c}hzxc"""
val editor = configureByText(before) val editor = configureByText(before)
injector.registerGroup.storeText('*', "fgh") injector.registerGroup.storeText('*', "fgh")
VimPlugin.getRegister() 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")) typeText(injector.parser.parseKeys("\"*P"))
val after = "fg${c}hqfg${c}hwe asd zxc rty fg${c}hfgh vbn" val after = "fg${c}hqfg${c}hwe asd zxc rty fg${c}hfgh vbn"
assertState(after) assertState(after)

View File

@ -33,7 +33,7 @@ class IdeaPutNotificationsTest : VimTestCase() {
appReadySetup(false) appReadySetup(false)
val vimEditor = fixture.editor.vim val vimEditor = fixture.editor.vim
VimPlugin.getRegister() 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")) typeText(injector.parser.parseKeys("p"))
val notification = notifications().last() val notification = notifications().last()
@ -53,7 +53,7 @@ class IdeaPutNotificationsTest : VimTestCase() {
appReadySetup(false) appReadySetup(false)
val vimEditor = fixture.editor.vim val vimEditor = fixture.editor.vim
VimPlugin.getRegister() 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")) typeText(injector.parser.parseKeys("p"))
val notifications = notifications() val notifications = notifications()
@ -71,7 +71,7 @@ class IdeaPutNotificationsTest : VimTestCase() {
appReadySetup(true) appReadySetup(true)
val vimEditor = fixture.editor.vim val vimEditor = fixture.editor.vim
VimPlugin.getRegister() 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")) typeText(injector.parser.parseKeys("p"))
val notifications = EventLog.getLogModel(fixture.project).notifications val notifications = EventLog.getLogModel(fixture.project).notifications

View File

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

View File

@ -31,7 +31,7 @@ class PutTextBeforeCursorActionTest : VimTestCase() {
""".trimIndent() """.trimIndent()
val editor = configureByText(before) val editor = configureByText(before)
val vimEditor = editor.vim 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"))
typeText(injector.parser.parseKeys("V" + "P")) typeText(injector.parser.parseKeys("V" + "P"))
val after = """ val after = """

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -130,7 +130,7 @@ class MultipleCaretsTest : VimTestCase() {
val editor = configureByText(before) val editor = configureByText(before)
val vimEditor = editor.vim val vimEditor = editor.vim
VimPlugin.getRegister() 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")) typeText(commandToKeys("pu"))
val after = """ val after = """
qwe qwe
@ -165,7 +165,7 @@ class MultipleCaretsTest : VimTestCase() {
val editor = configureByText(before) val editor = configureByText(before)
val vimEditor = editor.vim val vimEditor = editor.vim
VimPlugin.getRegister() 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")) typeText(commandToKeys("pu"))
val after = """ val after = """
qwe qwe
@ -201,7 +201,7 @@ class MultipleCaretsTest : VimTestCase() {
val editor = configureByText(before) val editor = configureByText(before)
val vimEditor = editor.vim val vimEditor = editor.vim
VimPlugin.getRegister() 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")) typeText(commandToKeys("4pu"))
val after = """ val after = """
qwe qwe
@ -237,7 +237,7 @@ class MultipleCaretsTest : VimTestCase() {
val editor = configureByText(before) val editor = configureByText(before)
val vimEditor = editor.vim val vimEditor = editor.vim
VimPlugin.getRegister() 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")) typeText(commandToKeys("4pu"))
val after = """ val after = """
qwe 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 before = "${c}qwe\n" + "rty\n" + "as${c}d\n" + "fgh\n" + "zxc\n" + "vbn\n"
val editor = configureByText(before) val editor = configureByText(before)
VimPlugin.getRegister() 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("vj")
typeText(commandToKeys("pu")) 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.Test
import org.junit.jupiter.api.assertThrows import org.junit.jupiter.api.assertThrows
import kotlin.test.assertEquals import kotlin.test.assertEquals
import kotlin.test.assertNull
import kotlin.test.assertTrue import kotlin.test.assertTrue
/** /**
@ -267,7 +268,7 @@ class MapCommandTest : VimTestCase() {
configureByText("${c}foo\n") configureByText("${c}foo\n")
typeText(commandToKeys("imap a b \\| c")) typeText(commandToKeys("imap a b \\| c"))
typeText(injector.parser.parseKeys("ia")) typeText(injector.parser.parseKeys("ia"))
assertState("b \\| cfoo\n") assertState("b | cfoo\n")
} }
// VIM-666 |:imap| // VIM-666 |:imap|
@ -277,7 +278,7 @@ class MapCommandTest : VimTestCase() {
configureByText("${c}foo\n") configureByText("${c}foo\n")
typeText(commandToKeys("imap a b \\| c |")) typeText(commandToKeys("imap a b \\| c |"))
typeText(injector.parser.parseKeys("ia")) typeText(injector.parser.parseKeys("ia"))
assertState("b \\| c foo\n") assertState("b | c foo\n")
} }
// VIM-670 |:map| // VIM-670 |:map|
@ -754,4 +755,23 @@ class MapCommandTest : VimTestCase() {
assertTrue(KeyHandler.getInstance().keyStack.isEmpty()) 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 // 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. // 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 // 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")) typeText(commandToKeys("p"))
assertExOutput(" Lorem Ipsum") assertExOutput(" Lorem Ipsum")
} }

View File

@ -9,7 +9,6 @@
package org.jetbrains.plugins.ideavim.ex.implementation.commands package org.jetbrains.plugins.ideavim.ex.implementation.commands
import com.maddyhome.idea.vim.VimPlugin import com.maddyhome.idea.vim.VimPlugin
import com.maddyhome.idea.vim.newapi.vim
import com.maddyhome.idea.vim.register.RegisterConstants import com.maddyhome.idea.vim.register.RegisterConstants
import org.jetbrains.plugins.ideavim.VimTestCase import org.jetbrains.plugins.ideavim.VimTestCase
import org.junit.jupiter.api.Test 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. |Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.
|""".trimMargin()) |""".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) configureByText(text)
val vimEditor = fixture.editor.vim val vimEditor = fixture.editor.vim
VimPlugin.getRegister() 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")) typeText(injector.parser.parseKeys("griw"))
assertState("one on${c}e three") assertState("one on${c}e three")
assertEquals("one", VimPlugin.getRegister().lastRegister?.text) assertEquals("one", VimPlugin.getRegister().lastRegister?.text)
@ -170,7 +170,7 @@ class ReplaceWithRegisterTest : VimTestCase() {
configureByText(text) configureByText(text)
val vimEditor = fixture.editor.vim val vimEditor = fixture.editor.vim
VimPlugin.getRegister() 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")) typeText(injector.parser.parseKeys("3griw"))
assertState("one on${c}e four") assertState("one on${c}e four")
assertEquals("one", VimPlugin.getRegister().lastRegister?.text) assertEquals("one", VimPlugin.getRegister().lastRegister?.text)
@ -184,7 +184,7 @@ class ReplaceWithRegisterTest : VimTestCase() {
configureByText(text) configureByText(text)
val vimEditor = fixture.editor.vim val vimEditor = fixture.editor.vim
VimPlugin.getRegister() 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")) typeText(injector.parser.parseKeys("griw"))
assertState("one two one four") assertState("one two one four")
assertEquals("one", VimPlugin.getRegister().lastRegister?.text) assertEquals("one", VimPlugin.getRegister().lastRegister?.text)
@ -197,7 +197,7 @@ class ReplaceWithRegisterTest : VimTestCase() {
configureByText(text) configureByText(text)
val vimEditor = fixture.editor.vim val vimEditor = fixture.editor.vim
VimPlugin.getRegister() 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" + ".")) typeText(injector.parser.parseKeys("griw" + "w" + "."))
assertState("one one on${c}e four") assertState("one one on${c}e four")
assertEquals("one", VimPlugin.getRegister().lastRegister?.text) assertEquals("one", VimPlugin.getRegister().lastRegister?.text)
@ -247,7 +247,7 @@ class ReplaceWithRegisterTest : VimTestCase() {
configureByText(text) configureByText(text)
val vimEditor = fixture.editor.vim val vimEditor = fixture.editor.vim
VimPlugin.getRegister() 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")) typeText(injector.parser.parseKeys("grr"))
assertState( assertState(
""" """
@ -414,7 +414,7 @@ class ReplaceWithRegisterTest : VimTestCase() {
configureByText(text) configureByText(text)
val vimEditor = fixture.editor.vim val vimEditor = fixture.editor.vim
VimPlugin.getRegister() 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")) typeText(injector.parser.parseKeys("viw" + "gr"))
assertState( assertState(
""" """
@ -485,7 +485,7 @@ class ReplaceWithRegisterTest : VimTestCase() {
configureByText(text) configureByText(text)
val vimEditor = fixture.editor.vim val vimEditor = fixture.editor.vim
VimPlugin.getRegister() 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")) typeText(injector.parser.parseKeys("V" + "gr"))
assertState( assertState(
""" """

View File

@ -660,7 +660,7 @@ abstract class VimTestCase {
} }
fun assertExOutput(expected: String, clear: Boolean = true) { 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") assertNotNull(actual, "No Ex output")
assertEquals(expected, actual) assertEquals(expected, actual)
NeovimTesting.typeCommand("<esc>", testInfo, fixture.editor) 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.VimBehaviorDiffers
import org.jetbrains.plugins.ideavim.VimJavaTestCase import org.jetbrains.plugins.ideavim.VimJavaTestCase
import org.junit.jupiter.api.Test import org.junit.jupiter.api.Test
import kotlin.test.assertEquals
class ChangeActionJavaTest : VimJavaTestCase() { class ChangeActionJavaTest : VimJavaTestCase() {
// VIM-511 |.| // 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| // VIM-287 |zc| |o|
@TestWithoutNeovim(SkipNeovimReason.FOLDING) @TestWithoutNeovim(SkipNeovimReason.FOLDING)
@Test @Test

View File

@ -15,7 +15,7 @@ val javaVersion: String by project
val remoteRobotVersion: String by project val remoteRobotVersion: String by project
dependencies { 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") compileOnly("org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion")
testFixturesImplementation("org.jetbrains.kotlin:kotlin-test:$kotlinVersion") testFixturesImplementation("org.jetbrains.kotlin:kotlin-test:$kotlinVersion")
testFixturesImplementation(testFixtures(project(":"))) // The root project 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 val keyConsumers: List<KeyConsumer> = listOf(ModalInputConsumer(), MappingProcessor, CommandCountConsumer(), DeleteCommandConsumer(), EditorResetConsumer(), CharArgumentConsumer(), RegisterConsumer(), DigraphConsumer(), CommandConsumer(), SelectRegisterConsumer(), ModeInputConsumer())
private var handleKeyRecursionCount = 0 private var handleKeyRecursionCount = 0
var keyHandlerState: KeyHandlerState = KeyHandlerState() // KeyHandlerState requires injector.keyGroup to be initialized and that's why we don't create it immediately and have this here
private set // 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 keyStack: KeyStack = KeyStack()
val modalEntryKeys: MutableList<KeyStroke> = ArrayList() val modalEntryKeys: MutableList<KeyStroke> = ArrayList()
@ -283,6 +290,7 @@ class KeyHandler {
// TODO we should have a single reset method // TODO we should have a single reset method
fun reset(keyState: KeyHandlerState, mode: Mode) { fun reset(keyState: KeyHandlerState, mode: Mode) {
logger.trace { "Reset is executed" } logger.trace { "Reset is executed" }
injector.commandLine.getActiveCommandLine()?.clearCurrentAction()
keyHandlerState.partialReset(mode) keyHandlerState.partialReset(mode)
keyState.commandBuilder.resetAll(getKeyRoot(mode.toMappingMode())) 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.command.OperatorArguments
import com.maddyhome.idea.vim.handler.VimActionHandler 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() { class RedoAction : VimActionHandler.SingleExecution() {
override val type: Command.Type = Command.Type.OTHER_SELF_SYNCHRONIZED 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.command.OperatorArguments
import com.maddyhome.idea.vim.handler.VimActionHandler 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() { class UndoAction : VimActionHandler.SingleExecution() {
override val type: Command.Type = Command.Type.OTHER_SELF_SYNCHRONIZED override val type: Command.Type = Command.Type.OTHER_SELF_SYNCHRONIZED

View File

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

View File

@ -8,7 +8,6 @@
package com.maddyhome.idea.vim.action.change.change package com.maddyhome.idea.vim.action.change.change
import com.intellij.vim.annotations.CommandOrMotion 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.ExecutionContext
import com.maddyhome.idea.vim.api.VimCaret import com.maddyhome.idea.vim.api.VimCaret
import com.maddyhome.idea.vim.api.VimChangeGroup import com.maddyhome.idea.vim.api.VimChangeGroup
@ -23,7 +22,7 @@ import com.maddyhome.idea.vim.helper.CharacterHelper
/** /**
* @author vlan * @author vlan
*/ */
@CommandOrMotion(keys = ["U"], modes = [Mode.VISUAL]) @CommandOrMotion(keys = [], modes = [])
class ChangeCaseUpperVisualAction : VisualOperatorActionHandler.ForEachCaret() { class ChangeCaseUpperVisualAction : VisualOperatorActionHandler.ForEachCaret() {
override val type: Command.Type = Command.Type.CHANGE 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.CommandOrMotion
import com.intellij.vim.annotations.Mode import com.intellij.vim.annotations.Mode
import com.maddyhome.idea.vim.api.ExecutionContext 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.VimEditor
import com.maddyhome.idea.vim.api.injector import com.maddyhome.idea.vim.api.injector
import com.maddyhome.idea.vim.command.Argument import com.maddyhome.idea.vim.command.Argument
@ -36,7 +35,15 @@ sealed class PutTextBaseAction(
val count = operatorArguments.count1 val count = operatorArguments.count1
val sortedCarets = editor.sortedCarets() val sortedCarets = editor.sortedCarets()
return if (sortedCarets.size > 1) { 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 var result = true
injector.application.runWriteAction { injector.application.runWriteAction {
caretToPutData.forEach { caretToPutData.forEach {
@ -45,28 +52,24 @@ sealed class PutTextBaseAction(
} }
result result
} else { } else {
val putData = getPutDataForCaret(sortedCarets.single(), count) injector.put.putText(editor, context, getPutData(count), operatorArguments)
injector.put.putText(editor, context, putData, operatorArguments)
} }
} }
private fun getPutDataForCaret(caret: ImmutableVimCaret, count: Int): PutData { private fun getPutData(count: Int): PutData {
val registerService = injector.registerGroup return PutData(getRegisterTextData(), null, count, insertTextBeforeCaret, indent, caretAfterInsertedText, -1)
val registerChar = if (caret.editor.carets().size == 1) { }
registerService.currentRegister }
} else {
registerService.getCurrentRegisterForMulticaret() fun getRegisterTextData(): TextData? {
} val register = injector.registerGroup.getRegister(injector.registerGroup.currentRegister)
val register = caret.registerStorage.getRegister(registerChar) return register?.let {
val textData = register?.let { TextData(
TextData( register.text ?: injector.parser.toPrintableString(register.keys),
register.text ?: injector.parser.toPrintableString(register.keys), register.type,
register.type, register.transferableData,
register.transferableData, register.name,
register.name, )
)
}
return PutData(textData, null, count, insertTextBeforeCaret, indent, caretAfterInsertedText, -1)
} }
} }

View File

@ -41,7 +41,21 @@ sealed class PutVisualTextBaseAction(
): Boolean { ): Boolean {
if (caretsAndSelections.isEmpty()) return false if (caretsAndSelections.isEmpty()) return false
val count = cmd.count 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() injector.registerGroup.resetRegister()
var result = true var result = true
injector.application.runWriteAction { injector.application.runWriteAction {
@ -51,18 +65,8 @@ sealed class PutVisualTextBaseAction(
} }
return result return result
} }
private fun getPutDataForCaret(caret: VimCaret, selection: VimSelection?, count: Int): PutData { private fun getPutDataForCaret(textData: PutData.TextData?, 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,
)
}
val visualSelection = selection?.let { PutData.VisualSelection(mapOf(caret to it), it.type) } val visualSelection = selection?.let { PutData.VisualSelection(mapOf(caret to it), it.type) }
return PutData(textData, visualSelection, count, insertTextBeforeCaret, indent, caretAfterInsertedText) 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.* import java.util.*
@CommandOrMotion(keys = [":"], modes = [Mode.NORMAL, Mode.VISUAL, Mode.OP_PENDING]) @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 flags: EnumSet<CommandFlags> = enumSetOf(CommandFlags.FLAG_START_EX)
override val type: Command.Type = Command.Type.OTHER_READONLY 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.intellij.vim.annotations.Mode
import com.maddyhome.idea.vim.api.ExecutionContext import com.maddyhome.idea.vim.api.ExecutionContext
import com.maddyhome.idea.vim.api.VimEditor 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.Command
import com.maddyhome.idea.vim.command.CommandFlags import com.maddyhome.idea.vim.command.CommandFlags
import com.maddyhome.idea.vim.command.OperatorArguments import com.maddyhome.idea.vim.command.OperatorArguments
import com.maddyhome.idea.vim.handler.VimActionHandler import com.maddyhome.idea.vim.handler.VimActionHandler
import com.maddyhome.idea.vim.helper.enumSetOf import com.maddyhome.idea.vim.helper.enumSetOf
import com.maddyhome.idea.vim.history.VimHistory
import java.util.* import java.util.*
@CommandOrMotion(keys = ["<Esc>", "<C-[>", "<C-C>"], modes = [Mode.CMD_LINE]) @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 val type: Command.Type = Command.Type.OTHER_READONLY
override fun execute(editor: VimEditor, context: ExecutionContext, cmd: Command, operatorArguments: OperatorArguments): Boolean { 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 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