mirror of
https://github.com/chylex/IntelliJ-IdeaVim.git
synced 2024-11-25 16:42:55 +01:00
Compare commits
46 Commits
e42b4d0ea3
...
85a1fbe89e
Author | SHA1 | Date | |
---|---|---|---|
|
85a1fbe89e | ||
|
142550a1f8 | ||
|
e3d3b73903 | ||
|
45f18ff91c | ||
|
2103163207 | ||
|
19dd49670c | ||
|
e738a1a821 | ||
|
6e0f301fb8 | ||
|
c76b8db293 | ||
|
9fa4ca8fb3 | ||
|
871b60fe8d | ||
|
6715a5b61f | ||
|
d7d91f1cc5 | ||
|
9f00dbd6f4 | ||
|
f95cf3d671 | ||
|
7fbc17624f | ||
|
b9c2ea37cb | ||
|
ca0db15e01 | ||
|
c32c62eacc | ||
|
43a79dbad4 | ||
|
2829a13187 | ||
|
efc8c9207d | ||
|
183ed10592 | ||
|
926b47a31e | ||
|
d272c919ea | ||
|
f6e7d04fd5 | ||
|
ccdff4f087 | ||
|
ff14303e88 | ||
|
48a592340b | ||
|
da8f5f3231 | ||
|
f8fa8b73fa | ||
|
aee126b625 | ||
|
396ac86939 | ||
|
81816f903f | ||
|
06a85b784b | ||
|
7f1e3bb155 | ||
|
241f554133 | ||
|
9498d0779c | ||
|
b12fd5100f | ||
|
92f622430d | ||
|
ef518f5b23 | ||
|
7acb17ebdb | ||
|
479a7dbbaf | ||
|
4fd1a25557 | ||
|
f32d42e625 | ||
|
362b9a5c3a |
2
.teamcity/_Self/Project.kt
vendored
2
.teamcity/_Self/Project.kt
vendored
@ -6,6 +6,7 @@ import _Self.buildTypes.Nvim
|
|||||||
import _Self.buildTypes.PluginVerifier
|
import _Self.buildTypes.PluginVerifier
|
||||||
import _Self.buildTypes.PropertyBased
|
import _Self.buildTypes.PropertyBased
|
||||||
import _Self.buildTypes.Qodana
|
import _Self.buildTypes.Qodana
|
||||||
|
import _Self.buildTypes.TestsForIntelliJ20222
|
||||||
import _Self.buildTypes.TestsForIntelliJEAP
|
import _Self.buildTypes.TestsForIntelliJEAP
|
||||||
import _Self.subprojects.GitHub
|
import _Self.subprojects.GitHub
|
||||||
import _Self.subprojects.OldTests
|
import _Self.subprojects.OldTests
|
||||||
@ -39,6 +40,7 @@ object Project : Project({
|
|||||||
|
|
||||||
// Builds
|
// Builds
|
||||||
buildType(TestsForIntelliJEAP)
|
buildType(TestsForIntelliJEAP)
|
||||||
|
buildType(TestsForIntelliJ20222)
|
||||||
|
|
||||||
buildType(PropertyBased)
|
buildType(PropertyBased)
|
||||||
buildType(LongRunning)
|
buildType(LongRunning)
|
||||||
|
2
.teamcity/_Self/buildTypes/ActiveTests.kt
vendored
2
.teamcity/_Self/buildTypes/ActiveTests.kt
vendored
@ -55,4 +55,4 @@ sealed class ActiveTests(buildName: String, ijVersion: String) : BuildType({
|
|||||||
})
|
})
|
||||||
|
|
||||||
object TestsForIntelliJEAP : ActiveTests("Tests for IntelliJ Latest EAP", "LATEST-EAP-SNAPSHOT")
|
object TestsForIntelliJEAP : ActiveTests("Tests for IntelliJ Latest EAP", "LATEST-EAP-SNAPSHOT")
|
||||||
//object TestsForIntelliJ20213 : ActiveTests("Tests for IntelliJ 2021.3", "2021.3.2")
|
object TestsForIntelliJ20222 : ActiveTests("Tests for IntelliJ 2022.2", "2022.2.1")
|
||||||
|
69
AUTHORS.md
69
AUTHORS.md
@ -32,16 +32,48 @@ Contributors:
|
|||||||
[![icon][github]](https://github.com/yole)
|
[![icon][github]](https://github.com/yole)
|
||||||
|
|
||||||
Dmitry Jemerov
|
Dmitry Jemerov
|
||||||
|
* [![icon][mail]](mailto:tony.kay@gmail.com)
|
||||||
|
[![icon][github]](https://github.com/awkay)
|
||||||
|
|
||||||
|
Tony Kay
|
||||||
|
* [![icon][mail]](mailto:jamescmartinez@gmail.com)
|
||||||
|
[![icon][github]](https://github.com/jamescmartinez)
|
||||||
|
|
||||||
|
James Martinez
|
||||||
|
* [![icon][mail]](mailto:almas337519@gmail.com)
|
||||||
|
[![icon][github]](https://github.com/strogiyotec)
|
||||||
|
|
||||||
|
strogiyotec
|
||||||
|
* [![icon][mail]](mailto:raimon49@hotmail.com)
|
||||||
|
[![icon][github]](https://github.com/raimon49)
|
||||||
|
|
||||||
|
raimon
|
||||||
|
* [![icon][mail]](mailto:agrsbm@gmail.com)
|
||||||
|
[![icon][github-off]](#)
|
||||||
|
|
||||||
|
Alexander Griesbaum
|
||||||
|
* [![icon][mail]](mailto:manwe64@gmail.com)
|
||||||
|
[![icon][github]](https://github.com/baldrs)
|
||||||
|
|
||||||
|
Baldrs
|
||||||
|
* [![icon][mail]](mailto:yury@shurup.com)
|
||||||
|
[![icon][github]](https://github.com/zyv)
|
||||||
|
|
||||||
|
Yury V. Zaytsev
|
||||||
|
* [![icon][mail]](mailto:jflorian@doubledog.org)
|
||||||
|
[![icon][github]](https://github.com/jflorian)
|
||||||
|
|
||||||
|
John Florian
|
||||||
* [![icon][mail]](mailto:marquis@marquiswang.com)
|
* [![icon][mail]](mailto:marquis@marquiswang.com)
|
||||||
[![icon][github]](https://github.com/marquiswang)
|
[![icon][github]](https://github.com/marquiswang)
|
||||||
|
|
||||||
Marquis Wang
|
Marquis Wang
|
||||||
* [![icon][mail]](mailto:madgnome@gmail.com)
|
* [![icon][mail]](mailto:madgnome@gmail.com)
|
||||||
[![icon][github-off]](#)
|
[![icon][github]](https://github.com/madgnome)
|
||||||
|
|
||||||
Julien Hoarau
|
Julien Hoarau
|
||||||
* [![icon][mail]](mailto:masanobu.imai@gmail.com)
|
* [![icon][mail]](mailto:masanobu.imai@gmail.com)
|
||||||
[![icon][github-off]](#)
|
[![icon][github]](https://github.com/masanobuimai)
|
||||||
|
|
||||||
Masanobu Imai
|
Masanobu Imai
|
||||||
* [![icon][mail]](mailto:poxvuibr@gmail.com)
|
* [![icon][mail]](mailto:poxvuibr@gmail.com)
|
||||||
@ -57,7 +89,7 @@ Contributors:
|
|||||||
|
|
||||||
John Lindquist
|
John Lindquist
|
||||||
* [![icon][mail]](mailto:iklotzko@ltech.com)
|
* [![icon][mail]](mailto:iklotzko@ltech.com)
|
||||||
[![icon][github-off]](#)
|
[![icon][github]](https://github.com/iklotzko)
|
||||||
|
|
||||||
Ira Klotzko
|
Ira Klotzko
|
||||||
* [![icon][mail]](mailto:alex@selesse.com)
|
* [![icon][mail]](mailto:alex@selesse.com)
|
||||||
@ -65,7 +97,7 @@ Contributors:
|
|||||||
|
|
||||||
Alex Selesse
|
Alex Selesse
|
||||||
* [![icon][mail]](mailto:dbennett@palantir.com)
|
* [![icon][mail]](mailto:dbennett@palantir.com)
|
||||||
[![icon][github-off]](#)
|
[![icon][github]](https://github.com/dathanb)
|
||||||
|
|
||||||
Dathan Bennett
|
Dathan Bennett
|
||||||
* [![icon][mail]](mailto:kphayen@gmail.com)
|
* [![icon][mail]](mailto:kphayen@gmail.com)
|
||||||
@ -77,11 +109,11 @@ Contributors:
|
|||||||
|
|
||||||
Alexey Shmalko
|
Alexey Shmalko
|
||||||
* [![icon][mail]](mailto:a.m.brookins@gmail.com)
|
* [![icon][mail]](mailto:a.m.brookins@gmail.com)
|
||||||
[![icon][github-off]](#)
|
[![icon][github]](https://github.com/abrookins)
|
||||||
|
|
||||||
Andrew Brookins
|
Andrew Brookins
|
||||||
* [![icon][mail]](mailto:changwang83@gmail.com)
|
* [![icon][mail]](mailto:changwang83@gmail.com)
|
||||||
[![icon][github-off]](#)
|
[![icon][github]](https://github.com/changwang)
|
||||||
|
|
||||||
Chang Wang
|
Chang Wang
|
||||||
* [![icon][mail]](mailto:josejaime.sanchez@gmail.com)
|
* [![icon][mail]](mailto:josejaime.sanchez@gmail.com)
|
||||||
@ -89,19 +121,19 @@ Contributors:
|
|||||||
|
|
||||||
Jaime Sanchez
|
Jaime Sanchez
|
||||||
* [![icon][mail]](mailto:thomas@homburg.dk)
|
* [![icon][mail]](mailto:thomas@homburg.dk)
|
||||||
[![icon][github-off]](#)
|
[![icon][github]](https://github.com/homburg)
|
||||||
|
|
||||||
Thomas B Homburg
|
Thomas B Homburg
|
||||||
* [![icon][mail]](mailto:smartbomb@server.fake)
|
* [![icon][mail]](mailto:smartbomb@server.fake)
|
||||||
[![icon][github-off]](#)
|
[![icon][github]](https://github.com/smartbomb)
|
||||||
|
|
||||||
smartbomb
|
smartbomb
|
||||||
* [![icon][mail]](mailto:tuomas.tynkkynen@iki.fi)
|
* [![icon][mail]](mailto:tuomas.tynkkynen@iki.fi)
|
||||||
[![icon][github-off]](#)
|
[![icon][github]](https://github.com/dezgeg)
|
||||||
|
|
||||||
Tuomas Tynkkynen
|
Tuomas Tynkkynen
|
||||||
* [![icon][mail]](mailto:jackson@donorschoose.org)
|
* [![icon][mail]](mailto:jackson@donorschoose.org)
|
||||||
[![icon][github-off]](#)
|
[![icon][github]](https://github.com/jdpopkin)
|
||||||
|
|
||||||
Jackson Popkin
|
Jackson Popkin
|
||||||
* [![icon][mail]](mailto:yuyuyu1999@gmail.com)
|
* [![icon][mail]](mailto:yuyuyu1999@gmail.com)
|
||||||
@ -109,7 +141,7 @@ Contributors:
|
|||||||
|
|
||||||
Teruo Kunihiro
|
Teruo Kunihiro
|
||||||
* [![icon][mail]](mailto:lubashka.994@mail.ru)
|
* [![icon][mail]](mailto:lubashka.994@mail.ru)
|
||||||
[![icon][github-off]](#)
|
[![icon][github]](https://github.com/lubba)
|
||||||
|
|
||||||
Liubov Paina
|
Liubov Paina
|
||||||
* [![icon][mail]](mailto:me@dhleong.net)
|
* [![icon][mail]](mailto:me@dhleong.net)
|
||||||
@ -137,7 +169,7 @@ Contributors:
|
|||||||
|
|
||||||
tieTYT
|
tieTYT
|
||||||
* [![icon][mail]](mailto:nickgieschen@gmail.com)
|
* [![icon][mail]](mailto:nickgieschen@gmail.com)
|
||||||
[![icon][github-off]](#)
|
[![icon][github]](https://github.com/nickgieschen)
|
||||||
|
|
||||||
Nick Gieschen
|
Nick Gieschen
|
||||||
* [![icon][mail]](mailto:ikenox@gmail.com)
|
* [![icon][mail]](mailto:ikenox@gmail.com)
|
||||||
@ -149,7 +181,7 @@ Contributors:
|
|||||||
|
|
||||||
Maximilian Luz
|
Maximilian Luz
|
||||||
* [![icon][mail]](mailto:vparfinenko@excelsior-usa.com)
|
* [![icon][mail]](mailto:vparfinenko@excelsior-usa.com)
|
||||||
[![icon][github-off]](#)
|
[![icon][github]](https://github.com/cypok)
|
||||||
|
|
||||||
Vladimir Parfinenko
|
Vladimir Parfinenko
|
||||||
* [![icon][mail]](mailto:hassmann@hwdev.de)
|
* [![icon][mail]](mailto:hassmann@hwdev.de)
|
||||||
@ -193,7 +225,7 @@ Contributors:
|
|||||||
|
|
||||||
Marcel Hild
|
Marcel Hild
|
||||||
* [![icon][mail]](mailto:vedranb@gmail.com)
|
* [![icon][mail]](mailto:vedranb@gmail.com)
|
||||||
[![icon][github-off]](#)
|
[![icon][github]](https://github.com/vedran)
|
||||||
|
|
||||||
Vedran Budimcic
|
Vedran Budimcic
|
||||||
* [![icon][mail]](mailto:andreigasparovici1@gmail.com)
|
* [![icon][mail]](mailto:andreigasparovici1@gmail.com)
|
||||||
@ -208,10 +240,13 @@ Contributors:
|
|||||||
[![icon][github]](https://github.com/TonyArra)
|
[![icon][github]](https://github.com/TonyArra)
|
||||||
|
|
||||||
Tony Arra
|
Tony Arra
|
||||||
* [![icon][mail]](mailto:bradziolko@gmail.com)
|
* [![icon][mail]](mailto:mj@ziolko.dev)
|
||||||
[![icon][github]](https://github.com/bradziolko)
|
[![icon][github]](https://github.com/mjziolko)
|
||||||
|
|
||||||
Brad Ziolko
|
Madeline Ziolko
|
||||||
|
[Original contribution from:
|
||||||
|
[![icon][mail]](mailto:bradziolko@gmail.com)
|
||||||
|
[![icon][github]](https://github.com/bradziolko)]
|
||||||
* [![icon][mail]](mailto:sumoooru2@gmail.com)
|
* [![icon][mail]](mailto:sumoooru2@gmail.com)
|
||||||
[![icon][github]](https://github.com/sumoooru2)
|
[![icon][github]](https://github.com/sumoooru2)
|
||||||
|
|
||||||
|
@ -23,6 +23,15 @@ It is important to distinguish EAP from traditional pre-release software.
|
|||||||
Please note that the quality of EAP versions may at times be way below even
|
Please note that the quality of EAP versions may at times be way below even
|
||||||
usual beta standards.
|
usual beta standards.
|
||||||
|
|
||||||
|
## To Be Released
|
||||||
|
|
||||||
|
### Fixes:
|
||||||
|
* [VIM-1758](https://youtrack.jetbrains.com/issue/VIM-1758) Commentary plugin in rider
|
||||||
|
* [VIM-1903](https://youtrack.jetbrains.com/issue/VIM-1903) Autoindent now works in rider
|
||||||
|
* [VIM-2744](https://youtrack.jetbrains.com/issue/VIM-2744) Fix undo from ex line
|
||||||
|
* [VIM-2749](https://youtrack.jetbrains.com/issue/VIM-2749) Fix :tabn and :tabN commands
|
||||||
|
* [VIM-2718](https://youtrack.jetbrains.com/issue/VIM-2718) Fixed case where the primary caret was changed
|
||||||
|
|
||||||
## 1.11.0, 2022-08-09
|
## 1.11.0, 2022-08-09
|
||||||
|
|
||||||
### Features:
|
### Features:
|
||||||
|
@ -26,7 +26,7 @@ plugins {
|
|||||||
java
|
java
|
||||||
kotlin("jvm") version "1.6.21"
|
kotlin("jvm") version "1.6.21"
|
||||||
|
|
||||||
id("org.jetbrains.intellij") version "1.8.0"
|
id("org.jetbrains.intellij") version "1.9.0"
|
||||||
id("org.jetbrains.changelog") version "1.3.1"
|
id("org.jetbrains.changelog") version "1.3.1"
|
||||||
|
|
||||||
// ktlint linter - read more: https://github.com/JLLeitschuh/ktlint-gradle
|
// ktlint linter - read more: https://github.com/JLLeitschuh/ktlint-gradle
|
||||||
@ -335,8 +335,15 @@ tasks.register("slackNotification") {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- Update authors
|
// Uncomment to enable FUS testing mode
|
||||||
|
// tasks {
|
||||||
|
// withType<org.jetbrains.intellij.tasks.RunIdeTask> {
|
||||||
|
// jvmArgs("-Didea.is.internal=true")
|
||||||
|
// jvmArgs("-Dfus.internal.test.mode=true")
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// --- Update authors
|
||||||
tasks.register("updateAuthors") {
|
tasks.register("updateAuthors") {
|
||||||
doLast {
|
doLast {
|
||||||
val uncheckedEmails = setOf(
|
val uncheckedEmails = setOf(
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
# suppress inspection "UnusedProperty" for whole file
|
# suppress inspection "UnusedProperty" for whole file
|
||||||
|
|
||||||
ideaVersion=LATEST-EAP-SNAPSHOT
|
ideaVersion=2022.2.2
|
||||||
downloadIdeaSources=true
|
downloadIdeaSources=true
|
||||||
instrumentPluginCode=true
|
instrumentPluginCode=true
|
||||||
version=SNAPSHOT
|
version=SNAPSHOT
|
||||||
|
@ -22,6 +22,7 @@ import com.maddyhome.idea.vim.VimPlugin
|
|||||||
import com.maddyhome.idea.vim.api.ExecutionContext
|
import com.maddyhome.idea.vim.api.ExecutionContext
|
||||||
import com.maddyhome.idea.vim.api.VimCaret
|
import com.maddyhome.idea.vim.api.VimCaret
|
||||||
import com.maddyhome.idea.vim.api.VimEditor
|
import com.maddyhome.idea.vim.api.VimEditor
|
||||||
|
import com.maddyhome.idea.vim.api.injector
|
||||||
import com.maddyhome.idea.vim.command.Argument
|
import com.maddyhome.idea.vim.command.Argument
|
||||||
import com.maddyhome.idea.vim.command.Command
|
import com.maddyhome.idea.vim.command.Command
|
||||||
import com.maddyhome.idea.vim.command.CommandFlags
|
import com.maddyhome.idea.vim.command.CommandFlags
|
||||||
@ -40,7 +41,7 @@ import com.maddyhome.idea.vim.newapi.ij
|
|||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
private fun doOperatorAction(editor: VimEditor, context: ExecutionContext, textRange: TextRange, selectionType: SelectionType): Boolean {
|
private fun doOperatorAction(editor: VimEditor, context: ExecutionContext, textRange: TextRange, selectionType: SelectionType): Boolean {
|
||||||
val operatorFunction = VimPlugin.getKey().operatorFunction
|
val operatorFunction = injector.keyGroup.operatorFunction
|
||||||
if (operatorFunction == null) {
|
if (operatorFunction == null) {
|
||||||
VimPlugin.showMessage(MessageHelper.message("E774"))
|
VimPlugin.showMessage(MessageHelper.message("E774"))
|
||||||
return false
|
return false
|
||||||
@ -49,7 +50,7 @@ private fun doOperatorAction(editor: VimEditor, context: ExecutionContext, textR
|
|||||||
val saveRepeatHandler = VimRepeater.repeatHandler
|
val saveRepeatHandler = VimRepeater.repeatHandler
|
||||||
VimPlugin.getMark().setChangeMarks(editor, textRange)
|
VimPlugin.getMark().setChangeMarks(editor, textRange)
|
||||||
KeyHandler.getInstance().reset(editor)
|
KeyHandler.getInstance().reset(editor)
|
||||||
val result = operatorFunction.apply(editor.ij, context.ij, selectionType)
|
val result = operatorFunction.apply(editor, context, selectionType)
|
||||||
VimRepeater.repeatHandler = saveRepeatHandler
|
VimRepeater.repeatHandler = saveRepeatHandler
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
@ -127,7 +127,7 @@ object VimExtensionFacade {
|
|||||||
/** Sets the value of 'operatorfunc' to be used as the operator function in 'g@'. */
|
/** Sets the value of 'operatorfunc' to be used as the operator function in 'g@'. */
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun setOperatorFunction(function: OperatorFunction) {
|
fun setOperatorFunction(function: OperatorFunction) {
|
||||||
VimPlugin.getKey().setOperatorFunction(function)
|
VimPlugin.getKey().operatorFunction = function
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -186,7 +186,7 @@ object VimExtensionFacade {
|
|||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun getRegisterForCaret(register: Char, caret: VimCaret): List<KeyStroke>? {
|
fun getRegisterForCaret(register: Char, caret: VimCaret): List<KeyStroke>? {
|
||||||
val reg = caret.registerStorage.getRegister(register) ?: return null
|
val reg = caret.registerStorage.getRegister(caret, register) ?: return null
|
||||||
return reg.keys
|
return reg.keys
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -199,7 +199,7 @@ object VimExtensionFacade {
|
|||||||
/** Set the current contents of the given register */
|
/** Set the current contents of the given register */
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun setRegisterForCaret(register: Char, caret: VimCaret, keys: List<KeyStroke?>?) {
|
fun setRegisterForCaret(register: Char, caret: VimCaret, keys: List<KeyStroke?>?) {
|
||||||
caret.registerStorage.setKeys(register, keys?.filterNotNull() ?: emptyList())
|
caret.registerStorage.setKeys(caret, register, keys?.filterNotNull() ?: emptyList())
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Set the current contents of the given register */
|
/** Set the current contents of the given register */
|
||||||
|
@ -17,10 +17,11 @@
|
|||||||
*/
|
*/
|
||||||
package com.maddyhome.idea.vim.extension.commentary
|
package com.maddyhome.idea.vim.extension.commentary
|
||||||
|
|
||||||
import com.intellij.openapi.actionSystem.DataContext
|
import com.intellij.codeInsight.actions.AsyncActionExecutionService
|
||||||
import com.intellij.openapi.actionSystem.IdeActions
|
import com.intellij.openapi.actionSystem.IdeActions
|
||||||
import com.intellij.openapi.application.runWriteAction
|
import com.intellij.openapi.application.runWriteAction
|
||||||
import com.intellij.openapi.editor.Editor
|
import com.intellij.openapi.editor.Editor
|
||||||
|
import com.intellij.openapi.util.Ref
|
||||||
import com.intellij.psi.PsiComment
|
import com.intellij.psi.PsiComment
|
||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
import com.intellij.psi.PsiFile
|
import com.intellij.psi.PsiFile
|
||||||
@ -56,47 +57,65 @@ import com.maddyhome.idea.vim.helper.vimStateMachine
|
|||||||
import com.maddyhome.idea.vim.key.OperatorFunction
|
import com.maddyhome.idea.vim.key.OperatorFunction
|
||||||
import com.maddyhome.idea.vim.newapi.IjVimEditor
|
import com.maddyhome.idea.vim.newapi.IjVimEditor
|
||||||
import com.maddyhome.idea.vim.newapi.ij
|
import com.maddyhome.idea.vim.newapi.ij
|
||||||
import com.maddyhome.idea.vim.newapi.vim
|
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
class CommentaryExtension : VimExtension {
|
class CommentaryExtension : VimExtension {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun doCommentary(editor: VimEditor, context: ExecutionContext, range: TextRange, selectionType: SelectionType, resetCaret: Boolean): Boolean {
|
fun doCommentary(
|
||||||
|
editor: VimEditor,
|
||||||
|
context: ExecutionContext,
|
||||||
|
range: TextRange,
|
||||||
|
selectionType: SelectionType,
|
||||||
|
resetCaret: Boolean,
|
||||||
|
): Boolean {
|
||||||
val mode = editor.vimStateMachine.mode
|
val mode = editor.vimStateMachine.mode
|
||||||
if (mode !== VimStateMachine.Mode.VISUAL) {
|
if (mode !== VimStateMachine.Mode.VISUAL) {
|
||||||
editor.ij.selectionModel.setSelection(range.startOffset, range.endOffset)
|
editor.ij.selectionModel.setSelection(range.startOffset, range.endOffset)
|
||||||
}
|
}
|
||||||
|
|
||||||
return runWriteAction {
|
return runWriteAction {
|
||||||
try {
|
// Treat block- and character-wise selections as block comments. Be ready to fall back to if the first action
|
||||||
// Treat block- and character-wise selections as block comments. Be ready to fall back to if the first action
|
// isn't available
|
||||||
// isn't available
|
val actions = if (selectionType === SelectionType.LINE_WISE) {
|
||||||
val actions = if (selectionType === SelectionType.LINE_WISE) {
|
listOf(IdeActions.ACTION_COMMENT_LINE, IdeActions.ACTION_COMMENT_BLOCK)
|
||||||
listOf(IdeActions.ACTION_COMMENT_LINE, IdeActions.ACTION_COMMENT_BLOCK)
|
} else {
|
||||||
} else {
|
listOf(IdeActions.ACTION_COMMENT_BLOCK, IdeActions.ACTION_COMMENT_LINE)
|
||||||
listOf(IdeActions.ACTION_COMMENT_BLOCK, IdeActions.ACTION_COMMENT_LINE)
|
|
||||||
}
|
|
||||||
|
|
||||||
injector.actionExecutor.executeAction(actions[0], context) ||
|
|
||||||
injector.actionExecutor.executeAction(actions[1], context)
|
|
||||||
} finally {
|
|
||||||
// Remove the selection, if we added it
|
|
||||||
if (mode !== VimStateMachine.Mode.VISUAL) {
|
|
||||||
editor.removeSelection()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Put the caret back at the start of the range, as though it was moved by the operator's motion argument.
|
|
||||||
// This is what Vim does. If IntelliJ is configured to add comments at the start of the line, this might put
|
|
||||||
// the caret in the "wrong" place. E.g. gc_ should put the caret on the first non-whitespace character. This
|
|
||||||
// is calculated by the motion, saved in the marks, and then we insert the comment. If it's inserted at the
|
|
||||||
// first non-whitespace character, then the caret is in the right place. If it's inserted at the first column,
|
|
||||||
// then the caret is now in a bit of a weird place. We can't detect this scenario, so we just have to accept
|
|
||||||
// the difference
|
|
||||||
if (resetCaret) {
|
|
||||||
editor.primaryCaret().moveToOffset(range.startOffset)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val res = Ref.create<Boolean>(true)
|
||||||
|
AsyncActionExecutionService.getInstance(editor.ij.project!!).withExecutionAfterAction(actions[0], {
|
||||||
|
res.set(injector.actionExecutor.executeAction(actions[0], context))
|
||||||
|
}, { afterCommenting(mode, editor, resetCaret, range) })
|
||||||
|
if (!res.get()) {
|
||||||
|
AsyncActionExecutionService.getInstance(editor.ij.project!!).withExecutionAfterAction(actions[1], {
|
||||||
|
res.set(injector.actionExecutor.executeAction(actions[1], context))
|
||||||
|
}, { afterCommenting(mode, editor, resetCaret, range) })
|
||||||
|
}
|
||||||
|
res.get()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun afterCommenting(
|
||||||
|
mode: VimStateMachine.Mode,
|
||||||
|
editor: VimEditor,
|
||||||
|
resetCaret: Boolean,
|
||||||
|
range: TextRange,
|
||||||
|
) {
|
||||||
|
// Remove the selection, if we added it
|
||||||
|
if (mode !== VimStateMachine.Mode.VISUAL) {
|
||||||
|
editor.removeSelection()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Put the caret back at the start of the range, as though it was moved by the operator's motion argument.
|
||||||
|
// This is what Vim does. If IntelliJ is configured to add comments at the start of the line, this might put
|
||||||
|
// the caret in the "wrong" place. E.g. gc_ should put the caret on the first non-whitespace character. This
|
||||||
|
// is calculated by the motion, saved in the marks, and then we insert the comment. If it's inserted at the
|
||||||
|
// first non-whitespace character, then the caret is in the right place. If it's inserted at the first column,
|
||||||
|
// then the caret is now in a bit of a weird place. We can't detect this scenario, so we just have to accept
|
||||||
|
// the difference
|
||||||
|
if (resetCaret) {
|
||||||
|
editor.primaryCaret().moveToOffset(range.startOffset)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -112,7 +131,13 @@ class CommentaryExtension : VimExtension {
|
|||||||
|
|
||||||
putKeyMappingIfMissing(MappingMode.NXO, injector.parser.parseKeys("gc"), owner, plugCommentaryKeys, true)
|
putKeyMappingIfMissing(MappingMode.NXO, injector.parser.parseKeys("gc"), owner, plugCommentaryKeys, true)
|
||||||
putKeyMappingIfMissing(MappingMode.N, injector.parser.parseKeys("gcc"), owner, plugCommentaryLineKeys, true)
|
putKeyMappingIfMissing(MappingMode.N, injector.parser.parseKeys("gcc"), owner, plugCommentaryLineKeys, true)
|
||||||
putKeyMappingIfMissing(MappingMode.N, injector.parser.parseKeys("gcu"), owner, injector.parser.parseKeys("<Plug>Commentary<Plug>Commentary"), true)
|
putKeyMappingIfMissing(
|
||||||
|
MappingMode.N,
|
||||||
|
injector.parser.parseKeys("gcu"),
|
||||||
|
owner,
|
||||||
|
injector.parser.parseKeys("<Plug>Commentary<Plug>Commentary"),
|
||||||
|
true
|
||||||
|
)
|
||||||
|
|
||||||
// Previous versions of IdeaVim used different mappings to Vim's Commentary. Make sure everything works if someone
|
// Previous versions of IdeaVim used different mappings to Vim's Commentary. Make sure everything works if someone
|
||||||
// is still using the old mapping
|
// is still using the old mapping
|
||||||
@ -132,14 +157,19 @@ class CommentaryExtension : VimExtension {
|
|||||||
private class CommentaryOperatorHandler : OperatorFunction, ExtensionHandler {
|
private class CommentaryOperatorHandler : OperatorFunction, ExtensionHandler {
|
||||||
override val isRepeatable = true
|
override val isRepeatable = true
|
||||||
|
|
||||||
|
// In this operator we process selection by ourselves. This is necessary for rider, VIM-1758
|
||||||
|
override fun postProcessSelection(): Boolean {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
override fun execute(editor: VimEditor, context: ExecutionContext) {
|
override fun execute(editor: VimEditor, context: ExecutionContext) {
|
||||||
setOperatorFunction(this)
|
setOperatorFunction(this)
|
||||||
executeNormalWithoutMapping(injector.parser.parseKeys("g@"), editor.ij)
|
executeNormalWithoutMapping(injector.parser.parseKeys("g@"), editor.ij)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun apply(editor: Editor, context: DataContext, selectionType: SelectionType): Boolean {
|
override fun apply(editor: VimEditor, context: ExecutionContext, selectionType: SelectionType): Boolean {
|
||||||
val range = VimPlugin.getMark().getChangeMarks(editor.vim) ?: return false
|
val range = VimPlugin.getMark().getChangeMarks(editor) ?: return false
|
||||||
return doCommentary(editor.vim, context.vim, range, selectionType, true)
|
return doCommentary(editor, context, range, selectionType, true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -174,7 +204,7 @@ class CommentaryExtension : VimExtension {
|
|||||||
context: ExecutionContext,
|
context: ExecutionContext,
|
||||||
count: Int,
|
count: Int,
|
||||||
rawCount: Int,
|
rawCount: Int,
|
||||||
argument: Argument?
|
argument: Argument?,
|
||||||
): TextRange? {
|
): TextRange? {
|
||||||
|
|
||||||
val nativeEditor = (editor as IjVimEditor).editor
|
val nativeEditor = (editor as IjVimEditor).editor
|
||||||
|
@ -18,7 +18,6 @@
|
|||||||
|
|
||||||
package com.maddyhome.idea.vim.extension.exchange
|
package com.maddyhome.idea.vim.extension.exchange
|
||||||
|
|
||||||
import com.intellij.openapi.actionSystem.DataContext
|
|
||||||
import com.intellij.openapi.application.runWriteAction
|
import com.intellij.openapi.application.runWriteAction
|
||||||
import com.intellij.openapi.editor.Editor
|
import com.intellij.openapi.editor.Editor
|
||||||
import com.intellij.openapi.editor.LogicalPosition
|
import com.intellij.openapi.editor.LogicalPosition
|
||||||
@ -133,7 +132,7 @@ class VimExchangeExtension : VimExtension {
|
|||||||
val subMode = editor.subMode
|
val subMode = editor.subMode
|
||||||
// Leave visual mode to create selection marks
|
// Leave visual mode to create selection marks
|
||||||
executeNormalWithoutMapping(injector.parser.parseKeys("<Esc>"), editor.ij)
|
executeNormalWithoutMapping(injector.parser.parseKeys("<Esc>"), editor.ij)
|
||||||
Operator(true).apply(editor.ij, context.ij, SelectionType.fromSubMode(subMode))
|
Operator(true).apply(editor, context, SelectionType.fromSubMode(subMode))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -147,7 +146,8 @@ class VimExchangeExtension : VimExtension {
|
|||||||
else -> error("Invalid SubMode: $this")
|
else -> error("Invalid SubMode: $this")
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun apply(editor: Editor, context: DataContext, selectionType: SelectionType): Boolean {
|
override fun apply(vimEditor: VimEditor, context: ExecutionContext, selectionType: SelectionType): Boolean {
|
||||||
|
val editor = vimEditor.ij
|
||||||
fun highlightExchange(ex: Exchange): RangeHighlighter {
|
fun highlightExchange(ex: Exchange): RangeHighlighter {
|
||||||
val attributes = editor.colorsScheme.getAttributes(EditorColors.TEXT_SEARCH_RESULT_ATTRIBUTES)
|
val attributes = editor.colorsScheme.getAttributes(EditorColors.TEXT_SEARCH_RESULT_ATTRIBUTES)
|
||||||
val hlArea = when (ex.type) {
|
val hlArea = when (ex.type) {
|
||||||
|
@ -345,7 +345,7 @@ class NerdTree : VimExtension {
|
|||||||
if (file.isDirectory) return@Code
|
if (file.isDirectory) return@Code
|
||||||
val splitters = FileEditorManagerEx.getInstanceEx(project).splitters
|
val splitters = FileEditorManagerEx.getInstanceEx(project).splitters
|
||||||
val currentWindow = splitters.currentWindow
|
val currentWindow = splitters.currentWindow
|
||||||
currentWindow.split(SwingConstants.HORIZONTAL, true, file, true)
|
currentWindow?.split(SwingConstants.HORIZONTAL, true, file, true)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
registerCommand(
|
registerCommand(
|
||||||
@ -354,7 +354,7 @@ class NerdTree : VimExtension {
|
|||||||
val file = event.getData(CommonDataKeys.VIRTUAL_FILE) ?: return@Code
|
val file = event.getData(CommonDataKeys.VIRTUAL_FILE) ?: return@Code
|
||||||
val splitters = FileEditorManagerEx.getInstanceEx(project).splitters
|
val splitters = FileEditorManagerEx.getInstanceEx(project).splitters
|
||||||
val currentWindow = splitters.currentWindow
|
val currentWindow = splitters.currentWindow
|
||||||
currentWindow.split(SwingConstants.VERTICAL, true, file, true)
|
currentWindow?.split(SwingConstants.VERTICAL, true, file, true)
|
||||||
|
|
||||||
// FIXME: 22.01.2021 This solution bouncing a bit
|
// FIXME: 22.01.2021 This solution bouncing a bit
|
||||||
callAction("ActivateProjectToolWindow", context.vim)
|
callAction("ActivateProjectToolWindow", context.vim)
|
||||||
@ -366,7 +366,7 @@ class NerdTree : VimExtension {
|
|||||||
val file = event.getData(CommonDataKeys.VIRTUAL_FILE) ?: return@Code
|
val file = event.getData(CommonDataKeys.VIRTUAL_FILE) ?: return@Code
|
||||||
val splitters = FileEditorManagerEx.getInstanceEx(project).splitters
|
val splitters = FileEditorManagerEx.getInstanceEx(project).splitters
|
||||||
val currentWindow = splitters.currentWindow
|
val currentWindow = splitters.currentWindow
|
||||||
currentWindow.split(SwingConstants.HORIZONTAL, true, file, true)
|
currentWindow?.split(SwingConstants.HORIZONTAL, true, file, true)
|
||||||
|
|
||||||
callAction("ActivateProjectToolWindow", context.vim)
|
callAction("ActivateProjectToolWindow", context.vim)
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,6 @@
|
|||||||
|
|
||||||
package com.maddyhome.idea.vim.extension.replacewithregister
|
package com.maddyhome.idea.vim.extension.replacewithregister
|
||||||
|
|
||||||
import com.intellij.openapi.actionSystem.DataContext
|
|
||||||
import com.intellij.openapi.editor.Editor
|
import com.intellij.openapi.editor.Editor
|
||||||
import com.maddyhome.idea.vim.VimPlugin
|
import com.maddyhome.idea.vim.VimPlugin
|
||||||
import com.maddyhome.idea.vim.api.ExecutionContext
|
import com.maddyhome.idea.vim.api.ExecutionContext
|
||||||
@ -115,21 +114,22 @@ class ReplaceWithRegister : VimExtension {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private class Operator : OperatorFunction {
|
private class Operator : OperatorFunction {
|
||||||
override fun apply(editor: Editor, context: DataContext, selectionType: SelectionType): Boolean {
|
override fun apply(vimEditor: VimEditor, context: ExecutionContext, selectionType: SelectionType): Boolean {
|
||||||
|
val editor = (vimEditor as IjVimEditor).editor
|
||||||
val range = getRange(editor) ?: return false
|
val range = getRange(editor) ?: return false
|
||||||
val visualSelection = PutData.VisualSelection(
|
val visualSelection = PutData.VisualSelection(
|
||||||
mapOf(
|
mapOf(
|
||||||
editor.caretModel.primaryCaret.vim to VimSelection.create(
|
vimEditor.primaryCaret() to VimSelection.create(
|
||||||
range.startOffset,
|
range.startOffset,
|
||||||
range.endOffset - 1,
|
range.endOffset - 1,
|
||||||
selectionType,
|
selectionType,
|
||||||
IjVimEditor(editor)
|
vimEditor
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
selectionType
|
selectionType
|
||||||
)
|
)
|
||||||
// todo multicaret
|
// todo multicaret
|
||||||
doReplace(editor, editor.vim.primaryCaret(), visualSelection)
|
doReplace(editor, vimEditor.primaryCaret(), visualSelection)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -152,7 +152,7 @@ class ReplaceWithRegister : VimExtension {
|
|||||||
|
|
||||||
private fun doReplace(editor: Editor, caret: VimCaret, visualSelection: PutData.VisualSelection) {
|
private fun doReplace(editor: Editor, caret: VimCaret, visualSelection: PutData.VisualSelection) {
|
||||||
val lastRegisterChar = injector.registerGroup.lastRegisterChar
|
val lastRegisterChar = injector.registerGroup.lastRegisterChar
|
||||||
val savedRegister = caret.registerStorage.getRegister(lastRegisterChar) ?: return
|
val savedRegister = caret.registerStorage.getRegister(caret, lastRegisterChar) ?: return
|
||||||
|
|
||||||
var usedType = savedRegister.type
|
var usedType = savedRegister.type
|
||||||
var usedText = savedRegister.text
|
var usedText = savedRegister.text
|
||||||
@ -185,8 +185,8 @@ class ReplaceWithRegister : VimExtension {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
caret.registerStorage.saveRegister(savedRegister.name, savedRegister)
|
caret.registerStorage.saveRegister(caret, savedRegister.name, savedRegister)
|
||||||
caret.registerStorage.saveRegister(VimPlugin.getRegister().defaultRegister, savedRegister)
|
caret.registerStorage.saveRegister(caret, VimPlugin.getRegister().defaultRegister, savedRegister)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,6 @@
|
|||||||
*/
|
*/
|
||||||
package com.maddyhome.idea.vim.extension.surround
|
package com.maddyhome.idea.vim.extension.surround
|
||||||
|
|
||||||
import com.intellij.openapi.actionSystem.DataContext
|
|
||||||
import com.intellij.openapi.application.runWriteAction
|
import com.intellij.openapi.application.runWriteAction
|
||||||
import com.intellij.openapi.editor.Editor
|
import com.intellij.openapi.editor.Editor
|
||||||
import com.maddyhome.idea.vim.VimPlugin
|
import com.maddyhome.idea.vim.VimPlugin
|
||||||
@ -94,7 +93,7 @@ class VimSurroundExtension : VimExtension {
|
|||||||
override fun execute(editor: VimEditor, context: ExecutionContext) {
|
override fun execute(editor: VimEditor, context: ExecutionContext) {
|
||||||
val selectionStart = editor.ij.caretModel.primaryCaret.selectionStart
|
val selectionStart = editor.ij.caretModel.primaryCaret.selectionStart
|
||||||
// NB: Operator ignores SelectionType anyway
|
// NB: Operator ignores SelectionType anyway
|
||||||
if (!Operator().apply(editor.ij, context.ij, SelectionType.CHARACTER_WISE)) {
|
if (!Operator().apply(editor, context, SelectionType.CHARACTER_WISE)) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
runWriteAction {
|
runWriteAction {
|
||||||
@ -220,7 +219,8 @@ class VimSurroundExtension : VimExtension {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private class Operator : OperatorFunction {
|
private class Operator : OperatorFunction {
|
||||||
override fun apply(editor: Editor, context: DataContext, selectionType: SelectionType): Boolean {
|
override fun apply(vimEditor: VimEditor, context: ExecutionContext, selectionType: SelectionType): Boolean {
|
||||||
|
val editor = vimEditor.ij
|
||||||
val c = getChar(editor)
|
val c = getChar(editor)
|
||||||
if (c.code == 0) return true
|
if (c.code == 0) return true
|
||||||
|
|
||||||
|
@ -20,7 +20,9 @@ package com.maddyhome.idea.vim.group;
|
|||||||
import com.google.common.base.Splitter;
|
import com.google.common.base.Splitter;
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
|
import com.intellij.codeInsight.actions.AsyncActionExecutionService;
|
||||||
import com.intellij.openapi.actionSystem.DataContext;
|
import com.intellij.openapi.actionSystem.DataContext;
|
||||||
|
import com.intellij.openapi.actionSystem.IdeActions;
|
||||||
import com.intellij.openapi.application.ApplicationManager;
|
import com.intellij.openapi.application.ApplicationManager;
|
||||||
import com.intellij.openapi.command.CommandProcessor;
|
import com.intellij.openapi.command.CommandProcessor;
|
||||||
import com.intellij.openapi.command.UndoConfirmationPolicy;
|
import com.intellij.openapi.command.UndoConfirmationPolicy;
|
||||||
@ -33,10 +35,13 @@ import com.intellij.openapi.editor.event.EditorMouseEvent;
|
|||||||
import com.intellij.openapi.editor.event.EditorMouseListener;
|
import com.intellij.openapi.editor.event.EditorMouseListener;
|
||||||
import com.intellij.openapi.editor.impl.TextRangeInterval;
|
import com.intellij.openapi.editor.impl.TextRangeInterval;
|
||||||
import com.intellij.openapi.project.Project;
|
import com.intellij.openapi.project.Project;
|
||||||
|
import com.intellij.openapi.ui.popup.Balloon;
|
||||||
|
import com.intellij.openapi.ui.popup.JBPopupFactory;
|
||||||
import com.intellij.openapi.util.text.StringUtil;
|
import com.intellij.openapi.util.text.StringUtil;
|
||||||
import com.intellij.psi.PsiFile;
|
import com.intellij.psi.PsiFile;
|
||||||
import com.intellij.psi.codeStyle.CodeStyleManager;
|
import com.intellij.psi.codeStyle.CodeStyleManager;
|
||||||
import com.intellij.psi.util.PsiUtilBase;
|
import com.intellij.psi.util.PsiUtilBase;
|
||||||
|
import com.intellij.ui.JBColor;
|
||||||
import com.intellij.util.containers.ContainerUtil;
|
import com.intellij.util.containers.ContainerUtil;
|
||||||
import com.maddyhome.idea.vim.EventFacade;
|
import com.maddyhome.idea.vim.EventFacade;
|
||||||
import com.maddyhome.idea.vim.VimPlugin;
|
import com.maddyhome.idea.vim.VimPlugin;
|
||||||
@ -48,13 +53,19 @@ import com.maddyhome.idea.vim.ex.ranges.LineRange;
|
|||||||
import com.maddyhome.idea.vim.group.visual.VimSelection;
|
import com.maddyhome.idea.vim.group.visual.VimSelection;
|
||||||
import com.maddyhome.idea.vim.group.visual.VisualModeHelperKt;
|
import com.maddyhome.idea.vim.group.visual.VisualModeHelperKt;
|
||||||
import com.maddyhome.idea.vim.helper.*;
|
import com.maddyhome.idea.vim.helper.*;
|
||||||
|
import com.maddyhome.idea.vim.icons.VimIcons;
|
||||||
import com.maddyhome.idea.vim.key.KeyHandlerKeeper;
|
import com.maddyhome.idea.vim.key.KeyHandlerKeeper;
|
||||||
import com.maddyhome.idea.vim.listener.VimInsertListener;
|
import com.maddyhome.idea.vim.listener.VimInsertListener;
|
||||||
import com.maddyhome.idea.vim.newapi.*;
|
import com.maddyhome.idea.vim.newapi.IjExecutionContext;
|
||||||
|
import com.maddyhome.idea.vim.newapi.IjExecutionContextKt;
|
||||||
|
import com.maddyhome.idea.vim.newapi.IjVimCaret;
|
||||||
|
import com.maddyhome.idea.vim.newapi.IjVimEditor;
|
||||||
import com.maddyhome.idea.vim.options.OptionConstants;
|
import com.maddyhome.idea.vim.options.OptionConstants;
|
||||||
import com.maddyhome.idea.vim.options.OptionScope;
|
import com.maddyhome.idea.vim.options.OptionScope;
|
||||||
import com.maddyhome.idea.vim.vimscript.model.datatypes.VimString;
|
import com.maddyhome.idea.vim.vimscript.model.datatypes.VimString;
|
||||||
import kotlin.Pair;
|
import kotlin.Pair;
|
||||||
|
import kotlin.Unit;
|
||||||
|
import kotlin.jvm.functions.Function0;
|
||||||
import kotlin.text.StringsKt;
|
import kotlin.text.StringsKt;
|
||||||
import org.jetbrains.annotations.NonNls;
|
import org.jetbrains.annotations.NonNls;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
@ -85,6 +96,8 @@ public class ChangeGroup extends VimChangeGroupBase {
|
|||||||
|
|
||||||
private final List<VimInsertListener> insertListeners = ContainerUtil.createLockFreeCopyOnWriteList();
|
private final List<VimInsertListener> insertListeners = ContainerUtil.createLockFreeCopyOnWriteList();
|
||||||
|
|
||||||
|
private long lastShownTime = 0L;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inserts a new line above the caret position
|
* Inserts a new line above the caret position
|
||||||
*
|
*
|
||||||
@ -571,17 +584,31 @@ public class ChangeGroup extends VimChangeGroupBase {
|
|||||||
final int startOffset = injector.getEngineEditorHelper().getLineStartForOffset(editor, range.getStartOffset());
|
final int startOffset = injector.getEngineEditorHelper().getLineStartForOffset(editor, range.getStartOffset());
|
||||||
final int endOffset = injector.getEngineEditorHelper().getLineEndForOffset(editor, range.getEndOffset());
|
final int endOffset = injector.getEngineEditorHelper().getLineEndForOffset(editor, range.getEndOffset());
|
||||||
|
|
||||||
VisualModeHelperKt.vimSetSystemSelectionSilently(((IjVimEditor) editor).getEditor().getSelectionModel(), startOffset, endOffset);
|
Editor ijEditor = ((IjVimEditor)editor).getEditor();
|
||||||
|
VisualModeHelperKt.vimSetSystemSelectionSilently(ijEditor.getSelectionModel(), startOffset, endOffset);
|
||||||
|
|
||||||
NativeAction joinLinesAction = VimInjectorKt.getInjector().getNativeActionManager().getIndentLines();
|
Project project = ijEditor.getProject();
|
||||||
if (joinLinesAction != null) {
|
Function0<Unit> actionExecution = () -> {
|
||||||
VimInjectorKt.getInjector().getActionExecutor().executeAction(joinLinesAction, context);
|
NativeAction joinLinesAction = VimInjectorKt.getInjector().getNativeActionManager().getIndentLines();
|
||||||
|
if (joinLinesAction != null) {
|
||||||
|
VimInjectorKt.getInjector().getActionExecutor().executeAction(joinLinesAction, context);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
Function0<Unit> afterAction = () -> {
|
||||||
|
final int firstLine = editor.offsetToLogicalPosition(Math.min(startOffset, endOffset)).getLine();
|
||||||
|
final int newOffset = VimPlugin.getMotion().moveCaretToLineStartSkipLeading(editor, firstLine);
|
||||||
|
injector.getMotion().moveCaret(editor, caret, newOffset);
|
||||||
|
restoreCursor(editor, caret, ((IjVimCaret)caret).getCaret().getLogicalPosition().line);
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
if (project != null) {
|
||||||
|
AsyncActionExecutionService.Companion.getInstance(project)
|
||||||
|
.withExecutionAfterAction(IdeActions.ACTION_EDITOR_AUTO_INDENT_LINES, actionExecution, afterAction);
|
||||||
|
} else {
|
||||||
|
actionExecution.invoke();
|
||||||
|
afterAction.invoke();
|
||||||
}
|
}
|
||||||
|
|
||||||
final int firstLine = editor.offsetToLogicalPosition(Math.min(startOffset, endOffset)).getLine();
|
|
||||||
final int newOffset = VimPlugin.getMotion().moveCaretToLineStartSkipLeading(editor, firstLine);
|
|
||||||
injector.getMotion().moveCaret(editor, caret, newOffset);
|
|
||||||
restoreCursor(editor, caret, ((IjVimCaret) caret).getCaret().getLogicalPosition().line);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -773,6 +800,22 @@ public class ChangeGroup extends VimChangeGroupBase {
|
|||||||
@NotNull TextRange selectedRange,
|
@NotNull TextRange selectedRange,
|
||||||
final int count,
|
final int count,
|
||||||
boolean avalanche) {
|
boolean avalanche) {
|
||||||
|
|
||||||
|
// Just an easter egg
|
||||||
|
if (avalanche) {
|
||||||
|
long currentTime = System.currentTimeMillis();
|
||||||
|
if (currentTime - lastShownTime > 60_000) {
|
||||||
|
lastShownTime = currentTime;
|
||||||
|
ApplicationManager.getApplication().invokeLater(() -> {
|
||||||
|
final Balloon balloon = JBPopupFactory.getInstance()
|
||||||
|
.createHtmlTextBalloonBuilder("Wow, nice vim skills!", VimIcons.IDEAVIM, JBColor.background(), null)
|
||||||
|
.createBalloon();
|
||||||
|
balloon.show(JBPopupFactory.getInstance().guessBestPopupLocation(((IjVimEditor)editor).getEditor()),
|
||||||
|
Balloon.Position.below);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
String nf = ((VimString) VimPlugin.getOptionService().getOptionValue(new OptionScope.LOCAL(editor), OptionConstants.nrformatsName, OptionConstants.nrformatsName)).getValue();
|
String nf = ((VimString) VimPlugin.getOptionService().getOptionValue(new OptionScope.LOCAL(editor), OptionConstants.nrformatsName, OptionConstants.nrformatsName)).getValue();
|
||||||
boolean alpha = nf.contains("alpha");
|
boolean alpha = nf.contains("alpha");
|
||||||
boolean hex = nf.contains("hex");
|
boolean hex = nf.contains("hex");
|
||||||
|
@ -73,8 +73,6 @@ public class KeyGroup extends VimKeyGroupBase implements PersistentStateComponen
|
|||||||
|
|
||||||
private static final Logger logger = Logger.getInstance(KeyGroup.class);
|
private static final Logger logger = Logger.getInstance(KeyGroup.class);
|
||||||
|
|
||||||
private @Nullable OperatorFunction operatorFunction = null;
|
|
||||||
|
|
||||||
public void registerRequiredShortcutKeys(@NotNull VimEditor editor) {
|
public void registerRequiredShortcutKeys(@NotNull VimEditor editor) {
|
||||||
EventFacade.getInstance()
|
EventFacade.getInstance()
|
||||||
.registerCustomShortcutSet(VimShortcutKeyAction.getInstance(), toShortcutSet(getRequiredShortcutKeys()),
|
.registerCustomShortcutSet(VimShortcutKeyAction.getInstance(), toShortcutSet(getRequiredShortcutKeys()),
|
||||||
@ -119,14 +117,6 @@ public class KeyGroup extends VimKeyGroupBase implements PersistentStateComponen
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public @Nullable OperatorFunction getOperatorFunction() {
|
|
||||||
return operatorFunction;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setOperatorFunction(@NotNull OperatorFunction function) {
|
|
||||||
operatorFunction = function;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void saveData(@NotNull Element element) {
|
public void saveData(@NotNull Element element) {
|
||||||
final Element conflictsElement = new Element(SHORTCUT_CONFLICTS_ELEMENT);
|
final Element conflictsElement = new Element(SHORTCUT_CONFLICTS_ELEMENT);
|
||||||
for (Map.Entry<KeyStroke, ShortcutOwnerInfo> entry : myShortcutConflicts.entrySet()) {
|
for (Map.Entry<KeyStroke, ShortcutOwnerInfo> entry : myShortcutConflicts.entrySet()) {
|
||||||
|
@ -23,8 +23,10 @@ import com.intellij.openapi.editor.ex.util.EditorUtil;
|
|||||||
import com.intellij.openapi.fileEditor.FileEditor;
|
import com.intellij.openapi.fileEditor.FileEditor;
|
||||||
import com.intellij.openapi.fileEditor.FileEditorManagerEvent;
|
import com.intellij.openapi.fileEditor.FileEditorManagerEvent;
|
||||||
import com.intellij.openapi.fileEditor.TextEditor;
|
import com.intellij.openapi.fileEditor.TextEditor;
|
||||||
|
import com.intellij.openapi.fileEditor.ex.FileEditorManagerEx;
|
||||||
import com.intellij.openapi.fileEditor.impl.EditorTabbedContainer;
|
import com.intellij.openapi.fileEditor.impl.EditorTabbedContainer;
|
||||||
import com.intellij.openapi.fileEditor.impl.EditorWindow;
|
import com.intellij.openapi.fileEditor.impl.EditorWindow;
|
||||||
|
import com.intellij.openapi.project.Project;
|
||||||
import com.intellij.openapi.vfs.LocalFileSystem;
|
import com.intellij.openapi.vfs.LocalFileSystem;
|
||||||
import com.intellij.openapi.vfs.VirtualFile;
|
import com.intellij.openapi.vfs.VirtualFile;
|
||||||
import com.intellij.openapi.vfs.VirtualFileManager;
|
import com.intellij.openapi.vfs.VirtualFileManager;
|
||||||
@ -1168,15 +1170,25 @@ public class MotionGroup extends VimMotionGroupBase {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int moveCaretGotoPreviousTab(@NotNull VimEditor editor, @NotNull ExecutionContext context, int rawCount) {
|
public int moveCaretGotoPreviousTab(@NotNull VimEditor editor, @NotNull ExecutionContext context, int rawCount) {
|
||||||
switchEditorTab(EditorWindow.DATA_KEY.getData((DataContext)context.getContext()), rawCount >= 1 ? -rawCount : -1, false);
|
Project project = ((IjVimEditor)editor).getEditor().getProject();
|
||||||
|
if (project == null) {
|
||||||
|
return editor.currentCaret().getOffset().getPoint();
|
||||||
|
}
|
||||||
|
EditorWindow currentWindow = FileEditorManagerEx.getInstanceEx(project).getSplitters().getCurrentWindow();
|
||||||
|
switchEditorTab(currentWindow, rawCount >= 1 ? -rawCount : -1, false);
|
||||||
return editor.currentCaret().getOffset().getPoint();
|
return editor.currentCaret().getOffset().getPoint();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int moveCaretGotoNextTab(@NotNull VimEditor editor, @NotNull ExecutionContext context, int rawCount) {
|
public int moveCaretGotoNextTab(@NotNull VimEditor editor, @NotNull ExecutionContext context, int rawCount) {
|
||||||
final boolean absolute = rawCount >= 1;
|
final boolean absolute = rawCount >= 1;
|
||||||
switchEditorTab(EditorWindow.DATA_KEY.getData((DataContext)context.getContext()), absolute ? rawCount - 1 : 1,
|
|
||||||
absolute);
|
Project project = ((IjVimEditor)editor).getEditor().getProject();
|
||||||
|
if (project == null) {
|
||||||
|
return editor.currentCaret().getOffset().getPoint();
|
||||||
|
}
|
||||||
|
EditorWindow currentWindow = FileEditorManagerEx.getInstanceEx(project).getSplitters().getCurrentWindow();
|
||||||
|
switchEditorTab(currentWindow, absolute ? rawCount - 1 : 1, absolute);
|
||||||
return editor.currentCaret().getOffset().getPoint();
|
return editor.currentCaret().getOffset().getPoint();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,7 +61,10 @@ internal fun Project.createLineBookmark(editor: Editor, line: Int, mnemonic: Cha
|
|||||||
val type = BookmarkType.get(mnemonic)
|
val type = BookmarkType.get(mnemonic)
|
||||||
if (type == BookmarkType.DEFAULT) return null
|
if (type == BookmarkType.DEFAULT) return null
|
||||||
|
|
||||||
val group = bookmarksManager.defaultGroup ?: bookmarksManager.addGroup("IdeaVim", true) ?: return null
|
val group = bookmarksManager.defaultGroup
|
||||||
|
?: bookmarksManager.getGroup("IdeaVim")
|
||||||
|
?: bookmarksManager.addGroup("IdeaVim", true)
|
||||||
|
?: return null
|
||||||
if (group.canAdd(bookmark)) {
|
if (group.canAdd(bookmark)) {
|
||||||
group.add(bookmark, type)
|
group.add(bookmark, type)
|
||||||
return bookmark
|
return bookmark
|
||||||
|
@ -190,7 +190,12 @@ class PutGroup : VimPutBase() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
visualSelection.typeInEditor.isLine -> {
|
visualSelection.typeInEditor.isLine -> {
|
||||||
if (caret.offset == editor.fileSize && editor.fileSize != 0) {
|
val lastChar = if (editor.fileSize > 0) {
|
||||||
|
editor.document.getText(com.intellij.openapi.util.TextRange(editor.fileSize - 1, editor.fileSize))[0]
|
||||||
|
} else {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
if (caret.offset == editor.fileSize && editor.fileSize != 0 && lastChar != '\n') {
|
||||||
application.runWriteAction { editor.document.insertString(caret.offset, "\n") }
|
application.runWriteAction { editor.document.insertString(caret.offset, "\n") }
|
||||||
listOf(caret.offset + 1)
|
listOf(caret.offset + 1)
|
||||||
} else listOf(caret.offset)
|
} else listOf(caret.offset)
|
||||||
|
@ -211,7 +211,7 @@ class YankGroup : YankGroupBase() {
|
|||||||
|
|
||||||
var result = true
|
var result = true
|
||||||
for ((caret, myRange) in caretToRange) {
|
for ((caret, myRange) in caretToRange) {
|
||||||
result = caret.registerStorage.storeText(editor, myRange, type, false) && result
|
result = caret.registerStorage.storeText(caret, editor, myRange, type, false) && result
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
@ -31,6 +31,7 @@ import com.intellij.psi.PsiElement;
|
|||||||
import com.intellij.psi.PsiFile;
|
import com.intellij.psi.PsiFile;
|
||||||
import com.intellij.psi.util.PsiTreeUtil;
|
import com.intellij.psi.util.PsiTreeUtil;
|
||||||
import com.maddyhome.idea.vim.VimPlugin;
|
import com.maddyhome.idea.vim.VimPlugin;
|
||||||
|
import com.maddyhome.idea.vim.api.VimSearchHelperBase;
|
||||||
import com.maddyhome.idea.vim.command.VimStateMachine;
|
import com.maddyhome.idea.vim.command.VimStateMachine;
|
||||||
import com.maddyhome.idea.vim.common.CharacterPosition;
|
import com.maddyhome.idea.vim.common.CharacterPosition;
|
||||||
import com.maddyhome.idea.vim.common.Direction;
|
import com.maddyhome.idea.vim.common.Direction;
|
||||||
@ -1201,7 +1202,7 @@ public class SearchHelper {
|
|||||||
int last = -1;
|
int last = -1;
|
||||||
int res = start;
|
int res = start;
|
||||||
while (true) {
|
while (true) {
|
||||||
res = findNextWordOne(chars, res, end, 1, true, false);
|
res = (int)VimSearchHelperBase.Companion.findNextWordOne(chars, res, end, 1, true, false);
|
||||||
if (res == start || res == 0 || res > end || res == last) {
|
if (res == start || res == 0 || res > end || res == last) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1230,105 +1231,6 @@ public class SearchHelper {
|
|||||||
return new CountPosition(count, position);
|
return new CountPosition(count, position);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int findNextWord(@NotNull Editor editor, int searchFrom, int count, boolean bigWord) {
|
|
||||||
CharSequence chars = editor.getDocument().getCharsSequence();
|
|
||||||
final int size = EditorHelperRt.getFileSize(editor);
|
|
||||||
|
|
||||||
return findNextWord(chars, searchFrom, size, count, bigWord, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int findNextWord(@NotNull CharSequence chars,
|
|
||||||
int pos,
|
|
||||||
int size,
|
|
||||||
int count,
|
|
||||||
boolean bigWord,
|
|
||||||
boolean spaceWords) {
|
|
||||||
int step = count >= 0 ? 1 : -1;
|
|
||||||
count = Math.abs(count);
|
|
||||||
|
|
||||||
int res = pos;
|
|
||||||
for (int i = 0; i < count; i++) {
|
|
||||||
res = findNextWordOne(chars, res, size, step, bigWord, spaceWords);
|
|
||||||
if (res == pos || res == 0 || res == size - 1) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int findNextWordOne(@NotNull CharSequence chars,
|
|
||||||
int pos,
|
|
||||||
int size,
|
|
||||||
int step,
|
|
||||||
boolean bigWord,
|
|
||||||
boolean spaceWords) {
|
|
||||||
boolean found = false;
|
|
||||||
pos = pos < size ? pos : Math.min(size, chars.length() - 1);
|
|
||||||
// For back searches, skip any current whitespace so we start at the end of a word
|
|
||||||
if (step < 0 && pos > 0) {
|
|
||||||
if (CharacterHelper.charType(chars.charAt(pos - 1), bigWord) == CharacterHelper.CharacterType.WHITESPACE &&
|
|
||||||
!spaceWords) {
|
|
||||||
pos = skipSpace(chars, pos - 1, step, size) + 1;
|
|
||||||
}
|
|
||||||
if (pos > 0 &&
|
|
||||||
CharacterHelper.charType(chars.charAt(pos), bigWord) !=
|
|
||||||
CharacterHelper.charType(chars.charAt(pos - 1), bigWord)) {
|
|
||||||
pos += step;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
int res = pos;
|
|
||||||
if (pos < 0 || pos >= size) {
|
|
||||||
return pos;
|
|
||||||
}
|
|
||||||
|
|
||||||
CharacterHelper.CharacterType type = CharacterHelper.charType(chars.charAt(pos), bigWord);
|
|
||||||
if (type == CharacterHelper.CharacterType.WHITESPACE && step < 0 && pos > 0 && !spaceWords) {
|
|
||||||
type = CharacterHelper.charType(chars.charAt(pos - 1), bigWord);
|
|
||||||
}
|
|
||||||
|
|
||||||
pos += step;
|
|
||||||
while (pos >= 0 && pos < size && !found) {
|
|
||||||
CharacterHelper.CharacterType newType = CharacterHelper.charType(chars.charAt(pos), bigWord);
|
|
||||||
if (newType != type) {
|
|
||||||
if (newType == CharacterHelper.CharacterType.WHITESPACE && step >= 0 && !spaceWords) {
|
|
||||||
pos = skipSpace(chars, pos, step, size);
|
|
||||||
res = pos;
|
|
||||||
}
|
|
||||||
else if (step < 0) {
|
|
||||||
res = pos + 1;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
res = pos;
|
|
||||||
}
|
|
||||||
|
|
||||||
type = CharacterHelper.charType(chars.charAt(res), bigWord);
|
|
||||||
found = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
pos += step;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (found) {
|
|
||||||
if (res < 0) //(pos <= 0)
|
|
||||||
{
|
|
||||||
res = 0;
|
|
||||||
}
|
|
||||||
else if (res >= size) //(pos >= size)
|
|
||||||
{
|
|
||||||
res = size - 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (pos <= 0) {
|
|
||||||
res = 0;
|
|
||||||
}
|
|
||||||
else if (pos >= size) {
|
|
||||||
res = size;
|
|
||||||
}
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static @NotNull List<Pair<TextRange, NumberType>> findNumbersInRange(final @NotNull Editor editor,
|
public static @NotNull List<Pair<TextRange, NumberType>> findNumbersInRange(final @NotNull Editor editor,
|
||||||
@NotNull TextRange textRange,
|
@NotNull TextRange textRange,
|
||||||
final boolean alpha,
|
final boolean alpha,
|
||||||
@ -1654,10 +1556,10 @@ public class SearchHelper {
|
|||||||
|
|
||||||
if ((!onWordStart && !(startSpace && isOuter)) || hasSelection || (count > 1 && dir == -1)) {
|
if ((!onWordStart && !(startSpace && isOuter)) || hasSelection || (count > 1 && dir == -1)) {
|
||||||
if (dir == 1) {
|
if (dir == 1) {
|
||||||
start = findNextWord(chars, pos, max, -1, isBig, !isOuter);
|
start = (int)VimSearchHelperBase.Companion.findNextWord(chars, pos, max, -1, isBig, !isOuter);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
start = findNextWord(chars, pos, max, -(count - (onWordStart && !hasSelection ? 1 : 0)), isBig, !isOuter);
|
start = (int)VimSearchHelperBase.Companion.findNextWord(chars, pos, max, -(count - (onWordStart && !hasSelection ? 1 : 0)), isBig, !isOuter);
|
||||||
}
|
}
|
||||||
|
|
||||||
start = EditorHelper.normalizeOffset(editor, start, false);
|
start = EditorHelper.normalizeOffset(editor, start, false);
|
||||||
@ -1805,7 +1707,7 @@ public class SearchHelper {
|
|||||||
if (step > 0 && pos < size - 1) {
|
if (step > 0 && pos < size - 1) {
|
||||||
if (CharacterHelper.charType(chars.charAt(pos + 1), bigWord) == CharacterHelper.CharacterType.WHITESPACE &&
|
if (CharacterHelper.charType(chars.charAt(pos + 1), bigWord) == CharacterHelper.CharacterType.WHITESPACE &&
|
||||||
!spaceWords) {
|
!spaceWords) {
|
||||||
pos = skipSpace(chars, pos + 1, step, size) - 1;
|
pos = (int)(VimSearchHelperBase.Companion.skipSpace(chars, pos + 1, step, size) - 1);
|
||||||
}
|
}
|
||||||
if (pos < size - 1 &&
|
if (pos < size - 1 &&
|
||||||
CharacterHelper.charType(chars.charAt(pos), bigWord) !=
|
CharacterHelper.charType(chars.charAt(pos), bigWord) !=
|
||||||
@ -1830,7 +1732,7 @@ public class SearchHelper {
|
|||||||
res = pos - 1;
|
res = pos - 1;
|
||||||
}
|
}
|
||||||
else if (newType == CharacterHelper.CharacterType.WHITESPACE && step < 0 && !spaceWords) {
|
else if (newType == CharacterHelper.CharacterType.WHITESPACE && step < 0 && !spaceWords) {
|
||||||
pos = skipSpace(chars, pos, step, size);
|
pos = (int)VimSearchHelperBase.Companion.skipSpace(chars, pos, step, size);
|
||||||
res = pos;
|
res = pos;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -1858,34 +1760,6 @@ public class SearchHelper {
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Skip whitespace starting with the supplied position.
|
|
||||||
* <p>
|
|
||||||
* An empty line is considered a whitespace break.
|
|
||||||
*
|
|
||||||
* @param chars The text as a character array
|
|
||||||
* @param offset The starting position
|
|
||||||
* @param step The direction to move
|
|
||||||
* @param size The size of the document
|
|
||||||
* @return The new position. This will be the first non-whitespace character found or an empty line
|
|
||||||
*/
|
|
||||||
private static int skipSpace(@NotNull CharSequence chars, int offset, int step, int size) {
|
|
||||||
char prev = 0;
|
|
||||||
while (offset >= 0 && offset < size) {
|
|
||||||
final char c = chars.charAt(offset);
|
|
||||||
if (c == '\n' && c == prev) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (CharacterHelper.charType(c, false) != CharacterHelper.CharacterType.WHITESPACE) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
prev = c;
|
|
||||||
offset += step;
|
|
||||||
}
|
|
||||||
|
|
||||||
return offset < size ? offset : size - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This locates the position with the document of the count-th occurrence of ch on the current line
|
* This locates the position with the document of the count-th occurrence of ch on the current line
|
||||||
*
|
*
|
||||||
|
@ -25,6 +25,7 @@ import com.intellij.openapi.command.CommandProcessor
|
|||||||
import com.intellij.openapi.command.impl.UndoManagerImpl
|
import com.intellij.openapi.command.impl.UndoManagerImpl
|
||||||
import com.intellij.openapi.command.undo.UndoManager
|
import com.intellij.openapi.command.undo.UndoManager
|
||||||
import com.intellij.openapi.components.Service
|
import com.intellij.openapi.components.Service
|
||||||
|
import com.intellij.openapi.fileEditor.impl.text.TextEditorProvider
|
||||||
import com.maddyhome.idea.vim.api.ExecutionContext
|
import com.maddyhome.idea.vim.api.ExecutionContext
|
||||||
import com.maddyhome.idea.vim.api.injector
|
import com.maddyhome.idea.vim.api.injector
|
||||||
import com.maddyhome.idea.vim.common.ChangesListener
|
import com.maddyhome.idea.vim.common.ChangesListener
|
||||||
@ -48,16 +49,17 @@ class UndoRedoHelper : UndoRedoBase() {
|
|||||||
override fun undo(context: ExecutionContext): Boolean {
|
override fun undo(context: ExecutionContext): Boolean {
|
||||||
val ijContext = context.context as DataContext
|
val ijContext = context.context as DataContext
|
||||||
val project = PlatformDataKeys.PROJECT.getData(ijContext) ?: return false
|
val project = PlatformDataKeys.PROJECT.getData(ijContext) ?: return false
|
||||||
val fileEditor = PlatformDataKeys.FILE_EDITOR.getData(ijContext)
|
val editor = CommonDataKeys.EDITOR.getData(context.ij) ?: return false
|
||||||
|
val vimEditor = editor.vim
|
||||||
|
val fileEditor = TextEditorProvider.getInstance().getTextEditor(editor)
|
||||||
val undoManager = UndoManager.getInstance(project)
|
val undoManager = UndoManager.getInstance(project)
|
||||||
if (fileEditor != null && undoManager.isUndoAvailable(fileEditor)) {
|
if (undoManager.isUndoAvailable(fileEditor)) {
|
||||||
val editor = CommonDataKeys.EDITOR.getData(context.ij)?.vim
|
|
||||||
if (injector.optionService.isSet(OptionScope.GLOBAL, IjVimOptionService.oldUndo)) {
|
if (injector.optionService.isSet(OptionScope.GLOBAL, IjVimOptionService.oldUndo)) {
|
||||||
SelectionVimListenerSuppressor.lock().use { undoManager.undo(fileEditor) }
|
SelectionVimListenerSuppressor.lock().use { undoManager.undo(fileEditor) }
|
||||||
} else {
|
} else {
|
||||||
performUntilFileChanges(editor, { undoManager.isUndoAvailable(fileEditor) }, { undoManager.undo(fileEditor) })
|
performUntilFileChanges(vimEditor, { undoManager.isUndoAvailable(fileEditor) }, { undoManager.undo(fileEditor) })
|
||||||
|
|
||||||
editor?.carets()?.forEach {
|
vimEditor.carets().forEach {
|
||||||
val ijCaret = it.ij
|
val ijCaret = it.ij
|
||||||
val hasSelection = ijCaret.hasSelection()
|
val hasSelection = ijCaret.hasSelection()
|
||||||
if (hasSelection) {
|
if (hasSelection) {
|
||||||
@ -78,16 +80,17 @@ class UndoRedoHelper : UndoRedoBase() {
|
|||||||
override fun redo(context: ExecutionContext): Boolean {
|
override fun redo(context: ExecutionContext): Boolean {
|
||||||
val ijContext = context.context as DataContext
|
val ijContext = context.context as DataContext
|
||||||
val project = PlatformDataKeys.PROJECT.getData(ijContext) ?: return false
|
val project = PlatformDataKeys.PROJECT.getData(ijContext) ?: return false
|
||||||
val fileEditor = PlatformDataKeys.FILE_EDITOR.getData(ijContext)
|
val editor = CommonDataKeys.EDITOR.getData(context.ij) ?: return false
|
||||||
|
val vimEditor = editor.vim
|
||||||
|
val fileEditor = TextEditorProvider.getInstance().getTextEditor(editor)
|
||||||
val undoManager = UndoManager.getInstance(project)
|
val undoManager = UndoManager.getInstance(project)
|
||||||
val editor = CommonDataKeys.EDITOR.getData(context.ij)?.vim
|
if (undoManager.isRedoAvailable(fileEditor)) {
|
||||||
if (fileEditor != null && undoManager.isRedoAvailable(fileEditor)) {
|
|
||||||
if (injector.optionService.isSet(OptionScope.GLOBAL, IjVimOptionService.oldUndo)) {
|
if (injector.optionService.isSet(OptionScope.GLOBAL, IjVimOptionService.oldUndo)) {
|
||||||
SelectionVimListenerSuppressor.lock().use { undoManager.redo(fileEditor) }
|
SelectionVimListenerSuppressor.lock().use { undoManager.redo(fileEditor) }
|
||||||
} else {
|
} else {
|
||||||
performUntilFileChanges(editor, { undoManager.isRedoAvailable(fileEditor) }, { undoManager.redo(fileEditor) })
|
performUntilFileChanges(vimEditor, { undoManager.isRedoAvailable(fileEditor) }, { undoManager.redo(fileEditor) })
|
||||||
CommandProcessor.getInstance().runUndoTransparentAction {
|
CommandProcessor.getInstance().runUndoTransparentAction {
|
||||||
editor?.carets()?.forEach { it.ij.removeSelection() }
|
vimEditor.carets().forEach { it.ij.removeSelection() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
|
@ -53,7 +53,7 @@ class IjVimCaret(val caret: Caret) : VimCaretBase() {
|
|||||||
get() {
|
get() {
|
||||||
var storage = this.caret.registerStorage
|
var storage = this.caret.registerStorage
|
||||||
if (storage == null) {
|
if (storage == null) {
|
||||||
storage = CaretRegisterStorageBase(editor.primaryCaret().ij == caret)
|
storage = CaretRegisterStorageBase()
|
||||||
this.caret.registerStorage = storage
|
this.caret.registerStorage = storage
|
||||||
}
|
}
|
||||||
return storage
|
return storage
|
||||||
@ -87,6 +87,8 @@ class IjVimCaret(val caret: Caret) : VimCaretBase() {
|
|||||||
}
|
}
|
||||||
override val vimLine: Int
|
override val vimLine: Int
|
||||||
get() = this.caret.vimLine
|
get() = this.caret.vimLine
|
||||||
|
override val isPrimary: Boolean
|
||||||
|
get() = editor.primaryCaret().ij == this.caret
|
||||||
|
|
||||||
override fun moveToOffset(offset: Int) {
|
override fun moveToOffset(offset: Int) {
|
||||||
// TODO: 17.12.2021 Unpack internal actions
|
// TODO: 17.12.2021 Unpack internal actions
|
||||||
|
@ -3,14 +3,14 @@ package com.maddyhome.idea.vim.newapi
|
|||||||
import com.intellij.openapi.components.Service
|
import com.intellij.openapi.components.Service
|
||||||
import com.maddyhome.idea.vim.api.VimCaret
|
import com.maddyhome.idea.vim.api.VimCaret
|
||||||
import com.maddyhome.idea.vim.api.VimEditor
|
import com.maddyhome.idea.vim.api.VimEditor
|
||||||
import com.maddyhome.idea.vim.api.VimSearchHelper
|
import com.maddyhome.idea.vim.api.VimSearchHelperBase
|
||||||
import com.maddyhome.idea.vim.common.TextRange
|
import com.maddyhome.idea.vim.common.TextRange
|
||||||
import com.maddyhome.idea.vim.helper.SearchHelper
|
import com.maddyhome.idea.vim.helper.SearchHelper
|
||||||
import com.maddyhome.idea.vim.helper.SearchOptions
|
import com.maddyhome.idea.vim.helper.SearchOptions
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
class IjVimSearchHelper : VimSearchHelper {
|
class IjVimSearchHelper : VimSearchHelperBase() {
|
||||||
override fun findNextParagraph(editor: VimEditor, caret: VimCaret, count: Int, allowBlanks: Boolean): Int {
|
override fun findNextParagraph(editor: VimEditor, caret: VimCaret, count: Int, allowBlanks: Boolean): Int {
|
||||||
return SearchHelper.findNextParagraph(
|
return SearchHelper.findNextParagraph(
|
||||||
(editor as IjVimEditor).editor,
|
(editor as IjVimEditor).editor,
|
||||||
@ -121,15 +121,6 @@ class IjVimSearchHelper : VimSearchHelper {
|
|||||||
return SearchHelper.findNextWordEnd(chars, pos, size, count, bigWord, spaceWords)
|
return SearchHelper.findNextWordEnd(chars, pos, size, count, bigWord, spaceWords)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun findNextWord(editor: VimEditor, searchFrom: Int, count: Int, bigWord: Boolean): Int {
|
|
||||||
return SearchHelper.findNextWord(
|
|
||||||
(editor as IjVimEditor).editor,
|
|
||||||
searchFrom,
|
|
||||||
count,
|
|
||||||
bigWord
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun findPattern(
|
override fun findPattern(
|
||||||
editor: VimEditor,
|
editor: VimEditor,
|
||||||
pattern: String?,
|
pattern: String?,
|
||||||
|
@ -23,9 +23,9 @@ import com.intellij.internal.statistic.eventLog.EventLogGroup
|
|||||||
import com.intellij.internal.statistic.eventLog.events.EventFields
|
import com.intellij.internal.statistic.eventLog.events.EventFields
|
||||||
import com.intellij.internal.statistic.eventLog.events.EventPair
|
import com.intellij.internal.statistic.eventLog.events.EventPair
|
||||||
import com.intellij.internal.statistic.eventLog.events.StringListEventField
|
import com.intellij.internal.statistic.eventLog.events.StringListEventField
|
||||||
import com.intellij.internal.statistic.eventLog.events.VarargEventId
|
|
||||||
import com.intellij.internal.statistic.service.fus.collectors.ApplicationUsagesCollector
|
import com.intellij.internal.statistic.service.fus.collectors.ApplicationUsagesCollector
|
||||||
import com.maddyhome.idea.vim.VimPlugin
|
import com.maddyhome.idea.vim.VimPlugin
|
||||||
|
import com.maddyhome.idea.vim.api.injector
|
||||||
import com.maddyhome.idea.vim.key.ShortcutOwner
|
import com.maddyhome.idea.vim.key.ShortcutOwner
|
||||||
import com.maddyhome.idea.vim.key.ShortcutOwnerInfo
|
import com.maddyhome.idea.vim.key.ShortcutOwnerInfo
|
||||||
import java.awt.event.InputEvent.CTRL_DOWN_MASK
|
import java.awt.event.InputEvent.CTRL_DOWN_MASK
|
||||||
@ -37,92 +37,16 @@ internal class ShortcutConflictState : ApplicationUsagesCollector() {
|
|||||||
override fun getGroup(): EventLogGroup = GROUP
|
override fun getGroup(): EventLogGroup = GROUP
|
||||||
|
|
||||||
override fun getMetrics(): Set<MetricEvent> {
|
override fun getMetrics(): Set<MetricEvent> {
|
||||||
return setOf(
|
val metrics = mutableSetOf<MetricEvent>()
|
||||||
HANDLERS.metric(
|
keyStrokes.forEach { keystroke ->
|
||||||
CTRL_1 withKeyStroke KeyStroke.getKeyStroke('1'.code, CTRL_DOWN_MASK),
|
getHandlersForShortcut(keystroke).forEach { mode ->
|
||||||
CTRL_2 withKeyStroke KeyStroke.getKeyStroke('2'.code, CTRL_DOWN_MASK),
|
metrics += HANDLER.metric(injector.parser.toKeyNotation(keystroke), mode)
|
||||||
CTRL_3 withKeyStroke KeyStroke.getKeyStroke('3'.code, CTRL_DOWN_MASK),
|
}
|
||||||
CTRL_4 withKeyStroke KeyStroke.getKeyStroke('4'.code, CTRL_DOWN_MASK),
|
}
|
||||||
CTRL_5 withKeyStroke KeyStroke.getKeyStroke('5'.code, CTRL_DOWN_MASK),
|
return metrics
|
||||||
CTRL_6 withKeyStroke KeyStroke.getKeyStroke('6'.code, CTRL_DOWN_MASK),
|
|
||||||
CTRL_7 withKeyStroke KeyStroke.getKeyStroke('7'.code, CTRL_DOWN_MASK),
|
|
||||||
CTRL_8 withKeyStroke KeyStroke.getKeyStroke('8'.code, CTRL_DOWN_MASK),
|
|
||||||
CTRL_9 withKeyStroke KeyStroke.getKeyStroke('9'.code, CTRL_DOWN_MASK),
|
|
||||||
CTRL_0 withKeyStroke KeyStroke.getKeyStroke('0'.code, CTRL_DOWN_MASK),
|
|
||||||
|
|
||||||
CTRL_SHIFT_1 withKeyStroke KeyStroke.getKeyStroke('1'.code, CTRL_DOWN_MASK + SHIFT_DOWN_MASK),
|
|
||||||
CTRL_SHIFT_2 withKeyStroke KeyStroke.getKeyStroke('2'.code, CTRL_DOWN_MASK + SHIFT_DOWN_MASK),
|
|
||||||
CTRL_SHIFT_3 withKeyStroke KeyStroke.getKeyStroke('3'.code, CTRL_DOWN_MASK + SHIFT_DOWN_MASK),
|
|
||||||
CTRL_SHIFT_4 withKeyStroke KeyStroke.getKeyStroke('4'.code, CTRL_DOWN_MASK + SHIFT_DOWN_MASK),
|
|
||||||
CTRL_SHIFT_5 withKeyStroke KeyStroke.getKeyStroke('5'.code, CTRL_DOWN_MASK + SHIFT_DOWN_MASK),
|
|
||||||
CTRL_SHIFT_6 withKeyStroke KeyStroke.getKeyStroke('6'.code, CTRL_DOWN_MASK + SHIFT_DOWN_MASK),
|
|
||||||
CTRL_SHIFT_7 withKeyStroke KeyStroke.getKeyStroke('7'.code, CTRL_DOWN_MASK + SHIFT_DOWN_MASK),
|
|
||||||
CTRL_SHIFT_8 withKeyStroke KeyStroke.getKeyStroke('8'.code, CTRL_DOWN_MASK + SHIFT_DOWN_MASK),
|
|
||||||
CTRL_SHIFT_9 withKeyStroke KeyStroke.getKeyStroke('9'.code, CTRL_DOWN_MASK + SHIFT_DOWN_MASK),
|
|
||||||
CTRL_SHIFT_0 withKeyStroke KeyStroke.getKeyStroke('0'.code, CTRL_DOWN_MASK + SHIFT_DOWN_MASK),
|
|
||||||
|
|
||||||
CTRL_A withKeyStroke KeyStroke.getKeyStroke('A'.code, CTRL_DOWN_MASK),
|
|
||||||
CTRL_B withKeyStroke KeyStroke.getKeyStroke('B'.code, CTRL_DOWN_MASK),
|
|
||||||
CTRL_C withKeyStroke KeyStroke.getKeyStroke('C'.code, CTRL_DOWN_MASK),
|
|
||||||
CTRL_D withKeyStroke KeyStroke.getKeyStroke('D'.code, CTRL_DOWN_MASK),
|
|
||||||
CTRL_E withKeyStroke KeyStroke.getKeyStroke('E'.code, CTRL_DOWN_MASK),
|
|
||||||
CTRL_F withKeyStroke KeyStroke.getKeyStroke('F'.code, CTRL_DOWN_MASK),
|
|
||||||
CTRL_G withKeyStroke KeyStroke.getKeyStroke('G'.code, CTRL_DOWN_MASK),
|
|
||||||
CTRL_H withKeyStroke KeyStroke.getKeyStroke('H'.code, CTRL_DOWN_MASK),
|
|
||||||
CTRL_I withKeyStroke KeyStroke.getKeyStroke('I'.code, CTRL_DOWN_MASK),
|
|
||||||
CTRL_J withKeyStroke KeyStroke.getKeyStroke('J'.code, CTRL_DOWN_MASK),
|
|
||||||
CTRL_K withKeyStroke KeyStroke.getKeyStroke('K'.code, CTRL_DOWN_MASK),
|
|
||||||
CTRL_L withKeyStroke KeyStroke.getKeyStroke('L'.code, CTRL_DOWN_MASK),
|
|
||||||
CTRL_M withKeyStroke KeyStroke.getKeyStroke('M'.code, CTRL_DOWN_MASK),
|
|
||||||
CTRL_N withKeyStroke KeyStroke.getKeyStroke('N'.code, CTRL_DOWN_MASK),
|
|
||||||
CTRL_O withKeyStroke KeyStroke.getKeyStroke('O'.code, CTRL_DOWN_MASK),
|
|
||||||
CTRL_P withKeyStroke KeyStroke.getKeyStroke('P'.code, CTRL_DOWN_MASK),
|
|
||||||
CTRL_Q withKeyStroke KeyStroke.getKeyStroke('Q'.code, CTRL_DOWN_MASK),
|
|
||||||
CTRL_R withKeyStroke KeyStroke.getKeyStroke('R'.code, CTRL_DOWN_MASK),
|
|
||||||
CTRL_S withKeyStroke KeyStroke.getKeyStroke('S'.code, CTRL_DOWN_MASK),
|
|
||||||
CTRL_T withKeyStroke KeyStroke.getKeyStroke('T'.code, CTRL_DOWN_MASK),
|
|
||||||
CTRL_U withKeyStroke KeyStroke.getKeyStroke('U'.code, CTRL_DOWN_MASK),
|
|
||||||
CTRL_V withKeyStroke KeyStroke.getKeyStroke('V'.code, CTRL_DOWN_MASK),
|
|
||||||
CTRL_W withKeyStroke KeyStroke.getKeyStroke('W'.code, CTRL_DOWN_MASK),
|
|
||||||
CTRL_X withKeyStroke KeyStroke.getKeyStroke('X'.code, CTRL_DOWN_MASK),
|
|
||||||
CTRL_Y withKeyStroke KeyStroke.getKeyStroke('Y'.code, CTRL_DOWN_MASK),
|
|
||||||
CTRL_Z withKeyStroke KeyStroke.getKeyStroke('Z'.code, CTRL_DOWN_MASK),
|
|
||||||
CTRL_BR1 withKeyStroke KeyStroke.getKeyStroke('['.code, CTRL_DOWN_MASK),
|
|
||||||
CTRL_BR2 withKeyStroke KeyStroke.getKeyStroke(']'.code, CTRL_DOWN_MASK),
|
|
||||||
|
|
||||||
CTRL_SHIFT_A withKeyStroke KeyStroke.getKeyStroke('A'.code, CTRL_DOWN_MASK + SHIFT_DOWN_MASK),
|
|
||||||
CTRL_SHIFT_B withKeyStroke KeyStroke.getKeyStroke('B'.code, CTRL_DOWN_MASK + SHIFT_DOWN_MASK),
|
|
||||||
CTRL_SHIFT_C withKeyStroke KeyStroke.getKeyStroke('C'.code, CTRL_DOWN_MASK + SHIFT_DOWN_MASK),
|
|
||||||
CTRL_SHIFT_D withKeyStroke KeyStroke.getKeyStroke('D'.code, CTRL_DOWN_MASK + SHIFT_DOWN_MASK),
|
|
||||||
CTRL_SHIFT_E withKeyStroke KeyStroke.getKeyStroke('E'.code, CTRL_DOWN_MASK + SHIFT_DOWN_MASK),
|
|
||||||
CTRL_SHIFT_F withKeyStroke KeyStroke.getKeyStroke('F'.code, CTRL_DOWN_MASK + SHIFT_DOWN_MASK),
|
|
||||||
CTRL_SHIFT_G withKeyStroke KeyStroke.getKeyStroke('G'.code, CTRL_DOWN_MASK + SHIFT_DOWN_MASK),
|
|
||||||
CTRL_SHIFT_H withKeyStroke KeyStroke.getKeyStroke('H'.code, CTRL_DOWN_MASK + SHIFT_DOWN_MASK),
|
|
||||||
CTRL_SHIFT_I withKeyStroke KeyStroke.getKeyStroke('I'.code, CTRL_DOWN_MASK + SHIFT_DOWN_MASK),
|
|
||||||
CTRL_SHIFT_J withKeyStroke KeyStroke.getKeyStroke('J'.code, CTRL_DOWN_MASK + SHIFT_DOWN_MASK),
|
|
||||||
CTRL_SHIFT_K withKeyStroke KeyStroke.getKeyStroke('K'.code, CTRL_DOWN_MASK + SHIFT_DOWN_MASK),
|
|
||||||
CTRL_SHIFT_L withKeyStroke KeyStroke.getKeyStroke('L'.code, CTRL_DOWN_MASK + SHIFT_DOWN_MASK),
|
|
||||||
CTRL_SHIFT_M withKeyStroke KeyStroke.getKeyStroke('M'.code, CTRL_DOWN_MASK + SHIFT_DOWN_MASK),
|
|
||||||
CTRL_SHIFT_N withKeyStroke KeyStroke.getKeyStroke('N'.code, CTRL_DOWN_MASK + SHIFT_DOWN_MASK),
|
|
||||||
CTRL_SHIFT_O withKeyStroke KeyStroke.getKeyStroke('O'.code, CTRL_DOWN_MASK + SHIFT_DOWN_MASK),
|
|
||||||
CTRL_SHIFT_P withKeyStroke KeyStroke.getKeyStroke('P'.code, CTRL_DOWN_MASK + SHIFT_DOWN_MASK),
|
|
||||||
CTRL_SHIFT_Q withKeyStroke KeyStroke.getKeyStroke('Q'.code, CTRL_DOWN_MASK + SHIFT_DOWN_MASK),
|
|
||||||
CTRL_SHIFT_R withKeyStroke KeyStroke.getKeyStroke('R'.code, CTRL_DOWN_MASK + SHIFT_DOWN_MASK),
|
|
||||||
CTRL_SHIFT_S withKeyStroke KeyStroke.getKeyStroke('S'.code, CTRL_DOWN_MASK + SHIFT_DOWN_MASK),
|
|
||||||
CTRL_SHIFT_T withKeyStroke KeyStroke.getKeyStroke('T'.code, CTRL_DOWN_MASK + SHIFT_DOWN_MASK),
|
|
||||||
CTRL_SHIFT_U withKeyStroke KeyStroke.getKeyStroke('U'.code, CTRL_DOWN_MASK + SHIFT_DOWN_MASK),
|
|
||||||
CTRL_SHIFT_V withKeyStroke KeyStroke.getKeyStroke('V'.code, CTRL_DOWN_MASK + SHIFT_DOWN_MASK),
|
|
||||||
CTRL_SHIFT_W withKeyStroke KeyStroke.getKeyStroke('W'.code, CTRL_DOWN_MASK + SHIFT_DOWN_MASK),
|
|
||||||
CTRL_SHIFT_X withKeyStroke KeyStroke.getKeyStroke('X'.code, CTRL_DOWN_MASK + SHIFT_DOWN_MASK),
|
|
||||||
CTRL_SHIFT_Y withKeyStroke KeyStroke.getKeyStroke('Y'.code, CTRL_DOWN_MASK + SHIFT_DOWN_MASK),
|
|
||||||
CTRL_SHIFT_Z withKeyStroke KeyStroke.getKeyStroke('Z'.code, CTRL_DOWN_MASK + SHIFT_DOWN_MASK),
|
|
||||||
CTRL_SHIFT_BR1 withKeyStroke KeyStroke.getKeyStroke('['.code, CTRL_DOWN_MASK + SHIFT_DOWN_MASK),
|
|
||||||
CTRL_SHIFT_BR2 withKeyStroke KeyStroke.getKeyStroke(']'.code, CTRL_DOWN_MASK + SHIFT_DOWN_MASK),
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private infix fun StringListEventField.withKeyStroke(ks: KeyStroke): EventPair<List<String>> {
|
fun StringListEventField.withKeyStroke(ks: KeyStroke): EventPair<List<String>> {
|
||||||
return this.with(getHandlersForShortcut(ks).map { it.name })
|
return this.with(getHandlersForShortcut(ks).map { it.name })
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -162,170 +86,91 @@ internal class ShortcutConflictState : ApplicationUsagesCollector() {
|
|||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private val GROUP = EventLogGroup("vim.handlers", 1)
|
private val GROUP = EventLogGroup("vim.handlers", 1)
|
||||||
private val values = HandledModes.values().map { it.name }
|
|
||||||
|
|
||||||
private val CTRL_1 = EventFields.StringList("Ctrl-1", values)
|
private val keyStrokes = listOf(
|
||||||
private val CTRL_2 = EventFields.StringList("Ctrl-2", values)
|
KeyStroke.getKeyStroke('1'.code, CTRL_DOWN_MASK),
|
||||||
private val CTRL_3 = EventFields.StringList("Ctrl-3", values)
|
KeyStroke.getKeyStroke('2'.code, CTRL_DOWN_MASK),
|
||||||
private val CTRL_4 = EventFields.StringList("Ctrl-4", values)
|
KeyStroke.getKeyStroke('3'.code, CTRL_DOWN_MASK),
|
||||||
private val CTRL_5 = EventFields.StringList("Ctrl-5", values)
|
KeyStroke.getKeyStroke('4'.code, CTRL_DOWN_MASK),
|
||||||
private val CTRL_6 = EventFields.StringList("Ctrl-6", values)
|
KeyStroke.getKeyStroke('5'.code, CTRL_DOWN_MASK),
|
||||||
private val CTRL_7 = EventFields.StringList("Ctrl-7", values)
|
KeyStroke.getKeyStroke('6'.code, CTRL_DOWN_MASK),
|
||||||
private val CTRL_8 = EventFields.StringList("Ctrl-8", values)
|
KeyStroke.getKeyStroke('7'.code, CTRL_DOWN_MASK),
|
||||||
private val CTRL_9 = EventFields.StringList("Ctrl-9", values)
|
KeyStroke.getKeyStroke('8'.code, CTRL_DOWN_MASK),
|
||||||
private val CTRL_0 = EventFields.StringList("Ctrl-0", values)
|
KeyStroke.getKeyStroke('9'.code, CTRL_DOWN_MASK),
|
||||||
|
KeyStroke.getKeyStroke('0'.code, CTRL_DOWN_MASK),
|
||||||
|
|
||||||
private val CTRL_SHIFT_1 = EventFields.StringList("Ctrl-Shift-1", values)
|
KeyStroke.getKeyStroke('1'.code, CTRL_DOWN_MASK + SHIFT_DOWN_MASK),
|
||||||
private val CTRL_SHIFT_2 = EventFields.StringList("Ctrl-Shift-2", values)
|
KeyStroke.getKeyStroke('2'.code, CTRL_DOWN_MASK + SHIFT_DOWN_MASK),
|
||||||
private val CTRL_SHIFT_3 = EventFields.StringList("Ctrl-Shift-3", values)
|
KeyStroke.getKeyStroke('3'.code, CTRL_DOWN_MASK + SHIFT_DOWN_MASK),
|
||||||
private val CTRL_SHIFT_4 = EventFields.StringList("Ctrl-Shift-4", values)
|
KeyStroke.getKeyStroke('4'.code, CTRL_DOWN_MASK + SHIFT_DOWN_MASK),
|
||||||
private val CTRL_SHIFT_5 = EventFields.StringList("Ctrl-Shift-5", values)
|
KeyStroke.getKeyStroke('5'.code, CTRL_DOWN_MASK + SHIFT_DOWN_MASK),
|
||||||
private val CTRL_SHIFT_6 = EventFields.StringList("Ctrl-Shift-6", values)
|
KeyStroke.getKeyStroke('6'.code, CTRL_DOWN_MASK + SHIFT_DOWN_MASK),
|
||||||
private val CTRL_SHIFT_7 = EventFields.StringList("Ctrl-Shift-7", values)
|
KeyStroke.getKeyStroke('7'.code, CTRL_DOWN_MASK + SHIFT_DOWN_MASK),
|
||||||
private val CTRL_SHIFT_8 = EventFields.StringList("Ctrl-Shift-8", values)
|
KeyStroke.getKeyStroke('8'.code, CTRL_DOWN_MASK + SHIFT_DOWN_MASK),
|
||||||
private val CTRL_SHIFT_9 = EventFields.StringList("Ctrl-Shift-9", values)
|
KeyStroke.getKeyStroke('9'.code, CTRL_DOWN_MASK + SHIFT_DOWN_MASK),
|
||||||
private val CTRL_SHIFT_0 = EventFields.StringList("Ctrl-Shift-0", values)
|
KeyStroke.getKeyStroke('0'.code, CTRL_DOWN_MASK + SHIFT_DOWN_MASK),
|
||||||
|
|
||||||
private val CTRL_A = EventFields.StringList("Ctrl-A", values)
|
KeyStroke.getKeyStroke('A'.code, CTRL_DOWN_MASK),
|
||||||
private val CTRL_B = EventFields.StringList("Ctrl-B", values)
|
KeyStroke.getKeyStroke('B'.code, CTRL_DOWN_MASK),
|
||||||
private val CTRL_C = EventFields.StringList("Ctrl-C", values)
|
KeyStroke.getKeyStroke('C'.code, CTRL_DOWN_MASK),
|
||||||
private val CTRL_D = EventFields.StringList("Ctrl-D", values)
|
KeyStroke.getKeyStroke('D'.code, CTRL_DOWN_MASK),
|
||||||
private val CTRL_E = EventFields.StringList("Ctrl-E", values)
|
KeyStroke.getKeyStroke('E'.code, CTRL_DOWN_MASK),
|
||||||
private val CTRL_F = EventFields.StringList("Ctrl-F", values)
|
KeyStroke.getKeyStroke('F'.code, CTRL_DOWN_MASK),
|
||||||
private val CTRL_G = EventFields.StringList("Ctrl-G", values)
|
KeyStroke.getKeyStroke('G'.code, CTRL_DOWN_MASK),
|
||||||
private val CTRL_H = EventFields.StringList("Ctrl-H", values)
|
KeyStroke.getKeyStroke('H'.code, CTRL_DOWN_MASK),
|
||||||
private val CTRL_I = EventFields.StringList("Ctrl-I", values)
|
KeyStroke.getKeyStroke('I'.code, CTRL_DOWN_MASK),
|
||||||
private val CTRL_J = EventFields.StringList("Ctrl-J", values)
|
KeyStroke.getKeyStroke('J'.code, CTRL_DOWN_MASK),
|
||||||
private val CTRL_K = EventFields.StringList("Ctrl-K", values)
|
KeyStroke.getKeyStroke('K'.code, CTRL_DOWN_MASK),
|
||||||
private val CTRL_L = EventFields.StringList("Ctrl-L", values)
|
KeyStroke.getKeyStroke('L'.code, CTRL_DOWN_MASK),
|
||||||
private val CTRL_M = EventFields.StringList("Ctrl-M", values)
|
KeyStroke.getKeyStroke('M'.code, CTRL_DOWN_MASK),
|
||||||
private val CTRL_N = EventFields.StringList("Ctrl-N", values)
|
KeyStroke.getKeyStroke('N'.code, CTRL_DOWN_MASK),
|
||||||
private val CTRL_O = EventFields.StringList("Ctrl-O", values)
|
KeyStroke.getKeyStroke('O'.code, CTRL_DOWN_MASK),
|
||||||
private val CTRL_P = EventFields.StringList("Ctrl-P", values)
|
KeyStroke.getKeyStroke('P'.code, CTRL_DOWN_MASK),
|
||||||
private val CTRL_Q = EventFields.StringList("Ctrl-Q", values)
|
KeyStroke.getKeyStroke('Q'.code, CTRL_DOWN_MASK),
|
||||||
private val CTRL_R = EventFields.StringList("Ctrl-R", values)
|
KeyStroke.getKeyStroke('R'.code, CTRL_DOWN_MASK),
|
||||||
private val CTRL_S = EventFields.StringList("Ctrl-S", values)
|
KeyStroke.getKeyStroke('S'.code, CTRL_DOWN_MASK),
|
||||||
private val CTRL_T = EventFields.StringList("Ctrl-T", values)
|
KeyStroke.getKeyStroke('T'.code, CTRL_DOWN_MASK),
|
||||||
private val CTRL_U = EventFields.StringList("Ctrl-U", values)
|
KeyStroke.getKeyStroke('U'.code, CTRL_DOWN_MASK),
|
||||||
private val CTRL_V = EventFields.StringList("Ctrl-V", values)
|
KeyStroke.getKeyStroke('V'.code, CTRL_DOWN_MASK),
|
||||||
private val CTRL_W = EventFields.StringList("Ctrl-W", values)
|
KeyStroke.getKeyStroke('W'.code, CTRL_DOWN_MASK),
|
||||||
private val CTRL_X = EventFields.StringList("Ctrl-X", values)
|
KeyStroke.getKeyStroke('X'.code, CTRL_DOWN_MASK),
|
||||||
private val CTRL_Y = EventFields.StringList("Ctrl-Y", values)
|
KeyStroke.getKeyStroke('Y'.code, CTRL_DOWN_MASK),
|
||||||
private val CTRL_Z = EventFields.StringList("Ctrl-Z", values)
|
KeyStroke.getKeyStroke('Z'.code, CTRL_DOWN_MASK),
|
||||||
private val CTRL_BR1 = EventFields.StringList("Ctrl-[", values)
|
KeyStroke.getKeyStroke('['.code, CTRL_DOWN_MASK),
|
||||||
private val CTRL_BR2 = EventFields.StringList("Ctrl-]", values)
|
KeyStroke.getKeyStroke(']'.code, CTRL_DOWN_MASK),
|
||||||
|
|
||||||
private val CTRL_SHIFT_A = EventFields.StringList("Ctrl-Shift-A", values)
|
KeyStroke.getKeyStroke('A'.code, CTRL_DOWN_MASK + SHIFT_DOWN_MASK),
|
||||||
private val CTRL_SHIFT_B = EventFields.StringList("Ctrl-Shift-B", values)
|
KeyStroke.getKeyStroke('B'.code, CTRL_DOWN_MASK + SHIFT_DOWN_MASK),
|
||||||
private val CTRL_SHIFT_C = EventFields.StringList("Ctrl-Shift-C", values)
|
KeyStroke.getKeyStroke('C'.code, CTRL_DOWN_MASK + SHIFT_DOWN_MASK),
|
||||||
private val CTRL_SHIFT_D = EventFields.StringList("Ctrl-Shift-D", values)
|
KeyStroke.getKeyStroke('D'.code, CTRL_DOWN_MASK + SHIFT_DOWN_MASK),
|
||||||
private val CTRL_SHIFT_E = EventFields.StringList("Ctrl-Shift-E", values)
|
KeyStroke.getKeyStroke('E'.code, CTRL_DOWN_MASK + SHIFT_DOWN_MASK),
|
||||||
private val CTRL_SHIFT_F = EventFields.StringList("Ctrl-Shift-F", values)
|
KeyStroke.getKeyStroke('F'.code, CTRL_DOWN_MASK + SHIFT_DOWN_MASK),
|
||||||
private val CTRL_SHIFT_G = EventFields.StringList("Ctrl-Shift-G", values)
|
KeyStroke.getKeyStroke('G'.code, CTRL_DOWN_MASK + SHIFT_DOWN_MASK),
|
||||||
private val CTRL_SHIFT_H = EventFields.StringList("Ctrl-Shift-H", values)
|
KeyStroke.getKeyStroke('H'.code, CTRL_DOWN_MASK + SHIFT_DOWN_MASK),
|
||||||
private val CTRL_SHIFT_I = EventFields.StringList("Ctrl-Shift-I", values)
|
KeyStroke.getKeyStroke('I'.code, CTRL_DOWN_MASK + SHIFT_DOWN_MASK),
|
||||||
private val CTRL_SHIFT_J = EventFields.StringList("Ctrl-Shift-J", values)
|
KeyStroke.getKeyStroke('J'.code, CTRL_DOWN_MASK + SHIFT_DOWN_MASK),
|
||||||
private val CTRL_SHIFT_K = EventFields.StringList("Ctrl-Shift-K", values)
|
KeyStroke.getKeyStroke('K'.code, CTRL_DOWN_MASK + SHIFT_DOWN_MASK),
|
||||||
private val CTRL_SHIFT_L = EventFields.StringList("Ctrl-Shift-L", values)
|
KeyStroke.getKeyStroke('L'.code, CTRL_DOWN_MASK + SHIFT_DOWN_MASK),
|
||||||
private val CTRL_SHIFT_M = EventFields.StringList("Ctrl-Shift-M", values)
|
KeyStroke.getKeyStroke('M'.code, CTRL_DOWN_MASK + SHIFT_DOWN_MASK),
|
||||||
private val CTRL_SHIFT_N = EventFields.StringList("Ctrl-Shift-N", values)
|
KeyStroke.getKeyStroke('N'.code, CTRL_DOWN_MASK + SHIFT_DOWN_MASK),
|
||||||
private val CTRL_SHIFT_O = EventFields.StringList("Ctrl-Shift-O", values)
|
KeyStroke.getKeyStroke('O'.code, CTRL_DOWN_MASK + SHIFT_DOWN_MASK),
|
||||||
private val CTRL_SHIFT_P = EventFields.StringList("Ctrl-Shift-P", values)
|
KeyStroke.getKeyStroke('P'.code, CTRL_DOWN_MASK + SHIFT_DOWN_MASK),
|
||||||
private val CTRL_SHIFT_Q = EventFields.StringList("Ctrl-Shift-Q", values)
|
KeyStroke.getKeyStroke('Q'.code, CTRL_DOWN_MASK + SHIFT_DOWN_MASK),
|
||||||
private val CTRL_SHIFT_R = EventFields.StringList("Ctrl-Shift-R", values)
|
KeyStroke.getKeyStroke('R'.code, CTRL_DOWN_MASK + SHIFT_DOWN_MASK),
|
||||||
private val CTRL_SHIFT_S = EventFields.StringList("Ctrl-Shift-S", values)
|
KeyStroke.getKeyStroke('S'.code, CTRL_DOWN_MASK + SHIFT_DOWN_MASK),
|
||||||
private val CTRL_SHIFT_T = EventFields.StringList("Ctrl-Shift-T", values)
|
KeyStroke.getKeyStroke('T'.code, CTRL_DOWN_MASK + SHIFT_DOWN_MASK),
|
||||||
private val CTRL_SHIFT_U = EventFields.StringList("Ctrl-Shift-U", values)
|
KeyStroke.getKeyStroke('U'.code, CTRL_DOWN_MASK + SHIFT_DOWN_MASK),
|
||||||
private val CTRL_SHIFT_V = EventFields.StringList("Ctrl-Shift-V", values)
|
KeyStroke.getKeyStroke('V'.code, CTRL_DOWN_MASK + SHIFT_DOWN_MASK),
|
||||||
private val CTRL_SHIFT_W = EventFields.StringList("Ctrl-Shift-W", values)
|
KeyStroke.getKeyStroke('W'.code, CTRL_DOWN_MASK + SHIFT_DOWN_MASK),
|
||||||
private val CTRL_SHIFT_X = EventFields.StringList("Ctrl-Shift-X", values)
|
KeyStroke.getKeyStroke('X'.code, CTRL_DOWN_MASK + SHIFT_DOWN_MASK),
|
||||||
private val CTRL_SHIFT_Y = EventFields.StringList("Ctrl-Shift-Y", values)
|
KeyStroke.getKeyStroke('Y'.code, CTRL_DOWN_MASK + SHIFT_DOWN_MASK),
|
||||||
private val CTRL_SHIFT_Z = EventFields.StringList("Ctrl-Shift-Z", values)
|
KeyStroke.getKeyStroke('Z'.code, CTRL_DOWN_MASK + SHIFT_DOWN_MASK),
|
||||||
private val CTRL_SHIFT_BR1 = EventFields.StringList("Ctrl-Shift-[", values)
|
KeyStroke.getKeyStroke('['.code, CTRL_DOWN_MASK + SHIFT_DOWN_MASK),
|
||||||
private val CTRL_SHIFT_BR2 = EventFields.StringList("Ctrl-Shift-]", values)
|
KeyStroke.getKeyStroke(']'.code, CTRL_DOWN_MASK + SHIFT_DOWN_MASK),
|
||||||
|
|
||||||
private val HANDLERS: VarargEventId = GROUP.registerVarargEvent(
|
|
||||||
"vim.handlers",
|
|
||||||
CTRL_1,
|
|
||||||
CTRL_2,
|
|
||||||
CTRL_3,
|
|
||||||
CTRL_4,
|
|
||||||
CTRL_5,
|
|
||||||
CTRL_6,
|
|
||||||
CTRL_7,
|
|
||||||
CTRL_8,
|
|
||||||
CTRL_9,
|
|
||||||
CTRL_0,
|
|
||||||
|
|
||||||
CTRL_SHIFT_1,
|
|
||||||
CTRL_SHIFT_2,
|
|
||||||
CTRL_SHIFT_3,
|
|
||||||
CTRL_SHIFT_4,
|
|
||||||
CTRL_SHIFT_5,
|
|
||||||
CTRL_SHIFT_6,
|
|
||||||
CTRL_SHIFT_7,
|
|
||||||
CTRL_SHIFT_8,
|
|
||||||
CTRL_SHIFT_9,
|
|
||||||
CTRL_SHIFT_0,
|
|
||||||
|
|
||||||
CTRL_A,
|
|
||||||
CTRL_B,
|
|
||||||
CTRL_C,
|
|
||||||
CTRL_D,
|
|
||||||
CTRL_E,
|
|
||||||
CTRL_F,
|
|
||||||
CTRL_G,
|
|
||||||
CTRL_H,
|
|
||||||
CTRL_I,
|
|
||||||
CTRL_J,
|
|
||||||
CTRL_K,
|
|
||||||
CTRL_L,
|
|
||||||
CTRL_M,
|
|
||||||
CTRL_N,
|
|
||||||
CTRL_O,
|
|
||||||
CTRL_P,
|
|
||||||
CTRL_Q,
|
|
||||||
CTRL_R,
|
|
||||||
CTRL_S,
|
|
||||||
CTRL_T,
|
|
||||||
CTRL_U,
|
|
||||||
CTRL_V,
|
|
||||||
CTRL_W,
|
|
||||||
CTRL_X,
|
|
||||||
CTRL_Y,
|
|
||||||
CTRL_Z,
|
|
||||||
CTRL_BR1,
|
|
||||||
CTRL_BR2,
|
|
||||||
|
|
||||||
CTRL_SHIFT_A,
|
|
||||||
CTRL_SHIFT_B,
|
|
||||||
CTRL_SHIFT_C,
|
|
||||||
CTRL_SHIFT_D,
|
|
||||||
CTRL_SHIFT_E,
|
|
||||||
CTRL_SHIFT_F,
|
|
||||||
CTRL_SHIFT_G,
|
|
||||||
CTRL_SHIFT_H,
|
|
||||||
CTRL_SHIFT_I,
|
|
||||||
CTRL_SHIFT_J,
|
|
||||||
CTRL_SHIFT_K,
|
|
||||||
CTRL_SHIFT_L,
|
|
||||||
CTRL_SHIFT_M,
|
|
||||||
CTRL_SHIFT_N,
|
|
||||||
CTRL_SHIFT_O,
|
|
||||||
CTRL_SHIFT_P,
|
|
||||||
CTRL_SHIFT_Q,
|
|
||||||
CTRL_SHIFT_R,
|
|
||||||
CTRL_SHIFT_S,
|
|
||||||
CTRL_SHIFT_T,
|
|
||||||
CTRL_SHIFT_U,
|
|
||||||
CTRL_SHIFT_V,
|
|
||||||
CTRL_SHIFT_W,
|
|
||||||
CTRL_SHIFT_X,
|
|
||||||
CTRL_SHIFT_Y,
|
|
||||||
CTRL_SHIFT_Z,
|
|
||||||
CTRL_SHIFT_BR1,
|
|
||||||
CTRL_SHIFT_BR2,
|
|
||||||
)
|
)
|
||||||
|
private val KEY_STROKE = EventFields.String("key_stroke", keyStrokes.map { injector.parser.toKeyNotation(it) })
|
||||||
|
private val HANDLER_MODE = EventFields.Enum<HandledModes>("handler")
|
||||||
|
private val HANDLER = GROUP.registerEvent("vim.handler", KEY_STROKE, HANDLER_MODE)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,8 +59,8 @@ internal class VimscriptState : ApplicationUsagesCollector() {
|
|||||||
var isFunctionDeclarationUsed = false
|
var isFunctionDeclarationUsed = false
|
||||||
var isFunctionCallUsed = false
|
var isFunctionCallUsed = false
|
||||||
|
|
||||||
private val SOURCED_FILES = EventFields.Int("number_of_sourced_files")
|
private val SOURCED_FILES = EventFields.RoundedInt("number_of_sourced_files")
|
||||||
private val IDEAVIMRC_SIZE = EventFields.Int("ideavimrc_size")
|
private val IDEAVIMRC_SIZE = EventFields.RoundedInt("ideavimrc_size")
|
||||||
private val EXTENSIONS_ENABLED_BY_SET = EventFields.StringList("extensions_enabled_by_set", PluginState.extensionNames)
|
private val EXTENSIONS_ENABLED_BY_SET = EventFields.StringList("extensions_enabled_by_set", PluginState.extensionNames)
|
||||||
private val EXTENSIONS_ENABLED_BY_PLUG = EventFields.StringList("extensions_enabled_by_plug", PluginState.extensionNames)
|
private val EXTENSIONS_ENABLED_BY_PLUG = EventFields.StringList("extensions_enabled_by_plug", PluginState.extensionNames)
|
||||||
private val IS_IDE_SPECIFIC_CONFIGURATION_USED = EventFields.Boolean("is_IDE-specific_configuration_used")
|
private val IS_IDE_SPECIFIC_CONFIGURATION_USED = EventFields.Boolean("is_IDE-specific_configuration_used")
|
||||||
|
@ -24,7 +24,6 @@ import com.intellij.openapi.actionSystem.ActionUpdateThread
|
|||||||
import com.intellij.openapi.actionSystem.AnActionEvent
|
import com.intellij.openapi.actionSystem.AnActionEvent
|
||||||
import com.intellij.openapi.actionSystem.DefaultActionGroup
|
import com.intellij.openapi.actionSystem.DefaultActionGroup
|
||||||
import com.intellij.openapi.actionSystem.PlatformDataKeys
|
import com.intellij.openapi.actionSystem.PlatformDataKeys
|
||||||
import com.intellij.openapi.components.service
|
|
||||||
import com.intellij.openapi.editor.Document
|
import com.intellij.openapi.editor.Document
|
||||||
import com.intellij.openapi.editor.toolbar.floating.AbstractFloatingToolbarProvider
|
import com.intellij.openapi.editor.toolbar.floating.AbstractFloatingToolbarProvider
|
||||||
import com.intellij.openapi.editor.toolbar.floating.FloatingToolbarComponent
|
import com.intellij.openapi.editor.toolbar.floating.FloatingToolbarComponent
|
||||||
@ -151,7 +150,7 @@ class ReloadVimRc : DumbAwareAction() {
|
|||||||
val editor = e.getData(PlatformDataKeys.EDITOR) ?: return
|
val editor = e.getData(PlatformDataKeys.EDITOR) ?: return
|
||||||
FileDocumentManager.getInstance().saveDocumentAsIs(editor.document)
|
FileDocumentManager.getInstance().saveDocumentAsIs(editor.document)
|
||||||
injector.keyGroup.removeKeyMapping(MappingOwner.IdeaVim.InitScript)
|
injector.keyGroup.removeKeyMapping(MappingOwner.IdeaVim.InitScript)
|
||||||
service<Troubleshooter>().removeByType("old-action-notation-in-mappings")
|
Troubleshooter.instance.removeByType("old-action-notation-in-mappings")
|
||||||
executeIdeaVimRc()
|
executeIdeaVimRc()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,7 @@ package com.maddyhome.idea.vim.ui.ex
|
|||||||
import com.intellij.openapi.diagnostic.logger
|
import com.intellij.openapi.diagnostic.logger
|
||||||
import com.maddyhome.idea.vim.KeyHandler
|
import com.maddyhome.idea.vim.KeyHandler
|
||||||
import com.maddyhome.idea.vim.VimPlugin
|
import com.maddyhome.idea.vim.VimPlugin
|
||||||
import com.maddyhome.idea.vim.helper.SearchHelper
|
import com.maddyhome.idea.vim.api.VimSearchHelperBase
|
||||||
import com.maddyhome.idea.vim.newapi.vim
|
import com.maddyhome.idea.vim.newapi.vim
|
||||||
import java.awt.event.ActionEvent
|
import java.awt.event.ActionEvent
|
||||||
import java.awt.event.KeyEvent
|
import java.awt.event.KeyEvent
|
||||||
@ -238,14 +238,14 @@ class DeletePreviousWordAction : TextAction(DefaultEditorKit.deletePrevWordActio
|
|||||||
target.saveLastEntry()
|
target.saveLastEntry()
|
||||||
val doc = target.document
|
val doc = target.document
|
||||||
val caret = target.caret
|
val caret = target.caret
|
||||||
val offset = SearchHelper.findNextWord(
|
val offset = VimSearchHelperBase.Companion.findNextWord(
|
||||||
target.actualText, caret.dot, target.actualText.length,
|
target.actualText, caret.dot.toLong(), target.actualText.length.toLong(),
|
||||||
-1, false, false
|
-1, false, false
|
||||||
)
|
)
|
||||||
if (logger.isDebugEnabled) logger.debug("offset=$offset")
|
if (logger.isDebugEnabled) logger.debug("offset=$offset")
|
||||||
try {
|
try {
|
||||||
val pos = caret.dot
|
val pos = caret.dot
|
||||||
doc.remove(offset, pos - offset)
|
doc.remove(offset.toInt(), (pos - offset).toInt())
|
||||||
} catch (ex: BadLocationException) {
|
} catch (ex: BadLocationException) {
|
||||||
// ignore
|
// ignore
|
||||||
}
|
}
|
||||||
|
@ -94,7 +94,7 @@ abstract class VimTestCase : UsefulTestCase() {
|
|||||||
super.setUp()
|
super.setUp()
|
||||||
val factory = IdeaTestFixtureFactory.getFixtureFactory()
|
val factory = IdeaTestFixtureFactory.getFixtureFactory()
|
||||||
val projectDescriptor = LightProjectDescriptor.EMPTY_PROJECT_DESCRIPTOR
|
val projectDescriptor = LightProjectDescriptor.EMPTY_PROJECT_DESCRIPTOR
|
||||||
val fixtureBuilder = factory.createLightFixtureBuilder(projectDescriptor)
|
val fixtureBuilder = factory.createLightFixtureBuilder(projectDescriptor, "IdeaVim")
|
||||||
val fixture = fixtureBuilder.fixture
|
val fixture = fixtureBuilder.fixture
|
||||||
myFixture = IdeaTestFixtureFactory.getFixtureFactory().createCodeInsightFixture(
|
myFixture = IdeaTestFixtureFactory.getFixtureFactory().createCodeInsightFixture(
|
||||||
fixture,
|
fixture,
|
||||||
|
@ -20,6 +20,7 @@ package org.jetbrains.plugins.ideavim.action
|
|||||||
import com.maddyhome.idea.vim.VimPlugin
|
import com.maddyhome.idea.vim.VimPlugin
|
||||||
import com.maddyhome.idea.vim.api.injector
|
import com.maddyhome.idea.vim.api.injector
|
||||||
import com.maddyhome.idea.vim.command.VimStateMachine
|
import com.maddyhome.idea.vim.command.VimStateMachine
|
||||||
|
import com.maddyhome.idea.vim.helper.StringHelper.parseKeys
|
||||||
import com.maddyhome.idea.vim.helper.vimStateMachine
|
import com.maddyhome.idea.vim.helper.vimStateMachine
|
||||||
import org.jetbrains.plugins.ideavim.SkipNeovimReason
|
import org.jetbrains.plugins.ideavim.SkipNeovimReason
|
||||||
import org.jetbrains.plugins.ideavim.TestWithoutNeovim
|
import org.jetbrains.plugins.ideavim.TestWithoutNeovim
|
||||||
@ -1039,4 +1040,16 @@ two
|
|||||||
)
|
)
|
||||||
assertOffset(4)
|
assertOffset(4)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun `test gv after backwards selection`() {
|
||||||
|
configureByText("${c}Oh, hi Mark\n")
|
||||||
|
typeText(parseKeys("yw" + "$" + "vb" + "p" + "gv"))
|
||||||
|
assertSelection("Oh")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun `test gv after linewise selection`() {
|
||||||
|
configureByText("${c}Oh, hi Mark\nOh, hi Markus\n")
|
||||||
|
typeText(parseKeys("V" + "y" + "j" + "V" + "p" + "gv"))
|
||||||
|
assertSelection("Oh, hi Mark")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,8 +18,8 @@
|
|||||||
|
|
||||||
package org.jetbrains.plugins.ideavim.action.change.change
|
package org.jetbrains.plugins.ideavim.action.change.change
|
||||||
|
|
||||||
//class InsertRegisterTest : VimTestCase() {
|
// class InsertRegisterTest : VimTestCase() {
|
||||||
// todo test cursor position VIM-2732
|
// todo test cursor position VIM-2732
|
||||||
// fun `test multiline insert from expression register`() {
|
// fun `test multiline insert from expression register`() {
|
||||||
// val keys = "VjyGo<C-r>=@\"<CR>"
|
// val keys = "VjyGo<C-r>=@\"<CR>"
|
||||||
// val before = """
|
// val before = """
|
||||||
@ -43,4 +43,4 @@ package org.jetbrains.plugins.ideavim.action.change.change
|
|||||||
// """.trimIndent()
|
// """.trimIndent()
|
||||||
// doTest(keys, before, after, VimStateMachine.Mode.INSERT, VimStateMachine.SubMode.NONE)
|
// doTest(keys, before, after, VimStateMachine.Mode.INSERT, VimStateMachine.SubMode.NONE)
|
||||||
// }
|
// }
|
||||||
//}
|
// }
|
||||||
|
@ -49,6 +49,23 @@ class DeleteMotionActionTest : VimTestCase() {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun `test on line in middle`() {
|
||||||
|
typeTextInFile(
|
||||||
|
injector.parser.parseKeys("dd"),
|
||||||
|
"""
|
||||||
|
def xxx():
|
||||||
|
expression${c} one
|
||||||
|
expression two
|
||||||
|
""".trimIndent()
|
||||||
|
)
|
||||||
|
assertState(
|
||||||
|
"""
|
||||||
|
def xxx():
|
||||||
|
${c}expression two
|
||||||
|
""".trimIndent()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
fun `test delete single line`() {
|
fun `test delete single line`() {
|
||||||
typeTextInFile(
|
typeTextInFile(
|
||||||
injector.parser.parseKeys("dd"),
|
injector.parser.parseKeys("dd"),
|
||||||
|
@ -18,6 +18,13 @@
|
|||||||
|
|
||||||
package org.jetbrains.plugins.ideavim.action.copy
|
package org.jetbrains.plugins.ideavim.action.copy
|
||||||
|
|
||||||
|
import com.intellij.codeInsight.editorActions.CopyPastePostProcessor
|
||||||
|
import com.intellij.codeInsight.editorActions.CopyPastePreProcessor
|
||||||
|
import com.intellij.codeInsight.editorActions.TextBlockTransferableData
|
||||||
|
import com.intellij.openapi.editor.CaretStateTransferableData
|
||||||
|
import com.intellij.openapi.editor.Editor
|
||||||
|
import com.intellij.psi.PsiFile
|
||||||
|
import com.intellij.testFramework.ExtensionTestUtil
|
||||||
import com.maddyhome.idea.vim.VimPlugin
|
import com.maddyhome.idea.vim.VimPlugin
|
||||||
import com.maddyhome.idea.vim.api.injector
|
import com.maddyhome.idea.vim.api.injector
|
||||||
import com.maddyhome.idea.vim.command.SelectionType
|
import com.maddyhome.idea.vim.command.SelectionType
|
||||||
@ -27,8 +34,32 @@ import com.maddyhome.idea.vim.newapi.vim
|
|||||||
import org.jetbrains.plugins.ideavim.VimTestCase
|
import org.jetbrains.plugins.ideavim.VimTestCase
|
||||||
import org.jetbrains.plugins.ideavim.rangeOf
|
import org.jetbrains.plugins.ideavim.rangeOf
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
|
import java.awt.datatransfer.Transferable
|
||||||
|
|
||||||
class PutTestAfterCursorActionTest : VimTestCase() {
|
class PutTestAfterCursorActionTest : VimTestCase() {
|
||||||
|
fun `test platform handlers are called`() {
|
||||||
|
val extension = TestExtension()
|
||||||
|
ExtensionTestUtil.maskExtensions(
|
||||||
|
CopyPastePostProcessor.EP_NAME,
|
||||||
|
listOf(extension),
|
||||||
|
myFixture.testRootDisposable
|
||||||
|
)
|
||||||
|
ExtensionTestUtil.maskExtensions(
|
||||||
|
CopyPastePreProcessor.EP_NAME,
|
||||||
|
listOf(),
|
||||||
|
myFixture.testRootDisposable
|
||||||
|
)
|
||||||
|
setRegister('4', "XXX ")
|
||||||
|
doTest(
|
||||||
|
"\"4p",
|
||||||
|
"This is my$c text",
|
||||||
|
"This is my XXX$c text",
|
||||||
|
VimStateMachine.Mode.COMMAND,
|
||||||
|
VimStateMachine.SubMode.NONE
|
||||||
|
)
|
||||||
|
assertEquals(1, extension.calledExtractTransferableData)
|
||||||
|
}
|
||||||
|
|
||||||
fun `test put from number register`() {
|
fun `test put from number register`() {
|
||||||
setRegister('4', "XXX ")
|
setRegister('4', "XXX ")
|
||||||
doTest(
|
doTest(
|
||||||
@ -99,4 +130,24 @@ class PutTestAfterCursorActionTest : VimTestCase() {
|
|||||||
""".trimIndent()
|
""".trimIndent()
|
||||||
assertState(after)
|
assertState(after)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class TestExtension : CopyPastePostProcessor<TextBlockTransferableData>() {
|
||||||
|
var calledExtractTransferableData = 0
|
||||||
|
override fun collectTransferableData(
|
||||||
|
file: PsiFile,
|
||||||
|
editor: Editor,
|
||||||
|
startOffsets: IntArray?,
|
||||||
|
endOffsets: IntArray?,
|
||||||
|
): List<TextBlockTransferableData> {
|
||||||
|
return emptyList()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun extractTransferableData(content: Transferable): List<TextBlockTransferableData> {
|
||||||
|
calledExtractTransferableData += 1
|
||||||
|
return listOf(
|
||||||
|
// Just some random data
|
||||||
|
CaretStateTransferableData(intArrayOf(), intArrayOf())
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -91,7 +91,7 @@ class YankVisualActionTest : VimTestCase() {
|
|||||||
typeText(injector.parser.parseKeys("viw" + "y"))
|
typeText(injector.parser.parseKeys("viw" + "y"))
|
||||||
val editor = myFixture.editor.vim
|
val editor = myFixture.editor.vim
|
||||||
val lastRegister = injector.registerGroup.lastRegisterChar
|
val lastRegister = injector.registerGroup.lastRegisterChar
|
||||||
val registers = editor.carets().map { it.registerStorage.getRegister(lastRegister)?.rawText }
|
val registers = editor.carets().map { it.registerStorage.getRegister(it, lastRegister)?.rawText }
|
||||||
assertEquals(listOf("found", "was"), registers)
|
assertEquals(listOf("found", "was"), registers)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -165,7 +165,7 @@ class YankVisualActionTest : VimTestCase() {
|
|||||||
typeText(injector.parser.parseKeys("V" + "y"))
|
typeText(injector.parser.parseKeys("V" + "y"))
|
||||||
val editor = myFixture.editor.vim
|
val editor = myFixture.editor.vim
|
||||||
val lastRegister = injector.registerGroup.lastRegisterChar
|
val lastRegister = injector.registerGroup.lastRegisterChar
|
||||||
val registers = editor.carets().map { it.registerStorage.getRegister(lastRegister)?.rawText }
|
val registers = editor.carets().map { it.registerStorage.getRegister(it, lastRegister)?.rawText }
|
||||||
assertEquals(
|
assertEquals(
|
||||||
listOf("all rocks and lavender and tufted grass,\n", "hard by the torrent of a mountain pass.\n"),
|
listOf("all rocks and lavender and tufted grass,\n", "hard by the torrent of a mountain pass.\n"),
|
||||||
registers
|
registers
|
||||||
|
@ -121,6 +121,22 @@ n ,f <Plug>Foo
|
|||||||
assertState("quux\n")
|
assertState("quux\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun testddWithMapping() {
|
||||||
|
configureByText(
|
||||||
|
"""
|
||||||
|
Hello$c 1
|
||||||
|
Hello 2
|
||||||
|
""".trimIndent()
|
||||||
|
)
|
||||||
|
typeText(commandToKeys("nmap dc k"))
|
||||||
|
typeText(injector.parser.parseKeys("dd"))
|
||||||
|
assertState(
|
||||||
|
"""
|
||||||
|
Hello 2
|
||||||
|
""".trimIndent()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
fun testNonRecursiveMapping() {
|
fun testNonRecursiveMapping() {
|
||||||
configureByText("\n")
|
configureByText("\n")
|
||||||
typeText(commandToKeys("inoremap a b"))
|
typeText(commandToKeys("inoremap a b"))
|
||||||
|
@ -38,8 +38,8 @@ class MarksCommandTest : VimTestCase() {
|
|||||||
assertState(
|
assertState(
|
||||||
"""I found it in a legendary land
|
"""I found it in a legendary land
|
||||||
|all rocks and lavender and tufted grass,
|
|all rocks and lavender and tufted grass,
|
||||||
|${s}all rocks and lavender and tufted grass,
|
|${s}all rocks and lavender and tufted grass,$se
|
||||||
|${se}hard by the torrent of a mountain pass.
|
|hard by the torrent of a mountain pass.
|
||||||
""".trimMargin()
|
""".trimMargin()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -23,11 +23,11 @@ import com.maddyhome.idea.vim.vimscript.model.expressions.Register
|
|||||||
import org.jetbrains.plugins.ideavim.VimTestCase
|
import org.jetbrains.plugins.ideavim.VimTestCase
|
||||||
import org.jetbrains.plugins.ideavim.ex.evaluate
|
import org.jetbrains.plugins.ideavim.ex.evaluate
|
||||||
|
|
||||||
class ExpressionTest: VimTestCase() {
|
class ExpressionTest : VimTestCase() {
|
||||||
|
|
||||||
fun `test multiline register content`() {
|
fun `test multiline register content`() {
|
||||||
configureByText("${c}Oh\nHi\nMark\n")
|
configureByText("${c}Oh\nHi\nMark\n")
|
||||||
typeText(parseKeys("VGy"))
|
typeText(parseKeys("VGy"))
|
||||||
assertEquals("Oh\nHi\nMark\n", Register('"').evaluate().toString())
|
assertEquals("Oh\nHi\nMark\n", Register('"').evaluate().toString())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,8 +18,8 @@
|
|||||||
|
|
||||||
package org.jetbrains.plugins.ideavim.helper;
|
package org.jetbrains.plugins.ideavim.helper;
|
||||||
|
|
||||||
|
import com.maddyhome.idea.vim.api.VimSearchHelperBase;
|
||||||
import com.maddyhome.idea.vim.command.VimStateMachine;
|
import com.maddyhome.idea.vim.command.VimStateMachine;
|
||||||
import com.maddyhome.idea.vim.helper.SearchHelper;
|
|
||||||
import com.maddyhome.idea.vim.helper.SearchHelperKtKt;
|
import com.maddyhome.idea.vim.helper.SearchHelperKtKt;
|
||||||
import org.jetbrains.plugins.ideavim.SkipNeovimReason;
|
import org.jetbrains.plugins.ideavim.SkipNeovimReason;
|
||||||
import org.jetbrains.plugins.ideavim.TestWithoutNeovim;
|
import org.jetbrains.plugins.ideavim.TestWithoutNeovim;
|
||||||
@ -29,7 +29,7 @@ public class SearchHelperTest extends VimTestCase {
|
|||||||
@TestWithoutNeovim(reason = SkipNeovimReason.NOT_VIM_TESTING)
|
@TestWithoutNeovim(reason = SkipNeovimReason.NOT_VIM_TESTING)
|
||||||
public void testFindNextWord() {
|
public void testFindNextWord() {
|
||||||
String text = "first second";
|
String text = "first second";
|
||||||
int nextWordPosition = SearchHelper.findNextWord(text, 0, text.length(), 1, true, false);
|
int nextWordPosition = (int)VimSearchHelperBase.Companion.findNextWord(text, 0, text.length(), 1, true, false);
|
||||||
|
|
||||||
assertEquals(nextWordPosition, text.indexOf("second"));
|
assertEquals(nextWordPosition, text.indexOf("second"));
|
||||||
}
|
}
|
||||||
@ -37,7 +37,7 @@ public class SearchHelperTest extends VimTestCase {
|
|||||||
@TestWithoutNeovim(reason = SkipNeovimReason.NOT_VIM_TESTING)
|
@TestWithoutNeovim(reason = SkipNeovimReason.NOT_VIM_TESTING)
|
||||||
public void testFindSecondNextWord() {
|
public void testFindSecondNextWord() {
|
||||||
String text = "first second third";
|
String text = "first second third";
|
||||||
int nextWordPosition = SearchHelper.findNextWord(text, 0, text.length(), 2, true, false);
|
int nextWordPosition = (int)VimSearchHelperBase.Companion.findNextWord(text, 0, text.length(), 2, true, false);
|
||||||
|
|
||||||
assertEquals(nextWordPosition, text.indexOf("third"));
|
assertEquals(nextWordPosition, text.indexOf("third"));
|
||||||
}
|
}
|
||||||
@ -45,7 +45,7 @@ public class SearchHelperTest extends VimTestCase {
|
|||||||
@TestWithoutNeovim(reason = SkipNeovimReason.NOT_VIM_TESTING)
|
@TestWithoutNeovim(reason = SkipNeovimReason.NOT_VIM_TESTING)
|
||||||
public void testFindAfterLastWord() {
|
public void testFindAfterLastWord() {
|
||||||
String text = "first second";
|
String text = "first second";
|
||||||
int nextWordPosition = SearchHelper.findNextWord(text, 0, text.length(), 3, true, false);
|
int nextWordPosition = (int)VimSearchHelperBase.Companion.findNextWord(text, 0, text.length(), 3, true, false);
|
||||||
|
|
||||||
assertEquals(nextWordPosition, text.length());
|
assertEquals(nextWordPosition, text.length());
|
||||||
}
|
}
|
||||||
@ -53,7 +53,8 @@ public class SearchHelperTest extends VimTestCase {
|
|||||||
@TestWithoutNeovim(reason = SkipNeovimReason.NOT_VIM_TESTING)
|
@TestWithoutNeovim(reason = SkipNeovimReason.NOT_VIM_TESTING)
|
||||||
public void testFindPreviousWord() {
|
public void testFindPreviousWord() {
|
||||||
String text = "first second";
|
String text = "first second";
|
||||||
int previousWordPosition = SearchHelper.findNextWord(text, text.indexOf("second"), text.length(), -1, true, false);
|
int previousWordPosition =
|
||||||
|
(int)VimSearchHelperBase.Companion.findNextWord(text, text.indexOf("second"), text.length(), -1, true, false);
|
||||||
|
|
||||||
//noinspection ConstantConditions
|
//noinspection ConstantConditions
|
||||||
assertEquals(previousWordPosition, text.indexOf("first"));
|
assertEquals(previousWordPosition, text.indexOf("first"));
|
||||||
@ -62,7 +63,8 @@ public class SearchHelperTest extends VimTestCase {
|
|||||||
@TestWithoutNeovim(reason = SkipNeovimReason.NOT_VIM_TESTING)
|
@TestWithoutNeovim(reason = SkipNeovimReason.NOT_VIM_TESTING)
|
||||||
public void testFindSecondPreviousWord() {
|
public void testFindSecondPreviousWord() {
|
||||||
String text = "first second third";
|
String text = "first second third";
|
||||||
int previousWordPosition = SearchHelper.findNextWord(text, text.indexOf("third"), text.length(), -2, true, false);
|
int previousWordPosition =
|
||||||
|
(int)VimSearchHelperBase.Companion.findNextWord(text, text.indexOf("third"), text.length(), -2, true, false);
|
||||||
|
|
||||||
//noinspection ConstantConditions
|
//noinspection ConstantConditions
|
||||||
assertEquals(previousWordPosition, text.indexOf("first"));
|
assertEquals(previousWordPosition, text.indexOf("first"));
|
||||||
@ -71,7 +73,8 @@ public class SearchHelperTest extends VimTestCase {
|
|||||||
@TestWithoutNeovim(reason = SkipNeovimReason.NOT_VIM_TESTING)
|
@TestWithoutNeovim(reason = SkipNeovimReason.NOT_VIM_TESTING)
|
||||||
public void testFindBeforeFirstWord() {
|
public void testFindBeforeFirstWord() {
|
||||||
String text = "first second";
|
String text = "first second";
|
||||||
int previousWordPosition = SearchHelper.findNextWord(text, text.indexOf("second"), text.length(), -3, true, false);
|
int previousWordPosition =
|
||||||
|
(int)VimSearchHelperBase.Companion.findNextWord(text, text.indexOf("second"), text.length(), -3, true, false);
|
||||||
|
|
||||||
//noinspection ConstantConditions
|
//noinspection ConstantConditions
|
||||||
assertEquals(previousWordPosition, text.indexOf("first"));
|
assertEquals(previousWordPosition, text.indexOf("first"));
|
||||||
@ -80,7 +83,8 @@ public class SearchHelperTest extends VimTestCase {
|
|||||||
@TestWithoutNeovim(reason = SkipNeovimReason.NOT_VIM_TESTING)
|
@TestWithoutNeovim(reason = SkipNeovimReason.NOT_VIM_TESTING)
|
||||||
public void testFindPreviousWordWhenCursorOutOfBound() {
|
public void testFindPreviousWordWhenCursorOutOfBound() {
|
||||||
String text = "first second";
|
String text = "first second";
|
||||||
int previousWordPosition = SearchHelper.findNextWord(text, text.length(), text.length(), -1, true, false);
|
int previousWordPosition =
|
||||||
|
(int)VimSearchHelperBase.Companion.findNextWord(text, text.length(), text.length(), -1, true, false);
|
||||||
|
|
||||||
assertEquals(previousWordPosition, text.indexOf("second"));
|
assertEquals(previousWordPosition, text.indexOf("second"));
|
||||||
}
|
}
|
||||||
|
@ -42,19 +42,25 @@ sealed class PutTextBaseAction(
|
|||||||
operatorArguments: OperatorArguments
|
operatorArguments: OperatorArguments
|
||||||
): Boolean {
|
): Boolean {
|
||||||
val count = operatorArguments.count1
|
val count = operatorArguments.count1
|
||||||
val caretToPutData = editor.sortedCarets().associateWith { getPutDataForCaret(it, count) }
|
val sortedCarets = editor.sortedCarets()
|
||||||
var result = true
|
return if (sortedCarets.size > 1) {
|
||||||
injector.application.runWriteAction {
|
val caretToPutData = sortedCarets.associateWith { getPutDataForCaret(it, count) }
|
||||||
caretToPutData.forEach {
|
var result = true
|
||||||
result = injector.put.putTextForCaret(editor, it.key, context, it.value) && result
|
injector.application.runWriteAction {
|
||||||
|
caretToPutData.forEach {
|
||||||
|
result = injector.put.putTextForCaret(editor, it.key, context, it.value) && result
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
result
|
||||||
|
} else {
|
||||||
|
val putData = getPutDataForCaret(sortedCarets.single(), count)
|
||||||
|
injector.put.putText(editor, context, putData, operatorArguments)
|
||||||
}
|
}
|
||||||
return result
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getPutDataForCaret(caret: VimCaret, count: Int): PutData {
|
private fun getPutDataForCaret(caret: VimCaret, count: Int): PutData {
|
||||||
val lastRegisterChar = injector.registerGroup.lastRegisterChar
|
val lastRegisterChar = injector.registerGroup.lastRegisterChar
|
||||||
val register = caret.registerStorage.getRegister(lastRegisterChar)
|
val register = caret.registerStorage.getRegister(caret, lastRegisterChar)
|
||||||
val textData = register?.let {
|
val textData = register?.let {
|
||||||
TextData(
|
TextData(
|
||||||
register.text ?: injector.parser.toPrintableString(register.keys),
|
register.text ?: injector.parser.toPrintableString(register.keys),
|
||||||
|
@ -66,7 +66,7 @@ sealed class PutVisualTextBaseAction(
|
|||||||
|
|
||||||
private fun getPutDataForCaret(caret: VimCaret, selection: VimSelection?, count: Int): PutData {
|
private fun getPutDataForCaret(caret: VimCaret, selection: VimSelection?, count: Int): PutData {
|
||||||
val lastRegisterChar = injector.registerGroup.lastRegisterChar
|
val lastRegisterChar = injector.registerGroup.lastRegisterChar
|
||||||
val register = caret.registerStorage.getRegister(lastRegisterChar)
|
val register = caret.registerStorage.getRegister(caret, lastRegisterChar)
|
||||||
val textData = register?.let {
|
val textData = register?.let {
|
||||||
PutData.TextData(
|
PutData.TextData(
|
||||||
register.text ?: injector.parser.toPrintableString(register.keys),
|
register.text ?: injector.parser.toPrintableString(register.keys),
|
||||||
|
@ -22,6 +22,7 @@ interface VimCaret {
|
|||||||
val vimLeadSelectionOffset: Int
|
val vimLeadSelectionOffset: Int
|
||||||
var vimLastVisualOperatorRange: VisualChange?
|
var vimLastVisualOperatorRange: VisualChange?
|
||||||
val vimLine: Int
|
val vimLine: Int
|
||||||
|
val isPrimary: Boolean
|
||||||
fun moveToOffset(offset: Int)
|
fun moveToOffset(offset: Int)
|
||||||
fun moveToOffsetNative(offset: Int)
|
fun moveToOffsetNative(offset: Int)
|
||||||
fun moveToLogicalPosition(logicalPosition: VimLogicalPosition)
|
fun moveToLogicalPosition(logicalPosition: VimLogicalPosition)
|
||||||
@ -43,17 +44,18 @@ interface VimCaret {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface CaretRegisterStorage {
|
interface CaretRegisterStorage {
|
||||||
|
// todo methods shouldn't have caret in signature
|
||||||
/**
|
/**
|
||||||
* Stores text to caret's recordable (named/numbered/unnamed) register
|
* Stores text to caret's recordable (named/numbered/unnamed) register
|
||||||
*/
|
*/
|
||||||
fun storeText(editor: VimEditor, range: TextRange, type: SelectionType, isDelete: Boolean): Boolean
|
fun storeText(caret: VimCaret, editor: VimEditor, range: TextRange, type: SelectionType, isDelete: Boolean): Boolean
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets text from caret's recordable register
|
* Gets text from caret's recordable register
|
||||||
* If the register is not recordable - global text state will be returned
|
* If the register is not recordable - global text state will be returned
|
||||||
*/
|
*/
|
||||||
fun getRegister(r: Char): Register?
|
fun getRegister(caret: VimCaret, r: Char): Register?
|
||||||
|
|
||||||
fun setKeys(register: Char, keys: List<KeyStroke>)
|
fun setKeys(caret: VimCaret, register: Char, keys: List<KeyStroke>)
|
||||||
fun saveRegister(r: Char, register: Register)
|
fun saveRegister(caret: VimCaret, r: Char, register: Register)
|
||||||
}
|
}
|
||||||
|
@ -9,15 +9,15 @@ import javax.swing.KeyStroke
|
|||||||
|
|
||||||
abstract class VimCaretBase : VimCaret
|
abstract class VimCaretBase : VimCaret
|
||||||
|
|
||||||
open class CaretRegisterStorageBase(private val isCaretPrimary: Boolean) : CaretRegisterStorage, VimRegisterGroupBase() {
|
open class CaretRegisterStorageBase : CaretRegisterStorage, VimRegisterGroupBase() {
|
||||||
override var lastRegisterChar: Char
|
override var lastRegisterChar: Char
|
||||||
get() {
|
get() {
|
||||||
return injector.registerGroup.lastRegisterChar
|
return injector.registerGroup.lastRegisterChar
|
||||||
}
|
}
|
||||||
set(_) {}
|
set(_) {}
|
||||||
|
|
||||||
override fun storeText(editor: VimEditor, range: TextRange, type: SelectionType, isDelete: Boolean): Boolean {
|
override fun storeText(caret: VimCaret, editor: VimEditor, range: TextRange, type: SelectionType, isDelete: Boolean): Boolean {
|
||||||
if (isCaretPrimary) {
|
if (caret.isPrimary) {
|
||||||
return injector.registerGroup.storeText(editor, range, type, isDelete)
|
return injector.registerGroup.storeText(editor, range, type, isDelete)
|
||||||
}
|
}
|
||||||
val register = lastRegisterChar
|
val register = lastRegisterChar
|
||||||
@ -27,15 +27,15 @@ open class CaretRegisterStorageBase(private val isCaretPrimary: Boolean) : Caret
|
|||||||
return super.storeText(editor, range, type, isDelete)
|
return super.storeText(editor, range, type, isDelete)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getRegister(r: Char): Register? {
|
override fun getRegister(caret: VimCaret, r: Char): Register? {
|
||||||
if (isCaretPrimary || !RegisterConstants.RECORDABLE_REGISTERS.contains(r)) {
|
if (caret.isPrimary || !RegisterConstants.RECORDABLE_REGISTERS.contains(r)) {
|
||||||
return injector.registerGroup.getRegister(r)
|
return injector.registerGroup.getRegister(r)
|
||||||
}
|
}
|
||||||
return super.getRegister(r) ?: injector.registerGroup.getRegister(r)
|
return super.getRegister(r) ?: injector.registerGroup.getRegister(r)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setKeys(register: Char, keys: List<KeyStroke>) {
|
override fun setKeys(caret: VimCaret, register: Char, keys: List<KeyStroke>) {
|
||||||
if (isCaretPrimary) {
|
if (caret.isPrimary) {
|
||||||
injector.registerGroup.setKeys(register, keys)
|
injector.registerGroup.setKeys(register, keys)
|
||||||
}
|
}
|
||||||
if (!RegisterConstants.RECORDABLE_REGISTERS.contains(register)) {
|
if (!RegisterConstants.RECORDABLE_REGISTERS.contains(register)) {
|
||||||
@ -44,8 +44,8 @@ open class CaretRegisterStorageBase(private val isCaretPrimary: Boolean) : Caret
|
|||||||
return super.setKeys(register, keys)
|
return super.setKeys(register, keys)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun saveRegister(r: Char, register: Register) {
|
override fun saveRegister(caret: VimCaret, r: Char, register: Register) {
|
||||||
if (isCaretPrimary) {
|
if (caret.isPrimary) {
|
||||||
injector.registerGroup.saveRegister(r, register)
|
injector.registerGroup.saveRegister(r, register)
|
||||||
}
|
}
|
||||||
if (!RegisterConstants.RECORDABLE_REGISTERS.contains(r)) {
|
if (!RegisterConstants.RECORDABLE_REGISTERS.contains(r)) {
|
||||||
|
@ -158,7 +158,7 @@ abstract class VimChangeGroupBase : VimChangeGroup {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (type == null ||
|
if (type == null ||
|
||||||
operatorArguments.mode.inInsertMode || caret.registerStorage.storeText(editor, updatedRange, type, true) ||
|
operatorArguments.mode.inInsertMode || caret.registerStorage.storeText(caret, editor, updatedRange, type, true) ||
|
||||||
caret != editor.primaryCaret() // sticky tape for VIM-2703 todo remove in the next release
|
caret != editor.primaryCaret() // sticky tape for VIM-2703 todo remove in the next release
|
||||||
) {
|
) {
|
||||||
val startOffsets = updatedRange.startOffsets
|
val startOffsets = updatedRange.startOffsets
|
||||||
|
@ -24,6 +24,7 @@ import com.maddyhome.idea.vim.key.KeyMapping
|
|||||||
import com.maddyhome.idea.vim.key.KeyMappingLayer
|
import com.maddyhome.idea.vim.key.KeyMappingLayer
|
||||||
import com.maddyhome.idea.vim.key.MappingInfo
|
import com.maddyhome.idea.vim.key.MappingInfo
|
||||||
import com.maddyhome.idea.vim.key.MappingOwner
|
import com.maddyhome.idea.vim.key.MappingOwner
|
||||||
|
import com.maddyhome.idea.vim.key.OperatorFunction
|
||||||
import com.maddyhome.idea.vim.key.ShortcutOwnerInfo
|
import com.maddyhome.idea.vim.key.ShortcutOwnerInfo
|
||||||
import com.maddyhome.idea.vim.vimscript.model.expressions.Expression
|
import com.maddyhome.idea.vim.vimscript.model.expressions.Expression
|
||||||
import javax.swing.KeyStroke
|
import javax.swing.KeyStroke
|
||||||
@ -73,4 +74,5 @@ interface VimKeyGroup {
|
|||||||
|
|
||||||
val shortcutConflicts: MutableMap<KeyStroke, ShortcutOwnerInfo>
|
val shortcutConflicts: MutableMap<KeyStroke, ShortcutOwnerInfo>
|
||||||
val savedShortcutConflicts: MutableMap<KeyStroke, ShortcutOwnerInfo>
|
val savedShortcutConflicts: MutableMap<KeyStroke, ShortcutOwnerInfo>
|
||||||
|
var operatorFunction: OperatorFunction?
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ import com.maddyhome.idea.vim.key.KeyMapping
|
|||||||
import com.maddyhome.idea.vim.key.KeyMappingLayer
|
import com.maddyhome.idea.vim.key.KeyMappingLayer
|
||||||
import com.maddyhome.idea.vim.key.MappingInfo
|
import com.maddyhome.idea.vim.key.MappingInfo
|
||||||
import com.maddyhome.idea.vim.key.MappingOwner
|
import com.maddyhome.idea.vim.key.MappingOwner
|
||||||
|
import com.maddyhome.idea.vim.key.OperatorFunction
|
||||||
import com.maddyhome.idea.vim.key.RequiredShortcut
|
import com.maddyhome.idea.vim.key.RequiredShortcut
|
||||||
import com.maddyhome.idea.vim.key.RootNode
|
import com.maddyhome.idea.vim.key.RootNode
|
||||||
import com.maddyhome.idea.vim.key.ShortcutOwnerInfo
|
import com.maddyhome.idea.vim.key.ShortcutOwnerInfo
|
||||||
@ -24,6 +25,8 @@ abstract class VimKeyGroupBase : VimKeyGroup {
|
|||||||
val keyRoots: MutableMap<MappingMode, CommandPartNode<VimActionsInitiator>> = EnumMap(MappingMode::class.java)
|
val keyRoots: MutableMap<MappingMode, CommandPartNode<VimActionsInitiator>> = EnumMap(MappingMode::class.java)
|
||||||
val keyMappings: MutableMap<MappingMode, KeyMapping> = EnumMap(MappingMode::class.java)
|
val keyMappings: MutableMap<MappingMode, KeyMapping> = EnumMap(MappingMode::class.java)
|
||||||
|
|
||||||
|
override var operatorFunction: OperatorFunction? = null
|
||||||
|
|
||||||
override fun removeKeyMapping(modes: Set<MappingMode>, keys: List<KeyStroke>) {
|
override fun removeKeyMapping(modes: Set<MappingMode>, keys: List<KeyStroke>) {
|
||||||
modes.map { getKeyMapping(it) }.forEach { it.delete(keys) }
|
modes.map { getKeyMapping(it) }.forEach { it.delete(keys) }
|
||||||
}
|
}
|
||||||
|
@ -83,7 +83,7 @@ interface VimSearchHelper {
|
|||||||
spaceWords: Boolean,
|
spaceWords: Boolean,
|
||||||
): Int
|
): Int
|
||||||
|
|
||||||
fun findNextWord(editor: VimEditor, searchFrom: Int, count: Int, bigWord: Boolean): Int
|
fun findNextWord(editor: VimEditor, searchFrom: Int, count: Int, bigWord: Boolean): Long
|
||||||
|
|
||||||
fun findPattern(
|
fun findPattern(
|
||||||
editor: VimEditor,
|
editor: VimEditor,
|
||||||
|
@ -0,0 +1,117 @@
|
|||||||
|
package com.maddyhome.idea.vim.api
|
||||||
|
|
||||||
|
import com.maddyhome.idea.vim.helper.CharacterHelper
|
||||||
|
import com.maddyhome.idea.vim.helper.CharacterHelper.charType
|
||||||
|
import kotlin.math.abs
|
||||||
|
import kotlin.math.min
|
||||||
|
|
||||||
|
abstract class VimSearchHelperBase : VimSearchHelper {
|
||||||
|
override fun findNextWord(editor: VimEditor, searchFrom: Int, count: Int, bigWord: Boolean): Long {
|
||||||
|
return findNextWord(editor.charsSequence(), searchFrom.toLong(), editor.fileSize(), count, bigWord, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun findNextWord(
|
||||||
|
chars: CharSequence,
|
||||||
|
pos: Long,
|
||||||
|
size: Long,
|
||||||
|
count: Int,
|
||||||
|
bigWord: Boolean,
|
||||||
|
spaceWords: Boolean,
|
||||||
|
): Long {
|
||||||
|
var _count = count
|
||||||
|
val step = if (_count >= 0) 1 else -1
|
||||||
|
_count = abs(_count)
|
||||||
|
var res = pos
|
||||||
|
for (i in 0 until _count) {
|
||||||
|
res = findNextWordOne(chars, res, size, step, bigWord, spaceWords)
|
||||||
|
if (res == pos || res == 0L || res == size - 1) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: 18.08.2022 Make private
|
||||||
|
fun findNextWordOne(
|
||||||
|
chars: CharSequence,
|
||||||
|
pos: Long,
|
||||||
|
size: Long,
|
||||||
|
step: Int,
|
||||||
|
bigWord: Boolean,
|
||||||
|
spaceWords: Boolean,
|
||||||
|
): Long {
|
||||||
|
var found = false
|
||||||
|
var _pos = if (pos < size) pos else min(size, (chars.length - 1).toLong())
|
||||||
|
// For back searches, skip any current whitespace so we start at the end of a word
|
||||||
|
if (step < 0 && _pos > 0) {
|
||||||
|
if (charType(chars[_pos - 1], bigWord) === CharacterHelper.CharacterType.WHITESPACE && !spaceWords) {
|
||||||
|
_pos = skipSpace(chars, _pos - 1, step, size) + 1
|
||||||
|
}
|
||||||
|
if (_pos > 0 && charType(chars[_pos], bigWord) !== charType(chars[_pos - 1], bigWord)) {
|
||||||
|
_pos += step
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var res = _pos
|
||||||
|
if (_pos < 0 || _pos >= size) {
|
||||||
|
return _pos
|
||||||
|
}
|
||||||
|
var type = charType(chars[_pos], bigWord)
|
||||||
|
if (type === CharacterHelper.CharacterType.WHITESPACE && step < 0 && _pos > 0 && !spaceWords) {
|
||||||
|
type = charType(chars[_pos - 1], bigWord)
|
||||||
|
}
|
||||||
|
_pos += step
|
||||||
|
while (_pos in 0 until size && !found) {
|
||||||
|
val newType = charType(chars[_pos], bigWord)
|
||||||
|
if (newType !== type) {
|
||||||
|
if (newType === CharacterHelper.CharacterType.WHITESPACE && step >= 0 && !spaceWords) {
|
||||||
|
_pos = skipSpace(chars, _pos, step, size)
|
||||||
|
res = _pos
|
||||||
|
} else if (step < 0) {
|
||||||
|
res = _pos + 1
|
||||||
|
} else {
|
||||||
|
res = _pos
|
||||||
|
}
|
||||||
|
type = charType(chars[res], bigWord)
|
||||||
|
found = true
|
||||||
|
}
|
||||||
|
_pos += step
|
||||||
|
}
|
||||||
|
if (found) {
|
||||||
|
if (res < 0) { // (pos <= 0)
|
||||||
|
res = 0
|
||||||
|
} else if (res >= size) { // (pos >= size)
|
||||||
|
res = size - 1
|
||||||
|
}
|
||||||
|
} else if (_pos <= 0) {
|
||||||
|
res = 0
|
||||||
|
} else if (_pos >= size) {
|
||||||
|
res = size
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Skip whitespace starting with the supplied position.
|
||||||
|
*
|
||||||
|
* An empty line is considered a whitespace break.
|
||||||
|
*/
|
||||||
|
// TODO: 18.08.2022 Make private
|
||||||
|
fun skipSpace(chars: CharSequence, offset: Long, step: Int, size: Long): Long {
|
||||||
|
var _offset = offset
|
||||||
|
var prev = 0.toChar()
|
||||||
|
while (_offset in 0 until size) {
|
||||||
|
val c = chars[_offset.toInt()]
|
||||||
|
if (c == '\n' && c == prev) break
|
||||||
|
if (charType(c, false) !== CharacterHelper.CharacterType.WHITESPACE) break
|
||||||
|
prev = c
|
||||||
|
_offset += step
|
||||||
|
}
|
||||||
|
return if (_offset < size) _offset else size - 1
|
||||||
|
}
|
||||||
|
|
||||||
|
operator fun CharSequence.get(index: Long): Char {
|
||||||
|
return this[index.toInt()]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -95,7 +95,7 @@ abstract class VimMachineBase : VimMachine {
|
|||||||
val operatedText = editor.deleteDryRun(range) ?: return null
|
val operatedText = editor.deleteDryRun(range) ?: return null
|
||||||
|
|
||||||
val normalizedRange = operatedText.toNormalizedTextRange(editor)
|
val normalizedRange = operatedText.toNormalizedTextRange(editor)
|
||||||
caret.registerStorage.storeText(editor, normalizedRange, operatedText.toType(), true)
|
caret.registerStorage.storeText(caret, editor, normalizedRange, operatedText.toType(), true)
|
||||||
(editor as MutableVimEditor).delete(range)
|
(editor as MutableVimEditor).delete(range)
|
||||||
|
|
||||||
val start = normalizedRange.startOffset
|
val start = normalizedRange.startOffset
|
||||||
|
@ -12,4 +12,5 @@ fun Int.toMotion(): Motion.AbsoluteOffset {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun Int.toMotionOrError(): Motion = if (this < 0) Motion.Error else Motion.AbsoluteOffset(this)
|
fun Int.toMotionOrError(): Motion = if (this < 0) Motion.Error else Motion.AbsoluteOffset(this)
|
||||||
|
fun Long.toMotionOrError(): Motion = if (this < 0) Motion.Error else Motion.AbsoluteOffset(this.toInt())
|
||||||
fun Int.toMotionOrNoMotion(): Motion = if (this < 0) Motion.NoMotion else Motion.AbsoluteOffset(this)
|
fun Int.toMotionOrNoMotion(): Motion = if (this < 0) Motion.NoMotion else Motion.AbsoluteOffset(this)
|
||||||
|
@ -132,7 +132,7 @@ sealed class VisualOperatorActionHandler : EditorActionHandlerBase(false) {
|
|||||||
logger.debug { "Count of selection segments: ${selections.size}" }
|
logger.debug { "Count of selection segments: ${selections.size}" }
|
||||||
logger.debug { selections.values.joinToString("\n") { vimSelection -> "Caret: $vimSelection" } }
|
logger.debug { selections.values.joinToString("\n") { vimSelection -> "Caret: $vimSelection" } }
|
||||||
|
|
||||||
val commandWrapper = VisualStartFinishWrapper(editor, cmd)
|
val commandWrapper = VisualStartFinishWrapper(editor, cmd, this)
|
||||||
commandWrapper.start()
|
commandWrapper.start()
|
||||||
|
|
||||||
val res = arrayOf(true)
|
val res = arrayOf(true)
|
||||||
@ -230,7 +230,11 @@ sealed class VisualOperatorActionHandler : EditorActionHandlerBase(false) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class VisualStartFinishWrapper(private val editor: VimEditor, private val cmd: Command) {
|
private class VisualStartFinishWrapper(
|
||||||
|
private val editor: VimEditor,
|
||||||
|
private val cmd: Command,
|
||||||
|
private val visualOperatorActionHandler: VisualOperatorActionHandler
|
||||||
|
) {
|
||||||
private val visualChanges = mutableMapOf<VimCaret, VisualChange?>()
|
private val visualChanges = mutableMapOf<VimCaret, VisualChange?>()
|
||||||
|
|
||||||
fun start() {
|
fun start() {
|
||||||
@ -256,9 +260,13 @@ sealed class VisualOperatorActionHandler : EditorActionHandlerBase(false) {
|
|||||||
fun finish(res: Boolean) {
|
fun finish(res: Boolean) {
|
||||||
logger.debug("Finish visual command. Result: $res")
|
logger.debug("Finish visual command. Result: $res")
|
||||||
|
|
||||||
if (CommandFlags.FLAG_MULTIKEY_UNDO !in cmd.flags && CommandFlags.FLAG_EXPECT_MORE !in cmd.flags) {
|
if (visualOperatorActionHandler.id != "VimVisualOperatorAction" ||
|
||||||
logger.debug("Not multikey undo - exit visual")
|
injector.keyGroup.operatorFunction?.postProcessSelection() != false
|
||||||
editor.exitVisualModeNative()
|
) {
|
||||||
|
if (CommandFlags.FLAG_MULTIKEY_UNDO !in cmd.flags && CommandFlags.FLAG_EXPECT_MORE !in cmd.flags) {
|
||||||
|
logger.debug("Not multikey undo - exit visual")
|
||||||
|
editor.exitVisualModeNative()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (res) {
|
if (res) {
|
||||||
|
@ -15,22 +15,23 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
package com.maddyhome.idea.vim.key
|
||||||
|
|
||||||
package com.maddyhome.idea.vim.key;
|
import com.maddyhome.idea.vim.api.ExecutionContext
|
||||||
|
import com.maddyhome.idea.vim.api.VimEditor
|
||||||
import com.intellij.openapi.actionSystem.DataContext;
|
import com.maddyhome.idea.vim.command.SelectionType
|
||||||
import com.intellij.openapi.editor.Editor;
|
|
||||||
import com.maddyhome.idea.vim.command.SelectionType;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author vlan
|
* @author vlan
|
||||||
*/
|
*/
|
||||||
public interface OperatorFunction {
|
interface OperatorFunction {
|
||||||
/**
|
/**
|
||||||
* The value of 'operatorfunc' to be used as the operator function in 'g@'.
|
* The value of 'operatorfunc' to be used as the operator function in 'g@'.
|
||||||
* <p>
|
*
|
||||||
|
*
|
||||||
* Make sure to synchronize your function properly using read/write actions.
|
* Make sure to synchronize your function properly using read/write actions.
|
||||||
*/
|
*/
|
||||||
boolean apply(@NotNull Editor editor, @NotNull DataContext context, @NotNull SelectionType selectionType);
|
fun apply(editor: VimEditor, context: ExecutionContext, selectionType: SelectionType): Boolean
|
||||||
|
|
||||||
|
fun postProcessSelection(): Boolean = true
|
||||||
}
|
}
|
@ -21,8 +21,8 @@ interface VimPut {
|
|||||||
editor: VimEditor,
|
editor: VimEditor,
|
||||||
context: ExecutionContext,
|
context: ExecutionContext,
|
||||||
data: PutData,
|
data: PutData,
|
||||||
updateVisualMarks: Boolean = false,
|
|
||||||
operatorArguments: OperatorArguments,
|
operatorArguments: OperatorArguments,
|
||||||
|
updateVisualMarks: Boolean = false,
|
||||||
): Boolean
|
): Boolean
|
||||||
|
|
||||||
fun putTextForCaret(editor: VimEditor, caret: VimCaret, context: ExecutionContext, data: PutData, updateVisualMarks: Boolean = false): Boolean
|
fun putTextForCaret(editor: VimEditor, caret: VimCaret, context: ExecutionContext, data: PutData, updateVisualMarks: Boolean = false): Boolean
|
||||||
|
@ -25,8 +25,8 @@ abstract class VimPutBase : VimPut {
|
|||||||
editor: VimEditor,
|
editor: VimEditor,
|
||||||
context: ExecutionContext,
|
context: ExecutionContext,
|
||||||
data: PutData,
|
data: PutData,
|
||||||
updateVisualMarks: Boolean,
|
|
||||||
operatorArguments: OperatorArguments,
|
operatorArguments: OperatorArguments,
|
||||||
|
updateVisualMarks: Boolean,
|
||||||
): Boolean {
|
): Boolean {
|
||||||
val additionalData = collectPreModificationData(editor, data)
|
val additionalData = collectPreModificationData(editor, data)
|
||||||
deleteSelectedText(editor, data, operatorArguments)
|
deleteSelectedText(editor, data, operatorArguments)
|
||||||
@ -67,15 +67,18 @@ abstract class VimPutBase : VimPut {
|
|||||||
val caretsAndSelections = data.visualSelection?.caretsAndSelections ?: return
|
val caretsAndSelections = data.visualSelection?.caretsAndSelections ?: return
|
||||||
val selection = caretsAndSelections[currentCaret] ?: caretsAndSelections.firstOrNull()?.value ?: return
|
val selection = caretsAndSelections[currentCaret] ?: caretsAndSelections.firstOrNull()?.value ?: return
|
||||||
|
|
||||||
var fistIndex = selection.vimStart
|
val leftIndex = min(selection.vimStart, selection.vimEnd)
|
||||||
val lastIndex = fistIndex + textLength - 1
|
val rightIndex = leftIndex + textLength - 1
|
||||||
|
|
||||||
if (wasTextInsertedLineWise(text)) {
|
val rangeForMarks = if (wasTextInsertedLineWise(text)) {
|
||||||
// here we skip the \n char before the inserted text
|
// here we skip the \n char after the inserted text
|
||||||
fistIndex += 1
|
TextRange(leftIndex, rightIndex - 1)
|
||||||
|
} else {
|
||||||
|
TextRange(leftIndex, rightIndex)
|
||||||
}
|
}
|
||||||
|
|
||||||
injector.markGroup.setVisualSelectionMarks(editor, TextRange(fistIndex, lastIndex))
|
editor.vimLastSelectionType = SelectionType.CHARACTER_WISE
|
||||||
|
injector.markGroup.setVisualSelectionMarks(editor, rangeForMarks)
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun deleteSelectedText(editor: VimEditor, data: PutData, operatorArguments: OperatorArguments) {
|
protected fun deleteSelectedText(editor: VimEditor, data: PutData, operatorArguments: OperatorArguments) {
|
||||||
|
Loading…
Reference in New Issue
Block a user