mirror of
https://github.com/chylex/IntelliJ-IdeaVim.git
synced 2025-08-17 16:31:45 +02:00
Compare commits
17 Commits
0.56
...
0.56.1-EAP
Author | SHA1 | Date | |
---|---|---|---|
![]() |
55f54b2e82 | ||
![]() |
1b18065e68 | ||
![]() |
053dc02152 | ||
![]() |
b8cb4a1295 | ||
![]() |
cd2cbf68a1 | ||
![]() |
73f3be8af0 | ||
![]() |
8cce059fb4 | ||
![]() |
db641ec6f6 | ||
![]() |
9d8239b68d | ||
![]() |
4ec0bac275 | ||
![]() |
613c234cfb | ||
![]() |
83dca71f69 | ||
![]() |
f7ea9cdb6e | ||
![]() |
762cb1804f | ||
![]() |
962cfb7ae2 | ||
![]() |
8415d104e9 | ||
![]() |
abd0f9b961 |
4
.gitignore
vendored
4
.gitignore
vendored
@@ -1,6 +1,10 @@
|
|||||||
*.swp
|
*.swp
|
||||||
/.gradle/
|
/.gradle/
|
||||||
|
|
||||||
/.idea/
|
/.idea/
|
||||||
|
!/.idea/scopes
|
||||||
|
!/.idea/copyright
|
||||||
|
|
||||||
/build/
|
/build/
|
||||||
/out/
|
/out/
|
||||||
/tmp/
|
/tmp/
|
6
.idea/copyright/IdeaVim.xml
generated
Normal file
6
.idea/copyright/IdeaVim.xml
generated
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<component name="CopyrightManager">
|
||||||
|
<copyright>
|
||||||
|
<option name="notice" value="IdeaVim - Vim emulator for IDEs based on the IntelliJ platform Copyright (C) 2003-&#36;today.year The IdeaVim authors This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>." />
|
||||||
|
<option name="myName" value="IdeaVim" />
|
||||||
|
</copyright>
|
||||||
|
</component>
|
7
.idea/copyright/profiles_settings.xml
generated
Normal file
7
.idea/copyright/profiles_settings.xml
generated
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
<component name="CopyrightManager">
|
||||||
|
<settings>
|
||||||
|
<module2copyright>
|
||||||
|
<element module="Copyright" copyright="IdeaVim" />
|
||||||
|
</module2copyright>
|
||||||
|
</settings>
|
||||||
|
</component>
|
3
.idea/scopes/Copyright.xml
generated
Normal file
3
.idea/scopes/Copyright.xml
generated
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
<component name="DependencyValidationManager">
|
||||||
|
<scope name="Copyright" pattern="file[IdeaVIM.main]:com//*||file[IdeaVIM.test]:*/" />
|
||||||
|
</component>
|
@@ -287,6 +287,10 @@ Contributors:
|
|||||||
[![icon][github]](https://github.com/kevin70)
|
[![icon][github]](https://github.com/kevin70)
|
||||||
|
|
||||||
kk
|
kk
|
||||||
|
* [![icon][mail]](mailto:runforprogram@163.com)
|
||||||
|
[![icon][github]](https://github.com/runforprogram)
|
||||||
|
|
||||||
|
runforprogram
|
||||||
|
|
||||||
If you are a contributor and your name is not listed here, feel free to
|
If you are a contributor and your name is not listed here, feel free to
|
||||||
contact the maintainers.
|
contact the maintainers.
|
||||||
|
14
CHANGES.md
14
CHANGES.md
@@ -22,6 +22,20 @@ It is important to distinguish EAP from traditional pre-release software.
|
|||||||
Please note that the quality of EAP versions may at times be way below even
|
Please note that the quality of EAP versions may at times be way below even
|
||||||
usual beta standards.
|
usual beta standards.
|
||||||
|
|
||||||
|
[To Be Released]
|
||||||
|
-------------
|
||||||
|
|
||||||
|
_Available since 0.56.1 EAP:_
|
||||||
|
|
||||||
|
**Fixes:**
|
||||||
|
* [VIM-1992](https://youtrack.jetbrains.com/issue/VIM-1992) Fix mappings to `<S-Letter>`
|
||||||
|
* [VIM-1991](https://youtrack.jetbrains.com/issue/VIM-1991) Fix working with number registers
|
||||||
|
|
||||||
|
**Merged PRs:**
|
||||||
|
* [234](https://github.com/JetBrains/ideavim/pull/234) by [runforprogram](https://github.com/runforprogram): [VIM-1991] fix >0 number register not work
|
||||||
|
|
||||||
|
_To Be Released..._
|
||||||
|
|
||||||
0.56, 2020-04-09
|
0.56, 2020-04-09
|
||||||
--------------
|
--------------
|
||||||
|
|
||||||
|
@@ -78,36 +78,6 @@ in the issue tracker.
|
|||||||
|
|
||||||
* You can install this file by selecting "Settings | Plugins | Install plugin
|
* You can install this file by selecting "Settings | Plugins | Install plugin
|
||||||
from disk...".
|
from disk...".
|
||||||
|
|
||||||
### Copyright
|
|
||||||
|
|
||||||
1. Go to `Preferences | Appearance & Behavior | Scopes`, press "+" button, `Shared`.
|
|
||||||
Name: Copyright scope
|
|
||||||
Pattern: `file[IdeaVIM.main]:com//*||file[IdeaVIM.test]:*/`
|
|
||||||
|
|
||||||
2. Go to `Preferences | Editor | Copyright | Copyright Profiles` and click the "+" button.
|
|
||||||
Name: IdeaVim
|
|
||||||
Text:
|
|
||||||
|
|
||||||
IdeaVim - Vim emulator for IDEs based on the IntelliJ platform
|
|
||||||
Copyright (C) 2003-$today.year The IdeaVim authors
|
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
3. Go to `Preferences | Editor | Copyright`, click the "+" button.
|
|
||||||
Scope: Copyright scope
|
|
||||||
Copyright: IdeaVim
|
|
||||||
|
|
||||||
### Testing
|
### Testing
|
||||||
|
|
||||||
|
119
README.md
119
README.md
@@ -25,23 +25,20 @@ Resources:
|
|||||||
* [@IdeaVim](https://twitter.com/ideavim) in Twitter
|
* [@IdeaVim](https://twitter.com/ideavim) in Twitter
|
||||||
|
|
||||||
|
|
||||||
Installation
|
Setup
|
||||||
------------
|
------------
|
||||||
|
|
||||||
Use the IDE's plugin manager to install the latest version of the plugin.
|
- IdeaVim can be installed via `Settings | Plugins`.
|
||||||
Start the IDE normally and enable the Vim emulation using "Tools | Vim
|
See [detailed instructions](https://www.jetbrains.com/help/idea/managing-plugins.html#).
|
||||||
Emulator" menu item. At this point you must use Vim keystrokes in all editors.
|
|
||||||
|
|
||||||
If you wish to disable the plugin, select the "Tools | Vim Emulator" menu so
|
- Use `Tools | Vim Emulator` to enable or disable emulation.
|
||||||
it is unchecked. At this point your IDE will work with its regular keyboard
|
|
||||||
shortcuts.
|
|
||||||
|
|
||||||
Keyboard shortcut conflicts between the Vim emulation and the IDE can be
|
- Use `~/.ideavimrc` file as an analog of `~/.vimrc` ([details](#Files)). XGD standard is supported as well.
|
||||||
resolved via "File | Settings | Editor | Vim Emulation", "File | Settings |
|
|
||||||
Keymap" on Linux & Windows, and via "Preferences | Editor | Vim Emulation",
|
|
||||||
"Preferences | Keymap" on macOS. They can also be resolved by key-mapping
|
|
||||||
commands in your ~/.ideavimrc file.
|
|
||||||
|
|
||||||
|
- Shortcut conflicts can be resolved using:
|
||||||
|
- Linux & Windows: `File | Settings | Editor | Vim Emulation` & `File | Settings | Keymap`,
|
||||||
|
- macOS: `Preferences | Editor | Vim Emulation` & `Preferences | Keymap`,
|
||||||
|
- regular vim mappings in the `~/.ideavimrc` file.
|
||||||
|
|
||||||
Get Early Access
|
Get Early Access
|
||||||
-------------------
|
-------------------
|
||||||
@@ -49,7 +46,9 @@ Get Early Access
|
|||||||
Would you like to try new features and fixes? Join the Early Access Program and
|
Would you like to try new features and fixes? Join the Early Access Program and
|
||||||
receive EAP builds as updates!
|
receive EAP builds as updates!
|
||||||
|
|
||||||
1. Click the IdeaVim icon in the status bar | `EAP` | `Get Early Access...`
|
1. Click the IdeaVim icon <img src="resources/META-INF/pluginIcon_noBorders.svg" width="16" height="16" alt="icon"/>
|
||||||
|
in the status bar | `EAP` | `Get Early Access...`
|
||||||
|
|
||||||
|
|
||||||
Or subscribe to EAP updates manually:
|
Or subscribe to EAP updates manually:
|
||||||
|
|
||||||
@@ -57,7 +56,7 @@ Or subscribe to EAP updates manually:
|
|||||||
2. Click the gear icon :gear:, select `Manage Plugin Repositories`, and add the following url:
|
2. Click the gear icon :gear:, select `Manage Plugin Repositories`, and add the following url:
|
||||||
`https://plugins.jetbrains.com/plugins/eap/ideavim`
|
`https://plugins.jetbrains.com/plugins/eap/ideavim`
|
||||||
|
|
||||||
See [the changelog](CHANGES.md) for the list of hot unreleased features.
|
See [the changelog](CHANGES.md) for the list of unreleased features.
|
||||||
|
|
||||||
It is important to distinguish EAP builds from traditional pre-release software.
|
It is important to distinguish EAP builds from traditional pre-release software.
|
||||||
Please note that the quality of EAP versions may at times be way below even
|
Please note that the quality of EAP versions may at times be way below even
|
||||||
@@ -91,7 +90,7 @@ Supported:
|
|||||||
* Vim web help
|
* Vim web help
|
||||||
* Select mode
|
* Select mode
|
||||||
|
|
||||||
Emulated Vim plugins:
|
[Emulated Vim plugins](doc/emulated-plugins.md):
|
||||||
|
|
||||||
* vim-easymotion
|
* vim-easymotion
|
||||||
* vim-surround
|
* vim-surround
|
||||||
@@ -115,19 +114,19 @@ See also:
|
|||||||
Files
|
Files
|
||||||
-----
|
-----
|
||||||
|
|
||||||
* ~/.ideavimrc
|
* `~/.ideavimrc`
|
||||||
* Your IdeaVim-specific Vim initialization commands
|
* Your IdeaVim-specific Vim initialization commands
|
||||||
|
|
||||||
You can read your ~/.vimrc file from ~/.ideavimrc with this command:
|
You can read your `~/.vimrc` file from `~/.ideavimrc` with this command:
|
||||||
|
|
||||||
source ~/.vimrc
|
source ~/.vimrc
|
||||||
|
|
||||||
Note, that IdeaVim currently parses ~/.ideavimrc file via simple pattern matching.
|
Note, that IdeaVim currently parses `~/.ideavimrc` file via simple pattern matching.
|
||||||
See [VIM-669](https://youtrack.jetbrains.com/issue/VIM-669) for proper parsing
|
See [VIM-669](https://youtrack.jetbrains.com/issue/VIM-669) for proper parsing
|
||||||
of VimL files.
|
of VimL files.
|
||||||
|
|
||||||
Also note that if you have overridden the `user.home` JVM option, this
|
Also note that if you have overridden the `user.home` JVM option, this
|
||||||
will affect where IdeaVim looks for your .ideavimrc file. For example, if you
|
will affect where IdeaVim looks for your `.ideavimrc` file. For example, if you
|
||||||
have `-Duser.home=/my/alternate/home` then IdeaVim will source
|
have `-Duser.home=/my/alternate/home` then IdeaVim will source
|
||||||
`/my/alternate/home/.ideavimrc` instead of `~/.ideavimrc`.
|
`/my/alternate/home/.ideavimrc` instead of `~/.ideavimrc`.
|
||||||
|
|
||||||
@@ -138,62 +137,25 @@ Put your settings to `$XDG_CONFIG_HOME$/ideavim/ideavimrc` file.
|
|||||||
Emulated Vim Plugins
|
Emulated Vim Plugins
|
||||||
--------------------
|
--------------------
|
||||||
|
|
||||||
IdeaVim extensions emulate some plugins of the original Vim. In order to use
|
See [doc/emulated-plugins.md](doc/emulated-plugins.md)
|
||||||
IdeaVim extensions, you have to enable them via this command in your `~/.ideavimrc`:
|
|
||||||
|
|
||||||
set <extension-name>
|
|
||||||
|
|
||||||
Available extensions:
|
|
||||||
|
|
||||||
* easymotion
|
|
||||||
* Setup:
|
|
||||||
* Install [IdeaVim-EasyMotion](https://plugins.jetbrains.com/plugin/13360-ideavim-easymotion/)
|
|
||||||
and [AceJump](https://plugins.jetbrains.com/plugin/7086-acejump/) plugins.
|
|
||||||
* `set easymotion`
|
|
||||||
* Emulates [vim-easymotion](https://github.com/easymotion/vim-easymotion)
|
|
||||||
* Commands: All commands with the mappings are supported. See the [full list of supported commands](https://github.com/AlexPl292/IdeaVim-EasyMotion#supported-commands).
|
|
||||||
|
|
||||||
* surround
|
|
||||||
* Setup: `set surround`
|
|
||||||
* Emulates [vim-surround](https://github.com/tpope/vim-surround)
|
|
||||||
* Commands: `ys`, `cs`, `ds`, `S`
|
|
||||||
|
|
||||||
* multiple-cursors
|
|
||||||
* Setup: `set multiple-cursors`
|
|
||||||
* Emulates [vim-multiple-cursors](https://github.com/terryma/vim-multiple-cursors)
|
|
||||||
* Commands: `<A-n>`, `<A-x>`, `<A-p>`, `g<A-n>`
|
|
||||||
|
|
||||||
* commentary
|
|
||||||
* Setup: `set commentary`
|
|
||||||
* Emulates [commentary.vim](https://github.com/tpope/vim-commentary)
|
|
||||||
* Commands: `gcc`, `gc + motion`, `v_gc`
|
|
||||||
|
|
||||||
* ReplaceWithRegister
|
|
||||||
* Setup: `set ReplaceWithRegister`
|
|
||||||
* Emulates [ReplaceWithRegister](https://github.com/vim-scripts/ReplaceWithRegister)
|
|
||||||
* Commands: `gr`, `grr`
|
|
||||||
|
|
||||||
* argtextobj
|
|
||||||
* Setup:
|
|
||||||
* `set argtextobj`
|
|
||||||
* By default, only the arguments inside parenthesis are considered. To extend the functionality
|
|
||||||
to other types of brackets, set `g:argtextobj_pairs` variable to a comma-separated
|
|
||||||
list of colon-separated pairs (same as VIM's `matchpairs` option), like
|
|
||||||
`let g:argtextobj_pairs="(:),{:},<:>"`. The order of pairs matters when
|
|
||||||
handling symbols that can also be operators: `func(x << 5, 20) >> 17`. To handle
|
|
||||||
this syntax parenthesis, must come before angle brackets in the list.
|
|
||||||
* Emulates [argtextobj.vim](https://www.vim.org/scripts/script.php?script_id=2699)
|
|
||||||
* Additional text objects: `aa`, `ia`
|
|
||||||
|
|
||||||
* textobj-entire
|
|
||||||
* Setup: `set textobj-entire`
|
|
||||||
* Emulates [vim-textobj-entire](https://github.com/kana/vim-textobj-entire)
|
|
||||||
* Additional text objects: `ae`, `ie`
|
|
||||||
|
|
||||||
|
|
||||||
Changes to the IDE
|
Changes to the IDE
|
||||||
------------------
|
------------------
|
||||||
|
|
||||||
|
### Executing IDE Actions
|
||||||
|
|
||||||
|
IdeaVim adds two commands for listing and executing arbitrary IDE actions as
|
||||||
|
Ex commands or via `:map` command mappings:
|
||||||
|
|
||||||
|
* `:actionlist [pattern]`
|
||||||
|
* Find IDE actions by name or keymap pattern (E.g. `:actionlist extract`, `:actionlist <C-D`)
|
||||||
|
* `:action {name}`
|
||||||
|
* Execute an action named `NAME`
|
||||||
|
|
||||||
|
For example, here `\r` is mapped to the Reformat Code action:
|
||||||
|
|
||||||
|
:map \r :action ReformatCode<CR>
|
||||||
|
|
||||||
### Undo/Redo
|
### Undo/Redo
|
||||||
|
|
||||||
The IdeaVim plugin uses the undo/redo functionality of the IntelliJ Platform,
|
The IdeaVim plugin uses the undo/redo functionality of the IntelliJ Platform,
|
||||||
@@ -212,21 +174,6 @@ improvement.
|
|||||||
|
|
||||||
See also [unresolved escape issues](https://youtrack.jetbrains.com/issues/VIM?q=%23Unresolved+Help+topic%3A+i_Esc).
|
See also [unresolved escape issues](https://youtrack.jetbrains.com/issues/VIM?q=%23Unresolved+Help+topic%3A+i_Esc).
|
||||||
|
|
||||||
### Executing IDE Actions
|
|
||||||
|
|
||||||
IdeaVim adds two commands for listing and executing arbitrary IDE actions as
|
|
||||||
Ex commands or via `:map` command mappings:
|
|
||||||
|
|
||||||
* `:actionlist [pattern]`
|
|
||||||
* Find IDE actions by name or keymap pattern (E.g. `:actionlist extract`, `:actionlist <C-D`)
|
|
||||||
* `:action {name}`
|
|
||||||
* Execute an action named `NAME`
|
|
||||||
|
|
||||||
For example, here `\r` is mapped to the Reformat Code action:
|
|
||||||
|
|
||||||
:map \r :action ReformatCode<CR>
|
|
||||||
|
|
||||||
|
|
||||||
Contributing
|
Contributing
|
||||||
------------
|
------------
|
||||||
|
|
||||||
|
@@ -9,7 +9,7 @@ buildscript {
|
|||||||
}
|
}
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
id 'org.jetbrains.intellij' version '0.4.16'
|
id 'org.jetbrains.intellij' version '0.4.18'
|
||||||
}
|
}
|
||||||
|
|
||||||
apply plugin: 'java'
|
apply plugin: 'java'
|
||||||
@@ -80,13 +80,13 @@ tasks.register("slackEapNotification") {
|
|||||||
changeLog = changeLog.replaceAll("\\[(.+)]\\(([^)]+)\\)", '<$2|$1>') // Enable links
|
changeLog = changeLog.replaceAll("\\[(.+)]\\(([^)]+)\\)", '<$2|$1>') // Enable links
|
||||||
def message ="""
|
def message ="""
|
||||||
{
|
{
|
||||||
"text": "Danny Torrence left a 1 star review for your property.",
|
"text": "New version of IdeaVim",
|
||||||
"blocks": [
|
"blocks": [
|
||||||
{
|
{
|
||||||
"type": "section",
|
"type": "section",
|
||||||
"text": {
|
"text": {
|
||||||
"type": "mrkdwn",
|
"type": "mrkdwn",
|
||||||
"text": "New EAP released: $version\\n$changeLog"
|
"text": "IdeaVim EAP $version has been relesed\\n$changeLog"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
62
doc/emulated-plugins.md
Normal file
62
doc/emulated-plugins.md
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
Emulated Vim Plugins
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
IdeaVim extensions emulate plugins of the original Vim. In order to use
|
||||||
|
IdeaVim extensions, you have to enable them via this command in your `~/.ideavimrc`:
|
||||||
|
|
||||||
|
set <extension-name>
|
||||||
|
|
||||||
|
Available extensions:
|
||||||
|
|
||||||
|
## easymotion
|
||||||
|
|
||||||
|
* Setup:
|
||||||
|
* Install [IdeaVim-EasyMotion](https://plugins.jetbrains.com/plugin/13360-ideavim-easymotion/)
|
||||||
|
and [AceJump](https://plugins.jetbrains.com/plugin/7086-acejump/) plugins.
|
||||||
|
* `set easymotion`
|
||||||
|
* Emulates [vim-easymotion](https://github.com/easymotion/vim-easymotion)
|
||||||
|
* Commands: All commands with the mappings are supported. See the [full list of supported commands](https://github.com/AlexPl292/IdeaVim-EasyMotion#supported-commands).
|
||||||
|
|
||||||
|
## surround
|
||||||
|
|
||||||
|
* Setup: `set surround`
|
||||||
|
* Emulates [vim-surround](https://github.com/tpope/vim-surround)
|
||||||
|
* Commands: `ys`, `cs`, `ds`, `S`
|
||||||
|
|
||||||
|
## multiple-cursors
|
||||||
|
|
||||||
|
* Setup: `set multiple-cursors`
|
||||||
|
* Emulates [vim-multiple-cursors](https://github.com/terryma/vim-multiple-cursors)
|
||||||
|
* Commands: `<A-n>`, `<A-x>`, `<A-p>`, `g<A-n>`
|
||||||
|
|
||||||
|
## commentary
|
||||||
|
|
||||||
|
* Setup: `set commentary`
|
||||||
|
* Emulates [commentary.vim](https://github.com/tpope/vim-commentary)
|
||||||
|
* Commands: `gcc`, `gc + motion`, `v_gc`
|
||||||
|
|
||||||
|
## ReplaceWithRegister
|
||||||
|
|
||||||
|
* Setup: `set ReplaceWithRegister`
|
||||||
|
* Emulates [ReplaceWithRegister](https://github.com/vim-scripts/ReplaceWithRegister)
|
||||||
|
* Commands: `gr`, `grr`
|
||||||
|
|
||||||
|
## argtextobj
|
||||||
|
|
||||||
|
* Setup:
|
||||||
|
* `set argtextobj`
|
||||||
|
* By default, only the arguments inside parenthesis are considered. To extend the functionality
|
||||||
|
to other types of brackets, set `g:argtextobj_pairs` variable to a comma-separated
|
||||||
|
list of colon-separated pairs (same as VIM's `matchpairs` option), like
|
||||||
|
`let g:argtextobj_pairs="(:),{:},<:>"`. The order of pairs matters when
|
||||||
|
handling symbols that can also be operators: `func(x << 5, 20) >> 17`. To handle
|
||||||
|
this syntax parenthesis, must come before angle brackets in the list.
|
||||||
|
* Emulates [argtextobj.vim](https://www.vim.org/scripts/script.php?script_id=2699)
|
||||||
|
* Additional text objects: `aa`, `ia`
|
||||||
|
|
||||||
|
## textobj-entire
|
||||||
|
|
||||||
|
* Setup: `set textobj-entire`
|
||||||
|
* Emulates [vim-textobj-entire](https://github.com/kana/vim-textobj-entire)
|
||||||
|
* Additional text objects: `ae`, `ie`
|
||||||
|
|
@@ -1,11 +1,11 @@
|
|||||||
# suppress inspection "UnusedProperty" for whole file
|
# suppress inspection "UnusedProperty" for whole file
|
||||||
|
|
||||||
ideaVersion=201-EAP-SNAPSHOT
|
ideaVersion=2020.1
|
||||||
downloadIdeaSources=true
|
downloadIdeaSources=true
|
||||||
instrumentPluginCode=true
|
instrumentPluginCode=true
|
||||||
version=SNAPSHOT
|
version=SNAPSHOT
|
||||||
javaVersion=1.8
|
javaVersion=1.8
|
||||||
kotlinVersion=1.3.70
|
kotlinVersion=1.3.71
|
||||||
publishUsername=username
|
publishUsername=username
|
||||||
publishToken=token
|
publishToken=token
|
||||||
publishChannels=eap
|
publishChannels=eap
|
||||||
|
4
gradle/wrapper/gradle-wrapper.properties
vendored
4
gradle/wrapper/gradle-wrapper.properties
vendored
@@ -1,5 +1,5 @@
|
|||||||
#Fri Mar 20 11:41:45 MSK 2020
|
#Fri Apr 10 10:57:10 MSK 2020
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.2.1-all.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-6.3-all.zip
|
||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
|
@@ -3,12 +3,8 @@
|
|||||||
<id>IdeaVIM</id>
|
<id>IdeaVIM</id>
|
||||||
<change-notes><![CDATA[
|
<change-notes><![CDATA[
|
||||||
<ul>
|
<ul>
|
||||||
<li>Support ReplaceWithRegister plugin emulation</li>
|
<li>Fix mappings for `<S-Letter>`</li>
|
||||||
<li>Support argtextobj.vim plugin emulation</li>
|
<li>Fix yank/paste with number registers</li>
|
||||||
<li>Support vim-textobj-entire plugin emulation</li>
|
|
||||||
<li>Support showcmd command</li>
|
|
||||||
<li>Support ls/buffers/files command</li>
|
|
||||||
<li>Control the icon in the status bar using an `ideastatusicon` option</li>
|
|
||||||
<li>Various bug fixes</li>
|
<li>Various bug fixes</li>
|
||||||
</ul>
|
</ul>
|
||||||
<p>See also the complete <a href="https://github.com/JetBrains/ideavim/blob/master/CHANGES.md">changelog</a>.</p>
|
<p>See also the complete <a href="https://github.com/JetBrains/ideavim/blob/master/CHANGES.md">changelog</a>.</p>
|
||||||
|
9
resources/META-INF/pluginIcon_noBorders.svg
Normal file
9
resources/META-INF/pluginIcon_noBorders.svg
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="0 0 40 40">
|
||||||
|
<defs>
|
||||||
|
<linearGradient id="ideavim_plugin-a" x1="-6.748%" x2="47.286%" y1="33.61%" y2="85.907%">
|
||||||
|
<stop offset="0%" stop-color="#3BEA62"/>
|
||||||
|
<stop offset="100%" stop-color="#087CFA"/>
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
<polygon fill="url(#ideavim_plugin-a)" fill-rule="evenodd" points="29.019 0 13.988 26.119 13.988 0 0 0 0 40 16.953 40 40 0"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 450 B |
@@ -563,7 +563,9 @@ public class KeyHandler {
|
|||||||
private boolean isCommandCountKey(char chKey, @NotNull CommandState editorState) {
|
private boolean isCommandCountKey(char chKey, @NotNull CommandState editorState) {
|
||||||
// Make sure to avoid handling '0' as the start of a count.
|
// Make sure to avoid handling '0' as the start of a count.
|
||||||
final CommandBuilder commandBuilder = editorState.getCommandBuilder();
|
final CommandBuilder commandBuilder = editorState.getCommandBuilder();
|
||||||
return (editorState.getMode() == CommandState.Mode.COMMAND || editorState.getMode() == CommandState.Mode.VISUAL)
|
return ((editorState.getMode() == CommandState.Mode.COMMAND
|
||||||
|
&&editorState.getSubMode()!=CommandState.SubMode.REGISTER_PENDING)
|
||||||
|
|| editorState.getMode() == CommandState.Mode.VISUAL)
|
||||||
&& commandBuilder.isExpectingCount() && Character.isDigit(chKey) && (commandBuilder.getCount() > 0 || chKey != '0');
|
&& commandBuilder.isExpectingCount() && Character.isDigit(chKey) && (commandBuilder.getCount() > 0 || chKey != '0');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -29,17 +29,35 @@ import com.maddyhome.idea.vim.command.Command
|
|||||||
import com.maddyhome.idea.vim.helper.vimChangeActionSwitchMode
|
import com.maddyhome.idea.vim.helper.vimChangeActionSwitchMode
|
||||||
import com.maddyhome.idea.vim.helper.vimLastColumn
|
import com.maddyhome.idea.vim.helper.vimLastColumn
|
||||||
|
|
||||||
sealed class ChangeEditorActionHandler : VimActionHandler.SingleExecution() {
|
/**
|
||||||
|
* Base handler for commands that performs change actions.
|
||||||
|
* This handler stores the commands and they can be repeated later with dot command.
|
||||||
|
*
|
||||||
|
* Use subclasses of this handler:
|
||||||
|
* - [ChangeEditorActionHandler.SingleExecution]
|
||||||
|
* - [ChangeEditorActionHandler.ForEachCaret]
|
||||||
|
*/
|
||||||
|
sealed class ChangeEditorActionHandler : EditorActionHandlerBase(false) {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This handler executes an action for each caret. That means that if you have 5 carets, [execute] will be
|
||||||
|
* called 5 times.
|
||||||
|
* @see [ChangeEditorActionHandler.SingleExecution] for only one execution.
|
||||||
|
*/
|
||||||
abstract class ForEachCaret : ChangeEditorActionHandler() {
|
abstract class ForEachCaret : ChangeEditorActionHandler() {
|
||||||
abstract fun execute(editor: Editor, caret: Caret, context: DataContext, count: Int, rawCount: Int, argument: Argument?): Boolean
|
abstract fun execute(editor: Editor, caret: Caret, context: DataContext, count: Int, rawCount: Int, argument: Argument?): Boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This handler executes an action only once for all carets. That means that if you have 5 carets,
|
||||||
|
* [execute] will be called 1 time.
|
||||||
|
* @see [ChangeEditorActionHandler.ForEachCaret] for per-caret execution
|
||||||
|
*/
|
||||||
abstract class SingleExecution : ChangeEditorActionHandler() {
|
abstract class SingleExecution : ChangeEditorActionHandler() {
|
||||||
abstract fun execute(editor: Editor, context: DataContext, count: Int, rawCount: Int, argument: Argument?): Boolean
|
abstract fun execute(editor: Editor, context: DataContext, count: Int, rawCount: Int, argument: Argument?): Boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
final override fun execute(editor: Editor, context: DataContext, cmd: Command): Boolean {
|
final override fun baseExecute(editor: Editor, caret: Caret, context: DataContext, cmd: Command): Boolean {
|
||||||
// Here we have to save the last changed command. This should be done separately for each
|
// Here we have to save the last changed command. This should be done separately for each
|
||||||
// call of the task, not for each caret. Currently there is no way to schedule any action
|
// call of the task, not for each caret. Currently there is no way to schedule any action
|
||||||
// to be worked after each task. So here we override the deprecated execute function which
|
// to be worked after each task. So here we override the deprecated execute function which
|
||||||
@@ -50,9 +68,9 @@ sealed class ChangeEditorActionHandler : VimActionHandler.SingleExecution() {
|
|||||||
val worked = Ref.create(true)
|
val worked = Ref.create(true)
|
||||||
when (this) {
|
when (this) {
|
||||||
is ForEachCaret -> {
|
is ForEachCaret -> {
|
||||||
editor.caretModel.runForEachCaret({ caret ->
|
editor.caretModel.runForEachCaret({ current ->
|
||||||
if (!caret.isValid) return@runForEachCaret
|
if (!current.isValid) return@runForEachCaret
|
||||||
if (!execute(editor, caret, context, cmd.count, cmd.rawCount, cmd.argument)) {
|
if (!execute(editor, current, context, cmd.count, cmd.rawCount, cmd.argument)) {
|
||||||
worked.set(false)
|
worked.set(false)
|
||||||
}
|
}
|
||||||
}, true)
|
}, true)
|
||||||
|
@@ -36,52 +36,22 @@ import java.util.*
|
|||||||
import javax.swing.KeyStroke
|
import javax.swing.KeyStroke
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Structure of handlers
|
* All the commands in IdeaVim should implement one of the following handlers and be registered in VimActions.xml
|
||||||
* `~` - this symbol means that this handler cannot be used directly (only its children)
|
* Check the KtDocs of handlers for the details.
|
||||||
* Almost each handler isn't usable by itself and has two children - "SingleExecution" and "ForEachCaret"
|
|
||||||
* which should be used
|
|
||||||
*
|
*
|
||||||
* ~ EditorActionHandlerBase ~
|
* Structure of handlers:
|
||||||
* |
|
|
||||||
* ----------------------------------------------------------------------------
|
|
||||||
* | | |
|
|
||||||
* ~ ForEachCaret ~ ~ SingleExecution ~ ~ VimActionHandler ~
|
|
||||||
* | | / \
|
|
||||||
* TextObjectActionHandler MotionActionHandler / \
|
|
||||||
* SingleExecution ForEachCaret
|
|
||||||
* |
|
|
||||||
* -------------------------------------------------------------
|
|
||||||
* | |
|
|
||||||
* ~ ChangeEditorActionHandler ~ ~ VisualOperatorActionHandler ~
|
|
||||||
* / \ / \
|
|
||||||
* SingleExecution ForEachCaret SingleExecution ForEachCaret
|
|
||||||
*
|
*
|
||||||
|
* - [EditorActionHandlerBase]: Base handler for all handlers. Please don't use it directly.
|
||||||
|
* - [VimActionHandler]: .............. Common vim commands.. E.g.: u, <C-W>s, <C-D>.
|
||||||
|
* - [TextObjectActionHandler]: ....... Text objects. ....... E.g.: iw, a(, i>
|
||||||
|
* - [MotionActionHandler]: ........... Motion commands. .... E.g.: k, w, <Up>
|
||||||
|
* - [ChangeEditorActionHandler]: ..... Change commands. .... E.g.: s, r, gU
|
||||||
|
* - [VisualOperatorActionHandler]: ... Visual commands.
|
||||||
*
|
*
|
||||||
* SpecialKeyHandlers are not presented here because these handlers are created to a limited set of commands and they
|
* SpecialKeyHandlers are not presented here because these handlers are created to a limited set of commands and they
|
||||||
* are already implemented
|
* are already implemented.
|
||||||
*/
|
*/
|
||||||
|
abstract class EditorActionHandlerBase(private val myRunForEachCaret: Boolean) {
|
||||||
/**
|
|
||||||
* Handler for common usage
|
|
||||||
*/
|
|
||||||
sealed class VimActionHandler(myRunForEachCaret: Boolean) : EditorActionHandlerBase(myRunForEachCaret) {
|
|
||||||
abstract class ForEachCaret : VimActionHandler(true) {
|
|
||||||
abstract fun execute(editor: Editor, caret: Caret, context: DataContext, cmd: Command): Boolean
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract class SingleExecution : VimActionHandler(false) {
|
|
||||||
abstract fun execute(editor: Editor, context: DataContext, cmd: Command): Boolean
|
|
||||||
}
|
|
||||||
|
|
||||||
final override fun baseExecute(editor: Editor, caret: Caret?, context: DataContext, cmd: Command): Boolean {
|
|
||||||
return when (this) {
|
|
||||||
is ForEachCaret -> caret == null || execute(editor, caret, context, cmd)
|
|
||||||
is SingleExecution -> execute(editor, context, cmd)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sealed class EditorActionHandlerBase(private val myRunForEachCaret: Boolean) {
|
|
||||||
val id: String = getActionId(this::class.java.name)
|
val id: String = getActionId(this::class.java.name)
|
||||||
|
|
||||||
abstract val type: Command.Type
|
abstract val type: Command.Type
|
||||||
@@ -97,25 +67,7 @@ sealed class EditorActionHandlerBase(private val myRunForEachCaret: Boolean) {
|
|||||||
*/
|
*/
|
||||||
open val flags: EnumSet<CommandFlags> = noneOfEnum()
|
open val flags: EnumSet<CommandFlags> = noneOfEnum()
|
||||||
|
|
||||||
|
abstract fun baseExecute(editor: Editor, caret: Caret, context: DataContext, cmd: Command): Boolean
|
||||||
abstract class ForEachCaret : EditorActionHandlerBase(true) {
|
|
||||||
abstract fun execute(editor: Editor, caret: Caret, context: DataContext, cmd: Command): Boolean
|
|
||||||
|
|
||||||
final override fun baseExecute(editor: Editor, caret: Caret?, context: DataContext, cmd: Command): Boolean {
|
|
||||||
if (caret == null) return false
|
|
||||||
return execute(editor, caret, context, cmd)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract class SingleExecution : EditorActionHandlerBase(false) {
|
|
||||||
abstract fun execute(editor: Editor, context: DataContext, cmd: Command): Boolean
|
|
||||||
|
|
||||||
final override fun baseExecute(editor: Editor, caret: Caret?, context: DataContext, cmd: Command): Boolean {
|
|
||||||
return execute(editor, context, cmd)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract fun baseExecute(editor: Editor, caret: Caret?, context: DataContext, cmd: Command): Boolean
|
|
||||||
|
|
||||||
fun execute(editor: Editor, context: DataContext) {
|
fun execute(editor: Editor, context: DataContext) {
|
||||||
val hostEditor: Editor = CommonDataKeys.HOST_EDITOR.getData(context) ?: editor
|
val hostEditor: Editor = CommonDataKeys.HOST_EDITOR.getData(context) ?: editor
|
||||||
|
@@ -42,7 +42,7 @@ import com.maddyhome.idea.vim.helper.vimSelectionStart
|
|||||||
* Base class for motion handlers.
|
* Base class for motion handlers.
|
||||||
* @see [MotionActionHandler.SingleExecution] and [MotionActionHandler.ForEachCaret]
|
* @see [MotionActionHandler.SingleExecution] and [MotionActionHandler.ForEachCaret]
|
||||||
*/
|
*/
|
||||||
sealed class MotionActionHandler : EditorActionHandlerBase.SingleExecution() {
|
sealed class MotionActionHandler : EditorActionHandlerBase(false) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base class for motion handlers.
|
* Base class for motion handlers.
|
||||||
@@ -127,7 +127,7 @@ sealed class MotionActionHandler : EditorActionHandlerBase.SingleExecution() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final override fun execute(editor: Editor, context: DataContext, cmd: Command): Boolean {
|
final override fun baseExecute(editor: Editor, caret: Caret, context: DataContext, cmd: Command): Boolean {
|
||||||
val blockSubmodeActive = editor.inBlockSubMode
|
val blockSubmodeActive = editor.inBlockSubMode
|
||||||
|
|
||||||
when (this) {
|
when (this) {
|
||||||
|
@@ -41,10 +41,16 @@ import com.maddyhome.idea.vim.helper.vimSelectionStart
|
|||||||
*
|
*
|
||||||
* This handler gets executed for each caret.
|
* This handler gets executed for each caret.
|
||||||
*/
|
*/
|
||||||
abstract class TextObjectActionHandler : EditorActionHandlerBase.ForEachCaret() {
|
abstract class TextObjectActionHandler : EditorActionHandlerBase(true) {
|
||||||
|
|
||||||
final override val type: Command.Type = Command.Type.MOTION
|
final override val type: Command.Type = Command.Type.MOTION
|
||||||
|
|
||||||
abstract fun getRange(editor: Editor, caret: Caret, context: DataContext, count: Int, rawCount: Int, argument: Argument?): TextRange?
|
abstract fun getRange(editor: Editor, caret: Caret, context: DataContext, count: Int, rawCount: Int, argument: Argument?): TextRange?
|
||||||
override fun execute(editor: Editor, caret: Caret, context: DataContext, cmd: Command): Boolean {
|
|
||||||
|
/**
|
||||||
|
* This code is called when user executes text object in visual mode. E.g. `va(a(a(`
|
||||||
|
*/
|
||||||
|
final override fun baseExecute(editor: Editor, caret: Caret, context: DataContext, cmd: Command): Boolean {
|
||||||
if (!editor.inVisualMode) return true
|
if (!editor.inVisualMode) return true
|
||||||
|
|
||||||
val range = getRange(editor, caret, context, cmd.count, cmd.rawCount, cmd.argument) ?: return false
|
val range = getRange(editor, caret, context, cmd.count, cmd.rawCount, cmd.argument) ?: return false
|
||||||
|
58
src/com/maddyhome/idea/vim/handler/VimActionHandler.kt
Normal file
58
src/com/maddyhome/idea/vim/handler/VimActionHandler.kt
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
* IdeaVim - Vim emulator for IDEs based on the IntelliJ platform
|
||||||
|
* Copyright (C) 2003-2020 The IdeaVim authors
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.maddyhome.idea.vim.handler
|
||||||
|
|
||||||
|
import com.intellij.openapi.actionSystem.DataContext
|
||||||
|
import com.intellij.openapi.editor.Caret
|
||||||
|
import com.intellij.openapi.editor.Editor
|
||||||
|
import com.maddyhome.idea.vim.command.Command
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handler for common usage.
|
||||||
|
*
|
||||||
|
* Use subclasses of this handler:
|
||||||
|
* - [VimActionHandler.SingleExecution]
|
||||||
|
* - [VimActionHandler.ForEachCaret]
|
||||||
|
*/
|
||||||
|
sealed class VimActionHandler(myRunForEachCaret: Boolean) : EditorActionHandlerBase(myRunForEachCaret) {
|
||||||
|
/**
|
||||||
|
* This handler executes an action for each caret. That means that if you have 5 carets,
|
||||||
|
* [execute] will be called 5 times.
|
||||||
|
* @see [VimActionHandler.SingleExecution] for only one execution.
|
||||||
|
*/
|
||||||
|
abstract class ForEachCaret : VimActionHandler(true) {
|
||||||
|
abstract fun execute(editor: Editor, caret: Caret, context: DataContext, cmd: Command): Boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This handler executes an action only once for all carets. That means that if you have 5 carets,
|
||||||
|
* [execute] will be called 1 time.
|
||||||
|
* @see [VimActionHandler.ForEachCaret] for per-caret execution.
|
||||||
|
*/
|
||||||
|
abstract class SingleExecution : VimActionHandler(false) {
|
||||||
|
abstract fun execute(editor: Editor, context: DataContext, cmd: Command): Boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
final override fun baseExecute(editor: Editor, caret: Caret, context: DataContext, cmd: Command): Boolean {
|
||||||
|
return when (this) {
|
||||||
|
is ForEachCaret -> execute(editor, caret, context, cmd)
|
||||||
|
is SingleExecution -> execute(editor, context, cmd)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -52,14 +52,17 @@ import com.maddyhome.idea.vim.helper.vimSelectionStart
|
|||||||
* @author Alex Plate
|
* @author Alex Plate
|
||||||
*
|
*
|
||||||
* Base class for visual operation handlers.
|
* Base class for visual operation handlers.
|
||||||
* @see [VisualOperatorActionHandler.SingleExecution] and [VisualOperatorActionHandler.ForEachCaret]
|
*
|
||||||
|
* Use subclasses of this handler:
|
||||||
|
* - [VisualOperatorActionHandler.SingleExecution]
|
||||||
|
* - [VisualOperatorActionHandler.ForEachCaret]
|
||||||
*/
|
*/
|
||||||
sealed class VisualOperatorActionHandler : VimActionHandler.SingleExecution() {
|
sealed class VisualOperatorActionHandler : EditorActionHandlerBase(false) {
|
||||||
/**
|
/**
|
||||||
* Base class for visual operation handlers.
|
* Base class for visual operation handlers.
|
||||||
* This handler executes an action for each caret. That means that if you have 5 carets,
|
* This handler executes an action for each caret. That means that if you have 5 carets,
|
||||||
* [executeAction] will be called 5 times.
|
* [executeAction] will be called 5 times.
|
||||||
* @see [VisualOperatorActionHandler.SingleExecution] for only one execution
|
* @see [VisualOperatorActionHandler.SingleExecution] for only one execution.
|
||||||
*/
|
*/
|
||||||
abstract class ForEachCaret : VisualOperatorActionHandler() {
|
abstract class ForEachCaret : VisualOperatorActionHandler() {
|
||||||
|
|
||||||
@@ -90,7 +93,7 @@ sealed class VisualOperatorActionHandler : VimActionHandler.SingleExecution() {
|
|||||||
/**
|
/**
|
||||||
* Base class for visual operation handlers.
|
* Base class for visual operation handlers.
|
||||||
* This handler executes an action only once for all carets. That means that if you have 5 carets,
|
* This handler executes an action only once for all carets. That means that if you have 5 carets,
|
||||||
* [executeAction] will be called 1 time.
|
* [executeForAllCarets] will be called 1 time.
|
||||||
* @see [VisualOperatorActionHandler.ForEachCaret] for per-caret execution
|
* @see [VisualOperatorActionHandler.ForEachCaret] for per-caret execution
|
||||||
*/
|
*/
|
||||||
abstract class SingleExecution : VisualOperatorActionHandler() {
|
abstract class SingleExecution : VisualOperatorActionHandler() {
|
||||||
@@ -104,7 +107,7 @@ sealed class VisualOperatorActionHandler : VimActionHandler.SingleExecution() {
|
|||||||
abstract fun executeForAllCarets(editor: Editor, context: DataContext, cmd: Command, caretsAndSelections: Map<Caret, VimSelection>): Boolean
|
abstract fun executeForAllCarets(editor: Editor, context: DataContext, cmd: Command, caretsAndSelections: Map<Caret, VimSelection>): Boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
final override fun execute(editor: Editor, context: DataContext, cmd: Command): Boolean {
|
final override fun baseExecute(editor: Editor, caret: Caret, context: DataContext, cmd: Command): Boolean {
|
||||||
logger.info("Execute visual command $cmd")
|
logger.info("Execute visual command $cmd")
|
||||||
|
|
||||||
editor.vimChangeActionSwitchMode = null
|
editor.vimChangeActionSwitchMode = null
|
||||||
@@ -131,9 +134,9 @@ sealed class VisualOperatorActionHandler : VimActionHandler.SingleExecution() {
|
|||||||
when {
|
when {
|
||||||
selections.keys.isEmpty() -> return false
|
selections.keys.isEmpty() -> return false
|
||||||
selections.keys.size == 1 -> res.set(executeAction(editor, selections.keys.first(), context, cmd, selections.values.first()))
|
selections.keys.size == 1 -> res.set(executeAction(editor, selections.keys.first(), context, cmd, selections.values.first()))
|
||||||
else -> editor.caretModel.runForEachCaret({ caret ->
|
else -> editor.caretModel.runForEachCaret({ currentCaret ->
|
||||||
val range = selections.getValue(caret)
|
val range = selections.getValue(currentCaret)
|
||||||
val loopRes = executeAction(editor, caret, context, cmd, range)
|
val loopRes = executeAction(editor, currentCaret, context, cmd, range)
|
||||||
res.set(loopRes and res.get())
|
res.set(loopRes and res.get())
|
||||||
}, true)
|
}, true)
|
||||||
}
|
}
|
||||||
|
@@ -535,8 +535,8 @@ public class StringHelper {
|
|||||||
if (modifiers == 0) {
|
if (modifiers == 0) {
|
||||||
return getKeyStroke(c);
|
return getKeyStroke(c);
|
||||||
}
|
}
|
||||||
else if (modifiers == SHIFT_DOWN_MASK) {
|
else if (modifiers == SHIFT_DOWN_MASK && Character.isLetter(c)) {
|
||||||
return getKeyStroke(Character.toUpperCase(c), modifiers);
|
return getKeyStroke(Character.toUpperCase(c));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return getKeyStroke(Character.toUpperCase(c), modifiers);
|
return getKeyStroke(Character.toUpperCase(c), modifiers);
|
||||||
|
@@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* IdeaVim - Vim emulator for IDEs based on the IntelliJ platform
|
||||||
|
* Copyright (C) 2003-2020 The IdeaVim authors
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.plugins.ideavim.action.copy
|
||||||
|
|
||||||
|
import com.maddyhome.idea.vim.VimPlugin
|
||||||
|
import com.maddyhome.idea.vim.command.CommandState
|
||||||
|
import com.maddyhome.idea.vim.command.SelectionType
|
||||||
|
import com.maddyhome.idea.vim.common.Register
|
||||||
|
import com.maddyhome.idea.vim.helper.StringHelper.parseKeys
|
||||||
|
import org.jetbrains.plugins.ideavim.VimTestCase
|
||||||
|
|
||||||
|
class PutTestAfterCursorActionTest : VimTestCase() {
|
||||||
|
fun `test put from number register`() {
|
||||||
|
VimPlugin.getRegister().saveRegister('4', Register('4', SelectionType.CHARACTER_WISE, "XXX ", ArrayList()))
|
||||||
|
doTest(parseKeys("\"4p"), "This is my${c} text", "This is my XXX${c} text", CommandState.Mode.COMMAND, CommandState.SubMode.NONE)
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
* IdeaVim - Vim emulator for IDEs based on the IntelliJ platform
|
||||||
|
* Copyright (C) 2003-2020 The IdeaVim authors
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.plugins.ideavim.action.copy
|
||||||
|
|
||||||
|
import com.maddyhome.idea.vim.VimPlugin
|
||||||
|
import com.maddyhome.idea.vim.helper.StringHelper.parseKeys
|
||||||
|
import junit.framework.Assert
|
||||||
|
import org.jetbrains.plugins.ideavim.VimTestCase
|
||||||
|
|
||||||
|
class YankLineActionTest : VimTestCase() {
|
||||||
|
fun `test yank to number register`() {
|
||||||
|
val before = """
|
||||||
|
${c}I found it in a legendary land
|
||||||
|
all rocks and lavender and tufted grass,
|
||||||
|
""".trimIndent()
|
||||||
|
configureByText(before)
|
||||||
|
typeText(parseKeys("\"4yy"))
|
||||||
|
val register = VimPlugin.getRegister().getRegister('4')!!
|
||||||
|
Assert.assertEquals("I found it in a legendary land\n", register.text)
|
||||||
|
}
|
||||||
|
}
|
@@ -1,379 +0,0 @@
|
|||||||
/*
|
|
||||||
* IdeaVim - Vim emulator for IDEs based on the IntelliJ platform
|
|
||||||
* Copyright (C) 2003-2020 The IdeaVim authors
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 2 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.jetbrains.plugins.ideavim.ex.handler;
|
|
||||||
|
|
||||||
import com.maddyhome.idea.vim.command.CommandState;
|
|
||||||
import com.maddyhome.idea.vim.ex.vimscript.VimScriptParser;
|
|
||||||
import org.jetbrains.plugins.ideavim.VimTestCase;
|
|
||||||
|
|
||||||
import static com.maddyhome.idea.vim.helper.StringHelper.parseKeys;
|
|
||||||
import static com.maddyhome.idea.vim.helper.StringHelper.stringToKeys;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author vlan
|
|
||||||
*/
|
|
||||||
public class MapCommandTest extends VimTestCase {
|
|
||||||
public void testMapKtoJ() {
|
|
||||||
configureByText("<caret>foo\n" +
|
|
||||||
"bar\n");
|
|
||||||
typeText(commandToKeys("nmap k j"));
|
|
||||||
assertPluginError(false);
|
|
||||||
assertOffset(0);
|
|
||||||
typeText(parseKeys("k"));
|
|
||||||
assertOffset(4);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testInsertMapJKtoEsc() {
|
|
||||||
configureByText("<caret>World!\n");
|
|
||||||
typeText(commandToKeys("imap jk <Esc>"));
|
|
||||||
assertPluginError(false);
|
|
||||||
typeText(parseKeys("i", "Hello, ", "jk"));
|
|
||||||
myFixture.checkResult("Hello, World!\n");
|
|
||||||
assertMode(CommandState.Mode.COMMAND);
|
|
||||||
assertOffset(6);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testBackslashEscape() {
|
|
||||||
configureByText("\n");
|
|
||||||
typeText(commandToKeys("imap \\\\,\\<,\\n foo"));
|
|
||||||
assertPluginError(false);
|
|
||||||
typeText(stringToKeys("i\\,<,\\n"));
|
|
||||||
myFixture.checkResult("foo\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testBackslashAtEnd() {
|
|
||||||
configureByText("\n");
|
|
||||||
typeText(commandToKeys("imap foo\\ bar"));
|
|
||||||
assertPluginError(false);
|
|
||||||
typeText(stringToKeys("ifoo\\"));
|
|
||||||
myFixture.checkResult("bar\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testUnfinishedSpecialKey() {
|
|
||||||
configureByText("\n");
|
|
||||||
typeText(commandToKeys("imap <Esc foo"));
|
|
||||||
typeText(stringToKeys("i<Esc"));
|
|
||||||
myFixture.checkResult("foo\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testUnknownSpecialKey() {
|
|
||||||
configureByText("\n");
|
|
||||||
typeText(commandToKeys("imap <foo> bar"));
|
|
||||||
typeText(stringToKeys("i<foo>"));
|
|
||||||
myFixture.checkResult("bar\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testMapTable() {
|
|
||||||
configureByText("\n");
|
|
||||||
typeText(commandToKeys("map <C-Down> gt"));
|
|
||||||
typeText(commandToKeys("imap foo bar"));
|
|
||||||
typeText(commandToKeys("imap bar <Esc>"));
|
|
||||||
typeText(commandToKeys("imap <C-Down> <C-O>gt"));
|
|
||||||
typeText(commandToKeys("nmap ,f <Plug>Foo"));
|
|
||||||
typeText(commandToKeys("nmap <Plug>Foo iHello<Esc>"));
|
|
||||||
|
|
||||||
typeText(commandToKeys("imap"));
|
|
||||||
assertExOutput("i <C-Down> <C-O>gt\n" +
|
|
||||||
"i bar <Esc>\n" +
|
|
||||||
"i foo bar\n");
|
|
||||||
|
|
||||||
typeText(commandToKeys("map"));
|
|
||||||
assertExOutput(" <C-Down> gt\n" +
|
|
||||||
"n <Plug>Foo iHello<Esc>\n" +
|
|
||||||
"n ,f <Plug>Foo\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testRecursiveMapping() {
|
|
||||||
configureByText("\n");
|
|
||||||
typeText(commandToKeys("imap foo bar"));
|
|
||||||
typeText(commandToKeys("imap bar baz"));
|
|
||||||
typeText(commandToKeys("imap baz quux"));
|
|
||||||
typeText(parseKeys("i", "foo"));
|
|
||||||
myFixture.checkResult("quux\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testNonRecursiveMapping() {
|
|
||||||
configureByText("\n");
|
|
||||||
typeText(commandToKeys("inoremap a b"));
|
|
||||||
assertPluginError(false);
|
|
||||||
typeText(commandToKeys("inoremap b a"));
|
|
||||||
typeText(parseKeys("i", "ab"));
|
|
||||||
myFixture.checkResult("ba\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testNonRecursiveMapTable() {
|
|
||||||
configureByText("\n");
|
|
||||||
typeText(commandToKeys("inoremap jj <Esc>"));
|
|
||||||
typeText(commandToKeys("imap foo bar"));
|
|
||||||
typeText(commandToKeys("imap"));
|
|
||||||
assertExOutput("i foo bar\n" +
|
|
||||||
"i jj * <Esc>\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testNop() {
|
|
||||||
configureByText("<caret>foo\n" +
|
|
||||||
"bar\n");
|
|
||||||
typeText(commandToKeys("noremap <Right> <nop>"));
|
|
||||||
assertPluginError(false);
|
|
||||||
typeText(parseKeys("l", "<Right>"));
|
|
||||||
assertPluginError(false);
|
|
||||||
myFixture.checkResult("foo\n" +
|
|
||||||
"bar\n");
|
|
||||||
assertOffset(1);
|
|
||||||
typeText(commandToKeys("nmap"));
|
|
||||||
assertExOutput("n <Right> * <Nop>\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testIgnoreModifiers() {
|
|
||||||
configureByText("\n");
|
|
||||||
typeText(commandToKeys("nmap <buffer> ,a /a<CR>"));
|
|
||||||
typeText(commandToKeys("nmap <nowait> ,b /b<CR>"));
|
|
||||||
typeText(commandToKeys("nmap <silent> ,c /c<CR>"));
|
|
||||||
typeText(commandToKeys("nmap <special> ,d /d<CR>"));
|
|
||||||
typeText(commandToKeys("nmap <script> ,e /e<CR>"));
|
|
||||||
typeText(commandToKeys("nmap <expr> ,f /f<CR>"));
|
|
||||||
typeText(commandToKeys("nmap <unique> ,g /g<CR>"));
|
|
||||||
typeText(commandToKeys("nmap"));
|
|
||||||
assertExOutput("n ,a /a<CR>\n" +
|
|
||||||
"n ,b /b<CR>\n" +
|
|
||||||
"n ,c /c<CR>\n" +
|
|
||||||
"n ,d /d<CR>\n" +
|
|
||||||
"n ,g /g<CR>\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
// VIM-645 |:nmap|
|
|
||||||
public void testMapSpace() {
|
|
||||||
configureByText("foo\n");
|
|
||||||
typeText(commandToKeys("nmap <space> dw"));
|
|
||||||
typeText(parseKeys(" "));
|
|
||||||
myFixture.checkResult("\n");
|
|
||||||
typeText(parseKeys("i", " ", "<Esc>"));
|
|
||||||
myFixture.checkResult(" \n");
|
|
||||||
}
|
|
||||||
|
|
||||||
// VIM-661 |:noremap| |r|
|
|
||||||
public void testNoMappingInReplaceCharacterArgument() {
|
|
||||||
configureByText("<caret>foo\n");
|
|
||||||
typeText(commandToKeys("noremap A Z"));
|
|
||||||
typeText(parseKeys("rA"));
|
|
||||||
myFixture.checkResult("Aoo\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
// VIM-661 |:omap| |d| |t|
|
|
||||||
public void testNoMappingInNonFirstCharOfOperatorPendingMode() {
|
|
||||||
configureByText("<caret>foo, bar\n");
|
|
||||||
typeText(commandToKeys("omap , ?"));
|
|
||||||
typeText(parseKeys("dt,"));
|
|
||||||
myFixture.checkResult(", bar\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
// VIM-666 |:imap|
|
|
||||||
public void testIgnoreEverythingAfterBar() {
|
|
||||||
configureByText("<caret>foo\n");
|
|
||||||
typeText(commandToKeys("imap a b |c \" Something else"));
|
|
||||||
typeText(parseKeys("ia"));
|
|
||||||
myFixture.checkResult("b foo\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
// VIM-666 |:imap|
|
|
||||||
public void testBarEscaped() {
|
|
||||||
configureByText("<caret>foo\n");
|
|
||||||
typeText(commandToKeys("imap a b \\| c"));
|
|
||||||
typeText(parseKeys("ia"));
|
|
||||||
myFixture.checkResult("b | cfoo\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
// VIM-666 |:imap|
|
|
||||||
public void testBarEscapedSeveralSpaces() {
|
|
||||||
configureByText("<caret>foo\n");
|
|
||||||
typeText(commandToKeys("imap a b \\| c |"));
|
|
||||||
typeText(parseKeys("ia"));
|
|
||||||
myFixture.checkResult("b | c foo\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
// VIM-670 |:map|
|
|
||||||
public void testFirstCharIsNonRecursive() {
|
|
||||||
configureByText("\n");
|
|
||||||
typeText(commandToKeys("map ab abcd"));
|
|
||||||
typeText(parseKeys("ab"));
|
|
||||||
myFixture.checkResult("bcd\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
// VIM-676 |:map|
|
|
||||||
public void testBackspaceCharacterInVimRc() {
|
|
||||||
configureByText("\n");
|
|
||||||
VimScriptParser.executeText("inoremap # X\u0008#\n");
|
|
||||||
typeText(parseKeys("i", "#", "<Esc>"));
|
|
||||||
myFixture.checkResult("#\n");
|
|
||||||
assertMode(CommandState.Mode.COMMAND);
|
|
||||||
typeText(commandToKeys("imap"));
|
|
||||||
assertExOutput("i # * X<C-H>#\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
// VIM-679 |:map|
|
|
||||||
public void testCancelCharacterInVimRc() {
|
|
||||||
configureByText("<caret>foo\n" +
|
|
||||||
"bar\n");
|
|
||||||
VimScriptParser.executeText("map \u0018i dd\n");
|
|
||||||
typeText(parseKeys("i", "#", "<Esc>"));
|
|
||||||
myFixture.checkResult("#foo\n" +
|
|
||||||
"bar\n");
|
|
||||||
assertMode(CommandState.Mode.COMMAND);
|
|
||||||
typeText(commandToKeys("map"));
|
|
||||||
assertExOutput(" <C-X>i dd\n");
|
|
||||||
typeText(parseKeys("<C-X>i"));
|
|
||||||
myFixture.checkResult("bar\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
// VIM-679 |:map|
|
|
||||||
public void testBarCtrlVEscaped() {
|
|
||||||
configureByText("<caret>foo\n");
|
|
||||||
VimScriptParser.executeText("imap a b \u0016|\u0016| c |\n");
|
|
||||||
typeText(parseKeys("ia"));
|
|
||||||
myFixture.checkResult("b || c foo\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
// VIM-679 |:map|
|
|
||||||
public void testCtrlMCtrlLAsNewLine() {
|
|
||||||
configureByText("<caret>foo\n");
|
|
||||||
VimScriptParser.executeText("map A :%s/foo/bar/g\r\u000C\n");
|
|
||||||
typeText(parseKeys("A"));
|
|
||||||
myFixture.checkResult("bar\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
// VIM-700 |:map|
|
|
||||||
public void testRemappingZero() {
|
|
||||||
configureByText("x<caret>yz\n");
|
|
||||||
VimScriptParser.executeText("map 0 ~");
|
|
||||||
typeText(parseKeys("0"));
|
|
||||||
myFixture.checkResult("xYz\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
// VIM-700 |:map|
|
|
||||||
public void testRemappingZeroStillAllowsZeroToBeUsedInCount() {
|
|
||||||
configureByText("a<caret>bcdefghijklmnop\n");
|
|
||||||
VimScriptParser.executeText("map 0 ^");
|
|
||||||
typeText(parseKeys("10~"));
|
|
||||||
myFixture.checkResult("aBCDEFGHIJKlmnop\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
// VIM-700 |:map|
|
|
||||||
public void testRemappingDeleteOverridesRemovingLastDigitFromCount() {
|
|
||||||
configureByText("a<caret>bcdefghijklmnop\n");
|
|
||||||
VimScriptParser.executeText("map <Del> ~");
|
|
||||||
typeText(parseKeys("10<Del>"));
|
|
||||||
myFixture.checkResult("aBCDEFGHIJKlmnop\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
// VIM-650 |mapleader|
|
|
||||||
public void testMapLeader() {
|
|
||||||
configureByText("\n");
|
|
||||||
typeText(commandToKeys("let mapleader = \",\""));
|
|
||||||
typeText(commandToKeys("nmap <Leader>z izzz<Esc>"));
|
|
||||||
typeText(parseKeys(",z"));
|
|
||||||
myFixture.checkResult("zzz\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testAmbiguousMapping() {
|
|
||||||
configureByText("\n");
|
|
||||||
typeText(commandToKeys("nmap ,f iHello<Esc>"));
|
|
||||||
typeText(commandToKeys("nmap ,fc iBye<Esc>"));
|
|
||||||
typeText(parseKeys(",fdh"));
|
|
||||||
myFixture.checkResult("Helo\n");
|
|
||||||
|
|
||||||
typeText(parseKeys("diw"));
|
|
||||||
myFixture.checkResult("\n");
|
|
||||||
|
|
||||||
typeText(parseKeys(",fch"));
|
|
||||||
myFixture.checkResult("Bye\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testLongAmbiguousMapping() {
|
|
||||||
configureByText("\n");
|
|
||||||
typeText(commandToKeys("nmap ,foo iHello<Esc>"));
|
|
||||||
typeText(commandToKeys("nmap ,fooc iBye<Esc>"));
|
|
||||||
typeText(parseKeys(",foodh"));
|
|
||||||
myFixture.checkResult("Helo\n");
|
|
||||||
|
|
||||||
typeText(parseKeys("diw"));
|
|
||||||
myFixture.checkResult("\n");
|
|
||||||
|
|
||||||
typeText(parseKeys(",fooch"));
|
|
||||||
myFixture.checkResult("Bye\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testPlugMapping() {
|
|
||||||
configureByText("\n");
|
|
||||||
typeText(commandToKeys("nmap ,f <Plug>Foo"));
|
|
||||||
typeText(commandToKeys("nmap <Plug>Foo iHello<Esc>"));
|
|
||||||
typeText(parseKeys(",fa!<Esc>"));
|
|
||||||
myFixture.checkResult("Hello!\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testIntersectingCommands() {
|
|
||||||
configureByText("123<caret>4567890");
|
|
||||||
typeText(commandToKeys("map ds h"));
|
|
||||||
typeText(commandToKeys("map I 3l"));
|
|
||||||
typeText(parseKeys("dI"));
|
|
||||||
myFixture.checkResult("123<caret>7890");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testIncompleteMapping() {
|
|
||||||
configureByText("123<caret>4567890");
|
|
||||||
typeText(commandToKeys("map <Plug>(Hi)l lll"));
|
|
||||||
typeText(commandToKeys("map I <Plug>(Hi)"));
|
|
||||||
typeText(parseKeys("Ih"));
|
|
||||||
myFixture.checkResult("12<caret>34567890");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testIntersectingCommands2() {
|
|
||||||
configureByText("123<caret>4567890");
|
|
||||||
typeText(commandToKeys("map as x"));
|
|
||||||
typeText(parseKeys("gas"));
|
|
||||||
myFixture.checkResult("123<caret>567890");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testMapZero() {
|
|
||||||
configureByText("A quick <caret>brown fox jumps over the lazy dog");
|
|
||||||
typeText(commandToKeys("nmap 0 w"));
|
|
||||||
typeText(parseKeys("0"));
|
|
||||||
assertOffset(14);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testMapZeroIgnoredInCount() {
|
|
||||||
configureByText("A quick <caret>brown fox jumps over the lazy dog. A quick brown fox jumps over the lazy dog");
|
|
||||||
typeText(commandToKeys("nmap 0 w"));
|
|
||||||
typeText(parseKeys("10w"));
|
|
||||||
assertOffset(51);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testMapNonZeroDigit() {
|
|
||||||
configureByText("A quick <caret>brown fox jumps over the lazy dog");
|
|
||||||
typeText(commandToKeys("nmap 2 w"));
|
|
||||||
typeText(parseKeys("2"));
|
|
||||||
assertOffset(14);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testMapNonZeroDigitNotIncludedInCount() {
|
|
||||||
configureByText("A quick <caret>brown fox jumps over the lazy dog. A quick brown fox jumps over the lazy dog");
|
|
||||||
typeText(commandToKeys("nmap 2 w"));
|
|
||||||
typeText(parseKeys("92"));
|
|
||||||
assertOffset(45);
|
|
||||||
}
|
|
||||||
}
|
|
426
test/org/jetbrains/plugins/ideavim/ex/handler/MapCommandTest.kt
Normal file
426
test/org/jetbrains/plugins/ideavim/ex/handler/MapCommandTest.kt
Normal file
@@ -0,0 +1,426 @@
|
|||||||
|
/*
|
||||||
|
* IdeaVim - Vim emulator for IDEs based on the IntelliJ platform
|
||||||
|
* Copyright (C) 2003-2020 The IdeaVim authors
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package org.jetbrains.plugins.ideavim.ex.handler
|
||||||
|
|
||||||
|
import com.maddyhome.idea.vim.command.CommandState
|
||||||
|
import com.maddyhome.idea.vim.ex.vimscript.VimScriptParser
|
||||||
|
import com.maddyhome.idea.vim.helper.StringHelper
|
||||||
|
import org.jetbrains.plugins.ideavim.VimTestCase
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author vlan
|
||||||
|
*/
|
||||||
|
class MapCommandTest : VimTestCase() {
|
||||||
|
fun testMapKtoJ() {
|
||||||
|
configureByText("""
|
||||||
|
${c}foo
|
||||||
|
bar
|
||||||
|
|
||||||
|
""".trimIndent())
|
||||||
|
typeText(commandToKeys("nmap k j"))
|
||||||
|
assertPluginError(false)
|
||||||
|
assertOffset(0)
|
||||||
|
typeText(StringHelper.parseKeys("k"))
|
||||||
|
assertOffset(4)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testInsertMapJKtoEsc() {
|
||||||
|
configureByText("${c}World!\n")
|
||||||
|
typeText(commandToKeys("imap jk <Esc>"))
|
||||||
|
assertPluginError(false)
|
||||||
|
typeText(StringHelper.parseKeys("i", "Hello, ", "jk"))
|
||||||
|
myFixture.checkResult("Hello, World!\n")
|
||||||
|
assertMode(CommandState.Mode.COMMAND)
|
||||||
|
assertOffset(6)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testBackslashEscape() {
|
||||||
|
configureByText("\n")
|
||||||
|
typeText(commandToKeys("imap \\\\,\\<,\\n foo"))
|
||||||
|
assertPluginError(false)
|
||||||
|
typeText(StringHelper.stringToKeys("i\\,<,\\n"))
|
||||||
|
myFixture.checkResult("foo\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testBackslashAtEnd() {
|
||||||
|
configureByText("\n")
|
||||||
|
typeText(commandToKeys("imap foo\\ bar"))
|
||||||
|
assertPluginError(false)
|
||||||
|
typeText(StringHelper.stringToKeys("ifoo\\"))
|
||||||
|
myFixture.checkResult("bar\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testUnfinishedSpecialKey() {
|
||||||
|
configureByText("\n")
|
||||||
|
typeText(commandToKeys("imap <Esc foo"))
|
||||||
|
typeText(StringHelper.stringToKeys("i<Esc"))
|
||||||
|
myFixture.checkResult("foo\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testUnknownSpecialKey() {
|
||||||
|
configureByText("\n")
|
||||||
|
typeText(commandToKeys("imap <foo> bar"))
|
||||||
|
typeText(StringHelper.stringToKeys("i<foo>"))
|
||||||
|
myFixture.checkResult("bar\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testMapTable() {
|
||||||
|
configureByText("\n")
|
||||||
|
typeText(commandToKeys("map <C-Down> gt"))
|
||||||
|
typeText(commandToKeys("imap foo bar"))
|
||||||
|
typeText(commandToKeys("imap bar <Esc>"))
|
||||||
|
typeText(commandToKeys("imap <C-Down> <C-O>gt"))
|
||||||
|
typeText(commandToKeys("nmap ,f <Plug>Foo"))
|
||||||
|
typeText(commandToKeys("nmap <Plug>Foo iHello<Esc>"))
|
||||||
|
typeText(commandToKeys("imap"))
|
||||||
|
assertExOutput("""
|
||||||
|
i <C-Down> <C-O>gt
|
||||||
|
i bar <Esc>
|
||||||
|
i foo bar
|
||||||
|
|
||||||
|
""".trimIndent())
|
||||||
|
typeText(commandToKeys("map"))
|
||||||
|
assertExOutput(""" <C-Down> gt
|
||||||
|
n <Plug>Foo iHello<Esc>
|
||||||
|
n ,f <Plug>Foo
|
||||||
|
""")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testRecursiveMapping() {
|
||||||
|
configureByText("\n")
|
||||||
|
typeText(commandToKeys("imap foo bar"))
|
||||||
|
typeText(commandToKeys("imap bar baz"))
|
||||||
|
typeText(commandToKeys("imap baz quux"))
|
||||||
|
typeText(StringHelper.parseKeys("i", "foo"))
|
||||||
|
myFixture.checkResult("quux\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testNonRecursiveMapping() {
|
||||||
|
configureByText("\n")
|
||||||
|
typeText(commandToKeys("inoremap a b"))
|
||||||
|
assertPluginError(false)
|
||||||
|
typeText(commandToKeys("inoremap b a"))
|
||||||
|
typeText(StringHelper.parseKeys("i", "ab"))
|
||||||
|
myFixture.checkResult("ba\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testNonRecursiveMapTable() {
|
||||||
|
configureByText("\n")
|
||||||
|
typeText(commandToKeys("inoremap jj <Esc>"))
|
||||||
|
typeText(commandToKeys("imap foo bar"))
|
||||||
|
typeText(commandToKeys("imap"))
|
||||||
|
assertExOutput("""
|
||||||
|
i foo bar
|
||||||
|
i jj * <Esc>
|
||||||
|
|
||||||
|
""".trimIndent())
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testNop() {
|
||||||
|
configureByText("""
|
||||||
|
${c}foo
|
||||||
|
bar
|
||||||
|
|
||||||
|
""".trimIndent())
|
||||||
|
typeText(commandToKeys("noremap <Right> <nop>"))
|
||||||
|
assertPluginError(false)
|
||||||
|
typeText(StringHelper.parseKeys("l", "<Right>"))
|
||||||
|
assertPluginError(false)
|
||||||
|
myFixture.checkResult("""
|
||||||
|
foo
|
||||||
|
bar
|
||||||
|
|
||||||
|
""".trimIndent())
|
||||||
|
assertOffset(1)
|
||||||
|
typeText(commandToKeys("nmap"))
|
||||||
|
assertExOutput("n <Right> * <Nop>\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testIgnoreModifiers() {
|
||||||
|
configureByText("\n")
|
||||||
|
typeText(commandToKeys("nmap <buffer> ,a /a<CR>"))
|
||||||
|
typeText(commandToKeys("nmap <nowait> ,b /b<CR>"))
|
||||||
|
typeText(commandToKeys("nmap <silent> ,c /c<CR>"))
|
||||||
|
typeText(commandToKeys("nmap <special> ,d /d<CR>"))
|
||||||
|
typeText(commandToKeys("nmap <script> ,e /e<CR>"))
|
||||||
|
typeText(commandToKeys("nmap <expr> ,f /f<CR>"))
|
||||||
|
typeText(commandToKeys("nmap <unique> ,g /g<CR>"))
|
||||||
|
typeText(commandToKeys("nmap"))
|
||||||
|
assertExOutput("""
|
||||||
|
n ,a /a<CR>
|
||||||
|
n ,b /b<CR>
|
||||||
|
n ,c /c<CR>
|
||||||
|
n ,d /d<CR>
|
||||||
|
n ,g /g<CR>
|
||||||
|
|
||||||
|
""".trimIndent())
|
||||||
|
}
|
||||||
|
|
||||||
|
// VIM-645 |:nmap|
|
||||||
|
fun testMapSpace() {
|
||||||
|
configureByText("foo\n")
|
||||||
|
typeText(commandToKeys("nmap <space> dw"))
|
||||||
|
typeText(StringHelper.parseKeys(" "))
|
||||||
|
myFixture.checkResult("\n")
|
||||||
|
typeText(StringHelper.parseKeys("i", " ", "<Esc>"))
|
||||||
|
myFixture.checkResult(" \n")
|
||||||
|
}
|
||||||
|
|
||||||
|
// VIM-661 |:noremap| |r|
|
||||||
|
fun testNoMappingInReplaceCharacterArgument() {
|
||||||
|
configureByText("${c}foo\n")
|
||||||
|
typeText(commandToKeys("noremap A Z"))
|
||||||
|
typeText(StringHelper.parseKeys("rA"))
|
||||||
|
myFixture.checkResult("Aoo\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
// VIM-661 |:omap| |d| |t|
|
||||||
|
fun testNoMappingInNonFirstCharOfOperatorPendingMode() {
|
||||||
|
configureByText("${c}foo, bar\n")
|
||||||
|
typeText(commandToKeys("omap , ?"))
|
||||||
|
typeText(StringHelper.parseKeys("dt,"))
|
||||||
|
myFixture.checkResult(", bar\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
// VIM-666 |:imap|
|
||||||
|
fun testIgnoreEverythingAfterBar() {
|
||||||
|
configureByText("${c}foo\n")
|
||||||
|
typeText(commandToKeys("imap a b |c \" Something else"))
|
||||||
|
typeText(StringHelper.parseKeys("ia"))
|
||||||
|
myFixture.checkResult("b foo\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
// VIM-666 |:imap|
|
||||||
|
fun testBarEscaped() {
|
||||||
|
configureByText("${c}foo\n")
|
||||||
|
typeText(commandToKeys("imap a b \\| c"))
|
||||||
|
typeText(StringHelper.parseKeys("ia"))
|
||||||
|
myFixture.checkResult("b | cfoo\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
// VIM-666 |:imap|
|
||||||
|
fun testBarEscapedSeveralSpaces() {
|
||||||
|
configureByText("${c}foo\n")
|
||||||
|
typeText(commandToKeys("imap a b \\| c |"))
|
||||||
|
typeText(StringHelper.parseKeys("ia"))
|
||||||
|
myFixture.checkResult("b | c foo\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
// VIM-670 |:map|
|
||||||
|
fun testFirstCharIsNonRecursive() {
|
||||||
|
configureByText("\n")
|
||||||
|
typeText(commandToKeys("map ab abcd"))
|
||||||
|
typeText(StringHelper.parseKeys("ab"))
|
||||||
|
myFixture.checkResult("bcd\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
// VIM-676 |:map|
|
||||||
|
fun testBackspaceCharacterInVimRc() {
|
||||||
|
configureByText("\n")
|
||||||
|
VimScriptParser.executeText("inoremap # X\u0008#\n")
|
||||||
|
typeText(StringHelper.parseKeys("i", "#", "<Esc>"))
|
||||||
|
myFixture.checkResult("#\n")
|
||||||
|
assertMode(CommandState.Mode.COMMAND)
|
||||||
|
typeText(commandToKeys("imap"))
|
||||||
|
assertExOutput("i # * X<C-H>#\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
// VIM-679 |:map|
|
||||||
|
fun testCancelCharacterInVimRc() {
|
||||||
|
configureByText("""
|
||||||
|
${c}foo
|
||||||
|
bar
|
||||||
|
|
||||||
|
""".trimIndent())
|
||||||
|
VimScriptParser.executeText("map \u0018i dd\n")
|
||||||
|
typeText(StringHelper.parseKeys("i", "#", "<Esc>"))
|
||||||
|
myFixture.checkResult("""
|
||||||
|
#foo
|
||||||
|
bar
|
||||||
|
|
||||||
|
""".trimIndent())
|
||||||
|
assertMode(CommandState.Mode.COMMAND)
|
||||||
|
typeText(commandToKeys("map"))
|
||||||
|
assertExOutput(" <C-X>i dd\n")
|
||||||
|
typeText(StringHelper.parseKeys("<C-X>i"))
|
||||||
|
myFixture.checkResult("bar\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
// VIM-679 |:map|
|
||||||
|
fun testBarCtrlVEscaped() {
|
||||||
|
configureByText("${c}foo\n")
|
||||||
|
VimScriptParser.executeText("imap a b \u0016|\u0016| c |\n")
|
||||||
|
typeText(StringHelper.parseKeys("ia"))
|
||||||
|
myFixture.checkResult("b || c foo\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
// VIM-679 |:map|
|
||||||
|
fun testCtrlMCtrlLAsNewLine() {
|
||||||
|
configureByText("${c}foo\n")
|
||||||
|
VimScriptParser.executeText("map A :%s/foo/bar/g\r\u000C\n")
|
||||||
|
typeText(StringHelper.parseKeys("A"))
|
||||||
|
myFixture.checkResult("bar\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
// VIM-700 |:map|
|
||||||
|
fun testRemappingZero() {
|
||||||
|
configureByText("x${c}yz\n")
|
||||||
|
VimScriptParser.executeText("map 0 ~")
|
||||||
|
typeText(StringHelper.parseKeys("0"))
|
||||||
|
myFixture.checkResult("xYz\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
// VIM-700 |:map|
|
||||||
|
fun testRemappingZeroStillAllowsZeroToBeUsedInCount() {
|
||||||
|
configureByText("a${c}bcdefghijklmnop\n")
|
||||||
|
VimScriptParser.executeText("map 0 ^")
|
||||||
|
typeText(StringHelper.parseKeys("10~"))
|
||||||
|
myFixture.checkResult("aBCDEFGHIJKlmnop\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
// VIM-700 |:map|
|
||||||
|
fun testRemappingDeleteOverridesRemovingLastDigitFromCount() {
|
||||||
|
configureByText("a${c}bcdefghijklmnop\n")
|
||||||
|
VimScriptParser.executeText("map <Del> ~")
|
||||||
|
typeText(StringHelper.parseKeys("10<Del>"))
|
||||||
|
myFixture.checkResult("aBCDEFGHIJKlmnop\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
// VIM-650 |mapleader|
|
||||||
|
fun testMapLeader() {
|
||||||
|
configureByText("\n")
|
||||||
|
typeText(commandToKeys("let mapleader = \",\""))
|
||||||
|
typeText(commandToKeys("nmap <Leader>z izzz<Esc>"))
|
||||||
|
typeText(StringHelper.parseKeys(",z"))
|
||||||
|
myFixture.checkResult("zzz\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testAmbiguousMapping() {
|
||||||
|
configureByText("\n")
|
||||||
|
typeText(commandToKeys("nmap ,f iHello<Esc>"))
|
||||||
|
typeText(commandToKeys("nmap ,fc iBye<Esc>"))
|
||||||
|
typeText(StringHelper.parseKeys(",fdh"))
|
||||||
|
myFixture.checkResult("Helo\n")
|
||||||
|
typeText(StringHelper.parseKeys("diw"))
|
||||||
|
myFixture.checkResult("\n")
|
||||||
|
typeText(StringHelper.parseKeys(",fch"))
|
||||||
|
myFixture.checkResult("Bye\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testLongAmbiguousMapping() {
|
||||||
|
configureByText("\n")
|
||||||
|
typeText(commandToKeys("nmap ,foo iHello<Esc>"))
|
||||||
|
typeText(commandToKeys("nmap ,fooc iBye<Esc>"))
|
||||||
|
typeText(StringHelper.parseKeys(",foodh"))
|
||||||
|
myFixture.checkResult("Helo\n")
|
||||||
|
typeText(StringHelper.parseKeys("diw"))
|
||||||
|
myFixture.checkResult("\n")
|
||||||
|
typeText(StringHelper.parseKeys(",fooch"))
|
||||||
|
myFixture.checkResult("Bye\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testPlugMapping() {
|
||||||
|
configureByText("\n")
|
||||||
|
typeText(commandToKeys("nmap ,f <Plug>Foo"))
|
||||||
|
typeText(commandToKeys("nmap <Plug>Foo iHello<Esc>"))
|
||||||
|
typeText(StringHelper.parseKeys(",fa!<Esc>"))
|
||||||
|
myFixture.checkResult("Hello!\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testIntersectingCommands() {
|
||||||
|
configureByText("123${c}4567890")
|
||||||
|
typeText(commandToKeys("map ds h"))
|
||||||
|
typeText(commandToKeys("map I 3l"))
|
||||||
|
typeText(StringHelper.parseKeys("dI"))
|
||||||
|
myFixture.checkResult("123${c}7890")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testIncompleteMapping() {
|
||||||
|
configureByText("123${c}4567890")
|
||||||
|
typeText(commandToKeys("map <Plug>(Hi)l lll"))
|
||||||
|
typeText(commandToKeys("map I <Plug>(Hi)"))
|
||||||
|
typeText(StringHelper.parseKeys("Ih"))
|
||||||
|
myFixture.checkResult("12${c}34567890")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testIntersectingCommands2() {
|
||||||
|
configureByText("123${c}4567890")
|
||||||
|
typeText(commandToKeys("map as x"))
|
||||||
|
typeText(StringHelper.parseKeys("gas"))
|
||||||
|
myFixture.checkResult("123${c}567890")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testMapZero() {
|
||||||
|
configureByText("A quick ${c}brown fox jumps over the lazy dog")
|
||||||
|
typeText(commandToKeys("nmap 0 w"))
|
||||||
|
typeText(StringHelper.parseKeys("0"))
|
||||||
|
assertOffset(14)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testMapZeroIgnoredInCount() {
|
||||||
|
configureByText("A quick ${c}brown fox jumps over the lazy dog. A quick brown fox jumps over the lazy dog")
|
||||||
|
typeText(commandToKeys("nmap 0 w"))
|
||||||
|
typeText(StringHelper.parseKeys("10w"))
|
||||||
|
assertOffset(51)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testMapNonZeroDigit() {
|
||||||
|
configureByText("A quick ${c}brown fox jumps over the lazy dog")
|
||||||
|
typeText(commandToKeys("nmap 2 w"))
|
||||||
|
typeText(StringHelper.parseKeys("2"))
|
||||||
|
assertOffset(14)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testMapNonZeroDigitNotIncludedInCount() {
|
||||||
|
configureByText("A quick ${c}brown fox jumps over the lazy dog. A quick brown fox jumps over the lazy dog")
|
||||||
|
typeText(commandToKeys("nmap 2 w"))
|
||||||
|
typeText(StringHelper.parseKeys("92"))
|
||||||
|
assertOffset(45)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testShiftSpace() {
|
||||||
|
configureByText("A quick ${c}brown fox jumps over the lazy dog. A quick brown fox jumps over the lazy dog")
|
||||||
|
typeText(commandToKeys("nmap <S-Space> w"))
|
||||||
|
typeText(StringHelper.parseKeys("<S-Space>"))
|
||||||
|
myFixture.checkResult("A quick brown ${c}fox jumps over the lazy dog. A quick brown fox jumps over the lazy dog")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testShiftLetter() {
|
||||||
|
configureByText("A quick ${c}brown fox jumps over the lazy dog. A quick brown fox jumps over the lazy dog")
|
||||||
|
typeText(commandToKeys("nmap <S-D> w"))
|
||||||
|
typeText(StringHelper.parseKeys("<S-D>"))
|
||||||
|
myFixture.checkResult("A quick brown ${c}fox jumps over the lazy dog. A quick brown fox jumps over the lazy dog")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testUppercaseLetter() {
|
||||||
|
configureByText("A quick ${c}brown fox jumps over the lazy dog. A quick brown fox jumps over the lazy dog")
|
||||||
|
typeText(commandToKeys("nmap D w"))
|
||||||
|
typeText(StringHelper.parseKeys("D"))
|
||||||
|
myFixture.checkResult("A quick brown ${c}fox jumps over the lazy dog. A quick brown fox jumps over the lazy dog")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun `test shift letter doesn't break insert mode`() {
|
||||||
|
configureByText("A quick ${c}brown fox jumps over the lazy dog. A quick brown fox jumps over the lazy dog")
|
||||||
|
typeText(commandToKeys("nmap <S-D> w"))
|
||||||
|
typeText(StringHelper.parseKeys("<S-D>"))
|
||||||
|
myFixture.checkResult("A quick brown ${c}fox jumps over the lazy dog. A quick brown fox jumps over the lazy dog")
|
||||||
|
|
||||||
|
typeText(StringHelper.parseKeys("iD<Esc>"))
|
||||||
|
myFixture.checkResult("A quick brown ${c}Dfox jumps over the lazy dog. A quick brown fox jumps over the lazy dog")
|
||||||
|
}
|
||||||
|
}
|
@@ -37,6 +37,7 @@ class ReplaceWithRegisterTest : VimTestCase() {
|
|||||||
|
|
||||||
fun `test replace with empty register`() {
|
fun `test replace with empty register`() {
|
||||||
val text = "one ${c}two three"
|
val text = "one ${c}two three"
|
||||||
|
VimPlugin.getRegister().resetRegisters()
|
||||||
|
|
||||||
configureByText(text)
|
configureByText(text)
|
||||||
typeText(parseKeys("griw"))
|
typeText(parseKeys("griw"))
|
||||||
|
@@ -24,7 +24,6 @@ import org.jetbrains.plugins.ideavim.VimTestCase;
|
|||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
import java.awt.event.InputEvent;
|
import java.awt.event.InputEvent;
|
||||||
import java.awt.event.KeyEvent;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -32,7 +31,7 @@ import java.util.List;
|
|||||||
*/
|
*/
|
||||||
public class StringHelperTest extends VimTestCase {
|
public class StringHelperTest extends VimTestCase {
|
||||||
public void testParseKeyModifiers() {
|
public void testParseKeyModifiers() {
|
||||||
assertTypedKeyStroke('C', "<S-C>");
|
assertTypedKeyStroke('C', "C");
|
||||||
assertTypedKeyStroke('c', "c");
|
assertTypedKeyStroke('c', "c");
|
||||||
|
|
||||||
assertPressedKeyStroke("control C", "<C-C>");
|
assertPressedKeyStroke("control C", "<C-C>");
|
||||||
@@ -113,12 +112,7 @@ public class StringHelperTest extends VimTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void assertTypedKeyStroke(char expected, @NotNull String actual) {
|
private void assertTypedKeyStroke(char expected, @NotNull String actual) {
|
||||||
if (Character.isUpperCase(expected)) {
|
assertEquals(KeyStroke.getKeyStroke(expected), parseKeyStroke(actual));
|
||||||
assertEquals(KeyStroke.getKeyStroke(expected, KeyEvent.SHIFT_DOWN_MASK), parseKeyStroke(actual));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
assertEquals(KeyStroke.getKeyStroke(expected), parseKeyStroke(actual));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
|
Reference in New Issue
Block a user