mirror of
https://github.com/chylex/IntelliJ-IdeaVim.git
synced 2025-09-14 05:32:10 +02:00
Compare commits
112 Commits
3da1cc300f
...
customized
Author | SHA1 | Date | |
---|---|---|---|
822dad52f3
|
|||
bf12c98880
|
|||
c02bd15e4f
|
|||
5957d5d681
|
|||
9445afb555
|
|||
6e115bdf64
|
|||
6305c412b5
|
|||
be2eabe3b9
|
|||
de13e4348a
|
|||
1c154fdc8a
|
|||
9b75931736
|
|||
3fe97aa767
|
|||
8eb2dbebcf
|
|||
cb781f9a0d
|
|||
6693755823
|
|||
9a9bd335d3
|
|||
91e22482c6
|
|||
06dc2ed75c
|
|||
12da1ac969
|
|||
5747ac0ebf
|
|||
8a47bc1840
|
|||
da4deaf698
|
|||
![]() |
4c09ab4766 | ||
![]() |
ee447bce07 | ||
![]() |
5fb4c10f88 | ||
![]() |
ed2fcb08b0 | ||
dedd90ce13 | |||
![]() |
73326e623e | ||
![]() |
a2bc34d6ec | ||
![]() |
b652c7726a | ||
![]() |
fb7a2de07b | ||
![]() |
def9ca479b | ||
![]() |
0936e0761f | ||
![]() |
09a335bcfe | ||
![]() |
37b8d69bac | ||
![]() |
13308050a8 | ||
![]() |
a1a553ebc9 | ||
![]() |
5bb0c4f7cb | ||
![]() |
da6736f24a | ||
![]() |
4df1ce2ae8 | ||
![]() |
00fd4cd491 | ||
![]() |
d185672e2f | ||
![]() |
55fef03a4a | ||
![]() |
69b3e4f782 | ||
![]() |
6be29b0378 | ||
![]() |
9965c863a6 | ||
![]() |
3f11ae512c | ||
![]() |
1c842eb3d8 | ||
![]() |
c7fbce675b | ||
![]() |
d7e68488c8 | ||
![]() |
69d13a74e6 | ||
![]() |
5a83df34a7 | ||
![]() |
0a18c388e0 | ||
![]() |
1a3409e7df | ||
![]() |
e93db961a0 | ||
![]() |
8fd76bd08f | ||
![]() |
0eea4a5b2c | ||
![]() |
18a0c533e2 | ||
![]() |
0bd8d8f4d2 | ||
![]() |
64a89c8863 | ||
![]() |
5b17d7740e | ||
![]() |
e406885ec6 | ||
![]() |
9bbeab8062 | ||
![]() |
373bfc4eab | ||
![]() |
050f2f7b97 | ||
![]() |
e30bc14843 | ||
![]() |
76d590be11 | ||
![]() |
b005328b4a | ||
![]() |
ad20021cee | ||
![]() |
126de5c218 | ||
![]() |
0f7aef3f15 | ||
![]() |
f352b84922 | ||
![]() |
789faa7cb2 | ||
![]() |
a338f5768a | ||
![]() |
8205c74571 | ||
![]() |
def40eb409 | ||
![]() |
010e8a7541 | ||
![]() |
46c6778b3a | ||
![]() |
0977bd4400 | ||
![]() |
db092e9b0a | ||
![]() |
5cfb98e188 | ||
![]() |
3a95b62885 | ||
![]() |
93e6adf5a9 | ||
![]() |
37204398ff | ||
![]() |
b2f450d14d | ||
![]() |
61da888571 | ||
![]() |
fcda97cfb8 | ||
![]() |
1dc7ea6363 | ||
![]() |
bb507db884 | ||
![]() |
7b0482ed94 | ||
![]() |
1c79b0d59a | ||
![]() |
ff4eb31418 | ||
![]() |
cb1078cf70 | ||
![]() |
da3e40eaf6 | ||
![]() |
17f77a9639 | ||
![]() |
3d03494354 | ||
![]() |
642caddda7 | ||
![]() |
1d97c43e30 | ||
![]() |
7ed3e3b53c | ||
![]() |
aa39ca2006 | ||
![]() |
bb122903de | ||
![]() |
c84a3cf64d | ||
![]() |
f4c9464b8a | ||
![]() |
3ba14d05b4 | ||
![]() |
2189b70b87 | ||
![]() |
ea2222f9d5 | ||
![]() |
7d68d41888 | ||
![]() |
44749b6d8c | ||
![]() |
1ce4dbc569 | ||
![]() |
db59513505 | ||
![]() |
8c9ff9465f | ||
![]() |
1a2322ddec |
1
.gitattributes
vendored
Normal file
1
.gitattributes
vendored
Normal file
@@ -0,0 +1 @@
|
||||
* text=auto eol=lf
|
3
.gitignore
vendored
3
.gitignore
vendored
@@ -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
|
||||
|
1
.teamcity/_Self/Project.kt
vendored
1
.teamcity/_Self/Project.kt
vendored
@@ -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)
|
||||
|
16
AUTHORS.md
16
AUTHORS.md
@@ -523,6 +523,22 @@ Contributors:
|
||||
[![icon][github]](https://github.com/LazyScaper)
|
||||
|
||||
Jake
|
||||
* [![icon][mail]](mailto:the1xdeveloper@gmail.com)
|
||||
[![icon][github]](https://github.com/The1xDeveloper)
|
||||
|
||||
The1xDeveloper
|
||||
* [![icon][mail]](mailto:shaunewilliams@gmail.com)
|
||||
[![icon][github]](https://github.com/shaunlebron)
|
||||
|
||||
shaun
|
||||
* [![icon][mail]](mailto:i.i.babko@gmail.com)
|
||||
[![icon][github]](https://github.com/igorbabko)
|
||||
|
||||
Igor Babko
|
||||
* [![icon][mail]](mailto:533601+felixwiemuth@users.noreply.github.com)
|
||||
[![icon][github]](https://github.com/felixwiemuth)
|
||||
|
||||
Felix Wiemuth
|
||||
|
||||
Previous contributors:
|
||||
|
||||
|
@@ -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
|
||||
|
||||
|
@@ -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`.
|
||||
|
@@ -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)
|
||||
|
@@ -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()
|
||||
|
@@ -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()
|
||||
|
@@ -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()
|
||||
|
@@ -125,6 +125,7 @@ dependencies {
|
||||
|
||||
// AceJump is an optional dependency. We use their SessionManager class to check if it's active
|
||||
plugin("AceJump", "3.8.19")
|
||||
plugin("com.intellij.classic.ui", "242.20224.159")
|
||||
}
|
||||
|
||||
moduleSources(project(":vim-engine", "sourcesJarArtifacts"))
|
||||
@@ -210,6 +211,8 @@ tasks {
|
||||
}
|
||||
|
||||
compileTestKotlin {
|
||||
enabled = false
|
||||
|
||||
kotlinOptions {
|
||||
jvmTarget = javaVersion
|
||||
apiVersion = "1.9"
|
||||
|
@@ -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)
|
||||
|
@@ -82,7 +82,7 @@ Original plugin: [NERDTree](https://github.com/preservim/nerdtree).
|
||||
|
||||
### Instructions
|
||||
|
||||
[See here](NERDTree-support.md).
|
||||
[See here](NERDTree-support).
|
||||
|
||||
</details>
|
||||
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
||||
|
@@ -16,11 +16,11 @@
|
||||
# https://data.services.jetbrains.com/products?code=IC
|
||||
# Maven releases are here: https://www.jetbrains.com/intellij-repository/releases
|
||||
# And snapshots: https://www.jetbrains.com/intellij-repository/snapshots
|
||||
ideaVersion=2024.1.1
|
||||
ideaVersion=2024.2
|
||||
# Values for type: https://plugins.jetbrains.com/docs/intellij/tools-gradle-intellij-plugin.html#intellij-extension-type
|
||||
ideaType=IC
|
||||
instrumentPluginCode=true
|
||||
version=SNAPSHOT
|
||||
version=chylex-41
|
||||
javaVersion=17
|
||||
remoteRobotVersion=0.11.23
|
||||
antlrVersion=4.10.1
|
||||
@@ -47,7 +47,6 @@ youtrackToken=
|
||||
|
||||
# Gradle settings
|
||||
org.gradle.jvmargs='-Dfile.encoding=UTF-8'
|
||||
org.gradle.configuration-cache=true
|
||||
org.gradle.caching=true
|
||||
|
||||
# Disable warning from gradle-intellij-plugin. Kotlin stdlib is included as compileOnly, so the warning is unnecessary
|
||||
|
@@ -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
|
||||
|
@@ -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")
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -0,0 +1,52 @@
|
||||
package com.maddyhome.idea.vim.action
|
||||
|
||||
import com.intellij.openapi.actionSystem.ActionUpdateThread
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent
|
||||
import com.intellij.openapi.command.UndoConfirmationPolicy
|
||||
import com.intellij.openapi.command.WriteCommandAction
|
||||
import com.intellij.openapi.fileEditor.TextEditor
|
||||
import com.intellij.openapi.fileEditor.ex.FileEditorManagerEx
|
||||
import com.intellij.openapi.project.DumbAwareAction
|
||||
import com.maddyhome.idea.vim.KeyHandler
|
||||
import com.maddyhome.idea.vim.api.injector
|
||||
import com.maddyhome.idea.vim.newapi.IjEditorExecutionContext
|
||||
import com.maddyhome.idea.vim.newapi.vim
|
||||
import com.maddyhome.idea.vim.state.mode.Mode
|
||||
|
||||
class VimRunLastMacroInOpenFiles : DumbAwareAction() {
|
||||
override fun update(e: AnActionEvent) {
|
||||
val lastRegister = injector.macro.lastRegister
|
||||
val isEnabled = lastRegister != 0.toChar()
|
||||
|
||||
e.presentation.isEnabled = isEnabled
|
||||
e.presentation.text = if (isEnabled) "Run Macro '${lastRegister}' in Open Files" else "Run Last Macro in Open Files"
|
||||
}
|
||||
|
||||
override fun getActionUpdateThread(): ActionUpdateThread {
|
||||
return ActionUpdateThread.EDT
|
||||
}
|
||||
|
||||
override fun actionPerformed(e: AnActionEvent) {
|
||||
val project = e.project ?: return
|
||||
val fileEditorManager = FileEditorManagerEx.getInstanceExIfCreated(project) ?: return
|
||||
val editors = fileEditorManager.allEditors.filterIsInstance<TextEditor>()
|
||||
|
||||
WriteCommandAction.writeCommandAction(project)
|
||||
.withName(e.presentation.text)
|
||||
.withGlobalUndo()
|
||||
.withUndoConfirmationPolicy(UndoConfirmationPolicy.REQUEST_CONFIRMATION)
|
||||
.run<RuntimeException> {
|
||||
val reg = injector.macro.lastRegister
|
||||
|
||||
for (editor in editors) {
|
||||
fileEditorManager.openFile(editor.file, true)
|
||||
|
||||
val vimEditor = editor.editor.vim
|
||||
vimEditor.mode = Mode.NORMAL()
|
||||
KeyHandler.getInstance().reset(vimEditor)
|
||||
|
||||
injector.macro.playbackRegister(vimEditor, IjEditorExecutionContext(e.dataContext), reg, 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -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
|
||||
|
@@ -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
|
||||
|
||||
|
@@ -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(
|
||||
|
@@ -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
|
||||
}
|
||||
}
|
||||
|
@@ -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
|
||||
|
@@ -69,7 +69,8 @@ object VimExtensionFacade {
|
||||
|
||||
|
||||
@JvmStatic
|
||||
@Deprecated("Use VimPlugin.getKey().putKeyMapping(modes, fromKeys, pluginOwner, extensionHandler, recursive)",
|
||||
@Deprecated(
|
||||
"Use VimPlugin.getKey().putKeyMapping(modes, fromKeys, pluginOwner, extensionHandler, recursive)",
|
||||
ReplaceWith(
|
||||
"VimPlugin.getKey().putKeyMapping(modes, fromKeys, pluginOwner, extensionHandler, recursive)",
|
||||
"com.maddyhome.idea.vim.VimPlugin"
|
||||
@@ -195,7 +196,7 @@ object VimExtensionFacade {
|
||||
|
||||
@JvmStatic
|
||||
fun getRegisterForCaret(register: Char, caret: VimCaret): List<KeyStroke>? {
|
||||
val reg = caret.registerStorage.getRegister(register) ?: return null
|
||||
val reg = injector.registerGroup.getRegister(register) ?: return null
|
||||
return reg.keys
|
||||
}
|
||||
|
||||
@@ -208,7 +209,7 @@ object VimExtensionFacade {
|
||||
/** Set the current contents of the given register */
|
||||
@JvmStatic
|
||||
fun setRegisterForCaret(register: Char, caret: ImmutableVimCaret, keys: List<KeyStroke?>?) {
|
||||
caret.registerStorage.setKeys(register, keys?.filterNotNull() ?: emptyList())
|
||||
injector.registerGroup.setKeys(register, keys?.filterNotNull() ?: emptyList())
|
||||
}
|
||||
|
||||
/** Set the current contents of the given register */
|
||||
|
@@ -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,9 +189,8 @@ public class VimArgTextObjExtension implements VimExtension {
|
||||
this.isInner = isInner;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public TextRange getRange(@NotNull VimEditor editor,
|
||||
public @Nullable TextRange getRange(@NotNull VimEditor editor,
|
||||
@NotNull ImmutableVimCaret caret,
|
||||
@NotNull ExecutionContext context,
|
||||
int count,
|
||||
@@ -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;
|
||||
}
|
||||
|
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -21,10 +21,7 @@ import com.intellij.openapi.editor.markup.TextAttributes
|
||||
import com.intellij.openapi.util.Disposer
|
||||
import com.intellij.util.Alarm
|
||||
import com.intellij.util.Alarm.ThreadToUse
|
||||
import com.jetbrains.rd.util.first
|
||||
import com.maddyhome.idea.vim.VimPlugin
|
||||
import com.maddyhome.idea.vim.api.ImmutableVimCaret
|
||||
import com.maddyhome.idea.vim.api.VimCaret
|
||||
import com.maddyhome.idea.vim.api.VimEditor
|
||||
import com.maddyhome.idea.vim.api.injector
|
||||
import com.maddyhome.idea.vim.common.ModeChangeListener
|
||||
@@ -117,9 +114,9 @@ internal class VimHighlightedYank : VimExtension, VimYankListener, ModeChangeLis
|
||||
initialised = false
|
||||
}
|
||||
|
||||
override fun yankPerformed(caretToRange: Map<ImmutableVimCaret, TextRange>) {
|
||||
override fun yankPerformed(editor: VimEditor, range: TextRange) {
|
||||
ensureInitialised()
|
||||
highlightHandler.highlightYankRange(caretToRange)
|
||||
highlightHandler.highlightYankRange(editor.ij, range)
|
||||
}
|
||||
|
||||
override fun modeChanged(editor: VimEditor, oldMode: Mode) {
|
||||
@@ -140,15 +137,13 @@ internal class VimHighlightedYank : VimExtension, VimYankListener, ModeChangeLis
|
||||
private var lastEditor: Editor? = null
|
||||
private val highlighters = mutableSetOf<RangeHighlighter>()
|
||||
|
||||
fun highlightYankRange(caretToRange: Map<ImmutableVimCaret, TextRange>) {
|
||||
fun highlightYankRange(editor: Editor, range: TextRange) {
|
||||
// from vim-highlightedyank docs: When a new text is yanked or user starts editing, the old highlighting would be deleted
|
||||
clearYankHighlighters()
|
||||
|
||||
val editor = caretToRange.first().key.editor.ij
|
||||
lastEditor = editor
|
||||
|
||||
val attributes = getHighlightTextAttributes(editor)
|
||||
for (range in caretToRange.values) {
|
||||
for (i in 0 until range.size()) {
|
||||
val highlighter = editor.markupModel.addRangeHighlighter(
|
||||
range.startOffsets[i],
|
||||
@@ -159,7 +154,6 @@ internal class VimHighlightedYank : VimExtension, VimYankListener, ModeChangeLis
|
||||
)
|
||||
highlighters.add(highlighter)
|
||||
}
|
||||
}
|
||||
|
||||
// from vim-highlightedyank docs: A negative number makes the highlight persistent.
|
||||
val timeout = extractUsersHighlightDuration()
|
||||
|
@@ -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
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -234,7 +230,7 @@ private object FileTypePatterns {
|
||||
} else if (fileTypeName == "CMakeLists.txt" || fileName == "CMakeLists") {
|
||||
this.cMakePatterns
|
||||
} else {
|
||||
return null
|
||||
this.htmlPatterns
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
@@ -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()
|
||||
|
@@ -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
|
||||
@@ -144,7 +143,7 @@ internal class ReplaceWithRegister : VimExtension {
|
||||
private fun doReplace(editor: Editor, context: DataContext, caret: ImmutableVimCaret, visualSelection: PutData.VisualSelection) {
|
||||
val registerGroup = injector.registerGroup
|
||||
val lastRegisterChar = if (editor.caretModel.caretCount == 1) registerGroup.currentRegister else registerGroup.getCurrentRegisterForMulticaret()
|
||||
val savedRegister = caret.registerStorage.getRegister(lastRegisterChar) ?: return
|
||||
val savedRegister = registerGroup.getRegister(lastRegisterChar) ?: return
|
||||
|
||||
var usedType = savedRegister.type
|
||||
var usedText = savedRegister.text
|
||||
@@ -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
|
||||
)
|
||||
}
|
||||
|
@@ -0,0 +1,30 @@
|
||||
package com.maddyhome.idea.vim.extension.surround
|
||||
|
||||
import com.intellij.util.text.CharSequenceSubSequence
|
||||
|
||||
internal data class RepeatedCharSequence(val text: CharSequence, val count: Int) : CharSequence {
|
||||
override val length = text.length * count
|
||||
|
||||
override fun get(index: Int): Char {
|
||||
if (index < 0 || index >= length) throw IndexOutOfBoundsException()
|
||||
return text[index % text.length]
|
||||
}
|
||||
|
||||
override fun subSequence(startIndex: Int, endIndex: Int): CharSequence {
|
||||
return CharSequenceSubSequence(this, startIndex, endIndex)
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
return text.repeat(count)
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun of(text: CharSequence, count: Int): CharSequence {
|
||||
return when (count) {
|
||||
0 -> ""
|
||||
1 -> text
|
||||
else -> RepeatedCharSequence(text, count)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -14,6 +14,7 @@ import com.intellij.openapi.editor.Editor
|
||||
import com.maddyhome.idea.vim.VimPlugin
|
||||
import com.maddyhome.idea.vim.api.ExecutionContext
|
||||
import com.maddyhome.idea.vim.api.VimCaret
|
||||
import com.maddyhome.idea.vim.api.VimChangeGroup
|
||||
import com.maddyhome.idea.vim.api.VimEditor
|
||||
import com.maddyhome.idea.vim.api.endsWithNewLine
|
||||
import com.maddyhome.idea.vim.api.getLeadingCharacterOffset
|
||||
@@ -36,7 +37,10 @@ import com.maddyhome.idea.vim.extension.VimExtensionFacade.setRegisterForCaret
|
||||
import com.maddyhome.idea.vim.extension.exportOperatorFunction
|
||||
import com.maddyhome.idea.vim.group.findBlockRange
|
||||
import com.maddyhome.idea.vim.helper.exitVisualMode
|
||||
import com.maddyhome.idea.vim.helper.runWithEveryCaretAndRestore
|
||||
import com.maddyhome.idea.vim.key.OperatorFunction
|
||||
import com.maddyhome.idea.vim.newapi.IjVimCaret
|
||||
import com.maddyhome.idea.vim.newapi.IjVimEditor
|
||||
import com.maddyhome.idea.vim.newapi.ij
|
||||
import com.maddyhome.idea.vim.newapi.vim
|
||||
import com.maddyhome.idea.vim.options.helpers.ClipboardOptionHelper
|
||||
@@ -80,7 +84,7 @@ internal class VimSurroundExtension : VimExtension {
|
||||
putKeyMappingIfMissing(MappingMode.XO, injector.parser.parseKeys("S"), owner, injector.parser.parseKeys("<Plug>VSurround"), true)
|
||||
}
|
||||
|
||||
VimExtensionFacade.exportOperatorFunction(OPERATOR_FUNC, Operator())
|
||||
VimExtensionFacade.exportOperatorFunction(OPERATOR_FUNC, Operator(supportsMultipleCursors = false, count = 1)) // TODO
|
||||
}
|
||||
|
||||
private class YSurroundHandler : ExtensionHandler {
|
||||
@@ -108,7 +112,7 @@ internal class VimSurroundExtension : VimExtension {
|
||||
val lastNonWhiteSpaceOffset = getLastNonWhitespaceCharacterOffset(editor.text(), lineStartOffset, lineEndOffset)
|
||||
if (lastNonWhiteSpaceOffset != null) {
|
||||
val range = TextRange(lineStartOffset, lastNonWhiteSpaceOffset + 1)
|
||||
performSurround(pair, range, it)
|
||||
performSurround(pair, range, it, count = operatorArguments.count1)
|
||||
}
|
||||
// it.moveToOffset(lineStartOffset)
|
||||
}
|
||||
@@ -131,15 +135,13 @@ internal class VimSurroundExtension : VimExtension {
|
||||
|
||||
private class VSurroundHandler : ExtensionHandler {
|
||||
override fun execute(editor: VimEditor, context: ExecutionContext, operatorArguments: OperatorArguments) {
|
||||
val selectionStart = editor.ij.caretModel.primaryCaret.selectionStart
|
||||
// NB: Operator ignores SelectionType anyway
|
||||
if (!Operator().apply(editor, context, editor.mode.selectionType)) {
|
||||
if (!Operator(supportsMultipleCursors = true, count = operatorArguments.count1).apply(editor, context, editor.mode.selectionType)) {
|
||||
return
|
||||
}
|
||||
runWriteAction {
|
||||
// Leave visual mode
|
||||
editor.exitVisualMode()
|
||||
editor.ij.caretModel.moveToOffset(selectionStart)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -160,6 +162,10 @@ internal class VimSurroundExtension : VimExtension {
|
||||
|
||||
companion object {
|
||||
fun change(editor: VimEditor, context: ExecutionContext, charFrom: Char, newSurround: Pair<String, String>?) {
|
||||
editor.ij.runWithEveryCaretAndRestore { changeAtCaret(editor, context, charFrom, newSurround) }
|
||||
}
|
||||
|
||||
fun changeAtCaret(editor: VimEditor, context: ExecutionContext, charFrom: Char, newSurround: Pair<String, String>?) {
|
||||
// Save old register values for carets
|
||||
val surroundings = editor.sortedCarets()
|
||||
.map {
|
||||
@@ -267,21 +273,42 @@ internal class VimSurroundExtension : VimExtension {
|
||||
}
|
||||
}
|
||||
|
||||
private class Operator : OperatorFunction {
|
||||
override fun apply(editor: VimEditor, context: ExecutionContext, selectionType: SelectionType?): Boolean {
|
||||
val ijEditor = editor.ij
|
||||
private class Operator(private val supportsMultipleCursors: Boolean, private val count: Int) : OperatorFunction {
|
||||
override fun apply(vimEditor: VimEditor, context: ExecutionContext, selectionType: SelectionType?): Boolean {
|
||||
val ijEditor = vimEditor.ij
|
||||
val c = getChar(ijEditor)
|
||||
if (c.code == 0) return true
|
||||
|
||||
val pair = getOrInputPair(c, ijEditor, context.ij) ?: return false
|
||||
// XXX: Will it work with line-wise or block-wise selections?
|
||||
val range = getSurroundRange(editor.currentCaret()) ?: return false
|
||||
performSurround(pair, range, editor.currentCaret(), selectionType == SelectionType.LINE_WISE)
|
||||
|
||||
runWriteAction {
|
||||
val change = VimPlugin.getChange()
|
||||
if (supportsMultipleCursors) {
|
||||
ijEditor.runWithEveryCaretAndRestore {
|
||||
applyOnce(ijEditor, change, pair, count)
|
||||
}
|
||||
}
|
||||
else {
|
||||
applyOnce(ijEditor, change, pair, count)
|
||||
// Jump back to start
|
||||
executeNormalWithoutMapping(injector.parser.parseKeys("`["), ijEditor)
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
private fun applyOnce(editor: Editor, change: VimChangeGroup, pair: Pair<String, String>, count: Int) {
|
||||
// XXX: Will it work with line-wise or block-wise selections?
|
||||
val primaryCaret = editor.caretModel.primaryCaret
|
||||
val range = getSurroundRange(primaryCaret.vim)
|
||||
if (range != null) {
|
||||
val start = RepeatedCharSequence.of(pair.first, count)
|
||||
val end = RepeatedCharSequence.of(pair.second, count)
|
||||
change.insertText(IjVimEditor(editor), IjVimCaret(primaryCaret), range.startOffset, start)
|
||||
change.insertText(IjVimEditor(editor), IjVimCaret(primaryCaret), range.endOffset + start.length, end)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getSurroundRange(caret: VimCaret): TextRange? {
|
||||
val editor = caret.editor
|
||||
if (editor.mode is Mode.CMD_LINE) {
|
||||
@@ -375,15 +402,15 @@ private fun getChar(editor: Editor): Char {
|
||||
return res
|
||||
}
|
||||
|
||||
private fun performSurround(pair: Pair<String, String>, range: TextRange, caret: VimCaret, tagsOnNewLines: Boolean = false) {
|
||||
private fun performSurround(pair: Pair<String, String>, range: TextRange, caret: VimCaret, count: Int, tagsOnNewLines: Boolean = false) {
|
||||
runWriteAction {
|
||||
val editor = caret.editor
|
||||
val change = VimPlugin.getChange()
|
||||
val leftSurround = pair.first + if (tagsOnNewLines) "\n" else ""
|
||||
val leftSurround = RepeatedCharSequence.of(pair.first + if (tagsOnNewLines) "\n" else "", count)
|
||||
|
||||
val isEOF = range.endOffset == editor.text().length
|
||||
val hasNewLine = editor.endsWithNewLine()
|
||||
val rightSurround = if (tagsOnNewLines) {
|
||||
val rightSurround = (if (tagsOnNewLines) {
|
||||
if (isEOF && !hasNewLine) {
|
||||
"\n" + pair.second
|
||||
} else {
|
||||
@@ -391,7 +418,7 @@ private fun performSurround(pair: Pair<String, String>, range: TextRange, caret:
|
||||
}
|
||||
} else {
|
||||
pair.second
|
||||
}
|
||||
}).let { RepeatedCharSequence.of(it, count) }
|
||||
|
||||
change.insertText(editor, caret, range.startOffset, leftSurround)
|
||||
change.insertText(editor, caret, range.endOffset + leftSurround.length, rightSurround)
|
||||
|
@@ -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,9 +92,8 @@ public class VimTextObjEntireExtension implements VimExtension {
|
||||
this.ignoreLeadingAndTrailing = ignoreLeadingAndTrailing;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public TextRange getRange(@NotNull VimEditor editor,
|
||||
public @Nullable TextRange getRange(@NotNull VimEditor editor,
|
||||
@NotNull ImmutableVimCaret caret,
|
||||
@NotNull ExecutionContext context,
|
||||
int count,
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -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,9 +96,8 @@ public class VimIndentObject implements VimExtension {
|
||||
this.includeBelow = includeBelow;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public TextRange getRange(@NotNull VimEditor editor,
|
||||
public @Nullable TextRange getRange(@NotNull VimEditor editor,
|
||||
@NotNull ImmutableVimCaret caret,
|
||||
@NotNull ExecutionContext context,
|
||||
int count,
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -39,7 +39,6 @@ import com.maddyhome.idea.vim.newapi.IjVimCaret
|
||||
import com.maddyhome.idea.vim.newapi.IjVimEditor
|
||||
import com.maddyhome.idea.vim.newapi.ij
|
||||
import com.maddyhome.idea.vim.state.mode.Mode
|
||||
import kotlin.math.min
|
||||
|
||||
/**
|
||||
* Provides all the insert/replace related functionality
|
||||
@@ -104,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(
|
||||
@@ -125,6 +129,7 @@ class ChangeGroup : VimChangeGroupBase() {
|
||||
context: ExecutionContext,
|
||||
range: TextRange,
|
||||
) {
|
||||
val startPos = editor.offsetToBufferPosition(caret.offset)
|
||||
val startOffset = editor.getLineStartForOffset(range.startOffset)
|
||||
val endOffset = editor.getLineEndForOffset(range.endOffset)
|
||||
val ijEditor = (editor as IjVimEditor).editor
|
||||
@@ -149,11 +154,7 @@ class ChangeGroup : VimChangeGroupBase() {
|
||||
}
|
||||
}
|
||||
val afterAction = {
|
||||
val firstLine = editor.offsetToBufferPosition(
|
||||
min(startOffset.toDouble(), endOffset.toDouble()).toInt()
|
||||
).line
|
||||
val newOffset = injector.motion.moveCaretToLineStartSkipLeading(editor, firstLine)
|
||||
caret.moveToOffset(newOffset)
|
||||
caret.moveToOffset(injector.motion.moveCaretToLineStartSkipLeading(editor, startPos.line))
|
||||
restoreCursor(editor, caret, (caret as IjVimCaret).caret.logicalPosition.line)
|
||||
}
|
||||
if (project != null) {
|
||||
|
@@ -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());
|
||||
|
@@ -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) {
|
||||
|
@@ -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() {
|
||||
|
@@ -139,7 +139,7 @@ object IjOptions {
|
||||
// Temporary feature flags during development, not really intended for external use
|
||||
val closenotebooks: ToggleOption = addOption(ToggleOption("closenotebooks", GLOBAL, "closenotebooks", true, isHidden = true))
|
||||
val commandOrMotionAnnotation: ToggleOption = addOption(ToggleOption("commandormotionannotation", GLOBAL, "commandormotionannotation", true, isHidden = true))
|
||||
val oldundo: ToggleOption = addOption(ToggleOption("oldundo", GLOBAL, "oldundo", false, isHidden = true))
|
||||
val oldundo: ToggleOption = addOption(ToggleOption("oldundo", GLOBAL, "oldundo", true, isHidden = true))
|
||||
val unifyjumps: ToggleOption = addOption(ToggleOption("unifyjumps", GLOBAL, "unifyjumps", true, isHidden = true))
|
||||
val vimscriptFunctionAnnotation: ToggleOption = addOption(ToggleOption("vimscriptfunctionannotation", GLOBAL, "vimscriptfunctionannotation", true, isHidden = true))
|
||||
|
||||
|
@@ -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;
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,68 @@
|
||||
package com.maddyhome.idea.vim.group
|
||||
|
||||
import com.intellij.codeInsight.daemon.ReferenceImporter
|
||||
import com.intellij.openapi.actionSystem.CommonDataKeys
|
||||
import com.intellij.openapi.actionSystem.DataContext
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.application.ReadAction
|
||||
import com.intellij.openapi.command.WriteCommandAction
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.openapi.fileEditor.FileDocumentManager
|
||||
import com.intellij.openapi.progress.ProgressIndicator
|
||||
import com.intellij.openapi.progress.ProgressManager
|
||||
import com.intellij.openapi.progress.Task
|
||||
import com.intellij.psi.PsiDocumentManager
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiRecursiveElementWalkingVisitor
|
||||
import java.util.function.BooleanSupplier
|
||||
|
||||
internal object MacroAutoImport {
|
||||
fun run(editor: Editor, dataContext: DataContext) {
|
||||
val project = CommonDataKeys.PROJECT.getData(dataContext) ?: return
|
||||
val file = PsiDocumentManager.getInstance(project).getPsiFile(editor.document) ?: return
|
||||
|
||||
if (!FileDocumentManager.getInstance().requestWriting(editor.document, project)) {
|
||||
return
|
||||
}
|
||||
|
||||
val importers = ReferenceImporter.EP_NAME.extensionList
|
||||
if (importers.isEmpty()) {
|
||||
return
|
||||
}
|
||||
|
||||
ProgressManager.getInstance().run(object : Task.Backgroundable(project, "Auto import", true) {
|
||||
override fun run(indicator: ProgressIndicator) {
|
||||
val fixes = ReadAction.nonBlocking<List<BooleanSupplier>> {
|
||||
val fixes = mutableListOf<BooleanSupplier>()
|
||||
|
||||
file.accept(object : PsiRecursiveElementWalkingVisitor() {
|
||||
override fun visitElement(element: PsiElement) {
|
||||
for (reference in element.references) {
|
||||
if (reference.resolve() != null) {
|
||||
continue
|
||||
}
|
||||
for (importer in importers) {
|
||||
importer.computeAutoImportAtOffset(editor, file, element.textRange.startOffset, true)
|
||||
?.let(fixes::add)
|
||||
}
|
||||
}
|
||||
super.visitElement(element)
|
||||
}
|
||||
})
|
||||
|
||||
return@nonBlocking fixes
|
||||
}.executeSynchronously()
|
||||
|
||||
ApplicationManager.getApplication().invokeAndWait {
|
||||
WriteCommandAction.writeCommandAction(project)
|
||||
.withName("Auto Import")
|
||||
.withGroupId("IdeaVimAutoImportAfterMacro")
|
||||
.shouldRecordActionForActiveDocument(true)
|
||||
.run<RuntimeException> {
|
||||
fixes.forEach { it.asBoolean }
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
@@ -22,6 +22,7 @@ import com.maddyhome.idea.vim.api.injector
|
||||
import com.maddyhome.idea.vim.helper.MessageHelper.message
|
||||
import com.maddyhome.idea.vim.macro.VimMacroBase
|
||||
import com.maddyhome.idea.vim.newapi.IjVimEditor
|
||||
import com.maddyhome.idea.vim.newapi.ij
|
||||
|
||||
/**
|
||||
* Used to handle playback of macros
|
||||
@@ -93,6 +94,9 @@ internal class MacroGroup : VimMacroBase() {
|
||||
} finally {
|
||||
keyStack.removeFirst()
|
||||
}
|
||||
if (!isInternalMacro) {
|
||||
MacroAutoImport.run(editor.ij, context.ij)
|
||||
}
|
||||
}
|
||||
|
||||
if (isInternalMacro) {
|
||||
|
@@ -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 -> {}
|
||||
}
|
||||
|
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -326,7 +326,7 @@ public class EditorHelper {
|
||||
|
||||
final int offset = y - ((screenHeight - lineHeight) / lineHeight / 2 * lineHeight);
|
||||
@NotNull final VimEditor editor1 = new IjVimEditor(editor);
|
||||
final int lastVisualLine = EngineEditorHelperKt.getVisualLineCount(editor1) - 1;
|
||||
final int lastVisualLine = EngineEditorHelperKt.getVisualLineCount(editor1) + editor.getSettings().getAdditionalLinesCount();
|
||||
final int offsetForLastLineAtBottom = getOffsetToScrollVisualLineToBottomOfScreen(editor, lastVisualLine);
|
||||
|
||||
// For `zz`, we want to use virtual space and move any line, including the last one, to the middle of the screen.
|
||||
|
@@ -12,6 +12,7 @@ package com.maddyhome.idea.vim.helper
|
||||
|
||||
import com.intellij.codeWithMe.ClientId
|
||||
import com.intellij.openapi.editor.Caret
|
||||
import com.intellij.openapi.editor.CaretState
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.openapi.editor.ex.util.EditorUtil
|
||||
import com.intellij.openapi.fileEditor.ex.FileEditorManagerEx
|
||||
@@ -20,6 +21,8 @@ import com.maddyhome.idea.vim.api.StringListOptionValue
|
||||
import com.maddyhome.idea.vim.api.injector
|
||||
import com.maddyhome.idea.vim.group.IjOptionConstants
|
||||
import com.maddyhome.idea.vim.newapi.globalIjOptions
|
||||
import com.maddyhome.idea.vim.newapi.vim
|
||||
import com.maddyhome.idea.vim.state.mode.inBlockSelection
|
||||
import java.awt.Component
|
||||
import javax.swing.JComponent
|
||||
import javax.swing.JTable
|
||||
@@ -96,3 +99,41 @@ internal val Caret.vimLine: Int
|
||||
*/
|
||||
internal val Editor.vimLine: Int
|
||||
get() = this.caretModel.currentCaret.vimLine
|
||||
|
||||
internal inline fun Editor.runWithEveryCaretAndRestore(action: () -> Unit) {
|
||||
val caretModel = this.caretModel
|
||||
val carets = if (this.vim.inBlockSelection) null else caretModel.allCarets
|
||||
if (carets == null || carets.size == 1) {
|
||||
action()
|
||||
}
|
||||
else {
|
||||
var initialDocumentSize = this.document.textLength
|
||||
var documentSizeDifference = 0
|
||||
|
||||
val caretOffsets = carets.map { it.selectionStart to it.selectionEnd }
|
||||
val restoredCarets = mutableListOf<CaretState>()
|
||||
|
||||
caretModel.removeSecondaryCarets()
|
||||
|
||||
for ((selectionStart, selectionEnd) in caretOffsets) {
|
||||
if (selectionStart == selectionEnd) {
|
||||
caretModel.primaryCaret.moveToOffset(selectionStart + documentSizeDifference)
|
||||
}
|
||||
else {
|
||||
caretModel.primaryCaret.setSelection(
|
||||
selectionStart + documentSizeDifference,
|
||||
selectionEnd + documentSizeDifference
|
||||
)
|
||||
}
|
||||
|
||||
action()
|
||||
restoredCarets.add(caretModel.caretsAndSelections.single())
|
||||
|
||||
val documentLength = this.document.textLength
|
||||
documentSizeDifference += documentLength - initialDocumentSize
|
||||
initialDocumentSize = documentLength
|
||||
}
|
||||
|
||||
caretModel.caretsAndSelections = restoredCarets
|
||||
}
|
||||
}
|
||||
|
@@ -20,6 +20,7 @@ import com.intellij.openapi.actionSystem.PlatformDataKeys
|
||||
import com.intellij.openapi.actionSystem.ex.ActionUtil
|
||||
import com.intellij.openapi.actionSystem.ex.ActionUtil.performDumbAwareWithCallbacks
|
||||
import com.intellij.openapi.actionSystem.impl.ProxyShortcutSet
|
||||
import com.intellij.openapi.actionSystem.impl.Utils
|
||||
import com.intellij.openapi.application.ex.ApplicationManagerEx
|
||||
import com.intellij.openapi.command.CommandProcessor
|
||||
import com.intellij.openapi.command.UndoConfirmationPolicy
|
||||
@@ -60,6 +61,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
|
||||
@@ -92,6 +96,7 @@ internal class IjActionExecutor : VimActionExecutor {
|
||||
ActionManager.getInstance(),
|
||||
0,
|
||||
)
|
||||
Utils.initUpdateSession(event)
|
||||
// beforeActionPerformedUpdate should be called to update the action. It fixes some rider-specific problems.
|
||||
// because rider use async update method. See VIM-1819.
|
||||
// This method executes inside of lastUpdateAndCheckDumb
|
||||
|
@@ -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))
|
||||
}
|
||||
|
@@ -60,7 +60,7 @@ internal object ScrollViewHelper {
|
||||
// that this needs to be replaced as a more or less dumb line for line rewrite.
|
||||
val topLine = getVisualLineAtTopOfScreen(editor)
|
||||
val bottomLine = getVisualLineAtBottomOfScreen(editor)
|
||||
val lastLine = vimEditor.getVisualLineCount() - 1
|
||||
val lastLine = vimEditor.getVisualLineCount() + editor.settings.additionalLinesCount
|
||||
|
||||
// We need the non-normalised value here, so we can handle cases such as so=999 to keep the current line centred
|
||||
val scrollOffset = injector.options(vimEditor).scrolloff
|
||||
|
@@ -28,6 +28,8 @@ import com.maddyhome.idea.vim.common.InsertSequence
|
||||
import com.maddyhome.idea.vim.newapi.IjVimCaret
|
||||
import com.maddyhome.idea.vim.newapi.globalIjOptions
|
||||
import com.maddyhome.idea.vim.newapi.ij
|
||||
import com.maddyhome.idea.vim.state.mode.SelectionType
|
||||
import com.maddyhome.idea.vim.state.mode.inVisualMode
|
||||
import com.maddyhome.idea.vim.undo.UndoRedoBase
|
||||
|
||||
/**
|
||||
@@ -66,15 +68,7 @@ internal class UndoRedoHelper : UndoRedoBase() {
|
||||
// TODO refactor me after VIM-308 when restoring selection and caret movement will be ignored by undo
|
||||
editor.runWithChangeTracking {
|
||||
undoManager.undo(fileEditor)
|
||||
|
||||
// We execute undo one more time if the previous one just restored selection
|
||||
if (!hasChanges && hasSelection(editor) && undoManager.isUndoAvailable(fileEditor)) {
|
||||
undoManager.undo(fileEditor)
|
||||
}
|
||||
}
|
||||
|
||||
CommandProcessor.getInstance().runUndoTransparentAction {
|
||||
removeSelections(editor)
|
||||
restoreVisualMode(editor)
|
||||
}
|
||||
} else {
|
||||
notifyAboutNewUndo(editor.ij.project)
|
||||
@@ -229,4 +223,21 @@ internal class UndoRedoHelper : UndoRedoBase() {
|
||||
val hasChanges: Boolean
|
||||
get() = changeListener.hasChanged || initialPath != editor.getPath()
|
||||
}
|
||||
|
||||
private fun restoreVisualMode(editor: VimEditor) {
|
||||
if (!editor.inVisualMode && editor.getSelectionModel().hasSelection()) {
|
||||
val detectedMode = VimPlugin.getVisualMotion().autodetectVisualSubmode(editor)
|
||||
|
||||
// Visual block selection is restored into multiple carets, so multi-carets that form a block are always
|
||||
// identified as visual block mode, leading to false positives.
|
||||
// Since I use visual block mode much less often than multi-carets, this is a judgment call to never restore
|
||||
// visual block mode.
|
||||
val wantedMode = if (detectedMode == SelectionType.BLOCK_WISE)
|
||||
SelectionType.CHARACTER_WISE
|
||||
else
|
||||
detectedMode
|
||||
|
||||
VimPlugin.getVisualMotion().enterVisualMode(editor, wantedMode)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -18,13 +18,13 @@ import com.intellij.openapi.editor.VisualPosition
|
||||
import com.intellij.openapi.editor.markup.RangeHighlighter
|
||||
import com.intellij.openapi.util.Key
|
||||
import com.intellij.openapi.util.UserDataHolder
|
||||
import com.maddyhome.idea.vim.api.CaretRegisterStorageBase
|
||||
import com.maddyhome.idea.vim.api.LocalMarkStorage
|
||||
import com.maddyhome.idea.vim.api.SelectionInfo
|
||||
import com.maddyhome.idea.vim.common.InsertSequence
|
||||
import com.maddyhome.idea.vim.ex.ExOutputModel
|
||||
import com.maddyhome.idea.vim.group.visual.VisualChange
|
||||
import com.maddyhome.idea.vim.group.visual.vimLeadSelectionOffset
|
||||
import com.maddyhome.idea.vim.common.InsertSequence
|
||||
import com.maddyhome.idea.vim.common.VimEditorReplaceMask
|
||||
import com.maddyhome.idea.vim.newapi.vim
|
||||
import com.maddyhome.idea.vim.state.VimStateMachine
|
||||
import com.maddyhome.idea.vim.state.mode.Mode
|
||||
@@ -96,7 +96,6 @@ internal var Caret.vimInsertStart: RangeMarker by userDataOr {
|
||||
}
|
||||
|
||||
// TODO: Data could be lost during visual block motion
|
||||
internal var Caret.registerStorage: CaretRegisterStorageBase? by userDataCaretToEditor()
|
||||
internal var Caret.markStorage: LocalMarkStorage? by userDataCaretToEditor()
|
||||
internal var Caret.lastSelectionInfo: SelectionInfo? by userDataCaretToEditor()
|
||||
|
||||
@@ -126,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() }
|
||||
|
@@ -1,32 +0,0 @@
|
||||
/*
|
||||
* Copyright 2003-2023 The IdeaVim authors
|
||||
*
|
||||
* Use of this source code is governed by an MIT-style
|
||||
* license that can be found in the LICENSE.txt file or at
|
||||
* https://opensource.org/licenses/MIT.
|
||||
*/
|
||||
|
||||
package com.maddyhome.idea.vim.helper
|
||||
|
||||
import com.intellij.ide.plugins.StandalonePluginUpdateChecker
|
||||
import com.intellij.openapi.components.Service
|
||||
import com.intellij.openapi.components.service
|
||||
import com.maddyhome.idea.vim.VimPlugin
|
||||
import com.maddyhome.idea.vim.group.NotificationService
|
||||
import com.maddyhome.idea.vim.icons.VimIcons
|
||||
|
||||
@Service(Service.Level.APP)
|
||||
internal class VimStandalonePluginUpdateChecker : StandalonePluginUpdateChecker(
|
||||
VimPlugin.getPluginId(),
|
||||
updateTimestampProperty = PROPERTY_NAME,
|
||||
NotificationService.IDEAVIM_STICKY_GROUP,
|
||||
VimIcons.IDEAVIM,
|
||||
) {
|
||||
|
||||
override fun skipUpdateCheck(): Boolean = VimPlugin.isNotEnabled() || "dev" in VimPlugin.getVersion()
|
||||
|
||||
companion object {
|
||||
private const val PROPERTY_NAME = "ideavim.statistics.timestamp"
|
||||
fun getInstance(): VimStandalonePluginUpdateChecker = service()
|
||||
}
|
||||
}
|
@@ -10,15 +10,12 @@ package com.maddyhome.idea.vim.listener
|
||||
|
||||
import com.intellij.execution.impl.ConsoleViewImpl
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.editor.EditorKind
|
||||
import com.maddyhome.idea.vim.KeyHandler
|
||||
import com.maddyhome.idea.vim.VimPlugin
|
||||
import com.maddyhome.idea.vim.api.ExecutionContext
|
||||
import com.maddyhome.idea.vim.api.VimEditor
|
||||
import com.maddyhome.idea.vim.api.injector
|
||||
import com.maddyhome.idea.vim.command.OperatorArguments
|
||||
import com.maddyhome.idea.vim.common.EditorListener
|
||||
import com.maddyhome.idea.vim.helper.EditorHelper
|
||||
import com.maddyhome.idea.vim.helper.inInsertMode
|
||||
import com.maddyhome.idea.vim.newapi.ij
|
||||
import com.maddyhome.idea.vim.state.mode.Mode
|
||||
@@ -63,17 +60,11 @@ class IJEditorFocusListener : EditorListener {
|
||||
val context: ExecutionContext = injector.executionContextManager.getEditorExecutionContext(editor)
|
||||
VimPlugin.getChange().insertBeforeCursor(editor, context)
|
||||
}
|
||||
if (!ijEditor.isViewer &&
|
||||
!EditorHelper.isFileEditor(ijEditor) &&
|
||||
ijEditor.document.isWritable &&
|
||||
!ijEditor.inInsertMode && ijEditor.editorKind != EditorKind.DIFF
|
||||
) {
|
||||
switchToInsertMode.run()
|
||||
} else if (!ijEditor.document.isWritable) {
|
||||
if (!ijEditor.document.isWritable) {
|
||||
val context: ExecutionContext = injector.executionContextManager.getEditorExecutionContext(editor)
|
||||
val mode = injector.vimState.mode
|
||||
when (mode) {
|
||||
is Mode.INSERT -> editor.exitInsertMode(context, OperatorArguments(false, 0, mode))
|
||||
is Mode.INSERT -> editor.exitInsertMode(context)
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
@@ -87,3 +78,4 @@ class IJEditorFocusListener : EditorListener {
|
||||
KeyHandler.getInstance().reset(editor)
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -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
|
||||
@@ -28,6 +30,7 @@ import com.intellij.openapi.actionSystem.CommonDataKeys
|
||||
import com.intellij.openapi.actionSystem.ex.AnActionListener
|
||||
import com.intellij.openapi.actionSystem.impl.ProxyShortcutSet
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.openapi.editor.impl.ScrollingModelImpl
|
||||
import com.intellij.openapi.keymap.KeymapManager
|
||||
import com.intellij.openapi.project.DumbAwareToggleAction
|
||||
import com.intellij.openapi.util.TextRange
|
||||
@@ -58,6 +61,7 @@ internal object IdeaSpecifics {
|
||||
private val surrounderAction =
|
||||
"com.intellij.codeInsight.generation.surroundWith.SurroundWithHandler\$InvokeSurrounderAction"
|
||||
private var editor: Editor? = null
|
||||
private var caretOffset = -1
|
||||
private var completionPrevDocumentLength: Int? = null
|
||||
private var completionPrevDocumentOffset: Int? = null
|
||||
|
||||
@@ -67,6 +71,7 @@ internal object IdeaSpecifics {
|
||||
val hostEditor = event.dataContext.getData(CommonDataKeys.HOST_EDITOR)
|
||||
if (hostEditor != null) {
|
||||
editor = hostEditor
|
||||
caretOffset = hostEditor.caretModel.offset
|
||||
}
|
||||
|
||||
val isVimAction = (action as? AnActionWrapper)?.delegate is VimShortcutKeyAction
|
||||
@@ -115,7 +120,8 @@ internal object IdeaSpecifics {
|
||||
if (VimPlugin.isNotEnabled()) return
|
||||
|
||||
val editor = editor
|
||||
if (editor != null && action is ChooseItemAction && injector.registerGroup.isRecording) {
|
||||
if (editor != null) {
|
||||
if (action is ChooseItemAction && injector.registerGroup.isRecording) {
|
||||
val prevDocumentLength = completionPrevDocumentLength
|
||||
val prevDocumentOffset = completionPrevDocumentOffset
|
||||
|
||||
@@ -148,9 +154,27 @@ 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) {
|
||||
val scrollModel = editor.scrollingModel as ScrollingModelImpl
|
||||
if (scrollModel.isScrollingNow) {
|
||||
val v = scrollModel.verticalScrollOffset
|
||||
val h = scrollModel.horizontalScrollOffset
|
||||
scrollModel.finishAnimation()
|
||||
scrollModel.scroll(h, v)
|
||||
scrollModel.finishAnimation()
|
||||
}
|
||||
injector.scroll.scrollCaretIntoView(editor.vim)
|
||||
}
|
||||
}
|
||||
|
||||
this.editor = null
|
||||
this.caretOffset = -1
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -35,6 +35,7 @@ import com.intellij.openapi.editor.ex.DocumentEx
|
||||
import com.intellij.openapi.editor.ex.EditorEventMulticasterEx
|
||||
import com.intellij.openapi.editor.ex.FocusChangeListener
|
||||
import com.intellij.openapi.editor.impl.EditorComponentImpl
|
||||
import com.intellij.openapi.editor.impl.EditorImpl
|
||||
import com.intellij.openapi.fileEditor.FileEditorManager
|
||||
import com.intellij.openapi.fileEditor.FileEditorManagerEvent
|
||||
import com.intellij.openapi.fileEditor.FileEditorManagerListener
|
||||
@@ -45,11 +46,14 @@ import com.intellij.openapi.fileEditor.ex.FileEditorWithProvider
|
||||
import com.intellij.openapi.fileEditor.impl.EditorComposite
|
||||
import com.intellij.openapi.fileEditor.impl.EditorWindow
|
||||
import com.intellij.openapi.project.ProjectManager
|
||||
import com.intellij.openapi.rd.createLifetime
|
||||
import com.intellij.openapi.rd.createNestedDisposable
|
||||
import com.intellij.openapi.util.Disposer
|
||||
import com.intellij.openapi.util.Key
|
||||
import com.intellij.openapi.util.removeUserData
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.util.ExceptionUtil
|
||||
import com.jetbrains.rd.util.lifetime.Lifetime
|
||||
import com.maddyhome.idea.vim.EventFacade
|
||||
import com.maddyhome.idea.vim.KeyHandler
|
||||
import com.maddyhome.idea.vim.VimKeyListener
|
||||
@@ -62,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
|
||||
@@ -79,7 +82,6 @@ import com.maddyhome.idea.vim.handler.keyCheckRequests
|
||||
import com.maddyhome.idea.vim.helper.CaretVisualAttributesListener
|
||||
import com.maddyhome.idea.vim.helper.GuicursorChangeListener
|
||||
import com.maddyhome.idea.vim.helper.StrictMode
|
||||
import com.maddyhome.idea.vim.helper.VimStandalonePluginUpdateChecker
|
||||
import com.maddyhome.idea.vim.helper.exitSelectMode
|
||||
import com.maddyhome.idea.vim.helper.exitVisualMode
|
||||
import com.maddyhome.idea.vim.helper.forceBarCursor
|
||||
@@ -95,6 +97,7 @@ import com.maddyhome.idea.vim.newapi.IjVimSearchGroup
|
||||
import com.maddyhome.idea.vim.newapi.InsertTimeRecorder
|
||||
import com.maddyhome.idea.vim.newapi.ij
|
||||
import com.maddyhome.idea.vim.newapi.vim
|
||||
import com.maddyhome.idea.vim.state.mode.Mode
|
||||
import com.maddyhome.idea.vim.state.mode.inSelectMode
|
||||
import com.maddyhome.idea.vim.state.mode.selectionType
|
||||
import com.maddyhome.idea.vim.ui.ShowCmdOptionChangeListener
|
||||
@@ -103,7 +106,6 @@ import com.maddyhome.idea.vim.ui.widgets.macro.MacroWidgetListener
|
||||
import com.maddyhome.idea.vim.ui.widgets.macro.macroWidgetOptionListener
|
||||
import com.maddyhome.idea.vim.ui.widgets.mode.listeners.ModeWidgetListener
|
||||
import com.maddyhome.idea.vim.ui.widgets.mode.modeWidgetOptionListener
|
||||
import com.maddyhome.idea.vim.vimDisposable
|
||||
import java.awt.event.MouseAdapter
|
||||
import java.awt.event.MouseEvent
|
||||
import javax.swing.SwingUtilities
|
||||
@@ -285,12 +287,10 @@ internal object VimListenerManager {
|
||||
// TODO: If the user changes the 'ideavimsupport' option, existing editors won't be initialised
|
||||
if (vimDisabled(editor)) return
|
||||
|
||||
// As I understand, there is no need to pass a disposable that also disposes on editor close
|
||||
// because all editor resources will be garbage collected anyway on editor close
|
||||
// Note that this uses the plugin's main disposable, rather than VimPlugin.onOffDisposable, because we don't need
|
||||
// to - we explicitly call VimListenerManager.removeAll from VimPlugin.turnOffPlugin, and this disposes each
|
||||
// editor's disposable individually.
|
||||
val disposable = editor.project?.vimDisposable ?: return
|
||||
val pluginLifetime = VimPlugin.getInstance().createLifetime()
|
||||
val editorLifetime = (editor as EditorImpl).disposable.createLifetime()
|
||||
val disposable =
|
||||
Lifetime.intersect(pluginLifetime, editorLifetime).createNestedDisposable("MyLifetimedDisposable")
|
||||
|
||||
// Protect against double initialisation
|
||||
if (editor.getUserData(editorListenersDisposableKey) != null) {
|
||||
@@ -387,6 +387,17 @@ internal object VimListenerManager {
|
||||
// We can't rely on being passed a non-null editor, so check for Code With Me scenarios explicitly
|
||||
if (VimPlugin.isNotEnabled() || !ClientId.isCurrentlyUnderLocalId) return
|
||||
|
||||
val newEditor = event.newEditor
|
||||
if (newEditor is TextEditor) {
|
||||
val editor = newEditor.editor
|
||||
if (editor.isInsertMode) {
|
||||
editor.vim.mode = Mode.NORMAL()
|
||||
KeyHandler.getInstance().reset(editor.vim)
|
||||
}
|
||||
// Breaks relativenumber for some reason
|
||||
// injector.scroll.scrollCaretIntoView(editor.vim)
|
||||
}
|
||||
|
||||
MotionGroup.fileEditorManagerSelectionChangedCallback(event)
|
||||
FileGroup.fileEditorManagerSelectionChangedCallback(event)
|
||||
VimPlugin.getSearch().fileEditorManagerSelectionChangedCallback(event)
|
||||
@@ -458,8 +469,6 @@ internal object VimListenerManager {
|
||||
|
||||
event.editor.putUserData(openingEditorKey, OpeningEditor(openingEditor, owningEditorWindow, isPreview, canBeReused))
|
||||
}
|
||||
|
||||
VimStandalonePluginUpdateChecker.getInstance().pluginUsed()
|
||||
}
|
||||
|
||||
override fun editorReleased(event: EditorFactoryEvent) {
|
||||
@@ -739,7 +748,7 @@ internal object VimListenerManager {
|
||||
injector.commandLine.getActiveCommandLine()?.close(refocusOwningEditor = true, resetCaret = false)
|
||||
injector.modalInput.getCurrentModalInput()?.deactivate(refocusOwningEditor = true, resetCaret = false)
|
||||
|
||||
ExOutputModel.tryGetInstance(editor)?.close()
|
||||
injector.outputPanel.getCurrentOutputPanel()?.close()
|
||||
|
||||
val caretModel = editor.caretModel
|
||||
if (editor.vim.mode.selectionType != null) {
|
||||
@@ -768,7 +777,7 @@ internal object VimListenerManager {
|
||||
injector.commandLine.getActiveCommandLine()?.close(refocusOwningEditor = true, resetCaret = false)
|
||||
injector.modalInput.getCurrentModalInput()?.deactivate(refocusOwningEditor = true, resetCaret = false)
|
||||
|
||||
ExOutputModel.getInstance(event.editor).close()
|
||||
injector.outputPanel.getCurrentOutputPanel()?.close()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -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
|
||||
|
@@ -12,8 +12,6 @@ import com.intellij.openapi.editor.Caret
|
||||
import com.intellij.openapi.editor.LogicalPosition
|
||||
import com.intellij.openapi.editor.VisualPosition
|
||||
import com.maddyhome.idea.vim.api.BufferPosition
|
||||
import com.maddyhome.idea.vim.api.CaretRegisterStorage
|
||||
import com.maddyhome.idea.vim.api.CaretRegisterStorageBase
|
||||
import com.maddyhome.idea.vim.api.ImmutableVimCaret
|
||||
import com.maddyhome.idea.vim.api.LocalMarkStorage
|
||||
import com.maddyhome.idea.vim.api.SelectionInfo
|
||||
@@ -29,7 +27,6 @@ import com.maddyhome.idea.vim.helper.insertHistory
|
||||
import com.maddyhome.idea.vim.helper.lastSelectionInfo
|
||||
import com.maddyhome.idea.vim.helper.markStorage
|
||||
import com.maddyhome.idea.vim.helper.moveToInlayAwareOffset
|
||||
import com.maddyhome.idea.vim.helper.registerStorage
|
||||
import com.maddyhome.idea.vim.helper.resetVimLastColumn
|
||||
import com.maddyhome.idea.vim.helper.vimInsertStart
|
||||
import com.maddyhome.idea.vim.helper.vimLastColumn
|
||||
@@ -41,18 +38,6 @@ import com.maddyhome.idea.vim.state.mode.SelectionType
|
||||
|
||||
internal class IjVimCaret(val caret: Caret) : VimCaretBase() {
|
||||
|
||||
override val registerStorage: CaretRegisterStorage
|
||||
get() {
|
||||
var storage = this.caret.registerStorage
|
||||
if (storage == null) {
|
||||
initInjector() // To initialize injector used in CaretRegisterStorageBase
|
||||
storage = CaretRegisterStorageBase(this)
|
||||
this.caret.registerStorage = storage
|
||||
} else if (storage.caret != this) {
|
||||
storage.caret = this
|
||||
}
|
||||
return storage
|
||||
}
|
||||
override val markStorage: LocalMarkStorage
|
||||
get() {
|
||||
var storage = this.caret.markStorage
|
||||
|
@@ -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()
|
||||
|
||||
@@ -165,21 +171,38 @@ internal class IjVimEditor(editor: Editor) : MutableLinearEditor, VimEditorBase(
|
||||
return editor.caretModel.allCarets.map { IjVimCaret(it) }
|
||||
}
|
||||
|
||||
override var isFirstCaret = true
|
||||
override var isReversingCarets = false
|
||||
|
||||
@Suppress("ideavimRunForEachCaret")
|
||||
override fun forEachCaret(action: (VimCaret) -> Unit) {
|
||||
if (editor.vim.inBlockSelection) {
|
||||
action(IjVimCaret(editor.caretModel.primaryCaret))
|
||||
} else {
|
||||
try {
|
||||
editor.caretModel.runForEachCaret({
|
||||
if (it.isValid) {
|
||||
action(IjVimCaret(it))
|
||||
isFirstCaret = false
|
||||
}
|
||||
}, false)
|
||||
} finally {
|
||||
isFirstCaret = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun forEachNativeCaret(action: (VimCaret) -> Unit, reverse: Boolean) {
|
||||
editor.caretModel.runForEachCaret({ action(IjVimCaret(it)) }, reverse)
|
||||
isReversingCarets = reverse
|
||||
try {
|
||||
editor.caretModel.runForEachCaret({
|
||||
action(IjVimCaret(it))
|
||||
isFirstCaret = false
|
||||
}, reverse)
|
||||
} finally {
|
||||
isFirstCaret = true
|
||||
isReversingCarets = false
|
||||
}
|
||||
}
|
||||
|
||||
override fun isInForEachCaretScope(): Boolean {
|
||||
@@ -381,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) {
|
||||
@@ -454,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
|
||||
|
@@ -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;
|
@@ -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)
|
||||
|
@@ -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>()
|
||||
}
|
||||
}
|
@@ -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;
|
||||
}
|
||||
|
@@ -7,7 +7,6 @@
|
||||
*/
|
||||
package com.maddyhome.idea.vim.ui.ex
|
||||
|
||||
import com.intellij.openapi.diagnostic.debug
|
||||
import com.intellij.openapi.diagnostic.logger
|
||||
import com.maddyhome.idea.vim.KeyHandler
|
||||
import com.maddyhome.idea.vim.api.injector
|
||||
@@ -15,50 +14,12 @@ import com.maddyhome.idea.vim.newapi.vim
|
||||
import org.jetbrains.annotations.NonNls
|
||||
import java.awt.event.ActionEvent
|
||||
import java.awt.event.KeyEvent
|
||||
import javax.swing.Action
|
||||
import javax.swing.KeyStroke
|
||||
import javax.swing.text.DefaultEditorKit
|
||||
import javax.swing.text.Document
|
||||
import javax.swing.text.TextAction
|
||||
|
||||
@Deprecated("ExCommands should be migrated to KeyHandler like commands for other modes")
|
||||
internal object ExEditorKit : DefaultEditorKit() {
|
||||
|
||||
@NonNls
|
||||
val CancelEntry: String = "cancel-entry"
|
||||
|
||||
@NonNls
|
||||
val CompleteEntry: String = "complete-entry"
|
||||
|
||||
@NonNls
|
||||
val EscapeChar: String = "escape"
|
||||
|
||||
@NonNls
|
||||
val DeleteToCursor: String = "delete-to-cursor"
|
||||
|
||||
@NonNls
|
||||
val ToggleInsertReplace: String = "toggle-insert"
|
||||
|
||||
@NonNls
|
||||
val HistoryUp: String = "history-up"
|
||||
|
||||
@NonNls
|
||||
val HistoryDown: String = "history-down"
|
||||
|
||||
@NonNls
|
||||
val HistoryUpFilter: String = "history-up-filter"
|
||||
|
||||
@NonNls
|
||||
val HistoryDownFilter: String = "history-down-filter"
|
||||
|
||||
@NonNls
|
||||
val StartDigraph: String = "start-digraph"
|
||||
|
||||
@NonNls
|
||||
val StartLiteral: String = "start-literal"
|
||||
|
||||
private val logger = logger<ExEditorKit>()
|
||||
|
||||
/**
|
||||
* Gets the MIME type of the data that this
|
||||
* kit represents support for.
|
||||
@@ -70,19 +31,6 @@ internal object ExEditorKit : DefaultEditorKit() {
|
||||
return "text/ideavim"
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches the set of commands that can be used
|
||||
* on a text component that is using a model and
|
||||
* view produced by this kit.
|
||||
*
|
||||
* @return the set of actions
|
||||
*/
|
||||
override fun getActions(): Array<Action> {
|
||||
val res = TextAction.augmentList(super.getActions(), exActions)
|
||||
logger.debug { "res.length=${res.size}" }
|
||||
return res
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an uninitialized text storage model
|
||||
* that is appropriate for this type of editor.
|
||||
@@ -93,28 +41,10 @@ internal object ExEditorKit : DefaultEditorKit() {
|
||||
return ExDocument()
|
||||
}
|
||||
|
||||
private val exActions = arrayOf<Action>(
|
||||
CancelEntryAction(),
|
||||
CompleteEntryAction(),
|
||||
EscapeCharAction(),
|
||||
DeleteNextCharAction(),
|
||||
DeletePreviousCharAction(),
|
||||
DeletePreviousWordAction(),
|
||||
DeleteToCursorAction(),
|
||||
HistoryUpAction(),
|
||||
HistoryDownAction(),
|
||||
HistoryUpFilterAction(),
|
||||
HistoryDownFilterAction(),
|
||||
ToggleInsertReplaceAction(),
|
||||
)
|
||||
|
||||
class DefaultExKeyHandler : DefaultKeyTypedAction() {
|
||||
override fun actionPerformed(e: ActionEvent) {
|
||||
val target = getTextComponent(e) as ExTextField
|
||||
val currentAction = target.currentAction
|
||||
if (currentAction != null) {
|
||||
currentAction.actionPerformed(e)
|
||||
} else {
|
||||
|
||||
val key = convert(e)
|
||||
if (key != null) {
|
||||
val c = key.keyChar
|
||||
@@ -137,7 +67,6 @@ internal object ExEditorKit : DefaultEditorKit() {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun convert(event: ActionEvent): KeyStroke? {
|
||||
val cmd = event.actionCommand
|
||||
|
@@ -23,7 +23,10 @@ import com.maddyhome.idea.vim.EventFacade;
|
||||
import com.maddyhome.idea.vim.KeyHandler;
|
||||
import com.maddyhome.idea.vim.VimPlugin;
|
||||
import com.maddyhome.idea.vim.action.VimShortcutKeyAction;
|
||||
import com.maddyhome.idea.vim.api.*;
|
||||
import com.maddyhome.idea.vim.api.VimCommandLine;
|
||||
import com.maddyhome.idea.vim.api.VimCommandLineCaret;
|
||||
import com.maddyhome.idea.vim.api.VimEditor;
|
||||
import com.maddyhome.idea.vim.api.VimKeyGroupBase;
|
||||
import com.maddyhome.idea.vim.ex.ranges.LineRange;
|
||||
import com.maddyhome.idea.vim.helper.SearchHighlightsHelper;
|
||||
import com.maddyhome.idea.vim.helper.UiHelper;
|
||||
@@ -60,7 +63,7 @@ import static com.maddyhome.idea.vim.group.KeyGroup.toShortcutSet;
|
||||
public class ExEntryPanel extends JPanel implements VimCommandLine {
|
||||
public static ExEntryPanel instance;
|
||||
public static ExEntryPanel instanceWithoutShortcuts;
|
||||
private boolean isReplaceMode = false;
|
||||
public boolean isReplaceMode = false;
|
||||
private WeakReference<Editor> weakEditor = null;
|
||||
|
||||
private VimInputInterceptor myInputInterceptor = null;
|
||||
@@ -341,14 +344,14 @@ 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) {
|
||||
if ((labelText.equals("/") || labelText.equals("?") || searchCommand) && !injector.getMacro().isExecutingMacro()) {
|
||||
final boolean forwards = !labelText.equals("?"); // :s, :g, :v are treated as forwards
|
||||
int pattenEnd = injector.getSearchGroup().findEndOfPattern(searchText, separator, 0);
|
||||
final String pattern = searchText.substring(0, pattenEnd);
|
||||
@@ -402,7 +405,7 @@ public class ExEntryPanel extends JPanel implements VimCommandLine {
|
||||
|
||||
@Override
|
||||
public void toggleReplaceMode() {
|
||||
isReplaceMode = !isReplaceMode;
|
||||
entry.toggleInsertReplace();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -528,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()));
|
||||
}
|
||||
|
||||
@@ -547,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;
|
||||
}
|
||||
@@ -569,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;
|
||||
}
|
||||
|
||||
@@ -583,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) {
|
||||
|
@@ -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),
|
||||
|
@@ -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)
|
||||
}
|
||||
|
@@ -16,11 +16,9 @@ import com.intellij.util.ui.JBUI;
|
||||
import com.maddyhome.idea.vim.VimPlugin;
|
||||
import com.maddyhome.idea.vim.api.VimCommandLine;
|
||||
import com.maddyhome.idea.vim.api.VimCommandLineCaret;
|
||||
import com.maddyhome.idea.vim.api.VimEditor;
|
||||
import com.maddyhome.idea.vim.helper.UiHelper;
|
||||
import com.maddyhome.idea.vim.history.HistoryConstants;
|
||||
import com.maddyhome.idea.vim.history.HistoryEntry;
|
||||
import com.maddyhome.idea.vim.newapi.IjVimEditor;
|
||||
import com.maddyhome.idea.vim.options.helpers.GuiCursorAttributes;
|
||||
import com.maddyhome.idea.vim.options.helpers.GuiCursorMode;
|
||||
import com.maddyhome.idea.vim.options.helpers.GuiCursorOptionHelper;
|
||||
@@ -67,9 +65,6 @@ public class ExTextField extends JTextField {
|
||||
// If we're in the middle of an action (e.g. entering a register to paste, or inserting a digraph), cancel it if
|
||||
// the mouse is clicked anywhere. Vim's behavior is to use the mouse click as an event, which can lead to
|
||||
// something like : !%!C, which I don't believe is documented, or useful
|
||||
if (currentAction != null) {
|
||||
clearCurrentAction();
|
||||
}
|
||||
super.mouseClicked(e);
|
||||
}
|
||||
});
|
||||
@@ -240,10 +235,6 @@ public class ExTextField extends JTextField {
|
||||
// This gets called for ALL events, before the IDE starts to process key events for the action system. We can add a
|
||||
// dispatcher that checks that the plugin is enabled, checks that the component with the focus is ExTextField,
|
||||
// dispatch to ExEntryPanel#handleKey and if it's processed, mark the event as consumed.
|
||||
if (currentAction != null) {
|
||||
currentAction.actionPerformed(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, String.valueOf(c), modifiers));
|
||||
}
|
||||
else {
|
||||
KeyEvent event = new KeyEvent(this, keyChar != KeyEvent.CHAR_UNDEFINED ? KeyEvent.KEY_TYPED :
|
||||
(stroke.isOnKeyRelease() ? KeyEvent.KEY_RELEASED : KeyEvent.KEY_PRESSED),
|
||||
(new Date()).getTime(), modifiers, keyCode, c);
|
||||
@@ -251,11 +242,10 @@ public class ExTextField extends JTextField {
|
||||
useHandleKeyFromEx = false;
|
||||
try {
|
||||
super.processKeyEvent(event);
|
||||
}finally {
|
||||
} finally {
|
||||
useHandleKeyFromEx = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processKeyEvent(KeyEvent e) {
|
||||
@@ -279,13 +269,8 @@ public class ExTextField extends JTextField {
|
||||
* Cancels current action, if there is one. If not, cancels entry.
|
||||
*/
|
||||
void escape() {
|
||||
if (currentAction != null) {
|
||||
clearCurrentAction();
|
||||
}
|
||||
else {
|
||||
cancel();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancels entry, including any current action.
|
||||
@@ -299,19 +284,10 @@ public class ExTextField extends JTextField {
|
||||
}
|
||||
|
||||
public void clearCurrentAction() {
|
||||
if (currentAction != null) {
|
||||
currentAction.reset();
|
||||
}
|
||||
currentAction = null;
|
||||
VimCommandLine commandLine = injector.getCommandLine().getActiveCommandLine();
|
||||
if (commandLine != null) commandLine.clearPromptCharacter();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
Action getCurrentAction() {
|
||||
return currentAction;
|
||||
}
|
||||
|
||||
private void setInsertMode() {
|
||||
ExDocument doc = (ExDocument)getDocument();
|
||||
if (doc.isOverwrite()) {
|
||||
@@ -542,10 +518,9 @@ public class ExTextField extends JTextField {
|
||||
|
||||
private DataContext context;
|
||||
private final CommandLineCaret caret;
|
||||
private String lastEntry;
|
||||
String lastEntry;
|
||||
private List<HistoryEntry> history;
|
||||
private int histIndex = 0;
|
||||
private @Nullable MultiStepAction currentAction;
|
||||
int histIndex = 0;
|
||||
int currentActionPromptCharacterOffset = -1;
|
||||
|
||||
private static final Logger logger = Logger.getInstance(ExTextField.class.getName());
|
||||
|
@@ -8,114 +8,20 @@
|
||||
|
||||
package com.maddyhome.idea.vim.vimscript
|
||||
|
||||
import com.intellij.openapi.actionSystem.DataContext
|
||||
import com.intellij.openapi.components.Service
|
||||
import com.intellij.openapi.diagnostic.logger
|
||||
import com.intellij.openapi.fileEditor.FileDocumentManager
|
||||
import com.intellij.openapi.vfs.VirtualFileManager
|
||||
import com.maddyhome.idea.vim.VimPlugin
|
||||
import com.maddyhome.idea.vim.api.ExecutionContext
|
||||
import com.maddyhome.idea.vim.api.VimEditor
|
||||
import com.maddyhome.idea.vim.api.VimScriptExecutorBase
|
||||
import com.maddyhome.idea.vim.api.injector
|
||||
import com.maddyhome.idea.vim.ex.ExException
|
||||
import com.maddyhome.idea.vim.ex.FinishException
|
||||
import com.maddyhome.idea.vim.extension.VimExtensionRegistrar
|
||||
import com.maddyhome.idea.vim.history.HistoryConstants
|
||||
import com.maddyhome.idea.vim.newapi.vim
|
||||
import com.maddyhome.idea.vim.register.RegisterConstants.LAST_COMMAND_REGISTER
|
||||
import com.maddyhome.idea.vim.vimscript.model.CommandLineVimLContext
|
||||
import com.maddyhome.idea.vim.vimscript.model.ExecutionResult
|
||||
import com.maddyhome.idea.vim.vimscript.model.VimLContext
|
||||
import com.maddyhome.idea.vim.vimscript.model.commands.Command
|
||||
import com.maddyhome.idea.vim.vimscript.model.commands.RepeatCommand
|
||||
import com.maddyhome.idea.vim.vimscript.parser.VimscriptParser
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
|
||||
@Service
|
||||
internal class Executor : VimScriptExecutorBase() {
|
||||
private val logger = logger<Executor>()
|
||||
override var executingVimscript = false
|
||||
override var executingIdeaVimRcConfiguration = false
|
||||
|
||||
@Throws(ExException::class)
|
||||
override fun execute(script: String, editor: VimEditor, context: ExecutionContext, skipHistory: Boolean, indicateErrors: Boolean, vimContext: VimLContext?): ExecutionResult {
|
||||
try {
|
||||
injector.vimscriptExecutor.executingVimscript = true
|
||||
var finalResult: ExecutionResult = ExecutionResult.Success
|
||||
|
||||
val myScript = VimscriptParser.parse(script)
|
||||
myScript.units.forEach { it.vimContext = vimContext ?: myScript }
|
||||
|
||||
for (unit in myScript.units) {
|
||||
try {
|
||||
val result = unit.execute(editor, context)
|
||||
if (result is ExecutionResult.Error) {
|
||||
finalResult = ExecutionResult.Error
|
||||
if (indicateErrors) {
|
||||
VimPlugin.indicateError()
|
||||
}
|
||||
}
|
||||
} catch (e: ExException) {
|
||||
if (e is FinishException) {
|
||||
break
|
||||
}
|
||||
finalResult = ExecutionResult.Error
|
||||
if (indicateErrors) {
|
||||
VimPlugin.showMessage(e.message)
|
||||
VimPlugin.indicateError()
|
||||
} else {
|
||||
logger.warn("Failed while executing $unit. " + e.message)
|
||||
}
|
||||
} catch (e: NotImplementedError) {
|
||||
if (indicateErrors) {
|
||||
VimPlugin.showMessage("Not implemented yet :(")
|
||||
VimPlugin.indicateError()
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
logger.warn(e)
|
||||
if (injector.application.isUnitTest()) {
|
||||
throw e
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!skipHistory) {
|
||||
VimPlugin.getHistory().addEntry(HistoryConstants.COMMAND, script)
|
||||
if (myScript.units.size == 1 && myScript.units[0] is Command && myScript.units[0] !is RepeatCommand) {
|
||||
VimPlugin.getRegister().storeTextSpecial(LAST_COMMAND_REGISTER, script)
|
||||
}
|
||||
}
|
||||
return finalResult
|
||||
} finally {
|
||||
injector.vimscriptExecutor.executingVimscript = false
|
||||
|
||||
// Initialize any extensions that were enabled during execution of this vimscript
|
||||
// See the doc of this function for details
|
||||
override fun enableDelayedExtensions() {
|
||||
VimExtensionRegistrar.enableDelayedExtensions()
|
||||
}
|
||||
}
|
||||
|
||||
override fun executeFile(file: File, editor: VimEditor, fileIsIdeaVimRcConfig: Boolean, indicateErrors: Boolean) {
|
||||
val context = DataContext.EMPTY_CONTEXT.vim
|
||||
try {
|
||||
if (fileIsIdeaVimRcConfig) {
|
||||
injector.vimscriptExecutor.executingIdeaVimRcConfiguration = true
|
||||
}
|
||||
ensureFileIsSaved(file)
|
||||
execute(file.readText(), editor, context, skipHistory = true, indicateErrors)
|
||||
} catch (ignored: IOException) {
|
||||
LOG.error(ignored)
|
||||
} finally {
|
||||
if (fileIsIdeaVimRcConfig) {
|
||||
injector.vimrcFileState.saveFileState(file.absolutePath)
|
||||
injector.vimscriptExecutor.executingIdeaVimRcConfiguration = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun ensureFileIsSaved(file: File) {
|
||||
override fun ensureFileIsSaved(file: File) {
|
||||
val documentManager = FileDocumentManager.getInstance()
|
||||
|
||||
VirtualFileManager.getInstance().findFileByNioPath(file.toPath())
|
||||
@@ -123,16 +29,4 @@ internal class Executor : VimScriptExecutorBase() {
|
||||
?.takeIf(documentManager::isDocumentUnsaved)
|
||||
?.let(documentManager::saveDocumentAsIs)
|
||||
}
|
||||
|
||||
@Throws(ExException::class)
|
||||
override fun executeLastCommand(editor: VimEditor, context: ExecutionContext): Boolean {
|
||||
val reg = VimPlugin.getRegister().getRegister(':') ?: return false
|
||||
val text = reg.text ?: return false
|
||||
execute(text, editor, context, skipHistory = false, indicateErrors = true, CommandLineVimLContext)
|
||||
return true
|
||||
}
|
||||
|
||||
companion object {
|
||||
val LOG = logger<Executor>()
|
||||
}
|
||||
}
|
||||
|
@@ -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
|
||||
}
|
||||
}
|
||||
|
@@ -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
|
||||
}
|
||||
|
@@ -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
|
||||
|
@@ -1,12 +1,4 @@
|
||||
<!--
|
||||
~ Copyright 2003-2023 The IdeaVim authors
|
||||
~
|
||||
~ Use of this source code is governed by an MIT-style
|
||||
~ license that can be found in the LICENSE.txt file or at
|
||||
~ https://opensource.org/licenses/MIT.
|
||||
-->
|
||||
|
||||
<idea-plugin url="https://plugins.jetbrains.com/plugin/164" xmlns:xi="http://www.w3.org/2001/XInclude">
|
||||
<idea-plugin xmlns:xi="http://www.w3.org/2001/XInclude">
|
||||
<name>IdeaVim</name>
|
||||
<id>IdeaVIM</id>
|
||||
<description><![CDATA[
|
||||
@@ -21,7 +13,7 @@
|
||||
<li><a href="https://youtrack.jetbrains.com/issues/VIM">Issue tracker</a>: feature requests and bug reports</li>
|
||||
</ul>
|
||||
]]></description>
|
||||
<version>SNAPSHOT</version>
|
||||
<version>chylex</version>
|
||||
<vendor>JetBrains</vendor>
|
||||
|
||||
<!-- Mark the plugin as compatible with RubyMine and other products based on the IntelliJ platform (including CWM) -->
|
||||
@@ -133,9 +125,11 @@
|
||||
<xi:include href="/META-INF/includes/VimListeners.xml" xpointer="xpointer(/idea-plugin/*)"/>
|
||||
|
||||
<actions resource-bundle="messages.IdeaVimBundle">
|
||||
<action id="VimPluginToggle" class="com.maddyhome.idea.vim.action.VimPluginToggleAction">
|
||||
<group id="com.chylex.intellij.vim" text="Vim" popup="true">
|
||||
<add-to-group group-id="ToolsMenu" anchor="last"/>
|
||||
</action>
|
||||
<action id="VimPluginToggle" class="com.maddyhome.idea.vim.action.VimPluginToggleAction"/>
|
||||
<action id="VimRunLastMacroInOpenFiles" class="com.maddyhome.idea.vim.action.VimRunLastMacroInOpenFiles"/>
|
||||
</group>
|
||||
|
||||
<!-- Internal -->
|
||||
<!--suppress PluginXmlI18n -->
|
||||
@@ -154,5 +148,6 @@
|
||||
</group>
|
||||
|
||||
<action id="VimFindActionIdAction" class="com.maddyhome.idea.vim.listener.FindActionIdAction"/>
|
||||
<action id="VimJumpToSource" class="com.intellij.diff.actions.impl.OpenInEditorAction" />
|
||||
</actions>
|
||||
</idea-plugin>
|
||||
|
@@ -44,6 +44,7 @@ viminfo
|
||||
virtualedit
|
||||
visualbell
|
||||
visualdelay
|
||||
whichwrap
|
||||
wrapscan
|
||||
|
||||
nobomb
|
||||
|
82
src/main/resources/ksp-generated/intellij_commands.json
Normal file
82
src/main/resources/ksp-generated/intellij_commands.json
Normal 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"
|
||||
}
|
||||
]
|
@@ -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"
|
||||
}
|
@@ -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"
|
||||
}
|
@@ -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")
|
||||
}
|
||||
}
|
||||
|
@@ -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")
|
||||
}
|
||||
|
||||
|
@@ -13,7 +13,6 @@ import com.maddyhome.idea.vim.action.motion.search.SearchWholeWordForwardAction
|
||||
import com.maddyhome.idea.vim.api.injector
|
||||
import com.maddyhome.idea.vim.common.TextRange
|
||||
import com.maddyhome.idea.vim.newapi.IjVimEditor
|
||||
import com.maddyhome.idea.vim.newapi.vim
|
||||
import com.maddyhome.idea.vim.state.mode.SelectionType
|
||||
import org.jetbrains.plugins.ideavim.VimBehaviorDiffers
|
||||
import org.jetbrains.plugins.ideavim.VimTestCase
|
||||
@@ -2173,7 +2172,7 @@ rtyfg${c}hzxc"""
|
||||
val editor = configureByText(before)
|
||||
injector.registerGroup.storeText('*', "fgh")
|
||||
VimPlugin.getRegister()
|
||||
.storeText(IjVimEditor(editor), editor.vim.primaryCaret(), TextRange(16, 19), SelectionType.CHARACTER_WISE, false)
|
||||
.storeText(IjVimEditor(editor), TextRange(16, 19), SelectionType.CHARACTER_WISE, false)
|
||||
typeText(injector.parser.parseKeys("\"*P"))
|
||||
val after = "fg${c}hqfg${c}hwe asd zxc rty fg${c}hfgh vbn"
|
||||
assertState(after)
|
||||
|
@@ -33,7 +33,7 @@ class IdeaPutNotificationsTest : VimTestCase() {
|
||||
appReadySetup(false)
|
||||
val vimEditor = fixture.editor.vim
|
||||
VimPlugin.getRegister()
|
||||
.storeText(vimEditor, vimEditor.primaryCaret(), before rangeOf "legendary", SelectionType.CHARACTER_WISE, false)
|
||||
.storeText(vimEditor, before rangeOf "legendary", SelectionType.CHARACTER_WISE, false)
|
||||
typeText(injector.parser.parseKeys("p"))
|
||||
|
||||
val notification = notifications().last()
|
||||
@@ -53,7 +53,7 @@ class IdeaPutNotificationsTest : VimTestCase() {
|
||||
appReadySetup(false)
|
||||
val vimEditor = fixture.editor.vim
|
||||
VimPlugin.getRegister()
|
||||
.storeText(vimEditor, vimEditor.primaryCaret(), before rangeOf "legendary", SelectionType.CHARACTER_WISE, false)
|
||||
.storeText(vimEditor, before rangeOf "legendary", SelectionType.CHARACTER_WISE, false)
|
||||
typeText(injector.parser.parseKeys("p"))
|
||||
|
||||
val notifications = notifications()
|
||||
@@ -71,7 +71,7 @@ class IdeaPutNotificationsTest : VimTestCase() {
|
||||
appReadySetup(true)
|
||||
val vimEditor = fixture.editor.vim
|
||||
VimPlugin.getRegister()
|
||||
.storeText(vimEditor, vimEditor.primaryCaret(), before rangeOf "legendary", SelectionType.CHARACTER_WISE, false)
|
||||
.storeText(vimEditor, before rangeOf "legendary", SelectionType.CHARACTER_WISE, false)
|
||||
typeText(injector.parser.parseKeys("p"))
|
||||
|
||||
val notifications = EventLog.getLogModel(fixture.project).notifications
|
||||
|
@@ -88,7 +88,7 @@ class PutTestAfterCursorActionTest : VimTestCase() {
|
||||
val editor = configureByText(before)
|
||||
val vimEditor = editor.vim
|
||||
VimPlugin.getRegister()
|
||||
.storeText(vimEditor, vimEditor.primaryCaret(), before rangeOf "A Discovery\n", SelectionType.LINE_WISE, false)
|
||||
.storeText(vimEditor, before rangeOf "A Discovery\n", SelectionType.LINE_WISE, false)
|
||||
typeText(injector.parser.parseKeys("p"))
|
||||
val after = """
|
||||
A Discovery
|
||||
@@ -127,7 +127,6 @@ class PutTestAfterCursorActionTest : VimTestCase() {
|
||||
val vimEditor = editor.vim
|
||||
injector.registerGroup.storeText(
|
||||
vimEditor,
|
||||
vimEditor.primaryCaret(),
|
||||
before rangeOf "I found it in a legendary land\n",
|
||||
SelectionType.LINE_WISE,
|
||||
false,
|
||||
@@ -157,7 +156,7 @@ class PutTestAfterCursorActionTest : VimTestCase() {
|
||||
val editor = configureByText(before)
|
||||
val vimEditor = editor.vim
|
||||
VimPlugin.getRegister()
|
||||
.storeText(vimEditor, vimEditor.primaryCaret(), before rangeOf "Discovery", SelectionType.CHARACTER_WISE, false)
|
||||
.storeText(vimEditor, before rangeOf "Discovery", SelectionType.CHARACTER_WISE, false)
|
||||
typeText(injector.parser.parseKeys("vep"))
|
||||
val after = """
|
||||
A Discovery
|
||||
|
@@ -31,7 +31,7 @@ class PutTextBeforeCursorActionTest : VimTestCase() {
|
||||
""".trimIndent()
|
||||
val editor = configureByText(before)
|
||||
val vimEditor = editor.vim
|
||||
injector.registerGroup.storeText(vimEditor, vimEditor.primaryCaret(), before rangeOf "Discovery", SelectionType.CHARACTER_WISE, false)
|
||||
injector.registerGroup.storeText(vimEditor, before rangeOf "Discovery", SelectionType.CHARACTER_WISE, false)
|
||||
typeText(injector.parser.parseKeys("V" + "P"))
|
||||
typeText(injector.parser.parseKeys("V" + "P"))
|
||||
val after = """
|
||||
|
@@ -54,7 +54,7 @@ class PutViaIdeaTest : VimTestCase() {
|
||||
|
||||
val vimEditor = fixture.editor.vim
|
||||
VimPlugin.getRegister()
|
||||
.storeText(vimEditor, vimEditor.primaryCaret(), before rangeOf "legendary", SelectionType.CHARACTER_WISE, false)
|
||||
.storeText(vimEditor, before rangeOf "legendary", SelectionType.CHARACTER_WISE, false)
|
||||
|
||||
typeText("ppp")
|
||||
val after = "Ilegendarylegendarylegendar${c}y found it in a legendary land"
|
||||
@@ -74,7 +74,6 @@ class PutViaIdeaTest : VimTestCase() {
|
||||
VimPlugin.getRegister()
|
||||
.storeText(
|
||||
vimEditor,
|
||||
vimEditor.primaryCaret(),
|
||||
before rangeOf "legendary$randomUUID",
|
||||
SelectionType.CHARACTER_WISE,
|
||||
false,
|
||||
@@ -100,7 +99,6 @@ class PutViaIdeaTest : VimTestCase() {
|
||||
val vimEditor = fixture.editor.vim
|
||||
VimPlugin.getRegister().storeText(
|
||||
vimEditor,
|
||||
vimEditor.primaryCaret(),
|
||||
before rangeOf "\nLorem ipsum dolor sit amet,\n",
|
||||
SelectionType.CHARACTER_WISE,
|
||||
false,
|
||||
|
@@ -75,7 +75,7 @@ class PutVisualTextActionTest : VimTestCase() {
|
||||
val before = "${c}I found it in a legendary land"
|
||||
val editor = configureByText(before)
|
||||
val vimEditor = editor.vim
|
||||
VimPlugin.getRegister().storeText(vimEditor, vimEditor.primaryCaret(), before rangeOf "legendary", SelectionType.CHARACTER_WISE, false)
|
||||
VimPlugin.getRegister().storeText(vimEditor, before rangeOf "legendary", SelectionType.CHARACTER_WISE, false)
|
||||
typeText(injector.parser.parseKeys("ve" + "p"))
|
||||
val after = "legendar${c}y it in a legendary land"
|
||||
assertState(after)
|
||||
@@ -87,7 +87,7 @@ class PutVisualTextActionTest : VimTestCase() {
|
||||
val before = "${c}I found it in a legendary land"
|
||||
val editor = configureByText(before)
|
||||
val vimEditor = editor.vim
|
||||
VimPlugin.getRegister().storeText(vimEditor, vimEditor.primaryCaret(), before rangeOf "legendary", SelectionType.CHARACTER_WISE, false)
|
||||
VimPlugin.getRegister().storeText(vimEditor, before rangeOf "legendary", SelectionType.CHARACTER_WISE, false)
|
||||
typeText(injector.parser.parseKeys("v2e" + "2p"))
|
||||
val after = "legendarylegendar${c}y in a legendary land"
|
||||
assertState(after)
|
||||
@@ -99,7 +99,7 @@ class PutVisualTextActionTest : VimTestCase() {
|
||||
val before = "${c}I found it in a legendary land"
|
||||
val editor = configureByText(before)
|
||||
val vimEditor = editor.vim
|
||||
VimPlugin.getRegister().storeText(vimEditor, vimEditor.primaryCaret(), before rangeOf "legendary", SelectionType.CHARACTER_WISE, false)
|
||||
VimPlugin.getRegister().storeText(vimEditor, before rangeOf "legendary", SelectionType.CHARACTER_WISE, false)
|
||||
typeText(injector.parser.parseKeys("v$" + "2p"))
|
||||
val after = "legendarylegendar${c}y"
|
||||
assertState(after)
|
||||
@@ -133,7 +133,7 @@ class PutVisualTextActionTest : VimTestCase() {
|
||||
val before = "I foun${c}d it in a legendary land"
|
||||
val editor = configureByText(before)
|
||||
val vimEditor = editor.vim
|
||||
VimPlugin.getRegister().storeText(vimEditor, vimEditor.primaryCaret(), before rangeOf "legendary", SelectionType.CHARACTER_WISE, false)
|
||||
VimPlugin.getRegister().storeText(vimEditor, before rangeOf "legendary", SelectionType.CHARACTER_WISE, false)
|
||||
typeText(injector.parser.parseKeys("vb" + "p"))
|
||||
val after = "I legendar${c}y it in a legendary land"
|
||||
assertState(after)
|
||||
@@ -154,7 +154,7 @@ class PutVisualTextActionTest : VimTestCase() {
|
||||
""".trimIndent()
|
||||
val editor = configureByText(before)
|
||||
val vimEditor = editor.vim
|
||||
VimPlugin.getRegister().storeText(vimEditor, vimEditor.primaryCaret(), before rangeOf "A Discovery\n", SelectionType.LINE_WISE, false)
|
||||
VimPlugin.getRegister().storeText(vimEditor, before rangeOf "A Discovery\n", SelectionType.LINE_WISE, false)
|
||||
typeText(injector.parser.parseKeys("ve" + "p"))
|
||||
val after = """
|
||||
A Discovery
|
||||
@@ -182,7 +182,7 @@ class PutVisualTextActionTest : VimTestCase() {
|
||||
""".trimIndent()
|
||||
val editor = configureByText(before)
|
||||
val vimEditor = editor.vim
|
||||
VimPlugin.getRegister().storeText(vimEditor, vimEditor.primaryCaret(), before rangeOf "A Discovery\n", SelectionType.LINE_WISE, false)
|
||||
VimPlugin.getRegister().storeText(vimEditor, before rangeOf "A Discovery\n", SelectionType.LINE_WISE, false)
|
||||
typeText(injector.parser.parseKeys("ve" + "p"))
|
||||
val after = """
|
||||
A Discovery
|
||||
@@ -210,7 +210,7 @@ class PutVisualTextActionTest : VimTestCase() {
|
||||
""".trimIndent()
|
||||
val editor = configureByText(before)
|
||||
val vimEditor = editor.vim
|
||||
VimPlugin.getRegister().storeText(vimEditor, vimEditor.primaryCaret(), before rangeOf "A Discovery\n", SelectionType.LINE_WISE, false)
|
||||
VimPlugin.getRegister().storeText(vimEditor, before rangeOf "A Discovery\n", SelectionType.LINE_WISE, false)
|
||||
typeText(injector.parser.parseKeys("ve" + "p"))
|
||||
val after = """
|
||||
A Discovery
|
||||
@@ -238,7 +238,7 @@ class PutVisualTextActionTest : VimTestCase() {
|
||||
""".trimIndent()
|
||||
val editor = configureByText(before)
|
||||
val vimEditor = editor.vim
|
||||
VimPlugin.getRegister().storeText(vimEditor, vimEditor.primaryCaret(), before rangeOf "A Discovery\n", SelectionType.LINE_WISE, false)
|
||||
VimPlugin.getRegister().storeText(vimEditor, before rangeOf "A Discovery\n", SelectionType.LINE_WISE, false)
|
||||
typeText(injector.parser.parseKeys("v$" + "p"))
|
||||
val after = """
|
||||
A Discovery
|
||||
@@ -455,7 +455,7 @@ class PutVisualTextActionTest : VimTestCase() {
|
||||
""".trimIndent()
|
||||
val editor = configureByText(before)
|
||||
val vimEditor = editor.vim
|
||||
VimPlugin.getRegister().storeText(vimEditor, vimEditor.primaryCaret(), editor.rangeOf("|found|", 2), SelectionType.BLOCK_WISE, false)
|
||||
VimPlugin.getRegister().storeText(vimEditor, editor.rangeOf("|found|", 2), SelectionType.BLOCK_WISE, false)
|
||||
typeText(injector.parser.parseKeys("ve" + "p"))
|
||||
val after = """
|
||||
A Discovery
|
||||
@@ -491,7 +491,7 @@ class PutVisualTextActionTest : VimTestCase() {
|
||||
""".trimIndent()
|
||||
val editor = configureByText(before)
|
||||
val vimEditor = editor.vim
|
||||
VimPlugin.getRegister().storeText(vimEditor, vimEditor.primaryCaret(), editor.rangeOf("|found|", 2), SelectionType.BLOCK_WISE, false)
|
||||
VimPlugin.getRegister().storeText(vimEditor, editor.rangeOf("|found|", 2), SelectionType.BLOCK_WISE, false)
|
||||
typeText(injector.parser.parseKeys("ve" + "p"))
|
||||
val after = """
|
||||
A Discovery
|
||||
@@ -529,7 +529,7 @@ class PutVisualTextActionTest : VimTestCase() {
|
||||
""".trimIndent()
|
||||
val editor = configureByText(before)
|
||||
val vimEditor = editor.vim
|
||||
VimPlugin.getRegister().storeText(vimEditor, vimEditor.primaryCaret(), editor.rangeOf("|found|", 2), SelectionType.BLOCK_WISE, false)
|
||||
VimPlugin.getRegister().storeText(vimEditor, editor.rangeOf("|found|", 2), SelectionType.BLOCK_WISE, false)
|
||||
typeText(injector.parser.parseKeys("ve" + "2p"))
|
||||
val after = """
|
||||
A Discovery
|
||||
@@ -640,7 +640,7 @@ class PutVisualTextActionTest : VimTestCase() {
|
||||
""".trimIndent()
|
||||
val editor = configureByText(before)
|
||||
val vimEditor = editor.vim
|
||||
VimPlugin.getRegister().storeText(vimEditor, vimEditor.primaryCaret(), before rangeOf "Discovery", SelectionType.CHARACTER_WISE, false)
|
||||
VimPlugin.getRegister().storeText(vimEditor, before rangeOf "Discovery", SelectionType.CHARACTER_WISE, false)
|
||||
typeText(injector.parser.parseKeys("V" + "p"))
|
||||
val after = """
|
||||
A Discovery
|
||||
@@ -666,7 +666,7 @@ class PutVisualTextActionTest : VimTestCase() {
|
||||
""".trimIndent()
|
||||
val editor = configureByText(before)
|
||||
val vimEditor = editor.vim
|
||||
VimPlugin.getRegister().storeText(vimEditor, vimEditor.primaryCaret(), before rangeOf "Discovery", SelectionType.CHARACTER_WISE, false)
|
||||
VimPlugin.getRegister().storeText(vimEditor, before rangeOf "Discovery", SelectionType.CHARACTER_WISE, false)
|
||||
typeText(injector.parser.parseKeys("V" + "2p"))
|
||||
val after = """
|
||||
A Discovery
|
||||
@@ -703,7 +703,7 @@ class PutVisualTextActionTest : VimTestCase() {
|
||||
""".trimIndent()
|
||||
val editor = configureByText(before)
|
||||
val vimEditor = editor.vim
|
||||
VimPlugin.getRegister().storeText(vimEditor, vimEditor.primaryCaret(), before rangeOf "Discovery", SelectionType.CHARACTER_WISE, false)
|
||||
VimPlugin.getRegister().storeText(vimEditor, before rangeOf "Discovery", SelectionType.CHARACTER_WISE, false)
|
||||
typeText(injector.parser.parseKeys("V" + "p"))
|
||||
val after = """
|
||||
A Discovery
|
||||
@@ -876,7 +876,7 @@ class PutVisualTextActionTest : VimTestCase() {
|
||||
""".trimIndent()
|
||||
val editor = configureByText(before)
|
||||
val vimEditor = editor.vim
|
||||
VimPlugin.getRegister().storeText(vimEditor, vimEditor.primaryCaret(), before rangeOf "A Discovery\n", SelectionType.LINE_WISE, false)
|
||||
VimPlugin.getRegister().storeText(vimEditor, before rangeOf "A Discovery\n", SelectionType.LINE_WISE, false)
|
||||
typeText(injector.parser.parseKeys("V" + "p"))
|
||||
val after = """
|
||||
A Discovery
|
||||
@@ -902,7 +902,7 @@ class PutVisualTextActionTest : VimTestCase() {
|
||||
""".trimIndent()
|
||||
val editor = configureByText(before)
|
||||
val vimEditor = editor.vim
|
||||
VimPlugin.getRegister().storeText(vimEditor, vimEditor.primaryCaret(), before rangeOf "A Discovery\n", SelectionType.LINE_WISE, false)
|
||||
VimPlugin.getRegister().storeText(vimEditor, before rangeOf "A Discovery\n", SelectionType.LINE_WISE, false)
|
||||
typeText(injector.parser.parseKeys("V" + "2p"))
|
||||
val after = """
|
||||
A Discovery
|
||||
@@ -939,7 +939,7 @@ class PutVisualTextActionTest : VimTestCase() {
|
||||
""".trimIndent()
|
||||
val editor = configureByText(before)
|
||||
val vimEditor = editor.vim
|
||||
VimPlugin.getRegister().storeText(vimEditor, vimEditor.primaryCaret(), before rangeOf "A Discovery\n", SelectionType.LINE_WISE, false)
|
||||
VimPlugin.getRegister().storeText(vimEditor, before rangeOf "A Discovery\n", SelectionType.LINE_WISE, false)
|
||||
typeText(injector.parser.parseKeys("V" + "p"))
|
||||
val after = """
|
||||
A Discovery
|
||||
@@ -1117,7 +1117,7 @@ class PutVisualTextActionTest : VimTestCase() {
|
||||
""".trimIndent()
|
||||
val editor = configureByText(before)
|
||||
val vimEditor = editor.vim
|
||||
VimPlugin.getRegister().storeText(vimEditor, vimEditor.primaryCaret(), editor.rangeOf("|found|", 2), SelectionType.BLOCK_WISE, false)
|
||||
VimPlugin.getRegister().storeText(vimEditor, editor.rangeOf("|found|", 2), SelectionType.BLOCK_WISE, false)
|
||||
typeText(injector.parser.parseKeys("V" + "p"))
|
||||
val after = """
|
||||
A Discovery
|
||||
@@ -1172,7 +1172,7 @@ class PutVisualTextActionTest : VimTestCase() {
|
||||
""".trimIndent()
|
||||
val editor = configureByText(before)
|
||||
val vimEditor = editor.vim
|
||||
VimPlugin.getRegister().storeText(vimEditor, vimEditor.primaryCaret(), editor.rangeOf("|found|", 2), SelectionType.BLOCK_WISE, false)
|
||||
VimPlugin.getRegister().storeText(vimEditor, editor.rangeOf("|found|", 2), SelectionType.BLOCK_WISE, false)
|
||||
typeText(injector.parser.parseKeys("V" + "p"))
|
||||
val after = """
|
||||
A Discovery
|
||||
@@ -1233,7 +1233,7 @@ class PutVisualTextActionTest : VimTestCase() {
|
||||
""".trimIndent()
|
||||
val editor = configureByText(before)
|
||||
val vimEditor = editor.vim
|
||||
VimPlugin.getRegister().storeText(vimEditor, vimEditor.primaryCaret(), editor.rangeOf("|found|", 2), SelectionType.BLOCK_WISE, false)
|
||||
VimPlugin.getRegister().storeText(vimEditor, editor.rangeOf("|found|", 2), SelectionType.BLOCK_WISE, false)
|
||||
typeText(injector.parser.parseKeys("V" + "2p"))
|
||||
val after = """
|
||||
A Discovery
|
||||
@@ -1409,7 +1409,7 @@ class PutVisualTextActionTest : VimTestCase() {
|
||||
""".trimIndent()
|
||||
val editor = configureByText(before)
|
||||
val vimEditor = editor.vim
|
||||
VimPlugin.getRegister().storeText(vimEditor, vimEditor.primaryCaret(), before rangeOf "Discovery", SelectionType.CHARACTER_WISE, false)
|
||||
VimPlugin.getRegister().storeText(vimEditor, before rangeOf "Discovery", SelectionType.CHARACTER_WISE, false)
|
||||
typeText(injector.parser.parseKeys("<C-V>2e2j" + "p"))
|
||||
val after = """
|
||||
A Discovery
|
||||
@@ -1435,7 +1435,7 @@ class PutVisualTextActionTest : VimTestCase() {
|
||||
""".trimIndent()
|
||||
val editor = configureByText(before)
|
||||
val vimEditor = editor.vim
|
||||
VimPlugin.getRegister().storeText(vimEditor, vimEditor.primaryCaret(), before rangeOf "Discovery", SelectionType.CHARACTER_WISE, false)
|
||||
VimPlugin.getRegister().storeText(vimEditor, before rangeOf "Discovery", SelectionType.CHARACTER_WISE, false)
|
||||
typeText(injector.parser.parseKeys("<C-V>3e2k" + "p"))
|
||||
val after = """
|
||||
A Discovery
|
||||
@@ -1461,7 +1461,7 @@ class PutVisualTextActionTest : VimTestCase() {
|
||||
""".trimIndent()
|
||||
val editor = configureByText(before)
|
||||
val vimEditor = editor.vim
|
||||
VimPlugin.getRegister().storeText(vimEditor, vimEditor.primaryCaret(), before rangeOf "Discovery", SelectionType.CHARACTER_WISE, false)
|
||||
VimPlugin.getRegister().storeText(vimEditor, before rangeOf "Discovery", SelectionType.CHARACTER_WISE, false)
|
||||
typeText(injector.parser.parseKeys("<C-V>2e2j" + "2p"))
|
||||
val after = """
|
||||
A Discovery
|
||||
@@ -1487,7 +1487,7 @@ class PutVisualTextActionTest : VimTestCase() {
|
||||
""".trimIndent()
|
||||
val editor = configureByText(before)
|
||||
val vimEditor = editor.vim
|
||||
VimPlugin.getRegister().storeText(vimEditor, vimEditor.primaryCaret(), before rangeOf "Discovery", SelectionType.CHARACTER_WISE, false)
|
||||
VimPlugin.getRegister().storeText(vimEditor, before rangeOf "Discovery", SelectionType.CHARACTER_WISE, false)
|
||||
typeText(injector.parser.parseKeys("<C-V>3j$" + "p"))
|
||||
val after = """
|
||||
A Discovery
|
||||
@@ -1526,7 +1526,7 @@ class PutVisualTextActionTest : VimTestCase() {
|
||||
""".trimIndent()
|
||||
val editor = configureByText(before)
|
||||
val vimEditor = editor.vim
|
||||
VimPlugin.getRegister().storeText(vimEditor, vimEditor.primaryCaret(), before rangeOf "A Discovery\n", SelectionType.LINE_WISE, false)
|
||||
VimPlugin.getRegister().storeText(vimEditor, before rangeOf "A Discovery\n", SelectionType.LINE_WISE, false)
|
||||
typeText(injector.parser.parseKeys("<C-V>2e2j" + "p"))
|
||||
val after = """
|
||||
A Discovery
|
||||
@@ -1554,7 +1554,7 @@ class PutVisualTextActionTest : VimTestCase() {
|
||||
""".trimIndent()
|
||||
val editor = configureByText(before)
|
||||
val vimEditor = editor.vim
|
||||
VimPlugin.getRegister().storeText(vimEditor, vimEditor.primaryCaret(), before rangeOf "A Discovery\n", SelectionType.LINE_WISE, false)
|
||||
VimPlugin.getRegister().storeText(vimEditor, before rangeOf "A Discovery\n", SelectionType.LINE_WISE, false)
|
||||
typeText(injector.parser.parseKeys("<C-V>2e2j" + "P"))
|
||||
val after = """
|
||||
A Discovery
|
||||
@@ -1593,7 +1593,7 @@ class PutVisualTextActionTest : VimTestCase() {
|
||||
""".trimIndent()
|
||||
val editor = configureByText(before)
|
||||
val vimEditor = editor.vim
|
||||
VimPlugin.getRegister().storeText(vimEditor, vimEditor.primaryCaret(), before rangeOf "A Discovery\n", SelectionType.LINE_WISE, false)
|
||||
VimPlugin.getRegister().storeText(vimEditor, before rangeOf "A Discovery\n", SelectionType.LINE_WISE, false)
|
||||
typeText(injector.parser.parseKeys("<C-V>2e2j" + "2p"))
|
||||
val after = """
|
||||
A Discovery
|
||||
@@ -1633,7 +1633,7 @@ class PutVisualTextActionTest : VimTestCase() {
|
||||
""".trimIndent()
|
||||
val editor = configureByText(before)
|
||||
val vimEditor = editor.vim
|
||||
VimPlugin.getRegister().storeText(vimEditor, vimEditor.primaryCaret(), before rangeOf "A Discovery\n", SelectionType.LINE_WISE, false)
|
||||
VimPlugin.getRegister().storeText(vimEditor, before rangeOf "A Discovery\n", SelectionType.LINE_WISE, false)
|
||||
typeText(injector.parser.parseKeys("<C-V>2e3j" + "p"))
|
||||
val after = """
|
||||
A Discovery
|
||||
@@ -1672,7 +1672,7 @@ class PutVisualTextActionTest : VimTestCase() {
|
||||
""".trimIndent()
|
||||
val editor = configureByText(before)
|
||||
val vimEditor = editor.vim
|
||||
VimPlugin.getRegister().storeText(vimEditor, vimEditor.primaryCaret(), before rangeOf "A Discovery\n", SelectionType.LINE_WISE, false)
|
||||
VimPlugin.getRegister().storeText(vimEditor, before rangeOf "A Discovery\n", SelectionType.LINE_WISE, false)
|
||||
typeText(injector.parser.parseKeys("<C-V>2j$" + "p"))
|
||||
val after = """
|
||||
A Discovery
|
||||
@@ -1707,7 +1707,7 @@ class PutVisualTextActionTest : VimTestCase() {
|
||||
""".trimIndent()
|
||||
val editor = configureByText(before)
|
||||
val vimEditor = editor.vim
|
||||
VimPlugin.getRegister().storeText(vimEditor, vimEditor.primaryCaret(), editor.rangeOf("|found|", 2), SelectionType.BLOCK_WISE, false)
|
||||
VimPlugin.getRegister().storeText(vimEditor, editor.rangeOf("|found|", 2), SelectionType.BLOCK_WISE, false)
|
||||
typeText(injector.parser.parseKeys("<C-V>2e2j" + "p"))
|
||||
val after = """
|
||||
A Discovery
|
||||
@@ -1743,7 +1743,7 @@ class PutVisualTextActionTest : VimTestCase() {
|
||||
""".trimIndent()
|
||||
val editor = configureByText(before)
|
||||
val vimEditor = editor.vim
|
||||
VimPlugin.getRegister().storeText(vimEditor, vimEditor.primaryCaret(), editor.rangeOf("|found|", 2), SelectionType.BLOCK_WISE, false)
|
||||
VimPlugin.getRegister().storeText(vimEditor, editor.rangeOf("|found|", 2), SelectionType.BLOCK_WISE, false)
|
||||
typeText(injector.parser.parseKeys("<C-V>2e3j" + "p"))
|
||||
val after = """
|
||||
A Discovery
|
||||
@@ -1779,7 +1779,7 @@ class PutVisualTextActionTest : VimTestCase() {
|
||||
""".trimIndent()
|
||||
val editor = configureByText(before)
|
||||
val vimEditor = editor.vim
|
||||
VimPlugin.getRegister().storeText(vimEditor, vimEditor.primaryCaret(), editor.rangeOf("|found|", 2), SelectionType.BLOCK_WISE, false)
|
||||
VimPlugin.getRegister().storeText(vimEditor, editor.rangeOf("|found|", 2), SelectionType.BLOCK_WISE, false)
|
||||
typeText(injector.parser.parseKeys("<C-V>2ej" + "p"))
|
||||
val after = """
|
||||
A Discovery
|
||||
@@ -1815,7 +1815,7 @@ class PutVisualTextActionTest : VimTestCase() {
|
||||
""".trimIndent()
|
||||
val editor = configureByText(before)
|
||||
val vimEditor = editor.vim
|
||||
VimPlugin.getRegister().storeText(vimEditor, vimEditor.primaryCaret(), editor.rangeOf("|found|", 2), SelectionType.BLOCK_WISE, false)
|
||||
VimPlugin.getRegister().storeText(vimEditor, editor.rangeOf("|found|", 2), SelectionType.BLOCK_WISE, false)
|
||||
typeText(injector.parser.parseKeys("<C-V>elj" + "p"))
|
||||
val after = """
|
||||
A Discovery
|
||||
@@ -1852,7 +1852,7 @@ class PutVisualTextActionTest : VimTestCase() {
|
||||
""".trimIndent()
|
||||
val editor = configureByText(before)
|
||||
val vimEditor = editor.vim
|
||||
VimPlugin.getRegister().storeText(vimEditor, vimEditor.primaryCaret(), editor.rangeOf("|found|", 2), SelectionType.BLOCK_WISE, false)
|
||||
VimPlugin.getRegister().storeText(vimEditor, editor.rangeOf("|found|", 2), SelectionType.BLOCK_WISE, false)
|
||||
typeText(injector.parser.parseKeys("<C-V>2j$" + "p"))
|
||||
val after = """
|
||||
A Discovery
|
||||
|
@@ -33,7 +33,7 @@ class PutVisualTextMoveCursorActionTest : VimTestCase() {
|
||||
val before = "${c}I found it in a legendary land"
|
||||
val editor = configureByText(before)
|
||||
val vimEditor = editor.vim
|
||||
VimPlugin.getRegister().storeText(vimEditor, vimEditor.primaryCaret(), TextRange(16, 25), SelectionType.CHARACTER_WISE, false)
|
||||
VimPlugin.getRegister().storeText(vimEditor, TextRange(16, 25), SelectionType.CHARACTER_WISE, false)
|
||||
typeText(injector.parser.parseKeys("v2e" + "2gp"))
|
||||
val after = "legendarylegendary$c in a legendary land"
|
||||
assertState(after)
|
||||
@@ -45,7 +45,7 @@ class PutVisualTextMoveCursorActionTest : VimTestCase() {
|
||||
val before = "${c}I found it in a legendary land"
|
||||
val editor = configureByText(before)
|
||||
val vimEditor = editor.vim
|
||||
VimPlugin.getRegister().storeText(vimEditor, vimEditor.primaryCaret(), TextRange(16, 25), SelectionType.LINE_WISE, false)
|
||||
VimPlugin.getRegister().storeText(vimEditor, TextRange(16, 25), SelectionType.LINE_WISE, false)
|
||||
typeText(injector.parser.parseKeys("v2e" + "gp"))
|
||||
val after = """
|
||||
|
||||
@@ -61,7 +61,7 @@ class PutVisualTextMoveCursorActionTest : VimTestCase() {
|
||||
val before = "${c}I found it in a legendary land"
|
||||
val editor = configureByText(before)
|
||||
val vimEditor = editor.vim
|
||||
VimPlugin.getRegister().storeText(vimEditor, vimEditor.primaryCaret(), TextRange(16, 25), SelectionType.CHARACTER_WISE, false)
|
||||
VimPlugin.getRegister().storeText(vimEditor, TextRange(16, 25), SelectionType.CHARACTER_WISE, false)
|
||||
typeText(injector.parser.parseKeys("V" + "gp"))
|
||||
val after = "legendary\n$c"
|
||||
assertState(after)
|
||||
@@ -88,7 +88,7 @@ class PutVisualTextMoveCursorActionTest : VimTestCase() {
|
||||
""".trimIndent()
|
||||
val editor = configureByText(file)
|
||||
val vimEditor = editor.vim
|
||||
VimPlugin.getRegister().storeText(vimEditor, vimEditor.primaryCaret(), TextRange(2, 11), SelectionType.LINE_WISE, false)
|
||||
VimPlugin.getRegister().storeText(vimEditor, TextRange(2, 11), SelectionType.LINE_WISE, false)
|
||||
typeText(injector.parser.parseKeys("V" + "gp"))
|
||||
assertState(newFile)
|
||||
}
|
||||
@@ -134,7 +134,7 @@ class PutVisualTextMoveCursorActionTest : VimTestCase() {
|
||||
val before = "${c}I found it in a legendary land"
|
||||
val editor = configureByText(before)
|
||||
val vimEditor = editor.vim
|
||||
VimPlugin.getRegister().storeText(vimEditor, vimEditor.primaryCaret(), TextRange(16, 25), SelectionType.LINE_WISE, false)
|
||||
VimPlugin.getRegister().storeText(vimEditor, TextRange(16, 25), SelectionType.LINE_WISE, false)
|
||||
typeText(injector.parser.parseKeys("v2e" + "gP"))
|
||||
val after = """
|
||||
|
||||
@@ -150,7 +150,7 @@ class PutVisualTextMoveCursorActionTest : VimTestCase() {
|
||||
val before = "${c}I found it in a legendary land"
|
||||
val editor = configureByText(before)
|
||||
val vimEditor = editor.vim
|
||||
VimPlugin.getRegister().storeText(vimEditor, vimEditor.primaryCaret(), TextRange(16, 25), SelectionType.CHARACTER_WISE, false)
|
||||
VimPlugin.getRegister().storeText(vimEditor, TextRange(16, 25), SelectionType.CHARACTER_WISE, false)
|
||||
typeText(injector.parser.parseKeys("v2e" + "2gP"))
|
||||
val after = "legendarylegendary$c in a legendary land"
|
||||
assertState(after)
|
||||
@@ -162,7 +162,7 @@ class PutVisualTextMoveCursorActionTest : VimTestCase() {
|
||||
val before = "${c}I found it in a legendary land"
|
||||
val editor = configureByText(before)
|
||||
val vimEditor = editor.vim
|
||||
VimPlugin.getRegister().storeText(vimEditor, vimEditor.primaryCaret(), TextRange(16, 25), SelectionType.CHARACTER_WISE, false)
|
||||
VimPlugin.getRegister().storeText(vimEditor, TextRange(16, 25), SelectionType.CHARACTER_WISE, false)
|
||||
typeText(injector.parser.parseKeys("v$" + "2gP"))
|
||||
val after = "legendarylegendar${c}y"
|
||||
assertState(after)
|
||||
@@ -174,7 +174,7 @@ class PutVisualTextMoveCursorActionTest : VimTestCase() {
|
||||
val before = "${c}I found it in a legendary land"
|
||||
val editor = configureByText(before)
|
||||
val vimEditor = editor.vim
|
||||
VimPlugin.getRegister().storeText(vimEditor, vimEditor.primaryCaret(), TextRange(16, 25), SelectionType.CHARACTER_WISE, false)
|
||||
VimPlugin.getRegister().storeText(vimEditor, TextRange(16, 25), SelectionType.CHARACTER_WISE, false)
|
||||
typeText(injector.parser.parseKeys("V" + "gP"))
|
||||
val after = "legendary\n$c"
|
||||
assertState(after)
|
||||
@@ -273,7 +273,7 @@ class PutVisualTextMoveCursorActionTest : VimTestCase() {
|
||||
""".trimIndent()
|
||||
val editor = configureByText(before)
|
||||
val vimEditor = editor.vim
|
||||
VimPlugin.getRegister().storeText(vimEditor, vimEditor.primaryCaret(), TextRange(16, 19), SelectionType.BLOCK_WISE, false)
|
||||
VimPlugin.getRegister().storeText(vimEditor, TextRange(16, 19), SelectionType.BLOCK_WISE, false)
|
||||
typeText(injector.parser.parseKeys("<S-v>" + "gp"))
|
||||
val after = """
|
||||
${c}fgh
|
||||
@@ -299,7 +299,7 @@ class PutVisualTextMoveCursorActionTest : VimTestCase() {
|
||||
""".trimIndent()
|
||||
val editor = configureByText(before)
|
||||
val vimEditor = editor.vim
|
||||
VimPlugin.getRegister().storeText(vimEditor, vimEditor.primaryCaret(), TextRange(16, 19), SelectionType.LINE_WISE, false)
|
||||
VimPlugin.getRegister().storeText(vimEditor, TextRange(16, 19), SelectionType.LINE_WISE, false)
|
||||
typeText(injector.parser.parseKeys("<C-v>" + "h" + "gp"))
|
||||
val after = """
|
||||
q
|
||||
@@ -320,7 +320,7 @@ class PutVisualTextMoveCursorActionTest : VimTestCase() {
|
||||
val before = "${c}qwe asd ${c}zxc rty ${c}fgh vbn"
|
||||
val editor = configureByText(before)
|
||||
val vimEditor = editor.vim
|
||||
VimPlugin.getRegister().storeText(vimEditor, vimEditor.primaryCaret(), TextRange(16, 19), SelectionType.CHARACTER_WISE, false)
|
||||
VimPlugin.getRegister().storeText(vimEditor, TextRange(16, 19), SelectionType.CHARACTER_WISE, false)
|
||||
typeText(injector.parser.parseKeys("v2e" + "2gp"))
|
||||
val after = "fghfgh$c fghfgh$c fghfgh$c"
|
||||
assertState(after)
|
||||
|
@@ -91,7 +91,7 @@ class YankVisualActionTest : VimTestCase() {
|
||||
typeText(injector.parser.parseKeys("viw" + "y"))
|
||||
val editor = fixture.editor.vim
|
||||
val lastRegister = injector.registerGroup.lastRegisterChar
|
||||
val registers = editor.carets().map { it.registerStorage.getRegister(lastRegister)?.rawText }
|
||||
val registers = editor.carets().map { injector.registerGroup.getRegister(lastRegister)?.rawText }
|
||||
kotlin.test.assertEquals(listOf("found", "was"), registers)
|
||||
}
|
||||
|
||||
@@ -172,7 +172,7 @@ class YankVisualActionTest : VimTestCase() {
|
||||
typeText(injector.parser.parseKeys("V" + "y"))
|
||||
val editor = fixture.editor.vim
|
||||
val lastRegister = injector.registerGroup.lastRegisterChar
|
||||
val registers = editor.carets().map { it.registerStorage.getRegister(lastRegister)?.rawText }
|
||||
val registers = editor.carets().map { injector.registerGroup.getRegister(lastRegister)?.rawText }
|
||||
kotlin.test.assertEquals(
|
||||
listOf("all rocks and lavender and tufted grass,\n", "hard by the torrent of a mountain pass.\n"),
|
||||
registers,
|
||||
|
@@ -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(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@@ -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(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@@ -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
|
||||
|
@@ -130,7 +130,7 @@ class MultipleCaretsTest : VimTestCase() {
|
||||
val editor = configureByText(before)
|
||||
val vimEditor = editor.vim
|
||||
VimPlugin.getRegister()
|
||||
.storeText(vimEditor, vimEditor.primaryCaret(), TextRange(16, 19), SelectionType.CHARACTER_WISE, false)
|
||||
.storeText(vimEditor, TextRange(16, 19), SelectionType.CHARACTER_WISE, false)
|
||||
typeText(commandToKeys("pu"))
|
||||
val after = """
|
||||
qwe
|
||||
@@ -165,7 +165,7 @@ class MultipleCaretsTest : VimTestCase() {
|
||||
val editor = configureByText(before)
|
||||
val vimEditor = editor.vim
|
||||
VimPlugin.getRegister()
|
||||
.storeText(vimEditor, vimEditor.primaryCaret(), TextRange(16, 19), SelectionType.CHARACTER_WISE, false)
|
||||
.storeText(vimEditor, TextRange(16, 19), SelectionType.CHARACTER_WISE, false)
|
||||
typeText(commandToKeys("pu"))
|
||||
val after = """
|
||||
qwe
|
||||
@@ -201,7 +201,7 @@ class MultipleCaretsTest : VimTestCase() {
|
||||
val editor = configureByText(before)
|
||||
val vimEditor = editor.vim
|
||||
VimPlugin.getRegister()
|
||||
.storeText(vimEditor, vimEditor.primaryCaret(), TextRange(16, 19), SelectionType.CHARACTER_WISE, false)
|
||||
.storeText(vimEditor, TextRange(16, 19), SelectionType.CHARACTER_WISE, false)
|
||||
typeText(commandToKeys("4pu"))
|
||||
val after = """
|
||||
qwe
|
||||
@@ -237,7 +237,7 @@ class MultipleCaretsTest : VimTestCase() {
|
||||
val editor = configureByText(before)
|
||||
val vimEditor = editor.vim
|
||||
VimPlugin.getRegister()
|
||||
.storeText(vimEditor, vimEditor.primaryCaret(), TextRange(16, 19), SelectionType.CHARACTER_WISE, false)
|
||||
.storeText(vimEditor, TextRange(16, 19), SelectionType.CHARACTER_WISE, false)
|
||||
typeText(commandToKeys("4pu"))
|
||||
val after = """
|
||||
qwe
|
||||
@@ -258,7 +258,7 @@ class MultipleCaretsTest : VimTestCase() {
|
||||
val before = "${c}qwe\n" + "rty\n" + "as${c}d\n" + "fgh\n" + "zxc\n" + "vbn\n"
|
||||
val editor = configureByText(before)
|
||||
VimPlugin.getRegister()
|
||||
.storeText(editor.vim, editor.vim.primaryCaret(), TextRange(16, 19), SelectionType.CHARACTER_WISE, false)
|
||||
.storeText(editor.vim, TextRange(16, 19), SelectionType.CHARACTER_WISE, false)
|
||||
|
||||
typeText("vj")
|
||||
typeText(commandToKeys("pu"))
|
||||
|
@@ -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)
|
||||
}
|
||||
}
|
||||
|
@@ -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")
|
||||
}
|
||||
|
@@ -9,7 +9,6 @@
|
||||
package org.jetbrains.plugins.ideavim.ex.implementation.commands
|
||||
|
||||
import com.maddyhome.idea.vim.VimPlugin
|
||||
import com.maddyhome.idea.vim.newapi.vim
|
||||
import com.maddyhome.idea.vim.register.RegisterConstants
|
||||
import org.jetbrains.plugins.ideavim.VimTestCase
|
||||
import org.junit.jupiter.api.Test
|
||||
@@ -303,33 +302,4 @@ class YankLinesCommandTest : VimTestCase() {
|
||||
|Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.
|
||||
|""".trimMargin())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `test multicaret yank`() {
|
||||
configureByText(
|
||||
"""
|
||||
|Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||
|${c}Morbi nec luctus tortor, id venenatis lacus.
|
||||
|${c}Nunc sit amet tellus vel purus cursus posuere et at purus.
|
||||
|${c}Ut id dapibus augue.
|
||||
|Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.
|
||||
|Pellentesque orci dolor, tristique quis rutrum non, scelerisque id dui.
|
||||
""".trimMargin()
|
||||
)
|
||||
enterCommand("y")
|
||||
val carets = fixture.editor.vim.carets()
|
||||
assertEquals(3, carets.size)
|
||||
assertEquals(
|
||||
"Morbi nec luctus tortor, id venenatis lacus.\n",
|
||||
carets[0].registerStorage.getRegister(RegisterConstants.UNNAMED_REGISTER)?.text
|
||||
)
|
||||
assertEquals(
|
||||
"Nunc sit amet tellus vel purus cursus posuere et at purus.\n",
|
||||
carets[1].registerStorage.getRegister(RegisterConstants.UNNAMED_REGISTER)?.text
|
||||
)
|
||||
assertEquals(
|
||||
"Ut id dapibus augue.\n",
|
||||
carets[2].registerStorage.getRegister(RegisterConstants.UNNAMED_REGISTER)?.text
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@@ -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")
|
||||
|
@@ -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(
|
||||
|
@@ -50,7 +50,7 @@ class ReplaceWithRegisterTest : VimTestCase() {
|
||||
configureByText(text)
|
||||
val vimEditor = fixture.editor.vim
|
||||
VimPlugin.getRegister()
|
||||
.storeText(vimEditor, vimEditor.primaryCaret(), text rangeOf "one", SelectionType.CHARACTER_WISE, false)
|
||||
.storeText(vimEditor, text rangeOf "one", SelectionType.CHARACTER_WISE, false)
|
||||
typeText(injector.parser.parseKeys("griw"))
|
||||
assertState("one on${c}e three")
|
||||
assertEquals("one", VimPlugin.getRegister().lastRegister?.text)
|
||||
@@ -170,7 +170,7 @@ class ReplaceWithRegisterTest : VimTestCase() {
|
||||
configureByText(text)
|
||||
val vimEditor = fixture.editor.vim
|
||||
VimPlugin.getRegister()
|
||||
.storeText(vimEditor, vimEditor.primaryCaret(), text rangeOf "one", SelectionType.CHARACTER_WISE, false)
|
||||
.storeText(vimEditor, text rangeOf "one", SelectionType.CHARACTER_WISE, false)
|
||||
typeText(injector.parser.parseKeys("3griw"))
|
||||
assertState("one on${c}e four")
|
||||
assertEquals("one", VimPlugin.getRegister().lastRegister?.text)
|
||||
@@ -184,7 +184,7 @@ class ReplaceWithRegisterTest : VimTestCase() {
|
||||
configureByText(text)
|
||||
val vimEditor = fixture.editor.vim
|
||||
VimPlugin.getRegister()
|
||||
.storeText(vimEditor, vimEditor.primaryCaret(), text rangeOf "one", SelectionType.CHARACTER_WISE, false)
|
||||
.storeText(vimEditor, text rangeOf "one", SelectionType.CHARACTER_WISE, false)
|
||||
typeText(injector.parser.parseKeys("griw"))
|
||||
assertState("one two one four")
|
||||
assertEquals("one", VimPlugin.getRegister().lastRegister?.text)
|
||||
@@ -197,7 +197,7 @@ class ReplaceWithRegisterTest : VimTestCase() {
|
||||
configureByText(text)
|
||||
val vimEditor = fixture.editor.vim
|
||||
VimPlugin.getRegister()
|
||||
.storeText(vimEditor, vimEditor.primaryCaret(), text rangeOf "one", SelectionType.CHARACTER_WISE, false)
|
||||
.storeText(vimEditor, text rangeOf "one", SelectionType.CHARACTER_WISE, false)
|
||||
typeText(injector.parser.parseKeys("griw" + "w" + "."))
|
||||
assertState("one one on${c}e four")
|
||||
assertEquals("one", VimPlugin.getRegister().lastRegister?.text)
|
||||
@@ -247,7 +247,7 @@ class ReplaceWithRegisterTest : VimTestCase() {
|
||||
configureByText(text)
|
||||
val vimEditor = fixture.editor.vim
|
||||
VimPlugin.getRegister()
|
||||
.storeText(vimEditor, vimEditor.primaryCaret(), text rangeOf "legendary", SelectionType.CHARACTER_WISE, false)
|
||||
.storeText(vimEditor, text rangeOf "legendary", SelectionType.CHARACTER_WISE, false)
|
||||
typeText(injector.parser.parseKeys("grr"))
|
||||
assertState(
|
||||
"""
|
||||
@@ -414,7 +414,7 @@ class ReplaceWithRegisterTest : VimTestCase() {
|
||||
configureByText(text)
|
||||
val vimEditor = fixture.editor.vim
|
||||
VimPlugin.getRegister()
|
||||
.storeText(vimEditor, vimEditor.primaryCaret(), text rangeOf "legendary", SelectionType.CHARACTER_WISE, false)
|
||||
.storeText(vimEditor, text rangeOf "legendary", SelectionType.CHARACTER_WISE, false)
|
||||
typeText(injector.parser.parseKeys("viw" + "gr"))
|
||||
assertState(
|
||||
"""
|
||||
@@ -485,7 +485,7 @@ class ReplaceWithRegisterTest : VimTestCase() {
|
||||
configureByText(text)
|
||||
val vimEditor = fixture.editor.vim
|
||||
VimPlugin.getRegister()
|
||||
.storeText(vimEditor, vimEditor.primaryCaret(), text rangeOf "legendary", SelectionType.CHARACTER_WISE, false)
|
||||
.storeText(vimEditor, text rangeOf "legendary", SelectionType.CHARACTER_WISE, false)
|
||||
typeText(injector.parser.parseKeys("V" + "gr"))
|
||||
assertState(
|
||||
"""
|
||||
|
@@ -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)
|
||||
|
@@ -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
|
||||
|
@@ -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 }
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user