1
0
mirror of https://github.com/chylex/IntelliJ-IdeaVim.git synced 2025-01-30 20:45:59 +01:00

Compare commits

..

22 Commits

Author SHA1 Message Date
822dad52f3
Set plugin version to chylex-41 2024-09-05 07:40:10 +02:00
bf12c98880
Exit insert mode after refactoring 2024-09-05 07:40:10 +02:00
c02bd15e4f
Add action to run last macro in all opened files 2024-09-05 07:27:53 +02:00
5957d5d681
Stop macro execution after a failed search 2024-09-05 07:27:53 +02:00
9445afb555
Revert per-caret registers 2024-09-05 07:27:53 +02:00
6e115bdf64
Revert "Factor disposable objects on editor opening"
This reverts commit 1fa78935
2024-09-05 07:27:53 +02:00
6305c412b5
Fix(VIM-3364): Exception with mapped Generate action 2024-09-05 07:27:53 +02:00
be2eabe3b9
Apply scrolloff after executing native IDEA actions 2024-09-05 07:27:53 +02:00
de13e4348a
Stay on same line after reindenting 2024-09-05 07:12:09 +02:00
1c154fdc8a
Update search register when using f/t 2024-09-05 07:12:09 +02:00
9b75931736
Automatically add unambiguous imports after running a macro 2024-09-05 07:12:09 +02:00
3fe97aa767
Fix(VIM-3179): Respect virtual space below editor (imperfectly) 2024-09-05 07:12:09 +02:00
8eb2dbebcf
Fix(VIM-3178): Workaround to support "Jump to Source" action mapping 2024-09-05 07:12:09 +02:00
cb781f9a0d
Add support for count for visual and line motion surround 2024-09-05 07:12:09 +02:00
6693755823
Fix vim-surround not working with multiple cursors
Fixes multiple cursors with vim-surround commands `cs, ds, S` (but not `ys`).
2024-09-05 07:12:09 +02:00
9a9bd335d3
Fix(VIM-696) Restore visual mode after undo/redo, and disable incompatible actions 2024-09-05 07:12:09 +02:00
91e22482c6
Respect count with <Action> mappings 2024-09-05 07:08:52 +02:00
06dc2ed75c
Change matchit plugin to use HTML patterns in unrecognized files 2024-09-05 07:02:47 +02:00
12da1ac969
Reset insert mode when switching active editor 2024-09-05 07:02:47 +02:00
5747ac0ebf
Disable switching to insert mode for some editors 2024-09-05 07:02:44 +02:00
8a47bc1840
Remove update checker 2024-09-05 07:02:36 +02:00
da4deaf698
Set custom plugin version 2024-09-05 07:02:36 +02:00
329 changed files with 3789 additions and 8145 deletions

View File

@ -7,9 +7,6 @@ on:
workflow_dispatch:
push:
branches: [ master ]
permissions:
contents: write
jobs:
build:

View File

@ -20,11 +20,6 @@ on:
schedule:
- cron: '44 12 * * 4'
permissions:
actions: read
contents: read
security-events: write
jobs:
analyze:
name: Analyze

View File

@ -10,9 +10,6 @@ on:
push:
branches: [ master ]
permissions:
contents: write
jobs:
build:
@ -37,17 +34,6 @@ jobs:
id: update_authors
run: cp -a origin/doc/. docs
# The Wiki for github should have no `.md` in references
# Otherwise, such links will lead to the raw text.
# However, the `.md` should exist to have a navigation in GitHub code.
- name: Replace `.md)` with `)`
run: |
# Define the directory you want to process
DIRECTORY="docs"
# Find all files in the directory and perform the replacement
find $DIRECTORY -type f -exec sed -i 's/\.md)/)/g' {} +
- name: Commit changes
uses: stefanzweifel/git-auto-commit-action@v4
with:

View File

@ -5,12 +5,13 @@ object Constants {
const val EAP_CHANNEL = "eap"
const val DEV_CHANNEL = "Dev"
const val NVIM_TESTS = "2024.2.1"
const val PROPERTY_TESTS = "2024.2.1"
const val LONG_RUNNING_TESTS = "2024.2.1"
const val QODANA_TESTS = "2024.2.1"
const val RELEASE = "2024.2.1"
const val GITHUB_TESTS = "2024.1.1"
const val NVIM_TESTS = "2024.1.1"
const val PROPERTY_TESTS = "2024.1.1"
const val LONG_RUNNING_TESTS = "2024.1.1"
const val QODANA_TESTS = "2024.1.1"
const val RELEASE = "2024.1.1"
const val RELEASE_DEV = "2024.2.1"
const val RELEASE_EAP = "2024.2.1"
const val RELEASE_DEV = "2024.1.1"
const val RELEASE_EAP = "2024.1.1"
}

View File

@ -8,6 +8,7 @@ import _Self.buildTypes.PropertyBased
import _Self.buildTypes.Qodana
import _Self.buildTypes.TestingBuildType
import _Self.subprojects.GitHub
import _Self.subprojects.OldTests
import _Self.subprojects.Releases
import _Self.vcsRoots.GitHubPullRequest
import _Self.vcsRoots.ReleasesVcsRoot
@ -17,7 +18,7 @@ import jetbrains.buildServer.configs.kotlin.v2019_2.Project
object Project : Project({
description = "Vim engine for JetBrains IDEs"
subProjects(Releases, GitHub)
subProjects(Releases, OldTests, GitHub)
// VCS roots
vcsRoot(GitHubPullRequest)
@ -25,7 +26,8 @@ object Project : Project({
// Active tests
buildType(TestingBuildType("Latest EAP", "<default>", version = "LATEST-EAP-SNAPSHOT"))
buildType(TestingBuildType("2024.2.1", "<default>"))
buildType(TestingBuildType("2024.1.1", "<default>"))
buildType(TestingBuildType("2024.2", "<default>"))
buildType(TestingBuildType("Latest EAP With Xorg", "<default>", version = "LATEST-EAP-SNAPSHOT"))
buildType(PropertyBased)
@ -42,9 +44,6 @@ object Project : Project({
abstract class IdeaVimBuildType(init: BuildType.() -> Unit) : BuildType({
artifactRules = """
+:build/reports => build/reports
+:tests/java-tests/build/reports => java-tests/build/reports
+:tests/long-running-tests/build/reports => long-running-tests/build/reports
+:tests/property-tests/build/reports => property-tests/build/reports
+:/mnt/agent/temp/buildTmp/ => /mnt/agent/temp/buildTmp/
""".trimIndent()
@ -54,7 +53,7 @@ abstract class IdeaVimBuildType(init: BuildType.() -> Unit) : BuildType({
// These requirements define Linux-Medium configuration.
// Unfortunately, requirement by name (teamcity.agent.name) doesn't work
// IDK the reason for it, but on our agents this property is empty
equals("teamcity.agent.hardware.cpuCount", "16")
equals("teamcity.agent.hardware.cpuCount", "4")
equals("teamcity.agent.os.family", "Linux")
}

View File

@ -40,9 +40,6 @@ object Compatibility : IdeaVimBuildType({
# java -jar verifier1/verifier-cli-dev-all-1.jar check-plugin '${'$'}com.github.copilot' [latest-IU] -team-city
java -jar verifier1/verifier-cli-dev-all-1.jar check-plugin '${'$'}com.github.dankinsoid.multicursor' [latest-IU] -team-city
java -jar verifier1/verifier-cli-dev-all-1.jar check-plugin '${'$'}com.joshestein.ideavim-quickscope' [latest-IU] -team-city
java -jar verifier1/verifier-cli-dev-all-1.jar check-plugin '${'$'}com.julienphalip.ideavim.peekaboo' [latest-IU] -team-city
java -jar verifier1/verifier-cli-dev-all-1.jar check-plugin '${'$'}com.julienphalip.ideavim.switch' [latest-IU] -team-city
java -jar verifier1/verifier-cli-dev-all-1.jar check-plugin '${'$'}com.julienphalip.ideavim.functiontextobj' [latest-IU] -team-city
""".trimIndent()
}
}

View File

@ -41,7 +41,7 @@ object ReleaseEapFromBranch : IdeaVimBuildType({
vcs {
root(ReleasesVcsRoot)
branchFilter = """
+:heads/releases/*
+:heads/(releases/*)
""".trimIndent()
checkoutMode = CheckoutMode.AUTO

View File

@ -39,11 +39,9 @@ open class TestingBuildType(
steps {
gradle {
clearConditions()
tasks = "clean test"
buildFile = ""
enableStacktrace = true
jdkHome = "/usr/lib/jvm/java-17-amazon-corretto"
}
}

View File

@ -1,5 +1,6 @@
package _Self.subprojects
import _Self.Constants
import _Self.IdeaVimBuildType
import _Self.vcsRoots.GitHubPullRequest
import jetbrains.buildServer.configs.kotlin.v2019_2.CheckoutMode
@ -24,6 +25,7 @@ class GithubBuildType(command: String, desc: String) : IdeaVimBuildType({
params {
param("env.ORG_GRADLE_PROJECT_downloadIdeaSources", "false")
param("env.ORG_GRADLE_PROJECT_ideaVersion", Constants.GITHUB_TESTS)
param("env.ORG_GRADLE_PROJECT_instrumentPluginCode", "false")
}

25
.teamcity/_Self/subprojects/OldTests.kt vendored Normal file
View File

@ -0,0 +1,25 @@
package _Self.subprojects
import _Self.buildTypes.TestingBuildType
import jetbrains.buildServer.configs.kotlin.v2019_2.Project
object OldTests : Project({
name = "Old IdeaVim tests"
description = "Tests for older versions of IJ"
buildType(TestingBuildType("IC-2018.1", "181-182", javaVersion = "1.8", javaPlugin = false))
buildType(TestingBuildType("IC-2018.2", "181-182", javaVersion = "1.8", javaPlugin = false))
buildType(TestingBuildType("IC-2018.3", "183", javaVersion = "1.8", javaPlugin = false))
buildType(TestingBuildType("IC-2019.1", "191-193", javaVersion = "1.8", javaPlugin = false))
buildType(TestingBuildType("IC-2019.2", "191-193", javaVersion = "1.8", javaPlugin = false))
buildType(TestingBuildType("IC-2019.3", "191-193", javaVersion = "1.8", javaPlugin = false))
buildType(TestingBuildType("IC-2020.1", "201", javaVersion = "1.8", javaPlugin = false))
buildType(TestingBuildType("IC-2020.2", "202", javaVersion = "1.8", javaPlugin = false))
buildType(TestingBuildType("IC-2020.3", "203-212", javaVersion = "1.8", javaPlugin = false))
buildType(TestingBuildType("IC-2021.1", "203-212", javaVersion = "1.8", javaPlugin = false))
buildType(TestingBuildType("IC-2021.2.2", "203-212", javaVersion = "1.8", javaPlugin = false))
buildType(TestingBuildType("IC-2021.3.2", "213-221", javaVersion = "1.8", javaPlugin = false))
buildType(TestingBuildType("IC-2022.2.3", branch = "222", javaPlugin = false))
buildType(TestingBuildType("IC-2023.1", "231-232", javaPlugin = false))
buildType(TestingBuildType("IC-2023.2", "231-232", javaPlugin = false))
})

View File

@ -0,0 +1,39 @@
package patches.buildTypes
import jetbrains.buildServer.configs.kotlin.v2019_2.*
import jetbrains.buildServer.configs.kotlin.v2019_2.buildSteps.GradleBuildStep
import jetbrains.buildServer.configs.kotlin.v2019_2.buildSteps.gradle
import jetbrains.buildServer.configs.kotlin.v2019_2.ui.*
/*
This patch script was generated by TeamCity on settings change in UI.
To apply the patch, change the buildType with id = 'IdeaVimTests_Latest_EAP'
accordingly, and delete the patch script.
*/
changeBuildType(RelativeId("IdeaVimTests_Latest_EAP")) {
check(artifactRules == """
+:build/reports => build/reports
+:/mnt/agent/temp/buildTmp/ => /mnt/agent/temp/buildTmp/
""".trimIndent()) {
"Unexpected option value: artifactRules = $artifactRules"
}
artifactRules = """
+:build/reports => build/reports
+:/mnt/agent/temp/buildTmp/ => /mnt/agent/temp/buildTmp/
+:tests/java-tests/build/reports => tests/java-tests/build/reports
""".trimIndent()
expectSteps {
gradle {
tasks = "clean test"
buildFile = ""
enableStacktrace = true
}
}
steps {
update<GradleBuildStep>(0) {
clearConditions()
jdkHome = "/usr/lib/jvm/java-17-amazon-corretto"
}
}
}

View File

@ -0,0 +1,19 @@
package patches.buildTypes
import jetbrains.buildServer.configs.kotlin.v2019_2.*
import jetbrains.buildServer.configs.kotlin.v2019_2.ui.*
/*
This patch script was generated by TeamCity on settings change in UI.
To apply the patch, change the buildType with id = 'ReleaseEapFromBranch'
accordingly, and delete the patch script.
*/
changeBuildType(RelativeId("ReleaseEapFromBranch")) {
vcs {
check(branchFilter == "+:heads/(releases/*)") {
"Unexpected option value: branchFilter = $branchFilter"
}
branchFilter = "heads/releases/*"
}
}

View File

@ -539,30 +539,6 @@ Contributors:
[![icon][github]](https://github.com/felixwiemuth)
&nbsp;
Felix Wiemuth
* [![icon][mail]](mailto:kirill.karnaukhov@jetbrains.com)
[![icon][github]](https://github.com/kkarnauk)
&nbsp;
Kirill Karnaukhov,
* [![icon][mail]](mailto:sander.hestvik@gmail.com)
[![icon][github]](https://github.com/SanderHestvik)
&nbsp;
SanderHestvik
* [![icon][mail]](mailto:gregory.shrago@jetbrains.com)
[![icon][github]](https://github.com/gregsh)
&nbsp;
Greg Shrago
* [![icon][mail]](mailto:jphalip@gmail.com)
[![icon][github]](https://github.com/jphalip)
&nbsp;
Julien Phalip
* [![icon][mail]](mailto:j.trimailovas@gmail.com)
[![icon][github]](https://github.com/trimailov)
&nbsp;
Justas Trimailovas,
* [![icon][mail]](mailto:justast@wix.com)
[![icon][github]](https://github.com/justast-wix)
&nbsp;
Justas Trimailovas
Previous contributors:
@ -574,10 +550,6 @@ Previous contributors:
[![icon][github]](https://github.com/kevin70)
&nbsp;
kk
* [![icon][mail]](mailto:gregory.shrago@jetbrains.com)
[![icon][github]](https://github.com/gregsh)
&nbsp;
Greg Shrago
If you are a contributor and your name is not listed here, feel free to

View File

@ -21,7 +21,7 @@ repositories {
}
dependencies {
compileOnly("com.google.devtools.ksp:symbol-processing-api:2.1.0-1.0.29")
compileOnly("com.google.devtools.ksp:symbol-processing-api:2.0.0-1.0.24")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json-jvm:$kotlinxSerializationVersion") {
// kotlin stdlib is provided by IJ, so there is no need to include it into the distribution
exclude("org.jetbrains.kotlin", "kotlin-stdlib")

View File

@ -50,14 +50,14 @@ buildscript {
classpath("org.eclipse.jgit:org.eclipse.jgit:6.6.0.202305301015-r")
// This is needed for jgit to connect to ssh
classpath("org.eclipse.jgit:org.eclipse.jgit.ssh.apache:7.1.0.202411261347-r")
classpath("org.eclipse.jgit:org.eclipse.jgit.ssh.apache:6.10.0.202406032230-r")
classpath("org.kohsuke:github-api:1.305")
classpath("io.ktor:ktor-client-core:3.0.2")
classpath("io.ktor:ktor-client-cio:3.0.2")
classpath("io.ktor:ktor-client-auth:3.0.2")
classpath("io.ktor:ktor-client-content-negotiation:3.0.2")
classpath("io.ktor:ktor-serialization-kotlinx-json:3.0.2")
classpath("io.ktor:ktor-client-core:2.3.12")
classpath("io.ktor:ktor-client-cio:2.3.10")
classpath("io.ktor:ktor-client-auth:2.3.12")
classpath("io.ktor:ktor-client-content-negotiation:2.3.10")
classpath("io.ktor:ktor-serialization-kotlinx-json:2.3.12")
// This comes from the changelog plugin
// classpath("org.jetbrains:markdown:0.3.1")
@ -69,7 +69,7 @@ plugins {
kotlin("jvm") version "2.0.0"
application
id("java-test-fixtures")
id("org.jetbrains.intellij.platform") version "2.2.0"
id("org.jetbrains.intellij.platform") version "2.0.0-rc2"
id("org.jetbrains.changelog") version "2.2.1"
id("org.jetbrains.kotlinx.kover") version "0.6.1"
id("com.dorongold.task-tree") version "4.0.0"
@ -85,6 +85,7 @@ val ideaVersion: String by project
val ideaType: String by project
val instrumentPluginCode: String by project
val remoteRobotVersion: String by project
val splitModeVersion: String by project
val publishChannels: String by project
val publishToken: String by project
@ -107,17 +108,13 @@ dependencies {
compileOnly(project(":annotation-processors"))
compileOnly("org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion")
compileOnly("org.jetbrains:annotations:26.0.1")
compileOnly("org.jetbrains:annotations:24.1.0")
intellijPlatform {
// Snapshots don't use installers
// https://plugins.jetbrains.com/docs/intellij/tools-intellij-platform-gradle-plugin-dependencies-extension.html#target-versions-installers
val useInstaller = "EAP-SNAPSHOT" !in ideaVersion
// Note that it is also possible to use local("...") to compile against a locally installed IDE
// E.g. local("/Users/{user}/Applications/IntelliJ IDEA Ultimate.app")
// Or something like: intellijIdeaUltimate(ideaVersion)
create(ideaType, ideaVersion, useInstaller)
create(ideaType, ideaVersion)
pluginVerifier()
zipSigner()
@ -150,17 +147,17 @@ dependencies {
// https://mvnrepository.com/artifact/org.mockito.kotlin/mockito-kotlin
testImplementation("org.mockito.kotlin:mockito-kotlin:5.4.0")
testImplementation("org.junit.jupiter:junit-jupiter-api:5.10.5")
testImplementation("org.junit.jupiter:junit-jupiter-engine:5.10.5")
testImplementation("org.junit.jupiter:junit-jupiter-params:5.10.5")
testFixturesImplementation("org.junit.jupiter:junit-jupiter-api:5.10.5")
testFixturesImplementation("org.junit.jupiter:junit-jupiter-engine:5.10.5")
testFixturesImplementation("org.junit.jupiter:junit-jupiter-params:5.10.5")
testImplementation("org.junit.jupiter:junit-jupiter-api:5.10.3")
testImplementation("org.junit.jupiter:junit-jupiter-engine:5.10.3")
testImplementation("org.junit.jupiter:junit-jupiter-params:5.10.3")
testFixturesImplementation("org.junit.jupiter:junit-jupiter-api:5.10.3")
testFixturesImplementation("org.junit.jupiter:junit-jupiter-engine:5.10.3")
testFixturesImplementation("org.junit.jupiter:junit-jupiter-params:5.10.3")
// Temp workaround suggested in https://plugins.jetbrains.com/docs/intellij/tools-intellij-platform-gradle-plugin-faq.html#junit5-test-framework-refers-to-junit4
// Can be removed when IJPL-159134 is fixed
// testRuntimeOnly("junit:junit:4.13.2")
testImplementation("org.junit.vintage:junit-vintage-engine:5.10.5")
testImplementation("org.junit.vintage:junit-vintage-engine:5.10.3")
// testFixturesImplementation("org.junit.vintage:junit-vintage-engine:5.10.3")
}
@ -235,7 +232,6 @@ tasks {
// Uncomment to run the plugin in a custom IDE, rather than the IDE specified as a compile target in dependencies
// Note that the version must be greater than the plugin's target version, for obvious reasons
// You can also set splitMode and splitModeTarget here to test split mode in a custom IDE
// val runIdeCustom by intellijPlatformTesting.runIde.registering {
// type = IntelliJPlatformType.Rider
// version = "2024.1.2"
@ -268,6 +264,10 @@ tasks {
val runIdeSplitMode by intellijPlatformTesting.runIde.registering {
splitMode = true
splitModeTarget = SplitModeAware.SplitModeTarget.FRONTEND
// Frontend split mode support requires 242+
// TODO: Remove this once IdeaVim targets 242, as the task will naturally use the target version to run
version.set(splitModeVersion)
}
// Add plugin open API sources to the plugin ZIP

View File

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

View File

@ -82,7 +82,7 @@ Original plugin: [NERDTree](https://github.com/preservim/nerdtree).
### Instructions
[See here](NERDTree-support.md).
[See here](NERDTree-support).
</details>
@ -321,10 +321,7 @@ If you want to optimize highlight duration, assign a time in milliseconds:
If you want to change background color of highlight you can provide the rgba of the color you want e.g.
`let g:highlightedyank_highlight_color = "rgba(160, 160, 160, 155)"`
If you want to change text color of highlight you can provide the rgba of the color you want e.g.
`let g:highlightedyank_highlight_foreground_color = "rgba(0, 0, 0, 255)"`
https://github.com/machakann/vim-highlightedyank/blob/master/doc/highlightedyank.txt
</details>
@ -438,50 +435,3 @@ Original plugin: [vim-which-key](https://github.com/liuchengxu/vim-which-key).
https://github.com/TheBlob42/idea-which-key?tab=readme-ov-file#installation
</details>
<details>
<summary><h2>Vim Peekaboo</h2></summary>
By Julien Phalip
Original plugin: [vim-peekaboo](https://github.com/junegunn/vim-peekaboo).
### Setup
Add `set peekaboo` to your `~/.ideavimrc` file, then run `:source ~/.ideavimrc`
or restart the IDE.
### Instructions
https://plugins.jetbrains.com/plugin/25776-vim-peekaboo
</details>
<details>
<summary><h2>FunctionTextObj</h2></summary>
By Julien Phalip
### Setup
Add `set functiontextobj` to your `~/.ideavimrc` file, then run `:source ~/.ideavimrc`
or restart the IDE.
### Instructions
https://plugins.jetbrains.com/plugin/25897-vim-functiontextobj
</details>
<details>
<summary><h2>Switch</h2></summary>
By Julien Phalip
Original plugin: [switch.vim](https://github.com/AndrewRadev/switch.vim).
### Setup
Add `set switch` to your `~/.ideavimrc` file, then run `:source ~/.ideavimrc`
or restart the IDE.
### Instructions
https://plugins.jetbrains.com/plugin/25899-vim-switch
</details>

View File

@ -25,7 +25,7 @@ It's not intended to be read by the users as it brings no value to them.
IdeaVim has multiple YouTrack statuses, main are:
- Submitted: issue is created by user, but not processed by our team. This is the default status for new tickets.
- Open: issues is processed by our team, what means that the issues is reproduced and accepted
- Open: issues is processed by out team, what means that the issues is reproduced and accepted
- Waiting For Reply: Waiting for further information from the user. These issues are automatically closed if the
user doesn't reply in 30 days.
- Ready To Release: Bug is fixed, but not yet released

View File

@ -20,11 +20,17 @@ ideaVersion=2024.2
# Values for type: https://plugins.jetbrains.com/docs/intellij/tools-gradle-intellij-plugin.html#intellij-extension-type
ideaType=IC
instrumentPluginCode=true
version=chylex-42
version=chylex-41
javaVersion=17
remoteRobotVersion=0.11.23
antlrVersion=4.10.1
# [VERSION UPDATE] 2024.2 - remove when IdeaVim targets 2024.2
# Running IdeaVim in split mode requires 242. Update this version once 242 has been released, and remove it completely
# when IdeaVim targets 242, at which point runIdeSplitMode will run correctly with the target version.
# See also runIdeSplitMode
splitModeVersion=242-EAP-SNAPSHOT
# Please don't forget to update kotlin version in buildscript section
# Also update kotlinxSerializationVersion version

Binary file not shown.

View File

@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME

22
gradlew vendored
View File

@ -15,8 +15,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
# SPDX-License-Identifier: Apache-2.0
#
##############################################################################
#
@ -57,7 +55,7 @@
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
@ -85,9 +83,7 @@ done
# This is normally unused
# shellcheck disable=SC2034
APP_BASE_NAME=${0##*/}
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s
' "$PWD" ) || exit
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum
@ -148,7 +144,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #(
max*)
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC2039,SC3045
# shellcheck disable=SC3045
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
@ -156,7 +152,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
'' | soft) :;; #(
*)
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC2039,SC3045
# shellcheck disable=SC3045
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
@ -205,11 +201,11 @@ fi
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Collect all arguments for the java command:
# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
# and any embedded shellness will be escaped.
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
# treated as '${Hostname}' itself on the command line.
# Collect all arguments for the java command;
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
# shell script including quotes and variable substitutions, so put them in
# double quotes to make sure that they get re-expanded; and
# * put everything else in single quotes, so that it's not re-expanded.
set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \

22
gradlew.bat vendored
View File

@ -13,8 +13,6 @@
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@rem SPDX-License-Identifier: Apache-2.0
@rem
@if "%DEBUG%"=="" @echo off
@rem ##########################################################################
@ -45,11 +43,11 @@ set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if %ERRORLEVEL% equ 0 goto execute
echo. 1>&2
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
echo. 1>&2
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. 1>&2
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
@ -59,11 +57,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo. 1>&2
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
echo. 1>&2
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. 1>&2
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail

View File

@ -20,17 +20,17 @@ repositories {
}
dependencies {
compileOnly("org.jetbrains.kotlin:kotlin-stdlib:2.1.0")
compileOnly("org.jetbrains.kotlin:kotlin-stdlib:1.9.25")
implementation("io.ktor:ktor-client-core:3.0.2")
implementation("io.ktor:ktor-client-cio:3.0.2")
implementation("io.ktor:ktor-client-content-negotiation:3.0.2")
implementation("io.ktor:ktor-serialization-kotlinx-json:3.0.2")
implementation("io.ktor:ktor-client-auth:3.0.2")
implementation("io.ktor:ktor-client-core:2.3.12")
implementation("io.ktor:ktor-client-cio:2.3.10")
implementation("io.ktor:ktor-client-content-negotiation:2.3.10")
implementation("io.ktor:ktor-serialization-kotlinx-json:2.3.12")
implementation("io.ktor:ktor-client-auth:2.3.12")
implementation("org.eclipse.jgit:org.eclipse.jgit:6.6.0.202305301015-r")
// This is needed for jgit to connect to ssh
implementation("org.eclipse.jgit:org.eclipse.jgit.ssh.apache:7.1.0.202411261347-r")
implementation("org.eclipse.jgit:org.eclipse.jgit.ssh.apache:6.10.0.202406032230-r")
implementation("com.vdurmont:semver4j:3.1.0")
}

View File

@ -40,9 +40,6 @@ val knownPlugins = setOf(
"com.protoseo.input-source-auto-converter",
// "cc.implicated.intellij.plugins.bunny", // I don't want to include this plugin in the list of IdeaVim plugins as I don't understand what this is for
"com.julienphalip.ideavim.peekaboo", // https://plugins.jetbrains.com/plugin/25776-vim-peekaboo
"com.julienphalip.ideavim.switch", // https://plugins.jetbrains.com/plugin/25899-vim-switch
"com.julienphalip.ideavim.functiontextobj", // https://plugins.jetbrains.com/plugin/25897-vim-functiontextobj
)
suspend fun main() {

View File

@ -33,9 +33,6 @@ internal class PluginStartup : ProjectActivity/*, LightEditCompatible*/ {
private var firstInitializationOccurred = false
// TODO
// We should migrate to some solution from https://plugins.jetbrains.com/docs/intellij/plugin-components.html#application-startup
// If you'd like to add a new code here, please consider using one of the things described there.
override suspend fun execute(project: Project) {
if (firstInitializationOccurred) return
firstInitializationOccurred = true

View File

@ -10,7 +10,6 @@ package com.maddyhome.idea.vim;
import com.intellij.ide.plugins.IdeaPluginDescriptor;
import com.intellij.ide.plugins.PluginManagerCore;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.application.AccessToken;
import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.components.PersistentStateComponent;
@ -25,8 +24,10 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.util.SlowOperations;
import com.maddyhome.idea.vim.api.*;
import com.maddyhome.idea.vim.api.VimEditor;
import com.maddyhome.idea.vim.api.VimInjectorKt;
import com.maddyhome.idea.vim.api.VimKeyGroup;
import com.maddyhome.idea.vim.api.VimOptionGroup;
import com.maddyhome.idea.vim.config.VimState;
import com.maddyhome.idea.vim.config.migration.ApplicationConfigurationMigrator;
import com.maddyhome.idea.vim.extension.VimExtensionRegistrar;
@ -35,6 +36,7 @@ import com.maddyhome.idea.vim.group.copy.PutGroup;
import com.maddyhome.idea.vim.group.visual.VisualMotionGroup;
import com.maddyhome.idea.vim.helper.MacKeyRepeat;
import com.maddyhome.idea.vim.listener.VimListenerManager;
import com.maddyhome.idea.vim.newapi.IjVimInjector;
import com.maddyhome.idea.vim.newapi.IjVimInjectorKt;
import com.maddyhome.idea.vim.newapi.IjVimSearchGroup;
import com.maddyhome.idea.vim.ui.StatusBarIconFactory;
@ -139,8 +141,8 @@ public class VimPlugin implements PersistentStateComponent<Element>, Disposable
return (MacroGroup)VimInjectorKt.getInjector().getMacro();
}
public static @NotNull VimDigraphGroup getDigraph() {
return VimInjectorKt.getInjector().getDigraphGroup();
public static @NotNull DigraphGroup getDigraph() {
return (DigraphGroup)VimInjectorKt.getInjector().getDigraphGroup();
}
public static @NotNull HistoryGroup getHistory() {
@ -337,9 +339,7 @@ public class VimPlugin implements PersistentStateComponent<Element>, Disposable
// 4) ~/.ideavimrc execution
// Evaluate in the context of the fallback window, to capture local option state, to copy to the first editor window
try (AccessToken ignore = SlowOperations.knownIssue("VIM-3661")) {
registerIdeavimrc(VimInjectorKt.getInjector().getFallbackWindow());
}
registerIdeavimrc(VimInjectorKt.getInjector().getFallbackWindow());
// Turing on should be performed after all commands registration
getSearch().turnOn();

View File

@ -298,10 +298,26 @@ class VimShortcutKeyAction : AnAction(), DumbAware/*, LightEditCompatible*/ {
.addAll(getKeyStrokes(KeyEvent.VK_BACK_SPACE, 0, InputEvent.CTRL_DOWN_MASK))
.addAll(getKeyStrokes(KeyEvent.VK_INSERT, 0))
.addAll(getKeyStrokes(KeyEvent.VK_DELETE, 0, InputEvent.CTRL_DOWN_MASK))
.addAll(getKeyStrokes(KeyEvent.VK_UP, 0))
.addAll(getKeyStrokes(KeyEvent.VK_DOWN, 0))
.addAll(getKeyStrokes(KeyEvent.VK_LEFT, 0))
.addAll(getKeyStrokes(KeyEvent.VK_RIGHT, 0))
.addAll(getKeyStrokes(KeyEvent.VK_UP, 0, InputEvent.CTRL_DOWN_MASK, InputEvent.SHIFT_DOWN_MASK))
.addAll(getKeyStrokes(KeyEvent.VK_DOWN, 0, InputEvent.CTRL_DOWN_MASK, InputEvent.SHIFT_DOWN_MASK))
.addAll(
getKeyStrokes(
KeyEvent.VK_LEFT,
0,
InputEvent.CTRL_DOWN_MASK,
InputEvent.SHIFT_DOWN_MASK,
InputEvent.CTRL_DOWN_MASK or InputEvent.SHIFT_DOWN_MASK,
),
)
.addAll(
getKeyStrokes(
KeyEvent.VK_RIGHT,
0,
InputEvent.CTRL_DOWN_MASK,
InputEvent.SHIFT_DOWN_MASK,
InputEvent.CTRL_DOWN_MASK or InputEvent.SHIFT_DOWN_MASK,
),
)
.addAll(
getKeyStrokes(
KeyEvent.VK_HOME,

View File

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

View File

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

View File

@ -44,7 +44,6 @@ class DeleteJoinVisualLinesAction : VisualOperatorActionHandler.SingleExecution(
val range = caretsAndSelections[caret] ?: return@forEach
if (!injector.changeGroup.deleteJoinRange(
editor,
context,
caret,
range.toVimTextRange(true).normalize(),
false,

View File

@ -44,7 +44,6 @@ class DeleteJoinVisualLinesSpacesAction : VisualOperatorActionHandler.SingleExec
val range = caretsAndSelections[caret] ?: return@forEach
if (!injector.changeGroup.deleteJoinRange(
editor,
context,
caret,
range.toVimTextRange(true).normalize(),
true,

View File

@ -20,8 +20,6 @@ import com.maddyhome.idea.vim.command.OperatorArguments
import com.maddyhome.idea.vim.handler.IdeActionHandler
import com.maddyhome.idea.vim.handler.VimActionHandler
import com.maddyhome.idea.vim.helper.enumSetOf
import com.maddyhome.idea.vim.undo.VimKeyBasedUndoService
import com.maddyhome.idea.vim.undo.VimTimestampBasedUndoService
import java.util.*
@CommandOrMotion(keys = ["<Del>"], modes = [Mode.INSERT])
@ -41,13 +39,8 @@ internal class VimEditorDown : IdeActionHandler(IdeActions.ACTION_EDITOR_MOVE_CA
operatorArguments: OperatorArguments
): Boolean {
val undo = injector.undo
when (undo) {
is VimKeyBasedUndoService -> undo.setMergeUndoKey()
is VimTimestampBasedUndoService -> {
val nanoTime = System.nanoTime()
editor.forEachCaret { undo.endInsertSequence(it, it.offset, nanoTime) }
}
}
val nanoTime = System.nanoTime()
editor.forEachCaret { undo.endInsertSequence(it, it.offset, nanoTime) }
return super.execute(editor, context, cmd, operatorArguments)
}
}
@ -70,13 +63,8 @@ internal class VimEditorUp : IdeActionHandler(IdeActions.ACTION_EDITOR_MOVE_CARE
operatorArguments: OperatorArguments
): Boolean {
val undo = injector.undo
when (undo) {
is VimKeyBasedUndoService -> undo.setMergeUndoKey()
is VimTimestampBasedUndoService -> {
val nanoTime = System.nanoTime()
editor.forEachCaret { undo.endInsertSequence(it, it.offset, nanoTime) }
}
}
val nanoTime = System.nanoTime()
editor.forEachCaret { undo.endInsertSequence(it, it.offset, nanoTime) }
return super.execute(editor, context, cmd, operatorArguments)
}
}

View File

@ -27,30 +27,6 @@ public interface VimExtension {
return MappingOwner.Plugin.Companion.get(getName());
}
/**
* This method is always called AFTER the full execution of the `.ideavimrc` file.
* <p>
* During vim initialization process, it firstly loads the .vimrc file, then executes scripts from the plugins folder.
* This practically means that the .vimrc file is initialized first; then the plugins are loaded.
* See `:h initialization`
* <p>
* Why does this matter? Because this affects the order of commands are executed. For example,
* ```
* plug 'tommcdo/vim-exchange'
* let g:exchange_no_mappings=1
* ```
* Here the user will expect that the exchange plugin won't have default mappings. However, if we load vim-exchange
* immediately, this variable won't be initialized at the moment of plugin initialization.
* <p>
* There is also a tricky case for mappings override:
* ```
* plug 'tommcdo/vim-exchange'
* map X <Plug>(ExchangeLine)
* ```
* For this case, a plugin with a good implementation detects that there is already a defined mapping for
* `<Plug>(ExchangeLine)` and doesn't register the default cxx mapping. However, such detection requires the mapping
* to be defined before the plugin initialization.
*/
void init();
default void dispose() {

View File

@ -69,7 +69,8 @@ object VimExtensionFacade {
@JvmStatic
@Deprecated("Use VimPlugin.getKey().putKeyMapping(modes, fromKeys, pluginOwner, extensionHandler, recursive)",
@Deprecated(
"Use VimPlugin.getKey().putKeyMapping(modes, fromKeys, pluginOwner, extensionHandler, recursive)",
ReplaceWith(
"VimPlugin.getKey().putKeyMapping(modes, fromKeys, pluginOwner, extensionHandler, recursive)",
"com.maddyhome.idea.vim.VimPlugin"
@ -188,22 +189,14 @@ object VimExtensionFacade {
/** Get the current contents of the given register similar to 'getreg()'. */
@JvmStatic
@Deprecated("Please use com.maddyhome.idea.vim.extension.VimExtensionFacade.getRegister(com.maddyhome.idea.vim.api.VimEditor, char)")
fun getRegister(register: Char): List<KeyStroke>? {
val reg = VimPlugin.getRegister().getRegister(register) ?: return null
return reg.keys
}
/** Get the current contents of the given register similar to 'getreg()'. */
@JvmStatic
fun getRegister(editor: VimEditor, register: Char): List<KeyStroke>? {
val reg = VimPlugin.getRegister().getRegister(editor, injector.executionContextManager.getEditorExecutionContext(editor), register) ?: return null
return reg.keys
}
@JvmStatic
fun getRegisterForCaret(register: Char, caret: VimCaret): List<KeyStroke>? {
val reg = caret.registerStorage.getRegister(register) ?: return null
val reg = injector.registerGroup.getRegister(register) ?: return null
return reg.keys
}
@ -216,7 +209,7 @@ object VimExtensionFacade {
/** Set the current contents of the given register */
@JvmStatic
fun setRegisterForCaret(register: Char, caret: ImmutableVimCaret, keys: List<KeyStroke?>?) {
caret.registerStorage.setKeys(register, keys?.filterNotNull() ?: emptyList())
injector.registerGroup.setKeys(register, keys?.filterNotNull() ?: emptyList())
}
/** Set the current contents of the given register */

View File

@ -88,10 +88,29 @@ internal object VimExtensionRegistrar : VimExtensionRegistrator {
}
/**
* See the docs for [VimExtension.init]
* During vim initialization process, it firstly loads the .vimrc file, then executes scripts from the plugins folder.
* This practically means that the .vimrc file is initialized first, then the plugins are loaded.
* See `:h initialization`
*
* In IdeaVim we don't have a separate plugins folder to load it after .ideavimrc load. However, we can collect
* the list of plugins mentioned in the .ideavimrc and load them after .ideavimrc execution is finished.
*
* Why this matters? Because this affects the order of commands are executed. For example:
* ```
* plug 'tommcdo/vim-exchange'
* let g:exchange_no_mappings=1
* ```
* Here the user will expect that the exchange plugin won't have default mappings. However, if we load vim-exchange
* immediately, this variable won't be initialized at the moment of plugin initialization.
*
* There is also a tricky case for mappings override:
* ```
* plug 'tommcdo/vim-exchange'
* map X <Plug>(ExchangeLine)
* ```
* For this case, a plugin with a good implementation detects that there is already a defined mapping for
* `<Plug>(ExchangeLine)` and doesn't register the default cxx mapping. However, such detection requires the mapping
* to be defined before the plugin initialization.
*/
@JvmStatic
fun enableDelayedExtensions() {

View File

@ -222,10 +222,10 @@ internal class VimExchangeExtension : VimExtension {
}
}
val zRegText = getRegister(editor.vim, 'z')
val unnRegText = getRegister(editor.vim, '"')
val startRegText = getRegister(editor.vim, '*')
val plusRegText = getRegister(editor.vim, '+')
val zRegText = getRegister('z')
val unnRegText = getRegister('"')
val startRegText = getRegister('*')
val plusRegText = getRegister('+')
runWriteAction {
// TODO handle:
// " Compare using =~ because "'==' != 0" returns 0
@ -299,7 +299,7 @@ internal class VimExchangeExtension : VimExtension {
private fun getExchange(editor: Editor, isVisual: Boolean, selectionType: SelectionType): Exchange {
// TODO: improve KeyStroke list to sting conversion
fun getRegisterText(reg: Char): String = getRegister(editor.vim, reg)?.map { it.keyChar }?.joinToString("") ?: ""
fun getRegisterText(reg: Char): String = getRegister(reg)?.map { it.keyChar }?.joinToString("") ?: ""
fun getMarks(isVisual: Boolean): Pair<Mark, Mark> {
val (startMark, endMark) =
if (isVisual) {
@ -313,9 +313,9 @@ internal class VimExchangeExtension : VimExtension {
return Pair(marks.getMark(vimEditor.primaryCaret(), startMark)!!, marks.getMark(vimEditor.primaryCaret(), endMark)!!)
}
val unnRegText = getRegister(editor.vim, '"')
val starRegText = getRegister(editor.vim, '*')
val plusRegText = getRegister(editor.vim, '+')
val unnRegText = getRegister('"')
val starRegText = getRegister('*')
val plusRegText = getRegister('+')
val (selectionStart, selectionEnd) = getMarks(isVisual)
if (isVisual) {

View File

@ -45,10 +45,6 @@ private val HIGHLIGHT_DURATION_VARIABLE_NAME = "highlightedyank_highlight_durati
@NonNls
private val HIGHLIGHT_COLOR_VARIABLE_NAME = "highlightedyank_highlight_color"
@NonNls
private val HIGHLIGHT_FOREGROUND_COLOR_VARIABLE_NAME = "highlightedyank_highlight_foreground_color"
private var defaultHighlightTextColor: Color? = null
private fun getDefaultHighlightTextColor(): Color {
@ -79,9 +75,6 @@ internal class HighlightColorResetter : LafManagerListener {
* if you want to change background color of highlight you can provide the rgba of the color you want e.g.
* let g:highlightedyank_highlight_color = "rgba(160, 160, 160, 155)"
*
* if you want to change text color of highlight you can provide the rgba of the color you want e.g.
* let g:highlightedyank_highlight_foreground_color = "rgba(0, 0, 0, 255)"
*
* When a new text is yanked or user starts editing, the old highlighting would be deleted.
*/
internal class VimHighlightedYank : VimExtension, VimYankListener, ModeChangeListener {
@ -188,15 +181,13 @@ internal class VimHighlightedYank : VimExtension, VimYankListener, ModeChangeLis
highlighters.clear()
}
private fun getHighlightTextAttributes(editor: Editor): TextAttributes {
return TextAttributes(
extractUserHighlightForegroundColor(),
extractUsersHighlightColor(),
editor.colorsScheme.getColor(EditorColors.CARET_COLOR),
EffectType.SEARCH_MATCH,
Font.PLAIN,
)
}
private fun getHighlightTextAttributes(editor: Editor) = TextAttributes(
null,
extractUsersHighlightColor(),
editor.colorsScheme.getColor(EditorColors.CARET_COLOR),
EffectType.SEARCH_MATCH,
Font.PLAIN,
)
private fun extractUsersHighlightDuration(): Int {
return extractVariable(HIGHLIGHT_DURATION_VARIABLE_NAME, DEFAULT_HIGHLIGHT_DURATION) {
@ -209,52 +200,15 @@ internal class VimHighlightedYank : VimExtension, VimYankListener, ModeChangeLis
}
private fun extractUsersHighlightColor(): Color {
val value = VimPlugin.getVariableService().getGlobalVariableValue(HIGHLIGHT_COLOR_VARIABLE_NAME)
if (value != null) {
return try {
parseRgbaColor(value.asString())
} catch (e: Exception) {
@VimNlsSafe val message = MessageHelper.message(
"highlightedyank.invalid.value.of.0.1",
"g:$HIGHLIGHT_COLOR_VARIABLE_NAME",
e.message ?: "",
)
VimPlugin.showMessage(message)
getDefaultHighlightTextColor()
}
return extractVariable(HIGHLIGHT_COLOR_VARIABLE_NAME, getDefaultHighlightTextColor()) { value ->
val rgba = value.asString()
.substring(4)
.filter { it != '(' && it != ')' && !it.isWhitespace() }
.split(',')
.map { it.toInt() }
Color(rgba[0], rgba[1], rgba[2], rgba[3])
}
return getDefaultHighlightTextColor()
}
private fun extractUserHighlightForegroundColor(): Color? {
val value = VimPlugin.getVariableService().getGlobalVariableValue(HIGHLIGHT_FOREGROUND_COLOR_VARIABLE_NAME)
?: return null
return try {
parseRgbaColor(value.asString())
} catch (e: Exception) {
@VimNlsSafe val message = MessageHelper.message(
"highlightedyank.invalid.value.of.0.1",
"g:$HIGHLIGHT_FOREGROUND_COLOR_VARIABLE_NAME",
e.message ?: "",
)
VimPlugin.showMessage(message)
null
}
}
private fun parseRgbaColor(colorString: String): Color {
val rgba = colorString
.substring(4)
.filter { it != '(' && it != ')' && !it.isWhitespace() }
.split(',')
.map { it.toInt() }
if (rgba.size != 4 || rgba.any { it < 0 || it > 255 }) {
throw IllegalArgumentException("Invalid RGBA values. Each component must be between 0 and 255")
}
return Color(rgba[0], rgba[1], rgba[2], rgba[3])
}
private fun <T> extractVariable(variable: String, default: T, extractFun: (value: VimDataType) -> T): T {

View File

@ -42,10 +42,13 @@ import com.maddyhome.idea.vim.extension.VimExtension
import com.maddyhome.idea.vim.group.KeyGroup
import com.maddyhome.idea.vim.helper.MessageHelper
import com.maddyhome.idea.vim.helper.runAfterGotFocus
import com.maddyhome.idea.vim.key.KeyStrokeTrie
import com.maddyhome.idea.vim.key.CommandNode
import com.maddyhome.idea.vim.key.CommandPartNode
import com.maddyhome.idea.vim.key.MappingOwner
import com.maddyhome.idea.vim.key.Node
import com.maddyhome.idea.vim.key.RequiredShortcut
import com.maddyhome.idea.vim.key.add
import com.maddyhome.idea.vim.key.RootNode
import com.maddyhome.idea.vim.key.addLeafs
import com.maddyhome.idea.vim.newapi.ij
import com.maddyhome.idea.vim.newapi.vim
import com.maddyhome.idea.vim.vimscript.model.datatypes.VimString
@ -195,8 +198,6 @@ internal class NerdTree : VimExtension {
internal var waitForSearch = false
internal var speedSearchListenerInstalled = false
private val keys = mutableListOf<KeyStroke>()
override fun actionPerformed(e: AnActionEvent) {
var keyStroke = getKeyStroke(e) ?: return
val keyChar = keyStroke.keyChar
@ -204,14 +205,20 @@ internal class NerdTree : VimExtension {
keyStroke = KeyStroke.getKeyStroke(keyChar)
}
keys.add(keyStroke)
actionsRoot.getData(keys)?.let { action ->
when (action) {
is NerdAction.ToIj -> Util.callAction(null, action.name, e.dataContext.vim)
is NerdAction.Code -> e.project?.let { action.action(it, e.dataContext, e) }
}
val nextNode = currentNode[keyStroke]
keys.clear()
when (nextNode) {
null -> currentNode = actionsRoot
is CommandNode<NerdAction> -> {
currentNode = actionsRoot
val action = nextNode.actionHolder
when (action) {
is NerdAction.ToIj -> Util.callAction(null, action.name, e.dataContext.vim)
is NerdAction.Code -> e.project?.let { action.action(it, e.dataContext, e) }
}
}
is CommandPartNode<NerdAction> -> currentNode = nextNode
}
}
@ -533,29 +540,38 @@ private fun addCommand(alias: String, handler: CommandAliasHandler) {
VimPlugin.getCommand().setAlias(alias, CommandAlias.Call(0, -1, alias, handler))
}
private fun registerCommand(variable: String, defaultMapping: String, action: NerdAction) {
private fun registerCommand(variable: String, default: String, action: NerdAction) {
val variableValue = VimPlugin.getVariableService().getGlobalVariableValue(variable)
val mapping = if (variableValue is VimString) {
val mappings = if (variableValue is VimString) {
variableValue.value
} else {
defaultMapping
default
}
registerCommand(mapping, action)
actionsRoot.addLeafs(mappings, action)
}
private fun registerCommand(mapping: String, action: NerdAction) {
actionsRoot.add(mapping, action)
injector.parser.parseKeys(mapping).forEach {
distinctShortcuts.add(it)
}
private fun registerCommand(default: String, action: NerdAction) {
actionsRoot.addLeafs(default, action)
}
private val actionsRoot: KeyStrokeTrie<NerdAction> = KeyStrokeTrie<NerdAction>("NERDTree")
private val distinctShortcuts = mutableSetOf<KeyStroke>()
private val actionsRoot: RootNode<NerdAction> = RootNode("NERDTree")
private var currentNode: CommandPartNode<NerdAction> = actionsRoot
private fun collectShortcuts(node: Node<NerdAction>): Set<KeyStroke> {
return if (node is CommandPartNode<NerdAction>) {
val res = node.children.keys.toMutableSet()
res += node.children.values.map { collectShortcuts(it) }.flatten()
res
} else {
emptySet()
}
}
private fun installDispatcher(project: Project) {
val dispatcher = NerdTree.NerdDispatcher.getInstance(project)
val shortcuts = distinctShortcuts.map { RequiredShortcut(it, MappingOwner.Plugin.get(NerdTree.pluginName)) }
val shortcuts =
collectShortcuts(actionsRoot).map { RequiredShortcut(it, MappingOwner.Plugin.get(NerdTree.pluginName)) }
dispatcher.registerCustomShortcutSet(
KeyGroup.toShortcutSet(shortcuts),
(ProjectView.getInstance(project) as ProjectViewImpl).component,

View File

@ -62,7 +62,7 @@ internal class ParagraphMotion : VimExtension {
toKeys: List<KeyStroke>,
recursive: Boolean,
) {
val filteredModes = modes.filterNotTo(HashSet()) { VimPlugin.getKey().getKeyMapping(it).getLayer(fromKeys) != null }
val filteredModes = modes.filterNotTo(HashSet()) { VimPlugin.getKey().hasmapfrom(it, fromKeys) }
putKeyMappingIfMissing(filteredModes, fromKeys, pluginOwner, toKeys, recursive)
}
}

View File

@ -143,7 +143,7 @@ internal class ReplaceWithRegister : VimExtension {
private fun doReplace(editor: Editor, context: DataContext, caret: ImmutableVimCaret, visualSelection: PutData.VisualSelection) {
val registerGroup = injector.registerGroup
val lastRegisterChar = if (editor.caretModel.caretCount == 1) registerGroup.currentRegister else registerGroup.getCurrentRegisterForMulticaret()
val savedRegister = caret.registerStorage.getRegister(lastRegisterChar) ?: return
val savedRegister = registerGroup.getRegister(lastRegisterChar) ?: return
var usedType = savedRegister.type
var usedText = savedRegister.text

View File

@ -34,7 +34,6 @@ import com.maddyhome.idea.vim.extension.VimExtensionFacade.putKeyMapping
import com.maddyhome.idea.vim.extension.VimExtensionHandler
import com.maddyhome.idea.vim.helper.StrictMode
import com.maddyhome.idea.vim.newapi.ij
import org.jetbrains.annotations.TestOnly
import java.awt.Font
import java.awt.event.KeyEvent
import java.util.*
@ -46,26 +45,15 @@ private const val DEFAULT_HIGHLIGHT_DURATION_SNEAK = 300
// By [Mikhail Levchenko](https://github.com/Mishkun)
// Original repository with the plugin: https://github.com/Mishkun/ideavim-sneak
internal class IdeaVimSneakExtension : VimExtension {
@Suppress("CompanionObjectInExtension")
companion object {
private var highlightHandler: HighlightHandler? = null
@TestOnly
internal fun stopTimer() {
highlightHandler?.stopExistingTimer()
}
}
override fun getName(): String = "sneak"
override fun init() {
val _highlightHandler = HighlightHandler()
highlightHandler = _highlightHandler
mapToFunctionAndProvideKeys("s", SneakHandler(_highlightHandler, Direction.FORWARD), MappingMode.NXO)
val highlightHandler = HighlightHandler()
mapToFunctionAndProvideKeys("s", SneakHandler(highlightHandler, Direction.FORWARD), MappingMode.NXO)
// vim-sneak uses `Z` for visual mode because `S` conflict with vim-sneak plugin VIM-3330
mapToFunctionAndProvideKeys("S", SneakHandler(_highlightHandler, Direction.BACKWARD), MappingMode.NO)
mapToFunctionAndProvideKeys("Z", SneakHandler(_highlightHandler, Direction.BACKWARD), MappingMode.X)
mapToFunctionAndProvideKeys("S", SneakHandler(highlightHandler, Direction.BACKWARD), MappingMode.NO)
mapToFunctionAndProvideKeys("Z", SneakHandler(highlightHandler, Direction.BACKWARD), MappingMode.X)
// workaround to support ; and , commands
mapToFunctionAndProvideKeys("f", SneakMemoryHandler("f"), MappingMode.NXO)
@ -73,8 +61,8 @@ internal class IdeaVimSneakExtension : VimExtension {
mapToFunctionAndProvideKeys("t", SneakMemoryHandler("t"), MappingMode.NXO)
mapToFunctionAndProvideKeys("T", SneakMemoryHandler("T"), MappingMode.NXO)
mapToFunctionAndProvideKeys(";", SneakRepeatHandler(_highlightHandler, RepeatDirection.IDENTICAL), MappingMode.NXO)
mapToFunctionAndProvideKeys(",", SneakRepeatHandler(_highlightHandler, RepeatDirection.REVERSE), MappingMode.NXO)
mapToFunctionAndProvideKeys(";", SneakRepeatHandler(highlightHandler, RepeatDirection.IDENTICAL), MappingMode.NXO)
mapToFunctionAndProvideKeys(",", SneakRepeatHandler(highlightHandler, RepeatDirection.REVERSE), MappingMode.NXO)
}
private class SneakHandler(
@ -221,7 +209,6 @@ internal class IdeaVimSneakExtension : VimExtension {
private class HighlightHandler {
private var editor: Editor? = null
private val sneakHighlighters: MutableSet<RangeHighlighter> = mutableSetOf()
private var timer: Timer? = null
fun highlightSneakRange(editor: Editor, range: TextRange) {
clearAllSneakHighlighters()
@ -267,19 +254,13 @@ internal class IdeaVimSneakExtension : VimExtension {
}
private fun setClearHighlightRangeTimer(highlighter: RangeHighlighter) {
stopExistingTimer()
timer = Timer(DEFAULT_HIGHLIGHT_DURATION_SNEAK) {
val timer = Timer(DEFAULT_HIGHLIGHT_DURATION_SNEAK) {
if (editor?.isDisposed != true) {
editor?.markupModel?.removeHighlighter(highlighter)
}
}
timer?.isRepeats = false
timer?.start()
}
fun stopExistingTimer() {
timer?.stop()
timer?.actionListeners?.forEach { it.actionPerformed(null) }
timer.isRepeats = false
timer.start()
}
private fun getHighlightTextAttributes() = TextAttributes(
@ -326,7 +307,7 @@ private fun VimExtension.mapToFunctionAndProvideKeys(
VimPlugin.getKey().hasmapto(it, injector.parser.parseKeys(commandFromOriginalPlugin(keys)))
}
val filteredFromModes = mappingModes.filterNotTo(HashSet()) {
injector.keyGroup.getKeyMapping(it).getLayer(fromKeys) != null
injector.keyGroup.hasmapfrom(it, fromKeys)
}
val doubleFiltered = mappingModes

View File

@ -47,11 +47,11 @@ import com.maddyhome.idea.vim.options.helpers.ClipboardOptionHelper
import com.maddyhome.idea.vim.put.PutData
import com.maddyhome.idea.vim.state.mode.Mode
import com.maddyhome.idea.vim.state.mode.SelectionType
import com.maddyhome.idea.vim.state.mode.returnTo
import com.maddyhome.idea.vim.state.mode.selectionType
import org.jetbrains.annotations.NonNls
import java.awt.event.KeyEvent
import javax.swing.KeyStroke
import com.maddyhome.idea.vim.state.mode.returnTo
/**
* Port of vim-surround.
@ -161,17 +161,17 @@ internal class VimSurroundExtension : VimExtension {
}
companion object {
fun change(editor: VimEditor, context: ExecutionContext, charFrom: Char, newSurround: SurroundPair?) {
fun change(editor: VimEditor, context: ExecutionContext, charFrom: Char, newSurround: Pair<String, String>?) {
editor.ij.runWithEveryCaretAndRestore { changeAtCaret(editor, context, charFrom, newSurround) }
}
fun changeAtCaret(editor: VimEditor, context: ExecutionContext, charFrom: Char, newSurround: SurroundPair?) {
fun changeAtCaret(editor: VimEditor, context: ExecutionContext, charFrom: Char, newSurround: Pair<String, String>?) {
// Save old register values for carets
val surroundings = editor.sortedCarets()
.map {
val oldValue: List<KeyStroke>? = getRegisterForCaret(REGISTER, it)
setRegisterForCaret(REGISTER, it, null)
SurroundingInfo(it, null, oldValue, false)
SurroundingInfo(it, null, oldValue)
}
// Delete surrounding's content
@ -187,25 +187,21 @@ internal class VimSurroundExtension : VimExtension {
}
val registerValue = getRegisterForCaret(REGISTER, it.caret)
val innerValue = if (registerValue.isNullOrEmpty()) emptyList() else registerValue
val innerValue = if (registerValue.isNullOrEmpty()) null else registerValue
it.innerText = innerValue
}
// Valid surroundings are only those that:
// - are validly wrapping with surround characters (i.e. parenthesis, brackets, tags, quotes, etc.);
// - or have non-empty inner text (e.g. when we are surrounding words: `csw"`)
if (currentSurrounding != null || innerValue.isNotEmpty()) {
it.isValidSurrounding = true
surroundings.forEach {
if (it.innerText == null && getRegisterForCaret(REGISTER, it.caret)?.isNotEmpty() == true) {
it.innerText = emptyList()
}
}
surroundings
.filter { it.isValidSurrounding } // we do nothing with carets that are not inside the surrounding
.filter { it.innerText != null } // we do nothing with carets that are not inside the surrounding
.map { surrounding ->
val innerValue = injector.parser.toPrintableString(surrounding.innerText!!)
val text = newSurround?.let {
val trimmedValue = if (newSurround.shouldTrim) innerValue.trim() else innerValue
it.first + trimmedValue + it.second
} ?: innerValue
val text = newSurround?.let { it.first + innerValue + it.second } ?: innerValue
val textData = PutData.TextData(text, SelectionType.CHARACTER_WISE, emptyList(), null)
val putData = PutData(textData, null, 1, insertTextBeforeCaret = true, rawIndent = true, caretAfterInsertedText = false)
@ -258,7 +254,7 @@ internal class VimSurroundExtension : VimExtension {
}
}
private data class SurroundingInfo(val caret: VimCaret, var innerText: List<KeyStroke>?, val oldRegisterContent: List<KeyStroke>?, var isValidSurrounding: Boolean) {
private data class SurroundingInfo(val caret: VimCaret, var innerText: List<KeyStroke>?, val oldRegisterContent: List<KeyStroke>?) {
fun restoreRegister() {
setRegisterForCaret(REGISTER, caret, oldRegisterContent)
}
@ -301,7 +297,7 @@ internal class VimSurroundExtension : VimExtension {
return true
}
private fun applyOnce(editor: Editor, change: VimChangeGroup, pair: SurroundPair, count: Int) {
private fun applyOnce(editor: Editor, change: VimChangeGroup, pair: Pair<String, String>, count: Int) {
// XXX: Will it work with line-wise or block-wise selections?
val primaryCaret = editor.caretModel.primaryCaret
val range = getSurroundRange(primaryCaret.vim)
@ -333,35 +329,33 @@ private const val REGISTER = '"'
private const val OPERATOR_FUNC = "SurroundOperatorFunc"
private val tagNameAndAttributesCapturePattern = "(\\S+)([^>]*)>".toPattern()
private data class SurroundPair(val first: String, val second: String, val shouldTrim: Boolean)
private val tagNameAndAttributesCapturePattern = "(\\S+)([^>]*)>".toPattern()
private val SURROUND_PAIRS = mapOf(
'b' to SurroundPair("(", ")", false),
'(' to SurroundPair("( ", " )", false),
')' to SurroundPair("(", ")", true),
'B' to SurroundPair("{", "}", false),
'{' to SurroundPair("{ ", " }", false),
'}' to SurroundPair("{", "}", true),
'r' to SurroundPair("[", "]", false),
'[' to SurroundPair("[ ", " ]", false),
']' to SurroundPair("[", "]", true),
'a' to SurroundPair("<", ">", false),
'>' to SurroundPair("<", ">", false),
's' to SurroundPair(" ", "", false),
'b' to ("(" to ")"),
'(' to ("( " to " )"),
')' to ("(" to ")"),
'B' to ("{" to "}"),
'{' to ("{ " to " }"),
'}' to ("{" to "}"),
'r' to ("[" to "]"),
'[' to ("[ " to " ]"),
']' to ("[" to "]"),
'a' to ("<" to ">"),
'>' to ("<" to ">"),
's' to (" " to ""),
)
private fun getSurroundPair(c: Char): SurroundPair? = if (c in SURROUND_PAIRS) {
private fun getSurroundPair(c: Char): Pair<String, String>? = if (c in SURROUND_PAIRS) {
SURROUND_PAIRS[c]
} else if (!c.isLetter()) {
val s = c.toString()
SurroundPair(s, s, false)
s to s
} else {
null
}
private fun inputTagPair(editor: Editor, context: DataContext): SurroundPair? {
private fun inputTagPair(editor: Editor, context: DataContext): Pair<String, String>? {
val tagInput = inputString(editor, context, "<", '>')
if (editor.vim.mode is Mode.CMD_LINE) {
editor.vim.mode = editor.vim.mode.returnTo()
@ -370,7 +364,7 @@ private fun inputTagPair(editor: Editor, context: DataContext): SurroundPair? {
return if (matcher.find()) {
val tagName = matcher.group(1)
val tagAttributes = matcher.group(2)
SurroundPair("<$tagName$tagAttributes>", "</$tagName>", false)
"<$tagName$tagAttributes>" to "</$tagName>"
} else {
null
}
@ -380,20 +374,16 @@ private fun inputFunctionName(
editor: Editor,
context: DataContext,
withInternalSpaces: Boolean,
): SurroundPair? {
): Pair<String, String>? {
val functionNameInput = inputString(editor, context, "function: ", null)
if (editor.vim.mode is Mode.CMD_LINE) {
editor.vim.mode = editor.vim.mode.returnTo()
}
if (functionNameInput.isEmpty()) return null
return if (withInternalSpaces) {
SurroundPair("$functionNameInput( ", " )", false)
} else {
SurroundPair("$functionNameInput(", ")", false)
}
return if (withInternalSpaces) "$functionNameInput( " to " )" else "$functionNameInput(" to ")"
}
private fun getOrInputPair(c: Char, editor: Editor, context: DataContext): SurroundPair? = when (c) {
private fun getOrInputPair(c: Char, editor: Editor, context: DataContext): Pair<String, String>? = when (c) {
'<', 't' -> inputTagPair(editor, context)
'f' -> inputFunctionName(editor, context, false)
'F' -> inputFunctionName(editor, context, true)
@ -412,7 +402,7 @@ private fun getChar(editor: Editor): Char {
return res
}
private fun performSurround(pair: SurroundPair, range: TextRange, caret: VimCaret, count: Int, tagsOnNewLines: Boolean = false) {
private fun performSurround(pair: Pair<String, String>, range: TextRange, caret: VimCaret, count: Int, tagsOnNewLines: Boolean = false) {
runWriteAction {
val editor = caret.editor
val change = VimPlugin.getChange()

View File

@ -36,12 +36,9 @@ import com.maddyhome.idea.vim.helper.inInsertMode
import com.maddyhome.idea.vim.key.KeyHandlerKeeper.Companion.getInstance
import com.maddyhome.idea.vim.listener.VimInsertListener
import com.maddyhome.idea.vim.newapi.IjVimCaret
import com.maddyhome.idea.vim.newapi.IjVimCopiedText
import com.maddyhome.idea.vim.newapi.IjVimEditor
import com.maddyhome.idea.vim.newapi.ij
import com.maddyhome.idea.vim.state.mode.Mode
import com.maddyhome.idea.vim.undo.VimKeyBasedUndoService
import com.maddyhome.idea.vim.undo.VimTimestampBasedUndoService
/**
* Provides all the insert/replace related functionality
@ -64,15 +61,9 @@ class ChangeGroup : VimChangeGroupBase() {
val editor = (vimEditor as IjVimEditor).editor
val ijContext = context.ij
val doc = vimEditor.editor.document
val undo = injector.undo
when (undo) {
is VimKeyBasedUndoService -> undo.setInsertNonMergeUndoKey()
is VimTimestampBasedUndoService -> {
val nanoTime = System.nanoTime()
vimEditor.forEachCaret { undo.startInsertSequence(it, it.offset, nanoTime) }
}
}
val nanoTime = System.nanoTime()
vimEditor.forEachCaret { undo.startInsertSequence(it, it.offset, nanoTime) }
CommandProcessor.getInstance().executeCommand(
editor.project, {
ApplicationManager.getApplication()
@ -145,10 +136,10 @@ class ChangeGroup : VimChangeGroupBase() {
// FIXME: Here we do selection, and it is not a good idea, because it updates primary selection in Linux
// FIXME: I'll leave here a dirty fix that restores primary selection, but it would be better to rewrite this method
var copiedText: IjVimCopiedText? = null
var primaryTextAndTransferableData: Pair<String, List<Any>?>? = null
try {
if (injector.registerGroup.isPrimaryRegisterSupported()) {
copiedText = injector.clipboardManager.getPrimaryContent(editor, context) as IjVimCopiedText
primaryTextAndTransferableData = injector.clipboardManager.getPrimaryTextAndTransferableData()
}
} catch (e: Exception) {
// FIXME: [isPrimaryRegisterSupported()] is not implemented perfectly, so there might be thrown an exception after trying to access the primary selection
@ -174,8 +165,12 @@ class ChangeGroup : VimChangeGroupBase() {
afterAction.invoke()
}
try {
if (copiedText != null) {
injector.clipboardManager.setPrimaryContent(editor, context, copiedText)
if (primaryTextAndTransferableData != null) {
injector.clipboardManager.setPrimaryText(
primaryTextAndTransferableData.first,
primaryTextAndTransferableData.first,
primaryTextAndTransferableData.second ?: emptyList()
)
}
} catch (e: Exception) {
// FIXME: [isPrimaryRegisterSupported()] is not implemented perfectly, so there might be thrown an exception after trying to access the primary selection

View File

@ -0,0 +1,83 @@
/*
* Copyright 2003-2023 The IdeaVim authors
*
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE.txt file or at
* https://opensource.org/licenses/MIT.
*/
package com.maddyhome.idea.vim.group;
import com.intellij.openapi.diagnostic.Logger;
import com.maddyhome.idea.vim.api.VimDigraphGroupBase;
import com.maddyhome.idea.vim.api.VimEditor;
import com.maddyhome.idea.vim.api.VimOutputPanel;
import com.maddyhome.idea.vim.ex.ExOutputModel;
import com.maddyhome.idea.vim.helper.EditorHelper;
import com.maddyhome.idea.vim.newapi.IjVimEditor;
import org.jetbrains.annotations.NotNull;
import static com.maddyhome.idea.vim.api.VimInjectorKt.injector;
public class DigraphGroup extends VimDigraphGroupBase {
public void showDigraphs(@NotNull VimEditor editor) {
int width = EditorHelper.getApproximateScreenWidth(((IjVimEditor) editor).getEditor());
if (width < 10) {
width = 80;
}
int colCount = width / 12;
int height = (int)Math.ceil((double) getDigraphs().size() / (double)colCount);
if (logger.isDebugEnabled()) {
logger.debug("width=" + width);
logger.debug("colCount=" + colCount);
logger.debug("height=" + height);
}
StringBuilder res = new StringBuilder();
int cnt = 0;
for (Character code : getKeys().keySet()) {
String key = getKeys().get(code);
res.append(key);
res.append(' ');
if (code < 32) {
res.append('^');
res.append((char)(code + '@'));
}
else if (code >= 128 && code <= 159) {
res.append('~');
res.append((char)(code - 128 + '@'));
}
else {
res.append(code);
res.append(' ');
}
res.append(' ');
if (code < 0x1000) {
res.append('0');
}
if (code < 0x100) {
res.append('0');
}
if (code < 0x10) {
res.append('0');
}
res.append(Integer.toHexString(code));
res.append(" ");
cnt++;
if (cnt == colCount) {
res.append('\n');
cnt = 0;
}
}
VimOutputPanel output = injector.getOutputPanel().getOrCreate(editor, injector.getExecutionContextManager().getEditorExecutionContext(editor));
output.addText(res.toString(), true );
output.show();
}
private static final Logger logger = Logger.getInstance(DigraphGroup.class.getName());
}

View File

@ -42,6 +42,7 @@ import com.maddyhome.idea.vim.newapi.IjEditorExecutionContext
import com.maddyhome.idea.vim.newapi.IjVimEditor
import com.maddyhome.idea.vim.newapi.execute
import com.maddyhome.idea.vim.newapi.globalIjOptions
import com.maddyhome.idea.vim.state.VimStateMachine.Companion.getInstance
import com.maddyhome.idea.vim.state.mode.Mode.VISUAL
import java.io.File
import java.util.*

View File

@ -8,6 +8,7 @@
package com.maddyhome.idea.vim.group;
import com.google.common.collect.ImmutableList;
import com.intellij.codeInsight.lookup.impl.LookupImpl;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.actionSystem.ex.ActionManagerEx;
@ -16,16 +17,18 @@ import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.components.PersistentStateComponent;
import com.intellij.openapi.components.State;
import com.intellij.openapi.components.Storage;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.keymap.Keymap;
import com.intellij.openapi.keymap.KeymapManager;
import com.intellij.openapi.keymap.ex.KeymapManagerEx;
import com.intellij.util.containers.MultiMap;
import com.maddyhome.idea.vim.EventFacade;
import com.maddyhome.idea.vim.VimPlugin;
import com.maddyhome.idea.vim.action.VimShortcutKeyAction;
import com.maddyhome.idea.vim.action.change.LazyVimCommand;
import com.maddyhome.idea.vim.api.*;
import com.maddyhome.idea.vim.command.MappingMode;
import com.maddyhome.idea.vim.ex.ExOutputModel;
import com.maddyhome.idea.vim.key.*;
import com.maddyhome.idea.vim.newapi.IjNativeAction;
import com.maddyhome.idea.vim.newapi.IjVimEditor;
@ -55,6 +58,8 @@ public class KeyGroup extends VimKeyGroupBase implements PersistentStateComponen
private static final @NonNls String OWNER_ATTRIBUTE = "owner";
private static final String TEXT_ELEMENT = "text";
private static final Logger logger = Logger.getInstance(KeyGroup.class);
public void registerRequiredShortcutKeys(@NotNull VimEditor editor) {
EventFacade.getInstance()
.registerCustomShortcutSet(VimShortcutKeyAction.getInstance(), toShortcutSet(getRequiredShortcutKeys()),
@ -194,7 +199,8 @@ public class KeyGroup extends VimKeyGroupBase implements PersistentStateComponen
registerRequiredShortcut(keyStrokes, MappingOwner.IdeaVim.System.INSTANCE);
for (MappingMode mappingMode : command.getModes()) {
getBuiltinCommandsTrie(mappingMode).add(keyStrokes, command);
Node<LazyVimCommand> node = getKeyRoot(mappingMode);
NodesKt.addLeafs(node, keyStrokes, command);
}
}
}
@ -219,79 +225,53 @@ public class KeyGroup extends VimKeyGroupBase implements PersistentStateComponen
return new CustomShortcutSet(shortcuts.toArray(new Shortcut[0]));
}
private static @NotNull List<Pair<Set<MappingMode>, MappingInfo>> getKeyMappingRows(@NotNull Set<? extends MappingMode> modes,
@NotNull List<? extends KeyStroke> prefix) {
// Some map commands set a mapping for more than one mode (e.g. `map` sets for Normal, Visual, Select and
// Op-pending). Vim treats this as a single mapping, and when listing all maps only lists it once, with the
// appropriate mode indicator(s) in the first column (NVO is a space char). If the lhs mapping is changed or cleared
// for one of the modes, the original mapping is still a single map for the remaining modes, and the indicator
// changes. E.g. `map foo bar` followed by `sunmap foo` would result in `nox foo bar` in the output to `map`.
// Vim doesn't do automatic grouping - `nmap foo bar` followed by `omap foo bar` and `vmap foo bar` would result in
// 3 lines in the output to `map` - one for `n`, one for `o` and one for `v`.
// We store mappings separately per mode (to simplify lookup, especially when matching prefixes), but want to have
// the same behaviour as Vim in map output. So we store the original modes with the mapping and check they're still
// valid as we collect output
final List<Pair<Set<MappingMode>, MappingInfo>> rows = new ArrayList<>();
final MultiMap<List<? extends KeyStroke>, Set<MappingMode>> multiModeMappings = MultiMap.create();
final List<KeyStroke> fromKeys = new ArrayList<>();
private static @NotNull List<Pair<EnumSet<MappingMode>, MappingInfo>> getKeyMappingRows(@NotNull Set<? extends MappingMode> modes) {
final Map<ImmutableList<KeyStroke>, EnumSet<MappingMode>> actualModes = new HashMap<>();
for (MappingMode mode : modes) {
final KeyMapping mapping = VimPlugin.getKey().getKeyMapping(mode);
final Iterator<KeyMappingEntry> iterator = mapping.getAll(prefix).iterator();
while (iterator.hasNext()) {
final KeyMappingEntry entry = iterator.next();
final MappingInfo mappingInfo = entry.getMappingInfo();
final Set<@NotNull MappingMode> originalModes = mappingInfo.getOriginalModes();
if (originalModes.size() == 1) {
rows.add(new Pair<>(originalModes, mappingInfo));
for (List<? extends KeyStroke> fromKeys : mapping) {
final ImmutableList<KeyStroke> key = ImmutableList.copyOf(fromKeys);
final EnumSet<MappingMode> value = actualModes.get(key);
final EnumSet<MappingMode> newValue;
if (value != null) {
newValue = value.clone();
newValue.add(mode);
}
else {
entry.collectPath(fromKeys);
if (!multiModeMappings.get(fromKeys).contains(originalModes)) {
multiModeMappings.putValue(new ArrayList<>(fromKeys), originalModes);
rows.add(new Pair<>(getModesForMapping(fromKeys, originalModes), mappingInfo));
}
newValue = EnumSet.of(mode);
}
actualModes.put(key, newValue);
}
}
final List<Pair<EnumSet<MappingMode>, MappingInfo>> rows = new ArrayList<>();
for (Map.Entry<ImmutableList<KeyStroke>, EnumSet<MappingMode>> entry : actualModes.entrySet()) {
final ArrayList<KeyStroke> fromKeys = new ArrayList<>(entry.getKey());
final EnumSet<MappingMode> mappingModes = entry.getValue();
if (!mappingModes.isEmpty()) {
final MappingMode mode = mappingModes.iterator().next();
final KeyMapping mapping = VimPlugin.getKey().getKeyMapping(mode);
final MappingInfo mappingInfo = mapping.get(fromKeys);
if (mappingInfo != null) {
rows.add(new Pair<>(mappingModes, mappingInfo));
}
}
}
rows.sort(Comparator.comparing(Pair<Set<MappingMode>, MappingInfo>::getSecond));
rows.sort(Comparator.comparing(Pair<EnumSet<MappingMode>, MappingInfo>::getSecond));
return rows;
}
private static @NotNull Set<MappingMode> getModesForMapping(@NotNull List<? extends KeyStroke> keyStrokes,
@NotNull Set<MappingMode> originalMappingModes) {
final Set<MappingMode> actualModes = EnumSet.noneOf(MappingMode.class);
for (MappingMode mode : originalMappingModes) {
final MappingInfo mappingInfo = VimPlugin.getKey().getKeyMapping(mode).get(keyStrokes);
if (mappingInfo != null && mappingInfo.getOriginalModes() == originalMappingModes) {
actualModes.add(mode);
}
}
return actualModes;
}
private static @NotNull @NonNls String getModesStringCode(@NotNull Set<MappingMode> modes) {
if (modes.equals(MappingMode.IC)) return "!";
if (modes.equals(MappingMode.NVO)) return " ";
if (modes.equals(MappingMode.C)) return "c";
if (modes.equals(MappingMode.I)) return "i";
//if (modes.equals(MappingMode.L)) return "l";
// The following modes are concatenated
String mode = "";
if (modes.containsAll(MappingMode.N)) mode += "n";
if (modes.containsAll(MappingMode.O)) mode += "o";
if (modes.containsAll(MappingMode.V)) {
mode += "v";
if (modes.equals(MappingMode.NVO)) {
return "";
}
else {
if (modes.containsAll(MappingMode.X)) mode += "x";
if (modes.containsAll(MappingMode.S)) mode += "s";
else if (modes.contains(MappingMode.INSERT)) {
return "i";
}
return mode;
else if (modes.contains(MappingMode.NORMAL)) {
return "n";
}
// TODO: Add more codes
return "";
}
private @NotNull List<AnAction> getActions(@NotNull Component component, @NotNull KeyStroke keyStroke) {
@ -355,20 +335,20 @@ public class KeyGroup extends VimKeyGroupBase implements PersistentStateComponen
}
@Override
public boolean showKeyMappings(@NotNull Set<? extends MappingMode> modes, @NotNull List<? extends KeyStroke> prefix, @NotNull VimEditor editor) {
List<Pair<Set<MappingMode>, MappingInfo>> rows = getKeyMappingRows(modes, prefix);
public boolean showKeyMappings(@NotNull Set<? extends MappingMode> modes, @NotNull VimEditor editor) {
List<Pair<EnumSet<MappingMode>, MappingInfo>> rows = getKeyMappingRows(modes);
final StringBuilder builder = new StringBuilder();
for (Pair<Set<MappingMode>, MappingInfo> row : rows) {
for (Pair<EnumSet<MappingMode>, MappingInfo> row : rows) {
MappingInfo mappingInfo = row.getSecond();
builder.append(StringsKt.padEnd(getModesStringCode(row.getFirst()), 3, ' '));
builder.append(StringsKt.padEnd(VimInjectorKt.getInjector().getParser().toKeyNotation(mappingInfo.getFromKeys()) + " ", 12, ' '));
builder.append(mappingInfo.isRecursive() ? " " : "*"); // Or `&` if script-local mappings being recursive
builder.append(" "); // Should be `@` if it's a buffer-local mapping
builder.append(StringsKt.padEnd(getModesStringCode(row.getFirst()), 2, ' '));
builder.append(" ");
builder.append(StringsKt.padEnd(VimInjectorKt.getInjector().getParser().toKeyNotation(mappingInfo.getFromKeys()), 11, ' '));
builder.append(" ");
builder.append(mappingInfo.isRecursive() ? " " : "*");
builder.append(" ");
builder.append(mappingInfo.getPresentableString());
builder.append("\n");
}
VimOutputPanel outputPanel = injector.getOutputPanel().getOrCreate(editor, injector.getExecutionContextManager().getEditorExecutionContext(editor));
outputPanel.addText(builder.toString(), true);
outputPanel.show();

View File

@ -12,7 +12,6 @@ import com.intellij.application.options.CodeStyle
import com.intellij.codeStyle.AbstractConvertLineSeparatorsAction
import com.intellij.openapi.Disposable
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.editor.EditorKind
import com.intellij.openapi.editor.EditorSettings.LineNumerationType
import com.intellij.openapi.editor.ScrollPositionCalculator
@ -20,6 +19,8 @@ import com.intellij.openapi.editor.ex.EditorEx
import com.intellij.openapi.editor.ex.EditorSettingsExternalizable
import com.intellij.openapi.editor.impl.softwrap.SoftWrapAppliancePlaces
import com.intellij.openapi.fileEditor.FileDocumentManager
import com.intellij.openapi.fileEditor.FileEditorManagerEvent
import com.intellij.openapi.fileEditor.TextEditor
import com.intellij.openapi.fileEditor.impl.LoadTextUtil
import com.intellij.openapi.fileEditor.impl.text.TextEditorImpl
import com.intellij.openapi.project.Project
@ -157,24 +158,25 @@ internal class OptionGroup : VimOptionGroupBase(), IjVimOptionGroup, InternalOpt
}
companion object {
fun editorReleased(editor: Editor) {
// Vim always has at least one window; it's not possible to close it. Editing a new file will open a new buffer in
// the current window, or it's possible to split the current buffer into a new window, or open a new buffer in a
// new window. This is important for us because when Vim opens a new window, the new window's local options are
// copied from the current window.
// In detail: splitting the current window gets a complete copy of local and per-window global option values.
// Editing a new file will split the current window and then edit the new buffer in-place.
// IntelliJ does not always have an open window. It would be weird to close the last editor tab, and then open
// the next tab with different options - the user would expect the editor to look like the last one did.
// Therefore, we have a dummy "fallback" window that captures the options of the last closed editor. When opening
// an editor and there are no currently open editors, we use the fallback window to initialise the new window.
// This callback tracks when editors are closed, and if the last editor in a project is being closed, updates the
// fallback window's options.
val project = editor.project ?: return
if (!injector.editorGroup.getEditorsRaw()
.any { it.ij != editor && it.ij.project === project && it.ij.editorKind == EditorKind.MAIN_EDITOR }
) {
(VimPlugin.getOptionGroup() as OptionGroup).updateFallbackWindow(injector.fallbackWindow, editor.vim)
fun fileEditorManagerSelectionChangedCallback(event: FileEditorManagerEvent) {
// Vim only has one window, and it's not possible to close it. This means that editing a new file will always
// reuse an existing window (opening a new window will always open from an existing window). More importantly,
// this means that any newly edited file will always get up-to-date local-to-window options. A new window is based
// on the opening window (treated as split then edit, so copy local + per-window "global" window values, then
// apply the per-window "global" values) and an edit reapplies the per-window "global" values.
// If we close all windows, and open a new one, we can only use the per-window "global" values from the fallback
// window, but this is only initialised when we first read `~/.ideavimrc` during startup. Vim would use the values
// from the current window, so to simulate this, we should update the fallback window with the values from the
// window that was selected at the time that the last window was closed.
// Unfortunately, we can't reliably know if a closing editor is the selected editor. Instead, we rely on selection
// change events. If an editor is losing selection and there is no new selection, we can assume this means that
// the last editor has been closed, and use the closed editor to update the fallback window
//
// XXX: event.oldEditor will must probably return a disposed editor. So, it should be treated with care
if (event.newEditor == null) {
(event.oldEditor as? TextEditor)?.editor?.let {
(VimPlugin.getOptionGroup() as OptionGroup).updateFallbackWindow(injector.fallbackWindow, it.vim)
}
}
}
}

View File

@ -14,6 +14,7 @@ import com.intellij.openapi.components.State;
import com.intellij.openapi.components.Storage;
import com.intellij.openapi.diagnostic.Logger;
import com.maddyhome.idea.vim.VimPlugin;
import com.maddyhome.idea.vim.api.VimInjectorKt;
import com.maddyhome.idea.vim.newapi.IjVimInjectorKt;
import com.maddyhome.idea.vim.register.Register;
import com.maddyhome.idea.vim.register.VimRegisterGroupBase;

View File

@ -7,6 +7,7 @@
*/
package com.maddyhome.idea.vim.group
import com.intellij.codeWithMe.ClientId
import com.intellij.ide.bookmark.Bookmark
import com.intellij.ide.bookmark.BookmarkGroup
import com.intellij.ide.bookmark.BookmarksListener

View File

@ -51,8 +51,6 @@ import com.maddyhome.idea.vim.state.mode.SelectionType
import com.maddyhome.idea.vim.state.mode.isBlock
import com.maddyhome.idea.vim.state.mode.isChar
import com.maddyhome.idea.vim.state.mode.isLine
import com.maddyhome.idea.vim.undo.VimKeyBasedUndoService
import com.maddyhome.idea.vim.undo.VimTimestampBasedUndoService
import java.awt.datatransfer.DataFlavor
@Service
@ -87,15 +85,9 @@ internal class PutGroup : VimPutBase() {
val context = vimContext.context as DataContext
val carets: MutableMap<Caret, RangeMarker> = mutableMapOf()
if (injector.vimState.mode is Mode.INSERT) {
val nanoTime = System.nanoTime()
val undo = injector.undo
when (undo) {
is VimKeyBasedUndoService -> undo.setInsertNonMergeUndoKey()
is VimTimestampBasedUndoService -> {
vimEditor.forEachCaret { undo.startInsertSequence(it, it.offset, nanoTime) }
}
}
val nanoTime = System.nanoTime()
vimEditor.forEachCaret { undo.startInsertSequence(it, it.offset, nanoTime) }
}
EditorHelper.getOrderedCaretsList(editor).forEach { caret ->
val startOffset =

View File

@ -8,7 +8,6 @@
package com.maddyhome.idea.vim.group.visual
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.diagnostic.Logger
import com.intellij.openapi.diagnostic.trace
import com.intellij.openapi.editor.Editor
@ -16,8 +15,6 @@ import com.maddyhome.idea.vim.KeyHandler
import com.maddyhome.idea.vim.VimPlugin
import com.maddyhome.idea.vim.api.injector
import com.maddyhome.idea.vim.api.options
import com.maddyhome.idea.vim.group.visual.IdeaSelectionControl.controlNonVimSelectionChange
import com.maddyhome.idea.vim.group.visual.IdeaSelectionControl.predictMode
import com.maddyhome.idea.vim.helper.exitSelectMode
import com.maddyhome.idea.vim.helper.exitVisualMode
import com.maddyhome.idea.vim.helper.hasVisualSelection
@ -66,15 +63,12 @@ internal object IdeaSelectionControl {
// - There was no selection and now it is
// - There was a selection and now it doesn't exist
// - There was a selection and now it exists as well (transforming char selection to line selection, for example)
val hasSelection = ApplicationManager.getApplication().runReadAction<Boolean> {
editor.selectionModel.hasSelection(true)
}
if (initialMode?.hasVisualSelection == false && !hasSelection) {
if (initialMode?.hasVisualSelection == false && !editor.selectionModel.hasSelection(true)) {
logger.trace { "Exiting without selection adjusting" }
return@singleTask
}
if (hasSelection) {
if (editor.selectionModel.hasSelection(true)) {
if (editor.vim.inCommandLineMode && editor.vim.mode.returnTo().hasVisualSelection) {
logger.trace { "Modifying selection while in Command-line mode, most likely incsearch" }
return@singleTask

View File

@ -9,6 +9,8 @@
package com.maddyhome.idea.vim.group.visual
import com.maddyhome.idea.vim.api.injector
import com.maddyhome.idea.vim.group.visual.VimVisualTimer.mode
import com.maddyhome.idea.vim.group.visual.VimVisualTimer.singleTask
import com.maddyhome.idea.vim.newapi.globalIjOptions
import com.maddyhome.idea.vim.state.mode.Mode
import java.awt.event.ActionEvent

View File

@ -183,7 +183,6 @@ internal abstract class OctopusHandler(private val nextHandler: EditorActionHand
* - App code - set handler after
* - Template - doesn't intersect with enter anymore
* - rd.client.editor.enter - set handler before. Otherwise, rider will add new line on enter even in normal mode
* - inline.completion.enter - set handler before. Otherwise, AI completion is not invoked on enter.
*
* This rule is disabled due to VIM-3124
* - before terminalEnter - not necessary, but terminalEnter causes "file is read-only" tooltip for readonly files VIM-3122

View File

@ -157,19 +157,6 @@ public class EditorHelper {
return (int)(getVisibleArea(editor).width / getPlainSpaceWidthFloat(editor));
}
/**
* Gets the number of characters that can be fit inside the output panel for an editor.
* <p>
* This will be greater than the approximate screen width as it also includes any gutter components in the editor.
* </p>
*
* @param editor The editor
* @return The approximate number of columns that can fit in the output panel
*/
public static int getApproximateOutputPanelWidth(final @NotNull Editor editor) {
return (int)(editor.getComponent().getWidth() / getPlainSpaceWidthFloat(editor));
}
/**
* Gets the width of the space character in the editor's plain font as a float.
* <p>
@ -286,7 +273,7 @@ public class EditorHelper {
// Scroll the given visual line to the caret location, but do not scroll down passed the end of file, or the current
// virtual space at the bottom of the screen
final @NotNull VimEditor editor1 = new IjVimEditor(editor);
@NotNull final VimEditor editor1 = new IjVimEditor(editor);
final int lastVisualLine = EngineEditorHelperKt.getVisualLineCount(editor1) - 1;
final int yBottomLineOffset = max(getOffsetToScrollVisualLineToBottomOfScreen(editor, lastVisualLine), visibleArea.y);
scrollVertically(editor, min(yVisualLine - caretScreenOffset - inlayOffset, yBottomLineOffset));
@ -338,7 +325,7 @@ public class EditorHelper {
final int lineHeight = editor.getLineHeight();
final int offset = y - ((screenHeight - lineHeight) / lineHeight / 2 * lineHeight);
final @NotNull VimEditor editor1 = new IjVimEditor(editor);
@NotNull final VimEditor editor1 = new IjVimEditor(editor);
final int lastVisualLine = EngineEditorHelperKt.getVisualLineCount(editor1) + editor.getSettings().getAdditionalLinesCount();
final int offsetForLastLineAtBottom = getOffsetToScrollVisualLineToBottomOfScreen(editor, lastVisualLine);
@ -392,7 +379,7 @@ public class EditorHelper {
return 0;
}
private static int getHorizontalScrollbarHeight(final @NotNull Editor editor) {
private static int getHorizontalScrollbarHeight(@NotNull final Editor editor) {
// Horizontal scrollbars on macOS are either transparent AND auto-hide, so we don't need to worry about obscured
// text, or always visible, opaque and outside the content area, so we don't need to adjust for them
// Transparent scrollbars on Windows and Linux are overlays on the editor content area, and always visible. That
@ -475,7 +462,7 @@ public class EditorHelper {
*/
public static Pair<Boolean, Integer> scrollFullPageDown(final @NotNull Editor editor, int pages) {
final Rectangle visibleArea = getVisibleArea(editor);
final @NotNull VimEditor editor2 = new IjVimEditor(editor);
@NotNull final VimEditor editor2 = new IjVimEditor(editor);
final int lastVisualLine = EngineEditorHelperKt.getVisualLineCount(editor2) - 1;
int y = visibleArea.y + visibleArea.height;
@ -493,7 +480,7 @@ public class EditorHelper {
caretVisualLine = lastVisualLine;
}
else {
final @NotNull VimEditor editor1 = new IjVimEditor(editor);
@NotNull final VimEditor editor1 = new IjVimEditor(editor);
caretVisualLine = EngineEditorHelperKt.getVisualLineCount(editor1) - 1;
completed = false;
}
@ -528,7 +515,7 @@ public class EditorHelper {
public static Pair<Boolean, Integer> scrollFullPageUp(final @NotNull Editor editor, int pages) {
final Rectangle visibleArea = getVisibleArea(editor);
final int lineHeight = editor.getLineHeight();
final @NotNull VimEditor editor1 = new IjVimEditor(editor);
@NotNull final VimEditor editor1 = new IjVimEditor(editor);
final int lastVisualLine = EngineEditorHelperKt.getVisualLineCount(editor1) - 1;
int y = visibleArea.y;

View File

@ -75,7 +75,7 @@ internal class IjActionExecutor : VimActionExecutor {
val applicationEx = ApplicationManagerEx.getApplicationEx()
if (ProgressIndicatorUtils.isWriteActionRunningOrPending(applicationEx)) {
// This is needed for VIM-3376 and it should turn into error at soeme moment
thisLogger().warn("Actions cannot be updated when write-action is running or pending")
thisLogger().warn(RuntimeException("Actions cannot be updated when write-action is running or pending", ))
}
val ijAction = (action as IjNativeAction).action

View File

@ -13,6 +13,7 @@ import com.intellij.openapi.editor.ReadOnlyFragmentModificationException
import com.intellij.openapi.editor.VisualPosition
import com.intellij.openapi.editor.actionSystem.EditorActionManager
import com.intellij.openapi.editor.ex.util.EditorUtil
import com.maddyhome.idea.vim.api.EngineEditorHelper
import com.maddyhome.idea.vim.api.EngineEditorHelperBase
import com.maddyhome.idea.vim.api.VimEditor
import com.maddyhome.idea.vim.api.VimRangeMarker
@ -41,10 +42,6 @@ internal class IjEditorHelper : EngineEditorHelperBase() {
return EditorHelper.getApproximateScreenWidth(editor.ij)
}
override fun getApproximateOutputPanelWidth(editor: VimEditor): Int {
return EditorHelper.getApproximateOutputPanelWidth(editor.ij)
}
override fun handleWithReadonlyFragmentModificationHandler(editor: VimEditor, exception: Exception) {
return EditorActionManager.getInstance()
.getReadonlyFragmentModificationHandler(editor.ij.document)

View File

@ -29,6 +29,7 @@ import com.maddyhome.idea.vim.helper.EditorHelper.scrollVisualLineToBottomOfScre
import com.maddyhome.idea.vim.helper.EditorHelper.scrollVisualLineToMiddleOfScreen
import com.maddyhome.idea.vim.helper.EditorHelper.scrollVisualLineToTopOfScreen
import com.maddyhome.idea.vim.newapi.vim
import com.maddyhome.idea.vim.state.VimStateMachine
import kotlin.math.max
import kotlin.math.min
import kotlin.math.roundToInt

View File

@ -102,8 +102,7 @@ private fun updateSearchHighlights(
// Update highlights in all visible editors. We update non-visible editors when they get focus.
// Note that this now includes all editors - main, diff windows, even toolwindows like the Commit editor and consoles
val editors = injector.editorGroup.getEditors().filter {
(injector.application.isUnitTest() || it.ij.component.isShowing)
&& (currentEditor == null || it.projectId == currentEditor.projectId)
injector.application.isUnitTest() || it.ij.component.isShowing
}
editors.forEach {

View File

@ -14,9 +14,7 @@ import com.intellij.openapi.command.CommandProcessor
import com.intellij.openapi.command.undo.UndoManager
import com.intellij.openapi.components.Service
import com.intellij.openapi.diagnostic.logger
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.fileEditor.TextEditor
import com.intellij.openapi.fileEditor.TextEditorWithPreview
import com.intellij.openapi.fileEditor.impl.text.TextEditorProvider
import com.intellij.openapi.project.Project
import com.intellij.openapi.util.registry.Registry
@ -32,13 +30,13 @@ import com.maddyhome.idea.vim.newapi.globalIjOptions
import com.maddyhome.idea.vim.newapi.ij
import com.maddyhome.idea.vim.state.mode.SelectionType
import com.maddyhome.idea.vim.state.mode.inVisualMode
import com.maddyhome.idea.vim.undo.VimTimestampBasedUndoService
import com.maddyhome.idea.vim.undo.UndoRedoBase
/**
* @author oleg
*/
@Service
internal class UndoRedoHelper : VimTimestampBasedUndoService {
internal class UndoRedoHelper : UndoRedoBase() {
companion object {
private val logger = logger<UndoRedoHelper>()
}
@ -46,13 +44,13 @@ internal class UndoRedoHelper : VimTimestampBasedUndoService {
override fun undo(editor: VimEditor, context: ExecutionContext): Boolean {
val ijContext = context.context as DataContext
val project = PlatformDataKeys.PROJECT.getData(ijContext) ?: return false
val textEditor = getTextEditor(editor.ij)
val fileEditor = TextEditorProvider.getInstance().getTextEditor(editor.ij)
val undoManager = UndoManager.getInstance(project)
if (undoManager.isUndoAvailable(textEditor)) {
if (undoManager.isUndoAvailable(fileEditor)) {
val scrollingModel = editor.getScrollingModel()
scrollingModel.accumulateViewportChanges()
performUndo(editor, undoManager, textEditor)
performUndo(editor, undoManager, fileEditor)
scrollingModel.flushViewportChanges()
@ -61,15 +59,6 @@ internal class UndoRedoHelper : VimTimestampBasedUndoService {
return false
}
private fun getTextEditor(editor: Editor): TextEditor {
// If the Editor is hosted in a TextEditor with a preview, then TextEditorProvider will return a TextEditor for the
// hosted instance, not for the main editor that also contains the preview. If we pass the inner TextEditor to the
// UndoManager, it doesn't correctly restore state. Specifically, the change is undone/redone, but the caret is not
// moved. See VIM-3671.
val currentTextEditor = TextEditorProvider.getInstance().getTextEditor(editor)
return TextEditorWithPreview.getParentSplitEditor(currentTextEditor) as? TextEditor ?: currentTextEditor
}
private fun performUndo(
editor: VimEditor,
undoManager: UndoManager,
@ -117,10 +106,10 @@ internal class UndoRedoHelper : VimTimestampBasedUndoService {
override fun redo(editor: VimEditor, context: ExecutionContext): Boolean {
val ijContext = context.context as DataContext
val project = PlatformDataKeys.PROJECT.getData(ijContext) ?: return false
val textEditor = getTextEditor(editor.ij)
val fileEditor = TextEditorProvider.getInstance().getTextEditor(editor.ij)
val undoManager = UndoManager.getInstance(project)
if (undoManager.isRedoAvailable(textEditor)) {
performRedo(undoManager, textEditor, editor)
if (undoManager.isRedoAvailable(fileEditor)) {
performRedo(undoManager, fileEditor, editor)
return true
}

View File

@ -21,11 +21,12 @@ import com.intellij.openapi.util.UserDataHolder
import com.maddyhome.idea.vim.api.LocalMarkStorage
import com.maddyhome.idea.vim.api.SelectionInfo
import com.maddyhome.idea.vim.common.InsertSequence
import com.maddyhome.idea.vim.common.VimEditorReplaceMask
import com.maddyhome.idea.vim.ex.ExOutputModel
import com.maddyhome.idea.vim.group.visual.VisualChange
import com.maddyhome.idea.vim.group.visual.vimLeadSelectionOffset
import com.maddyhome.idea.vim.common.VimEditorReplaceMask
import com.maddyhome.idea.vim.newapi.vim
import com.maddyhome.idea.vim.state.VimStateMachine
import com.maddyhome.idea.vim.state.mode.Mode
import com.maddyhome.idea.vim.state.mode.SelectionType
import com.maddyhome.idea.vim.ui.ExOutputPanel

View File

@ -0,0 +1,15 @@
/*
* Copyright 2003-2023 The IdeaVim authors
*
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE.txt file or at
* https://opensource.org/licenses/MIT.
*/
package com.maddyhome.idea.vim.key
import com.maddyhome.idea.vim.api.injector
internal fun <T> Node<T>.addLeafs(keys: String, actionHolder: T) {
addLeafs(injector.parser.parseKeys(keys), actionHolder)
}

View File

@ -16,6 +16,7 @@ import com.intellij.openapi.diagnostic.Logger
import com.intellij.openapi.diagnostic.trace
import com.intellij.openapi.editor.Caret
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.editor.EditorFactory
import com.intellij.openapi.editor.EditorKind
import com.intellij.openapi.editor.actionSystem.TypedAction
import com.intellij.openapi.editor.event.CaretEvent
@ -31,10 +32,10 @@ import com.intellij.openapi.editor.event.EditorMouseMotionListener
import com.intellij.openapi.editor.event.SelectionEvent
import com.intellij.openapi.editor.event.SelectionListener
import com.intellij.openapi.editor.ex.DocumentEx
import com.intellij.openapi.editor.ex.EditorEx
import com.intellij.openapi.editor.ex.EditorEventMulticasterEx
import com.intellij.openapi.editor.ex.FocusChangeListener
import com.intellij.openapi.editor.impl.EditorComponentImpl
import com.intellij.openapi.fileEditor.FileEditor
import com.intellij.openapi.editor.impl.EditorImpl
import com.intellij.openapi.fileEditor.FileEditorManager
import com.intellij.openapi.fileEditor.FileEditorManagerEvent
import com.intellij.openapi.fileEditor.FileEditorManagerListener
@ -44,15 +45,15 @@ import com.intellij.openapi.fileEditor.ex.FileEditorManagerEx
import com.intellij.openapi.fileEditor.ex.FileEditorWithProvider
import com.intellij.openapi.fileEditor.impl.EditorComposite
import com.intellij.openapi.fileEditor.impl.EditorWindow
import com.intellij.openapi.observable.util.addKeyListener
import com.intellij.openapi.project.Project
import com.intellij.openapi.project.ProjectManager
import com.intellij.openapi.rd.createLifetime
import com.intellij.openapi.rd.createNestedDisposable
import com.intellij.openapi.util.Disposer
import com.intellij.openapi.util.Key
import com.intellij.openapi.util.removeUserData
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.util.ExceptionUtil
import com.intellij.util.SlowOperations
import com.jetbrains.rd.util.lifetime.Lifetime
import com.maddyhome.idea.vim.EventFacade
import com.maddyhome.idea.vim.KeyHandler
import com.maddyhome.idea.vim.VimKeyListener
@ -105,11 +106,8 @@ import com.maddyhome.idea.vim.ui.widgets.macro.MacroWidgetListener
import com.maddyhome.idea.vim.ui.widgets.macro.macroWidgetOptionListener
import com.maddyhome.idea.vim.ui.widgets.mode.listeners.ModeWidgetListener
import com.maddyhome.idea.vim.ui.widgets.mode.modeWidgetOptionListener
import org.jetbrains.annotations.TestOnly
import java.awt.event.MouseAdapter
import java.awt.event.MouseEvent
import java.lang.ref.WeakReference
import java.util.*
import javax.swing.SwingUtilities
/**
@ -131,15 +129,23 @@ import javax.swing.SwingUtilities
* Make sure the selected editor isn't the new editor, which can happen if there are no other editors open.
*/
private fun getOpeningEditor(newEditor: Editor) = newEditor.project?.let { project ->
// We can't rely on FileEditorManager.selectedTextEditor because we're trying to retrieve the selected text editor
// while creating a text editor that is about to become the selected text editor.
// This worked fine for 2024.2, but internal changes for 2024.3 broke things. It appears that the currently selected
// text editor is reset to null while the soon-to-be-selected text editor is being created. We therefore track the
// last selected editor manually.
// Note that if we ever switch back to FileEditorManager.selectedTextEditor, be careful of recursion, because the
// actual editor might be created on-demand, which would notify our initialisation method, which would call us...
VimListenerManager.VimLastSelectedEditorTracker.getLastSelectedEditor(project)?.takeUnless { it == newEditor }
// Some TextEditor implementations create a dummy Editor instance on demand, e.g., while downloading a file to edit
// (see BaseRemoteFileEditor). This can cause recursion if the newly opened/created TextEditor is also the currently
// selected TextEditor, because we will be notified of the new dummy Editor before it has finished initialisation, and
// try to get its opening editor, causing a new dummy Editor to be created and notifications sent, and so on.
// This was reported for 232 and 233 (see VIM-3066), but I can't recreate in 241. The callstack looks different, now
// using coroutines, so it's possible the deadlock has been broken. However, it's sensible to leave the recursion
// guard in.
if (openingEditorRecursionGuard) return null
openingEditorRecursionGuard = true
try {
FileEditorManager.getInstance(project).selectedTextEditor?.takeUnless { it == newEditor }
}
finally {
openingEditorRecursionGuard = false
}
}
private var openingEditorRecursionGuard = false
internal object VimListenerManager {
@ -149,9 +155,7 @@ internal object VimListenerManager {
fun turnOn() {
GlobalListeners.enable()
SlowOperations.knownIssue("VIM-3648, VIM-3649").use {
EditorListeners.addAll()
}
EditorListeners.addAll()
check(correctorRequester.tryEmit(Unit))
check(keyCheckRequests.tryEmit(Unit))
@ -212,6 +216,16 @@ internal object VimListenerManager {
EventFacade.getInstance().addEditorFactoryListener(VimEditorFactoryListener, VimPlugin.getInstance().onOffDisposable)
val busConnection = ApplicationManager.getApplication().messageBus.connect(VimPlugin.getInstance().onOffDisposable)
busConnection.subscribe(FileOpenedSyncListener.TOPIC, VimEditorFactoryListener)
// Listen for focus change to update various features such as mode widget
val eventMulticaster = EditorFactory.getInstance().eventMulticaster
(eventMulticaster as? EditorEventMulticasterEx)?.addFocusChangeListener(
VimFocusListener,
VimPlugin.getInstance().onOffDisposable
)
// Listen for document changes to update document state such as marks
eventMulticaster.addDocumentListener(VimDocumentListener, VimPlugin.getInstance().onOffDisposable)
}
fun disable() {
@ -273,52 +287,45 @@ internal object VimListenerManager {
// TODO: If the user changes the 'ideavimsupport' option, existing editors won't be initialised
if (vimDisabled(editor)) return
val pluginLifetime = VimPlugin.getInstance().createLifetime()
val editorLifetime = (editor as EditorImpl).disposable.createLifetime()
val disposable =
Lifetime.intersect(pluginLifetime, editorLifetime).createNestedDisposable("MyLifetimedDisposable")
// Protect against double initialisation
if (editor.getUserData(editorListenersDisposableKey) != null) {
return
}
// Make sure we explicitly dispose this per-editor disposable!
// Because the listeners are registered with a parent disposable, they add child disposables that have to call a
// method on the editor to remove the listener. This means the disposable contains a reference to the editor (even
// if the listener handler is a singleton that doesn't hold a reference).
// Unless the per-editor disposable is disposed, all of these disposables sit in the disposer tree until the
// parent disposable is disposed, which will mean we leak editor instances.
// The per-editor disposable is explicitly disposed when the editor is released, and disposed via its parent when
// the plugin's on/off functionality is toggled, and so also when the plugin is disabled/unloaded by the platform.
// It doesn't matter if we explicitly remove all listeners before disposing onOffDisposable, as that will remove
// the per-editor disposable from the disposer tree.
val perEditorDisposable = Disposer.newDisposable(VimPlugin.getInstance().onOffDisposable)
editor.putUserData(editorListenersDisposableKey, perEditorDisposable)
val listenersDisposable = Disposer.newDisposable(disposable)
editor.putUserData(editorListenersDisposableKey, listenersDisposable)
Disposer.register(perEditorDisposable) {
Disposer.register(listenersDisposable) {
if (VimListenerTestObject.enabled) {
VimListenerTestObject.disposedCounter += 1
}
}
// This listener and several below add a reference to the editor to the disposer tree
editor.contentComponent.addKeyListener(perEditorDisposable, VimKeyListener)
editor.contentComponent.addKeyListener(VimKeyListener)
Disposer.register(listenersDisposable) { editor.contentComponent.removeKeyListener(VimKeyListener) }
// Initialise the local options. We MUST do this before anything has the chance to query options
val vimEditor = editor.vim
VimPlugin.getOptionGroup().initialiseLocalOptions(vimEditor, openingEditor, scenario)
val eventFacade = EventFacade.getInstance()
eventFacade.addEditorMouseListener(editor, EditorMouseHandler, perEditorDisposable)
eventFacade.addEditorMouseMotionListener(editor, EditorMouseHandler, perEditorDisposable)
eventFacade.addEditorSelectionListener(editor, EditorSelectionHandler, perEditorDisposable)
eventFacade.addComponentMouseListener(editor.contentComponent, ComponentMouseListener, perEditorDisposable)
eventFacade.addCaretListener(editor, EditorCaretHandler, perEditorDisposable)
eventFacade.addEditorMouseListener(editor, EditorMouseHandler, listenersDisposable)
eventFacade.addEditorMouseMotionListener(editor, EditorMouseHandler, listenersDisposable)
eventFacade.addEditorSelectionListener(editor, EditorSelectionHandler, listenersDisposable)
eventFacade.addComponentMouseListener(editor.contentComponent, ComponentMouseListener, listenersDisposable)
eventFacade.addCaretListener(editor, EditorCaretHandler, listenersDisposable)
VimPlugin.getEditor().editorCreated(editor)
VimPlugin.getChange().editorCreated(editor, perEditorDisposable)
(editor as EditorEx).addFocusListener(VimFocusListener, perEditorDisposable)
VimPlugin.getChange().editorCreated(editor, listenersDisposable)
injector.listenersNotifier.notifyEditorCreated(vimEditor)
Disposer.register(perEditorDisposable) {
Disposer.register(listenersDisposable) {
VimPlugin.getEditor().editorDeinit(editor)
}
}
@ -356,7 +363,7 @@ internal object VimListenerManager {
* open in non-local Code With Me guest editors, which we still want to process (e.g. to update marks when a guest
* edits a file. Updating search highlights will be a no-op if there are no open local editors)
*/
class VimDocumentListener : DocumentListener {
private object VimDocumentListener : DocumentListener {
override fun beforeDocumentChange(event: DocumentEvent) {
VimMarkServiceImpl.MarkUpdater.beforeDocumentChange(event)
IjVimSearchGroup.DocumentSearchListener.INSTANCE.beforeDocumentChange(event)
@ -370,26 +377,6 @@ internal object VimListenerManager {
}
}
internal object VimLastSelectedEditorTracker {
// This stores a weak reference to an editor against a weak reference to a project, which means there is nothing
// keeping the project or editor from being garbage collected at any time. Stale keys are automatically expunged
// whenever the map is used.
private val selectedEditors = WeakHashMap<Project, WeakReference<Editor>>()
fun getLastSelectedEditor(project: Project): Editor? = selectedEditors[project]?.get()
internal fun setLastSelectedEditor(fileEditor: FileEditor?) {
(fileEditor as? TextEditor)?.editor?.let { editor ->
editor.project?.let { project -> selectedEditors[project] = WeakReference(editor) }
}
}
@TestOnly
internal fun resetLastSelectedEditor(project: Project) {
selectedEditors.remove(project)
}
}
/**
* Called when the selected file editor changes. In other words, when the user selects a new tab. Used to remember the
* last selected file, update search highlights in the new tab, etc. This will be called with non-local Code With Me
@ -414,8 +401,8 @@ internal object VimListenerManager {
MotionGroup.fileEditorManagerSelectionChangedCallback(event)
FileGroup.fileEditorManagerSelectionChangedCallback(event)
VimPlugin.getSearch().fileEditorManagerSelectionChangedCallback(event)
OptionGroup.fileEditorManagerSelectionChangedCallback(event)
IjVimRedrawService.fileEditorManagerSelectionChangedCallback(event)
VimLastSelectedEditorTracker.setLastSelectedEditor(event.newEditor)
}
}
@ -487,21 +474,8 @@ internal object VimListenerManager {
override fun editorReleased(event: EditorFactoryEvent) {
if (vimDisabled(event.editor)) return
val vimEditor = event.editor.vim
EditorListeners.remove(event.editor)
injector.listenersNotifier.notifyEditorReleased(vimEditor)
injector.markService.editorReleased(vimEditor)
// This ticket will have a different stack trace, but it's the same problem. Originally, we tracked the last
// editor closing based on file selection (closing an editor would select the next editor - so a null selection
// was taken to mean that there were no more editors to select). This assumption broke in 242, so it's changed to
// check when the editor is released.
// However, the actions taken when the last editor closes can still be expensive/slow because we copy options, and
// some options are backed by PSI options. E.g. 'textwidth' is mapped to
// CodeStyle.getSettings(ijEditor).isWrapOnTyping(language)), and getting the document's PSI language is a slow
// operation. This underlying issue still needs to be addressed, even though the method has moved
SlowOperations.knownIssue("VIM-3658").use {
OptionGroup.editorReleased(event.editor)
}
}
override fun fileOpenedSync(
@ -789,16 +763,11 @@ internal object VimListenerManager {
// https://youtrack.jetbrains.com/issue/IDEA-277716
// https://youtrack.jetbrains.com/issue/VIM-2368
if (event.mouseEvent.clickCount == 1 && !SwingUtilities.isRightMouseButton(event.mouseEvent)) {
val hasSelection = ApplicationManager.getApplication().runReadAction<Boolean> {
editor.selectionModel.hasSelection(true)
}
if (!hasSelection) {
if (editor.inVisualMode) {
editor.vim.exitVisualMode()
} else if (editor.vim.inSelectMode) {
editor.exitSelectMode(false)
KeyHandler.getInstance().reset(editor.vim)
}
if (editor.inVisualMode) {
editor.vim.exitVisualMode()
} else if (editor.vim.inSelectMode) {
editor.exitSelectMode(false)
KeyHandler.getInstance().reset(editor.vim)
}
}
} else if (event.area != EditorMouseEventArea.ANNOTATIONS_AREA &&

View File

@ -22,13 +22,10 @@ import com.intellij.openapi.project.DumbService
import com.intellij.openapi.project.IndexNotReadyException
import com.intellij.psi.PsiDocumentManager
import com.intellij.util.ui.EmptyClipboardOwner
import com.maddyhome.idea.vim.api.ExecutionContext
import com.maddyhome.idea.vim.api.VimClipboardManager
import com.maddyhome.idea.vim.api.VimEditor
import com.maddyhome.idea.vim.api.getText
import com.maddyhome.idea.vim.api.injector
import com.maddyhome.idea.vim.common.TextRange
import com.maddyhome.idea.vim.common.VimCopiedText
import com.maddyhome.idea.vim.diagnostic.debug
import com.maddyhome.idea.vim.diagnostic.vimLogger
import java.awt.HeadlessException
@ -40,52 +37,18 @@ import java.io.IOException
@Service
internal class IjClipboardManager : VimClipboardManager {
@Deprecated("Please use com.maddyhome.idea.vim.api.VimClipboardManager#getPrimaryTextAndTransferableData")
override fun getPrimaryTextAndTransferableData(): Pair<String, List<Any>?>? {
val clipboard = Toolkit.getDefaultToolkit()?.systemSelection ?: return null
val contents = clipboard.getContents(null) ?: return null
return getTextAndTransferableData(contents)
}
override fun getPrimaryContent(editor: VimEditor, context: ExecutionContext): IjVimCopiedText? {
val (text, transferableData) = getPrimaryTextAndTransferableData() ?: return null
return IjVimCopiedText(text, transferableData ?: emptyList())
}
@Deprecated("Please use com.maddyhome.idea.vim.api.VimClipboardManager#getClipboardTextAndTransferableData")
override fun getClipboardTextAndTransferableData(): Pair<String, List<Any>?>? {
val contents = getContents() ?: return null
return getTextAndTransferableData(contents)
}
override fun getClipboardContent(editor: VimEditor, context: ExecutionContext): VimCopiedText? {
val (text, transferableData) = getClipboardTextAndTransferableData() ?: return null
return IjVimCopiedText(text, transferableData ?: emptyList())
}
override fun setClipboardContent(editor: VimEditor, context: ExecutionContext, textData: VimCopiedText): Boolean {
require(textData is IjVimCopiedText)
return handleTextSetting(textData.text, textData.text, textData.transferableData) { content -> setContents(content) } != null
}
// TODO prefer methods with ranges, because they collect and preprocess for us
// override fun createClipboardEntry(
// editor: VimEditor,
// context: ExecutionContext,
// text: String,
// range: TextRange,
// ): ClipboardEntry {
// val transferableData = getTransferableData(editor, range, text)
// val preprocessedText = preprocessText(editor, range, text, transferableData)
// return IJClipboardEntry(preprocessedText, text, transferableData)
// }
// override fun setClipboardText(editor: VimEditor, context: ExecutionContext, entry: ClipboardEntry): Boolean {
// require(entry is IJClipboardEntry)
// return setClipboardText(entry.text, entry.rawText, entry.transferableData) != null
// }
private fun getTextAndTransferableData(trans: Transferable): Pair<String, List<TextBlockTransferableData>?>? {
private fun getTextAndTransferableData(trans: Transferable): Pair<String, List<Any>?>? {
var res: String? = null
var transferableData: List<TextBlockTransferableData> = ArrayList()
try {
@ -100,29 +63,10 @@ internal class IjClipboardManager : VimClipboardManager {
return Pair(res, transferableData)
}
@Deprecated("Please use com.maddyhome.idea.vim.api.VimClipboardManager#setClipboardText")
override fun setClipboardText(text: String, rawText: String, transferableData: List<Any>): Transferable? {
return handleTextSetting(text, rawText, transferableData) { content -> setContents(content) }
}
override fun setPrimaryContent(
editor: VimEditor,
context: ExecutionContext,
textData: VimCopiedText,
): Boolean {
require(textData is IjVimCopiedText)
return handleTextSetting(textData.text, textData.text, textData.transferableData) { content ->
val clipboard = Toolkit.getDefaultToolkit()?.systemSelection ?: return@handleTextSetting null
clipboard.setContents(content, EmptyClipboardOwner.INSTANCE)
} != null
}
// override fun setPrimaryText(editor: VimEditor, context: ExecutionContext, entry: ClipboardEntry): Boolean {
// require(entry is IJClipboardEntry)
// return setPrimaryText(entry.text, entry.rawText, entry.transferableData) != null
// }
@Deprecated("Please use com.maddyhome.idea.vim.api.VimClipboardManager#setPrimaryText")
override fun setPrimaryText(text: String, rawText: String, transferableData: List<Any>): Transferable? {
return handleTextSetting(text, rawText, transferableData) { content ->
val clipboard = Toolkit.getDefaultToolkit()?.systemSelection ?: return@handleTextSetting null
@ -130,16 +74,6 @@ internal class IjClipboardManager : VimClipboardManager {
}
}
override fun collectCopiedText(editor: VimEditor, context: ExecutionContext, range: TextRange, text: String): VimCopiedText {
val transferableData = getTransferableData(editor, range)
val preprocessedText = preprocessText(editor, range, text, transferableData)
return IjVimCopiedText(preprocessedText, transferableData)
}
override fun dumbCopiedText(text: String): VimCopiedText {
return IjVimCopiedText(text, emptyList())
}
@Suppress("UNCHECKED_CAST")
private fun handleTextSetting(text: String, rawText: String, transferableData: List<Any>, setContent: (TextBlockTransferable) -> Unit?): Transferable? {
val mutableTransferableData = (transferableData as List<TextBlockTransferableData>).toMutableList()
@ -158,7 +92,7 @@ internal class IjClipboardManager : VimClipboardManager {
return null
}
override fun getTransferableData(vimEditor: VimEditor, textRange: TextRange): List<TextBlockTransferableData> {
override fun getTransferableData(vimEditor: VimEditor, textRange: TextRange, text: String): List<Any> {
val editor = (vimEditor as IjVimEditor).editor
val transferableData: MutableList<TextBlockTransferableData> = ArrayList()
val project = editor.project ?: return emptyList()
@ -183,7 +117,7 @@ internal class IjClipboardManager : VimClipboardManager {
}
}
}
transferableData.add(CaretStateTransferableData(intArrayOf(0), intArrayOf(textRange.endOffset - textRange.startOffset)))
transferableData.add(CaretStateTransferableData(intArrayOf(0), intArrayOf(text.length)))
// These data provided by {@link com.intellij.openapi.editor.richcopy.TextWithMarkupProcessor} doesn't work with
// IdeaVim and I don't see a way to fix it
@ -241,7 +175,3 @@ internal class IjClipboardManager : VimClipboardManager {
val logger = vimLogger<IjClipboardManager>()
}
}
data class IjVimCopiedText(override val text: String, val transferableData: List<Any>): VimCopiedText {
override fun updateText(newText: String): VimCopiedText = IjVimCopiedText(newText, transferableData)
}

View File

@ -19,7 +19,6 @@ import com.maddyhome.idea.vim.api.VimCaret
import com.maddyhome.idea.vim.api.VimCaretBase
import com.maddyhome.idea.vim.api.VimEditor
import com.maddyhome.idea.vim.api.VimVisualPosition
import com.maddyhome.idea.vim.api.injector
import com.maddyhome.idea.vim.common.InsertSequence
import com.maddyhome.idea.vim.common.LiveRange
import com.maddyhome.idea.vim.group.visual.VisualChange
@ -35,14 +34,10 @@ import com.maddyhome.idea.vim.helper.vimLastVisualOperatorRange
import com.maddyhome.idea.vim.helper.vimLine
import com.maddyhome.idea.vim.helper.vimSelectionStart
import com.maddyhome.idea.vim.helper.vimSelectionStartClear
import com.maddyhome.idea.vim.register.VimRegisterGroup
import com.maddyhome.idea.vim.state.mode.SelectionType
internal class IjVimCaret(val caret: Caret) : VimCaretBase() {
override val registerStorage: VimRegisterGroup
get() = injector.registerGroup
override val markStorage: LocalMarkStorage
get() {
var storage = this.caret.markStorage

View File

@ -60,8 +60,6 @@ import com.maddyhome.idea.vim.impl.state.VimStateMachineImpl
import com.maddyhome.idea.vim.state.mode.Mode
import com.maddyhome.idea.vim.state.mode.SelectionType
import com.maddyhome.idea.vim.state.mode.inBlockSelection
import com.maddyhome.idea.vim.undo.VimKeyBasedUndoService
import com.maddyhome.idea.vim.undo.VimTimestampBasedUndoService
import org.jetbrains.annotations.ApiStatus
import java.lang.System.identityHashCode
@ -142,13 +140,7 @@ internal class IjVimEditor(editor: Editor) : MutableLinearEditor, VimEditorBase(
override fun insertText(caret: VimCaret, atPosition: Int, text: CharSequence) {
if (injector.vimState.mode is Mode.INSERT) {
val undo = injector.undo
when (undo) {
is VimKeyBasedUndoService -> undo.setInsertNonMergeUndoKey()
is VimTimestampBasedUndoService -> {
undo.startInsertSequence(caret, atPosition, System.nanoTime())
}
}
injector.undo.startInsertSequence(caret, atPosition, System.nanoTime())
}
editor.document.insertString(atPosition, text)
}
@ -557,7 +549,7 @@ internal class InsertTimeRecorder: ModeChangeListener {
override fun modeChanged(editor: VimEditor, oldMode: Mode) {
editor as IjVimEditor
if (oldMode == Mode.INSERT) {
val undo = injector.undo as? VimTimestampBasedUndoService ?: return
val undo = injector.undo
val nanoTime = System.nanoTime()
editor.forEachCaret { undo.endInsertSequence(it, it.offset, nanoTime) }
}

View File

@ -22,6 +22,7 @@ import com.maddyhome.idea.vim.api.VimApplication
import com.maddyhome.idea.vim.api.VimChangeGroup
import com.maddyhome.idea.vim.api.VimClipboardManager
import com.maddyhome.idea.vim.api.VimCommandGroup
import com.maddyhome.idea.vim.api.VimCommandLine
import com.maddyhome.idea.vim.api.VimCommandLineService
import com.maddyhome.idea.vim.api.VimDigraphGroup
import com.maddyhome.idea.vim.api.VimEditor

View File

@ -18,8 +18,11 @@ import com.intellij.openapi.editor.event.DocumentEvent
import com.intellij.openapi.editor.event.DocumentListener
import com.intellij.openapi.editor.markup.RangeHighlighter
import com.intellij.openapi.fileEditor.FileEditorManagerEvent
import com.intellij.openapi.util.Ref
import com.maddyhome.idea.vim.VimPlugin
import com.maddyhome.idea.vim.api.ExecutionContext
import com.maddyhome.idea.vim.api.Options
import com.maddyhome.idea.vim.api.VimCaret
import com.maddyhome.idea.vim.api.VimEditor
import com.maddyhome.idea.vim.api.VimSearchGroupBase
import com.maddyhome.idea.vim.api.globalOptions
@ -27,16 +30,21 @@ import com.maddyhome.idea.vim.api.injector
import com.maddyhome.idea.vim.common.Direction
import com.maddyhome.idea.vim.common.Direction.Companion.fromInt
import com.maddyhome.idea.vim.diagnostic.vimLogger
import com.maddyhome.idea.vim.helper.MessageHelper
import com.maddyhome.idea.vim.helper.TestInputModel.Companion.getInstance
import com.maddyhome.idea.vim.helper.addSubstitutionConfirmationHighlight
import com.maddyhome.idea.vim.helper.highlightSearchResults
import com.maddyhome.idea.vim.helper.isCloseKeyStroke
import com.maddyhome.idea.vim.helper.shouldIgnoreCase
import com.maddyhome.idea.vim.helper.updateSearchHighlights
import com.maddyhome.idea.vim.helper.vimLastHighlighters
import com.maddyhome.idea.vim.options.GlobalOptionChangeListener
import com.maddyhome.idea.vim.ui.ModalEntry
import com.maddyhome.idea.vim.vimscript.model.functions.handlers.SubmatchFunctionHandler
import org.jdom.Element
import org.jetbrains.annotations.Contract
import org.jetbrains.annotations.TestOnly
import javax.swing.KeyStroke
@State(
name = "VimSearchSettings",
@ -44,7 +52,7 @@ import org.jetbrains.annotations.TestOnly
)
open class IjVimSearchGroup : VimSearchGroupBase(), PersistentStateComponent<Element> {
companion object {
private val logger by lazy { vimLogger<IjVimSearchGroup>() }
private val logger = vimLogger<IjVimSearchGroup>()
}
init {
@ -104,25 +112,27 @@ open class IjVimSearchGroup : VimSearchGroupBase(), PersistentStateComponent<Ele
return IjSearchHighlight(ijEditor, highlighter)
}
override fun setLatestMatch(match: String) {
SubmatchFunctionHandler.getInstance().latestMatch = match
}
override fun replaceString(
editor: VimEditor,
startOffset: Int,
endOffset: Int,
newString: String,
) {
ApplicationManager.getApplication().runWriteAction {
(editor as IjVimEditor).editor.document.replaceString(startOffset, endOffset, newString)
}
}
@TestOnly
override fun resetState() {
super.resetState()
showSearchHighlight = injector.globalOptions().hlsearch
}
override fun isSomeTextHighlighted(): Boolean {
val vimEditors = injector.editorGroup.getEditors().filter {
(injector.application.isUnitTest() || it.ij.component.isShowing)
}
for (vimEditor in vimEditors) {
val editor = vimEditor.ij
if (editor.vimLastHighlighters != null) {
return true
}
}
return false
}
override fun setShouldShowSearchHighlights() {
showSearchHighlight = injector.globalOptions().hlsearch
}

View File

@ -32,9 +32,9 @@ internal class Troubleshooter {
fun findIncorrectMappings(): List<Problem> {
val problems = ArrayList<Problem>()
MappingMode.entries.forEach { mode ->
injector.keyGroup.getKeyMapping(mode).getAllByOwner(MappingOwner.IdeaVim.InitScript).forEach { entry ->
(entry.mappingInfo as? ToKeysMappingInfo)?.let { mappingInfo ->
if (":action" in mappingInfo.toKeys.joinToString { it.keyChar.toString() }) {
injector.keyGroup.getKeyMapping(mode).getByOwner(MappingOwner.IdeaVim.InitScript).forEach { (_, to) ->
if (to is ToKeysMappingInfo) {
if (":action" in to.toKeys.joinToString { it.keyChar.toString() }) {
problems += Problem("Mappings contain `:action` call")
}
}

View File

@ -7,6 +7,7 @@
*/
package com.maddyhome.idea.vim.ui.ex
import com.intellij.openapi.diagnostic.logger
import com.maddyhome.idea.vim.KeyHandler
import com.maddyhome.idea.vim.api.injector
import com.maddyhome.idea.vim.newapi.vim

View File

@ -11,7 +11,6 @@ package com.maddyhome.idea.vim.ui.widgets.mode.listeners
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.fileEditor.FileEditorManager
import com.intellij.openapi.project.Project
import com.intellij.openapi.util.RecursionManager
import com.intellij.openapi.wm.WindowManager
import com.maddyhome.idea.vim.api.VimEditor
import com.maddyhome.idea.vim.common.EditorListener
@ -74,14 +73,7 @@ internal class ModeWidgetListener: ModeChangeListener, EditorListener, VimWidget
private fun getFocusedEditorForProject(editorProject: Project?): Editor? {
if (editorProject == null) return null
return recursionGuard.doPreventingRecursion(recursionKey, false) {
val fileEditorManager = FileEditorManager.getInstance(editorProject)
fileEditorManager.selectedTextEditor
}
}
companion object {
private val recursionGuard = RecursionManager.createGuard<Any>("IdeaVim.modeWidgetListener")
private val recursionKey = Any()
val fileEditorManager = FileEditorManager.getInstance(editorProject)
return fileEditorManager.selectedTextEditor
}
}

View File

@ -15,8 +15,10 @@ import com.maddyhome.idea.vim.api.ExecutionContext
import com.maddyhome.idea.vim.api.VimEditor
import com.maddyhome.idea.vim.api.injector
import com.maddyhome.idea.vim.command.OperatorArguments
import com.maddyhome.idea.vim.ex.ExOutputModel
import com.maddyhome.idea.vim.ex.ranges.Range
import com.maddyhome.idea.vim.helper.MessageHelper
import com.maddyhome.idea.vim.newapi.ij
import com.maddyhome.idea.vim.vimscript.model.ExecutionResult
import java.util.*
@ -24,9 +26,7 @@ import java.util.*
* @author smartbomb
*/
@ExCommand(command = "actionl[ist]")
internal data class ActionListCommand(val range: Range, val modifier: CommandModifier, val argument: String) :
Command.SingleExecution(range, modifier) {
internal data class ActionListCommand(val range: Range, val argument: String) : Command.SingleExecution(range) {
override val argFlags = flags(RangeFlag.RANGE_FORBIDDEN, ArgumentFlag.ARGUMENT_OPTIONAL, Access.READ_ONLY)
override fun processCommand(editor: VimEditor, context: ExecutionContext, operatorArguments: OperatorArguments): ExecutionResult {

View File

@ -27,14 +27,13 @@ import com.maddyhome.idea.vim.vimscript.model.ExecutionResult
* @author John Weigel
*/
@ExCommand(command = "b[uffer]")
internal data class BufferCommand(val range: Range, val modifier: CommandModifier, val argument: String) :
Command.SingleExecution(range, modifier) {
internal data class BufferCommand(val range: Range, val argument: String) : Command.SingleExecution(range) {
override val argFlags = flags(RangeFlag.RANGE_FORBIDDEN, ArgumentFlag.ARGUMENT_OPTIONAL, Access.READ_ONLY)
override fun processCommand(editor: VimEditor, context: ExecutionContext, operatorArguments: OperatorArguments): ExecutionResult {
val overrideModified = modifier == CommandModifier.BANG
val buffer = argument.trim()
val arg = argument.trim()
val overrideModified = arg.startsWith('!')
val buffer = if (overrideModified) arg.replace(Regex("^!\\s*"), "") else arg
var result = true
if (buffer.isNotEmpty()) {

View File

@ -32,9 +32,7 @@ import org.jetbrains.annotations.NonNls
* @author John Weigel
*/
@ExCommand(command = "ls,files,buffers")
internal data class BufferListCommand(val range: Range, val modifier: CommandModifier, val argument: String) :
Command.SingleExecution(range, modifier) {
internal data class BufferListCommand(val range: Range, val argument: String) : Command.SingleExecution(range) {
override val argFlags = flags(RangeFlag.RANGE_FORBIDDEN, ArgumentFlag.ARGUMENT_OPTIONAL, Access.READ_ONLY)
companion object {

View File

@ -18,6 +18,7 @@ import com.maddyhome.idea.vim.api.VimEditor
import com.maddyhome.idea.vim.api.injector
import com.maddyhome.idea.vim.command.OperatorArguments
import com.maddyhome.idea.vim.ex.ExException
import com.maddyhome.idea.vim.ex.ExOutputModel
import com.maddyhome.idea.vim.ex.ranges.Range
import com.maddyhome.idea.vim.ex.ranges.toTextRange
import com.maddyhome.idea.vim.helper.EditorHelper
@ -29,9 +30,7 @@ import com.maddyhome.idea.vim.vimscript.model.ExecutionResult
* see "h :!"
*/
@ExCommand(command = "!")
internal data class CmdFilterCommand(val range: Range, val modifier: CommandModifier, val argument: String)
: Command.SingleExecution(range, modifier) {
internal data class CmdFilterCommand(val range: Range, val argument: String) : Command.SingleExecution(range) {
override val argFlags = flags(RangeFlag.RANGE_OPTIONAL, ArgumentFlag.ARGUMENT_OPTIONAL, Access.SELF_SYNCHRONIZED)
override fun processCommand(editor: VimEditor, context: ExecutionContext, operatorArguments: OperatorArguments): ExecutionResult {
@ -100,7 +99,7 @@ internal data class CmdFilterCommand(val range: Range, val modifier: CommandModi
lastCommand = command
ExecutionResult.Success
}
} catch (_: ProcessCanceledException) {
} catch (e: ProcessCanceledException) {
throw ExException("Command terminated")
} catch (e: Exception) {
throw ExException(e.message)

View File

@ -24,11 +24,8 @@ import java.net.URLEncoder
* see "h :help"
*/
@ExCommand(command = "h[elp]")
internal data class HelpCommand(val range: Range, val modifier: CommandModifier, val argument: String) :
Command.SingleExecution(range, modifier, argument) {
internal data class HelpCommand(val range: Range, val argument: String) : Command.SingleExecution(range, argument) {
override val argFlags = flags(RangeFlag.RANGE_OPTIONAL, ArgumentFlag.ARGUMENT_OPTIONAL, Access.READ_ONLY)
override fun processCommand(editor: VimEditor, context: ExecutionContext, operatorArguments: OperatorArguments): ExecutionResult {
BrowserUtil.browse(helpTopicUrl(argument))
return ExecutionResult.Success
@ -40,7 +37,7 @@ internal data class HelpCommand(val range: Range, val modifier: CommandModifier,
return try {
String.format("%s?docs=help&search=%s", HELP_QUERY_URL, URLEncoder.encode(topic, "UTF-8"))
} catch (_: UnsupportedEncodingException) {
} catch (e: UnsupportedEncodingException) {
HELP_ROOT_URL
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2003-2024 The IdeaVim authors
* Copyright 2003-2023 The IdeaVim authors
*
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE.txt file or at
@ -15,6 +15,9 @@ import com.maddyhome.idea.vim.api.injector
import com.maddyhome.idea.vim.api.lineLength
import com.maddyhome.idea.vim.api.options
import com.maddyhome.idea.vim.api.visualLineToBufferLine
import com.maddyhome.idea.vim.helper.EditorHelper
import com.maddyhome.idea.vim.helper.vimLine
import com.maddyhome.idea.vim.newapi.ij
import com.maddyhome.idea.vim.state.mode.inVisualMode
import com.maddyhome.idea.vim.vimscript.model.VimLContext
import com.maddyhome.idea.vim.vimscript.model.datatypes.VimDataType
@ -99,12 +102,12 @@ private fun variableToPosition(editor: VimEditor, variable: VimDataType, dollarF
if (name.isEmpty()) return null
// Current caret line
if (name[0] == '.') return editor.currentCaret().vimLine.asVimInt() to currentCol(editor)
if (name[0] == '.') return editor.ij.vimLine.asVimInt() to currentCol(editor)
// Visual start
if (name == "v") {
if (!editor.inVisualMode) {
return editor.currentCaret().vimLine.asVimInt() to currentCol(editor)
return editor.ij.vimLine.asVimInt() to currentCol(editor)
}
val vimStart = editor.currentCaret().vimSelectionStart
@ -127,7 +130,7 @@ private fun variableToPosition(editor: VimEditor, variable: VimDataType, dollarF
// First visual line
if (name.length >= 2 && name[0] == 'w' && name[1] == '0') {
if (!dollarForLine) return null
val actualVisualTop = injector.engineEditorHelper.getVisualLineAtTopOfScreen(editor)
val actualVisualTop = EditorHelper.getVisualLineAtTopOfScreen(editor.ij)
val actualLogicalTop = editor.visualLineToBufferLine(actualVisualTop)
return (actualLogicalTop + 1).asVimInt() to currentCol(editor)
}
@ -135,7 +138,7 @@ private fun variableToPosition(editor: VimEditor, variable: VimDataType, dollarF
// Last visual line
if (name.length >= 2 && name[0] == 'w' && name[1] == '$') {
if (!dollarForLine) return null
val actualVisualBottom = injector.engineEditorHelper.getVisualLineAtBottomOfScreen(editor)
val actualVisualBottom = EditorHelper.getVisualLineAtBottomOfScreen(editor.ij)
val actualLogicalBottom = editor.visualLineToBufferLine(actualVisualBottom)
return (actualLogicalBottom + 1).asVimInt() to currentCol(editor)
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2003-2024 The IdeaVim authors
* Copyright 2003-2023 The IdeaVim authors
*
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE.txt file or at
@ -20,7 +20,7 @@ import com.maddyhome.idea.vim.vimscript.model.expressions.Expression
import com.maddyhome.idea.vim.vimscript.model.functions.FunctionHandler
@VimscriptFunction(name = "submatch")
class SubmatchFunctionHandler : FunctionHandler() {
internal class SubmatchFunctionHandler : FunctionHandler() {
override val minimumNumberOfArguments = 1
override val maximumNumberOfArguments = 2

View File

@ -26,7 +26,7 @@
serviceInterface="com.maddyhome.idea.vim.api.VimCommandLineService"/>
<applicationService serviceImplementation="com.maddyhome.idea.vim.ui.ex.IjOutputPanelService"
serviceInterface="com.maddyhome.idea.vim.api.VimOutputPanelService"/>
<applicationService serviceImplementation="com.maddyhome.idea.vim.api.VimDigraphGroupBase"
<applicationService serviceImplementation="com.maddyhome.idea.vim.group.DigraphGroup"
serviceInterface="com.maddyhome.idea.vim.api.VimDigraphGroup"/>
<applicationService serviceImplementation="com.maddyhome.idea.vim.group.HistoryGroup"/>
<applicationService serviceImplementation="com.maddyhome.idea.vim.group.KeyGroup"

View File

@ -95,7 +95,7 @@
<!-- Do not care about red handlers in order. They are necessary for proper ordering, and they'll be resolved when needed -->
<editorActionHandler action="EditorEnter" implementationClass="com.maddyhome.idea.vim.handler.VimEnterHandler"
id="ideavim-enter"
order="before editorEnter, before inline.completion.enter, before rd.client.editor.enter, after smart-step-into-enter, after AceHandlerEnter, after jupyterCommandModeEnterKeyHandler, after swift.placeholder.enter"/>
order="before editorEnter, before rd.client.editor.enter, after smart-step-into-enter, after AceHandlerEnter, after jupyterCommandModeEnterKeyHandler, after swift.placeholder.enter"/>
<editorActionHandler action="EditorEnter" implementationClass="com.maddyhome.idea.vim.handler.CaretShapeEnterEditorHandler"
id="ideavim-enter-shape"
order="before jupyterCommandModeEnterKeyHandler"/>
@ -118,8 +118,6 @@
implementationClass="com.maddyhome.idea.vim.handler.StartNewLineBeforeCurrentDetector"
id="ideavim-start-new-line-before-current-detector"
order="first"/>
<editorFactoryDocumentListener
implementation="com.maddyhome.idea.vim.listener.VimListenerManager$VimDocumentListener"/>
</extensions>
<xi:include href="/META-INF/includes/ApplicationServices.xml" xpointer="xpointer(/idea-plugin/*)"/>

View File

@ -1,3 +1,6 @@
{
"has": "com.maddyhome.idea.vim.vimscript.model.functions.handlers.HasFunctionHandler"
"col": "com.maddyhome.idea.vim.vimscript.model.functions.handlers.ColFunctionHandler",
"has": "com.maddyhome.idea.vim.vimscript.model.functions.handlers.HasFunctionHandler",
"line": "com.maddyhome.idea.vim.vimscript.model.functions.handlers.LineFunctionHandler",
"submatch": "com.maddyhome.idea.vim.vimscript.model.functions.handlers.SubmatchFunctionHandler"
}

View File

@ -28,7 +28,6 @@ E20=E20: Mark not set
e_nopresub=E33: No previous substitute regular expression
e_noprev=E34: No previous command
e_noprevre=E35: No previous regular expression
E39=E39: Number expected
e_re_damg=E43: Damaged match string
e_re_corr=E44: Currupted regexp program
E50=E50: Too many \\z(
@ -70,7 +69,6 @@ E385=E385: Search hit BOTTOM without match for: {0}
E471=E471: Argument required
E474=E474: Invalid argument: {0}
E475=E475: Invalid argument: {0}
E477=E477: No ! allowed
E481=E481: No range allowed
E486=E486: Pattern not found: {0}
E488=E488: Trailing characters: {0}
@ -86,7 +84,6 @@ E549=E549: Illegal percentage: {0}
E774=E774: 'operatorfunc' is empty
e841.reserved.name.cannot.be.used.for.user.defined.command=E841: Reserved name, cannot be used for user defined command
E939=E939: Positive count required
E1214=E1214: Digraph must be just two characters: {0}
message.search.hit.bottom=search hit BOTTOM, continuing at TOP
message.search.hit.top=search hit TOP, continuing at BOTTOM

View File

@ -69,7 +69,6 @@ class ChangeActionTest : VimTestCase() {
// VIM-620 |i_CTRL-O|
@Test
@TestWithoutNeovim(SkipNeovimReason.UNCLEAR)
fun testInsertSingleCommandAndNewLineInserting4() {
doTest(
listOf("i", "<C-O>", "v", "d"),
@ -130,7 +129,6 @@ class ChangeActionTest : VimTestCase() {
// VIM-311 |i_CTRL-O|
@Test
@TestWithoutNeovim(SkipNeovimReason.UNCLEAR)
fun testInsertSingleCommand() {
doTest(
listOf("i", "def", "<C-O>", "d2h", "x"),
@ -1074,7 +1072,6 @@ foobaz
@Test
@TestFor(issues = ["VIM-2074"])
@TestWithoutNeovim(SkipNeovimReason.UNCLEAR)
fun `backspace with replace mode`() {
configureByText("${c}Hello world")
typeText("R1111")

View File

@ -11,7 +11,6 @@ import com.intellij.idea.TestFor
import com.maddyhome.idea.vim.KeyHandler
import com.maddyhome.idea.vim.VimPlugin
import com.maddyhome.idea.vim.api.injector
import com.maddyhome.idea.vim.newapi.vim
import com.maddyhome.idea.vim.state.mode.Mode
import org.jetbrains.plugins.ideavim.SkipNeovimReason
import org.jetbrains.plugins.ideavim.TestWithoutNeovim
@ -251,10 +250,7 @@ class CopyActionTest : VimTestCase() {
enterCommand("set clipboard=unnamed")
kotlin.test.assertEquals('*', VimPlugin.getRegister().defaultRegister)
typeText("yy")
val vimEditor = fixture.editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
val registerService = injector.registerGroup
val starRegister = registerService.getRegister(vimEditor, context, '*')
val starRegister = VimPlugin.getRegister().getRegister('*')
assertNotNull<Any>(starRegister)
kotlin.test.assertEquals("bar\n", starRegister.text)
}
@ -266,10 +262,7 @@ class CopyActionTest : VimTestCase() {
fun testLineWiseClipboardYankPaste() {
configureByText("<caret>foo\n")
typeText("\"*yy" + "\"*p")
val vimEditor = fixture.editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
val registerService = injector.registerGroup
val register = registerService.getRegister(vimEditor, context, '*')
val register = VimPlugin.getRegister().getRegister('*')
assertNotNull<Any>(register)
kotlin.test.assertEquals("foo\n", register.text)
val editor = fixture.editor
@ -297,10 +290,7 @@ class CopyActionTest : VimTestCase() {
""".trimIndent(),
)
typeText("<C-V>j" + "\"*y" + "\"*p")
val vimEditor = fixture.editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
val registerService = injector.registerGroup
val register = registerService.getRegister(vimEditor, context, '*')
val register = VimPlugin.getRegister().getRegister('*')
assertNotNull<Any>(register)
kotlin.test.assertEquals(
"""

View File

@ -10,10 +10,10 @@ package org.jetbrains.plugins.ideavim.action
import com.intellij.idea.TestFor
import com.intellij.testFramework.LoggedErrorProcessor
import com.maddyhome.idea.vim.KeyHandler
import com.maddyhome.idea.vim.VimPlugin
import com.maddyhome.idea.vim.api.injector
import com.maddyhome.idea.vim.api.keys
import com.maddyhome.idea.vim.command.MappingMode
import com.maddyhome.idea.vim.newapi.vim
import org.jetbrains.plugins.ideavim.ExceptionHandler
import org.jetbrains.plugins.ideavim.OnlyThrowLoggedErrorProcessor
import org.jetbrains.plugins.ideavim.SkipNeovimReason
@ -52,18 +52,15 @@ class MacroActionTest : VimTestCase() {
configureByText("")
enterCommand("imap pp hello")
typeText(injector.parser.parseKeys("qa" + "i" + "pp<Esc>" + "q"))
assertRegister('a', "ipp^[")
assertRegister('a', "ipp<Esc>")
}
@Test
fun testRecordMacroWithDigraph() {
typeTextInFile(injector.parser.parseKeys("qa" + "i" + "<C-K>OK<Esc>" + "q"), "")
val vimEditor = fixture.editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
val registerService = injector.registerGroup
val register = registerService.getRegister(vimEditor, context, 'a')
val register = VimPlugin.getRegister().getRegister('a')
assertNotNull<Any>(register)
assertRegister('a', "i^KOK^[")
assertRegister('a', "i<C-K>OK<Esc>")
}
@Test
@ -99,10 +96,7 @@ class MacroActionTest : VimTestCase() {
configureByText(content)
typeText(injector.parser.parseKeys("qa" + ":map x y<CR>" + "q"))
val vimEditor = fixture.editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
val registerService = injector.registerGroup
val register = registerService.getRegister(vimEditor, context, 'a')
val register = VimPlugin.getRegister().getRegister('a')
val registerSize = register!!.keys.size
assertEquals(9, registerSize)
}
@ -250,10 +244,8 @@ class MacroActionTest : VimTestCase() {
)
injector.keyGroup.putKeyMapping(MappingMode.NXO, keys("abc"), exceptionMappingOwner, ExceptionHandler(), false)
val vimEditor = fixture.editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
injector.registerGroup.storeText(vimEditor, context, 'k', "abc")
injector.registerGroup.storeText(vimEditor, context, 'q', "x@ky")
injector.registerGroup.storeText('k', "abc")
injector.registerGroup.storeText('q', "x@ky")
val exception = assertThrows<Throwable> {
LoggedErrorProcessor.executeWith<Throwable>(OnlyThrowLoggedErrorProcessor) {

View File

@ -10,7 +10,6 @@ package org.jetbrains.plugins.ideavim.action
import com.maddyhome.idea.vim.VimPlugin
import com.maddyhome.idea.vim.api.injector
import com.maddyhome.idea.vim.newapi.vim
import org.jetbrains.plugins.ideavim.SkipNeovimReason
import org.jetbrains.plugins.ideavim.TestWithoutNeovim
import org.jetbrains.plugins.ideavim.VimTestCase
@ -29,10 +28,8 @@ class MacroWithEditingTest : VimTestCase() {
@Test
fun `test copy and perform macro`() {
typeTextInFile(injector.parser.parseKeys("^v\$h\"wy"), "iHello")
val vimEditor = fixture.editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
kotlin.test.assertEquals("iHello", VimPlugin.getRegister().getRegister(vimEditor, context, 'w')?.text)
typeTextInFile(injector.parser.parseKeys("^v\$h\"wy"), "iHello<Esc>")
kotlin.test.assertEquals("iHello<Esc>", VimPlugin.getRegister().getRegister('w')?.rawText)
setText("")
typeText(injector.parser.parseKeys("@w"))
waitAndAssert {
@ -42,10 +39,8 @@ class MacroWithEditingTest : VimTestCase() {
@Test
fun `test copy and perform macro ctrl_a`() {
typeTextInFile(injector.parser.parseKeys("^v\$h\"wy"), "\u0001")
val vimEditor = fixture.editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
kotlin.test.assertEquals(injector.parser.parseKeys("<C-A>"), injector.registerGroup.getRegister(vimEditor, context, 'w')!!.keys)
typeTextInFile(injector.parser.parseKeys("^v\$h\"wy"), "<C-A>")
kotlin.test.assertEquals("<C-A>", VimPlugin.getRegister().getRegister('w')?.rawText)
setText("1")
typeText(injector.parser.parseKeys("@w"))
waitAndAssert {

View File

@ -13,11 +13,9 @@ import com.maddyhome.idea.vim.action.motion.search.SearchWholeWordForwardAction
import com.maddyhome.idea.vim.api.injector
import com.maddyhome.idea.vim.common.TextRange
import com.maddyhome.idea.vim.newapi.IjVimEditor
import com.maddyhome.idea.vim.newapi.vim
import com.maddyhome.idea.vim.state.mode.SelectionType
import org.jetbrains.plugins.ideavim.VimBehaviorDiffers
import org.jetbrains.plugins.ideavim.VimTestCase
import org.junit.jupiter.api.Disabled
import org.junit.jupiter.api.Test
import kotlin.test.assertNotNull
@ -1817,7 +1815,6 @@ $c five six se${c}ven eight
)
}
@Disabled("Action execution in tests is broken for 2024.2")
@Test
fun testInsertNewLineAboveAction() {
typeTextInFile(
@ -1844,7 +1841,6 @@ $c five six se${c}ven eight
)
}
@Disabled("Action execution in tests is broken for 2024.2")
@VimBehaviorDiffers(originalVimAfter = "${c}\n${c}\nabcde\n${c}\n${c}\nabcde\n")
@Test
fun testInsertNewLineAboveActionWithMultipleCaretsInLine() {
@ -1859,7 +1855,6 @@ $c five six se${c}ven eight
assertState("${c}\nabcde\n${c}\nabcde\n")
}
@Disabled("Action execution in tests is broken for 2024.2")
@Test
fun testInsertNewLineBelowAction() {
typeTextInFile(
@ -2165,9 +2160,7 @@ rtyfg${c}hzxc"""
fun testPutTextBeforeCursor() {
val before = "${c}qwe asd ${c}zxc rty ${c}fgh vbn"
configureByText(before)
val vimEditor = fixture.editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
injector.registerGroup.storeText(vimEditor, context, '*', "fgh", SelectionType.CHARACTER_WISE)
injector.registerGroup.storeText('*', "fgh", SelectionType.CHARACTER_WISE)
typeText(injector.parser.parseKeys("\"*P" + "3l" + "\"*P"))
val after = "fghqwfg${c}he asd fghzxfg${c}hc rty fghfgfg${c}hh vbn"
assertState(after)
@ -2177,11 +2170,9 @@ rtyfg${c}hzxc"""
fun testPutTextBeforeCursorOverlapRange() {
val before = "${c}q${c}we asd zxc rty ${c}fgh vbn"
val editor = configureByText(before)
val vimEditor = fixture.editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
injector.registerGroup.storeText(vimEditor, context, '*', "fgh")
injector.registerGroup.storeText('*', "fgh")
VimPlugin.getRegister()
.storeText(IjVimEditor(editor), context, editor.vim.primaryCaret(), TextRange(16, 19), SelectionType.CHARACTER_WISE, false)
.storeText(IjVimEditor(editor), TextRange(16, 19), SelectionType.CHARACTER_WISE, false)
typeText(injector.parser.parseKeys("\"*P"))
val after = "fg${c}hqfg${c}hwe asd zxc rty fg${c}hfgh vbn"
assertState(after)
@ -2191,9 +2182,7 @@ rtyfg${c}hzxc"""
fun testPutTextAfterCursor() {
val before = "${c}qwe asd ${c}zxc rty ${c}fgh vbn"
configureByText(before)
val vimEditor = fixture.editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
injector.registerGroup.storeText(vimEditor, context, '*', "fgh", SelectionType.CHARACTER_WISE)
injector.registerGroup.storeText('*', "fgh", SelectionType.CHARACTER_WISE)
typeText(injector.parser.parseKeys("\"*p" + "3l" + "2\"*p"))
val after = "qfghwe fghfg${c}hasd zfghxc fghfg${c}hrty ffghgh fghfg${c}hvbn"
assertState(after)
@ -2203,9 +2192,7 @@ rtyfg${c}hzxc"""
fun testPutTextAfterCursorOverlapRange() {
val before = "${c}q${c}we asd zxc rty ${c}fgh vbn"
configureByText(before)
val vimEditor = fixture.editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
injector.registerGroup.storeText(vimEditor, context, '*', "fgh", SelectionType.CHARACTER_WISE)
injector.registerGroup.storeText('*', "fgh", SelectionType.CHARACTER_WISE)
typeText(injector.parser.parseKeys("2\"*p"))
val after = "qfghfg${c}hwfghfg${c}he asd zxc rty ffghfg${c}hgh vbn"
assertState(after)
@ -2220,9 +2207,7 @@ rtyfg${c}hzxc"""
""".trimIndent()
configureByText(before)
val vimEditor = fixture.editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
injector.registerGroup.storeText(vimEditor, context, '*', "zxcvbn\n", SelectionType.LINE_WISE)
injector.registerGroup.storeText('*', "zxcvbn\n", SelectionType.LINE_WISE)
typeText(injector.parser.parseKeys("\"*P"))
val after = """
${c}zxcvbn
@ -2356,9 +2341,7 @@ rtyfg${c}hzxc"""
private fun testPutOverlapLine(before: String, after: String, beforeCursor: Boolean) {
configureByText(before)
val vimEditor = fixture.editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
injector.registerGroup.storeText(vimEditor, context, '*', "zxcvbn\n", SelectionType.LINE_WISE)
injector.registerGroup.storeText('*', "zxcvbn\n", SelectionType.LINE_WISE)
typeText(injector.parser.parseKeys("\"*" + if (beforeCursor) "P" else "p"))
assertState(after)
}
@ -2372,9 +2355,7 @@ rtyfg${c}hzxc"""
""".trimIndent()
configureByText(before)
val vimEditor = fixture.editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
injector.registerGroup.storeText(vimEditor, context, '*', "zxcvbn", SelectionType.LINE_WISE)
injector.registerGroup.storeText('*', "zxcvbn", SelectionType.LINE_WISE)
typeText(injector.parser.parseKeys("\"*p"))
val after = """
qwerty
@ -2392,9 +2373,7 @@ rtyfg${c}hzxc"""
fun testPutTextBeforeCursorMoveCursor() {
val before = "qw${c}e asd z${c}xc rty ${c}fgh vbn"
configureByText(before)
val vimEditor = fixture.editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
injector.registerGroup.storeText(vimEditor, context, '*', "fgh", SelectionType.CHARACTER_WISE)
injector.registerGroup.storeText('*', "fgh", SelectionType.CHARACTER_WISE)
typeText(injector.parser.parseKeys("l" + "\"*gP" + "b" + "\"*gP"))
val after = "fgh${c}qwefgh asd fgh${c}zxfghc rty fgh${c}ffghgh vbn"
assertState(after)
@ -2404,9 +2383,7 @@ rtyfg${c}hzxc"""
fun testPutTextAfterCursorMoveCursor() {
val before = "qw${c}e asd z${c}xc rty ${c}fgh vbn"
configureByText(before)
val vimEditor = fixture.editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
injector.registerGroup.storeText(vimEditor, context, '*', "fgh", SelectionType.CHARACTER_WISE)
injector.registerGroup.storeText('*', "fgh", SelectionType.CHARACTER_WISE)
typeText(injector.parser.parseKeys("l" + "\"*gp" + "b" + "\"*gp"))
val after = "qwe ffgh${c}ghasd zfgh${c}xcfgh rty ffgh${c}gfghh vbn"
assertState(after)
@ -2421,9 +2398,7 @@ rtyfg${c}hzxc"""
""".trimIndent()
configureByText(before)
val vimEditor = fixture.editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
injector.registerGroup.storeText(vimEditor, context, '*', "zxcvbn\n", SelectionType.LINE_WISE)
injector.registerGroup.storeText('*', "zxcvbn\n", SelectionType.LINE_WISE)
typeText(injector.parser.parseKeys("\"*gP"))
val after = """
zxcvbn
@ -2446,9 +2421,7 @@ rtyfg${c}hzxc"""
""".trimIndent()
configureByText(before)
val vimEditor = fixture.editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
injector.registerGroup.storeText(vimEditor, context, '*', "zxcvbn", SelectionType.LINE_WISE)
injector.registerGroup.storeText('*', "zxcvbn", SelectionType.LINE_WISE)
typeText(injector.parser.parseKeys("\"*gp"))
val after = """
qwerty
@ -2468,9 +2441,7 @@ rtyfg${c}hzxc"""
* two
"""
configureByText(before)
val vimEditor = fixture.editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
injector.registerGroup.storeText(vimEditor, context, '*', " *\n *\n", SelectionType.BLOCK_WISE)
injector.registerGroup.storeText('*', " *\n *\n", SelectionType.BLOCK_WISE)
typeText(injector.parser.parseKeys("\"*p"))
val after = """ * $c *one$c *
* *two *
@ -2484,9 +2455,7 @@ rtyfg${c}hzxc"""
* two
"""
configureByText(before)
val vimEditor = fixture.editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
injector.registerGroup.storeText(vimEditor, context, '*', " *\n \n", SelectionType.BLOCK_WISE)
injector.registerGroup.storeText('*', " *\n \n", SelectionType.BLOCK_WISE)
typeText(injector.parser.parseKeys("\"*P"))
val after = """ *$c * on$c *e
* tw o
@ -2505,9 +2474,7 @@ rtyfg${c}hzxc"""
vb${c}n
""".trimIndent()
configureByText(before)
val vimEditor = fixture.editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
injector.registerGroup.storeText(vimEditor, context, '*', "qwe\n", SelectionType.LINE_WISE)
injector.registerGroup.storeText('*', "qwe\n", SelectionType.LINE_WISE)
typeText(injector.parser.parseKeys("\"*p"))
val after = """
qwe
@ -2529,10 +2496,7 @@ rtyfg${c}hzxc"""
val before = "qwe ${c}asd ${c}zxc"
configureByText(before)
typeText(injector.parser.parseKeys("ye"))
val vimEditor = fixture.editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
val registerService = injector.registerGroup
val lastRegister = registerService.getRegister(vimEditor, context, registerService.lastRegisterChar)
val lastRegister = VimPlugin.getRegister().lastRegister
assertNotNull<Any>(lastRegister)
val text = lastRegister.text
assertNotNull<Any>(text)
@ -2554,10 +2518,7 @@ rtyfg${c}hzxc"""
""".trimIndent()
configureByText(before)
typeText(injector.parser.parseKeys("yj"))
val vimEditor = fixture.editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
val registerService = injector.registerGroup
val lastRegister = registerService.getRegister(vimEditor, context, registerService.lastRegisterChar)
val lastRegister = VimPlugin.getRegister().lastRegister
assertNotNull<Any>(lastRegister)
val text = lastRegister.text
assertNotNull<Any>(text)
@ -2591,10 +2552,7 @@ rtyfg${c}hzxc"""
""".trimIndent()
configureByText(before)
typeText(injector.parser.parseKeys("2yy"))
val vimEditor = fixture.editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
val registerService = injector.registerGroup
val lastRegister = registerService.getRegister(vimEditor, context, registerService.lastRegisterChar)
val lastRegister = VimPlugin.getRegister().lastRegister
assertNotNull<Any>(lastRegister)
val text = lastRegister.text
assertNotNull<Any>(text)

View File

@ -9,7 +9,6 @@ package org.jetbrains.plugins.ideavim.action
import com.maddyhome.idea.vim.VimPlugin
import com.maddyhome.idea.vim.api.injector
import com.maddyhome.idea.vim.newapi.vim
import com.maddyhome.idea.vim.register.RegisterConstants.LAST_INSERTED_TEXT_REGISTER
import com.maddyhome.idea.vim.register.RegisterConstants.LAST_SEARCH_REGISTER
import com.maddyhome.idea.vim.register.RegisterConstants.SMALL_DELETION_REGISTER
@ -211,9 +210,7 @@ class SpecialRegistersTest : VimTestCase() {
private fun getRegisterText(registerName: Char): String? {
val registerGroup = VimPlugin.getRegister()
val vimEditor = fixture.editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
val register = registerGroup.getRegister(vimEditor, context, registerName)
val register = registerGroup.getRegister(registerName)
assertNotNull<Any>(register)
return register!!.text
}

View File

@ -162,16 +162,6 @@ class UndoActionTest : VimTestCase() {
configureByText("Lorem ${c}ipsum dolor sit amet")
}
@Test
@TestFor(issues = ["VIM-3671"])
fun `test undo scrolls caret to reset scrolloff`() {
configureByLines(200, "lorem ipsum dolor sit amet")
enterCommand("set scrolloff=10")
typeText("50G", "dd", "G", "u")
assertPosition(49, 0)
assertVisibleArea(39, 73)
}
private fun hasSelection(): Boolean {
val editor = fixture.editor
return editor.caretModel.primaryCaret.hasSelection()

View File

@ -194,16 +194,4 @@ Mode.INSERT,
fun testLastSymbolInWord() {
doTest("cw", "fo${c}o", "fo${c}", Mode.INSERT)
}
// VIM-3729
@Test
fun `test change with count applies only to motion when repeated`() {
doTest(listOf("2c3l", "foo<Esc>", "w", "."),
"""
banana banana
""".trimIndent(),
"""
foo foo
""".trimIndent())
}
}

View File

@ -10,8 +10,7 @@
package org.jetbrains.plugins.ideavim.action.change.delete
import com.maddyhome.idea.vim.api.injector
import com.maddyhome.idea.vim.newapi.vim
import com.maddyhome.idea.vim.VimPlugin
import org.jetbrains.plugins.ideavim.SkipNeovimReason
import org.jetbrains.plugins.ideavim.TestWithoutNeovim
import org.jetbrains.plugins.ideavim.VimBehaviorDiffers
@ -103,10 +102,7 @@ class DeleteMotionActionTest : VimTestCase() {
expression${c} two
""".trimIndent(),
)
val vimEditor = fixture.editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
val registerService = injector.registerGroup
val savedText = registerService.getRegister(vimEditor, context, registerService.lastRegisterChar)?.text ?: ""
val savedText = VimPlugin.getRegister().lastRegister?.text ?: ""
kotlin.test.assertEquals(" expression two\n", savedText)
}

View File

@ -1,58 +0,0 @@
/*
* Copyright 2003-2024 The IdeaVim authors
*
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE.txt file or at
* https://opensource.org/licenses/MIT.
*/
package org.jetbrains.plugins.ideavim.action.change.insert
import org.jetbrains.plugins.ideavim.VimTestCase
import org.junit.jupiter.api.Test
class InsertCompletedDigraphActionTest : VimTestCase() {
@Test
fun `test insert digraph`() {
doTest(listOf("i", "<C-K>OK", "<Esc>"), "", "")
}
@Test
fun `test insert digraph with reversed characters`() {
doTest(listOf("i", "<C-K>KO", "<Esc>"), "", "")
}
@Test
fun `test insert same character with different digraphs`() {
doTest(listOf("i", "<C-K>Ct", "<C-K>c|", "<Esc>"), "", "¢¢")
}
@Test
fun `test insert custom digraph`() {
doTest(listOf("i", "<C-K>(0", "<Esc>"), "", "") {
enterCommand("digraph (0 9450")
}
}
@Test
fun `test insert custom digraph with reversed characters`() {
doTest(listOf("i", "<C-K>0(", "<Esc>"), "", "") {
enterCommand("digraph (0 9450")
}
}
@Test
fun `test insert custom digraph overriding existing custom digraph`() {
doTest(listOf("i", "<C-K>(0", "<Esc>"), "", "") {
enterCommand("digraph (0 9450")
enterCommand("digraph (0 10003")
}
}
@Test
fun `test insert custom digraph overriding existing default digraph`() {
doTest(listOf("i", "<C-K>OK", "<Esc>"), "", "") {
enterCommand("digraph OK 9450")
}
}
}

View File

@ -15,7 +15,6 @@ import com.maddyhome.idea.vim.state.mode.Mode
import org.jetbrains.plugins.ideavim.SkipNeovimReason
import org.jetbrains.plugins.ideavim.TestWithoutNeovim
import org.jetbrains.plugins.ideavim.VimTestCase
import org.junit.jupiter.api.Disabled
import org.junit.jupiter.api.Test
import kotlin.test.assertEquals
import kotlin.test.assertTrue
@ -85,7 +84,6 @@ class InsertNewLineAboveActionTest : VimTestCase() {
doTest("O", before, after, Mode.INSERT)
}
@Disabled("Action execution in tests is broken for 2024.2")
@Test
fun `test insert new line above with multiple carets`() {
val before = """ I fou${c}nd it in a legendary land

View File

@ -12,7 +12,6 @@ import com.maddyhome.idea.vim.state.mode.Mode
import org.jetbrains.plugins.ideavim.SkipNeovimReason
import org.jetbrains.plugins.ideavim.TestWithoutNeovim
import org.jetbrains.plugins.ideavim.VimTestCase
import org.junit.jupiter.api.Disabled
import org.junit.jupiter.api.Test
class InsertNewLineBelowActionTest : VimTestCase() {
@ -80,7 +79,6 @@ class InsertNewLineBelowActionTest : VimTestCase() {
doTest("o", before, after, Mode.INSERT)
}
@Disabled("Action execution in tests is broken for 2024.2")
@Test
fun `test insert new line below with multiple carets`() {
val before = """ I fou${c}nd it in a legendary land

View File

@ -32,9 +32,8 @@ class IdeaPutNotificationsTest : VimTestCase() {
configureByText(before)
appReadySetup(false)
val vimEditor = fixture.editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
val registerService = injector.registerGroup
registerService.storeText(vimEditor, context, vimEditor.primaryCaret(), before rangeOf "legendary", SelectionType.CHARACTER_WISE, false)
VimPlugin.getRegister()
.storeText(vimEditor, before rangeOf "legendary", SelectionType.CHARACTER_WISE, false)
typeText(injector.parser.parseKeys("p"))
val notification = notifications().last()
@ -53,9 +52,8 @@ class IdeaPutNotificationsTest : VimTestCase() {
configureByText(before)
appReadySetup(false)
val vimEditor = fixture.editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
val registerService = injector.registerGroup
registerService.storeText(vimEditor, context, vimEditor.primaryCaret(), before rangeOf "legendary", SelectionType.CHARACTER_WISE, false)
VimPlugin.getRegister()
.storeText(vimEditor, before rangeOf "legendary", SelectionType.CHARACTER_WISE, false)
typeText(injector.parser.parseKeys("p"))
val notifications = notifications()
@ -72,9 +70,8 @@ class IdeaPutNotificationsTest : VimTestCase() {
configureByText(before)
appReadySetup(true)
val vimEditor = fixture.editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
val registerService = injector.registerGroup
registerService.storeText(vimEditor, context, vimEditor.primaryCaret(), before rangeOf "legendary", SelectionType.CHARACTER_WISE, false)
VimPlugin.getRegister()
.storeText(vimEditor, before rangeOf "legendary", SelectionType.CHARACTER_WISE, false)
typeText(injector.parser.parseKeys("p"))
val notifications = EventLog.getLogModel(fixture.project).notifications

View File

@ -15,6 +15,7 @@ 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.api.globalOptions
import com.maddyhome.idea.vim.api.injector
import com.maddyhome.idea.vim.newapi.vim
@ -86,9 +87,8 @@ class PutTestAfterCursorActionTest : VimTestCase() {
""".trimIndent()
val editor = configureByText(before)
val vimEditor = editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
val registerService = injector.registerGroup
registerService.storeText(vimEditor, context, vimEditor.primaryCaret(), before rangeOf "A Discovery\n", SelectionType.LINE_WISE, false)
VimPlugin.getRegister()
.storeText(vimEditor, before rangeOf "A Discovery\n", SelectionType.LINE_WISE, false)
typeText(injector.parser.parseKeys("p"))
val after = """
A Discovery
@ -124,13 +124,9 @@ class PutTestAfterCursorActionTest : VimTestCase() {
// Add Guard to simulate Notebook behaviour. See (VIM-2577)
val guardRange = before rangeOf "\nGUARD\n"
editor.document.createGuardedBlock(guardRange.startOffset, guardRange.endOffset)
val vimEditor = fixture.editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
val registerService = injector.registerGroup
registerService.storeText(
val vimEditor = editor.vim
injector.registerGroup.storeText(
vimEditor,
context,
vimEditor.primaryCaret(),
before rangeOf "I found it in a legendary land\n",
SelectionType.LINE_WISE,
false,
@ -159,9 +155,8 @@ class PutTestAfterCursorActionTest : VimTestCase() {
""".trimIndent()
val editor = configureByText(before)
val vimEditor = editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
val registerService = injector.registerGroup
registerService.storeText(vimEditor, context, vimEditor.primaryCaret(), before rangeOf "Discovery", SelectionType.CHARACTER_WISE, false)
VimPlugin.getRegister()
.storeText(vimEditor, before rangeOf "Discovery", SelectionType.CHARACTER_WISE, false)
typeText(injector.parser.parseKeys("vep"))
val after = """
A Discovery

View File

@ -31,9 +31,7 @@ class PutTextBeforeCursorActionTest : VimTestCase() {
""".trimIndent()
val editor = configureByText(before)
val vimEditor = editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
val registerService = injector.registerGroup
registerService.storeText(vimEditor, context, vimEditor.primaryCaret(), before rangeOf "Discovery", SelectionType.CHARACTER_WISE, false)
injector.registerGroup.storeText(vimEditor, before rangeOf "Discovery", SelectionType.CHARACTER_WISE, false)
typeText(injector.parser.parseKeys("V" + "P"))
typeText(injector.parser.parseKeys("V" + "P"))
val after = """

View File

@ -39,10 +39,7 @@ class PutViaIdeaTest : VimTestCase() {
val before = "${c}Lorem ipsum dolor sit amet,"
configureByText(before)
val vimEditor = fixture.editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
val registerService = injector.registerGroup
registerService.storeText(vimEditor, context, '"', "legendary", SelectionType.CHARACTER_WISE)
injector.registerGroup.storeText('"', "legendary", SelectionType.CHARACTER_WISE)
typeText("ve", "p")
val after = "legendar${c}y ipsum dolor sit amet,"
@ -56,9 +53,8 @@ class PutViaIdeaTest : VimTestCase() {
configureByText(before)
val vimEditor = fixture.editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
val registerService = injector.registerGroup
registerService.storeText(vimEditor, context, vimEditor.primaryCaret(), before rangeOf "legendary", SelectionType.CHARACTER_WISE, false)
VimPlugin.getRegister()
.storeText(vimEditor, before rangeOf "legendary", SelectionType.CHARACTER_WISE, false)
typeText("ppp")
val after = "Ilegendarylegendarylegendar${c}y found it in a legendary land"
@ -74,14 +70,10 @@ class PutViaIdeaTest : VimTestCase() {
CopyPasteManager.getInstance().setContents(TextBlockTransferable("Fill", emptyList(), null))
CopyPasteManager.getInstance().setContents(TextBlockTransferable("Buffer", emptyList(), null))
VimPlugin.getRegister()
val vimEditor = fixture.editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
val registerService = injector.registerGroup
registerService.storeText(
VimPlugin.getRegister()
.storeText(
vimEditor,
context,
vimEditor.primaryCaret(),
before rangeOf "legendary$randomUUID",
SelectionType.CHARACTER_WISE,
false,
@ -105,12 +97,8 @@ class PutViaIdeaTest : VimTestCase() {
configureByText(before)
val vimEditor = fixture.editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
val registerService = injector.registerGroup
registerService.storeText(
VimPlugin.getRegister().storeText(
vimEditor,
context,
vimEditor.primaryCaret(),
before rangeOf "\nLorem ipsum dolor sit amet,\n",
SelectionType.CHARACTER_WISE,
false,

View File

@ -10,6 +10,7 @@
package org.jetbrains.plugins.ideavim.action.copy
import com.maddyhome.idea.vim.VimPlugin
import com.maddyhome.idea.vim.api.injector
import com.maddyhome.idea.vim.newapi.vim
import com.maddyhome.idea.vim.state.mode.SelectionType
@ -73,12 +74,8 @@ class PutVisualTextActionTest : VimTestCase() {
fun `test put visual text`() {
val before = "${c}I found it in a legendary land"
val editor = configureByText(before)
val vimEditor = editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
val registerService = injector.registerGroup
registerService.storeText(vimEditor, context, vimEditor.primaryCaret(), before rangeOf "legendary", SelectionType.CHARACTER_WISE, false)
VimPlugin.getRegister().storeText(vimEditor, before rangeOf "legendary", SelectionType.CHARACTER_WISE, false)
typeText(injector.parser.parseKeys("ve" + "p"))
val after = "legendar${c}y it in a legendary land"
assertState(after)
@ -89,12 +86,8 @@ class PutVisualTextActionTest : VimTestCase() {
fun `test put visual text twice`() {
val before = "${c}I found it in a legendary land"
val editor = configureByText(before)
val vimEditor = editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
val registerService = injector.registerGroup
registerService.storeText(vimEditor, context, vimEditor.primaryCaret(), before rangeOf "legendary", SelectionType.CHARACTER_WISE, false)
VimPlugin.getRegister().storeText(vimEditor, before rangeOf "legendary", SelectionType.CHARACTER_WISE, false)
typeText(injector.parser.parseKeys("v2e" + "2p"))
val after = "legendarylegendar${c}y in a legendary land"
assertState(after)
@ -105,12 +98,8 @@ class PutVisualTextActionTest : VimTestCase() {
fun `test put visual text full line`() {
val before = "${c}I found it in a legendary land"
val editor = configureByText(before)
val vimEditor = editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
val registerService = injector.registerGroup
registerService.storeText(vimEditor, context, vimEditor.primaryCaret(), before rangeOf "legendary", SelectionType.CHARACTER_WISE, false)
VimPlugin.getRegister().storeText(vimEditor, before rangeOf "legendary", SelectionType.CHARACTER_WISE, false)
typeText(injector.parser.parseKeys("v$" + "2p"))
val after = "legendarylegendar${c}y"
assertState(after)
@ -121,9 +110,7 @@ class PutVisualTextActionTest : VimTestCase() {
fun `test put visual text multicaret`() {
val before = "${c}I found ${c}it in a ${c}legendary land"
configureByText(before)
val vimEditor = fixture.editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
injector.registerGroup.storeText(vimEditor, context,'+', "legendary", SelectionType.CHARACTER_WISE)
injector.registerGroup.storeText('+', "legendary", SelectionType.CHARACTER_WISE)
typeText(injector.parser.parseKeys("ve" + "\"+p"))
val after = "legendar${c}y legendar${c}y in a legendar${c}y land"
assertState(after)
@ -134,9 +121,7 @@ class PutVisualTextActionTest : VimTestCase() {
fun `test put visual text multicaret clipboard register`() {
val before = "${c}I found ${c}it in a ${c}legendary land"
configureByText(before)
val vimEditor = fixture.editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
injector.registerGroup.storeText(vimEditor, context,'+', "legendary", SelectionType.CHARACTER_WISE)
injector.registerGroup.storeText('+', "legendary", SelectionType.CHARACTER_WISE)
typeText(injector.parser.parseKeys("ve" + "\"+p"))
val after = "legendar${c}y legendar${c}y in a legendar${c}y land"
assertState(after)
@ -147,12 +132,8 @@ class PutVisualTextActionTest : VimTestCase() {
fun `test put visual text another direction`() {
val before = "I foun${c}d it in a legendary land"
val editor = configureByText(before)
val vimEditor = editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
val registerService = injector.registerGroup
registerService.storeText(vimEditor, context, vimEditor.primaryCaret(), before rangeOf "legendary", SelectionType.CHARACTER_WISE, false)
VimPlugin.getRegister().storeText(vimEditor, before rangeOf "legendary", SelectionType.CHARACTER_WISE, false)
typeText(injector.parser.parseKeys("vb" + "p"))
val after = "I legendar${c}y it in a legendary land"
assertState(after)
@ -172,12 +153,8 @@ class PutVisualTextActionTest : VimTestCase() {
hard by the torrent of a mountain pass.
""".trimIndent()
val editor = configureByText(before)
val vimEditor = editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
val registerService = injector.registerGroup
registerService.storeText(vimEditor, context, vimEditor.primaryCaret(), before rangeOf "A Discovery\n", SelectionType.LINE_WISE, false)
VimPlugin.getRegister().storeText(vimEditor, before rangeOf "A Discovery\n", SelectionType.LINE_WISE, false)
typeText(injector.parser.parseKeys("ve" + "p"))
val after = """
A Discovery
@ -204,12 +181,8 @@ class PutVisualTextActionTest : VimTestCase() {
hard by the torrent of a mountain pass.
""".trimIndent()
val editor = configureByText(before)
val vimEditor = editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
val registerService = injector.registerGroup
registerService.storeText(vimEditor, context, vimEditor.primaryCaret(), before rangeOf "A Discovery\n", SelectionType.LINE_WISE, false)
VimPlugin.getRegister().storeText(vimEditor, before rangeOf "A Discovery\n", SelectionType.LINE_WISE, false)
typeText(injector.parser.parseKeys("ve" + "p"))
val after = """
A Discovery
@ -236,12 +209,8 @@ class PutVisualTextActionTest : VimTestCase() {
${c}hard by the torrent of a mountain pass.
""".trimIndent()
val editor = configureByText(before)
val vimEditor = editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
val registerService = injector.registerGroup
registerService.storeText(vimEditor, context, vimEditor.primaryCaret(), before rangeOf "A Discovery\n", SelectionType.LINE_WISE, false)
VimPlugin.getRegister().storeText(vimEditor, before rangeOf "A Discovery\n", SelectionType.LINE_WISE, false)
typeText(injector.parser.parseKeys("ve" + "p"))
val after = """
A Discovery
@ -268,12 +237,8 @@ class PutVisualTextActionTest : VimTestCase() {
${c}hard by the torrent of a mountain pass.
""".trimIndent()
val editor = configureByText(before)
val vimEditor = editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
val registerService = injector.registerGroup
registerService.storeText(vimEditor, context, vimEditor.primaryCaret(), before rangeOf "A Discovery\n", SelectionType.LINE_WISE, false)
VimPlugin.getRegister().storeText(vimEditor, before rangeOf "A Discovery\n", SelectionType.LINE_WISE, false)
typeText(injector.parser.parseKeys("v$" + "p"))
val after = """
A Discovery
@ -300,9 +265,7 @@ class PutVisualTextActionTest : VimTestCase() {
${c}hard by the torrent of a mountain pass.
""".trimIndent()
configureByText(before)
val vimEditor = fixture.editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
injector.registerGroup.storeText(vimEditor, context,'*', "A Discovery\n", SelectionType.LINE_WISE)
injector.registerGroup.storeText('*', "A Discovery\n", SelectionType.LINE_WISE)
typeText(injector.parser.parseKeys("ve" + "\"*p"))
val after = """
A Discovery
@ -333,9 +296,7 @@ class PutVisualTextActionTest : VimTestCase() {
${c}hard by the torrent of a mountain pass.
""".trimIndent()
configureByText(before)
val vimEditor = fixture.editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
injector.registerGroup.storeText(vimEditor, context,'+', "A Discovery\n", SelectionType.LINE_WISE)
injector.registerGroup.storeText('+', "A Discovery\n", SelectionType.LINE_WISE)
typeText(injector.parser.parseKeys("ve" + "\"+p"))
val after = """
A Discovery
@ -366,9 +327,7 @@ class PutVisualTextActionTest : VimTestCase() {
${c}hard by the$c torrent of a mountain pass.
""".trimIndent()
configureByText(before)
val vimEditor = fixture.editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
injector.registerGroup.storeText(vimEditor, context,'+', "A Discovery\n", SelectionType.LINE_WISE)
injector.registerGroup.storeText('+', "A Discovery\n", SelectionType.LINE_WISE)
typeText(injector.parser.parseKeys("ve" + "\"+p"))
val after = """
A Discovery
@ -397,9 +356,7 @@ class PutVisualTextActionTest : VimTestCase() {
${c}hard by the$c torrent of a mountain pass.
""".trimIndent()
configureByText(before)
val vimEditor = fixture.editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
injector.registerGroup.storeText(vimEditor, context,'+', "A Discovery\n", SelectionType.LINE_WISE)
injector.registerGroup.storeText('+', "A Discovery\n", SelectionType.LINE_WISE)
typeText(injector.parser.parseKeys("ve" + "\"+p"))
val after = """
A Discovery
@ -428,9 +385,7 @@ class PutVisualTextActionTest : VimTestCase() {
${c}hard by the$c torrent of a mountain pass.
""".trimIndent()
configureByText(before)
val vimEditor = fixture.editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
injector.registerGroup.storeText(vimEditor, context,'+', "A Discovery\n", SelectionType.LINE_WISE)
injector.registerGroup.storeText('+', "A Discovery\n", SelectionType.LINE_WISE)
typeText(injector.parser.parseKeys("ve" + "2\"+p"))
val after = """
A Discovery
@ -461,9 +416,7 @@ class PutVisualTextActionTest : VimTestCase() {
${c}hard by the$c torrent of a mountain pass.
""".trimIndent()
configureByText(before)
val vimEditor = fixture.editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
injector.registerGroup.storeText(vimEditor, context,'+', "A Discovery\n", SelectionType.LINE_WISE)
injector.registerGroup.storeText('+', "A Discovery\n", SelectionType.LINE_WISE)
typeText(injector.parser.parseKeys("ve" + "2\"+p"))
val after = """
A Discovery
@ -501,12 +454,8 @@ class PutVisualTextActionTest : VimTestCase() {
the dingy underside, the checquered fringe.
""".trimIndent()
val editor = configureByText(before)
val vimEditor = editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
val registerService = injector.registerGroup
registerService.storeText(vimEditor, context, vimEditor.primaryCaret(), editor.rangeOf("|found|", 2), SelectionType.BLOCK_WISE, false)
VimPlugin.getRegister().storeText(vimEditor, editor.rangeOf("|found|", 2), SelectionType.BLOCK_WISE, false)
typeText(injector.parser.parseKeys("ve" + "p"))
val after = """
A Discovery
@ -541,12 +490,8 @@ class PutVisualTextActionTest : VimTestCase() {
the dingy ${c}underside, the checquered fringe.
""".trimIndent()
val editor = configureByText(before)
val vimEditor = editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
val registerService = injector.registerGroup
registerService.storeText(vimEditor, context, vimEditor.primaryCaret(), editor.rangeOf("|found|", 2), SelectionType.BLOCK_WISE, false)
VimPlugin.getRegister().storeText(vimEditor, editor.rangeOf("|found|", 2), SelectionType.BLOCK_WISE, false)
typeText(injector.parser.parseKeys("ve" + "p"))
val after = """
A Discovery
@ -583,12 +528,8 @@ class PutVisualTextActionTest : VimTestCase() {
the dingy ${c}underside, the checquered fringe.
""".trimIndent()
val editor = configureByText(before)
val vimEditor = editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
val registerService = injector.registerGroup
registerService.storeText(vimEditor, context, vimEditor.primaryCaret(), editor.rangeOf("|found|", 2), SelectionType.BLOCK_WISE, false)
VimPlugin.getRegister().storeText(vimEditor, editor.rangeOf("|found|", 2), SelectionType.BLOCK_WISE, false)
typeText(injector.parser.parseKeys("ve" + "2p"))
val after = """
A Discovery
@ -625,10 +566,8 @@ class PutVisualTextActionTest : VimTestCase() {
the dingy ${c}underside, the checquered fringe.
""".trimIndent()
configureByText(before)
val vimEditor = fixture.editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
injector.registerGroup.storeText(vimEditor, context,'+', "|found|\n|l roc|\n|ere i|", SelectionType.BLOCK_WISE)
// registerService.storeText(editor.vim context,, editor.rangeOf("|found|", 2), SelectionType.BLOCK_WISE, false)
injector.registerGroup.storeText('+', "|found|\n|l roc|\n|ere i|", SelectionType.BLOCK_WISE)
// VimPlugin.getRegister().storeText(editor.vim, editor.rangeOf("|found|", 2), SelectionType.BLOCK_WISE, false)
typeText(injector.parser.parseKeys("ve" + "\"+p"))
val after = """
A Discovery
@ -665,10 +604,8 @@ class PutVisualTextActionTest : VimTestCase() {
the dingy ${c}underside, the checquered fringe.
""".trimIndent()
configureByText(before)
val vimEditor = fixture.editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
injector.registerGroup.storeText(vimEditor, context,'+', "|found|\n|l roc|\n|ere i|", SelectionType.BLOCK_WISE)
// registerService.storeText(editor.vim context,, editor.rangeOf("|found|", 2), SelectionType.BLOCK_WISE, false)
injector.registerGroup.storeText('+', "|found|\n|l roc|\n|ere i|", SelectionType.BLOCK_WISE)
// VimPlugin.getRegister().storeText(editor.vim, editor.rangeOf("|found|", 2), SelectionType.BLOCK_WISE, false)
typeText(injector.parser.parseKeys("ve" + "\"+p"))
val after = """
A Discovery
@ -702,12 +639,8 @@ class PutVisualTextActionTest : VimTestCase() {
hard by the torrent of a mountain pass.
""".trimIndent()
val editor = configureByText(before)
val vimEditor = editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
val registerService = injector.registerGroup
registerService.storeText(vimEditor, context, vimEditor.primaryCaret(), before rangeOf "Discovery", SelectionType.CHARACTER_WISE, false)
VimPlugin.getRegister().storeText(vimEditor, before rangeOf "Discovery", SelectionType.CHARACTER_WISE, false)
typeText(injector.parser.parseKeys("V" + "p"))
val after = """
A Discovery
@ -732,12 +665,8 @@ class PutVisualTextActionTest : VimTestCase() {
hard by the torrent of a mountain pass.
""".trimIndent()
val editor = configureByText(before)
val vimEditor = editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
val registerService = injector.registerGroup
registerService.storeText(vimEditor, context, vimEditor.primaryCaret(), before rangeOf "Discovery", SelectionType.CHARACTER_WISE, false)
VimPlugin.getRegister().storeText(vimEditor, before rangeOf "Discovery", SelectionType.CHARACTER_WISE, false)
typeText(injector.parser.parseKeys("V" + "2p"))
val after = """
A Discovery
@ -773,12 +702,8 @@ class PutVisualTextActionTest : VimTestCase() {
hard by ${c}the torrent of a mountain pass.
""".trimIndent()
val editor = configureByText(before)
val vimEditor = editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
val registerService = injector.registerGroup
registerService.storeText(vimEditor, context, vimEditor.primaryCaret(), before rangeOf "Discovery", SelectionType.CHARACTER_WISE, false)
VimPlugin.getRegister().storeText(vimEditor, before rangeOf "Discovery", SelectionType.CHARACTER_WISE, false)
typeText(injector.parser.parseKeys("V" + "p"))
val after = """
A Discovery
@ -814,9 +739,7 @@ class PutVisualTextActionTest : VimTestCase() {
hard by the ${c}torrent of a mountain pass.
""".trimIndent()
configureByText(before)
val vimEditor = fixture.editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
injector.registerGroup.storeText(vimEditor, context,'*', "Discovery", SelectionType.CHARACTER_WISE)
injector.registerGroup.storeText('*', "Discovery", SelectionType.CHARACTER_WISE)
typeText(injector.parser.parseKeys("V" + "\"*p"))
val after = """
A Discovery
@ -852,9 +775,7 @@ class PutVisualTextActionTest : VimTestCase() {
hard by the ${c}torrent of a mountain pass.
""".trimIndent()
configureByText(before)
val vimEditor = fixture.editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
injector.registerGroup.storeText(vimEditor, context,'+', "Discovery", SelectionType.CHARACTER_WISE)
injector.registerGroup.storeText('+', "Discovery", SelectionType.CHARACTER_WISE)
typeText(injector.parser.parseKeys("V" + "\"+p"))
val after = """
A Discovery
@ -890,9 +811,7 @@ class PutVisualTextActionTest : VimTestCase() {
hard by the ${c}torrent of a mountain pass.
""".trimIndent()
configureByText(before)
val vimEditor = fixture.editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
injector.registerGroup.storeText(vimEditor, context,'+', "Discovery", SelectionType.CHARACTER_WISE)
injector.registerGroup.storeText('+', "Discovery", SelectionType.CHARACTER_WISE)
typeText(injector.parser.parseKeys("V" + "\"+p"))
val after = """
A Discovery
@ -928,9 +847,7 @@ class PutVisualTextActionTest : VimTestCase() {
hard by the ${c}torrent of a mountain pass.
""".trimIndent()
configureByText(before)
val vimEditor = fixture.editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
injector.registerGroup.storeText(vimEditor, context,'+', "Discovery", SelectionType.CHARACTER_WISE)
injector.registerGroup.storeText('+', "Discovery", SelectionType.CHARACTER_WISE)
typeText(injector.parser.parseKeys("V" + "\"+p"))
val after = """
A Discovery
@ -958,12 +875,8 @@ class PutVisualTextActionTest : VimTestCase() {
hard by the torrent of a mountain pass.
""".trimIndent()
val editor = configureByText(before)
val vimEditor = editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
val registerService = injector.registerGroup
registerService.storeText(vimEditor, context, vimEditor.primaryCaret(), before rangeOf "A Discovery\n", SelectionType.LINE_WISE, false)
VimPlugin.getRegister().storeText(vimEditor, before rangeOf "A Discovery\n", SelectionType.LINE_WISE, false)
typeText(injector.parser.parseKeys("V" + "p"))
val after = """
A Discovery
@ -988,12 +901,8 @@ class PutVisualTextActionTest : VimTestCase() {
hard by the torrent of a mountain pass.
""".trimIndent()
val editor = configureByText(before)
val vimEditor = editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
val registerService = injector.registerGroup
registerService.storeText(vimEditor, context, vimEditor.primaryCaret(), before rangeOf "A Discovery\n", SelectionType.LINE_WISE, false)
VimPlugin.getRegister().storeText(vimEditor, before rangeOf "A Discovery\n", SelectionType.LINE_WISE, false)
typeText(injector.parser.parseKeys("V" + "2p"))
val after = """
A Discovery
@ -1029,12 +938,8 @@ class PutVisualTextActionTest : VimTestCase() {
hard by the ${c}torrent of a mountain pass.
""".trimIndent()
val editor = configureByText(before)
val vimEditor = editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
val registerService = injector.registerGroup
registerService.storeText(vimEditor, context, vimEditor.primaryCaret(), before rangeOf "A Discovery\n", SelectionType.LINE_WISE, false)
VimPlugin.getRegister().storeText(vimEditor, before rangeOf "A Discovery\n", SelectionType.LINE_WISE, false)
typeText(injector.parser.parseKeys("V" + "p"))
val after = """
A Discovery
@ -1070,9 +975,7 @@ class PutVisualTextActionTest : VimTestCase() {
hard by the ${c}torrent of a mountain pass.
""".trimIndent()
configureByText(before)
val vimEditor = fixture.editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
injector.registerGroup.storeText(vimEditor, context,'*', "A Discovery\n", SelectionType.LINE_WISE)
injector.registerGroup.storeText('*', "A Discovery\n", SelectionType.LINE_WISE)
typeText(injector.parser.parseKeys("V" + "\"*p"))
val after = """
A Discovery
@ -1108,9 +1011,7 @@ class PutVisualTextActionTest : VimTestCase() {
hard by the ${c}torrent of a mountain pass.
""".trimIndent()
configureByText(before)
val vimEditor = fixture.editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
injector.registerGroup.storeText(vimEditor, context,'+', "A Discovery\n", SelectionType.LINE_WISE)
injector.registerGroup.storeText('+', "A Discovery\n", SelectionType.LINE_WISE)
typeText(injector.parser.parseKeys("V" + "\"+p"))
val after = """
A Discovery
@ -1146,9 +1047,7 @@ class PutVisualTextActionTest : VimTestCase() {
hard by the ${c}torrent of a mountain pass.
""".trimIndent()
configureByText(before)
val vimEditor = fixture.editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
injector.registerGroup.storeText(vimEditor, context,'+', "A Discovery\n", SelectionType.LINE_WISE)
injector.registerGroup.storeText('+', "A Discovery\n", SelectionType.LINE_WISE)
typeText(injector.parser.parseKeys("V" + "\"+p"))
val after = """
A Discovery
@ -1184,9 +1083,7 @@ class PutVisualTextActionTest : VimTestCase() {
hard by the ${c}torrent of a mountain pass.
""".trimIndent()
configureByText(before)
val vimEditor = fixture.editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
injector.registerGroup.storeText(vimEditor, context,'+', "A Discovery\n", SelectionType.LINE_WISE)
injector.registerGroup.storeText('+', "A Discovery\n", SelectionType.LINE_WISE)
typeText(injector.parser.parseKeys("V" + "\"+p"))
val after = """
A Discovery
@ -1219,12 +1116,8 @@ class PutVisualTextActionTest : VimTestCase() {
the dingy underside, the checquered fringe.
""".trimIndent()
val editor = configureByText(before)
val vimEditor = editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
val registerService = injector.registerGroup
registerService.storeText(vimEditor, context, vimEditor.primaryCaret(), editor.rangeOf("|found|", 2), SelectionType.BLOCK_WISE, false)
VimPlugin.getRegister().storeText(vimEditor, editor.rangeOf("|found|", 2), SelectionType.BLOCK_WISE, false)
typeText(injector.parser.parseKeys("V" + "p"))
val after = """
A Discovery
@ -1278,12 +1171,8 @@ class PutVisualTextActionTest : VimTestCase() {
the dingy ${c}underside, the checquered fringe.
""".trimIndent()
val editor = configureByText(before)
val vimEditor = editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
val registerService = injector.registerGroup
registerService.storeText(vimEditor, context, vimEditor.primaryCaret(), editor.rangeOf("|found|", 2), SelectionType.BLOCK_WISE, false)
VimPlugin.getRegister().storeText(vimEditor, editor.rangeOf("|found|", 2), SelectionType.BLOCK_WISE, false)
typeText(injector.parser.parseKeys("V" + "p"))
val after = """
A Discovery
@ -1343,12 +1232,8 @@ class PutVisualTextActionTest : VimTestCase() {
the dingy ${c}underside, the checquered fringe.
""".trimIndent()
val editor = configureByText(before)
val vimEditor = editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
val registerService = injector.registerGroup
registerService.storeText(vimEditor, context, vimEditor.primaryCaret(), editor.rangeOf("|found|", 2), SelectionType.BLOCK_WISE, false)
VimPlugin.getRegister().storeText(vimEditor, editor.rangeOf("|found|", 2), SelectionType.BLOCK_WISE, false)
typeText(injector.parser.parseKeys("V" + "2p"))
val after = """
A Discovery
@ -1407,9 +1292,7 @@ class PutVisualTextActionTest : VimTestCase() {
the dingy ${c}underside, the checquered fringe.
""".trimIndent()
configureByText(before)
val vimEditor = fixture.editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
injector.registerGroup.storeText(vimEditor, context,'+', "|found|\n|l roc|\n|ere i|", SelectionType.BLOCK_WISE)
injector.registerGroup.storeText('+', "|found|\n|l roc|\n|ere i|", SelectionType.BLOCK_WISE)
typeText(injector.parser.parseKeys("V" + "\"+p"))
val after = """
A Discovery
@ -1470,9 +1353,7 @@ class PutVisualTextActionTest : VimTestCase() {
the dingy ${c}underside, the checquered fringe.
""".trimIndent()
configureByText(before)
val vimEditor = fixture.editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
injector.registerGroup.storeText(vimEditor, context,'+', "|found|\n|l roc|\n|ere i|", SelectionType.BLOCK_WISE)
injector.registerGroup.storeText('+', "|found|\n|l roc|\n|ere i|", SelectionType.BLOCK_WISE)
typeText(injector.parser.parseKeys("V" + "\"+p"))
val after = """
A Discovery
@ -1527,12 +1408,8 @@ class PutVisualTextActionTest : VimTestCase() {
hard by the torrent of a mountain pass.
""".trimIndent()
val editor = configureByText(before)
val vimEditor = editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
val registerService = injector.registerGroup
registerService.storeText(vimEditor, context, vimEditor.primaryCaret(), before rangeOf "Discovery", SelectionType.CHARACTER_WISE, false)
VimPlugin.getRegister().storeText(vimEditor, before rangeOf "Discovery", SelectionType.CHARACTER_WISE, false)
typeText(injector.parser.parseKeys("<C-V>2e2j" + "p"))
val after = """
A Discovery
@ -1557,12 +1434,8 @@ class PutVisualTextActionTest : VimTestCase() {
hard by the torrent of a mountain pass.
""".trimIndent()
val editor = configureByText(before)
val vimEditor = editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
val registerService = injector.registerGroup
registerService.storeText(vimEditor, context, vimEditor.primaryCaret(), before rangeOf "Discovery", SelectionType.CHARACTER_WISE, false)
VimPlugin.getRegister().storeText(vimEditor, before rangeOf "Discovery", SelectionType.CHARACTER_WISE, false)
typeText(injector.parser.parseKeys("<C-V>3e2k" + "p"))
val after = """
A Discovery
@ -1587,12 +1460,8 @@ class PutVisualTextActionTest : VimTestCase() {
hard by the torrent of a mountain pass.
""".trimIndent()
val editor = configureByText(before)
val vimEditor = editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
val registerService = injector.registerGroup
registerService.storeText(vimEditor, context, vimEditor.primaryCaret(), before rangeOf "Discovery", SelectionType.CHARACTER_WISE, false)
VimPlugin.getRegister().storeText(vimEditor, before rangeOf "Discovery", SelectionType.CHARACTER_WISE, false)
typeText(injector.parser.parseKeys("<C-V>2e2j" + "2p"))
val after = """
A Discovery
@ -1617,12 +1486,8 @@ class PutVisualTextActionTest : VimTestCase() {
ha|rd by the torrent of a mountain pass.
""".trimIndent()
val editor = configureByText(before)
val vimEditor = editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
val registerService = injector.registerGroup
registerService.storeText(vimEditor, context, vimEditor.primaryCaret(), before rangeOf "Discovery", SelectionType.CHARACTER_WISE, false)
VimPlugin.getRegister().storeText(vimEditor, before rangeOf "Discovery", SelectionType.CHARACTER_WISE, false)
typeText(injector.parser.parseKeys("<C-V>3j$" + "p"))
val after = """
A Discovery
@ -1660,12 +1525,8 @@ class PutVisualTextActionTest : VimTestCase() {
hard by the torrent of a mountain pass.
""".trimIndent()
val editor = configureByText(before)
val vimEditor = editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
val registerService = injector.registerGroup
registerService.storeText(vimEditor, context, vimEditor.primaryCaret(), before rangeOf "A Discovery\n", SelectionType.LINE_WISE, false)
VimPlugin.getRegister().storeText(vimEditor, before rangeOf "A Discovery\n", SelectionType.LINE_WISE, false)
typeText(injector.parser.parseKeys("<C-V>2e2j" + "p"))
val after = """
A Discovery
@ -1692,12 +1553,8 @@ class PutVisualTextActionTest : VimTestCase() {
hard by the torrent of a mountain pass.
""".trimIndent()
val editor = configureByText(before)
val vimEditor = editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
val registerService = injector.registerGroup
registerService.storeText(vimEditor, context, vimEditor.primaryCaret(), before rangeOf "A Discovery\n", SelectionType.LINE_WISE, false)
VimPlugin.getRegister().storeText(vimEditor, before rangeOf "A Discovery\n", SelectionType.LINE_WISE, false)
typeText(injector.parser.parseKeys("<C-V>2e2j" + "P"))
val after = """
A Discovery
@ -1735,12 +1592,8 @@ class PutVisualTextActionTest : VimTestCase() {
hard by the torrent of a mountain pass.
""".trimIndent()
val editor = configureByText(before)
val vimEditor = editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
val registerService = injector.registerGroup
registerService.storeText(vimEditor, context, vimEditor.primaryCaret(), before rangeOf "A Discovery\n", SelectionType.LINE_WISE, false)
VimPlugin.getRegister().storeText(vimEditor, before rangeOf "A Discovery\n", SelectionType.LINE_WISE, false)
typeText(injector.parser.parseKeys("<C-V>2e2j" + "2p"))
val after = """
A Discovery
@ -1779,12 +1632,8 @@ class PutVisualTextActionTest : VimTestCase() {
ha|rd by| the torrent of a mountain pass.
""".trimIndent()
val editor = configureByText(before)
val vimEditor = editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
val registerService = injector.registerGroup
registerService.storeText(vimEditor, context, vimEditor.primaryCaret(), before rangeOf "A Discovery\n", SelectionType.LINE_WISE, false)
VimPlugin.getRegister().storeText(vimEditor, before rangeOf "A Discovery\n", SelectionType.LINE_WISE, false)
typeText(injector.parser.parseKeys("<C-V>2e3j" + "p"))
val after = """
A Discovery
@ -1822,12 +1671,8 @@ class PutVisualTextActionTest : VimTestCase() {
hard by the torrent of a mountain pass.
""".trimIndent()
val editor = configureByText(before)
val vimEditor = editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
val registerService = injector.registerGroup
registerService.storeText(vimEditor, context, vimEditor.primaryCaret(), before rangeOf "A Discovery\n", SelectionType.LINE_WISE, false)
VimPlugin.getRegister().storeText(vimEditor, before rangeOf "A Discovery\n", SelectionType.LINE_WISE, false)
typeText(injector.parser.parseKeys("<C-V>2j$" + "p"))
val after = """
A Discovery
@ -1861,12 +1706,8 @@ class PutVisualTextActionTest : VimTestCase() {
the dingy underside, the checquered fringe.
""".trimIndent()
val editor = configureByText(before)
val vimEditor = editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
val registerService = injector.registerGroup
registerService.storeText(vimEditor, context, vimEditor.primaryCaret(), editor.rangeOf("|found|", 2), SelectionType.BLOCK_WISE, false)
VimPlugin.getRegister().storeText(vimEditor, editor.rangeOf("|found|", 2), SelectionType.BLOCK_WISE, false)
typeText(injector.parser.parseKeys("<C-V>2e2j" + "p"))
val after = """
A Discovery
@ -1901,12 +1742,8 @@ class PutVisualTextActionTest : VimTestCase() {
the |dingy un|derside, the checquered fringe.
""".trimIndent()
val editor = configureByText(before)
val vimEditor = editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
val registerService = injector.registerGroup
registerService.storeText(vimEditor, context, vimEditor.primaryCaret(), editor.rangeOf("|found|", 2), SelectionType.BLOCK_WISE, false)
VimPlugin.getRegister().storeText(vimEditor, editor.rangeOf("|found|", 2), SelectionType.BLOCK_WISE, false)
typeText(injector.parser.parseKeys("<C-V>2e3j" + "p"))
val after = """
A Discovery
@ -1941,12 +1778,8 @@ class PutVisualTextActionTest : VimTestCase() {
the dingy underside, the checquered fringe.
""".trimIndent()
val editor = configureByText(before)
val vimEditor = editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
val registerService = injector.registerGroup
registerService.storeText(vimEditor, context, vimEditor.primaryCaret(), editor.rangeOf("|found|", 2), SelectionType.BLOCK_WISE, false)
VimPlugin.getRegister().storeText(vimEditor, editor.rangeOf("|found|", 2), SelectionType.BLOCK_WISE, false)
typeText(injector.parser.parseKeys("<C-V>2ej" + "p"))
val after = """
A Discovery
@ -1982,10 +1815,7 @@ class PutVisualTextActionTest : VimTestCase() {
""".trimIndent()
val editor = configureByText(before)
val vimEditor = editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
val registerService = injector.registerGroup
registerService.storeText(vimEditor, context, vimEditor.primaryCaret(), editor.rangeOf("|found|", 2), SelectionType.BLOCK_WISE, false)
VimPlugin.getRegister().storeText(vimEditor, editor.rangeOf("|found|", 2), SelectionType.BLOCK_WISE, false)
typeText(injector.parser.parseKeys("<C-V>elj" + "p"))
val after = """
A Discovery
@ -2021,12 +1851,8 @@ class PutVisualTextActionTest : VimTestCase() {
the dingy underside, the checquered fringe.
""".trimIndent()
val editor = configureByText(before)
val vimEditor = editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
val registerService = injector.registerGroup
registerService.storeText(vimEditor, context, vimEditor.primaryCaret(), editor.rangeOf("|found|", 2), SelectionType.BLOCK_WISE, false)
VimPlugin.getRegister().storeText(vimEditor, editor.rangeOf("|found|", 2), SelectionType.BLOCK_WISE, false)
typeText(injector.parser.parseKeys("<C-V>2j$" + "p"))
val after = """
A Discovery

View File

@ -8,6 +8,7 @@
package org.jetbrains.plugins.ideavim.action.copy
import com.maddyhome.idea.vim.VimPlugin
import com.maddyhome.idea.vim.api.injector
import com.maddyhome.idea.vim.common.TextRange
import com.maddyhome.idea.vim.newapi.vim
@ -32,9 +33,7 @@ class PutVisualTextMoveCursorActionTest : VimTestCase() {
val before = "${c}I found it in a legendary land"
val editor = configureByText(before)
val vimEditor = editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
val registerService = injector.registerGroup
registerService.storeText(vimEditor, context, vimEditor.primaryCaret(), TextRange(16, 25), SelectionType.CHARACTER_WISE, false)
VimPlugin.getRegister().storeText(vimEditor, TextRange(16, 25), SelectionType.CHARACTER_WISE, false)
typeText(injector.parser.parseKeys("v2e" + "2gp"))
val after = "legendarylegendary$c in a legendary land"
assertState(after)
@ -46,9 +45,7 @@ class PutVisualTextMoveCursorActionTest : VimTestCase() {
val before = "${c}I found it in a legendary land"
val editor = configureByText(before)
val vimEditor = editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
val registerService = injector.registerGroup
registerService.storeText(vimEditor, context, vimEditor.primaryCaret(), TextRange(16, 25), SelectionType.LINE_WISE, false)
VimPlugin.getRegister().storeText(vimEditor, TextRange(16, 25), SelectionType.LINE_WISE, false)
typeText(injector.parser.parseKeys("v2e" + "gp"))
val after = """
@ -64,9 +61,7 @@ class PutVisualTextMoveCursorActionTest : VimTestCase() {
val before = "${c}I found it in a legendary land"
val editor = configureByText(before)
val vimEditor = editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
val registerService = injector.registerGroup
registerService.storeText(vimEditor, context, vimEditor.primaryCaret(), TextRange(16, 25), SelectionType.CHARACTER_WISE, false)
VimPlugin.getRegister().storeText(vimEditor, TextRange(16, 25), SelectionType.CHARACTER_WISE, false)
typeText(injector.parser.parseKeys("V" + "gp"))
val after = "legendary\n$c"
assertState(after)
@ -93,9 +88,7 @@ class PutVisualTextMoveCursorActionTest : VimTestCase() {
""".trimIndent()
val editor = configureByText(file)
val vimEditor = editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
val registerService = injector.registerGroup
registerService.storeText(vimEditor, context, vimEditor.primaryCaret(), TextRange(2, 11), SelectionType.LINE_WISE, false)
VimPlugin.getRegister().storeText(vimEditor, TextRange(2, 11), SelectionType.LINE_WISE, false)
typeText(injector.parser.parseKeys("V" + "gp"))
assertState(newFile)
}
@ -141,9 +134,7 @@ class PutVisualTextMoveCursorActionTest : VimTestCase() {
val before = "${c}I found it in a legendary land"
val editor = configureByText(before)
val vimEditor = editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
val registerService = injector.registerGroup
registerService.storeText(vimEditor, context, vimEditor.primaryCaret(), TextRange(16, 25), SelectionType.LINE_WISE, false)
VimPlugin.getRegister().storeText(vimEditor, TextRange(16, 25), SelectionType.LINE_WISE, false)
typeText(injector.parser.parseKeys("v2e" + "gP"))
val after = """
@ -159,9 +150,7 @@ class PutVisualTextMoveCursorActionTest : VimTestCase() {
val before = "${c}I found it in a legendary land"
val editor = configureByText(before)
val vimEditor = editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
val registerService = injector.registerGroup
registerService.storeText(vimEditor, context, vimEditor.primaryCaret(), TextRange(16, 25), SelectionType.CHARACTER_WISE, false)
VimPlugin.getRegister().storeText(vimEditor, TextRange(16, 25), SelectionType.CHARACTER_WISE, false)
typeText(injector.parser.parseKeys("v2e" + "2gP"))
val after = "legendarylegendary$c in a legendary land"
assertState(after)
@ -173,9 +162,7 @@ class PutVisualTextMoveCursorActionTest : VimTestCase() {
val before = "${c}I found it in a legendary land"
val editor = configureByText(before)
val vimEditor = editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
val registerService = injector.registerGroup
registerService.storeText(vimEditor, context, vimEditor.primaryCaret(), TextRange(16, 25), SelectionType.CHARACTER_WISE, false)
VimPlugin.getRegister().storeText(vimEditor, TextRange(16, 25), SelectionType.CHARACTER_WISE, false)
typeText(injector.parser.parseKeys("v$" + "2gP"))
val after = "legendarylegendar${c}y"
assertState(after)
@ -187,9 +174,7 @@ class PutVisualTextMoveCursorActionTest : VimTestCase() {
val before = "${c}I found it in a legendary land"
val editor = configureByText(before)
val vimEditor = editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
val registerService = injector.registerGroup
registerService.storeText(vimEditor, context, vimEditor.primaryCaret(), TextRange(16, 25), SelectionType.CHARACTER_WISE, false)
VimPlugin.getRegister().storeText(vimEditor, TextRange(16, 25), SelectionType.CHARACTER_WISE, false)
typeText(injector.parser.parseKeys("V" + "gP"))
val after = "legendary\n$c"
assertState(after)
@ -230,9 +215,7 @@ class PutVisualTextMoveCursorActionTest : VimTestCase() {
""".trimIndent()
configureByText(before)
val vimEditor = fixture.editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
injector.registerGroup.storeText(vimEditor, context, '+', "zxcvbn\n", SelectionType.LINE_WISE)
injector.registerGroup.storeText('+', "zxcvbn\n", SelectionType.LINE_WISE)
typeText(injector.parser.parseKeys("vl" + "\"+gp"))
val after = """
q
@ -260,9 +243,7 @@ class PutVisualTextMoveCursorActionTest : VimTestCase() {
""".trimIndent()
configureByText(before)
val vimEditor = fixture.editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
injector.registerGroup.storeText(vimEditor, context, '+', "zxcvbn\n", SelectionType.LINE_WISE)
injector.registerGroup.storeText('+', "zxcvbn\n", SelectionType.LINE_WISE)
typeText(injector.parser.parseKeys("vl" + "\"+gp"))
val after = """
q
@ -292,9 +273,7 @@ class PutVisualTextMoveCursorActionTest : VimTestCase() {
""".trimIndent()
val editor = configureByText(before)
val vimEditor = editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
val registerService = injector.registerGroup
registerService.storeText(vimEditor, context, vimEditor.primaryCaret(), TextRange(16, 19), SelectionType.BLOCK_WISE, false)
VimPlugin.getRegister().storeText(vimEditor, TextRange(16, 19), SelectionType.BLOCK_WISE, false)
typeText(injector.parser.parseKeys("<S-v>" + "gp"))
val after = """
${c}fgh
@ -320,9 +299,7 @@ class PutVisualTextMoveCursorActionTest : VimTestCase() {
""".trimIndent()
val editor = configureByText(before)
val vimEditor = editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
val registerService = injector.registerGroup
registerService.storeText(vimEditor, context, vimEditor.primaryCaret(), TextRange(16, 19), SelectionType.LINE_WISE, false)
VimPlugin.getRegister().storeText(vimEditor, TextRange(16, 19), SelectionType.LINE_WISE, false)
typeText(injector.parser.parseKeys("<C-v>" + "h" + "gp"))
val after = """
q
@ -343,9 +320,7 @@ class PutVisualTextMoveCursorActionTest : VimTestCase() {
val before = "${c}qwe asd ${c}zxc rty ${c}fgh vbn"
val editor = configureByText(before)
val vimEditor = editor.vim
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
val registerService = injector.registerGroup
registerService.storeText(vimEditor, context, vimEditor.primaryCaret(), TextRange(16, 19), SelectionType.CHARACTER_WISE, false)
VimPlugin.getRegister().storeText(vimEditor, TextRange(16, 19), SelectionType.CHARACTER_WISE, false)
typeText(injector.parser.parseKeys("v2e" + "2gp"))
val after = "fghfgh$c fghfgh$c fghfgh$c"
assertState(after)

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