1
0
mirror of https://github.com/chylex/IntelliJ-IdeaVim.git synced 2025-08-18 10:31:44 +02:00

Compare commits

..

112 Commits

Author SHA1 Message Date
822dad52f3 Set plugin version to chylex-41 2024-09-05 07:40:10 +02:00
bf12c98880 Exit insert mode after refactoring 2024-09-05 07:40:10 +02:00
c02bd15e4f Add action to run last macro in all opened files 2024-09-05 07:27:53 +02:00
5957d5d681 Stop macro execution after a failed search 2024-09-05 07:27:53 +02:00
9445afb555 Revert per-caret registers 2024-09-05 07:27:53 +02:00
6e115bdf64 Revert "Factor disposable objects on editor opening"
This reverts commit 1fa78935
2024-09-05 07:27:53 +02:00
6305c412b5 Fix(VIM-3364): Exception with mapped Generate action 2024-09-05 07:27:53 +02:00
be2eabe3b9 Apply scrolloff after executing native IDEA actions 2024-09-05 07:27:53 +02:00
de13e4348a Stay on same line after reindenting 2024-09-05 07:12:09 +02:00
1c154fdc8a Update search register when using f/t 2024-09-05 07:12:09 +02:00
9b75931736 Automatically add unambiguous imports after running a macro 2024-09-05 07:12:09 +02:00
3fe97aa767 Fix(VIM-3179): Respect virtual space below editor (imperfectly) 2024-09-05 07:12:09 +02:00
8eb2dbebcf Fix(VIM-3178): Workaround to support "Jump to Source" action mapping 2024-09-05 07:12:09 +02:00
cb781f9a0d Add support for count for visual and line motion surround 2024-09-05 07:12:09 +02:00
6693755823 Fix vim-surround not working with multiple cursors
Fixes multiple cursors with vim-surround commands `cs, ds, S` (but not `ys`).
2024-09-05 07:12:09 +02:00
9a9bd335d3 Fix(VIM-696) Restore visual mode after undo/redo, and disable incompatible actions 2024-09-05 07:12:09 +02:00
91e22482c6 Respect count with <Action> mappings 2024-09-05 07:08:52 +02:00
06dc2ed75c Change matchit plugin to use HTML patterns in unrecognized files 2024-09-05 07:02:47 +02:00
12da1ac969 Reset insert mode when switching active editor 2024-09-05 07:02:47 +02:00
5747ac0ebf Disable switching to insert mode for some editors 2024-09-05 07:02:44 +02:00
8a47bc1840 Remove update checker 2024-09-05 07:02:36 +02:00
da4deaf698 Set custom plugin version 2024-09-05 07:02:36 +02:00
IdeaVim Bot
4c09ab4766 Add Felix Wiemuth to contributors list 2024-08-31 09:01:59 +00:00
Alex Plate
ee447bce07 Add a note to replace the raw string after the changes will be available
https://github.com/JetBrains/intellij-community/pull/2825
2024-08-30 18:57:00 +03:00
Alex Plate
5fb4c10f88 Add 2024.2 IJ for testing on TC 2024-08-30 18:42:02 +03:00
Alex Plate
ed2fcb08b0 [VIM-3620] Add a link to the usage survey 2024-08-30 18:34:10 +03:00
dedd90ce13 Fix(VIM-3615): Escape closes dialog while waiting for more keys 2024-08-30 16:46:53 +03:00
Alex Plate
73326e623e Use the behavior form in docs 2024-08-30 16:42:03 +03:00
Alex Plate
a2bc34d6ec [VIM-3620] Show the uninstall survey only when uninstalling IdeaVim 2024-08-30 16:41:36 +03:00
Felix Wiemuth
b652c7726a Fix typo 2024-08-30 16:41:05 +03:00
Matt Ellis
fb7a2de07b Encapsulate the command builder's state flag
This also gets rid of BAD_COMMAND, which was set but never checked - the function that set the flag would immediately reset the command builder
2024-08-30 16:36:24 +03:00
Matt Ellis
def9ca479b Ensure builder resets to a root command trie node
Also refactors command nodes a bit for better debug/trace output
2024-08-30 16:36:24 +03:00
Matt Ellis
0936e0761f Reorder CommandBuilder methods
Try to keep related functions together: awaiting arguments, count, registers, adding action/argument, processing keystrokes, build, reset.
2024-08-30 16:36:24 +03:00
Matt Ellis
09a335bcfe Start to encapsulate setting command builder state
Also rename `pushCommandPart` and `completeCommandPart`
2024-08-30 16:36:24 +03:00
Matt Ellis
37b8d69bac Remove unused EMPTY_COMMAND 2024-08-30 16:36:24 +03:00
Matt Ellis
13308050a8 Remove unnecessary OperatorArguments parameters 2024-08-30 16:36:24 +03:00
Matt Ellis
a1a553ebc9 Deprecate OperatorArguments.mode 2024-08-30 16:36:24 +03:00
Matt Ellis
5bb0c4f7cb Use editor.mode instead of OperatorArguments.mode
`OperatorArguments.mode` is the mode *before* the command was completed, rather than the current mode, which is non-obvious. E.g. for a command in Insert mode, it will still be Insert, and for a (simple) command in Normal, it will still be Normal. The only difference is that a command such as `dw` would be in Operator-pending before the command is completed. That logic is not required for this method, so it's safe to use the current mode.

This allows us to start to deprecate `OperatorArguments.mode`.
2024-08-30 16:36:24 +03:00
Matt Ellis
da6736f24a Simplify the logic when yanking during delete 2024-08-30 16:36:24 +03:00
Matt Ellis
4df1ce2ae8 Remove OperatorArguments.mode usage in block insert
`OperatorArguments.mode` is the mode *before* the command is completed, so might be Visual, Operator-pending, Insert, etc. It's not immediately obvious this is the case, so we're going to deprecate `OperatorArguments.mode` to avoid confusion with `editor.mode`.

It's not required for this method because it's only called for Visual-block mode.
2024-08-30 16:36:24 +03:00
Matt Ellis
00fd4cd491 Handle op-pending for space and backspace 2024-08-30 16:36:24 +03:00
Matt Ellis
d185672e2f Deprecate OperatorArguments.isOperatorPending
Register specific handlers for Operator-pending mode instead of relying on a runtime flag for behaviour. Also refactors and renames some arrow motion handlers.
2024-08-30 16:36:24 +03:00
Matt Ellis
55fef03a4a Add 'whichwrap' to dictionary 2024-08-30 16:36:24 +03:00
Matt Ellis
69b3e4f782 Start to refactor OperatorArguments 2024-08-30 16:36:24 +03:00
Matt Ellis
6be29b0378 Remove KeyHandler.isOperatorPending
It's easier to just look at mode. We don't need the additional check on command builder, because we can't be in OP_PENDING without pushing an operator action to the command builder
2024-08-30 16:36:24 +03:00
Matt Ellis
9965c863a6 Encapsulate command node state in builder 2024-08-30 16:36:24 +03:00
Matt Ellis
3f11ae512c Move register pending state to command builder 2024-08-30 16:36:24 +03:00
Matt Ellis
1c842eb3d8 Avoid exposing misleading count on command builder 2024-08-30 16:36:24 +03:00
Matt Ellis
c7fbce675b Update comment 2024-08-30 16:36:24 +03:00
Matt Ellis
d7e68488c8 Make Command.rawCount immutable 2024-08-30 16:36:24 +03:00
Matt Ellis
69d13a74e6 Remove unnecessary copy method 2024-08-30 16:36:24 +03:00
Matt Ellis
5a83df34a7 Replace var properties with read only 2024-08-30 16:36:24 +03:00
Matt Ellis
0a18c388e0 Simplify CommandBuilder
Fixes selecting last register if multiple registers are used in a command
2024-08-30 16:36:24 +03:00
Matt Ellis
1a3409e7df Remove count from motion argument
Only Command has a count. The motion argument is now a sealed class hierarchy, and consists only of the motion action and optional argument. This is to reduce confusion over which count to use, and potential incorrect calculation of the count
2024-08-30 16:36:24 +03:00
Matt Ellis
e93db961a0 Wrap offsets argument as an external action 2024-08-30 16:36:24 +03:00
Matt Ellis
8fd76bd08f Refactor properties for sealed Argument classes 2024-08-30 16:36:24 +03:00
Matt Ellis
0eea4a5b2c Introduce sealed classes to represent an argument 2024-08-30 16:36:24 +03:00
Matt Ellis
18a0c533e2 Remove unused OperatedRange type 2024-08-30 16:36:24 +03:00
Matt Ellis
0bd8d8f4d2 Remove unused digraph command flag 2024-08-30 16:36:24 +03:00
Alex Plate
64a89c8863 [VIM-3620] Add the uninstall survey
We're actively working on understanding the users and what we can improve in the plugin
2024-08-28 18:57:29 +03:00
Filipp Vakhitov
5b17d7740e Update generated files after merging PRs 2024-08-25 21:51:14 +03: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
191 changed files with 4963 additions and 2496 deletions

3
.gitignore vendored
View File

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

View File

@@ -27,6 +27,7 @@ object Project : Project({
// Active tests
buildType(TestingBuildType("Latest EAP", "<default>", version = "LATEST-EAP-SNAPSHOT"))
buildType(TestingBuildType("2024.1.1", "<default>"))
buildType(TestingBuildType("2024.2", "<default>"))
buildType(TestingBuildType("Latest EAP With Xorg", "<default>", version = "LATEST-EAP-SNAPSHOT"))
buildType(PropertyBased)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -8,7 +8,7 @@ Every effort is made to make these options compatible with Vim behaviour.
However, some differences are inevitable.
```
'clipboard' 'cb' Defines clipboard behavioue
'clipboard' 'cb' Defines clipboard behavior
A comma-separated list of words to control clipboard behaviour:
unnamed The clipboard register '*' is used instead of the
unnamed register

View File

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

View File

@@ -20,7 +20,7 @@ ideaVersion=2024.2
# Values for type: https://plugins.jetbrains.com/docs/intellij/tools-gradle-intellij-plugin.html#intellij-extension-type
ideaType=IC
instrumentPluginCode=true
version=chylex-39
version=chylex-41
javaVersion=17
remoteRobotVersion=0.11.23
antlrVersion=4.10.1

View File

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

View File

@@ -8,6 +8,10 @@
package com.maddyhome.idea.vim
import com.intellij.ide.BrowserUtil
import com.intellij.ide.plugins.IdeaPluginDescriptor
import com.intellij.ide.plugins.PluginStateListener
import com.intellij.ide.plugins.PluginStateManager
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.fileEditor.ex.FileEditorManagerEx
import com.intellij.openapi.project.Project
@@ -40,6 +44,18 @@ internal class PluginStartup : ProjectActivity/*, LightEditCompatible*/ {
// This code should be executed once
VimPlugin.getInstance().initialize()
// Uninstall survey. Should be registered once for all projects
PluginStateManager.addStateListener(object : PluginStateListener {
override fun install(p0: IdeaPluginDescriptor) {/*Nothing*/
}
override fun uninstall(descriptor: IdeaPluginDescriptor) {
if (descriptor.pluginId == VimPlugin.getPluginId()) {
BrowserUtil.open("https://surveys.jetbrains.com/s3/ideavim-uninstall-feedback")
}
}
})
}
}

View File

@@ -37,7 +37,7 @@ import com.maddyhome.idea.vim.vimscript.model.expressions.FunctionCallExpression
import com.maddyhome.idea.vim.vimscript.model.expressions.SimpleExpression
// todo make it multicaret
private fun doOperatorAction(editor: VimEditor, context: ExecutionContext, textRange: TextRange, selectionType: SelectionType): Boolean {
private fun doOperatorAction(editor: VimEditor, context: ExecutionContext, textRange: TextRange, motionType: SelectionType): Boolean {
val func = injector.globalOptions().operatorfunc
if (func.isEmpty()) {
VimPlugin.showMessage(MessageHelper.message("E774"))
@@ -57,9 +57,9 @@ private fun doOperatorAction(editor: VimEditor, context: ExecutionContext, textR
if (value is VimFuncref) {
handler = value.handler
}
} catch (ex: ExException) {
} catch (_: ExException) {
// Get the argument for function('...') or funcref('...') for the error message
val functionName = if (expression is FunctionCallExpression && expression.arguments.size > 0) {
val functionName = if (expression is FunctionCallExpression && expression.arguments.isNotEmpty()) {
expression.arguments[0].evaluate(editor, context, scriptContext).toString()
}
else {
@@ -77,7 +77,7 @@ private fun doOperatorAction(editor: VimEditor, context: ExecutionContext, textR
return false
}
val arg = when (selectionType) {
val arg = when (motionType) {
SelectionType.LINE_WISE -> "line"
SelectionType.CHARACTER_WISE -> "char"
SelectionType.BLOCK_WISE -> "block"
@@ -101,19 +101,13 @@ internal class OperatorAction : VimActionHandler.SingleExecution() {
override val argumentType: Argument.Type = Argument.Type.MOTION
override fun execute(editor: VimEditor, context: ExecutionContext, cmd: Command, operatorArguments: OperatorArguments): Boolean {
val argument = cmd.argument ?: return false
val argument = cmd.argument as? Argument.Motion ?: return false
if (!editor.inRepeatMode) {
argumentCaptured = argument
}
val range = getMotionRange(editor, context, argument, operatorArguments)
if (range != null) {
val selectionType = if (argument.motion.isLinewiseMotion()) {
SelectionType.LINE_WISE
} else {
SelectionType.CHARACTER_WISE
}
return doOperatorAction(editor, context, range, selectionType)
return doOperatorAction(editor, context, range, argument.getMotionType())
}
return false
}
@@ -121,7 +115,7 @@ internal class OperatorAction : VimActionHandler.SingleExecution() {
private fun getMotionRange(
editor: VimEditor,
context: ExecutionContext,
argument: Argument,
argument: Argument.Motion,
operatorArguments: OperatorArguments,
): TextRange? {
// Note that we're using getMotionRange2 in order to avoid normalising the linewise range into line start
@@ -136,7 +130,7 @@ internal class OperatorAction : VimActionHandler.SingleExecution() {
operatorArguments,
)?.normalize()?.let {
// If we're linewise, make sure the end offset isn't just the EOL char
if (argument.motion.isLinewiseMotion() && it.endOffset < editor.fileSize()) {
if (argument.getMotionType() == SelectionType.LINE_WISE && it.endOffset < editor.fileSize()) {
TextRange(it.startOffset, it.endOffset + 1)
} else {
it

View File

@@ -25,7 +25,7 @@ internal class RepeatChangeAction : VimActionHandler.SingleExecution() {
override fun execute(editor: VimEditor, context: ExecutionContext, cmd: Command, operatorArguments: OperatorArguments): Boolean {
val state = injector.vimState
val lastCommand = VimRepeater.lastChangeCommand
var lastCommand = VimRepeater.lastChangeCommand
if (lastCommand == null && Extension.lastExtensionHandler == null) return false
@@ -57,12 +57,7 @@ internal class RepeatChangeAction : VimActionHandler.SingleExecution() {
)
} else if (!repeatHandler && lastCommand != null) {
if (cmd.rawCount > 0) {
lastCommand.rawCount = cmd.count
val arg = lastCommand.argument
if (arg != null) {
val mot = arg.motion
mot.rawCount = 0
}
lastCommand = lastCommand.copy(rawCount = cmd.rawCount)
}
state.executingCommand = lastCommand

View File

@@ -40,7 +40,7 @@ class DeleteJoinLinesAction : ChangeEditorActionHandler.ConditionalSingleExecuti
): Boolean {
injector.editorGroup.notifyIdeaJoin(editor)
return injector.changeGroup.deleteJoinLines(editor, caret, operatorArguments.count1, false, operatorArguments)
return injector.changeGroup.deleteJoinLines(editor, caret, operatorArguments.count1, false)
}
override fun execute(

View File

@@ -35,7 +35,7 @@ class DeleteJoinLinesSpacesAction : ChangeEditorActionHandler.SingleExecution()
injector.editorGroup.notifyIdeaJoin(editor)
var res = true
editor.nativeCarets().sortedByDescending { it.offset }.forEach { caret ->
if (!injector.changeGroup.deleteJoinLines(editor, caret, operatorArguments.count1, true, operatorArguments)) {
if (!injector.changeGroup.deleteJoinLines(editor, caret, operatorArguments.count1, true)) {
res = false
}
}

View File

@@ -22,11 +22,6 @@ import com.maddyhome.idea.vim.handler.VimActionHandler
import com.maddyhome.idea.vim.helper.enumSetOf
import java.util.*
@CommandOrMotion(keys = ["<C-H>", "<BS>"], modes = [Mode.INSERT])
internal class VimEditorBackSpace : IdeActionHandler(IdeActions.ACTION_EDITOR_BACKSPACE) {
override val type: Command.Type = Command.Type.DELETE
}
@CommandOrMotion(keys = ["<Del>"], modes = [Mode.INSERT])
internal class VimEditorDelete : IdeActionHandler(IdeActions.ACTION_EDITOR_DELETE) {
override val type: Command.Type = Command.Type.DELETE

View File

@@ -33,7 +33,6 @@ import org.jetbrains.annotations.Nullable;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.EnumSet;
import static com.maddyhome.idea.vim.extension.VimExtensionFacade.putExtensionHandlerMapping;
import static com.maddyhome.idea.vim.extension.VimExtensionFacade.putKeyMappingIfMissing;
@@ -64,8 +63,8 @@ public class VimArgTextObjExtension implements VimExtension {
*/
private static class BracketPairs {
// NOTE: brackets must match by the position, and ordered by rank (highest to lowest).
@NotNull private final String openBrackets;
@NotNull private final String closeBrackets;
private final @NotNull String openBrackets;
private final @NotNull String closeBrackets;
static class ParseException extends Exception {
public ParseException(@NotNull String message) {
@@ -87,8 +86,7 @@ public class VimArgTextObjExtension implements VimExtension {
* @param bracketPairs comma-separated list of colon-separated bracket pairs.
* @throws ParseException if a syntax error is detected.
*/
@NotNull
static BracketPairs fromBracketPairList(@NotNull final String bracketPairs) throws ParseException {
static @NotNull BracketPairs fromBracketPairList(final @NotNull String bracketPairs) throws ParseException {
StringBuilder openBrackets = new StringBuilder();
StringBuilder closeBrackets = new StringBuilder();
ParseState state = ParseState.OPEN;
@@ -128,7 +126,7 @@ public class VimArgTextObjExtension implements VimExtension {
return new BracketPairs(openBrackets.toString(), closeBrackets.toString());
}
BracketPairs(@NotNull final String openBrackets, @NotNull final String closeBrackets) {
BracketPairs(final @NotNull String openBrackets, final @NotNull String closeBrackets) {
assert openBrackets.length() == closeBrackets.length();
this.openBrackets = openBrackets;
this.closeBrackets = closeBrackets;
@@ -158,10 +156,9 @@ public class VimArgTextObjExtension implements VimExtension {
}
}
public static final BracketPairs DEFAULT_BRACKET_PAIRS = new BracketPairs("(", ")");
private static final BracketPairs DEFAULT_BRACKET_PAIRS = new BracketPairs("(", ")");
@Nullable
private static String bracketPairsVariable() {
private static @Nullable String bracketPairsVariable() {
final Object value = VimPlugin.getVariableService().getGlobalVariableValue("argtextobj_pairs");
if (value instanceof VimString vimValue) {
return vimValue.getValue();
@@ -192,13 +189,12 @@ public class VimArgTextObjExtension implements VimExtension {
this.isInner = isInner;
}
@Nullable
@Override
public TextRange getRange(@NotNull VimEditor editor,
@NotNull ImmutableVimCaret caret,
@NotNull ExecutionContext context,
int count,
int rawCount) {
public @Nullable TextRange getRange(@NotNull VimEditor editor,
@NotNull ImmutableVimCaret caret,
@NotNull ExecutionContext context,
int count,
int rawCount) {
BracketPairs bracketPairs = DEFAULT_BRACKET_PAIRS;
final String bracketPairsVar = bracketPairsVariable();
if (bracketPairsVar != null) {
@@ -236,24 +232,22 @@ public class VimArgTextObjExtension implements VimExtension {
return new TextRange(finder.getLeftBound(), finder.getRightBound());
}
@NotNull
@Override
public TextObjectVisualType getVisualType() {
public @NotNull TextObjectVisualType getVisualType() {
return TextObjectVisualType.CHARACTER_WISE;
}
}
@Override
public void execute(@NotNull VimEditor editor, @NotNull ExecutionContext context, @NotNull OperatorArguments operatorArguments) {
@NotNull KeyHandler keyHandler = KeyHandler.getInstance();
@NotNull KeyHandlerState keyHandlerState = KeyHandler.getInstance().getKeyHandlerState();
int count = Math.max(1, keyHandlerState.getCommandBuilder().getCount());
final ArgumentTextObjectHandler textObjectHandler = new ArgumentTextObjectHandler(isInner);
//noinspection DuplicatedCode
if (!keyHandler.isOperatorPending(editor.getMode(), keyHandlerState)) {
if (!(editor.getMode() instanceof Mode.OP_PENDING)) {
int count0 = operatorArguments.getCount0();
editor.nativeCarets().forEach((VimCaret caret) -> {
final TextRange range = textObjectHandler.getRange(editor, caret, context, count, 0);
final TextRange range = textObjectHandler.getRange(editor, caret, context, Math.max(1, count0), count0);
if (range != null) {
try (VimListenerSuppressor.Locked ignored = SelectionVimListenerSuppressor.INSTANCE.lock()) {
if (editor.getMode() instanceof Mode.VISUAL) {
@@ -265,8 +259,7 @@ public class VimArgTextObjExtension implements VimExtension {
}
});
} else {
keyHandlerState.getCommandBuilder().completeCommandPart(new Argument(new Command(count,
textObjectHandler, Command.Type.MOTION, EnumSet.noneOf(CommandFlags.class))));
keyHandlerState.getCommandBuilder().addAction(textObjectHandler);
}
}
}
@@ -276,9 +269,9 @@ public class VimArgTextObjExtension implements VimExtension {
* position
*/
private static class ArgBoundsFinder {
@NotNull private final CharSequence text;
@NotNull private final Document document;
@NotNull private final BracketPairs brackets;
private final @NotNull CharSequence text;
private final @NotNull Document document;
private final @NotNull BracketPairs brackets;
private int leftBound = Integer.MAX_VALUE;
private int rightBound = Integer.MIN_VALUE;
private int leftBracket;
@@ -305,7 +298,7 @@ public class VimArgTextObjExtension implements VimExtension {
* @param position starting position.
*/
boolean findBoundsAt(int position) throws IllegalStateException {
if (text.length() == 0) {
if (text.isEmpty()) {
error = "empty document";
return false;
}

View File

@@ -25,9 +25,6 @@ import com.maddyhome.idea.vim.api.VimEditor
import com.maddyhome.idea.vim.api.getLineEndOffset
import com.maddyhome.idea.vim.api.globalOptions
import com.maddyhome.idea.vim.api.injector
import com.maddyhome.idea.vim.command.Argument
import com.maddyhome.idea.vim.command.Command
import com.maddyhome.idea.vim.command.CommandFlags
import com.maddyhome.idea.vim.command.MappingMode
import com.maddyhome.idea.vim.command.OperatorArguments
import com.maddyhome.idea.vim.command.TextObjectVisualType
@@ -52,7 +49,6 @@ import com.maddyhome.idea.vim.newapi.ij
import com.maddyhome.idea.vim.newapi.vim
import com.maddyhome.idea.vim.state.mode.Mode
import com.maddyhome.idea.vim.state.mode.SelectionType
import java.util.*
internal class CommentaryExtension : VimExtension {
@@ -184,10 +180,8 @@ internal class CommentaryExtension : VimExtension {
override val isRepeatable = true
override fun execute(editor: VimEditor, context: ExecutionContext, operatorArguments: OperatorArguments) {
val command = Command(operatorArguments.count1, CommentaryTextObjectMotionHandler, Command.Type.MOTION, EnumSet.noneOf(CommandFlags::class.java))
val keyState = KeyHandler.getInstance().keyHandlerState
keyState.commandBuilder.completeCommandPart(Argument(command))
keyState.commandBuilder.addAction(CommentaryTextObjectMotionHandler)
}
}

View File

@@ -44,6 +44,7 @@ import com.maddyhome.idea.vim.helper.enumSetOf
import com.maddyhome.idea.vim.newapi.IjVimEditor
import com.maddyhome.idea.vim.newapi.ij
import com.maddyhome.idea.vim.newapi.vim
import com.maddyhome.idea.vim.state.mode.Mode
import java.util.*
import java.util.regex.Pattern
@@ -93,34 +94,29 @@ internal class Matchit : VimExtension {
override fun execute(editor: VimEditor, context: ExecutionContext, operatorArguments: OperatorArguments) {
val keyHandler = KeyHandler.getInstance()
val keyState = keyHandler.keyHandlerState
val count = keyState.commandBuilder.count
// Reset the command count so it doesn't transfer onto subsequent commands.
keyState.commandBuilder.resetCount()
// Normally we want to jump to the start of the matching pair. But when moving forward in operator
// pending mode, we want to include the entire match. isInOpPending makes that distinction.
val isInOpPending = keyHandler.isOperatorPending(editor.mode, keyState)
if (isInOpPending) {
if (editor.mode is Mode.OP_PENDING) {
val matchitAction = MatchitAction()
matchitAction.reverse = reverse
matchitAction.isInOpPending = true
keyState.commandBuilder.completeCommandPart(
Argument(
Command(
count,
matchitAction,
Command.Type.MOTION,
EnumSet.noneOf(CommandFlags::class.java),
),
),
)
keyState.commandBuilder.addAction(matchitAction)
} else {
editor.sortedCarets().forEach { caret ->
injector.jumpService.saveJumpLocation(editor)
caret.moveToOffset(getMatchitOffset(editor.ij, caret.ij, count, isInOpPending, reverse))
caret.moveToOffset(
getMatchitOffset(
editor.ij,
caret.ij,
operatorArguments.count0,
isInOpPending = false,
reverse
))
}
}
}
@@ -354,7 +350,7 @@ private object FileTypePatterns {
private val DEFAULT_PAIRS = setOf('(', ')', '[', ']', '{', '}')
private fun getMatchitOffset(editor: Editor, caret: Caret, count: Int, isInOpPending: Boolean, reverse: Boolean): Int {
private fun getMatchitOffset(editor: Editor, caret: Caret, count0: Int, isInOpPending: Boolean, reverse: Boolean): Int {
val virtualFile = EditorHelper.getVirtualFile(editor)
var caretOffset = caret.offset
@@ -367,9 +363,9 @@ private fun getMatchitOffset(editor: Editor, caret: Caret, count: Int, isInOpPen
val currentChar = editor.document.charsSequence[caretOffset]
var motionOffset: Int? = null
if (count > 0) {
if (count0 > 0) {
// Matchit doesn't affect the percent motion, so we fall back to the default behavior.
motionOffset = VimPlugin.getMotion().moveCaretToLinePercent(editor.vim, caret.vim, count)
motionOffset = VimPlugin.getMotion().moveCaretToLinePercent(editor.vim, caret.vim, count0)
} else {
// Check the simplest case first.
if (DEFAULT_PAIRS.contains(currentChar)) {
@@ -400,8 +396,7 @@ private fun getMatchitOffset(editor: Editor, caret: Caret, count: Int, isInOpPen
private fun getMotionOffset(motion: Motion): Int? {
return when (motion) {
is Motion.AbsoluteOffset -> motion.offset
is Motion.AdjustedOffset -> motion.offset
is Motion.AdjustedOffset, is Motion.AbsoluteOffset -> motion.offset
is Motion.Error, is Motion.NoMotion -> null
}
}

View File

@@ -555,12 +555,13 @@ private fun registerCommand(default: String, action: NerdAction) {
}
private val actionsRoot: RootNode<NerdAction> = RootNode()
private val actionsRoot: RootNode<NerdAction> = RootNode("NERDTree")
private var currentNode: CommandPartNode<NerdAction> = actionsRoot
private fun collectShortcuts(node: Node<NerdAction>): Set<KeyStroke> {
return if (node is CommandPartNode<NerdAction>) {
val res = node.keys.toMutableSet()
res += node.values.map { collectShortcuts(it) }.flatten()
val res = node.children.keys.toMutableSet()
res += node.children.values.map { collectShortcuts(it) }.flatten()
res
} else {
emptySet()

View File

@@ -10,7 +10,6 @@ package com.maddyhome.idea.vim.extension.replacewithregister
import com.intellij.openapi.actionSystem.DataContext
import com.intellij.openapi.editor.Editor
import com.maddyhome.idea.vim.KeyHandler
import com.maddyhome.idea.vim.VimPlugin
import com.maddyhome.idea.vim.api.ExecutionContext
import com.maddyhome.idea.vim.api.ImmutableVimCaret
@@ -166,17 +165,11 @@ private fun doReplace(editor: Editor, context: DataContext, caret: ImmutableVimC
putToLine = -1,
)
val vimEditor = editor.vim
val keyHandler = KeyHandler.getInstance()
ClipboardOptionHelper.IdeaputDisabler().use {
VimPlugin.getPut().putText(
vimEditor,
context.vim,
putData,
operatorArguments = OperatorArguments(
keyHandler.isOperatorPending(vimEditor.mode, keyHandler.keyHandlerState),
0,
editor.vim.mode,
),
saveToRegister = false
)
}

View File

@@ -29,14 +29,12 @@ import com.maddyhome.idea.vim.state.mode.Mode;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.EnumSet;
import static com.maddyhome.idea.vim.extension.VimExtensionFacade.putExtensionHandlerMapping;
import static com.maddyhome.idea.vim.extension.VimExtensionFacade.putKeyMappingIfMissing;
/**
* Port of vim-entire:
* https://github.com/kana/vim-textobj-entire
* <a href="https://github.com/kana/vim-textobj-entire">vim-textobj-entire</a>
*
* <p>
* vim-textobj-entire provides two text objects:
@@ -51,7 +49,7 @@ import static com.maddyhome.idea.vim.extension.VimExtensionFacade.putKeyMappingI
* </ul>
*
* See also the reference manual for more details at:
* https://github.com/kana/vim-textobj-entire/blob/master/doc/textobj-entire.txt
* <a href="https://github.com/kana/vim-textobj-entire/blob/master/doc/textobj-entire.txt">text-obj-entire.txt</a>
*
* @author Alexandre Grison (@agrison)
*/
@@ -94,13 +92,12 @@ public class VimTextObjEntireExtension implements VimExtension {
this.ignoreLeadingAndTrailing = ignoreLeadingAndTrailing;
}
@Nullable
@Override
public TextRange getRange(@NotNull VimEditor editor,
@NotNull ImmutableVimCaret caret,
@NotNull ExecutionContext context,
int count,
int rawCount) {
public @Nullable TextRange getRange(@NotNull VimEditor editor,
@NotNull ImmutableVimCaret caret,
@NotNull ExecutionContext context,
int count,
int rawCount) {
int start = 0, end = ((IjVimEditor)editor).getEditor().getDocument().getTextLength();
// for the `ie` text object we don't want leading an trailing spaces
@@ -125,24 +122,22 @@ public class VimTextObjEntireExtension implements VimExtension {
return new TextRange(start, end);
}
@NotNull
@Override
public TextObjectVisualType getVisualType() {
public @NotNull TextObjectVisualType getVisualType() {
return TextObjectVisualType.CHARACTER_WISE;
}
}
@Override
public void execute(@NotNull VimEditor editor, @NotNull ExecutionContext context, @NotNull OperatorArguments operatorArguments) {
@NotNull KeyHandler keyHandler = KeyHandler.getInstance();
@NotNull KeyHandlerState keyHandlerState = KeyHandler.getInstance().getKeyHandlerState();
int count = Math.max(1, keyHandlerState.getCommandBuilder().getCount());
final EntireTextObjectHandler textObjectHandler = new EntireTextObjectHandler(ignoreLeadingAndTrailing);
//noinspection DuplicatedCode
if (!keyHandler.isOperatorPending(editor.getMode(), keyHandlerState)) {
if (!(editor.getMode() instanceof Mode.OP_PENDING)) {
int count0 = operatorArguments.getCount0();
((IjVimEditor) editor).getEditor().getCaretModel().runForEachCaret((Caret caret) -> {
final TextRange range = textObjectHandler.getRange(editor, new IjVimCaret(caret), context, count, 0);
final TextRange range = textObjectHandler.getRange(editor, new IjVimCaret(caret), context, Math.max(1, count0), count0);
if (range != null) {
try (VimListenerSuppressor.Locked ignored = SelectionVimListenerSuppressor.INSTANCE.lock()) {
if (editor.getMode() instanceof Mode.VISUAL) {
@@ -155,9 +150,7 @@ public class VimTextObjEntireExtension implements VimExtension {
});
} else {
keyHandlerState.getCommandBuilder().completeCommandPart(new Argument(new Command(count,
textObjectHandler, Command.Type.MOTION,
EnumSet.noneOf(CommandFlags.class))));
keyHandlerState.getCommandBuilder().addAction(textObjectHandler);
}
}
}

View File

@@ -30,14 +30,12 @@ import com.maddyhome.idea.vim.state.mode.Mode;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.EnumSet;
import static com.maddyhome.idea.vim.extension.VimExtensionFacade.putExtensionHandlerMapping;
import static com.maddyhome.idea.vim.extension.VimExtensionFacade.putKeyMapping;
/**
* Port of vim-indent-object:
* https://github.com/michaeljsmith/vim-indent-object
* <a href="https://github.com/michaeljsmith/vim-indent-object">vim-indent-object</a>
*
* <p>
* vim-indent-object provides these text objects based on the cursor line's indentation:
@@ -49,7 +47,7 @@ import static com.maddyhome.idea.vim.extension.VimExtensionFacade.putKeyMapping;
* </ul>
*
* See also the reference manual for more details at:
* https://github.com/michaeljsmith/vim-indent-object/blob/master/doc/indent-object.txt
* <a href="https://github.com/michaeljsmith/vim-indent-object/blob/master/doc/indent-object.txt">indent-object.txt</a>
*
* @author Shrikant Kandula (@sharat87)
*/
@@ -98,13 +96,12 @@ public class VimIndentObject implements VimExtension {
this.includeBelow = includeBelow;
}
@Nullable
@Override
public TextRange getRange(@NotNull VimEditor editor,
@NotNull ImmutableVimCaret caret,
@NotNull ExecutionContext context,
int count,
int rawCount) {
public @Nullable TextRange getRange(@NotNull VimEditor editor,
@NotNull ImmutableVimCaret caret,
@NotNull ExecutionContext context,
int count,
int rawCount) {
final CharSequence charSequence = ((IjVimEditor)editor).getEditor().getDocument().getCharsSequence();
final int caretOffset = ((IjVimCaret)caret).getCaret().getOffset();
@@ -249,9 +246,8 @@ public class VimIndentObject implements VimExtension {
return new TextRange(upperBoundaryOffset, lowerBoundaryOffset);
}
@NotNull
@Override
public TextObjectVisualType getVisualType() {
public @NotNull TextObjectVisualType getVisualType() {
return TextObjectVisualType.LINE_WISE;
}
@@ -264,15 +260,14 @@ public class VimIndentObject implements VimExtension {
@Override
public void execute(@NotNull VimEditor editor, @NotNull ExecutionContext context, @NotNull OperatorArguments operatorArguments) {
IjVimEditor vimEditor = (IjVimEditor)editor;
@NotNull KeyHandler keyHandler = KeyHandler.getInstance();
@NotNull KeyHandlerState keyHandlerState = KeyHandler.getInstance().getKeyHandlerState();
int count = Math.max(1, keyHandlerState.getCommandBuilder().getCount());
final IndentObjectHandler textObjectHandler = new IndentObjectHandler(includeAbove, includeBelow);
if (!keyHandler.isOperatorPending(editor.getMode(), keyHandlerState)) {
if (!(editor.getMode() instanceof Mode.OP_PENDING)) {
int count0 = operatorArguments.getCount0();
((IjVimEditor)editor).getEditor().getCaretModel().runForEachCaret((Caret caret) -> {
final TextRange range = textObjectHandler.getRange(vimEditor, new IjVimCaret(caret), context, count, 0);
final TextRange range = textObjectHandler.getRange(vimEditor, new IjVimCaret(caret), context, Math.max(1, count0), count0);
if (range != null) {
try (VimListenerSuppressor.Locked ignored = SelectionVimListenerSuppressor.INSTANCE.lock()) {
if (editor.getMode() instanceof Mode.VISUAL) {
@@ -285,9 +280,7 @@ public class VimIndentObject implements VimExtension {
});
} else {
keyHandlerState.getCommandBuilder().completeCommandPart(new Argument(new Command(count,
textObjectHandler, Command.Type.MOTION,
EnumSet.noneOf(CommandFlags.class))));
keyHandlerState.getCommandBuilder().addAction(textObjectHandler);
}
}
}

View File

@@ -103,6 +103,11 @@ class ChangeGroup : VimChangeGroupBase() {
}
}
override fun processBackspace(editor: VimEditor, context: ExecutionContext) {
injector.actionExecutor.executeAction(editor, name = IdeActions.ACTION_EDITOR_BACKSPACE, context = context)
injector.scroll.scrollCaretIntoView(editor)
}
private fun restoreCursor(editor: VimEditor, caret: VimCaret, startLine: Int) {
if (caret != editor.primaryCaret()) {
(editor as IjVimEditor).editor.caretModel.addCaret(

View File

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

View File

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

View File

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

View File

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

View File

@@ -35,7 +35,7 @@ import com.maddyhome.idea.vim.command.Argument
import com.maddyhome.idea.vim.command.MotionType
import com.maddyhome.idea.vim.command.OperatorArguments
import com.maddyhome.idea.vim.common.TextRange
import com.maddyhome.idea.vim.ex.ExOutputModel
import com.maddyhome.idea.vim.handler.ExternalActionHandler
import com.maddyhome.idea.vim.handler.Motion
import com.maddyhome.idea.vim.handler.Motion.AbsoluteOffset
import com.maddyhome.idea.vim.handler.MotionActionHandler
@@ -193,21 +193,16 @@ internal class MotionGroup : VimMotionGroupBase() {
argument: Argument,
operatorArguments: OperatorArguments,
): TextRange? {
if (argument !is Argument.Motion) {
throw RuntimeException("Unexpected argument passed to getMotionRange2: $argument")
}
var start: Int
var end: Int
if (argument.type === Argument.Type.OFFSETS) {
val offsets = argument.offsets[caret.vim] ?: return null
val (first, second) = offsets.getNativeStartAndEnd()
start = first
end = second
} else {
val cmd = argument.motion
// Normalize the counts between the command and the motion argument
val cnt = cmd.count * operatorArguments.count1
val raw = if (operatorArguments.count0 == 0 && cmd.rawCount == 0) 0 else cnt
if (cmd.action is MotionActionHandler) {
val action = cmd.action as MotionActionHandler
val action = argument.motion
when (action) {
is MotionActionHandler -> {
// This is where we are now
start = caret.offset
@@ -216,8 +211,8 @@ internal class MotionGroup : VimMotionGroupBase() {
editor.vim,
caret.vim,
IjEditorExecutionContext(context!!),
cmd.argument,
operatorArguments.withCount0(raw),
argument.argument,
operatorArguments
)
// Invalid motion
@@ -233,22 +228,32 @@ internal class MotionGroup : VimMotionGroupBase() {
end++
}
}
} else if (cmd.action is TextObjectActionHandler) {
val action = cmd.action as TextObjectActionHandler
val range =
action.getRange(editor.vim, caret.vim, IjEditorExecutionContext(context!!), cnt, raw) ?: return null
}
is TextObjectActionHandler -> {
val range = action.getRange(
editor.vim,
caret.vim,
IjEditorExecutionContext(context!!),
operatorArguments.count1,
operatorArguments.count0
) ?: return null
start = range.startOffset
end = range.endOffset
if (cmd.isLinewiseMotion()) end--
} else {
throw RuntimeException(
"Commands doesn't take " + cmd.action.javaClass.simpleName + " as an operator",
)
if (argument.isLinewiseMotion()) end--
}
is ExternalActionHandler -> {
val range = action.getRange(caret.vim) ?: return null
start = range.startOffset
end = range.endOffset
}
else -> throw RuntimeException("Commands doesn't take " + action.javaClass.simpleName + " as an operator")
}
// This is a kludge for dw, dW, and d[w. Without this kludge, an extra newline is operated when it shouldn't be.
val id = argument.motion.action.id
val id = argument.motion.id
if (id == VimChangeGroupBase.VIM_MOTION_WORD_RIGHT || id == VimChangeGroupBase.VIM_MOTION_BIG_WORD_RIGHT || id == VimChangeGroupBase.VIM_MOTION_CAMEL_RIGHT) {
val text = editor.document.charsSequence.subSequence(start, end).toString()
val lastNewLine = text.lastIndexOf('\n')
@@ -258,6 +263,7 @@ internal class MotionGroup : VimMotionGroupBase() {
}
}
}
return TextRange(start, end)
}
@@ -317,7 +323,7 @@ internal class MotionGroup : VimMotionGroupBase() {
is Mode.CMD_LINE -> {
val commandLine = injector.commandLine.getActiveCommandLine() ?: return
commandLine.close(refocusOwningEditor = false, resetCaret = false)
ExOutputModel.tryGetInstance(editor)?.close()
injector.outputPanel.getCurrentOutputPanel()?.close()
}
else -> {}
}

View File

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

View File

@@ -61,6 +61,9 @@ internal class IjActionExecutor : VimActionExecutor {
get() = IdeActions.ACTION_EXPAND_REGION
override val ACTION_EXPAND_REGION_RECURSIVELY: String
get() = IdeActions.ACTION_EXPAND_REGION_RECURSIVELY
override val ACTION_EXPAND_COLLAPSE_TOGGLE: String
// [VERSION UPDATE] 2024.3+ Replace raw "ExpandCollapseToggleAction" with IdeActions.ACTION_EXPAND_COLLAPSE_TOGGLE_REGION from the platform.
get() = "ExpandCollapseToggleAction"
/**
* Execute an action

View File

@@ -16,7 +16,6 @@ import com.maddyhome.idea.vim.VimPlugin
import com.maddyhome.idea.vim.api.VimEditor
import com.maddyhome.idea.vim.api.getLineEndForOffset
import com.maddyhome.idea.vim.api.getLineStartForOffset
import com.maddyhome.idea.vim.command.OperatorArguments
import com.maddyhome.idea.vim.listener.SelectionVimListenerSuppressor
import com.maddyhome.idea.vim.newapi.IjEditorExecutionContext
import com.maddyhome.idea.vim.newapi.IjVimCaret
@@ -94,6 +93,6 @@ internal fun VimEditor.exitSelectMode(adjustCaretPosition: Boolean) {
}
}
internal fun Editor.exitInsertMode(context: DataContext, operatorArguments: OperatorArguments) {
VimPlugin.getChange().processEscape(IjVimEditor(this), IjEditorExecutionContext(context), operatorArguments)
internal fun Editor.exitInsertMode(context: DataContext) {
VimPlugin.getChange().processEscape(IjVimEditor(this), IjEditorExecutionContext(context))
}

View File

@@ -24,6 +24,7 @@ import com.maddyhome.idea.vim.common.InsertSequence
import com.maddyhome.idea.vim.ex.ExOutputModel
import com.maddyhome.idea.vim.group.visual.VisualChange
import com.maddyhome.idea.vim.group.visual.vimLeadSelectionOffset
import com.maddyhome.idea.vim.common.VimEditorReplaceMask
import com.maddyhome.idea.vim.newapi.vim
import com.maddyhome.idea.vim.state.VimStateMachine
import com.maddyhome.idea.vim.state.mode.Mode
@@ -124,6 +125,7 @@ internal var Editor.vimExOutput: ExOutputModel? by userData()
internal var Editor.vimTestInputModel: TestInputModel? by userData()
internal var Editor.vimChangeActionSwitchMode: Mode? by userData()
internal var Editor.replaceMask: VimEditorReplaceMask? by userData()
internal var Caret.currentInsert: InsertSequence? by userData()
internal val Caret.insertHistory: MutableList<InsertSequence> by userDataOr { mutableListOf() }

View File

@@ -15,7 +15,6 @@ import com.maddyhome.idea.vim.VimPlugin
import com.maddyhome.idea.vim.api.ExecutionContext
import com.maddyhome.idea.vim.api.VimEditor
import com.maddyhome.idea.vim.api.injector
import com.maddyhome.idea.vim.command.OperatorArguments
import com.maddyhome.idea.vim.common.EditorListener
import com.maddyhome.idea.vim.helper.inInsertMode
import com.maddyhome.idea.vim.newapi.ij
@@ -65,7 +64,7 @@ class IJEditorFocusListener : EditorListener {
val context: ExecutionContext = injector.executionContextManager.getEditorExecutionContext(editor)
val mode = injector.vimState.mode
when (mode) {
is Mode.INSERT -> editor.exitInsertMode(context, OperatorArguments(false, 0, mode))
is Mode.INSERT -> editor.exitInsertMode(context)
else -> {}
}
}
@@ -79,3 +78,4 @@ class IJEditorFocusListener : EditorListener {
KeyHandler.getInstance().reset(editor)
}
}

View File

@@ -16,7 +16,9 @@ import com.intellij.codeInsight.lookup.impl.actions.ChooseItemAction
import com.intellij.codeInsight.template.Template
import com.intellij.codeInsight.template.TemplateEditingAdapter
import com.intellij.codeInsight.template.TemplateManagerListener
import com.intellij.codeInsight.template.impl.TemplateManagerImpl
import com.intellij.codeInsight.template.impl.TemplateState
import com.intellij.codeInsight.template.impl.actions.NextVariableAction
import com.intellij.find.FindModelListener
import com.intellij.openapi.actionSystem.ActionManager
import com.intellij.openapi.actionSystem.ActionUpdateThread
@@ -152,6 +154,10 @@ internal object IdeaSpecifics {
KeyHandler.getInstance().reset(it.vim)
}
}
else if (action is NextVariableAction && TemplateManagerImpl.getTemplateState(editor) == null) {
editor.vim.exitInsertMode(event.dataContext.vim)
KeyHandler.getInstance().reset(editor.vim)
}
//endregion
if (caretOffset != -1 && caretOffset != editor.caretModel.offset) {

View File

@@ -66,7 +66,6 @@ import com.maddyhome.idea.vim.api.coerceOffset
import com.maddyhome.idea.vim.api.getLineEndForOffset
import com.maddyhome.idea.vim.api.getLineStartForOffset
import com.maddyhome.idea.vim.api.injector
import com.maddyhome.idea.vim.ex.ExOutputModel
import com.maddyhome.idea.vim.group.EditorGroup
import com.maddyhome.idea.vim.group.FileGroup
import com.maddyhome.idea.vim.group.IjOptions
@@ -395,7 +394,8 @@ internal object VimListenerManager {
editor.vim.mode = Mode.NORMAL()
KeyHandler.getInstance().reset(editor.vim)
}
injector.scroll.scrollCaretIntoView(editor.vim)
// Breaks relativenumber for some reason
// injector.scroll.scrollCaretIntoView(editor.vim)
}
MotionGroup.fileEditorManagerSelectionChangedCallback(event)
@@ -748,7 +748,7 @@ internal object VimListenerManager {
injector.commandLine.getActiveCommandLine()?.close(refocusOwningEditor = true, resetCaret = false)
injector.modalInput.getCurrentModalInput()?.deactivate(refocusOwningEditor = true, resetCaret = false)
ExOutputModel.tryGetInstance(editor)?.close()
injector.outputPanel.getCurrentOutputPanel()?.close()
val caretModel = editor.caretModel
if (editor.vim.mode.selectionType != null) {
@@ -777,7 +777,7 @@ internal object VimListenerManager {
injector.commandLine.getActiveCommandLine()?.close(refocusOwningEditor = true, resetCaret = false)
injector.modalInput.getCurrentModalInput()?.deactivate(refocusOwningEditor = true, resetCaret = false)
ExOutputModel.getInstance(event.editor).close()
injector.outputPanel.getCurrentOutputPanel()?.close()
}
}
}

View File

@@ -14,6 +14,27 @@ import com.maddyhome.idea.vim.common.LiveRange
internal class IjLiveRange(val marker: RangeMarker) : LiveRange {
override val startOffset: Int
get() = marker.startOffset
override val endOffset: Int
get() = marker.endOffset
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false
other as IjLiveRange
if (startOffset != other.startOffset) return false
if (endOffset != other.endOffset) return false
return true
}
override fun hashCode(): Int {
var result = startOffset
result = 31 * result + endOffset
return result
}
}
val RangeMarker.vim: LiveRange

View File

@@ -38,12 +38,12 @@ import com.maddyhome.idea.vim.api.VimSelectionModel
import com.maddyhome.idea.vim.api.VimVisualPosition
import com.maddyhome.idea.vim.api.VirtualFile
import com.maddyhome.idea.vim.api.injector
import com.maddyhome.idea.vim.command.OperatorArguments
import com.maddyhome.idea.vim.common.IndentConfig
import com.maddyhome.idea.vim.common.IndentConfig.Companion.create
import com.maddyhome.idea.vim.common.LiveRange
import com.maddyhome.idea.vim.common.ModeChangeListener
import com.maddyhome.idea.vim.common.TextRange
import com.maddyhome.idea.vim.common.VimEditorReplaceMask
import com.maddyhome.idea.vim.common.forgetAllReplaceMasks
import com.maddyhome.idea.vim.group.visual.vimSetSystemBlockSelectionSilently
import com.maddyhome.idea.vim.helper.EditorHelper
import com.maddyhome.idea.vim.helper.StrictMode
@@ -53,6 +53,7 @@ import com.maddyhome.idea.vim.helper.fileSize
import com.maddyhome.idea.vim.helper.getTopLevelEditor
import com.maddyhome.idea.vim.helper.inExMode
import com.maddyhome.idea.vim.helper.isTemplateActive
import com.maddyhome.idea.vim.helper.replaceMask
import com.maddyhome.idea.vim.helper.vimChangeActionSwitchMode
import com.maddyhome.idea.vim.helper.vimLastSelectionType
import com.maddyhome.idea.vim.impl.state.VimStateMachineImpl
@@ -75,6 +76,11 @@ internal class IjVimEditor(editor: Editor) : MutableLinearEditor, VimEditorBase(
// TBH, I don't like the names. Need to think a bit more about this
val editor = editor.getTopLevelEditor()
val originalEditor = editor
override var replaceMask: VimEditorReplaceMask?
get() = editor.replaceMask
set(value) {
editor.replaceMask = value
}
override fun updateMode(mode: Mode) {
(injector.vimState as VimStateMachineImpl).mode = mode
@@ -91,7 +97,7 @@ internal class IjVimEditor(editor: Editor) : MutableLinearEditor, VimEditorBase(
editor.vimChangeActionSwitchMode = value
}
override val indentConfig: VimIndentConfig
get() = create(editor)
get() = IndentConfig.create(editor)
override fun fileSize(): Long = editor.fileSize.toLong()
@@ -398,8 +404,8 @@ internal class IjVimEditor(editor: Editor) : MutableLinearEditor, VimEditorBase(
return editor.visualPositionToOffset(VisualPosition(position.line, position.column, position.leansRight))
}
override fun exitInsertMode(context: ExecutionContext, operatorArguments: OperatorArguments) {
editor.exitInsertMode(context.ij, operatorArguments)
override fun exitInsertMode(context: ExecutionContext) {
editor.exitInsertMode(context.ij)
}
override fun exitSelectModeNative(adjustCaret: Boolean) {
@@ -471,6 +477,7 @@ internal class IjVimEditor(editor: Editor) : MutableLinearEditor, VimEditorBase(
get() = (editor as? EditorEx)?.isInsertMode ?: false
set(value) {
(editor as? EditorEx)?.isInsertMode = value
forgetAllReplaceMasks()
}
override val document: VimDocument

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

@@ -192,6 +192,13 @@ private object VimActionsPopup {
null,
),
)
actionGroup.add(
HelpLink(
"Take Survey ↗",
"https://surveys.jetbrains.com/s3/ideavim-usage-survey",
AllIcons.Actions.IntentionBulb,
),
)
actionGroup.addSeparator(MessageHelper.message("action.eap.choice.active.text"))
actionGroup.add(JoinEap)

View File

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

View File

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

View File

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

View File

@@ -63,7 +63,7 @@ import static com.maddyhome.idea.vim.group.KeyGroup.toShortcutSet;
public class ExEntryPanel extends JPanel implements VimCommandLine {
public static ExEntryPanel instance;
public static ExEntryPanel instanceWithoutShortcuts;
private boolean isReplaceMode = false;
public boolean isReplaceMode = false;
private WeakReference<Editor> weakEditor = null;
private VimInputInterceptor myInputInterceptor = null;
@@ -344,12 +344,12 @@ public class ExEntryPanel extends JPanel implements VimCommandLine {
}
}
// Get the current count from the command builder. This value is coerced to at least 1, so will always be valid.
// The aggregated value includes any counts for operator and register selections, and the uncommitted count for
// the search command (`/` or `?`). E.g., `2"a3"b4"c5d6/` would return 720.
// If we're showing highlights for an ex command like `:s`, there won't be a command, but the value is already
// coerced to at least 1.
int count1 = KeyHandler.getInstance().getKeyHandlerState().getEditorCommandBuilder().getAggregatedUncommittedCount();
// Get a snapshot of the count for the in progress command, and coerce it to 1. This value will include all
// count components - selecting register(s), operator and motions. E.g. `2"a3"b4"c5d6/` will return 720.
// If we're showing highlights for an Ex command like `:s`, the command builder will be empty, but we'll still
// get a valid value.
int count1 = Math.max(1, KeyHandler.getInstance().getKeyHandlerState().getEditorCommandBuilder()
.calculateCount0Snapshot());
if ((labelText.equals("/") || labelText.equals("?") || searchCommand) && !injector.getMacro().isExecutingMacro()) {
final boolean forwards = !labelText.equals("?"); // :s, :g, :v are treated as forwards
@@ -405,7 +405,7 @@ public class ExEntryPanel extends JPanel implements VimCommandLine {
@Override
public void toggleReplaceMode() {
isReplaceMode = !isReplaceMode;
entry.toggleInsertReplace();
}
/**
@@ -531,17 +531,17 @@ public class ExEntryPanel extends JPanel implements VimCommandLine {
private static final Logger logger = Logger.getInstance(ExEntryPanel.class.getName());
@NotNull
@Override
public VimCommandLineCaret getCaret() {
public @NotNull VimCommandLineCaret getCaret() {
return (VimCommandLineCaret) entry.getCaret();
}
@Override
public void setText(@NotNull String string) {
public void setText(@NotNull String string, boolean updateLastEntry) {
// It's a feature of Swing that caret is moved when we set new text. However, our API is Swing independent and we do not expect this
int offset = getCaret().getOffset();
entry.updateText(string);
if (updateLastEntry) entry.saveLastEntry();
getCaret().setOffset(Math.min(offset, getVisibleText().length()));
}
@@ -550,9 +550,8 @@ public class ExEntryPanel extends JPanel implements VimCommandLine {
entry.clearCurrentAction();
}
@Nullable
@Override
public Integer getPromptCharacterOffset() {
public @Nullable Integer getPromptCharacterOffset() {
int offset = entry.currentActionPromptCharacterOffset;
return offset == -1 ? null : offset;
}
@@ -572,8 +571,7 @@ public class ExEntryPanel extends JPanel implements VimCommandLine {
IdeFocusManager.findInstance().requestFocus(entry, true);
}
@Nullable
public VimInputInterceptor<?> getInputInterceptor() {
public @Nullable VimInputInterceptor<?> getInputInterceptor() {
return myInputInterceptor;
}
@@ -586,18 +584,37 @@ public class ExEntryPanel extends JPanel implements VimCommandLine {
myInputInterceptor = vimInputInterceptor;
}
@Nullable
@Override
public Function1<String, Unit> getInputProcessing() {
public @Nullable Function1<String, Unit> getInputProcessing() {
return inputProcessing;
}
@Nullable
@Override
public Character getFinishOn() {
public @Nullable Character getFinishOn() {
return finishOn;
}
@Override
public int getHistIndex() {
return entry.histIndex;
}
@Override
public void setHistIndex(int i) {
entry.histIndex = i;
}
@NotNull
@Override
public String getLastEntry() {
return entry.lastEntry;
}
@Override
public void setLastEntry(@NotNull String s) {
entry.lastEntry = s;
}
public static class LafListener implements LafManagerListener {
@Override
public void lookAndFeelChanged(@NotNull LafManager source) {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -44,6 +44,7 @@ viminfo
virtualedit
visualbell
visualdelay
whichwrap
wrapscan
nobomb

View File

@@ -0,0 +1,82 @@
[
{
"keys": ".",
"class": "com.maddyhome.idea.vim.action.change.RepeatChangeAction",
"modes": "N"
},
{
"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

@@ -7,6 +7,7 @@
*/
package org.jetbrains.plugins.ideavim.action
import com.intellij.idea.TestFor
import com.maddyhome.idea.vim.api.injector
import com.maddyhome.idea.vim.state.mode.Mode
import com.maddyhome.idea.vim.state.mode.ReturnTo
@@ -1068,4 +1069,14 @@ foobaz
Mode.NORMAL(),
)
}
@Test
@TestFor(issues = ["VIM-2074"])
fun `backspace with replace mode`() {
configureByText("${c}Hello world")
typeText("R1111")
assertState("1111o world")
typeText("<BS><BS><BS>")
assertState("1ello world")
}
}

View File

@@ -109,7 +109,7 @@ class CopyActionTest : VimTestCase() {
@TestWithoutNeovim(reason = SkipNeovimReason.DIFFERENT)
@Test
fun testYankRegisterUsesLastEnteredRegister() {
typeTextInFile("\"a\"byl" + "\"ap", "hel<caret>lo world\n")
typeTextInFile("\"a\"byl" + "\"bp", "hel<caret>lo world\n")
assertState("helllo world\n")
}

View File

@@ -85,4 +85,33 @@ class MotionBackspaceActionTest : VimTestCase() {
enterCommand("set whichwrap=b")
}
}
@TestWithoutNeovim(SkipNeovimReason.OPTION)
@Test
fun `test backspace motion with operator`() {
doTest(
"d<BS>",
"""
lorem ${c}ipsum dolor sit amet
""".trimIndent(),
"""
lorem${c}ipsum dolor sit amet
""".trimIndent(),
)
}
@TestWithoutNeovim(SkipNeovimReason.OPTION)
@Test
fun `test backspace motion with operator at start of line`() {
doTest(
"d<BS>",
"""
lorem ipsum dolor sit amet
${c}lorem ipsum dolor sit amet
""".trimIndent(),
"""
lorem ipsum dolor sit amet${c}lorem ipsum dolor sit amet
""".trimIndent(),
)
}
}

View File

@@ -85,4 +85,35 @@ class MotionSpaceActionTest : VimTestCase() {
enterCommand("set whichwrap=s")
}
}
@Suppress("SpellCheckingInspection")
@TestWithoutNeovim(SkipNeovimReason.OPTION)
@Test
fun `test space motion with operator`() {
doTest(
"d<Space>",
"""
lorem ${c}ipsum dolor sit amet
""".trimIndent(),
"""
lorem ${c}psum dolor sit amet
""".trimIndent(),
)
}
@TestWithoutNeovim(SkipNeovimReason.OPTION)
@Test
fun `test space motion with operator at end of line`() {
doTest(
"d<Space>",
"""
lorem ipsum dolor sit ame${c}t
lorem ipsum dolor sit amet
""".trimIndent(),
"""
lorem ipsum dolor sit am${c}e
lorem ipsum dolor sit amet
""".trimIndent(),
)
}
}

View File

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

View File

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

View File

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

View File

@@ -15,7 +15,7 @@ class VimVariableServiceTest : VimTestCase() {
@Test
fun `test v count variable without count specified`() {
configureByText("\n")
enterCommand("nnoremap <expr> n ':echo ' .. v:count .. \"\\<CR>\"")
enterCommand("""nnoremap <expr> n ':echo ' .. v:count .. "\<CR>"""")
typeText("n")
assertExOutput("0")
}
@@ -23,15 +23,31 @@ class VimVariableServiceTest : VimTestCase() {
@Test
fun `test v count variable`() {
configureByText("\n")
enterCommand("nnoremap <expr> n ':' .. \"\\<C-u>\" .. 'echo ' .. v:count .. \"\\<CR>\"")
enterCommand("""nnoremap <expr> n ':' .. "\<C-u>" .. 'echo ' .. v:count .. "\<CR>"""")
typeText("5n")
assertExOutput("5")
}
@Test
fun `test v count variable with additional count during select register`() {
configureByText("\n")
enterCommand("""nnoremap <expr> n ':' .. "\<C-u>" .. 'echo ' .. v:count .. "\<CR>"""")
typeText("2\"a5n")
assertExOutput("10")
}
@Test
fun `test v count variable with additional pathological count during select register`() {
configureByText("\n")
enterCommand("""nnoremap <expr> n ':' .. "\<C-u>" .. 'echo ' .. v:count .. "\<CR>"""")
typeText("2\"a3\"b4\"c5n")
assertExOutput("120")
}
@Test
fun `test v count1 variable without count specified`() {
configureByText("\n")
enterCommand("nnoremap <expr> n ':echo ' .. v:count1 .. \"\\<CR>\"")
enterCommand("""nnoremap <expr> n ':echo ' .. v:count1 .. "\<CR>"""")
typeText("n")
assertExOutput("1")
}
@@ -39,11 +55,27 @@ class VimVariableServiceTest : VimTestCase() {
@Test
fun `test v count1 variable`() {
configureByText("\n")
enterCommand("nnoremap <expr> n ':' .. \"\\<C-u>\" .. 'echo ' .. v:count1 .. \"\\<CR>\"")
enterCommand("""nnoremap <expr> n ':' .. "\<C-u>" .. 'echo ' .. v:count1 .. "\<CR>"""")
typeText("5n")
assertExOutput("5")
}
@Test
fun `test v count1 variable with additional count during select register`() {
configureByText("\n")
enterCommand("""nnoremap <expr> n ':' .. "\<C-u>" .. 'echo ' .. v:count1 .. "\<CR>"""")
typeText("2\"a5n")
assertExOutput("10")
}
@Test
fun `test v count1 variable with additional pathological count during select register`() {
configureByText("\n")
enterCommand("""nnoremap <expr> n ':' .. "\<C-u>" .. 'echo ' .. v:count1 .. "\<CR>"""")
typeText("2\"a3\"b4\"c5n")
assertExOutput("120")
}
@Test
fun `test mapping with updating jumplist`() {
configureByText("${c}1\n2\n3\n4\n5\n6\n7\n8\n9\n")

View File

@@ -141,6 +141,16 @@ Mode.INSERT,
)
}
@Test
fun testDeleteWithMultipleCounts() {
doTest(
"2d2aa",
"function(int <caret>arg1, char* arg<caret>2=\"a,b,c(d,e)\", bool arg3, string arg4, int arg5)",
"function(<caret>)",
Mode.NORMAL(),
)
}
@Test
fun testSelectTwoArguments() {
doTest(

View File

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

View File

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

View File

@@ -95,7 +95,7 @@ private class AvailableActions(private val editor: Editor) : ImperativeCommand {
val currentNode = KeyHandler.getInstance().keyHandlerState.commandBuilder.getCurrentTrie()
// Note: esc is always an option
val possibleKeys = (currentNode.keys.toList() + esc).sortedBy { injector.parser.toKeyNotation(it) }
val possibleKeys = (currentNode.children.keys.toList() + esc).sortedBy { injector.parser.toKeyNotation(it) }
println("Keys: ${possibleKeys.joinToString(", ")}")
val keyGenerator = Generator.integers(0, possibleKeys.lastIndex)
.suchThat { injector.parser.toKeyNotation(possibleKeys[it]) !in stinkyKeysList }

View File

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

View File

@@ -17,14 +17,13 @@ import com.maddyhome.idea.vim.command.CommandFlags
import com.maddyhome.idea.vim.command.MappingMode
import com.maddyhome.idea.vim.command.MappingProcessor
import com.maddyhome.idea.vim.command.OperatorArguments
import com.maddyhome.idea.vim.common.CurrentCommandState
import com.maddyhome.idea.vim.diagnostic.VimLogger
import com.maddyhome.idea.vim.diagnostic.trace
import com.maddyhome.idea.vim.diagnostic.vimLogger
import com.maddyhome.idea.vim.impl.state.toMappingMode
import com.maddyhome.idea.vim.key.CommandPartNode
import com.maddyhome.idea.vim.key.KeyConsumer
import com.maddyhome.idea.vim.key.KeyStack
import com.maddyhome.idea.vim.key.RootNode
import com.maddyhome.idea.vim.key.consumers.CharArgumentConsumer
import com.maddyhome.idea.vim.key.consumers.CommandConsumer
import com.maddyhome.idea.vim.key.consumers.CommandCountConsumer
@@ -55,8 +54,15 @@ class KeyHandler {
private val keyConsumers: List<KeyConsumer> = listOf(ModalInputConsumer(), MappingProcessor, CommandCountConsumer(), DeleteCommandConsumer(), EditorResetConsumer(), CharArgumentConsumer(), RegisterConsumer(), DigraphConsumer(), CommandConsumer(), SelectRegisterConsumer(), ModeInputConsumer())
private var handleKeyRecursionCount = 0
var keyHandlerState: KeyHandlerState = KeyHandlerState()
private set
// KeyHandlerState requires injector.keyGroup to be initialized and that's why we don't create it immediately and have this here
// TODO figure out a better solution
private val defaultKeyHandlerState by lazy { KeyHandlerState() }
private var mutableKeyHandlerState: KeyHandlerState? = null
var keyHandlerState: KeyHandlerState
get() = mutableKeyHandlerState ?: defaultKeyHandlerState
private set(value) {
mutableKeyHandlerState = value
}
val keyStack: KeyStack = KeyStack()
val modalEntryKeys: MutableList<KeyStroke> = ArrayList()
@@ -190,11 +196,9 @@ class KeyHandler {
}
private fun onUnknownKey(editor: VimEditor, keyState: KeyHandlerState) {
logger.trace("Command builder is set to BAD")
keyState.commandBuilder.commandState = CurrentCommandState.BAD_COMMAND
editor.resetOpPending()
injector.vimState.resetRegisterPending()
editor.isReplaceCharacter = false
// Note that this will also reset the CommandBuilder to NEW_COMMAND
reset(keyState, editor.mode)
}
@@ -203,14 +207,6 @@ class KeyHandler {
injector.messages.indicateError()
}
fun isDuplicateOperatorKeyStroke(key: KeyStroke, mode: Mode, keyState: KeyHandlerState): Boolean {
return isOperatorPending(mode, keyState) && keyState.commandBuilder.isDuplicateOperatorKeyStroke(key)
}
fun isOperatorPending(mode: Mode, keyState: KeyHandlerState): Boolean {
return mode is Mode.OP_PENDING && !keyState.commandBuilder.isEmpty
}
private fun executeCommand(
editor: VimEditor,
context: ExecutionContext,
@@ -219,11 +215,7 @@ class KeyHandler {
) {
logger.trace("Command execution")
val command = keyState.commandBuilder.buildCommand()
val operatorArguments = OperatorArguments(
editor.mode is Mode.OP_PENDING,
command.rawCount,
editorState.mode,
)
val operatorArguments = OperatorArguments(command.rawCount, editorState.mode)
// If we were in "operator pending" mode, reset back to normal mode.
// But opening command line should not reset operator pending mode (e.g. `d/foo`
@@ -283,11 +275,12 @@ class KeyHandler {
// TODO we should have a single reset method
fun reset(keyState: KeyHandlerState, mode: Mode) {
logger.trace { "Reset is executed" }
injector.commandLine.getActiveCommandLine()?.clearCurrentAction()
keyHandlerState.partialReset(mode)
keyState.commandBuilder.resetAll(getKeyRoot(mode.toMappingMode()))
}
private fun getKeyRoot(mappingMode: MappingMode): CommandPartNode<LazyVimCommand> {
private fun getKeyRoot(mappingMode: MappingMode): RootNode<LazyVimCommand> {
return injector.keyGroup.getKeyRoot(mappingMode)
}
@@ -333,7 +326,7 @@ class KeyHandler {
) : Runnable {
override fun run() {
val editorState = injector.vimState
keyState.commandBuilder.commandState = CurrentCommandState.NEW_COMMAND
val register = cmd.register
if (register != null) {
injector.registerGroup.selectRegister(register)
@@ -353,22 +346,15 @@ class KeyHandler {
// mode we were in. This handles commands in those modes that temporarily allow us to execute normal
// mode commands. An exception is if this command should leave us in the temporary mode such as
// "select register"
val myMode = editorState.mode
val returnTo = myMode.returnTo
if (myMode is Mode.NORMAL && returnTo != null && !cmd.flags.contains(CommandFlags.FLAG_EXPECT_MORE)) {
when (returnTo) {
ReturnTo.INSERT -> {
editor.mode = Mode.INSERT
}
ReturnTo.REPLACE -> {
editor.mode = Mode.REPLACE
}
if (editorState.mode is Mode.NORMAL && !cmd.flags.contains(CommandFlags.FLAG_EXPECT_MORE)) {
when (editorState.mode.returnTo) {
ReturnTo.INSERT -> editor.mode = Mode.INSERT
ReturnTo.REPLACE -> editor.mode = Mode.REPLACE
null -> {}
}
}
if (keyState.commandBuilder.isDone()) {
getInstance().reset(keyState, editorState.mode)
}
instance.reset(keyState, editorState.mode)
}
}

View File

@@ -17,23 +17,17 @@ import com.maddyhome.idea.vim.api.injector
import com.maddyhome.idea.vim.api.lineLength
import com.maddyhome.idea.vim.command.Argument
import com.maddyhome.idea.vim.command.Command
import com.maddyhome.idea.vim.command.CommandFlags
import com.maddyhome.idea.vim.command.OperatorArguments
import com.maddyhome.idea.vim.diagnostic.debug
import com.maddyhome.idea.vim.diagnostic.vimLogger
import com.maddyhome.idea.vim.handler.ChangeEditorActionHandler
import com.maddyhome.idea.vim.helper.enumSetOf
import com.maddyhome.idea.vim.state.KeyHandlerState
import java.util.*
@CommandOrMotion(keys = ["r"], modes = [Mode.NORMAL])
class ChangeCharacterAction : ChangeEditorActionHandler.ForEachCaret() {
override val type: Command.Type = Command.Type.CHANGE
override val argumentType: Argument.Type = Argument.Type.DIGRAPH
override val flags: EnumSet<CommandFlags> = enumSetOf(CommandFlags.FLAG_ALLOW_DIGRAPH)
override fun onStartWaitingForArgument(editor: VimEditor, context: ExecutionContext, keyState: KeyHandlerState) {
editor.isReplaceCharacter = true
}
@@ -45,7 +39,7 @@ class ChangeCharacterAction : ChangeEditorActionHandler.ForEachCaret() {
argument: Argument?,
operatorArguments: OperatorArguments,
): Boolean {
return argument != null && changeCharacter(editor, caret, operatorArguments.count1, argument.character)
return argument is Argument.Character && changeCharacter(editor, caret, operatorArguments.count1, argument.character)
}
}

View File

@@ -37,12 +37,11 @@ class ChangeLineAction : ChangeInInsertSequenceAction() {
): Boolean {
// `S` command is a synonym of `cc`
val motion = MotionDownLess1FirstNonSpaceAction()
val command = Command(1, motion, motion.type, motion.flags)
return injector.changeGroup.changeMotion(
editor,
caret,
context,
Argument(command),
Argument.Motion(motion, null),
operatorArguments,
)
}

View File

@@ -15,6 +15,7 @@ import com.maddyhome.idea.vim.api.injector
import com.maddyhome.idea.vim.command.Argument
import com.maddyhome.idea.vim.command.Command
import com.maddyhome.idea.vim.command.OperatorArguments
import com.maddyhome.idea.vim.common.VimEditorReplaceMask
import com.maddyhome.idea.vim.handler.ChangeEditorActionHandler
@CommandOrMotion(keys = ["R"], modes = [Mode.NORMAL])
@@ -39,4 +40,5 @@ class ChangeReplaceAction : ChangeEditorActionHandler.SingleExecution() {
*/
private fun changeReplace(editor: VimEditor, context: ExecutionContext) {
injector.changeGroup.initInsert(editor, context, com.maddyhome.idea.vim.state.mode.Mode.REPLACE)
editor.replaceMask = VimEditorReplaceMask()
}

View File

@@ -39,7 +39,6 @@ class ChangeVisualAction : VisualOperatorActionHandler.ForEachCaret() {
range.toVimTextRange(false),
range.type,
context,
operatorArguments,
)
}
}

View File

@@ -15,16 +15,13 @@ import com.maddyhome.idea.vim.api.VimEditor
import com.maddyhome.idea.vim.api.injector
import com.maddyhome.idea.vim.command.Argument
import com.maddyhome.idea.vim.command.Command
import com.maddyhome.idea.vim.command.CommandFlags
import com.maddyhome.idea.vim.command.OperatorArguments
import com.maddyhome.idea.vim.common.TextRange
import com.maddyhome.idea.vim.diagnostic.debug
import com.maddyhome.idea.vim.diagnostic.vimLogger
import com.maddyhome.idea.vim.group.visual.VimSelection
import com.maddyhome.idea.vim.handler.VisualOperatorActionHandler
import com.maddyhome.idea.vim.helper.enumSetOf
import com.maddyhome.idea.vim.state.KeyHandlerState
import java.util.*
/**
* @author vlan
@@ -32,11 +29,8 @@ import java.util.*
@CommandOrMotion(keys = ["r"], modes = [Mode.VISUAL])
class ChangeVisualCharacterAction : VisualOperatorActionHandler.ForEachCaret() {
override val type: Command.Type = Command.Type.CHANGE
override val argumentType: Argument.Type = Argument.Type.DIGRAPH
override val flags: EnumSet<CommandFlags> = enumSetOf(CommandFlags.FLAG_ALLOW_DIGRAPH)
override fun onStartWaitingForArgument(editor: VimEditor, context: ExecutionContext, keyState: KeyHandlerState) {
editor.isReplaceCharacter = true
}
@@ -50,7 +44,7 @@ class ChangeVisualCharacterAction : VisualOperatorActionHandler.ForEachCaret() {
operatorArguments: OperatorArguments,
): Boolean {
val argument = cmd.argument
return argument != null &&
return argument is Argument.Character &&
changeCharacterRange(editor, caret, range.toVimTextRange(false), argument.character)
}
}

View File

@@ -56,7 +56,6 @@ class ChangeVisualLinesAction : VisualOperatorActionHandler.ForEachCaret() {
lineRange,
SelectionType.LINE_WISE,
context,
operatorArguments,
)
}
}

View File

@@ -53,7 +53,7 @@ class ChangeVisualLinesEndAction : VisualOperatorActionHandler.ForEachCaret() {
}
}
val blockRange = TextRange(starts, ends)
injector.changeGroup.changeRange(editor, caret, blockRange, SelectionType.BLOCK_WISE, context, operatorArguments)
injector.changeGroup.changeRange(editor, caret, blockRange, SelectionType.BLOCK_WISE, context)
} else {
val lineEndForOffset = editor.getLineEndForOffset(vimTextRange.endOffset)
val endsWithNewLine = if (lineEndForOffset.toLong() == editor.fileSize()) 0 else 1
@@ -61,7 +61,7 @@ class ChangeVisualLinesEndAction : VisualOperatorActionHandler.ForEachCaret() {
editor.getLineStartForOffset(vimTextRange.startOffset),
lineEndForOffset + endsWithNewLine,
)
injector.changeGroup.changeRange(editor, caret, lineRange, SelectionType.LINE_WISE, context, operatorArguments)
injector.changeGroup.changeRange(editor, caret, lineRange, SelectionType.LINE_WISE, context)
}
}
}

View File

@@ -31,7 +31,7 @@ class FilterVisualLinesAction : VimActionHandler.SingleExecution(), FilterComman
override fun execute(editor: VimEditor, context: ExecutionContext, cmd: Command, operatorArguments: OperatorArguments): Boolean {
// Start ex entry with the initial text set to the calculated range and `!`
startFilterCommand(editor, context, cmd)
startFilterCommand(editor, context, cmd.rawCount)
return true
}
}
@@ -63,13 +63,13 @@ class FilterMotionAction : VimActionHandler.SingleExecution(), FilterCommand, Du
// Start ex entry with the initial text set to the calculated range and `!`
val count = if (start.line < end.line) end.line - start.line + 1 else 1
startFilterCommand(editor, context, Argument.EMPTY_COMMAND.copy(rawCount = count))
startFilterCommand(editor, context, count)
return true
}
}
interface FilterCommand {
fun startFilterCommand(editor: VimEditor, context: ExecutionContext, cmd: Command) {
injector.commandLine.createCommandPrompt(editor, context, cmd, initialText = "!")
fun startFilterCommand(editor: VimEditor, context: ExecutionContext, count0: Int) {
injector.commandLine.createCommandPrompt(editor, context, count0, initialText = "!")
}
}

View File

@@ -38,6 +38,6 @@ class DeleteMotionAction : ChangeEditorActionHandler.ForEachCaret(), DuplicableO
val (range, selectionType) = injector.changeGroup
.getDeleteRangeAndType(editor, caret, context, argument, false, operatorArguments)
?: return false
return injector.changeGroup.deleteRange(editor, caret, range, selectionType, false, operatorArguments)
return injector.changeGroup.deleteRange(editor, caret, range, selectionType, false)
}
}

View File

@@ -40,7 +40,6 @@ class DeleteVisualAction : VisualOperatorActionHandler.ForEachCaret() {
range.toVimTextRange(false),
selectionType,
false,
operatorArguments,
)
}
}

View File

@@ -56,6 +56,6 @@ class DeleteVisualLinesAction : VisualOperatorActionHandler.ForEachCaret() {
Triple(caret, lineRange, SelectionType.LINE_WISE)
}
}
return injector.changeGroup.deleteRange(editor, usedCaret, usedRange, usedType, false, operatorArguments)
return injector.changeGroup.deleteRange(editor, usedCaret, usedRange, usedType, false)
}
}

View File

@@ -58,7 +58,6 @@ class DeleteVisualLinesEndAction : VisualOperatorActionHandler.ForEachCaret() {
blockRange,
SelectionType.BLOCK_WISE,
false,
operatorArguments,
)
} else {
val lineEndForOffset = editor.getLineEndForOffset(vimTextRange.endOffset)
@@ -67,7 +66,7 @@ class DeleteVisualLinesEndAction : VisualOperatorActionHandler.ForEachCaret() {
editor.getLineStartForOffset(vimTextRange.startOffset),
lineEndForOffset + endsWithNewLine,
)
injector.changeGroup.deleteRange(editor, caret, lineRange, SelectionType.LINE_WISE, false, operatorArguments)
injector.changeGroup.deleteRange(editor, caret, lineRange, SelectionType.LINE_WISE, false)
}
}
}

View File

@@ -0,0 +1,40 @@
/*
* 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.change.insert
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.getLineStartForOffset
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-H>", "<BS>"], modes = [Mode.INSERT])
internal class InsertBackspaceAction : VimActionHandler.SingleExecution() {
override val type: Command.Type = Command.Type.OTHER_WRITABLE
override fun execute( editor: VimEditor, context: ExecutionContext, cmd: Command, operatorArguments: OperatorArguments, ): Boolean {
if (editor.insertMode) {
injector.changeGroup.processBackspace(editor, context)
} else {
for (caret in editor.carets()) {
val offset = (caret.offset - 1).takeIf { it > 0 } ?: continue
val oldChar = editor.replaceMask?.popChange(editor, offset)
if (oldChar != null) {
injector.changeGroup.replaceText(editor, caret, offset, offset + 1, oldChar.toString())
}
caret.moveToOffset(offset)
}
}
return true
}
}

View File

@@ -52,7 +52,8 @@ class InsertCompletedDigraphAction : VimActionHandler.SingleExecution() {
override fun execute(editor: VimEditor, context: ExecutionContext, cmd: Command, operatorArguments: OperatorArguments): Boolean {
// The converted digraph character has been captured as an argument, push it back through key handler
val keyStroke = KeyStroke.getKeyStroke(cmd.argument!!.character)
val argument = cmd.argument as? Argument.Character ?: return false
val keyStroke = KeyStroke.getKeyStroke(argument.character)
val keyHandler = KeyHandler.getInstance()
keyHandler.handleKey(editor, keyStroke, context, keyHandler.keyHandlerState)
return true

View File

@@ -52,7 +52,8 @@ class InsertCompletedLiteralAction : VimActionHandler.SingleExecution() {
override fun execute(editor: VimEditor, context: ExecutionContext, cmd: Command, operatorArguments: OperatorArguments): Boolean {
// The converted literal character has been captured as an argument, push it back through key handler
val keyStroke = KeyStroke.getKeyStroke(cmd.argument!!.character)
val argument = cmd.argument as? Argument.Character ?: return false
val keyStroke = KeyStroke.getKeyStroke(argument.character)
val keyHandler = KeyHandler.getInstance()
keyHandler.handleKey(editor, keyStroke, context, keyHandler.keyHandlerState)
return true

View File

@@ -36,7 +36,7 @@ class InsertDeleteInsertedTextAction : ChangeEditorActionHandler.ForEachCaret()
argument: Argument?,
operatorArguments: OperatorArguments,
): Boolean {
return insertDeleteInsertedText(editor, caret, operatorArguments)
return insertDeleteInsertedText(editor, caret)
}
}
@@ -48,11 +48,7 @@ class InsertDeleteInsertedTextAction : ChangeEditorActionHandler.ForEachCaret()
* @param caret The caret on which the action is performed
* @return true if able to delete the text, false if not
*/
private fun insertDeleteInsertedText(
editor: VimEditor,
caret: VimCaret,
operatorArguments: OperatorArguments,
): Boolean {
private fun insertDeleteInsertedText(editor: VimEditor, caret: VimCaret): Boolean {
var deleteTo = caret.vimInsertStart.startOffset
val offset = caret.offset
if (offset == deleteTo) {
@@ -65,7 +61,6 @@ private fun insertDeleteInsertedText(
TextRange(deleteTo, offset),
SelectionType.CHARACTER_WISE,
false,
operatorArguments,
)
return true
}

View File

@@ -37,7 +37,7 @@ class InsertDeletePreviousWordAction : ChangeEditorActionHandler.ForEachCaret()
argument: Argument?,
operatorArguments: OperatorArguments,
): Boolean {
return insertDeletePreviousWord(editor, caret, operatorArguments)
return insertDeletePreviousWord(editor, caret)
}
}
@@ -50,7 +50,7 @@ class InsertDeletePreviousWordAction : ChangeEditorActionHandler.ForEachCaret()
* @param editor The editor to delete the text from
* @return true if able to delete text, false if not
*/
private fun insertDeletePreviousWord(editor: VimEditor, caret: VimCaret, operatorArguments: OperatorArguments): Boolean {
private fun insertDeletePreviousWord(editor: VimEditor, caret: VimCaret): Boolean {
val deleteTo: Int = if (caret.getBufferPosition().column == 0) {
caret.offset - 1
} else {
@@ -74,6 +74,6 @@ private fun insertDeletePreviousWord(editor: VimEditor, caret: VimCaret, operato
return false
}
val range = TextRange(deleteTo, caret.offset)
injector.changeGroup.deleteRange(editor, caret, range, SelectionType.CHARACTER_WISE, true, operatorArguments)
injector.changeGroup.deleteRange(editor, caret, range, SelectionType.CHARACTER_WISE, true)
return true
}

View File

@@ -18,14 +18,10 @@ import com.maddyhome.idea.vim.command.OperatorArguments
import com.maddyhome.idea.vim.ex.ExException
import com.maddyhome.idea.vim.handler.VimActionHandler
import com.maddyhome.idea.vim.helper.RWLockLabel
import com.maddyhome.idea.vim.helper.isCloseKeyStroke
import com.maddyhome.idea.vim.key.interceptors.VimInputInterceptorBase
import com.maddyhome.idea.vim.put.PutData
import com.maddyhome.idea.vim.register.Register
import com.maddyhome.idea.vim.state.mode.SelectionType
import com.maddyhome.idea.vim.vimscript.model.Script
import java.awt.event.KeyEvent
import javax.swing.KeyStroke
@CommandOrMotion(keys = ["<C-R>"], modes = [Mode.INSERT])
class InsertRegisterAction : VimActionHandler.SingleExecution() {
@@ -39,9 +35,8 @@ class InsertRegisterAction : VimActionHandler.SingleExecution() {
cmd: Command,
operatorArguments: OperatorArguments,
): Boolean {
val argument = cmd.argument
if (argument?.character == '=') {
val argument = cmd.argument as? Argument.Character ?: return false
if (argument.character == '=') {
injector.commandLine.readInputAndProcess(editor, context, "=", finishOn = null) { input ->
try {
if (input.isNotEmpty()) {
@@ -50,7 +45,7 @@ class InsertRegisterAction : VimActionHandler.SingleExecution() {
val textToStore = expression.toInsertableString()
injector.registerGroup.storeTextSpecial('=', textToStore)
}
insertRegister(editor, context, '=', operatorArguments)
insertRegister(editor, context, '=')
} catch (e: ExException) {
injector.messages.indicateError()
injector.messages.showStatusBarMessage(editor, e.message)
@@ -58,7 +53,7 @@ class InsertRegisterAction : VimActionHandler.SingleExecution() {
}
return true
} else {
return argument != null && insertRegister(editor, context, argument.character, operatorArguments)
return insertRegister(editor, context, argument.character)
}
}
}
@@ -72,18 +67,13 @@ class InsertRegisterAction : VimActionHandler.SingleExecution() {
* @return true if able to insert the register contents, false if not
*/
@RWLockLabel.SelfSynchronized
private fun insertRegister(
editor: VimEditor,
context: ExecutionContext,
key: Char,
operatorArguments: OperatorArguments,
): Boolean {
private fun insertRegister(editor: VimEditor, context: ExecutionContext, key: Char): Boolean {
val register: Register? = injector.registerGroup.getRegister(key)
if (register != null) {
val text = register.rawText ?: injector.parser.toPrintableString(register.keys)
val textData = PutData.TextData(text, SelectionType.CHARACTER_WISE, emptyList(), register.name)
val putData = PutData(textData, null, 1, insertTextBeforeCaret = true, rawIndent = true, caretAfterInsertedText = true)
injector.put.putText(editor, context, putData, operatorArguments = operatorArguments)
injector.put.putText(editor, context, putData)
return true
}
return false

View File

@@ -36,7 +36,7 @@ class VisualBlockAppendAction : VisualOperatorActionHandler.SingleExecution() {
if (editor.isOneLineMode()) return false
val range = caretsAndSelections.values.stream().findFirst().orElse(null) ?: return false
return if (range.type == SelectionType.BLOCK_WISE) {
injector.changeGroup.blockInsert(editor, context, range.toVimTextRange(false), true, operatorArguments)
injector.changeGroup.initBlockInsert(editor, context, range.toVimTextRange(false), true)
} else {
injector.changeGroup.insertAfterLineEnd(editor, context)
true

View File

@@ -36,7 +36,7 @@ class VisualBlockInsertAction : VisualOperatorActionHandler.SingleExecution() {
if (editor.isOneLineMode()) return false
val vimSelection = caretsAndSelections.values.stream().findFirst().orElse(null) ?: return false
return if (vimSelection.type == SelectionType.BLOCK_WISE) {
injector.changeGroup.blockInsert(editor, context, vimSelection.toVimTextRange(false), false, operatorArguments)
injector.changeGroup.initBlockInsert(editor, context, vimSelection.toVimTextRange(false), false)
} else {
injector.changeGroup.insertBeforeFirstNonBlank(editor, context)
true

View File

@@ -52,7 +52,7 @@ sealed class PutTextBaseAction(
}
result
} else {
injector.put.putText(editor, context, getPutData(count), operatorArguments)
injector.put.putText(editor, context, getPutData(count))
}
}

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,13 +20,13 @@ import com.maddyhome.idea.vim.helper.enumSetOf
import java.util.*
@CommandOrMotion(keys = [":"], modes = [Mode.NORMAL, Mode.VISUAL, Mode.OP_PENDING])
internal class ExEntryAction : VimActionHandler.SingleExecution() {
class ExEntryAction : VimActionHandler.SingleExecution() {
override val flags: EnumSet<CommandFlags> = enumSetOf(CommandFlags.FLAG_START_EX)
override val type: Command.Type = Command.Type.OTHER_READONLY
override fun execute(editor: VimEditor, context: ExecutionContext, cmd: Command, operatorArguments: OperatorArguments): Boolean {
if (editor.isOneLineMode()) return false
injector.commandLine.createCommandPrompt(editor, context, cmd, initialText = "")
injector.commandLine.createCommandPrompt(editor, context, cmd.rawCount, initialText = "")
return true
}
}

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