mirror of
https://github.com/chylex/IntelliJ-IdeaVim.git
synced 2025-09-15 17:32:14 +02:00
Compare commits
135 Commits
VIM-2227
...
86bf723791
Author | SHA1 | Date | |
---|---|---|---|
![]() |
86bf723791 | ||
![]() |
71f2e9de4a | ||
![]() |
33d3f270a3 | ||
![]() |
da94edd386 | ||
![]() |
90dfaefd11 | ||
![]() |
8bc616cc55 | ||
![]() |
a9e79d62c5 | ||
![]() |
1998221a0b | ||
![]() |
a9b1625749 | ||
![]() |
b411836570 | ||
![]() |
df7e0221a8 | ||
![]() |
8ff8f2b685 | ||
![]() |
65dea7e3f7 | ||
![]() |
1942f86633 | ||
![]() |
ee4ce5033a | ||
![]() |
040fe806c8 | ||
![]() |
97f5c9225e | ||
![]() |
09b86c15f9 | ||
![]() |
8f34285d8c | ||
![]() |
d3c3b71e3e | ||
![]() |
aa6f49c9b1 | ||
![]() |
c011628420 | ||
![]() |
1c9fa9d662 | ||
![]() |
7b9bc64364 | ||
![]() |
729062bfdd | ||
![]() |
bc6c726a45 | ||
![]() |
dfc3df713e | ||
![]() |
42eca1d5f2 | ||
![]() |
66245e2730 | ||
![]() |
d44b82c1d1 | ||
![]() |
5440e48fa3 | ||
![]() |
1c513cf8aa | ||
![]() |
a17c4b8d43 | ||
![]() |
15eb4ac278 | ||
![]() |
0d9b81eab3 | ||
![]() |
f02e1a20c7 | ||
![]() |
a11991dad7 | ||
![]() |
1238828bfd | ||
![]() |
ba409cb24c | ||
![]() |
d597670275 | ||
![]() |
d8540e95f8 | ||
![]() |
d35ebf00dd | ||
![]() |
2b32cb26b1 | ||
![]() |
ca95fcb658 | ||
![]() |
cc18bbd168 | ||
![]() |
8c8ea800cb | ||
![]() |
0746dcc686 | ||
![]() |
930650be9d | ||
![]() |
4e3a9ffa40 | ||
![]() |
3bf68a2bb8 | ||
![]() |
a80f6feab0 | ||
![]() |
3cf8ae52ed | ||
![]() |
62632a4514 | ||
![]() |
249bd3778a | ||
![]() |
ab9e5d7a4a | ||
![]() |
083b7dc952 | ||
![]() |
1791692d92 | ||
![]() |
ba23c9ab5e | ||
![]() |
f96ab37bcb | ||
![]() |
0da34bbb34 | ||
![]() |
51e7c745ea | ||
![]() |
8347251572 | ||
![]() |
ce8512f4e0 | ||
![]() |
a724a19d00 | ||
![]() |
7eae7a98e8 | ||
![]() |
fe9566eebd | ||
![]() |
b69756730f | ||
![]() |
6cd1a60b53 | ||
![]() |
9d935e47b5 | ||
![]() |
a7d5372d06 | ||
![]() |
a575942c81 | ||
![]() |
3cf6c53a8e | ||
![]() |
91d86680de | ||
![]() |
d1d082fb99 | ||
![]() |
2c634d1bf0 | ||
![]() |
02a6fe4dc9 | ||
![]() |
223d681526 | ||
![]() |
f42ef1c2fc | ||
![]() |
f4817b2111 | ||
![]() |
6f5def0abf | ||
![]() |
f0fcd7f133 | ||
![]() |
6115adb72e | ||
![]() |
bfd0b5fd91 | ||
![]() |
6c0a52155b | ||
![]() |
c7ebce39bf | ||
![]() |
a0dc7a792f | ||
![]() |
fdb09a8f1f | ||
![]() |
4ac2aa2339 | ||
![]() |
ebbc20692a | ||
![]() |
5c82d112c9 | ||
![]() |
40fd50d7f1 | ||
![]() |
f7b948fee2 | ||
![]() |
6cdcf133bb | ||
![]() |
f3025757b6 | ||
![]() |
a49811a3f9 | ||
![]() |
2ac4b265d1 | ||
![]() |
46e994b563 | ||
![]() |
81482bd298 | ||
![]() |
f1a239c085 | ||
![]() |
a48e38de7b | ||
![]() |
0aaacee117 | ||
![]() |
b8373af69f | ||
![]() |
e99b2ee73d | ||
![]() |
705022331a | ||
![]() |
bf62d444bf | ||
![]() |
5dcff5657b | ||
![]() |
7e79d5a960 | ||
![]() |
c1b480976d | ||
![]() |
ddabbe6891 | ||
![]() |
ffa3052b50 | ||
![]() |
654ea88851 | ||
![]() |
4dc7982baa | ||
![]() |
ae2fc1cd85 | ||
![]() |
78bc8666e6 | ||
![]() |
9c2de2cfc7 | ||
![]() |
71e81465f3 | ||
![]() |
885031e086 | ||
![]() |
d77c5bb5cf | ||
![]() |
781bce0000 | ||
![]() |
a3ca1b965b | ||
![]() |
dd20b480a7 | ||
![]() |
38292e97af | ||
![]() |
46ea752164 | ||
![]() |
194b744361 | ||
b50197f7ce | |||
![]() |
c00703d1d0 | ||
![]() |
6e12377116 | ||
![]() |
b0c4391ad8 | ||
![]() |
f43ac2538a | ||
![]() |
9eaf8b5d2d | ||
![]() |
e365d0b07c | ||
![]() |
69c273c4a5 | ||
![]() |
f7950e7adb | ||
![]() |
7c1ae9812e | ||
![]() |
5c794ac40e |
3
.github/workflows/mergePr.yml
vendored
3
.github/workflows/mergePr.yml
vendored
@@ -4,6 +4,7 @@
|
|||||||
name: Update Changelog On PR
|
name: Update Changelog On PR
|
||||||
|
|
||||||
on:
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
pull_request:
|
pull_request:
|
||||||
types: [ closed ]
|
types: [ closed ]
|
||||||
|
|
||||||
@@ -29,7 +30,7 @@ jobs:
|
|||||||
id: update_authors
|
id: update_authors
|
||||||
run: ./gradlew updateMergedPr -PprId=${{ github.event.number }}
|
run: ./gradlew updateMergedPr -PprId=${{ github.event.number }}
|
||||||
env:
|
env:
|
||||||
GITHUB_OAUTH: ${{ secrets.AUTOMATION_TOKEN }}
|
GITHUB_OAUTH: ${{ secrets.MERGE_PR }}
|
||||||
|
|
||||||
- name: Commit changes
|
- name: Commit changes
|
||||||
uses: stefanzweifel/git-auto-commit-action@v4
|
uses: stefanzweifel/git-auto-commit-action@v4
|
||||||
|
40
.github/workflows/mergePrTest.yml
vendored
Normal file
40
.github/workflows/mergePrTest.yml
vendored
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
# This workflow will build a package using Gradle and then publish it to GitHub packages when a release is created
|
||||||
|
# For more information see: https://github.com/actions/setup-java/blob/main/docs/advanced-usage.md#Publishing-using-gradle
|
||||||
|
|
||||||
|
name: Update Changelog On PR (Test)
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
with:
|
||||||
|
fetch-depth: 50
|
||||||
|
- name: Set up JDK 11
|
||||||
|
uses: actions/setup-java@v2
|
||||||
|
with:
|
||||||
|
java-version: '11'
|
||||||
|
distribution: 'adopt'
|
||||||
|
server-id: github # Value of the distributionManagement/repository/id field of the pom.xml
|
||||||
|
settings-path: ${{ github.workspace }} # location for the settings.xml file
|
||||||
|
|
||||||
|
- name: Update authors
|
||||||
|
id: update_authors
|
||||||
|
run: ./gradlew updateMergedPr -PprId=525
|
||||||
|
env:
|
||||||
|
GITHUB_OAUTH: ${{ secrets.MERGE_PR }}
|
||||||
|
|
||||||
|
# - name: Commit changes
|
||||||
|
# uses: stefanzweifel/git-auto-commit-action@v4
|
||||||
|
# with:
|
||||||
|
# branch: master
|
||||||
|
# commit_message: Update changelog after merging PR
|
||||||
|
# commit_user_name: Alex Plate
|
||||||
|
# commit_user_email: aleksei.plate@jetbrains.com
|
||||||
|
# commit_author: Alex Plate <aleksei.plate@jetbrains.com>
|
||||||
|
# file_pattern: CHANGES.md
|
2
.github/workflows/updateAuthors.yml
vendored
2
.github/workflows/updateAuthors.yml
vendored
@@ -37,7 +37,7 @@ jobs:
|
|||||||
run: ./gradlew updateAuthors --stacktrace
|
run: ./gradlew updateAuthors --stacktrace
|
||||||
env:
|
env:
|
||||||
SUCCESS_COMMIT: ${{ steps.last_successful_commit.outputs.commit_hash }}
|
SUCCESS_COMMIT: ${{ steps.last_successful_commit.outputs.commit_hash }}
|
||||||
GITHUB_OAUTH: ${{ secrets.AUTOMATION_TOKEN }}
|
GITHUB_OAUTH: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
- name: Commit changes
|
- name: Commit changes
|
||||||
uses: stefanzweifel/git-auto-commit-action@v4
|
uses: stefanzweifel/git-auto-commit-action@v4
|
||||||
|
3
.teamcity/_Self/Constants.kt
vendored
3
.teamcity/_Self/Constants.kt
vendored
@@ -13,7 +13,8 @@ object Constants {
|
|||||||
const val PROPERTY_TESTS = "LATEST-EAP-SNAPSHOT"
|
const val PROPERTY_TESTS = "LATEST-EAP-SNAPSHOT"
|
||||||
const val LONG_RUNNING_TESTS = "LATEST-EAP-SNAPSHOT"
|
const val LONG_RUNNING_TESTS = "LATEST-EAP-SNAPSHOT"
|
||||||
const val QODANA_TESTS = "LATEST-EAP-SNAPSHOT"
|
const val QODANA_TESTS = "LATEST-EAP-SNAPSHOT"
|
||||||
const val RELEASE = "2021.3"
|
const val RELEASE = "LATEST-EAP-SNAPSHOT"
|
||||||
|
|
||||||
const val RELEASE_DEV = "LATEST-EAP-SNAPSHOT"
|
const val RELEASE_DEV = "LATEST-EAP-SNAPSHOT"
|
||||||
const val RELEASE_EAP = "LATEST-EAP-SNAPSHOT"
|
const val RELEASE_EAP = "LATEST-EAP-SNAPSHOT"
|
||||||
}
|
}
|
||||||
|
14
.teamcity/_Self/Project.kt
vendored
14
.teamcity/_Self/Project.kt
vendored
@@ -1,6 +1,12 @@
|
|||||||
package _Self
|
package _Self
|
||||||
|
|
||||||
import _Self.buildTypes.*
|
import _Self.buildTypes.Compatibility
|
||||||
|
import _Self.buildTypes.LongRunning
|
||||||
|
import _Self.buildTypes.Nvim
|
||||||
|
import _Self.buildTypes.PluginVerifier
|
||||||
|
import _Self.buildTypes.PropertyBased
|
||||||
|
import _Self.buildTypes.Qodana
|
||||||
|
import _Self.buildTypes.TestsForIntelliJEAP
|
||||||
import _Self.subprojects.GitHub
|
import _Self.subprojects.GitHub
|
||||||
import _Self.subprojects.OldTests
|
import _Self.subprojects.OldTests
|
||||||
import _Self.subprojects.Releases
|
import _Self.subprojects.Releases
|
||||||
@@ -10,6 +16,7 @@ import _Self.vcsRoots.Branch_191_193
|
|||||||
import _Self.vcsRoots.Branch_201
|
import _Self.vcsRoots.Branch_201
|
||||||
import _Self.vcsRoots.Branch_202
|
import _Self.vcsRoots.Branch_202
|
||||||
import _Self.vcsRoots.Branch_203_212
|
import _Self.vcsRoots.Branch_203_212
|
||||||
|
import _Self.vcsRoots.Branch_213_221
|
||||||
import _Self.vcsRoots.Branch_Release
|
import _Self.vcsRoots.Branch_Release
|
||||||
import _Self.vcsRoots.GitHubPullRequest
|
import _Self.vcsRoots.GitHubPullRequest
|
||||||
import jetbrains.buildServer.configs.kotlin.v2019_2.Project
|
import jetbrains.buildServer.configs.kotlin.v2019_2.Project
|
||||||
@@ -26,11 +33,11 @@ object Project : Project({
|
|||||||
vcsRoot(Branch_201)
|
vcsRoot(Branch_201)
|
||||||
vcsRoot(Branch_202)
|
vcsRoot(Branch_202)
|
||||||
vcsRoot(Branch_203_212)
|
vcsRoot(Branch_203_212)
|
||||||
|
vcsRoot(Branch_213_221)
|
||||||
vcsRoot(Branch_Release)
|
vcsRoot(Branch_Release)
|
||||||
vcsRoot(GitHubPullRequest)
|
vcsRoot(GitHubPullRequest)
|
||||||
|
|
||||||
// Builds
|
// Builds
|
||||||
buildType(TestsForIntelliJ20213)
|
|
||||||
buildType(TestsForIntelliJEAP)
|
buildType(TestsForIntelliJEAP)
|
||||||
|
|
||||||
buildType(PropertyBased)
|
buildType(PropertyBased)
|
||||||
@@ -38,6 +45,7 @@ object Project : Project({
|
|||||||
|
|
||||||
buildType(Nvim)
|
buildType(Nvim)
|
||||||
buildType(PluginVerifier)
|
buildType(PluginVerifier)
|
||||||
|
buildType(Compatibility)
|
||||||
|
|
||||||
buildType(Qodana)
|
buildType(Qodana)
|
||||||
|
|
||||||
@@ -47,7 +55,7 @@ object Project : Project({
|
|||||||
type = "CloudImage"
|
type = "CloudImage"
|
||||||
id = "PROJECT_EXT_768"
|
id = "PROJECT_EXT_768"
|
||||||
param("agent_pool_id", "41")
|
param("agent_pool_id", "41")
|
||||||
param("amazon-id", "ami-0d1a6a32faa92923e")
|
param("amazon-id", "ami-0fa17ce8238eb8868")
|
||||||
param("ebs-optimized", "false")
|
param("ebs-optimized", "false")
|
||||||
param("image-instances-limit", "")
|
param("image-instances-limit", "")
|
||||||
param("image-name-prefix", "BuildAgentsIdeaVim")
|
param("image-name-prefix", "BuildAgentsIdeaVim")
|
||||||
|
2
.teamcity/_Self/buildTypes/ActiveTests.kt
vendored
2
.teamcity/_Self/buildTypes/ActiveTests.kt
vendored
@@ -55,4 +55,4 @@ sealed class ActiveTests(buildName: String, ijVersion: String) : BuildType({
|
|||||||
})
|
})
|
||||||
|
|
||||||
object TestsForIntelliJEAP : ActiveTests("Tests for IntelliJ Latest EAP", "LATEST-EAP-SNAPSHOT")
|
object TestsForIntelliJEAP : ActiveTests("Tests for IntelliJ Latest EAP", "LATEST-EAP-SNAPSHOT")
|
||||||
object TestsForIntelliJ20213 : ActiveTests("Tests for IntelliJ 2021.3", "2021.3.2")
|
//object TestsForIntelliJ20213 : ActiveTests("Tests for IntelliJ 2021.3", "2021.3.2")
|
||||||
|
49
.teamcity/_Self/buildTypes/Compatibility.kt
vendored
Normal file
49
.teamcity/_Self/buildTypes/Compatibility.kt
vendored
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
package _Self.buildTypes
|
||||||
|
|
||||||
|
import jetbrains.buildServer.configs.kotlin.v2019_2.BuildType
|
||||||
|
import jetbrains.buildServer.configs.kotlin.v2019_2.DslContext
|
||||||
|
import jetbrains.buildServer.configs.kotlin.v2019_2.buildFeatures.golang
|
||||||
|
import jetbrains.buildServer.configs.kotlin.v2019_2.buildSteps.script
|
||||||
|
import jetbrains.buildServer.configs.kotlin.v2019_2.triggers.schedule
|
||||||
|
|
||||||
|
object Compatibility : BuildType({
|
||||||
|
id("IdeaVimCompatibility")
|
||||||
|
name = "IdeaVim compatibility with external plugins"
|
||||||
|
|
||||||
|
vcs {
|
||||||
|
root(DslContext.settingsRoot)
|
||||||
|
}
|
||||||
|
|
||||||
|
steps {
|
||||||
|
script {
|
||||||
|
name = "Check"
|
||||||
|
scriptContent = """
|
||||||
|
java -jar verifier/verifier-cli-dev-all.jar check-plugin '${'$'}org.jetbrains.IdeaVim-EasyMotion' [latest-IU] -team-city
|
||||||
|
java -jar verifier/verifier-cli-dev-all.jar check-plugin '${'$'}io.github.mishkun.ideavimsneak' [latest-IU] -team-city
|
||||||
|
java -jar verifier/verifier-cli-dev-all.jar check-plugin '${'$'}eu.theblob42.idea.whichkey' [latest-IU] -team-city
|
||||||
|
java -jar verifier/verifier-cli-dev-all.jar check-plugin '${'$'}IdeaVimExtension' [latest-IU] -team-city
|
||||||
|
# Outdated java -jar verifier/verifier-cli-dev-all.jar check-plugin '${'$'}github.zgqq.intellij-enhance' [latest-IU] -team-city
|
||||||
|
java -jar verifier/verifier-cli-dev-all.jar check-plugin '${'$'}com.github.copilot' [latest-IU] -team-city
|
||||||
|
java -jar verifier/verifier-cli-dev-all.jar check-plugin '${'$'}com.github.dankinsoid.multicursor' [latest-IU] -team-city
|
||||||
|
java -jar verifier/verifier-cli-dev-all.jar check-plugin '${'$'}com.joshestein.ideavim-quickscope' [latest-IU] -team-city
|
||||||
|
""".trimIndent()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
triggers {
|
||||||
|
schedule {
|
||||||
|
schedulingPolicy = daily {
|
||||||
|
hour = 4
|
||||||
|
}
|
||||||
|
branchFilter = ""
|
||||||
|
triggerBuild = always()
|
||||||
|
withPendingChangesOnly = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
features {
|
||||||
|
golang {
|
||||||
|
testFormat = "json"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
2
.teamcity/_Self/buildTypes/Nvim.kt
vendored
2
.teamcity/_Self/buildTypes/Nvim.kt
vendored
@@ -31,7 +31,7 @@ object Nvim : BuildType({
|
|||||||
script {
|
script {
|
||||||
name = "Set up NeoVim"
|
name = "Set up NeoVim"
|
||||||
scriptContent = """
|
scriptContent = """
|
||||||
wget https://github.com/neovim/neovim/releases/download/v0.4.4/nvim-linux64.tar.gz
|
wget https://github.com/neovim/neovim/releases/download/v0.7.2/nvim-linux64.tar.gz
|
||||||
tar xzf nvim-linux64.tar.gz
|
tar xzf nvim-linux64.tar.gz
|
||||||
cd nvim-linux64/bin
|
cd nvim-linux64/bin
|
||||||
chmod +x nvim
|
chmod +x nvim
|
||||||
|
6
.teamcity/_Self/buildTypes/Qodana.kt
vendored
6
.teamcity/_Self/buildTypes/Qodana.kt
vendored
@@ -4,6 +4,7 @@ import _Self.Constants.QODANA_TESTS
|
|||||||
import jetbrains.buildServer.configs.kotlin.v2019_2.BuildType
|
import jetbrains.buildServer.configs.kotlin.v2019_2.BuildType
|
||||||
import jetbrains.buildServer.configs.kotlin.v2019_2.CheckoutMode
|
import jetbrains.buildServer.configs.kotlin.v2019_2.CheckoutMode
|
||||||
import jetbrains.buildServer.configs.kotlin.v2019_2.DslContext
|
import jetbrains.buildServer.configs.kotlin.v2019_2.DslContext
|
||||||
|
import jetbrains.buildServer.configs.kotlin.v2019_2.buildSteps.Qodana
|
||||||
import jetbrains.buildServer.configs.kotlin.v2019_2.buildSteps.qodana
|
import jetbrains.buildServer.configs.kotlin.v2019_2.buildSteps.qodana
|
||||||
import jetbrains.buildServer.configs.kotlin.v2019_2.failureConditions.BuildFailureOnMetric
|
import jetbrains.buildServer.configs.kotlin.v2019_2.failureConditions.BuildFailureOnMetric
|
||||||
import jetbrains.buildServer.configs.kotlin.v2019_2.failureConditions.failOnMetricChange
|
import jetbrains.buildServer.configs.kotlin.v2019_2.failureConditions.failOnMetricChange
|
||||||
@@ -46,12 +47,15 @@ object Qodana : BuildType({
|
|||||||
param("clonefinder-enable", "true")
|
param("clonefinder-enable", "true")
|
||||||
param("clonefinder-reference-projects", "src")
|
param("clonefinder-reference-projects", "src")
|
||||||
param("yaml-configuration", "")
|
param("yaml-configuration", "")
|
||||||
|
linter = jvm {
|
||||||
|
version = Qodana.JVMVersion.LATEST
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
triggers {
|
triggers {
|
||||||
vcs {
|
vcs {
|
||||||
enabled = false
|
enabled = true
|
||||||
branchFilter = ""
|
branchFilter = ""
|
||||||
}
|
}
|
||||||
schedule {
|
schedule {
|
||||||
|
62
.teamcity/_Self/buildTypes/TestsForIntelliJ_213-221.kt
vendored
Normal file
62
.teamcity/_Self/buildTypes/TestsForIntelliJ_213-221.kt
vendored
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
@file:Suppress("ClassName")
|
||||||
|
|
||||||
|
package _Self.buildTypes
|
||||||
|
|
||||||
|
import jetbrains.buildServer.configs.kotlin.v2019_2.BuildType
|
||||||
|
import jetbrains.buildServer.configs.kotlin.v2019_2.CheckoutMode
|
||||||
|
import jetbrains.buildServer.configs.kotlin.v2019_2.buildSteps.gradle
|
||||||
|
import jetbrains.buildServer.configs.kotlin.v2019_2.failureConditions.BuildFailureOnMetric
|
||||||
|
import jetbrains.buildServer.configs.kotlin.v2019_2.failureConditions.failOnMetricChange
|
||||||
|
import jetbrains.buildServer.configs.kotlin.v2019_2.triggers.vcs
|
||||||
|
|
||||||
|
sealed class TestsForIntelliJ_213_221_branch(private val version: String) : BuildType({
|
||||||
|
name = "Tests for IntelliJ $version"
|
||||||
|
|
||||||
|
params {
|
||||||
|
param("env.ORG_GRADLE_PROJECT_downloadIdeaSources", "false")
|
||||||
|
param("env.ORG_GRADLE_PROJECT_legacyNoJavaPlugin", "true")
|
||||||
|
param("env.ORG_GRADLE_PROJECT_ideaVersion", "IC-$version")
|
||||||
|
param("env.ORG_GRADLE_PROJECT_instrumentPluginCode", "false")
|
||||||
|
param("env.ORG_GRADLE_PROJECT_javaVersion", "1.8")
|
||||||
|
}
|
||||||
|
|
||||||
|
vcs {
|
||||||
|
root(_Self.vcsRoots.Branch_213_221)
|
||||||
|
|
||||||
|
checkoutMode = CheckoutMode.AUTO
|
||||||
|
}
|
||||||
|
|
||||||
|
steps {
|
||||||
|
gradle {
|
||||||
|
tasks = "clean test"
|
||||||
|
buildFile = ""
|
||||||
|
enableStacktrace = true
|
||||||
|
param("org.jfrog.artifactory.selectedDeployableServer.defaultModuleVersionConfiguration", "GLOBAL")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
triggers {
|
||||||
|
vcs {
|
||||||
|
branchFilter = ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
requirements {
|
||||||
|
noLessThanVer("teamcity.agent.jvm.version", "1.8")
|
||||||
|
}
|
||||||
|
|
||||||
|
failureConditions {
|
||||||
|
failOnMetricChange {
|
||||||
|
metric = BuildFailureOnMetric.MetricType.TEST_COUNT
|
||||||
|
threshold = 20
|
||||||
|
units = BuildFailureOnMetric.MetricUnit.PERCENTS
|
||||||
|
comparison = BuildFailureOnMetric.MetricComparison.LESS
|
||||||
|
compareTo = build {
|
||||||
|
buildRule = lastSuccessful()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
object TestsForIntelliJ20213 : TestsForIntelliJ_213_221_branch("2021.3.2")
|
2
.teamcity/_Self/subprojects/OldTests.kt
vendored
2
.teamcity/_Self/subprojects/OldTests.kt
vendored
@@ -11,6 +11,7 @@ import _Self.buildTypes.TestsForIntelliJ20202
|
|||||||
import _Self.buildTypes.TestsForIntelliJ20203
|
import _Self.buildTypes.TestsForIntelliJ20203
|
||||||
import _Self.buildTypes.TestsForIntelliJ20211
|
import _Self.buildTypes.TestsForIntelliJ20211
|
||||||
import _Self.buildTypes.TestsForIntelliJ20212
|
import _Self.buildTypes.TestsForIntelliJ20212
|
||||||
|
import _Self.buildTypes.TestsForIntelliJ20213
|
||||||
import jetbrains.buildServer.configs.kotlin.v2019_2.Project
|
import jetbrains.buildServer.configs.kotlin.v2019_2.Project
|
||||||
|
|
||||||
object OldTests : Project({
|
object OldTests : Project({
|
||||||
@@ -28,4 +29,5 @@ object OldTests : Project({
|
|||||||
buildType(TestsForIntelliJ20203)
|
buildType(TestsForIntelliJ20203)
|
||||||
buildType(TestsForIntelliJ20211)
|
buildType(TestsForIntelliJ20211)
|
||||||
buildType(TestsForIntelliJ20212)
|
buildType(TestsForIntelliJ20212)
|
||||||
|
buildType(TestsForIntelliJ20213)
|
||||||
})
|
})
|
||||||
|
12
.teamcity/_Self/vcsRoots/Branch_213_221.kt
vendored
Normal file
12
.teamcity/_Self/vcsRoots/Branch_213_221.kt
vendored
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
@file:Suppress("ClassName")
|
||||||
|
|
||||||
|
package _Self.vcsRoots
|
||||||
|
|
||||||
|
import jetbrains.buildServer.configs.kotlin.v2019_2.vcs.GitVcsRoot
|
||||||
|
|
||||||
|
object Branch_213_221 : GitVcsRoot({
|
||||||
|
id("HttpsGithubComJetBrainsIdeavimBranch213221")
|
||||||
|
name = "https://github.com/JetBrains/ideavim (branch 213-221)"
|
||||||
|
url = "https://github.com/JetBrains/ideavim.git"
|
||||||
|
branch = "213-221"
|
||||||
|
})
|
25
.teamcity/patches/buildTypes/Nvim.kts
vendored
25
.teamcity/patches/buildTypes/Nvim.kts
vendored
@@ -1,25 +0,0 @@
|
|||||||
package patches.buildTypes
|
|
||||||
|
|
||||||
import jetbrains.buildServer.configs.kotlin.v2019_2.*
|
|
||||||
import jetbrains.buildServer.configs.kotlin.v2019_2.triggers.VcsTrigger
|
|
||||||
import jetbrains.buildServer.configs.kotlin.v2019_2.triggers.vcs
|
|
||||||
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 = 'Nvim'
|
|
||||||
accordingly, and delete the patch script.
|
|
||||||
*/
|
|
||||||
changeBuildType(RelativeId("Nvim")) {
|
|
||||||
triggers {
|
|
||||||
val trigger1 = find<VcsTrigger> {
|
|
||||||
vcs {
|
|
||||||
branchFilter = ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
trigger1.apply {
|
|
||||||
enabled = false
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
25
.teamcity/patches/buildTypes/PluginVerifier.kts
vendored
25
.teamcity/patches/buildTypes/PluginVerifier.kts
vendored
@@ -1,25 +0,0 @@
|
|||||||
package patches.buildTypes
|
|
||||||
|
|
||||||
import jetbrains.buildServer.configs.kotlin.v2019_2.*
|
|
||||||
import jetbrains.buildServer.configs.kotlin.v2019_2.triggers.VcsTrigger
|
|
||||||
import jetbrains.buildServer.configs.kotlin.v2019_2.triggers.vcs
|
|
||||||
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 = 'PluginVerifier'
|
|
||||||
accordingly, and delete the patch script.
|
|
||||||
*/
|
|
||||||
changeBuildType(RelativeId("PluginVerifier")) {
|
|
||||||
triggers {
|
|
||||||
val trigger1 = find<VcsTrigger> {
|
|
||||||
vcs {
|
|
||||||
branchFilter = ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
trigger1.apply {
|
|
||||||
enabled = false
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
47
.teamcity/patches/buildTypes/Qodana.kts
vendored
47
.teamcity/patches/buildTypes/Qodana.kts
vendored
@@ -2,9 +2,8 @@ package patches.buildTypes
|
|||||||
|
|
||||||
import jetbrains.buildServer.configs.kotlin.v2019_2.*
|
import jetbrains.buildServer.configs.kotlin.v2019_2.*
|
||||||
import jetbrains.buildServer.configs.kotlin.v2019_2.buildSteps.Qodana
|
import jetbrains.buildServer.configs.kotlin.v2019_2.buildSteps.Qodana
|
||||||
|
import jetbrains.buildServer.configs.kotlin.v2019_2.buildSteps.gradle
|
||||||
import jetbrains.buildServer.configs.kotlin.v2019_2.buildSteps.qodana
|
import jetbrains.buildServer.configs.kotlin.v2019_2.buildSteps.qodana
|
||||||
import jetbrains.buildServer.configs.kotlin.v2019_2.triggers.ScheduleTrigger
|
|
||||||
import jetbrains.buildServer.configs.kotlin.v2019_2.triggers.schedule
|
|
||||||
import jetbrains.buildServer.configs.kotlin.v2019_2.ui.*
|
import jetbrains.buildServer.configs.kotlin.v2019_2.ui.*
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -16,9 +15,8 @@ changeBuildType(RelativeId("Qodana")) {
|
|||||||
expectSteps {
|
expectSteps {
|
||||||
qodana {
|
qodana {
|
||||||
name = "Qodana"
|
name = "Qodana"
|
||||||
reportAsTests = true
|
linter = jvm {
|
||||||
inspectionProfile = customProfile {
|
version = Qodana.JVMVersion.LATEST
|
||||||
path = ".idea/inspectionProfiles/Qodana.xml"
|
|
||||||
}
|
}
|
||||||
param("clonefinder-enable", "true")
|
param("clonefinder-enable", "true")
|
||||||
param("clonefinder-languages", "Java")
|
param("clonefinder-languages", "Java")
|
||||||
@@ -26,7 +24,6 @@ changeBuildType(RelativeId("Qodana")) {
|
|||||||
param("clonefinder-mode", "")
|
param("clonefinder-mode", "")
|
||||||
param("clonefinder-queried-project", "src")
|
param("clonefinder-queried-project", "src")
|
||||||
param("clonefinder-reference-projects", "src")
|
param("clonefinder-reference-projects", "src")
|
||||||
param("fail-build-on-errors", "")
|
|
||||||
param("licenseaudit-enable", "true")
|
param("licenseaudit-enable", "true")
|
||||||
param("namesAndTagsCustom", "repo.labs.intellij.net/static-analyser/qodana")
|
param("namesAndTagsCustom", "repo.labs.intellij.net/static-analyser/qodana")
|
||||||
param("report-version", "")
|
param("report-version", "")
|
||||||
@@ -34,27 +31,25 @@ changeBuildType(RelativeId("Qodana")) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
steps {
|
steps {
|
||||||
update<Qodana>(0) {
|
insert(0) {
|
||||||
|
gradle {
|
||||||
|
name = "Generate grammar"
|
||||||
|
tasks = "generateGrammarSource"
|
||||||
|
param("org.jfrog.artifactory.selectedDeployableServer.defaultModuleVersionConfiguration", "GLOBAL")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
update<Qodana>(1) {
|
||||||
clearConditions()
|
clearConditions()
|
||||||
linter = jvm {
|
reportAsTests = true
|
||||||
version = Qodana.JVMVersion.LATEST
|
argumentsCommandDocker = "-e QODANA_TOKEN=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJvcmdhbml6YXRpb24iOiIzUFZrQSIsInByb2plY3QiOiIzN1FlQSIsInRva2VuIjoiM0t2bXoifQ.uohp81tM7iAfvvB6k8faarfpV-OjusAaEbWQ8iNrOgs"
|
||||||
}
|
argumentsEntryPointDocker = "--baseline qodana.sarif.json"
|
||||||
}
|
param("clonefinder-languages", "")
|
||||||
}
|
param("collect-anonymous-statistics", "")
|
||||||
|
param("licenseaudit-enable", "")
|
||||||
triggers {
|
param("clonefinder-languages-container", "")
|
||||||
val trigger1 = find<ScheduleTrigger> {
|
param("clonefinder-queried-project", "")
|
||||||
schedule {
|
param("clonefinder-enable", "")
|
||||||
schedulingPolicy = weekly {
|
param("clonefinder-reference-projects", "")
|
||||||
dayOfWeek = ScheduleTrigger.DAY.Tuesday
|
|
||||||
}
|
|
||||||
branchFilter = ""
|
|
||||||
triggerBuild = always()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
trigger1.apply {
|
|
||||||
enabled = false
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
27
.teamcity/patches/buildTypes/ReleaseEap.kts
vendored
Normal file
27
.teamcity/patches/buildTypes/ReleaseEap.kts
vendored
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
package patches.buildTypes
|
||||||
|
|
||||||
|
import jetbrains.buildServer.configs.kotlin.v2019_2.*
|
||||||
|
import jetbrains.buildServer.configs.kotlin.v2019_2.buildFeatures.VcsLabeling
|
||||||
|
import jetbrains.buildServer.configs.kotlin.v2019_2.buildFeatures.vcsLabeling
|
||||||
|
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 = 'ReleaseEap'
|
||||||
|
accordingly, and delete the patch script.
|
||||||
|
*/
|
||||||
|
changeBuildType(RelativeId("ReleaseEap")) {
|
||||||
|
features {
|
||||||
|
val feature1 = find<VcsLabeling> {
|
||||||
|
vcsLabeling {
|
||||||
|
vcsRootId = "${DslContext.settingsRoot.id}"
|
||||||
|
labelingPattern = "%system.build.number%"
|
||||||
|
successfulOnly = true
|
||||||
|
branchFilter = ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
feature1.apply {
|
||||||
|
successfulOnly = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -416,6 +416,10 @@ Contributors:
|
|||||||
[![icon][github]](https://github.com/Vvalter)
|
[![icon][github]](https://github.com/Vvalter)
|
||||||
|
|
||||||
Simon Rainer
|
Simon Rainer
|
||||||
|
* [![icon][mail]](mailto:filipp.vakhitov@jetbrains.com)
|
||||||
|
[![icon][github]](https://github.com/lippfi)
|
||||||
|
|
||||||
|
lippfi
|
||||||
|
|
||||||
If you are a contributor and your name is not listed here, feel free to
|
If you are a contributor and your name is not listed here, feel free to
|
||||||
contact the maintainers.
|
contact the maintainers.
|
||||||
|
@@ -36,6 +36,7 @@ usual beta standards.
|
|||||||
E.g. `<Plug>Commentary` instead of `<Plug>(CommentMotion)`. Old mappings are maintained for compatibility.
|
E.g. `<Plug>Commentary` instead of `<Plug>(CommentMotion)`. Old mappings are maintained for compatibility.
|
||||||
* If you open `~/.ideavimrc` in IDE, remove a mapping, and reload the config using the reload button,
|
* If you open `~/.ideavimrc` in IDE, remove a mapping, and reload the config using the reload button,
|
||||||
the mapping will actually be unmapped.
|
the mapping will actually be unmapped.
|
||||||
|
* New vim (and IdeaVim) behaviour: `ci(`& friends searches for the brackets in the line.
|
||||||
|
|
||||||
### Fixes:
|
### Fixes:
|
||||||
* [VIM-2587](https://youtrack.jetbrains.com/issue/VIM-2587) Use ctrl-6 as ctrl-^
|
* [VIM-2587](https://youtrack.jetbrains.com/issue/VIM-2587) Use ctrl-6 as ctrl-^
|
||||||
@@ -55,6 +56,9 @@ usual beta standards.
|
|||||||
* [VIM-696](https://youtrack.jetbrains.com/issue/VIM-696/vim-selection-issue-after-undo) Fix selection after undo
|
* [VIM-696](https://youtrack.jetbrains.com/issue/VIM-696/vim-selection-issue-after-undo) Fix selection after undo
|
||||||
* [VIM-744](https://youtrack.jetbrains.com/issue/VIM-744/Use-undoredo-with-count-modifier) Add count to undo/redo
|
* [VIM-744](https://youtrack.jetbrains.com/issue/VIM-744/Use-undoredo-with-count-modifier) Add count to undo/redo
|
||||||
* [VIM-1862](https://youtrack.jetbrains.com/issue/VIM-1862/Ex-commands-executed-in-keymaps-and-macros-are-added-to-the-command-history) Fix command history
|
* [VIM-1862](https://youtrack.jetbrains.com/issue/VIM-1862/Ex-commands-executed-in-keymaps-and-macros-are-added-to-the-command-history) Fix command history
|
||||||
|
* [VIM-2227](https://youtrack.jetbrains.com/issue/VIM-2227) Wrong behavior when deleting / changing surround with invalid character
|
||||||
|
* [VIM-2691](https://youtrack.jetbrains.com/issue/VIM-2691) Save file on :w
|
||||||
|
* [VIM-2710](https://youtrack.jetbrains.com/issue/VIM-2710) Show options value on `set opt`
|
||||||
|
|
||||||
### Merged PRs:
|
### Merged PRs:
|
||||||
* [468](https://github.com/JetBrains/ideavim/pull/468) by [Thomas Schouten](https://github.com/PHPirates): Implement UserDataHolder for EditorDataContext
|
* [468](https://github.com/JetBrains/ideavim/pull/468) by [Thomas Schouten](https://github.com/PHPirates): Implement UserDataHolder for EditorDataContext
|
||||||
@@ -63,6 +67,9 @@ usual beta standards.
|
|||||||
* [493](https://github.com/JetBrains/ideavim/pull/493) by [Matt Ellis](https://github.com/citizenmatt): Improvements to Commentary extension
|
* [493](https://github.com/JetBrains/ideavim/pull/493) by [Matt Ellis](https://github.com/citizenmatt): Improvements to Commentary extension
|
||||||
* [494](https://github.com/JetBrains/ideavim/pull/494) by [Matt Ellis](https://github.com/citizenmatt): Cleanup pre-212 CaretVisualAttributes compatibility code
|
* [494](https://github.com/JetBrains/ideavim/pull/494) by [Matt Ellis](https://github.com/citizenmatt): Cleanup pre-212 CaretVisualAttributes compatibility code
|
||||||
* [504](https://github.com/JetBrains/ideavim/pull/504) by [Matt Ellis](https://github.com/citizenmatt): Minor bug fixes
|
* [504](https://github.com/JetBrains/ideavim/pull/504) by [Matt Ellis](https://github.com/citizenmatt): Minor bug fixes
|
||||||
|
* [519](https://github.com/JetBrains/ideavim/pull/519) by [chylex](https://github.com/chylex): Fix(VIM-2227): Wrong behavior when deleting / changing surround with invalid character
|
||||||
|
* [525](https://github.com/JetBrains/ideavim/pull/525) by [Matt Ellis](https://github.com/citizenmatt): Improve handling of fractional width fonts
|
||||||
|
* [526](https://github.com/JetBrains/ideavim/pull/526) by [Alex Pláte](https://github.com/AlexPl292): Create gradle.properties
|
||||||
|
|
||||||
## 1.10.0, 2022-02-17
|
## 1.10.0, 2022-02-17
|
||||||
|
|
||||||
|
@@ -5,7 +5,7 @@ IdeaVim is an open source project created by 80+ contributors. Would you like to
|
|||||||
This page is created to help you start contributing. And who knows, maybe in a few days this project will be brighter than ever!
|
This page is created to help you start contributing. And who knows, maybe in a few days this project will be brighter than ever!
|
||||||
|
|
||||||
:warning: The plugin is currently under a huge refactoring aiming to split into vim-engine and IdeaVim in order to
|
:warning: The plugin is currently under a huge refactoring aiming to split into vim-engine and IdeaVim in order to
|
||||||
support the new [Fleet IDE](https://www.jetbrains.com/fleet/).
|
support the new [Fleet IDE](https://www.jetbrains.com/fleet/). Please see [Fleet refactoring](#Fleet-refactoring).
|
||||||
|
|
||||||
## Before you begin
|
## Before you begin
|
||||||
|
|
||||||
@@ -120,6 +120,17 @@ so you can reuse your `.vimrc` settings.
|
|||||||
We also support proper command mappings (functions are mapped to `<Plug>...`), the operator function (`OperatorFunction`), and so on.
|
We also support proper command mappings (functions are mapped to `<Plug>...`), the operator function (`OperatorFunction`), and so on.
|
||||||
- Magic is supported as well. See `Magic`.
|
- Magic is supported as well. See `Magic`.
|
||||||
|
|
||||||
|
|
||||||
|
## Fleet refactoring
|
||||||
|
At the moment, IdeaVim is under an active refactoring aiming to split IdeaVim into two modules: vim-engine and IdeaVim.
|
||||||
|
|
||||||
|
If you develop a plugin that depends on IdeaVim: We have an instrument to check that our changes don't affect
|
||||||
|
the plugins in the marketplace. Also, we commit to support currently used API at least till the end of 2022.
|
||||||
|
If you still encounter any issues with the newer versions of IdeaVim, please [contact maintainers](https://github.com/JetBrains/ideavim#contact-maintainers).
|
||||||
|
We kindly ask you not to use anything from the new API (like `VimEditor`, `injector`) because at the moment we don't
|
||||||
|
guarantee the compatibility of this API in the future versions.
|
||||||
|
|
||||||
|
|
||||||
-----
|
-----
|
||||||
|
|
||||||
### I read the whole page but something is still unclear.
|
### I read the whole page but something is still unclear.
|
||||||
|
@@ -24,11 +24,11 @@ plugins {
|
|||||||
java
|
java
|
||||||
kotlin("jvm") version "1.6.21"
|
kotlin("jvm") version "1.6.21"
|
||||||
|
|
||||||
id("org.jetbrains.intellij") version "1.6.0"
|
id("org.jetbrains.intellij") version "1.7.0-SNAPSHOT"
|
||||||
id("org.jetbrains.changelog") version "1.3.1"
|
id("org.jetbrains.changelog") version "1.3.1"
|
||||||
|
|
||||||
// ktlint linter - read more: https://github.com/JLLeitschuh/ktlint-gradle
|
// ktlint linter - read more: https://github.com/JLLeitschuh/ktlint-gradle
|
||||||
id("org.jlleitschuh.gradle.ktlint") version "10.2.1"
|
id("org.jlleitschuh.gradle.ktlint") version "10.3.0"
|
||||||
}
|
}
|
||||||
|
|
||||||
// Import variables from gradle.properties file
|
// Import variables from gradle.properties file
|
||||||
@@ -70,7 +70,9 @@ dependencies {
|
|||||||
runtimeOnly("org.antlr:antlr4-runtime:$antlrVersion")
|
runtimeOnly("org.antlr:antlr4-runtime:$antlrVersion")
|
||||||
antlr("org.antlr:antlr4:$antlrVersion")
|
antlr("org.antlr:antlr4:$antlrVersion")
|
||||||
|
|
||||||
implementation(project(":vim-engine"))
|
api(project(":vim-engine"))
|
||||||
|
|
||||||
|
testApi("com.squareup.okhttp3:okhttp:4.10.0")
|
||||||
}
|
}
|
||||||
|
|
||||||
configurations {
|
configurations {
|
||||||
@@ -85,6 +87,8 @@ tasks.register<Test>("testWithNeovim") {
|
|||||||
group = "verification"
|
group = "verification"
|
||||||
systemProperty("ideavim.nvim.test", "true")
|
systemProperty("ideavim.nvim.test", "true")
|
||||||
exclude("/ui/**")
|
exclude("/ui/**")
|
||||||
|
exclude("**/longrunning/**")
|
||||||
|
exclude("**/propertybased/**")
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.register<Test>("testPropertyBased") {
|
tasks.register<Test>("testPropertyBased") {
|
||||||
@@ -115,6 +119,8 @@ tasks {
|
|||||||
include("**/*test.class")
|
include("**/*test.class")
|
||||||
include("**/*Tests.class")
|
include("**/*Tests.class")
|
||||||
exclude("**/ParserTest.class")
|
exclude("**/ParserTest.class")
|
||||||
|
exclude("**/longrunning/**")
|
||||||
|
exclude("**/propertybased/**")
|
||||||
}
|
}
|
||||||
|
|
||||||
val testPropertyBased by getting(Test::class) {
|
val testPropertyBased by getting(Test::class) {
|
||||||
@@ -144,14 +150,15 @@ tasks {
|
|||||||
compileKotlin {
|
compileKotlin {
|
||||||
kotlinOptions {
|
kotlinOptions {
|
||||||
jvmTarget = javaVersion
|
jvmTarget = javaVersion
|
||||||
apiVersion = "1.5"
|
apiVersion = "1.6"
|
||||||
|
freeCompilerArgs = listOf("-Xjvm-default=all-compatibility")
|
||||||
// allWarningsAsErrors = true
|
// allWarningsAsErrors = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
compileTestKotlin {
|
compileTestKotlin {
|
||||||
kotlinOptions {
|
kotlinOptions {
|
||||||
jvmTarget = javaVersion
|
jvmTarget = javaVersion
|
||||||
apiVersion = "1.5"
|
apiVersion = "1.6"
|
||||||
// allWarningsAsErrors = true
|
// allWarningsAsErrors = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -199,7 +206,7 @@ tasks {
|
|||||||
runPluginVerifier {
|
runPluginVerifier {
|
||||||
downloadDir.set("${project.buildDir}/pluginVerifier/ides")
|
downloadDir.set("${project.buildDir}/pluginVerifier/ides")
|
||||||
teamCityOutputFormat.set(true)
|
teamCityOutputFormat.set(true)
|
||||||
ideVersions.set(listOf("IC-2021.3.4"))
|
// ideVersions.set(listOf("IC-2021.3.4"))
|
||||||
}
|
}
|
||||||
|
|
||||||
generateGrammarSource {
|
generateGrammarSource {
|
||||||
@@ -211,12 +218,37 @@ tasks {
|
|||||||
named("compileKotlin") {
|
named("compileKotlin") {
|
||||||
dependsOn("generateGrammarSource")
|
dependsOn("generateGrammarSource")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add plugin open API sources to the plugin ZIP
|
||||||
|
val createOpenApiSourceJar by registering(Jar::class) {
|
||||||
|
// Java sources
|
||||||
|
from(sourceSets.main.get().java) {
|
||||||
|
include("**/com/maddyhome/idea/vim/**/*.java")
|
||||||
|
}
|
||||||
|
// Kotlin sources
|
||||||
|
from(kotlin.sourceSets.main.get().kotlin) {
|
||||||
|
include("**/com/maddyhome/idea/vim/**/*.kt")
|
||||||
|
}
|
||||||
|
destinationDirectory.set(layout.buildDirectory.dir("libs"))
|
||||||
|
archiveClassifier.set("src")
|
||||||
|
}
|
||||||
|
|
||||||
|
buildPlugin {
|
||||||
|
dependsOn(createOpenApiSourceJar)
|
||||||
|
from(createOpenApiSourceJar) { into("lib/src") }
|
||||||
|
}
|
||||||
|
|
||||||
|
// Don't forget to update plugin.xml
|
||||||
|
patchPluginXml {
|
||||||
|
sinceBuild.set("222")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- Linting
|
// --- Linting
|
||||||
|
|
||||||
ktlint {
|
ktlint {
|
||||||
disabledRules.add("no-wildcard-imports")
|
disabledRules.add("no-wildcard-imports")
|
||||||
|
version.set("0.43.0")
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- Tests
|
// --- Tests
|
||||||
@@ -307,7 +339,8 @@ tasks.register("updateAuthors") {
|
|||||||
"aleksei.plate@jetbrains.com",
|
"aleksei.plate@jetbrains.com",
|
||||||
"aleksei.plate@teamcity",
|
"aleksei.plate@teamcity",
|
||||||
"aleksei.plate@TeamCity",
|
"aleksei.plate@TeamCity",
|
||||||
"alex.plate@192.168.0.109"
|
"alex.plate@192.168.0.109",
|
||||||
|
"nikita.koshcheev@TeamCity",
|
||||||
)
|
)
|
||||||
updateAuthors(uncheckedEmails)
|
updateAuthors(uncheckedEmails)
|
||||||
}
|
}
|
||||||
@@ -318,6 +351,7 @@ val prId: String by project
|
|||||||
tasks.register("updateMergedPr") {
|
tasks.register("updateMergedPr") {
|
||||||
doLast {
|
doLast {
|
||||||
if (project.hasProperty("prId")) {
|
if (project.hasProperty("prId")) {
|
||||||
|
println("Got pr id: $prId")
|
||||||
updateMergedPr(prId.toInt())
|
updateMergedPr(prId.toInt())
|
||||||
} else {
|
} else {
|
||||||
error("Cannot get prId")
|
error("Cannot get prId")
|
||||||
@@ -481,7 +515,9 @@ data class Change(val id: String, val text: String)
|
|||||||
|
|
||||||
fun updateMergedPr(number: Int) {
|
fun updateMergedPr(number: Int) {
|
||||||
val gitHub = org.kohsuke.github.GitHub.connect()
|
val gitHub = org.kohsuke.github.GitHub.connect()
|
||||||
|
println("Connecting to the repo...")
|
||||||
val repository = gitHub.getRepository("JetBrains/ideavim")
|
val repository = gitHub.getRepository("JetBrains/ideavim")
|
||||||
|
println("Getting pull requests...")
|
||||||
val pullRequest = repository.getPullRequest(number)
|
val pullRequest = repository.getPullRequest(number)
|
||||||
if (pullRequest.user.login == "dependabot[bot]") return
|
if (pullRequest.user.login == "dependabot[bot]") return
|
||||||
|
|
||||||
|
@@ -5,9 +5,10 @@ downloadIdeaSources=true
|
|||||||
instrumentPluginCode=true
|
instrumentPluginCode=true
|
||||||
version=SNAPSHOT
|
version=SNAPSHOT
|
||||||
javaVersion=11
|
javaVersion=11
|
||||||
remoteRobotVersion=0.11.10
|
remoteRobotVersion=0.11.15
|
||||||
antlrVersion=4.10.1
|
antlrVersion=4.10.1
|
||||||
|
|
||||||
|
|
||||||
# Please don't forget to update kotlin version in buildscript section
|
# Please don't forget to update kotlin version in buildscript section
|
||||||
kotlinVersion=1.6.21
|
kotlinVersion=1.6.21
|
||||||
publishToken=token
|
publishToken=token
|
||||||
|
79982
qodana.sarif.json
Normal file
79982
qodana.sarif.json
Normal file
File diff suppressed because it is too large
Load Diff
21
qodana.yaml
21
qodana.yaml
@@ -1,6 +1,8 @@
|
|||||||
version: 1.0
|
version: 1.0
|
||||||
profile:
|
profile:
|
||||||
name: Qodana
|
name: Qodana
|
||||||
|
include:
|
||||||
|
- name: CheckDependencyLicenses
|
||||||
exclude:
|
exclude:
|
||||||
- name: MoveVariableDeclarationIntoWhen
|
- name: MoveVariableDeclarationIntoWhen
|
||||||
- name: PluginXmlValidity
|
- name: PluginXmlValidity
|
||||||
@@ -9,12 +11,15 @@ exclude:
|
|||||||
- name: UnusedReturnValue
|
- name: UnusedReturnValue
|
||||||
- name: All
|
- name: All
|
||||||
paths:
|
paths:
|
||||||
- build.gradle
|
- build.gradle.kts
|
||||||
- gradle/wrapper/gradle-wrapper.properties
|
- gradle/wrapper/gradle-wrapper.properties
|
||||||
- resources/icons/youtrack.svg
|
- src/main/resources/icons/youtrack.svg
|
||||||
- src/com/maddyhome/idea/vim/ex/vimscript/VimScriptCommandHandler.java
|
- src/main/java/com/maddyhome/idea/vim/helper/SearchHelper.java
|
||||||
- src/com/maddyhome/idea/vim/helper/SearchHelper.java
|
- src/main/java/com/maddyhome/idea/vim/regexp/RegExp.kt
|
||||||
- src/com/maddyhome/idea/vim/regexp/RegExp.java
|
- src/test/java/org/jetbrains/plugins/ideavim/propertybased/samples/JavaText.kt
|
||||||
- test/org/jetbrains/plugins/ideavim/propertybased/samples/JavaText.kt
|
- src/test/java/org/jetbrains/plugins/ideavim/propertybased/samples/LoremText.kt
|
||||||
- test/org/jetbrains/plugins/ideavim/propertybased/samples/LoremText.kt
|
- src/test/java/org/jetbrains/plugins/ideavim/propertybased/samples/SimpleText.kt
|
||||||
- test/org/jetbrains/plugins/ideavim/propertybased/samples/SimpleText.kt
|
- src/main/java/com/maddyhome/idea/vim/vimscript/parser/generated/VimscriptListener.java
|
||||||
|
- src/main/java/com/maddyhome/idea/vim/vimscript/parser/generated/VimscriptLexer.java
|
||||||
|
- src/main/java/com/maddyhome/idea/vim/vimscript/parser/generated/VimscriptParser.java
|
||||||
|
- src/main/java/com/maddyhome/idea/vim/vimscript/parser/generated/VimscriptVisitor.java
|
@@ -1,3 +1,13 @@
|
|||||||
|
// Set repository for snapshot versions of gradle plugin
|
||||||
|
pluginManagement {
|
||||||
|
repositories {
|
||||||
|
maven {
|
||||||
|
url 'https://oss.sonatype.org/content/repositories/snapshots/'
|
||||||
|
}
|
||||||
|
gradlePluginPortal()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
rootProject.name = 'IdeaVIM'
|
rootProject.name = 'IdeaVIM'
|
||||||
include 'vim-engine'
|
include 'vim-engine'
|
||||||
|
|
||||||
|
@@ -146,7 +146,7 @@ rShift: GREATER+;
|
|||||||
|
|
||||||
letCommands:
|
letCommands:
|
||||||
(WS | COLON)* range? (WS | COLON)* LET WS+ expr WS*
|
(WS | COLON)* range? (WS | COLON)* LET WS+ expr WS*
|
||||||
assignmentOperator = (ASSIGN | PLUS_ASSIGN | MINUS_ASSIGN | STAR_ASSIGN | DIV_ASSIGN | MOD_ASSIGN | DOT_ASSIGN)
|
assignmentOperator
|
||||||
WS* expr WS* ((inline_comment NEW_LINE) | (NEW_LINE | BAR)+)
|
WS* expr WS* ((inline_comment NEW_LINE) | (NEW_LINE | BAR)+)
|
||||||
#Let1Command|
|
#Let1Command|
|
||||||
|
|
||||||
@@ -154,6 +154,21 @@ letCommands:
|
|||||||
#Let2Command
|
#Let2Command
|
||||||
;
|
;
|
||||||
|
|
||||||
|
assignmentOperator:
|
||||||
|
ASSIGN | plusAssign | minusAssign | startAssign | divAssign | modAssign | dotAssign;
|
||||||
|
plusAssign:
|
||||||
|
PLUS ASSIGN;
|
||||||
|
minusAssign:
|
||||||
|
MINUS ASSIGN;
|
||||||
|
startAssign:
|
||||||
|
STAR ASSIGN;
|
||||||
|
divAssign:
|
||||||
|
DIV ASSIGN;
|
||||||
|
modAssign:
|
||||||
|
MOD ASSIGN;
|
||||||
|
dotAssign:
|
||||||
|
DOT ASSIGN;
|
||||||
|
|
||||||
shortRange:
|
shortRange:
|
||||||
((QUESTION (~QUESTION)* QUESTION?) | (DIV (~DIV)* DIV?));
|
((QUESTION (~QUESTION)* QUESTION?) | (DIV (~DIV)* DIV?));
|
||||||
range:
|
range:
|
||||||
@@ -778,12 +793,12 @@ IS_NOT_CS: 'isnot#';
|
|||||||
|
|
||||||
// Assignment operators
|
// Assignment operators
|
||||||
ASSIGN: '=';
|
ASSIGN: '=';
|
||||||
PLUS_ASSIGN: '+=';
|
//PLUS_ASSIGN: '+=';
|
||||||
MINUS_ASSIGN: '-=';
|
//MINUS_ASSIGN: '-=';
|
||||||
STAR_ASSIGN: '*=';
|
//STAR_ASSIGN: '*=';
|
||||||
DIV_ASSIGN: '/=';
|
//DIV_ASSIGN: '/=';
|
||||||
MOD_ASSIGN: '%=';
|
//MOD_ASSIGN: '%=';
|
||||||
DOT_ASSIGN: '.=';
|
//DOT_ASSIGN: '.=';
|
||||||
|
|
||||||
// Escaped chars
|
// Escaped chars
|
||||||
ESCAPED_QUESTION: '\\?';
|
ESCAPED_QUESTION: '\\?';
|
||||||
|
@@ -101,12 +101,6 @@ public class EventFacade {
|
|||||||
EditorFactory.getInstance().addEditorFactoryListener(listener, parentDisposable);
|
EditorFactory.getInstance().addEditorFactoryListener(listener, parentDisposable);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("deprecation")
|
|
||||||
public void removeEditorFactoryListener(@NotNull EditorFactoryListener listener) {
|
|
||||||
// Listener is removed not only if application is disposed
|
|
||||||
EditorFactory.getInstance().removeEditorFactoryListener(listener);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addEditorMouseListener(@NotNull Editor editor, @NotNull EditorMouseListener listener) {
|
public void addEditorMouseListener(@NotNull Editor editor, @NotNull EditorMouseListener listener) {
|
||||||
editor.addEditorMouseListener(listener);
|
editor.addEditorMouseListener(listener);
|
||||||
}
|
}
|
||||||
|
@@ -19,8 +19,6 @@ package com.maddyhome.idea.vim;
|
|||||||
|
|
||||||
import com.intellij.ide.plugins.IdeaPluginDescriptor;
|
import com.intellij.ide.plugins.IdeaPluginDescriptor;
|
||||||
import com.intellij.ide.plugins.PluginManagerCore;
|
import com.intellij.ide.plugins.PluginManagerCore;
|
||||||
import com.intellij.notification.Notification;
|
|
||||||
import com.intellij.notification.NotificationListener;
|
|
||||||
import com.intellij.openapi.Disposable;
|
import com.intellij.openapi.Disposable;
|
||||||
import com.intellij.openapi.application.Application;
|
import com.intellij.openapi.application.Application;
|
||||||
import com.intellij.openapi.application.ApplicationManager;
|
import com.intellij.openapi.application.ApplicationManager;
|
||||||
@@ -32,9 +30,9 @@ import com.intellij.openapi.extensions.PluginId;
|
|||||||
import com.intellij.openapi.keymap.Keymap;
|
import com.intellij.openapi.keymap.Keymap;
|
||||||
import com.intellij.openapi.keymap.ex.KeymapManagerEx;
|
import com.intellij.openapi.keymap.ex.KeymapManagerEx;
|
||||||
import com.intellij.openapi.keymap.impl.DefaultKeymap;
|
import com.intellij.openapi.keymap.impl.DefaultKeymap;
|
||||||
import com.intellij.openapi.options.ShowSettingsUtil;
|
|
||||||
import com.intellij.openapi.project.Project;
|
import com.intellij.openapi.project.Project;
|
||||||
import com.intellij.openapi.ui.Messages;
|
import com.intellij.openapi.ui.Messages;
|
||||||
|
import com.intellij.openapi.util.Disposer;
|
||||||
import com.intellij.openapi.util.SystemInfo;
|
import com.intellij.openapi.util.SystemInfo;
|
||||||
import com.maddyhome.idea.vim.api.VimInjectorKt;
|
import com.maddyhome.idea.vim.api.VimInjectorKt;
|
||||||
import com.maddyhome.idea.vim.api.VimKeyGroup;
|
import com.maddyhome.idea.vim.api.VimKeyGroup;
|
||||||
@@ -48,20 +46,17 @@ import com.maddyhome.idea.vim.group.visual.VisualMotionGroup;
|
|||||||
import com.maddyhome.idea.vim.helper.MacKeyRepeat;
|
import com.maddyhome.idea.vim.helper.MacKeyRepeat;
|
||||||
import com.maddyhome.idea.vim.listener.VimListenerManager;
|
import com.maddyhome.idea.vim.listener.VimListenerManager;
|
||||||
import com.maddyhome.idea.vim.newapi.IjVimInjector;
|
import com.maddyhome.idea.vim.newapi.IjVimInjector;
|
||||||
import com.maddyhome.idea.vim.options.OptionService;
|
|
||||||
import com.maddyhome.idea.vim.ui.StatusBarIconFactory;
|
import com.maddyhome.idea.vim.ui.StatusBarIconFactory;
|
||||||
import com.maddyhome.idea.vim.ui.VimEmulationConfigurable;
|
|
||||||
import com.maddyhome.idea.vim.ui.ex.ExEntryPanel;
|
import com.maddyhome.idea.vim.ui.ex.ExEntryPanel;
|
||||||
import com.maddyhome.idea.vim.vimscript.services.FunctionStorage;
|
import com.maddyhome.idea.vim.vimscript.services.FunctionStorage;
|
||||||
import com.maddyhome.idea.vim.vimscript.services.IjVimOptionService;
|
import com.maddyhome.idea.vim.vimscript.services.IjVimOptionService;
|
||||||
import com.maddyhome.idea.vim.vimscript.services.VimVariableService;
|
import com.maddyhome.idea.vim.vimscript.services.OptionService;
|
||||||
|
import com.maddyhome.idea.vim.vimscript.services.VariableService;
|
||||||
import org.jdom.Element;
|
import org.jdom.Element;
|
||||||
import org.jetbrains.annotations.Nls;
|
import org.jetbrains.annotations.Nls;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import javax.swing.event.HyperlinkEvent;
|
|
||||||
|
|
||||||
import static com.maddyhome.idea.vim.group.EditorGroup.EDITOR_STORE_ELEMENT;
|
import static com.maddyhome.idea.vim.group.EditorGroup.EDITOR_STORE_ELEMENT;
|
||||||
import static com.maddyhome.idea.vim.group.KeyGroup.SHORTCUT_CONFLICTS_ELEMENT;
|
import static com.maddyhome.idea.vim.group.KeyGroup.SHORTCUT_CONFLICTS_ELEMENT;
|
||||||
import static com.maddyhome.idea.vim.vimscript.services.VimRcService.executeIdeaVimRc;
|
import static com.maddyhome.idea.vim.vimscript.services.VimRcService.executeIdeaVimRc;
|
||||||
@@ -94,6 +89,8 @@ public class VimPlugin implements PersistentStateComponent<Element>, Disposable
|
|||||||
|
|
||||||
private final @NotNull VimState state = new VimState();
|
private final @NotNull VimState state = new VimState();
|
||||||
|
|
||||||
|
public Disposable onOffDisposable;
|
||||||
|
|
||||||
VimPlugin() {
|
VimPlugin() {
|
||||||
ApplicationConfigurationMigrator.getInstance().migrate();
|
ApplicationConfigurationMigrator.getInstance().migrate();
|
||||||
}
|
}
|
||||||
@@ -226,8 +223,8 @@ public class VimPlugin implements PersistentStateComponent<Element>, Disposable
|
|||||||
return (PutGroup)VimInjectorKt.getInjector().getPut();
|
return (PutGroup)VimInjectorKt.getInjector().getPut();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static @NotNull VimVariableService getVariableService() {
|
public static @NotNull VariableService getVariableService() {
|
||||||
return ApplicationManager.getApplication().getService(VimVariableService.class);
|
return ApplicationManager.getApplication().getService(VariableService.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static @NotNull OptionService getOptionService() {
|
public static @NotNull OptionService getOptionService() {
|
||||||
@@ -341,6 +338,8 @@ public class VimPlugin implements PersistentStateComponent<Element>, Disposable
|
|||||||
* execution, what theoretically may cause bugs (e.g. VIM-2540)
|
* execution, what theoretically may cause bugs (e.g. VIM-2540)
|
||||||
*/
|
*/
|
||||||
private void turnOnPlugin() {
|
private void turnOnPlugin() {
|
||||||
|
onOffDisposable = Disposer.newDisposable(this, "IdeaVimOnOffDisposer");
|
||||||
|
|
||||||
// 1) Update state
|
// 1) Update state
|
||||||
ApplicationManager.getApplication().invokeLater(this::updateState);
|
ApplicationManager.getApplication().invokeLater(this::updateState);
|
||||||
|
|
||||||
@@ -376,6 +375,8 @@ public class VimPlugin implements PersistentStateComponent<Element>, Disposable
|
|||||||
|
|
||||||
// Unregister vim actions in command mode
|
// Unregister vim actions in command mode
|
||||||
RegisterActions.unregisterActions();
|
RegisterActions.unregisterActions();
|
||||||
|
|
||||||
|
Disposer.dispose(onOffDisposable);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean stateUpdated = false;
|
private boolean stateUpdated = false;
|
||||||
@@ -389,7 +390,9 @@ public class VimPlugin implements PersistentStateComponent<Element>, Disposable
|
|||||||
final Boolean enabled = keyRepeat.isEnabled();
|
final Boolean enabled = keyRepeat.isEnabled();
|
||||||
final Boolean isKeyRepeat = getEditor().isKeyRepeat();
|
final Boolean isKeyRepeat = getEditor().isKeyRepeat();
|
||||||
if ((enabled == null || !enabled) && (isKeyRepeat == null || isKeyRepeat)) {
|
if ((enabled == null || !enabled) && (isKeyRepeat == null || isKeyRepeat)) {
|
||||||
if (VimPlugin.getNotifications().enableRepeatingMode() == Messages.YES) {
|
// This system property is used in IJ ui robot to hide the startup tips
|
||||||
|
boolean showNotification = Boolean.getBoolean("ide.show.tips.on.startup.default.value");
|
||||||
|
if (showNotification && VimPlugin.getNotifications().enableRepeatingMode() == Messages.YES) {
|
||||||
getEditor().setKeyRepeat(true);
|
getEditor().setKeyRepeat(true);
|
||||||
keyRepeat.setEnabled(true);
|
keyRepeat.setEnabled(true);
|
||||||
}
|
}
|
||||||
@@ -408,12 +411,6 @@ public class VimPlugin implements PersistentStateComponent<Element>, Disposable
|
|||||||
keymap = manager.getKeymap(DefaultKeymap.getInstance().getDefaultKeymapName());
|
keymap = manager.getKeymap(DefaultKeymap.getInstance().getDefaultKeymapName());
|
||||||
}
|
}
|
||||||
assert keymap != null : "Default keymap not found";
|
assert keymap != null : "Default keymap not found";
|
||||||
VimPlugin.getNotifications().specialKeymap(keymap, new NotificationListener.Adapter() {
|
|
||||||
@Override
|
|
||||||
protected void hyperlinkActivated(@NotNull Notification notification, @NotNull HyperlinkEvent e) {
|
|
||||||
ShowSettingsUtil.getInstance().showSettingsDialog(null, VimEmulationConfigurable.class);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
manager.setActiveKeymap(keymap);
|
manager.setActiveKeymap(keymap);
|
||||||
}
|
}
|
||||||
if (previousStateVersion > 0 && previousStateVersion < 4) {
|
if (previousStateVersion > 0 && previousStateVersion < 4) {
|
||||||
|
@@ -34,8 +34,8 @@ import com.maddyhome.idea.vim.group.visual.VimSelection
|
|||||||
import com.maddyhome.idea.vim.handler.VimActionHandler
|
import com.maddyhome.idea.vim.handler.VimActionHandler
|
||||||
import com.maddyhome.idea.vim.handler.VisualOperatorActionHandler
|
import com.maddyhome.idea.vim.handler.VisualOperatorActionHandler
|
||||||
import com.maddyhome.idea.vim.helper.MessageHelper
|
import com.maddyhome.idea.vim.helper.MessageHelper
|
||||||
import com.maddyhome.idea.vim.helper.commandState
|
|
||||||
import com.maddyhome.idea.vim.helper.enumSetOf
|
import com.maddyhome.idea.vim.helper.enumSetOf
|
||||||
|
import com.maddyhome.idea.vim.helper.vimStateMachine
|
||||||
import com.maddyhome.idea.vim.newapi.ij
|
import com.maddyhome.idea.vim.newapi.ij
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
@@ -61,7 +61,7 @@ class OperatorAction : VimActionHandler.SingleExecution() {
|
|||||||
|
|
||||||
override fun execute(editor: VimEditor, context: ExecutionContext, cmd: Command, operatorArguments: OperatorArguments): Boolean {
|
override fun execute(editor: VimEditor, context: ExecutionContext, cmd: Command, operatorArguments: OperatorArguments): Boolean {
|
||||||
val argument = cmd.argument ?: return false
|
val argument = cmd.argument ?: return false
|
||||||
if (!editor.commandState.isDotRepeatInProgress) {
|
if (!editor.vimStateMachine.isDotRepeatInProgress) {
|
||||||
argumentCaptured = argument
|
argumentCaptured = argument
|
||||||
}
|
}
|
||||||
val range = getMotionRange(editor, context, argument, operatorArguments)
|
val range = getMotionRange(editor, context, argument, operatorArguments)
|
||||||
|
@@ -25,14 +25,14 @@ import com.maddyhome.idea.vim.api.injector
|
|||||||
import com.maddyhome.idea.vim.command.Command
|
import com.maddyhome.idea.vim.command.Command
|
||||||
import com.maddyhome.idea.vim.command.OperatorArguments
|
import com.maddyhome.idea.vim.command.OperatorArguments
|
||||||
import com.maddyhome.idea.vim.handler.VimActionHandler
|
import com.maddyhome.idea.vim.handler.VimActionHandler
|
||||||
import com.maddyhome.idea.vim.helper.commandState
|
import com.maddyhome.idea.vim.helper.vimStateMachine
|
||||||
import com.maddyhome.idea.vim.newapi.ij
|
import com.maddyhome.idea.vim.newapi.ij
|
||||||
|
|
||||||
class RepeatChangeAction : VimActionHandler.SingleExecution() {
|
class RepeatChangeAction : VimActionHandler.SingleExecution() {
|
||||||
override val type: Command.Type = Command.Type.OTHER_WRITABLE
|
override val type: Command.Type = Command.Type.OTHER_WRITABLE
|
||||||
|
|
||||||
override fun execute(editor: VimEditor, context: ExecutionContext, cmd: Command, operatorArguments: OperatorArguments): Boolean {
|
override fun execute(editor: VimEditor, context: ExecutionContext, cmd: Command, operatorArguments: OperatorArguments): Boolean {
|
||||||
val state = editor.commandState
|
val state = editor.vimStateMachine
|
||||||
val lastCommand = VimRepeater.lastChangeCommand
|
val lastCommand = VimRepeater.lastChangeCommand
|
||||||
|
|
||||||
if (lastCommand == null && Extension.lastExtensionHandler == null) return false
|
if (lastCommand == null && Extension.lastExtensionHandler == null) return false
|
||||||
|
@@ -45,7 +45,7 @@ class DeleteJoinLinesAction : ChangeEditorActionHandler.SingleExecution() {
|
|||||||
val res = arrayOf(true)
|
val res = arrayOf(true)
|
||||||
editor.forEachNativeCaret(
|
editor.forEachNativeCaret(
|
||||||
{ caret: VimCaret ->
|
{ caret: VimCaret ->
|
||||||
if (!injector.changeGroup.deleteJoinLines(editor, caret, operatorArguments.count1, false)) res[0] = false
|
if (!injector.changeGroup.deleteJoinLines(editor, caret, operatorArguments.count1, false, operatorArguments)) res[0] = false
|
||||||
},
|
},
|
||||||
true
|
true
|
||||||
)
|
)
|
||||||
|
@@ -45,7 +45,7 @@ class DeleteJoinLinesSpacesAction : ChangeEditorActionHandler.SingleExecution()
|
|||||||
val res = arrayOf(true)
|
val res = arrayOf(true)
|
||||||
editor.forEachNativeCaret(
|
editor.forEachNativeCaret(
|
||||||
{ caret: VimCaret ->
|
{ caret: VimCaret ->
|
||||||
if (!injector.changeGroup.deleteJoinLines(editor, caret, operatorArguments.count1, true)) res[0] = false
|
if (!injector.changeGroup.deleteJoinLines(editor, caret, operatorArguments.count1, true, operatorArguments)) res[0] = false
|
||||||
},
|
},
|
||||||
true
|
true
|
||||||
)
|
)
|
||||||
|
@@ -57,7 +57,14 @@ class DeleteJoinVisualLinesAction : VisualOperatorActionHandler.SingleExecution(
|
|||||||
caret: VimCaret ->
|
caret: VimCaret ->
|
||||||
if (!caret.isValid) return@forEachNativeCaret
|
if (!caret.isValid) return@forEachNativeCaret
|
||||||
val range = caretsAndSelections[caret] ?: return@forEachNativeCaret
|
val range = caretsAndSelections[caret] ?: return@forEachNativeCaret
|
||||||
if (!injector.changeGroup.deleteJoinRange(editor, caret, range.toVimTextRange(true).normalize(), false)) {
|
if (!injector.changeGroup.deleteJoinRange(
|
||||||
|
editor,
|
||||||
|
caret,
|
||||||
|
range.toVimTextRange(true).normalize(),
|
||||||
|
false,
|
||||||
|
operatorArguments
|
||||||
|
)
|
||||||
|
) {
|
||||||
res[0] = false
|
res[0] = false
|
||||||
}
|
}
|
||||||
}, true
|
}, true
|
||||||
|
@@ -56,7 +56,14 @@ class DeleteJoinVisualLinesSpacesAction : VisualOperatorActionHandler.SingleExec
|
|||||||
{ caret: VimCaret ->
|
{ caret: VimCaret ->
|
||||||
if (!caret.isValid) return@forEachNativeCaret
|
if (!caret.isValid) return@forEachNativeCaret
|
||||||
val range = caretsAndSelections[caret] ?: return@forEachNativeCaret
|
val range = caretsAndSelections[caret] ?: return@forEachNativeCaret
|
||||||
if (!injector.changeGroup.deleteJoinRange(editor, caret, range.toVimTextRange(true).normalize(), true)) {
|
if (!injector.changeGroup.deleteJoinRange(
|
||||||
|
editor,
|
||||||
|
caret,
|
||||||
|
range.toVimTextRange(true).normalize(),
|
||||||
|
true,
|
||||||
|
operatorArguments
|
||||||
|
)
|
||||||
|
) {
|
||||||
res[0] = false
|
res[0] = false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@@ -18,6 +18,7 @@
|
|||||||
package com.maddyhome.idea.vim.action.internal
|
package com.maddyhome.idea.vim.action.internal
|
||||||
|
|
||||||
import com.intellij.ide.ui.AntialiasingType
|
import com.intellij.ide.ui.AntialiasingType
|
||||||
|
import com.intellij.ide.ui.UISettings
|
||||||
import com.intellij.openapi.actionSystem.AnAction
|
import com.intellij.openapi.actionSystem.AnAction
|
||||||
import com.intellij.openapi.actionSystem.AnActionEvent
|
import com.intellij.openapi.actionSystem.AnActionEvent
|
||||||
import com.intellij.openapi.actionSystem.CommonDataKeys
|
import com.intellij.openapi.actionSystem.CommonDataKeys
|
||||||
@@ -124,7 +125,7 @@ class AddBlockInlaysAction : AnAction() {
|
|||||||
val editorContext = FontInfo.getFontRenderContext(editor.contentComponent)
|
val editorContext = FontInfo.getFontRenderContext(editor.contentComponent)
|
||||||
return FontRenderContext(
|
return FontRenderContext(
|
||||||
editorContext.transform, AntialiasingType.getKeyForCurrentScope(false),
|
editorContext.transform, AntialiasingType.getKeyForCurrentScope(false),
|
||||||
if (editor is EditorImpl) editor.myFractionalMetricsHintValue else RenderingHints.VALUE_FRACTIONALMETRICS_OFF
|
if (editor is EditorImpl) UISettings.editorFractionalMetricsHint else RenderingHints.VALUE_FRACTIONALMETRICS_OFF
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
97
src/main/java/com/maddyhome/idea/vim/command/CommandState.kt
Normal file
97
src/main/java/com/maddyhome/idea/vim/command/CommandState.kt
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
/*
|
||||||
|
* IdeaVim - Vim emulator for IDEs based on the IntelliJ platform
|
||||||
|
* Copyright (C) 2003-2022 The IdeaVim authors
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.maddyhome.idea.vim.command
|
||||||
|
|
||||||
|
import com.intellij.openapi.editor.Editor
|
||||||
|
import com.maddyhome.idea.vim.helper.vimStateMachine
|
||||||
|
import com.maddyhome.idea.vim.newapi.vim
|
||||||
|
|
||||||
|
/**
|
||||||
|
* COMPATIBILITY-LAYER: Additional class
|
||||||
|
* Please see: https://jb.gg/zo8n0r
|
||||||
|
*/
|
||||||
|
class CommandState(private val machine: VimStateMachine) {
|
||||||
|
|
||||||
|
val isOperatorPending: Boolean
|
||||||
|
get() = machine.isOperatorPending
|
||||||
|
|
||||||
|
val mode: CommandState.Mode
|
||||||
|
get() = machine.mode.ij
|
||||||
|
|
||||||
|
val commandBuilder: CommandBuilder
|
||||||
|
get() = machine.commandBuilder
|
||||||
|
|
||||||
|
val mappingState: MappingState
|
||||||
|
get() = machine.mappingState
|
||||||
|
|
||||||
|
enum class Mode {
|
||||||
|
// Basic modes
|
||||||
|
COMMAND, VISUAL, SELECT, INSERT, CMD_LINE, /*EX*/
|
||||||
|
|
||||||
|
// Additional modes
|
||||||
|
OP_PENDING, REPLACE /*, VISUAL_REPLACE*/, INSERT_NORMAL, INSERT_VISUAL, INSERT_SELECT
|
||||||
|
}
|
||||||
|
|
||||||
|
enum class SubMode {
|
||||||
|
NONE, VISUAL_CHARACTER, VISUAL_LINE, VISUAL_BLOCK
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
@JvmStatic
|
||||||
|
fun getInstance(editor: Editor): CommandState {
|
||||||
|
return CommandState(editor.vim.vimStateMachine)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val CommandState.SubMode.engine: VimStateMachine.SubMode
|
||||||
|
get() = when (this) {
|
||||||
|
CommandState.SubMode.NONE -> VimStateMachine.SubMode.NONE
|
||||||
|
CommandState.SubMode.VISUAL_CHARACTER -> VimStateMachine.SubMode.VISUAL_CHARACTER
|
||||||
|
CommandState.SubMode.VISUAL_LINE -> VimStateMachine.SubMode.VISUAL_LINE
|
||||||
|
CommandState.SubMode.VISUAL_BLOCK -> VimStateMachine.SubMode.VISUAL_BLOCK
|
||||||
|
}
|
||||||
|
|
||||||
|
val CommandState.Mode.engine: VimStateMachine.Mode
|
||||||
|
get() = when (this) {
|
||||||
|
CommandState.Mode.COMMAND -> VimStateMachine.Mode.COMMAND
|
||||||
|
CommandState.Mode.VISUAL -> VimStateMachine.Mode.VISUAL
|
||||||
|
CommandState.Mode.SELECT -> VimStateMachine.Mode.SELECT
|
||||||
|
CommandState.Mode.INSERT -> VimStateMachine.Mode.INSERT
|
||||||
|
CommandState.Mode.CMD_LINE -> VimStateMachine.Mode.CMD_LINE
|
||||||
|
CommandState.Mode.OP_PENDING -> VimStateMachine.Mode.OP_PENDING
|
||||||
|
CommandState.Mode.REPLACE -> VimStateMachine.Mode.REPLACE
|
||||||
|
CommandState.Mode.INSERT_NORMAL -> VimStateMachine.Mode.INSERT_NORMAL
|
||||||
|
CommandState.Mode.INSERT_VISUAL -> VimStateMachine.Mode.INSERT_VISUAL
|
||||||
|
CommandState.Mode.INSERT_SELECT -> VimStateMachine.Mode.INSERT_SELECT
|
||||||
|
}
|
||||||
|
|
||||||
|
val VimStateMachine.Mode.ij: CommandState.Mode
|
||||||
|
get() = when (this) {
|
||||||
|
VimStateMachine.Mode.COMMAND -> CommandState.Mode.COMMAND
|
||||||
|
VimStateMachine.Mode.VISUAL -> CommandState.Mode.VISUAL
|
||||||
|
VimStateMachine.Mode.SELECT -> CommandState.Mode.SELECT
|
||||||
|
VimStateMachine.Mode.INSERT -> CommandState.Mode.INSERT
|
||||||
|
VimStateMachine.Mode.CMD_LINE -> CommandState.Mode.CMD_LINE
|
||||||
|
VimStateMachine.Mode.OP_PENDING -> CommandState.Mode.OP_PENDING
|
||||||
|
VimStateMachine.Mode.REPLACE -> CommandState.Mode.REPLACE
|
||||||
|
VimStateMachine.Mode.INSERT_NORMAL -> CommandState.Mode.INSERT_NORMAL
|
||||||
|
VimStateMachine.Mode.INSERT_VISUAL -> CommandState.Mode.INSERT_VISUAL
|
||||||
|
VimStateMachine.Mode.INSERT_SELECT -> CommandState.Mode.INSERT_SELECT
|
||||||
|
}
|
@@ -23,14 +23,15 @@ import com.intellij.openapi.editor.Editor
|
|||||||
import com.maddyhome.idea.vim.KeyHandler
|
import com.maddyhome.idea.vim.KeyHandler
|
||||||
import com.maddyhome.idea.vim.VimPlugin
|
import com.maddyhome.idea.vim.VimPlugin
|
||||||
import com.maddyhome.idea.vim.action.change.Extension
|
import com.maddyhome.idea.vim.action.change.Extension
|
||||||
|
import com.maddyhome.idea.vim.api.VimCaret
|
||||||
|
import com.maddyhome.idea.vim.command.MappingMode
|
||||||
import com.maddyhome.idea.vim.command.SelectionType
|
import com.maddyhome.idea.vim.command.SelectionType
|
||||||
import com.maddyhome.idea.vim.common.CommandAlias
|
import com.maddyhome.idea.vim.common.CommandAlias
|
||||||
import com.maddyhome.idea.vim.common.CommandAliasHandler
|
import com.maddyhome.idea.vim.common.CommandAliasHandler
|
||||||
import com.maddyhome.idea.vim.common.MappingMode
|
|
||||||
import com.maddyhome.idea.vim.helper.CommandLineHelper
|
import com.maddyhome.idea.vim.helper.CommandLineHelper
|
||||||
import com.maddyhome.idea.vim.helper.EditorDataContext
|
import com.maddyhome.idea.vim.helper.EditorDataContext
|
||||||
import com.maddyhome.idea.vim.helper.TestInputModel
|
import com.maddyhome.idea.vim.helper.TestInputModel
|
||||||
import com.maddyhome.idea.vim.helper.commandState
|
import com.maddyhome.idea.vim.helper.vimStateMachine
|
||||||
import com.maddyhome.idea.vim.key.MappingOwner
|
import com.maddyhome.idea.vim.key.MappingOwner
|
||||||
import com.maddyhome.idea.vim.key.OperatorFunction
|
import com.maddyhome.idea.vim.key.OperatorFunction
|
||||||
import com.maddyhome.idea.vim.newapi.vim
|
import com.maddyhome.idea.vim.newapi.vim
|
||||||
@@ -48,6 +49,22 @@ import javax.swing.KeyStroke
|
|||||||
object VimExtensionFacade {
|
object VimExtensionFacade {
|
||||||
/** The 'map' command for mapping keys to handlers defined in extensions. */
|
/** The 'map' command for mapping keys to handlers defined in extensions. */
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
|
fun putExtensionHandlerMapping(
|
||||||
|
modes: Set<MappingMode>,
|
||||||
|
fromKeys: List<KeyStroke>,
|
||||||
|
pluginOwner: MappingOwner,
|
||||||
|
extensionHandler: ExtensionHandler,
|
||||||
|
recursive: Boolean,
|
||||||
|
) {
|
||||||
|
VimPlugin.getKey().putKeyMapping(modes, fromKeys, pluginOwner, extensionHandler, recursive)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* COMPATIBILITY-LAYER: Additional method
|
||||||
|
* Please see: https://jb.gg/zo8n0r
|
||||||
|
*/
|
||||||
|
/** The 'map' command for mapping keys to handlers defined in extensions. */
|
||||||
|
@JvmStatic
|
||||||
fun putExtensionHandlerMapping(
|
fun putExtensionHandlerMapping(
|
||||||
modes: Set<MappingMode>,
|
modes: Set<MappingMode>,
|
||||||
fromKeys: List<KeyStroke>,
|
fromKeys: List<KeyStroke>,
|
||||||
@@ -129,7 +146,7 @@ object VimExtensionFacade {
|
|||||||
/** Returns a single key stroke from the user input similar to 'getchar()'. */
|
/** Returns a single key stroke from the user input similar to 'getchar()'. */
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun inputKeyStroke(editor: Editor): KeyStroke {
|
fun inputKeyStroke(editor: Editor): KeyStroke {
|
||||||
if (editor.vim.commandState.isDotRepeatInProgress) {
|
if (editor.vim.vimStateMachine.isDotRepeatInProgress) {
|
||||||
val input = Extension.consumeKeystroke()
|
val input = Extension.consumeKeystroke()
|
||||||
return input ?: error("Not enough keystrokes saved: ${Extension.lastExtensionHandler}")
|
return input ?: error("Not enough keystrokes saved: ${Extension.lastExtensionHandler}")
|
||||||
}
|
}
|
||||||
@@ -137,7 +154,7 @@ object VimExtensionFacade {
|
|||||||
val key: KeyStroke? = if (ApplicationManager.getApplication().isUnitTestMode) {
|
val key: KeyStroke? = if (ApplicationManager.getApplication().isUnitTestMode) {
|
||||||
val mappingStack = KeyHandler.getInstance().keyStack
|
val mappingStack = KeyHandler.getInstance().keyStack
|
||||||
mappingStack.feedSomeStroke() ?: TestInputModel.getInstance(editor).nextKeyStroke()?.also {
|
mappingStack.feedSomeStroke() ?: TestInputModel.getInstance(editor).nextKeyStroke()?.also {
|
||||||
if (editor.vim.commandState.isRecording) {
|
if (editor.vim.vimStateMachine.isRecording) {
|
||||||
KeyHandler.getInstance().modalEntryKeys += it
|
KeyHandler.getInstance().modalEntryKeys += it
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -167,12 +184,24 @@ object VimExtensionFacade {
|
|||||||
return reg.keys
|
return reg.keys
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun getRegisterForCaret(register: Char, caret: VimCaret): List<KeyStroke>? {
|
||||||
|
val reg = caret.registerStorage.getRegister(register) ?: return null
|
||||||
|
return reg.keys
|
||||||
|
}
|
||||||
|
|
||||||
/** Set the current contents of the given register */
|
/** Set the current contents of the given register */
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun setRegister(register: Char, keys: List<KeyStroke?>?) {
|
fun setRegister(register: Char, keys: List<KeyStroke?>?) {
|
||||||
VimPlugin.getRegister().setKeys(register, keys?.filterNotNull() ?: emptyList())
|
VimPlugin.getRegister().setKeys(register, keys?.filterNotNull() ?: emptyList())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Set the current contents of the given register */
|
||||||
|
@JvmStatic
|
||||||
|
fun setRegisterForCaret(register: Char, caret: VimCaret, keys: List<KeyStroke?>?) {
|
||||||
|
caret.registerStorage.setKeys(register, keys?.filterNotNull() ?: emptyList())
|
||||||
|
}
|
||||||
|
|
||||||
/** Set the current contents of the given register */
|
/** Set the current contents of the given register */
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun setRegister(register: Char, keys: List<KeyStroke?>?, type: SelectionType) {
|
fun setRegister(register: Char, keys: List<KeyStroke?>?, type: SelectionType) {
|
||||||
|
@@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
* IdeaVim - Vim emulator for IDEs based on the IntelliJ platform
|
||||||
|
* Copyright (C) 2003-2022 The IdeaVim authors
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.maddyhome.idea.vim.extension
|
||||||
|
|
||||||
|
import com.intellij.openapi.actionSystem.DataContext
|
||||||
|
import com.intellij.openapi.editor.Editor
|
||||||
|
import com.maddyhome.idea.vim.api.ExecutionContext
|
||||||
|
import com.maddyhome.idea.vim.api.VimEditor
|
||||||
|
import com.maddyhome.idea.vim.newapi.ij
|
||||||
|
|
||||||
|
/**
|
||||||
|
* COMPATIBILITY-LAYER: Created a class, renamed original class
|
||||||
|
* Please see: https://jb.gg/zo8n0r
|
||||||
|
*/
|
||||||
|
interface VimExtensionHandler : ExtensionHandler {
|
||||||
|
override fun execute(editor: VimEditor, context: ExecutionContext) {
|
||||||
|
execute(editor.ij, context.ij)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun execute(editor: Editor, context: DataContext)
|
||||||
|
|
||||||
|
abstract class WithCallback : ExtensionHandler.WithCallback(), VimExtensionHandler
|
||||||
|
}
|
@@ -25,9 +25,9 @@ import com.maddyhome.idea.vim.api.VimExtensionRegistrator
|
|||||||
import com.maddyhome.idea.vim.api.injector
|
import com.maddyhome.idea.vim.api.injector
|
||||||
import com.maddyhome.idea.vim.ex.ExException
|
import com.maddyhome.idea.vim.ex.ExException
|
||||||
import com.maddyhome.idea.vim.key.MappingOwner.Plugin.Companion.remove
|
import com.maddyhome.idea.vim.key.MappingOwner.Plugin.Companion.remove
|
||||||
|
import com.maddyhome.idea.vim.option.ToggleOption
|
||||||
import com.maddyhome.idea.vim.options.OptionChangeListener
|
import com.maddyhome.idea.vim.options.OptionChangeListener
|
||||||
import com.maddyhome.idea.vim.options.OptionScope
|
import com.maddyhome.idea.vim.options.OptionScope
|
||||||
import com.maddyhome.idea.vim.options.ToggleOption
|
|
||||||
import com.maddyhome.idea.vim.statistic.PluginState
|
import com.maddyhome.idea.vim.statistic.PluginState
|
||||||
import com.maddyhome.idea.vim.vimscript.model.datatypes.VimDataType
|
import com.maddyhome.idea.vim.vimscript.model.datatypes.VimDataType
|
||||||
|
|
||||||
|
@@ -18,24 +18,21 @@
|
|||||||
|
|
||||||
package com.maddyhome.idea.vim.extension.argtextobj;
|
package com.maddyhome.idea.vim.extension.argtextobj;
|
||||||
|
|
||||||
import com.intellij.openapi.actionSystem.DataContext;
|
|
||||||
import com.intellij.openapi.editor.Caret;
|
import com.intellij.openapi.editor.Caret;
|
||||||
import com.intellij.openapi.editor.Document;
|
import com.intellij.openapi.editor.Document;
|
||||||
import com.intellij.openapi.editor.Editor;
|
|
||||||
import com.maddyhome.idea.vim.VimPlugin;
|
import com.maddyhome.idea.vim.VimPlugin;
|
||||||
import com.maddyhome.idea.vim.api.*;
|
import com.maddyhome.idea.vim.api.*;
|
||||||
import com.maddyhome.idea.vim.command.*;
|
import com.maddyhome.idea.vim.command.*;
|
||||||
import com.maddyhome.idea.vim.common.MappingMode;
|
import com.maddyhome.idea.vim.command.MappingMode;
|
||||||
import com.maddyhome.idea.vim.common.TextRange;
|
import com.maddyhome.idea.vim.common.TextRange;
|
||||||
import com.maddyhome.idea.vim.extension.VimExtension;
|
import com.maddyhome.idea.vim.extension.VimExtension;
|
||||||
import com.maddyhome.idea.vim.extension.VimExtensionHandler;
|
import com.maddyhome.idea.vim.extension.ExtensionHandler;
|
||||||
import com.maddyhome.idea.vim.handler.TextObjectActionHandler;
|
import com.maddyhome.idea.vim.handler.TextObjectActionHandler;
|
||||||
import com.maddyhome.idea.vim.helper.InlayHelperKt;
|
import com.maddyhome.idea.vim.helper.InlayHelperKt;
|
||||||
import com.maddyhome.idea.vim.helper.MessageHelper;
|
import com.maddyhome.idea.vim.helper.MessageHelper;
|
||||||
import com.maddyhome.idea.vim.helper.VimNlsSafe;
|
import com.maddyhome.idea.vim.helper.VimNlsSafe;
|
||||||
import com.maddyhome.idea.vim.listener.SelectionVimListenerSuppressor;
|
import com.maddyhome.idea.vim.listener.SelectionVimListenerSuppressor;
|
||||||
import com.maddyhome.idea.vim.listener.VimListenerSuppressor;
|
import com.maddyhome.idea.vim.listener.VimListenerSuppressor;
|
||||||
import com.maddyhome.idea.vim.newapi.IjExecutionContext;
|
|
||||||
import com.maddyhome.idea.vim.newapi.IjVimCaret;
|
import com.maddyhome.idea.vim.newapi.IjVimCaret;
|
||||||
import com.maddyhome.idea.vim.newapi.IjVimEditor;
|
import com.maddyhome.idea.vim.newapi.IjVimEditor;
|
||||||
import com.maddyhome.idea.vim.vimscript.model.datatypes.VimString;
|
import com.maddyhome.idea.vim.vimscript.model.datatypes.VimString;
|
||||||
@@ -186,7 +183,7 @@ public class VimArgTextObjExtension implements VimExtension {
|
|||||||
/**
|
/**
|
||||||
* A text object for an argument to a function definition or a call.
|
* A text object for an argument to a function definition or a call.
|
||||||
*/
|
*/
|
||||||
static class ArgumentHandler implements VimExtensionHandler {
|
static class ArgumentHandler implements ExtensionHandler {
|
||||||
final boolean isInner;
|
final boolean isInner;
|
||||||
|
|
||||||
ArgumentHandler(boolean isInner) {
|
ArgumentHandler(boolean isInner) {
|
||||||
@@ -262,17 +259,17 @@ public class VimArgTextObjExtension implements VimExtension {
|
|||||||
public void execute(@NotNull VimEditor editor, @NotNull ExecutionContext context) {
|
public void execute(@NotNull VimEditor editor, @NotNull ExecutionContext context) {
|
||||||
|
|
||||||
IjVimEditor vimEditor = (IjVimEditor) editor;
|
IjVimEditor vimEditor = (IjVimEditor) editor;
|
||||||
@NotNull CommandState commandState = CommandState.getInstance(vimEditor);
|
@NotNull VimStateMachine vimStateMachine = VimStateMachine.getInstance(vimEditor);
|
||||||
int count = Math.max(1, commandState.getCommandBuilder().getCount());
|
int count = Math.max(1, vimStateMachine.getCommandBuilder().getCount());
|
||||||
|
|
||||||
final ArgumentTextObjectHandler textObjectHandler = new ArgumentTextObjectHandler(isInner);
|
final ArgumentTextObjectHandler textObjectHandler = new ArgumentTextObjectHandler(isInner);
|
||||||
//noinspection DuplicatedCode
|
//noinspection DuplicatedCode
|
||||||
if (!commandState.isOperatorPending()) {
|
if (!vimStateMachine.isOperatorPending()) {
|
||||||
vimEditor.getEditor().getCaretModel().runForEachCaret((Caret caret) -> {
|
vimEditor.getEditor().getCaretModel().runForEachCaret((Caret caret) -> {
|
||||||
final TextRange range = textObjectHandler.getRange(vimEditor, new IjVimCaret(caret), context, count, 0, null);
|
final TextRange range = textObjectHandler.getRange(vimEditor, new IjVimCaret(caret), context, count, 0, null);
|
||||||
if (range != null) {
|
if (range != null) {
|
||||||
try (VimListenerSuppressor.Locked ignored = SelectionVimListenerSuppressor.INSTANCE.lock()) {
|
try (VimListenerSuppressor.Locked ignored = SelectionVimListenerSuppressor.INSTANCE.lock()) {
|
||||||
if (commandState.getMode() == CommandState.Mode.VISUAL) {
|
if (vimStateMachine.getMode() == VimStateMachine.Mode.VISUAL) {
|
||||||
vimSetSelection(caret, range.getStartOffset(), range.getEndOffset() - 1, true);
|
vimSetSelection(caret, range.getStartOffset(), range.getEndOffset() - 1, true);
|
||||||
} else {
|
} else {
|
||||||
InlayHelperKt.moveToInlayAwareOffset(caret, range.getStartOffset());
|
InlayHelperKt.moveToInlayAwareOffset(caret, range.getStartOffset());
|
||||||
@@ -282,7 +279,7 @@ public class VimArgTextObjExtension implements VimExtension {
|
|||||||
|
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
commandState.getCommandBuilder().completeCommandPart(new Argument(new Command(count,
|
vimStateMachine.getCommandBuilder().completeCommandPart(new Argument(new Command(count,
|
||||||
textObjectHandler, Command.Type.MOTION, EnumSet.noneOf(CommandFlags.class))));
|
textObjectHandler, Command.Type.MOTION, EnumSet.noneOf(CommandFlags.class))));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -34,13 +34,14 @@ import com.maddyhome.idea.vim.api.injector
|
|||||||
import com.maddyhome.idea.vim.command.Argument
|
import com.maddyhome.idea.vim.command.Argument
|
||||||
import com.maddyhome.idea.vim.command.Command
|
import com.maddyhome.idea.vim.command.Command
|
||||||
import com.maddyhome.idea.vim.command.CommandFlags
|
import com.maddyhome.idea.vim.command.CommandFlags
|
||||||
import com.maddyhome.idea.vim.command.CommandState
|
import com.maddyhome.idea.vim.command.MappingMode
|
||||||
import com.maddyhome.idea.vim.command.SelectionType
|
import com.maddyhome.idea.vim.command.SelectionType
|
||||||
import com.maddyhome.idea.vim.command.TextObjectVisualType
|
import com.maddyhome.idea.vim.command.TextObjectVisualType
|
||||||
|
import com.maddyhome.idea.vim.command.VimStateMachine
|
||||||
import com.maddyhome.idea.vim.common.CommandAliasHandler
|
import com.maddyhome.idea.vim.common.CommandAliasHandler
|
||||||
import com.maddyhome.idea.vim.common.MappingMode
|
|
||||||
import com.maddyhome.idea.vim.common.TextRange
|
import com.maddyhome.idea.vim.common.TextRange
|
||||||
import com.maddyhome.idea.vim.ex.ranges.Ranges
|
import com.maddyhome.idea.vim.ex.ranges.Ranges
|
||||||
|
import com.maddyhome.idea.vim.extension.ExtensionHandler
|
||||||
import com.maddyhome.idea.vim.extension.VimExtension
|
import com.maddyhome.idea.vim.extension.VimExtension
|
||||||
import com.maddyhome.idea.vim.extension.VimExtensionFacade.addCommand
|
import com.maddyhome.idea.vim.extension.VimExtensionFacade.addCommand
|
||||||
import com.maddyhome.idea.vim.extension.VimExtensionFacade.executeNormalWithoutMapping
|
import com.maddyhome.idea.vim.extension.VimExtensionFacade.executeNormalWithoutMapping
|
||||||
@@ -48,11 +49,10 @@ import com.maddyhome.idea.vim.extension.VimExtensionFacade.putExtensionHandlerMa
|
|||||||
import com.maddyhome.idea.vim.extension.VimExtensionFacade.putKeyMapping
|
import com.maddyhome.idea.vim.extension.VimExtensionFacade.putKeyMapping
|
||||||
import com.maddyhome.idea.vim.extension.VimExtensionFacade.putKeyMappingIfMissing
|
import com.maddyhome.idea.vim.extension.VimExtensionFacade.putKeyMappingIfMissing
|
||||||
import com.maddyhome.idea.vim.extension.VimExtensionFacade.setOperatorFunction
|
import com.maddyhome.idea.vim.extension.VimExtensionFacade.setOperatorFunction
|
||||||
import com.maddyhome.idea.vim.extension.VimExtensionHandler
|
|
||||||
import com.maddyhome.idea.vim.handler.TextObjectActionHandler
|
import com.maddyhome.idea.vim.handler.TextObjectActionHandler
|
||||||
import com.maddyhome.idea.vim.helper.EditorHelper
|
import com.maddyhome.idea.vim.helper.EditorHelper
|
||||||
import com.maddyhome.idea.vim.helper.PsiHelper
|
import com.maddyhome.idea.vim.helper.PsiHelper
|
||||||
import com.maddyhome.idea.vim.helper.commandState
|
import com.maddyhome.idea.vim.helper.vimStateMachine
|
||||||
import com.maddyhome.idea.vim.key.OperatorFunction
|
import com.maddyhome.idea.vim.key.OperatorFunction
|
||||||
import com.maddyhome.idea.vim.newapi.IjVimEditor
|
import com.maddyhome.idea.vim.newapi.IjVimEditor
|
||||||
import com.maddyhome.idea.vim.newapi.ij
|
import com.maddyhome.idea.vim.newapi.ij
|
||||||
@@ -63,8 +63,8 @@ class CommentaryExtension : VimExtension {
|
|||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun doCommentary(editor: VimEditor, context: ExecutionContext, range: TextRange, selectionType: SelectionType, resetCaret: Boolean): Boolean {
|
fun doCommentary(editor: VimEditor, context: ExecutionContext, range: TextRange, selectionType: SelectionType, resetCaret: Boolean): Boolean {
|
||||||
val mode = editor.commandState.mode
|
val mode = editor.vimStateMachine.mode
|
||||||
if (mode !== CommandState.Mode.VISUAL) {
|
if (mode !== VimStateMachine.Mode.VISUAL) {
|
||||||
editor.ij.selectionModel.setSelection(range.startOffset, range.endOffset)
|
editor.ij.selectionModel.setSelection(range.startOffset, range.endOffset)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -82,7 +82,7 @@ class CommentaryExtension : VimExtension {
|
|||||||
injector.actionExecutor.executeAction(actions[1], context)
|
injector.actionExecutor.executeAction(actions[1], context)
|
||||||
} finally {
|
} finally {
|
||||||
// Remove the selection, if we added it
|
// Remove the selection, if we added it
|
||||||
if (mode !== CommandState.Mode.VISUAL) {
|
if (mode !== VimStateMachine.Mode.VISUAL) {
|
||||||
editor.removeSelection()
|
editor.removeSelection()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -129,7 +129,7 @@ class CommentaryExtension : VimExtension {
|
|||||||
* E.g. handles the `gc` in `gc_`, by setting the operator function, then invoking `g@` to receive the `_` motion to
|
* E.g. handles the `gc` in `gc_`, by setting the operator function, then invoking `g@` to receive the `_` motion to
|
||||||
* invoke the operator. This object is both the mapping handler and the operator function.
|
* invoke the operator. This object is both the mapping handler and the operator function.
|
||||||
*/
|
*/
|
||||||
private class CommentaryOperatorHandler : OperatorFunction, VimExtensionHandler {
|
private class CommentaryOperatorHandler : OperatorFunction, ExtensionHandler {
|
||||||
override val isRepeatable = true
|
override val isRepeatable = true
|
||||||
|
|
||||||
override fun execute(editor: VimEditor, context: ExecutionContext) {
|
override fun execute(editor: VimEditor, context: ExecutionContext) {
|
||||||
@@ -148,11 +148,11 @@ class CommentaryExtension : VimExtension {
|
|||||||
*
|
*
|
||||||
* This object is both the `<Plug>Commentary` mapping handler and the text object handler
|
* This object is both the `<Plug>Commentary` mapping handler and the text object handler
|
||||||
*/
|
*/
|
||||||
private class CommentaryTextObjectMotionHandler : TextObjectActionHandler(), VimExtensionHandler {
|
private class CommentaryTextObjectMotionHandler : TextObjectActionHandler(), ExtensionHandler {
|
||||||
override val isRepeatable = true
|
override val isRepeatable = true
|
||||||
|
|
||||||
override fun execute(editor: VimEditor, context: ExecutionContext) {
|
override fun execute(editor: VimEditor, context: ExecutionContext) {
|
||||||
val commandState = editor.commandState
|
val commandState = editor.vimStateMachine
|
||||||
val count = maxOf(1, commandState.commandBuilder.count)
|
val count = maxOf(1, commandState.commandBuilder.count)
|
||||||
|
|
||||||
val textObjectHandler = this
|
val textObjectHandler = this
|
||||||
|
@@ -31,10 +31,11 @@ import com.maddyhome.idea.vim.VimPlugin
|
|||||||
import com.maddyhome.idea.vim.api.ExecutionContext
|
import com.maddyhome.idea.vim.api.ExecutionContext
|
||||||
import com.maddyhome.idea.vim.api.VimEditor
|
import com.maddyhome.idea.vim.api.VimEditor
|
||||||
import com.maddyhome.idea.vim.api.injector
|
import com.maddyhome.idea.vim.api.injector
|
||||||
import com.maddyhome.idea.vim.command.CommandState
|
import com.maddyhome.idea.vim.command.MappingMode
|
||||||
import com.maddyhome.idea.vim.command.SelectionType
|
import com.maddyhome.idea.vim.command.SelectionType
|
||||||
import com.maddyhome.idea.vim.common.MappingMode
|
import com.maddyhome.idea.vim.command.VimStateMachine
|
||||||
import com.maddyhome.idea.vim.common.TextRange
|
import com.maddyhome.idea.vim.common.TextRange
|
||||||
|
import com.maddyhome.idea.vim.extension.ExtensionHandler
|
||||||
import com.maddyhome.idea.vim.extension.VimExtension
|
import com.maddyhome.idea.vim.extension.VimExtension
|
||||||
import com.maddyhome.idea.vim.extension.VimExtensionFacade.executeNormalWithoutMapping
|
import com.maddyhome.idea.vim.extension.VimExtensionFacade.executeNormalWithoutMapping
|
||||||
import com.maddyhome.idea.vim.extension.VimExtensionFacade.getRegister
|
import com.maddyhome.idea.vim.extension.VimExtensionFacade.getRegister
|
||||||
@@ -42,7 +43,6 @@ import com.maddyhome.idea.vim.extension.VimExtensionFacade.putExtensionHandlerMa
|
|||||||
import com.maddyhome.idea.vim.extension.VimExtensionFacade.putKeyMappingIfMissing
|
import com.maddyhome.idea.vim.extension.VimExtensionFacade.putKeyMappingIfMissing
|
||||||
import com.maddyhome.idea.vim.extension.VimExtensionFacade.setOperatorFunction
|
import com.maddyhome.idea.vim.extension.VimExtensionFacade.setOperatorFunction
|
||||||
import com.maddyhome.idea.vim.extension.VimExtensionFacade.setRegister
|
import com.maddyhome.idea.vim.extension.VimExtensionFacade.setRegister
|
||||||
import com.maddyhome.idea.vim.extension.VimExtensionHandler
|
|
||||||
import com.maddyhome.idea.vim.helper.EditorHelper
|
import com.maddyhome.idea.vim.helper.EditorHelper
|
||||||
import com.maddyhome.idea.vim.helper.fileSize
|
import com.maddyhome.idea.vim.helper.fileSize
|
||||||
import com.maddyhome.idea.vim.helper.moveToInlayAwareLogicalPosition
|
import com.maddyhome.idea.vim.helper.moveToInlayAwareLogicalPosition
|
||||||
@@ -95,7 +95,7 @@ class VimExchangeExtension : VimExtension {
|
|||||||
val EXCHANGE_KEY = Key<Exchange>("exchange")
|
val EXCHANGE_KEY = Key<Exchange>("exchange")
|
||||||
|
|
||||||
// End mark has always greater of eq offset than start mark
|
// End mark has always greater of eq offset than start mark
|
||||||
class Exchange(val type: CommandState.SubMode, val start: Mark, val end: Mark, val text: String) {
|
class Exchange(val type: VimStateMachine.SubMode, val start: Mark, val end: Mark, val text: String) {
|
||||||
private var myHighlighter: RangeHighlighter? = null
|
private var myHighlighter: RangeHighlighter? = null
|
||||||
fun setHighlighter(highlighter: RangeHighlighter) {
|
fun setHighlighter(highlighter: RangeHighlighter) {
|
||||||
myHighlighter = highlighter
|
myHighlighter = highlighter
|
||||||
@@ -112,7 +112,7 @@ class VimExchangeExtension : VimExtension {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class ExchangeHandler(private val isLine: Boolean) : VimExtensionHandler {
|
private class ExchangeHandler(private val isLine: Boolean) : ExtensionHandler {
|
||||||
override val isRepeatable = true
|
override val isRepeatable = true
|
||||||
|
|
||||||
override fun execute(editor: VimEditor, context: ExecutionContext) {
|
override fun execute(editor: VimEditor, context: ExecutionContext) {
|
||||||
@@ -121,13 +121,13 @@ class VimExchangeExtension : VimExtension {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class ExchangeClearHandler : VimExtensionHandler {
|
private class ExchangeClearHandler : ExtensionHandler {
|
||||||
override fun execute(editor: VimEditor, context: ExecutionContext) {
|
override fun execute(editor: VimEditor, context: ExecutionContext) {
|
||||||
clearExchange(editor.ij)
|
clearExchange(editor.ij)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class VExchangeHandler : VimExtensionHandler {
|
private class VExchangeHandler : ExtensionHandler {
|
||||||
override fun execute(editor: VimEditor, context: ExecutionContext) {
|
override fun execute(editor: VimEditor, context: ExecutionContext) {
|
||||||
runWriteAction {
|
runWriteAction {
|
||||||
val subMode = editor.subMode
|
val subMode = editor.subMode
|
||||||
@@ -140,10 +140,10 @@ class VimExchangeExtension : VimExtension {
|
|||||||
|
|
||||||
private class Operator(private val isVisual: Boolean) : OperatorFunction {
|
private class Operator(private val isVisual: Boolean) : OperatorFunction {
|
||||||
fun Editor.getMarkOffset(mark: Mark) = EditorHelper.getOffset(this, mark.logicalLine, mark.col)
|
fun Editor.getMarkOffset(mark: Mark) = EditorHelper.getOffset(this, mark.logicalLine, mark.col)
|
||||||
fun CommandState.SubMode.getString() = when (this) {
|
fun VimStateMachine.SubMode.getString() = when (this) {
|
||||||
CommandState.SubMode.VISUAL_CHARACTER -> "v"
|
VimStateMachine.SubMode.VISUAL_CHARACTER -> "v"
|
||||||
CommandState.SubMode.VISUAL_LINE -> "V"
|
VimStateMachine.SubMode.VISUAL_LINE -> "V"
|
||||||
CommandState.SubMode.VISUAL_BLOCK -> "\\<C-V>"
|
VimStateMachine.SubMode.VISUAL_BLOCK -> "\\<C-V>"
|
||||||
else -> error("Invalid SubMode: $this")
|
else -> error("Invalid SubMode: $this")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -151,7 +151,7 @@ class VimExchangeExtension : VimExtension {
|
|||||||
fun highlightExchange(ex: Exchange): RangeHighlighter {
|
fun highlightExchange(ex: Exchange): RangeHighlighter {
|
||||||
val attributes = editor.colorsScheme.getAttributes(EditorColors.TEXT_SEARCH_RESULT_ATTRIBUTES)
|
val attributes = editor.colorsScheme.getAttributes(EditorColors.TEXT_SEARCH_RESULT_ATTRIBUTES)
|
||||||
val hlArea = when (ex.type) {
|
val hlArea = when (ex.type) {
|
||||||
CommandState.SubMode.VISUAL_LINE -> HighlighterTargetArea.LINES_IN_RANGE
|
VimStateMachine.SubMode.VISUAL_LINE -> HighlighterTargetArea.LINES_IN_RANGE
|
||||||
// TODO: handle other modes
|
// TODO: handle other modes
|
||||||
else -> HighlighterTargetArea.EXACT_RANGE
|
else -> HighlighterTargetArea.EXACT_RANGE
|
||||||
}
|
}
|
||||||
@@ -274,7 +274,7 @@ class VimExchangeExtension : VimExtension {
|
|||||||
x.logicalLine - y.logicalLine
|
x.logicalLine - y.logicalLine
|
||||||
}
|
}
|
||||||
|
|
||||||
return if (x.type == CommandState.SubMode.VISUAL_BLOCK && y.type == CommandState.SubMode.VISUAL_BLOCK) {
|
return if (x.type == VimStateMachine.SubMode.VISUAL_BLOCK && y.type == VimStateMachine.SubMode.VISUAL_BLOCK) {
|
||||||
when {
|
when {
|
||||||
intersects(x, y) -> {
|
intersects(x, y) -> {
|
||||||
ExchangeCompareResult.OVERLAP
|
ExchangeCompareResult.OVERLAP
|
||||||
|
@@ -33,21 +33,21 @@ import com.maddyhome.idea.vim.api.injector
|
|||||||
import com.maddyhome.idea.vim.command.Argument
|
import com.maddyhome.idea.vim.command.Argument
|
||||||
import com.maddyhome.idea.vim.command.Command
|
import com.maddyhome.idea.vim.command.Command
|
||||||
import com.maddyhome.idea.vim.command.CommandFlags
|
import com.maddyhome.idea.vim.command.CommandFlags
|
||||||
|
import com.maddyhome.idea.vim.command.MappingMode
|
||||||
import com.maddyhome.idea.vim.command.MotionType
|
import com.maddyhome.idea.vim.command.MotionType
|
||||||
import com.maddyhome.idea.vim.command.OperatorArguments
|
import com.maddyhome.idea.vim.command.OperatorArguments
|
||||||
import com.maddyhome.idea.vim.common.Direction
|
import com.maddyhome.idea.vim.common.Direction
|
||||||
import com.maddyhome.idea.vim.common.MappingMode
|
import com.maddyhome.idea.vim.extension.ExtensionHandler
|
||||||
import com.maddyhome.idea.vim.extension.VimExtension
|
import com.maddyhome.idea.vim.extension.VimExtension
|
||||||
import com.maddyhome.idea.vim.extension.VimExtensionFacade
|
import com.maddyhome.idea.vim.extension.VimExtensionFacade
|
||||||
import com.maddyhome.idea.vim.extension.VimExtensionFacade.putKeyMappingIfMissing
|
import com.maddyhome.idea.vim.extension.VimExtensionFacade.putKeyMappingIfMissing
|
||||||
import com.maddyhome.idea.vim.extension.VimExtensionHandler
|
|
||||||
import com.maddyhome.idea.vim.handler.Motion
|
import com.maddyhome.idea.vim.handler.Motion
|
||||||
import com.maddyhome.idea.vim.handler.MotionActionHandler
|
import com.maddyhome.idea.vim.handler.MotionActionHandler
|
||||||
import com.maddyhome.idea.vim.handler.toMotionOrError
|
import com.maddyhome.idea.vim.handler.toMotionOrError
|
||||||
import com.maddyhome.idea.vim.helper.EditorHelper
|
import com.maddyhome.idea.vim.helper.EditorHelper
|
||||||
import com.maddyhome.idea.vim.helper.PsiHelper
|
import com.maddyhome.idea.vim.helper.PsiHelper
|
||||||
import com.maddyhome.idea.vim.helper.commandState
|
|
||||||
import com.maddyhome.idea.vim.helper.enumSetOf
|
import com.maddyhome.idea.vim.helper.enumSetOf
|
||||||
|
import com.maddyhome.idea.vim.helper.vimStateMachine
|
||||||
import com.maddyhome.idea.vim.newapi.ij
|
import com.maddyhome.idea.vim.newapi.ij
|
||||||
import com.maddyhome.idea.vim.newapi.vim
|
import com.maddyhome.idea.vim.newapi.vim
|
||||||
import java.util.*
|
import java.util.*
|
||||||
@@ -94,14 +94,14 @@ class Matchit : VimExtension {
|
|||||||
override var motionType: MotionType = MotionType.INCLUSIVE
|
override var motionType: MotionType = MotionType.INCLUSIVE
|
||||||
}
|
}
|
||||||
|
|
||||||
private class MatchitHandler(private val reverse: Boolean) : VimExtensionHandler {
|
private class MatchitHandler(private val reverse: Boolean) : ExtensionHandler {
|
||||||
|
|
||||||
override fun execute(editor: VimEditor, context: ExecutionContext) {
|
override fun execute(editor: VimEditor, context: ExecutionContext) {
|
||||||
val commandState = editor.commandState
|
val commandState = editor.vimStateMachine
|
||||||
val count = commandState.commandBuilder.count
|
val count = commandState.commandBuilder.count
|
||||||
|
|
||||||
// Reset the command count so it doesn't transfer onto subsequent commands.
|
// Reset the command count so it doesn't transfer onto subsequent commands.
|
||||||
editor.commandState.commandBuilder.resetCount()
|
editor.vimStateMachine.commandBuilder.resetCount()
|
||||||
|
|
||||||
// Normally we want to jump to the start of the matching pair. But when moving forward in operator
|
// Normally we want to jump to the start of the matching pair. But when moving forward in operator
|
||||||
// pending mode, we want to include the entire match. isInOpPending makes that distinction.
|
// pending mode, we want to include the entire match. isInOpPending makes that distinction.
|
||||||
|
@@ -29,13 +29,13 @@ import com.maddyhome.idea.vim.VimPlugin
|
|||||||
import com.maddyhome.idea.vim.api.ExecutionContext
|
import com.maddyhome.idea.vim.api.ExecutionContext
|
||||||
import com.maddyhome.idea.vim.api.VimEditor
|
import com.maddyhome.idea.vim.api.VimEditor
|
||||||
import com.maddyhome.idea.vim.api.injector
|
import com.maddyhome.idea.vim.api.injector
|
||||||
import com.maddyhome.idea.vim.command.CommandState
|
import com.maddyhome.idea.vim.command.MappingMode
|
||||||
import com.maddyhome.idea.vim.common.MappingMode
|
import com.maddyhome.idea.vim.command.VimStateMachine
|
||||||
import com.maddyhome.idea.vim.common.TextRange
|
import com.maddyhome.idea.vim.common.TextRange
|
||||||
|
import com.maddyhome.idea.vim.extension.ExtensionHandler
|
||||||
import com.maddyhome.idea.vim.extension.VimExtension
|
import com.maddyhome.idea.vim.extension.VimExtension
|
||||||
import com.maddyhome.idea.vim.extension.VimExtensionFacade.putExtensionHandlerMapping
|
import com.maddyhome.idea.vim.extension.VimExtensionFacade.putExtensionHandlerMapping
|
||||||
import com.maddyhome.idea.vim.extension.VimExtensionFacade.putKeyMappingIfMissing
|
import com.maddyhome.idea.vim.extension.VimExtensionFacade.putKeyMappingIfMissing
|
||||||
import com.maddyhome.idea.vim.extension.VimExtensionHandler
|
|
||||||
import com.maddyhome.idea.vim.group.MotionGroup
|
import com.maddyhome.idea.vim.group.MotionGroup
|
||||||
import com.maddyhome.idea.vim.group.visual.vimSetSelection
|
import com.maddyhome.idea.vim.group.visual.vimSetSelection
|
||||||
import com.maddyhome.idea.vim.helper.EditorHelper
|
import com.maddyhome.idea.vim.helper.EditorHelper
|
||||||
@@ -111,7 +111,7 @@ class VimMultipleCursorsExtension : VimExtension {
|
|||||||
putKeyMappingIfMissing(MappingMode.X, injector.parser.parseKeys("<A-p>"), owner, injector.parser.parseKeys(REMOVE_OCCURRENCE), true)
|
putKeyMappingIfMissing(MappingMode.X, injector.parser.parseKeys("<A-p>"), owner, injector.parser.parseKeys(REMOVE_OCCURRENCE), true)
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class WriteActionHandler : VimExtensionHandler {
|
abstract class WriteActionHandler : ExtensionHandler {
|
||||||
override fun execute(editor: VimEditor, context: ExecutionContext) {
|
override fun execute(editor: VimEditor, context: ExecutionContext) {
|
||||||
ApplicationManager.getApplication().runWriteAction {
|
ApplicationManager.getApplication().runWriteAction {
|
||||||
executeInWriteAction(editor.ij, context.ij)
|
executeInWriteAction(editor.ij, context.ij)
|
||||||
@@ -313,7 +313,7 @@ class VimMultipleCursorsExtension : VimExtension {
|
|||||||
|
|
||||||
private fun enterVisualMode(editor: VimEditor) {
|
private fun enterVisualMode(editor: VimEditor) {
|
||||||
// We need to reset the key handler to make sure we pick up the fact that we're in visual mode
|
// We need to reset the key handler to make sure we pick up the fact that we're in visual mode
|
||||||
VimPlugin.getVisualMotion().enterVisualMode(editor, CommandState.SubMode.VISUAL_CHARACTER)
|
VimPlugin.getVisualMotion().enterVisualMode(editor, VimStateMachine.SubMode.VISUAL_CHARACTER)
|
||||||
KeyHandler.getInstance().reset(editor)
|
KeyHandler.getInstance().reset(editor)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -44,18 +44,18 @@ import com.maddyhome.idea.vim.api.VimEditor
|
|||||||
import com.maddyhome.idea.vim.api.injector
|
import com.maddyhome.idea.vim.api.injector
|
||||||
import com.maddyhome.idea.vim.common.CommandAlias
|
import com.maddyhome.idea.vim.common.CommandAlias
|
||||||
import com.maddyhome.idea.vim.common.CommandAliasHandler
|
import com.maddyhome.idea.vim.common.CommandAliasHandler
|
||||||
import com.maddyhome.idea.vim.common.CommandNode
|
|
||||||
import com.maddyhome.idea.vim.common.CommandPartNode
|
|
||||||
import com.maddyhome.idea.vim.common.Node
|
|
||||||
import com.maddyhome.idea.vim.common.RootNode
|
|
||||||
import com.maddyhome.idea.vim.common.addLeafs
|
|
||||||
import com.maddyhome.idea.vim.ex.ranges.Ranges
|
import com.maddyhome.idea.vim.ex.ranges.Ranges
|
||||||
import com.maddyhome.idea.vim.extension.VimExtension
|
import com.maddyhome.idea.vim.extension.VimExtension
|
||||||
import com.maddyhome.idea.vim.group.KeyGroup
|
import com.maddyhome.idea.vim.group.KeyGroup
|
||||||
import com.maddyhome.idea.vim.helper.MessageHelper
|
import com.maddyhome.idea.vim.helper.MessageHelper
|
||||||
import com.maddyhome.idea.vim.helper.runAfterGotFocus
|
import com.maddyhome.idea.vim.helper.runAfterGotFocus
|
||||||
|
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.MappingOwner
|
||||||
|
import com.maddyhome.idea.vim.key.Node
|
||||||
import com.maddyhome.idea.vim.key.RequiredShortcut
|
import com.maddyhome.idea.vim.key.RequiredShortcut
|
||||||
|
import com.maddyhome.idea.vim.key.RootNode
|
||||||
|
import com.maddyhome.idea.vim.key.addLeafs
|
||||||
import com.maddyhome.idea.vim.newapi.ij
|
import com.maddyhome.idea.vim.newapi.ij
|
||||||
import com.maddyhome.idea.vim.newapi.vim
|
import com.maddyhome.idea.vim.newapi.vim
|
||||||
import com.maddyhome.idea.vim.vimscript.model.datatypes.VimString
|
import com.maddyhome.idea.vim.vimscript.model.datatypes.VimString
|
||||||
|
@@ -23,11 +23,11 @@ import com.intellij.openapi.editor.Editor
|
|||||||
import com.maddyhome.idea.vim.api.ExecutionContext
|
import com.maddyhome.idea.vim.api.ExecutionContext
|
||||||
import com.maddyhome.idea.vim.api.VimEditor
|
import com.maddyhome.idea.vim.api.VimEditor
|
||||||
import com.maddyhome.idea.vim.api.injector
|
import com.maddyhome.idea.vim.api.injector
|
||||||
import com.maddyhome.idea.vim.common.MappingMode
|
import com.maddyhome.idea.vim.command.MappingMode
|
||||||
|
import com.maddyhome.idea.vim.extension.ExtensionHandler
|
||||||
import com.maddyhome.idea.vim.extension.VimExtension
|
import com.maddyhome.idea.vim.extension.VimExtension
|
||||||
import com.maddyhome.idea.vim.extension.VimExtensionFacade
|
import com.maddyhome.idea.vim.extension.VimExtensionFacade
|
||||||
import com.maddyhome.idea.vim.extension.VimExtensionFacade.putKeyMappingIfMissing
|
import com.maddyhome.idea.vim.extension.VimExtensionFacade.putKeyMappingIfMissing
|
||||||
import com.maddyhome.idea.vim.extension.VimExtensionHandler
|
|
||||||
import com.maddyhome.idea.vim.group.MotionGroup
|
import com.maddyhome.idea.vim.group.MotionGroup
|
||||||
import com.maddyhome.idea.vim.helper.EditorHelper
|
import com.maddyhome.idea.vim.helper.EditorHelper
|
||||||
import com.maddyhome.idea.vim.helper.SearchHelper
|
import com.maddyhome.idea.vim.helper.SearchHelper
|
||||||
@@ -45,7 +45,7 @@ class ParagraphMotion : VimExtension {
|
|||||||
putKeyMappingIfMissing(MappingMode.NXO, injector.parser.parseKeys("{"), owner, injector.parser.parseKeys("<Plug>(ParagraphPrevMotion)"), true)
|
putKeyMappingIfMissing(MappingMode.NXO, injector.parser.parseKeys("{"), owner, injector.parser.parseKeys("<Plug>(ParagraphPrevMotion)"), true)
|
||||||
}
|
}
|
||||||
|
|
||||||
private class ParagraphMotionHandler(private val count: Int) : VimExtensionHandler {
|
private class ParagraphMotionHandler(private val count: Int) : ExtensionHandler {
|
||||||
override fun execute(editor: VimEditor, context: ExecutionContext) {
|
override fun execute(editor: VimEditor, context: ExecutionContext) {
|
||||||
editor.ij.vimForEachCaret { caret ->
|
editor.ij.vimForEachCaret { caret ->
|
||||||
val motion = moveCaretToNextParagraph(editor.ij, caret, count)
|
val motion = moveCaretToNextParagraph(editor.ij, caret, count)
|
||||||
|
@@ -25,21 +25,24 @@ import com.maddyhome.idea.vim.api.ExecutionContext
|
|||||||
import com.maddyhome.idea.vim.api.VimCaret
|
import com.maddyhome.idea.vim.api.VimCaret
|
||||||
import com.maddyhome.idea.vim.api.VimEditor
|
import com.maddyhome.idea.vim.api.VimEditor
|
||||||
import com.maddyhome.idea.vim.api.injector
|
import com.maddyhome.idea.vim.api.injector
|
||||||
import com.maddyhome.idea.vim.command.CommandState
|
import com.maddyhome.idea.vim.command.MappingMode
|
||||||
|
import com.maddyhome.idea.vim.command.OperatorArguments
|
||||||
import com.maddyhome.idea.vim.command.SelectionType
|
import com.maddyhome.idea.vim.command.SelectionType
|
||||||
|
import com.maddyhome.idea.vim.command.VimStateMachine
|
||||||
import com.maddyhome.idea.vim.command.isLine
|
import com.maddyhome.idea.vim.command.isLine
|
||||||
import com.maddyhome.idea.vim.common.MappingMode
|
|
||||||
import com.maddyhome.idea.vim.common.TextRange
|
import com.maddyhome.idea.vim.common.TextRange
|
||||||
|
import com.maddyhome.idea.vim.extension.ExtensionHandler
|
||||||
import com.maddyhome.idea.vim.extension.VimExtension
|
import com.maddyhome.idea.vim.extension.VimExtension
|
||||||
import com.maddyhome.idea.vim.extension.VimExtensionFacade
|
import com.maddyhome.idea.vim.extension.VimExtensionFacade
|
||||||
import com.maddyhome.idea.vim.extension.VimExtensionFacade.executeNormalWithoutMapping
|
import com.maddyhome.idea.vim.extension.VimExtensionFacade.executeNormalWithoutMapping
|
||||||
import com.maddyhome.idea.vim.extension.VimExtensionFacade.putKeyMappingIfMissing
|
import com.maddyhome.idea.vim.extension.VimExtensionFacade.putKeyMappingIfMissing
|
||||||
import com.maddyhome.idea.vim.extension.VimExtensionFacade.setOperatorFunction
|
import com.maddyhome.idea.vim.extension.VimExtensionFacade.setOperatorFunction
|
||||||
import com.maddyhome.idea.vim.extension.VimExtensionHandler
|
|
||||||
import com.maddyhome.idea.vim.group.visual.VimSelection
|
import com.maddyhome.idea.vim.group.visual.VimSelection
|
||||||
import com.maddyhome.idea.vim.helper.EditorDataContext
|
import com.maddyhome.idea.vim.helper.EditorDataContext
|
||||||
|
import com.maddyhome.idea.vim.helper.editorMode
|
||||||
import com.maddyhome.idea.vim.helper.mode
|
import com.maddyhome.idea.vim.helper.mode
|
||||||
import com.maddyhome.idea.vim.helper.subMode
|
import com.maddyhome.idea.vim.helper.subMode
|
||||||
|
import com.maddyhome.idea.vim.helper.vimStateMachine
|
||||||
import com.maddyhome.idea.vim.key.OperatorFunction
|
import com.maddyhome.idea.vim.key.OperatorFunction
|
||||||
import com.maddyhome.idea.vim.newapi.IjExecutionContext
|
import com.maddyhome.idea.vim.newapi.IjExecutionContext
|
||||||
import com.maddyhome.idea.vim.newapi.IjVimEditor
|
import com.maddyhome.idea.vim.newapi.IjVimEditor
|
||||||
@@ -63,22 +66,21 @@ class ReplaceWithRegister : VimExtension {
|
|||||||
putKeyMappingIfMissing(MappingMode.X, injector.parser.parseKeys("gr"), owner, injector.parser.parseKeys(RWR_VISUAL), true)
|
putKeyMappingIfMissing(MappingMode.X, injector.parser.parseKeys("gr"), owner, injector.parser.parseKeys(RWR_VISUAL), true)
|
||||||
}
|
}
|
||||||
|
|
||||||
private class RwrVisual : VimExtensionHandler {
|
private class RwrVisual : ExtensionHandler {
|
||||||
override fun execute(editor: VimEditor, context: ExecutionContext) {
|
override fun execute(editor: VimEditor, context: ExecutionContext) {
|
||||||
val caretsAndSelections = mutableMapOf<VimCaret, VimSelection>()
|
|
||||||
val typeInEditor = SelectionType.fromSubMode(editor.subMode)
|
val typeInEditor = SelectionType.fromSubMode(editor.subMode)
|
||||||
editor.forEachCaret { caret ->
|
editor.forEachCaret { caret ->
|
||||||
val selectionStart = caret.selectionStart
|
val selectionStart = caret.selectionStart
|
||||||
val selectionEnd = caret.selectionEnd
|
val selectionEnd = caret.selectionEnd
|
||||||
|
|
||||||
caretsAndSelections += caret to VimSelection.create(selectionStart, selectionEnd - 1, typeInEditor, editor)
|
val visualSelection = caret to VimSelection.create(selectionStart, selectionEnd - 1, typeInEditor, editor)
|
||||||
|
doReplace(editor.ij, caret, PutData.VisualSelection(mapOf(visualSelection), typeInEditor))
|
||||||
}
|
}
|
||||||
doReplace(editor.ij, PutData.VisualSelection(caretsAndSelections, typeInEditor))
|
|
||||||
editor.exitVisualModeNative()
|
editor.exitVisualModeNative()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class RwrMotion : VimExtensionHandler {
|
private class RwrMotion : ExtensionHandler {
|
||||||
override val isRepeatable: Boolean = true
|
override val isRepeatable: Boolean = true
|
||||||
|
|
||||||
override fun execute(editor: VimEditor, context: ExecutionContext) {
|
override fun execute(editor: VimEditor, context: ExecutionContext) {
|
||||||
@@ -87,7 +89,7 @@ class ReplaceWithRegister : VimExtension {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class RwrLine : VimExtensionHandler {
|
private class RwrLine : ExtensionHandler {
|
||||||
override val isRepeatable: Boolean = true
|
override val isRepeatable: Boolean = true
|
||||||
|
|
||||||
override fun execute(editor: VimEditor, context: ExecutionContext) {
|
override fun execute(editor: VimEditor, context: ExecutionContext) {
|
||||||
@@ -97,11 +99,11 @@ class ReplaceWithRegister : VimExtension {
|
|||||||
val lineStart = editor.getLineStartOffset(logicalLine)
|
val lineStart = editor.getLineStartOffset(logicalLine)
|
||||||
val lineEnd = editor.getLineEndOffset(logicalLine, true)
|
val lineEnd = editor.getLineEndOffset(logicalLine, true)
|
||||||
|
|
||||||
caretsAndSelections += caret to VimSelection.create(lineStart, lineEnd, SelectionType.LINE_WISE, editor)
|
val visualSelection = caret to VimSelection.create(lineStart, lineEnd, SelectionType.LINE_WISE, editor)
|
||||||
}
|
caretsAndSelections += visualSelection
|
||||||
|
|
||||||
val visualSelection = PutData.VisualSelection(caretsAndSelections, SelectionType.LINE_WISE)
|
doReplace(editor.ij, caret, PutData.VisualSelection(mapOf(visualSelection), SelectionType.LINE_WISE))
|
||||||
doReplace(editor.ij, visualSelection)
|
}
|
||||||
|
|
||||||
editor.forEachCaret { caret ->
|
editor.forEachCaret { caret ->
|
||||||
val vimStart = caretsAndSelections[caret]?.vimStart
|
val vimStart = caretsAndSelections[caret]?.vimStart
|
||||||
@@ -126,13 +128,14 @@ class ReplaceWithRegister : VimExtension {
|
|||||||
),
|
),
|
||||||
selectionType
|
selectionType
|
||||||
)
|
)
|
||||||
doReplace(editor, visualSelection)
|
// todo multicaret
|
||||||
|
doReplace(editor, editor.vim.primaryCaret(), visualSelection)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getRange(editor: Editor): TextRange? = when (editor.vim.mode) {
|
private fun getRange(editor: Editor): TextRange? = when (editor.vim.mode) {
|
||||||
CommandState.Mode.COMMAND -> VimPlugin.getMark().getChangeMarks(editor.vim)
|
VimStateMachine.Mode.COMMAND -> VimPlugin.getMark().getChangeMarks(editor.vim)
|
||||||
CommandState.Mode.VISUAL -> editor.caretModel.primaryCaret.run { TextRange(selectionStart, selectionEnd) }
|
VimStateMachine.Mode.VISUAL -> editor.caretModel.primaryCaret.run { TextRange(selectionStart, selectionEnd) }
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -147,8 +150,9 @@ class ReplaceWithRegister : VimExtension {
|
|||||||
@NonNls
|
@NonNls
|
||||||
private const val RWR_VISUAL = "<Plug>ReplaceWithRegisterVisual"
|
private const val RWR_VISUAL = "<Plug>ReplaceWithRegisterVisual"
|
||||||
|
|
||||||
private fun doReplace(editor: Editor, visualSelection: PutData.VisualSelection) {
|
private fun doReplace(editor: Editor, caret: VimCaret, visualSelection: PutData.VisualSelection) {
|
||||||
val savedRegister = VimPlugin.getRegister().lastRegister ?: return
|
val lastRegisterChar = injector.registerGroup.lastRegisterChar
|
||||||
|
val savedRegister = caret.registerStorage.getRegister(lastRegisterChar) ?: return
|
||||||
|
|
||||||
var usedType = savedRegister.type
|
var usedType = savedRegister.type
|
||||||
var usedText = savedRegister.text
|
var usedText = savedRegister.text
|
||||||
@@ -170,11 +174,19 @@ class ReplaceWithRegister : VimExtension {
|
|||||||
putToLine = -1
|
putToLine = -1
|
||||||
)
|
)
|
||||||
ClipboardOptionHelper.IdeaputDisabler().use {
|
ClipboardOptionHelper.IdeaputDisabler().use {
|
||||||
VimPlugin.getPut().putText(IjVimEditor(editor), IjExecutionContext(EditorDataContext.init(editor)), putData)
|
VimPlugin.getPut().putText(
|
||||||
|
IjVimEditor(editor),
|
||||||
|
IjExecutionContext(EditorDataContext.init(editor)),
|
||||||
|
putData,
|
||||||
|
operatorArguments = OperatorArguments(
|
||||||
|
editor.vimStateMachine?.isOperatorPending ?: false,
|
||||||
|
0, editor.editorMode, editor.subMode
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
VimPlugin.getRegister().saveRegister(savedRegister.name, savedRegister)
|
caret.registerStorage.saveRegister(savedRegister.name, savedRegister)
|
||||||
VimPlugin.getRegister().saveRegister(VimPlugin.getRegister().defaultRegister, savedRegister)
|
caret.registerStorage.saveRegister(VimPlugin.getRegister().defaultRegister, savedRegister)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -22,30 +22,31 @@ import com.intellij.openapi.application.runWriteAction
|
|||||||
import com.intellij.openapi.editor.Editor
|
import com.intellij.openapi.editor.Editor
|
||||||
import com.maddyhome.idea.vim.VimPlugin
|
import com.maddyhome.idea.vim.VimPlugin
|
||||||
import com.maddyhome.idea.vim.api.ExecutionContext
|
import com.maddyhome.idea.vim.api.ExecutionContext
|
||||||
|
import com.maddyhome.idea.vim.api.VimCaret
|
||||||
import com.maddyhome.idea.vim.api.VimEditor
|
import com.maddyhome.idea.vim.api.VimEditor
|
||||||
import com.maddyhome.idea.vim.api.injector
|
import com.maddyhome.idea.vim.api.injector
|
||||||
import com.maddyhome.idea.vim.command.CommandState
|
import com.maddyhome.idea.vim.command.MappingMode
|
||||||
import com.maddyhome.idea.vim.command.SelectionType
|
import com.maddyhome.idea.vim.command.SelectionType
|
||||||
import com.maddyhome.idea.vim.common.MappingMode
|
import com.maddyhome.idea.vim.command.VimStateMachine
|
||||||
import com.maddyhome.idea.vim.common.TextRange
|
import com.maddyhome.idea.vim.common.TextRange
|
||||||
|
import com.maddyhome.idea.vim.extension.ExtensionHandler
|
||||||
import com.maddyhome.idea.vim.extension.VimExtension
|
import com.maddyhome.idea.vim.extension.VimExtension
|
||||||
import com.maddyhome.idea.vim.extension.VimExtensionFacade.executeNormalWithoutMapping
|
import com.maddyhome.idea.vim.extension.VimExtensionFacade.executeNormalWithoutMapping
|
||||||
import com.maddyhome.idea.vim.extension.VimExtensionFacade.getRegister
|
import com.maddyhome.idea.vim.extension.VimExtensionFacade.getRegisterForCaret
|
||||||
import com.maddyhome.idea.vim.extension.VimExtensionFacade.inputKeyStroke
|
import com.maddyhome.idea.vim.extension.VimExtensionFacade.inputKeyStroke
|
||||||
import com.maddyhome.idea.vim.extension.VimExtensionFacade.inputString
|
import com.maddyhome.idea.vim.extension.VimExtensionFacade.inputString
|
||||||
import com.maddyhome.idea.vim.extension.VimExtensionFacade.putExtensionHandlerMapping
|
import com.maddyhome.idea.vim.extension.VimExtensionFacade.putExtensionHandlerMapping
|
||||||
import com.maddyhome.idea.vim.extension.VimExtensionFacade.putKeyMappingIfMissing
|
import com.maddyhome.idea.vim.extension.VimExtensionFacade.putKeyMappingIfMissing
|
||||||
import com.maddyhome.idea.vim.extension.VimExtensionFacade.setOperatorFunction
|
import com.maddyhome.idea.vim.extension.VimExtensionFacade.setOperatorFunction
|
||||||
import com.maddyhome.idea.vim.extension.VimExtensionFacade.setRegister
|
import com.maddyhome.idea.vim.extension.VimExtensionFacade.setRegisterForCaret
|
||||||
import com.maddyhome.idea.vim.extension.VimExtensionHandler
|
import com.maddyhome.idea.vim.helper.editorMode
|
||||||
import com.maddyhome.idea.vim.helper.EditorHelper
|
|
||||||
import com.maddyhome.idea.vim.helper.mode
|
|
||||||
import com.maddyhome.idea.vim.key.OperatorFunction
|
import com.maddyhome.idea.vim.key.OperatorFunction
|
||||||
import com.maddyhome.idea.vim.newapi.IjVimCaret
|
import com.maddyhome.idea.vim.newapi.IjVimCaret
|
||||||
import com.maddyhome.idea.vim.newapi.IjVimEditor
|
import com.maddyhome.idea.vim.newapi.IjVimEditor
|
||||||
import com.maddyhome.idea.vim.newapi.ij
|
import com.maddyhome.idea.vim.newapi.ij
|
||||||
import com.maddyhome.idea.vim.newapi.vim
|
import com.maddyhome.idea.vim.newapi.vim
|
||||||
import com.maddyhome.idea.vim.options.helpers.ClipboardOptionHelper
|
import com.maddyhome.idea.vim.options.helpers.ClipboardOptionHelper
|
||||||
|
import com.maddyhome.idea.vim.put.PutData
|
||||||
import org.jetbrains.annotations.NonNls
|
import org.jetbrains.annotations.NonNls
|
||||||
import java.awt.event.KeyEvent
|
import java.awt.event.KeyEvent
|
||||||
import javax.swing.KeyStroke
|
import javax.swing.KeyStroke
|
||||||
@@ -80,7 +81,7 @@ class VimSurroundExtension : VimExtension {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class YSurroundHandler : VimExtensionHandler {
|
private class YSurroundHandler : ExtensionHandler {
|
||||||
override val isRepeatable = true
|
override val isRepeatable = true
|
||||||
|
|
||||||
override fun execute(editor: VimEditor, context: ExecutionContext) {
|
override fun execute(editor: VimEditor, context: ExecutionContext) {
|
||||||
@@ -89,7 +90,7 @@ class VimSurroundExtension : VimExtension {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class VSurroundHandler : VimExtensionHandler {
|
private class VSurroundHandler : ExtensionHandler {
|
||||||
override fun execute(editor: VimEditor, context: ExecutionContext) {
|
override fun execute(editor: VimEditor, context: ExecutionContext) {
|
||||||
val selectionStart = editor.ij.caretModel.primaryCaret.selectionStart
|
val selectionStart = editor.ij.caretModel.primaryCaret.selectionStart
|
||||||
// NB: Operator ignores SelectionType anyway
|
// NB: Operator ignores SelectionType anyway
|
||||||
@@ -104,7 +105,7 @@ class VimSurroundExtension : VimExtension {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class CSurroundHandler : VimExtensionHandler {
|
private class CSurroundHandler : ExtensionHandler {
|
||||||
override val isRepeatable = true
|
override val isRepeatable = true
|
||||||
|
|
||||||
override fun execute(editor: VimEditor, context: ExecutionContext) {
|
override fun execute(editor: VimEditor, context: ExecutionContext) {
|
||||||
@@ -115,28 +116,70 @@ class VimSurroundExtension : VimExtension {
|
|||||||
if (charTo.code == 0) return
|
if (charTo.code == 0) return
|
||||||
|
|
||||||
val newSurround = getOrInputPair(charTo, editor.ij) ?: return
|
val newSurround = getOrInputPair(charTo, editor.ij) ?: return
|
||||||
runWriteAction { change(editor.ij, charFrom, newSurround) }
|
runWriteAction { change(editor, context, charFrom, newSurround) }
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun change(editor: Editor, charFrom: Char, newSurround: Pair<String, String>?) {
|
fun change(editor: VimEditor, context: ExecutionContext, charFrom: Char, newSurround: Pair<String, String>?) {
|
||||||
// We take over the " register, so preserve it
|
// Save old register values for carets
|
||||||
val oldValue: List<KeyStroke>? = getRegister(REGISTER)
|
val surroundings = editor.sortedCarets()
|
||||||
// Extract the inner value
|
.map {
|
||||||
perform("di" + pick(charFrom), editor)
|
val oldValue: List<KeyStroke>? = getRegisterForCaret(REGISTER, it)
|
||||||
val innerValue: MutableList<KeyStroke> = getRegister(REGISTER)?.toMutableList() ?: mutableListOf()
|
setRegisterForCaret(REGISTER, it, null)
|
||||||
// Delete the surrounding
|
SurroundingInfo(it, null, oldValue, null)
|
||||||
perform("da" + pick(charFrom), editor)
|
}
|
||||||
// Insert the surrounding characters and paste
|
|
||||||
if (newSurround != null) {
|
// Delete surrounding's content
|
||||||
innerValue.addAll(0, injector.parser.parseKeys(newSurround.first))
|
perform("di" + pick(charFrom), editor.ij)
|
||||||
innerValue.addAll(injector.parser.parseKeys(newSurround.second))
|
|
||||||
|
// Add info about surrounding's inner text and location
|
||||||
|
surroundings.forEach {
|
||||||
|
val registerValue = getRegisterForCaret(REGISTER, it.caret)
|
||||||
|
val innerValue = if (registerValue.isNullOrEmpty()) null else registerValue
|
||||||
|
it.innerText = innerValue
|
||||||
|
|
||||||
|
val lineEndOffset = injector.engineEditorHelper.getLineEndOffset(editor, it.caret.getLine().line, false)
|
||||||
|
if (lineEndOffset == it.caret.offset.point) {
|
||||||
|
it.isLineEnd = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove surrounding
|
||||||
|
perform("da" + pick(charFrom), editor.ij)
|
||||||
|
|
||||||
|
surroundings.forEach {
|
||||||
|
if (it.innerText == null && getRegisterForCaret(REGISTER, it.caret)?.isNotEmpty() == true) {
|
||||||
|
it.innerText = emptyList()
|
||||||
|
}
|
||||||
|
|
||||||
|
// caret should be placed at the first char of inserted text
|
||||||
|
// the best solution would be using [ mark after the paste, but marks are not supported by multicaret
|
||||||
|
// todo
|
||||||
|
if (it.innerText != null) {
|
||||||
|
it.offset = it.caret.offset.point
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
surroundings
|
||||||
|
.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 { it.first + innerValue + it.second } ?: innerValue
|
||||||
|
val textData = PutData.TextData(text, SelectionType.CHARACTER_WISE, emptyList())
|
||||||
|
val putData = PutData(textData, null, 1, insertTextBeforeCaret = !surrounding.isLineEnd, rawIndent = true, caretAfterInsertedText = false)
|
||||||
|
|
||||||
|
surrounding.caret to putData
|
||||||
|
}.forEach {
|
||||||
|
injector.put.putTextForCaret(editor, it.first, context, it.second)
|
||||||
|
}
|
||||||
|
|
||||||
|
surroundings.forEach {
|
||||||
|
it.restoreRegister()
|
||||||
|
}
|
||||||
|
|
||||||
|
if (surroundings.size == 1) {
|
||||||
|
surroundings.first().moveCaret()
|
||||||
}
|
}
|
||||||
pasteSurround(innerValue, editor)
|
|
||||||
// Restore the old value
|
|
||||||
setRegister(REGISTER, oldValue)
|
|
||||||
// Jump back to start
|
|
||||||
executeNormalWithoutMapping(injector.parser.parseKeys("`["), editor)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun perform(sequence: String, editor: Editor) {
|
private fun perform(sequence: String, editor: Editor) {
|
||||||
@@ -144,21 +187,6 @@ class VimSurroundExtension : VimExtension {
|
|||||||
.use { executeNormalWithoutMapping(injector.parser.parseKeys("\"" + REGISTER + sequence), editor) }
|
.use { executeNormalWithoutMapping(injector.parser.parseKeys("\"" + REGISTER + sequence), editor) }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun pasteSurround(
|
|
||||||
innerValue: List<KeyStroke?>,
|
|
||||||
editor: Editor,
|
|
||||||
) { // This logic is direct from vim-surround
|
|
||||||
val offset = editor.caretModel.offset
|
|
||||||
val lineEndOffset = EditorHelper.getLineEndForOffset(editor, offset)
|
|
||||||
val motionEndMark = VimPlugin.getMark().getMark(editor.vim, ']')
|
|
||||||
val motionEndOffset = if (motionEndMark != null) {
|
|
||||||
EditorHelper.getOffset(editor, motionEndMark.logicalLine, motionEndMark.col)
|
|
||||||
} else -1
|
|
||||||
val pasteCommand = if (motionEndOffset == lineEndOffset && offset + 1 == lineEndOffset) "p" else "P"
|
|
||||||
setRegister(REGISTER, innerValue)
|
|
||||||
perform(pasteCommand, editor)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun pick(charFrom: Char) = when (charFrom) {
|
private fun pick(charFrom: Char) = when (charFrom) {
|
||||||
'a' -> '>'
|
'a' -> '>'
|
||||||
'r' -> ']'
|
'r' -> ']'
|
||||||
@@ -167,7 +195,19 @@ class VimSurroundExtension : VimExtension {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class DSurroundHandler : VimExtensionHandler {
|
private data class SurroundingInfo(val caret: VimCaret, var innerText: List<KeyStroke>?, val oldRegisterContent: List<KeyStroke>?, var offset: Int?, var isLineEnd: Boolean = false) {
|
||||||
|
fun restoreRegister() {
|
||||||
|
setRegisterForCaret(REGISTER, caret, oldRegisterContent)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun moveCaret() {
|
||||||
|
if (innerText != null && offset != null) {
|
||||||
|
caret.moveToOffset(offset!! + if (isLineEnd) 1 else 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class DSurroundHandler : ExtensionHandler {
|
||||||
override val isRepeatable = true
|
override val isRepeatable = true
|
||||||
|
|
||||||
override fun execute(editor: VimEditor, context: ExecutionContext) {
|
override fun execute(editor: VimEditor, context: ExecutionContext) {
|
||||||
@@ -175,7 +215,7 @@ class VimSurroundExtension : VimExtension {
|
|||||||
val charFrom = getChar(editor.ij)
|
val charFrom = getChar(editor.ij)
|
||||||
if (charFrom.code == 0) return
|
if (charFrom.code == 0) return
|
||||||
|
|
||||||
runWriteAction { CSurroundHandler.change(editor.ij, charFrom, null) }
|
runWriteAction { CSurroundHandler.change(editor, context, charFrom, null) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -199,9 +239,9 @@ class VimSurroundExtension : VimExtension {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getSurroundRange(editor: Editor): TextRange? = when (editor.mode) {
|
private fun getSurroundRange(editor: Editor): TextRange? = when (editor.editorMode) {
|
||||||
CommandState.Mode.COMMAND -> VimPlugin.getMark().getChangeMarks(editor.vim)
|
VimStateMachine.Mode.COMMAND -> VimPlugin.getMark().getChangeMarks(editor.vim)
|
||||||
CommandState.Mode.VISUAL -> editor.caretModel.primaryCaret.run { TextRange(selectionStart, selectionEnd) }
|
VimStateMachine.Mode.VISUAL -> editor.caretModel.primaryCaret.run { TextRange(selectionStart, selectionEnd) }
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -18,26 +18,22 @@
|
|||||||
|
|
||||||
package com.maddyhome.idea.vim.extension.textobjentire;
|
package com.maddyhome.idea.vim.extension.textobjentire;
|
||||||
|
|
||||||
import com.intellij.openapi.actionSystem.DataContext;
|
|
||||||
import com.intellij.openapi.editor.Caret;
|
import com.intellij.openapi.editor.Caret;
|
||||||
import com.intellij.openapi.editor.Editor;
|
|
||||||
import com.maddyhome.idea.vim.api.ExecutionContext;
|
import com.maddyhome.idea.vim.api.ExecutionContext;
|
||||||
import com.maddyhome.idea.vim.api.VimCaret;
|
import com.maddyhome.idea.vim.api.VimCaret;
|
||||||
import com.maddyhome.idea.vim.api.VimEditor;
|
import com.maddyhome.idea.vim.api.VimEditor;
|
||||||
import com.maddyhome.idea.vim.api.VimInjectorKt;
|
import com.maddyhome.idea.vim.api.VimInjectorKt;
|
||||||
import com.maddyhome.idea.vim.command.*;
|
import com.maddyhome.idea.vim.command.*;
|
||||||
import com.maddyhome.idea.vim.common.MappingMode;
|
import com.maddyhome.idea.vim.command.MappingMode;
|
||||||
import com.maddyhome.idea.vim.common.TextRange;
|
import com.maddyhome.idea.vim.common.TextRange;
|
||||||
import com.maddyhome.idea.vim.extension.VimExtension;
|
import com.maddyhome.idea.vim.extension.VimExtension;
|
||||||
import com.maddyhome.idea.vim.extension.VimExtensionHandler;
|
import com.maddyhome.idea.vim.extension.ExtensionHandler;
|
||||||
import com.maddyhome.idea.vim.handler.TextObjectActionHandler;
|
import com.maddyhome.idea.vim.handler.TextObjectActionHandler;
|
||||||
import com.maddyhome.idea.vim.helper.InlayHelperKt;
|
import com.maddyhome.idea.vim.helper.InlayHelperKt;
|
||||||
import com.maddyhome.idea.vim.listener.SelectionVimListenerSuppressor;
|
import com.maddyhome.idea.vim.listener.SelectionVimListenerSuppressor;
|
||||||
import com.maddyhome.idea.vim.listener.VimListenerSuppressor;
|
import com.maddyhome.idea.vim.listener.VimListenerSuppressor;
|
||||||
import com.maddyhome.idea.vim.newapi.IjExecutionContext;
|
|
||||||
import com.maddyhome.idea.vim.newapi.IjVimCaret;
|
import com.maddyhome.idea.vim.newapi.IjVimCaret;
|
||||||
import com.maddyhome.idea.vim.newapi.IjVimEditor;
|
import com.maddyhome.idea.vim.newapi.IjVimEditor;
|
||||||
import org.apache.tools.ant.taskdefs.Exec;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
@@ -88,7 +84,7 @@ public class VimTextObjEntireExtension implements VimExtension {
|
|||||||
putKeyMappingIfMissing(MappingMode.XO, VimInjectorKt.getInjector().getParser().parseKeys("ie"), getOwner(), VimInjectorKt.getInjector().getParser().parseKeys("<Plug>textobj-entire-i"), true);
|
putKeyMappingIfMissing(MappingMode.XO, VimInjectorKt.getInjector().getParser().parseKeys("ie"), getOwner(), VimInjectorKt.getInjector().getParser().parseKeys("<Plug>textobj-entire-i"), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static class EntireHandler implements VimExtensionHandler {
|
static class EntireHandler implements ExtensionHandler {
|
||||||
final boolean ignoreLeadingAndTrailing;
|
final boolean ignoreLeadingAndTrailing;
|
||||||
|
|
||||||
EntireHandler(boolean ignoreLeadingAndTrailing) {
|
EntireHandler(boolean ignoreLeadingAndTrailing) {
|
||||||
@@ -148,17 +144,17 @@ public class VimTextObjEntireExtension implements VimExtension {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void execute(@NotNull VimEditor editor, @NotNull ExecutionContext context) {
|
public void execute(@NotNull VimEditor editor, @NotNull ExecutionContext context) {
|
||||||
@NotNull CommandState commandState = CommandState.getInstance(editor);
|
@NotNull VimStateMachine vimStateMachine = VimStateMachine.getInstance(editor);
|
||||||
int count = Math.max(1, commandState.getCommandBuilder().getCount());
|
int count = Math.max(1, vimStateMachine.getCommandBuilder().getCount());
|
||||||
|
|
||||||
final EntireTextObjectHandler textObjectHandler = new EntireTextObjectHandler(ignoreLeadingAndTrailing);
|
final EntireTextObjectHandler textObjectHandler = new EntireTextObjectHandler(ignoreLeadingAndTrailing);
|
||||||
//noinspection DuplicatedCode
|
//noinspection DuplicatedCode
|
||||||
if (!commandState.isOperatorPending()) {
|
if (!vimStateMachine.isOperatorPending()) {
|
||||||
((IjVimEditor) editor).getEditor().getCaretModel().runForEachCaret((Caret caret) -> {
|
((IjVimEditor) editor).getEditor().getCaretModel().runForEachCaret((Caret caret) -> {
|
||||||
final TextRange range = textObjectHandler.getRange(editor, new IjVimCaret(caret), context, count, 0, null);
|
final TextRange range = textObjectHandler.getRange(editor, new IjVimCaret(caret), context, count, 0, null);
|
||||||
if (range != null) {
|
if (range != null) {
|
||||||
try (VimListenerSuppressor.Locked ignored = SelectionVimListenerSuppressor.INSTANCE.lock()) {
|
try (VimListenerSuppressor.Locked ignored = SelectionVimListenerSuppressor.INSTANCE.lock()) {
|
||||||
if (commandState.getMode() == CommandState.Mode.VISUAL) {
|
if (vimStateMachine.getMode() == VimStateMachine.Mode.VISUAL) {
|
||||||
vimSetSelection(caret, range.getStartOffset(), range.getEndOffset() - 1, true);
|
vimSetSelection(caret, range.getStartOffset(), range.getEndOffset() - 1, true);
|
||||||
} else {
|
} else {
|
||||||
InlayHelperKt.moveToInlayAwareOffset(caret, range.getStartOffset());
|
InlayHelperKt.moveToInlayAwareOffset(caret, range.getStartOffset());
|
||||||
@@ -168,7 +164,7 @@ public class VimTextObjEntireExtension implements VimExtension {
|
|||||||
|
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
commandState.getCommandBuilder().completeCommandPart(new Argument(new Command(count,
|
vimStateMachine.getCommandBuilder().completeCommandPart(new Argument(new Command(count,
|
||||||
textObjectHandler, Command.Type.MOTION,
|
textObjectHandler, Command.Type.MOTION,
|
||||||
EnumSet.noneOf(CommandFlags.class))));
|
EnumSet.noneOf(CommandFlags.class))));
|
||||||
}
|
}
|
||||||
|
@@ -18,23 +18,20 @@
|
|||||||
|
|
||||||
package com.maddyhome.idea.vim.extension.textobjindent;
|
package com.maddyhome.idea.vim.extension.textobjindent;
|
||||||
|
|
||||||
import com.intellij.openapi.actionSystem.DataContext;
|
|
||||||
import com.intellij.openapi.editor.Caret;
|
import com.intellij.openapi.editor.Caret;
|
||||||
import com.intellij.openapi.editor.Editor;
|
|
||||||
import com.maddyhome.idea.vim.api.ExecutionContext;
|
import com.maddyhome.idea.vim.api.ExecutionContext;
|
||||||
import com.maddyhome.idea.vim.api.VimCaret;
|
import com.maddyhome.idea.vim.api.VimCaret;
|
||||||
import com.maddyhome.idea.vim.api.VimEditor;
|
import com.maddyhome.idea.vim.api.VimEditor;
|
||||||
import com.maddyhome.idea.vim.api.VimInjectorKt;
|
import com.maddyhome.idea.vim.api.VimInjectorKt;
|
||||||
import com.maddyhome.idea.vim.command.*;
|
import com.maddyhome.idea.vim.command.*;
|
||||||
import com.maddyhome.idea.vim.common.MappingMode;
|
import com.maddyhome.idea.vim.command.MappingMode;
|
||||||
import com.maddyhome.idea.vim.common.TextRange;
|
import com.maddyhome.idea.vim.common.TextRange;
|
||||||
import com.maddyhome.idea.vim.extension.VimExtension;
|
import com.maddyhome.idea.vim.extension.VimExtension;
|
||||||
import com.maddyhome.idea.vim.extension.VimExtensionHandler;
|
import com.maddyhome.idea.vim.extension.ExtensionHandler;
|
||||||
import com.maddyhome.idea.vim.handler.TextObjectActionHandler;
|
import com.maddyhome.idea.vim.handler.TextObjectActionHandler;
|
||||||
import com.maddyhome.idea.vim.helper.InlayHelperKt;
|
import com.maddyhome.idea.vim.helper.InlayHelperKt;
|
||||||
import com.maddyhome.idea.vim.listener.SelectionVimListenerSuppressor;
|
import com.maddyhome.idea.vim.listener.SelectionVimListenerSuppressor;
|
||||||
import com.maddyhome.idea.vim.listener.VimListenerSuppressor;
|
import com.maddyhome.idea.vim.listener.VimListenerSuppressor;
|
||||||
import com.maddyhome.idea.vim.newapi.IjExecutionContext;
|
|
||||||
import com.maddyhome.idea.vim.newapi.IjVimCaret;
|
import com.maddyhome.idea.vim.newapi.IjVimCaret;
|
||||||
import com.maddyhome.idea.vim.newapi.IjVimEditor;
|
import com.maddyhome.idea.vim.newapi.IjVimEditor;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
@@ -86,7 +83,7 @@ public class VimIndentObject implements VimExtension {
|
|||||||
putKeyMapping(MappingMode.XO, VimInjectorKt.getInjector().getParser().parseKeys("ii"), getOwner(), VimInjectorKt.getInjector().getParser().parseKeys("<Plug>textobj-indent-ii"), true);
|
putKeyMapping(MappingMode.XO, VimInjectorKt.getInjector().getParser().parseKeys("ii"), getOwner(), VimInjectorKt.getInjector().getParser().parseKeys("<Plug>textobj-indent-ii"), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static class IndentObject implements VimExtensionHandler {
|
static class IndentObject implements ExtensionHandler {
|
||||||
final boolean includeAbove;
|
final boolean includeAbove;
|
||||||
final boolean includeBelow;
|
final boolean includeBelow;
|
||||||
|
|
||||||
@@ -275,17 +272,17 @@ public class VimIndentObject implements VimExtension {
|
|||||||
@Override
|
@Override
|
||||||
public void execute(@NotNull VimEditor editor, @NotNull ExecutionContext context) {
|
public void execute(@NotNull VimEditor editor, @NotNull ExecutionContext context) {
|
||||||
IjVimEditor vimEditor = (IjVimEditor)editor;
|
IjVimEditor vimEditor = (IjVimEditor)editor;
|
||||||
@NotNull CommandState commandState = CommandState.getInstance(vimEditor);
|
@NotNull VimStateMachine vimStateMachine = VimStateMachine.getInstance(vimEditor);
|
||||||
int count = Math.max(1, commandState.getCommandBuilder().getCount());
|
int count = Math.max(1, vimStateMachine.getCommandBuilder().getCount());
|
||||||
|
|
||||||
final IndentObjectHandler textObjectHandler = new IndentObjectHandler(includeAbove, includeBelow);
|
final IndentObjectHandler textObjectHandler = new IndentObjectHandler(includeAbove, includeBelow);
|
||||||
|
|
||||||
if (!commandState.isOperatorPending()) {
|
if (!vimStateMachine.isOperatorPending()) {
|
||||||
((IjVimEditor)editor).getEditor().getCaretModel().runForEachCaret((Caret caret) -> {
|
((IjVimEditor)editor).getEditor().getCaretModel().runForEachCaret((Caret caret) -> {
|
||||||
final TextRange range = textObjectHandler.getRange(vimEditor, new IjVimCaret(caret), context, count, 0, null);
|
final TextRange range = textObjectHandler.getRange(vimEditor, new IjVimCaret(caret), context, count, 0, null);
|
||||||
if (range != null) {
|
if (range != null) {
|
||||||
try (VimListenerSuppressor.Locked ignored = SelectionVimListenerSuppressor.INSTANCE.lock()) {
|
try (VimListenerSuppressor.Locked ignored = SelectionVimListenerSuppressor.INSTANCE.lock()) {
|
||||||
if (commandState.getMode() == CommandState.Mode.VISUAL) {
|
if (vimStateMachine.getMode() == VimStateMachine.Mode.VISUAL) {
|
||||||
vimSetSelection(caret, range.getStartOffset(), range.getEndOffset() - 1, true);
|
vimSetSelection(caret, range.getStartOffset(), range.getEndOffset() - 1, true);
|
||||||
} else {
|
} else {
|
||||||
InlayHelperKt.moveToInlayAwareOffset(caret, range.getStartOffset());
|
InlayHelperKt.moveToInlayAwareOffset(caret, range.getStartOffset());
|
||||||
@@ -295,7 +292,7 @@ public class VimIndentObject implements VimExtension {
|
|||||||
|
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
commandState.getCommandBuilder().completeCommandPart(new Argument(new Command(count,
|
vimStateMachine.getCommandBuilder().completeCommandPart(new Argument(new Command(count,
|
||||||
textObjectHandler, Command.Type.MOTION,
|
textObjectHandler, Command.Type.MOTION,
|
||||||
EnumSet.noneOf(CommandFlags.class))));
|
EnumSet.noneOf(CommandFlags.class))));
|
||||||
}
|
}
|
||||||
|
@@ -39,7 +39,6 @@ import com.intellij.psi.codeStyle.CodeStyleManager;
|
|||||||
import com.intellij.psi.util.PsiUtilBase;
|
import com.intellij.psi.util.PsiUtilBase;
|
||||||
import com.intellij.util.containers.ContainerUtil;
|
import com.intellij.util.containers.ContainerUtil;
|
||||||
import com.maddyhome.idea.vim.EventFacade;
|
import com.maddyhome.idea.vim.EventFacade;
|
||||||
import com.maddyhome.idea.vim.RegisterActions;
|
|
||||||
import com.maddyhome.idea.vim.VimPlugin;
|
import com.maddyhome.idea.vim.VimPlugin;
|
||||||
import com.maddyhome.idea.vim.api.*;
|
import com.maddyhome.idea.vim.api.*;
|
||||||
import com.maddyhome.idea.vim.command.*;
|
import com.maddyhome.idea.vim.command.*;
|
||||||
@@ -107,7 +106,7 @@ public class ChangeGroup extends VimChangeGroupBase {
|
|||||||
injector.getMotion().moveCaret(editor, caret, VimPlugin.getMotion().moveCaretToLineEnd(editor, caret));
|
injector.getMotion().moveCaret(editor, caret, VimPlugin.getMotion().moveCaretToLineEnd(editor, caret));
|
||||||
}
|
}
|
||||||
|
|
||||||
UserDataManager.setVimChangeActionSwitchMode(((IjVimEditor) editor).getEditor(), CommandState.Mode.INSERT);
|
UserDataManager.setVimChangeActionSwitchMode(((IjVimEditor) editor).getEditor(), VimStateMachine.Mode.INSERT);
|
||||||
insertText(editor, caret, "\n" + IndentConfig.create(((IjVimEditor) editor).getEditor()).createIndentBySize(col));
|
insertText(editor, caret, "\n" + IndentConfig.create(((IjVimEditor) editor).getEditor()).createIndentBySize(col));
|
||||||
|
|
||||||
if (firstLiner) {
|
if (firstLiner) {
|
||||||
@@ -123,10 +122,10 @@ public class ChangeGroup extends VimChangeGroupBase {
|
|||||||
* @param col The column to indent to
|
* @param col The column to indent to
|
||||||
*/
|
*/
|
||||||
private void insertNewLineBelow(@NotNull VimEditor editor, @NotNull VimCaret caret, int col) {
|
private void insertNewLineBelow(@NotNull VimEditor editor, @NotNull VimCaret caret, int col) {
|
||||||
if (((IjVimEditor) editor).getEditor().isOneLineMode()) return;
|
if (editor.isOneLineMode()) return;
|
||||||
|
|
||||||
injector.getMotion().moveCaret(editor, caret, VimPlugin.getMotion().moveCaretToLineEnd(editor, caret));
|
caret.moveToOffset(injector.getMotion().moveCaretToLineEnd(editor, caret));
|
||||||
UserDataManager.setVimChangeActionSwitchMode(((IjVimEditor) editor).getEditor(), CommandState.Mode.INSERT);
|
editor.setVimChangeActionSwitchMode(VimStateMachine.Mode.INSERT);
|
||||||
insertText(editor, caret, "\n" + IndentConfig.create(((IjVimEditor) editor).getEditor()).createIndentBySize(col));
|
insertText(editor, caret, "\n" + IndentConfig.create(((IjVimEditor) editor).getEditor()).createIndentBySize(col));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -165,41 +164,6 @@ public class ChangeGroup extends VimChangeGroupBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @Nullable Pair<@NotNull TextRange, @NotNull SelectionType> getDeleteRangeAndType(@NotNull VimEditor editor,
|
|
||||||
@NotNull VimCaret caret,
|
|
||||||
@NotNull ExecutionContext context,
|
|
||||||
final @NotNull Argument argument,
|
|
||||||
boolean isChange,
|
|
||||||
@NotNull OperatorArguments operatorArguments) {
|
|
||||||
final TextRange range =
|
|
||||||
injector.getMotion().getMotionRange(editor, caret, context, argument, operatorArguments);
|
|
||||||
if (range == null) return null;
|
|
||||||
|
|
||||||
// Delete motion commands that are not linewise become linewise if all the following are true:
|
|
||||||
// 1) The range is across multiple lines
|
|
||||||
// 2) There is only whitespace before the start of the range
|
|
||||||
// 3) There is only whitespace after the end of the range
|
|
||||||
SelectionType type;
|
|
||||||
if (argument.getMotion().isLinewiseMotion()) {
|
|
||||||
type = SelectionType.LINE_WISE;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
type = SelectionType.CHARACTER_WISE;
|
|
||||||
}
|
|
||||||
final Command motion = argument.getMotion();
|
|
||||||
if (!isChange && !motion.isLinewiseMotion()) {
|
|
||||||
VimLogicalPosition start = editor.offsetToLogicalPosition(range.getStartOffset());
|
|
||||||
VimLogicalPosition end = editor.offsetToLogicalPosition(range.getEndOffset());
|
|
||||||
if (start.getLine() != end.getLine()) {
|
|
||||||
if (!SearchHelper.anyNonWhitespace(((IjVimEditor) editor).getEditor(), range.getStartOffset(), -1) &&
|
|
||||||
!SearchHelper.anyNonWhitespace(((IjVimEditor) editor).getEditor(), range.getEndOffset(), 1)) {
|
|
||||||
type = SelectionType.LINE_WISE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return new Pair<>(range, type);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @Nullable Pair<@NotNull TextRange, @NotNull SelectionType> getDeleteRangeAndType2(@NotNull VimEditor editor,
|
public @Nullable Pair<@NotNull TextRange, @NotNull SelectionType> getDeleteRangeAndType2(@NotNull VimEditor editor,
|
||||||
@@ -236,60 +200,6 @@ public class ChangeGroup extends VimChangeGroupBase {
|
|||||||
return new Pair<>(range, type);
|
return new Pair<>(range, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Delete the range of text.
|
|
||||||
*
|
|
||||||
* @param editor The editor to delete the text from
|
|
||||||
* @param caret The caret to be moved after deletion
|
|
||||||
* @param range The range to delete
|
|
||||||
* @param type The type of deletion
|
|
||||||
* @param isChange Is from a change action
|
|
||||||
* @return true if able to delete the text, false if not
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public boolean deleteRange(@NotNull VimEditor editor,
|
|
||||||
@NotNull VimCaret caret,
|
|
||||||
@NotNull TextRange range,
|
|
||||||
@Nullable SelectionType type,
|
|
||||||
boolean isChange) {
|
|
||||||
|
|
||||||
// Update the last column before we delete, or we might be retrieving the data for a line that no longer exists
|
|
||||||
UserDataManager.setVimLastColumn(((IjVimCaret) caret).getCaret(), InlayHelperKt.getInlayAwareVisualColumn(((IjVimCaret) caret).getCaret()));
|
|
||||||
|
|
||||||
boolean removeLastNewLine = removeLastNewLine(editor, range, type);
|
|
||||||
final boolean res = deleteText(editor, range, type);
|
|
||||||
if (removeLastNewLine) {
|
|
||||||
int textLength = ((IjVimEditor) editor).getEditor().getDocument().getTextLength();
|
|
||||||
((IjVimEditor) editor).getEditor().getDocument().deleteString(textLength - 1, textLength);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (res) {
|
|
||||||
int pos = EditorHelper.normalizeOffset(((IjVimEditor) editor).getEditor(), range.getStartOffset(), isChange);
|
|
||||||
if (type == SelectionType.LINE_WISE) {
|
|
||||||
pos = VimPlugin.getMotion()
|
|
||||||
.moveCaretToLineWithStartOfLineOption(editor, editor.offsetToLogicalPosition(pos).getLine(),
|
|
||||||
caret);
|
|
||||||
}
|
|
||||||
injector.getMotion().moveCaret(editor, caret, pos);
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean removeLastNewLine(@NotNull VimEditor editor, @NotNull TextRange range, @Nullable SelectionType type) {
|
|
||||||
int endOffset = range.getEndOffset();
|
|
||||||
int fileSize = EditorHelperRt.getFileSize(((IjVimEditor) editor).getEditor());
|
|
||||||
if (endOffset > fileSize) {
|
|
||||||
if (injector.getOptionService().isSet(OptionScope.GLOBAL.INSTANCE, OptionConstants.ideastrictmodeName, OptionConstants.ideastrictmodeName)) {
|
|
||||||
throw new IllegalStateException("Incorrect offset. File size: " + fileSize + ", offset: " + endOffset);
|
|
||||||
}
|
|
||||||
endOffset = fileSize;
|
|
||||||
}
|
|
||||||
return type == SelectionType.LINE_WISE &&
|
|
||||||
range.getStartOffset() != 0 &&
|
|
||||||
((IjVimEditor) editor).getEditor().getDocument().getCharsSequence().charAt(endOffset - 1) != '\n' &&
|
|
||||||
endOffset == fileSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void insertLineAround(@NotNull VimEditor editor, @NotNull ExecutionContext context, int shift) {
|
public void insertLineAround(@NotNull VimEditor editor, @NotNull ExecutionContext context, int shift) {
|
||||||
com.maddyhome.idea.vim.newapi.ChangeGroupKt.insertLineAround(editor, context, shift);
|
com.maddyhome.idea.vim.newapi.ChangeGroupKt.insertLineAround(editor, context, shift);
|
||||||
@@ -303,48 +213,6 @@ public class ChangeGroup extends VimChangeGroupBase {
|
|||||||
return com.maddyhome.idea.vim.newapi.ChangeGroupKt.deleteRange(editor, caret, range, type);
|
return com.maddyhome.idea.vim.newapi.ChangeGroupKt.deleteRange(editor, caret, range, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Delete count characters and then enter insert mode
|
|
||||||
*
|
|
||||||
* @param editor The editor to change
|
|
||||||
* @param caret The caret to be moved
|
|
||||||
* @param count The number of characters to change
|
|
||||||
* @return true if able to delete count characters, false if not
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public boolean changeCharacters(@NotNull VimEditor editor, @NotNull VimCaret caret, int count) {
|
|
||||||
int len = EditorHelper.getLineLength(((IjVimEditor) editor).getEditor());
|
|
||||||
int col = ((IjVimCaret) caret).getCaret().getLogicalPosition().column;
|
|
||||||
if (col + count >= len) {
|
|
||||||
return changeEndOfLine(editor, caret, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean res = deleteCharacter(editor, caret, count, true);
|
|
||||||
if (res) {
|
|
||||||
UserDataManager.setVimChangeActionSwitchMode(((IjVimEditor) editor).getEditor(), CommandState.Mode.INSERT);
|
|
||||||
}
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Delete from the cursor to the end of count - 1 lines down and enter insert mode
|
|
||||||
*
|
|
||||||
* @param editor The editor to change
|
|
||||||
* @param caret The caret to perform action on
|
|
||||||
* @param count The number of lines to change
|
|
||||||
* @return true if able to delete count lines, false if not
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public boolean changeEndOfLine(@NotNull VimEditor editor, @NotNull VimCaret caret, int count) {
|
|
||||||
boolean res = deleteEndOfLine(editor, caret, count);
|
|
||||||
if (res) {
|
|
||||||
injector.getMotion().moveCaret(editor, caret, VimPlugin.getMotion().moveCaretToLineEnd(editor, caret));
|
|
||||||
UserDataManager.setVimChangeActionSwitchMode(((IjVimEditor) editor).getEditor(), CommandState.Mode.INSERT);
|
|
||||||
}
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete the text covered by the motion command argument and enter insert mode
|
* Delete the text covered by the motion command argument and enter insert mode
|
||||||
@@ -368,35 +236,35 @@ public class ChangeGroup extends VimChangeGroupBase {
|
|||||||
String id = motion.getAction().getId();
|
String id = motion.getAction().getId();
|
||||||
boolean kludge = false;
|
boolean kludge = false;
|
||||||
boolean bigWord = id.equals(VIM_MOTION_BIG_WORD_RIGHT);
|
boolean bigWord = id.equals(VIM_MOTION_BIG_WORD_RIGHT);
|
||||||
final CharSequence chars = ((IjVimEditor) editor).getEditor().getDocument().getCharsSequence();
|
final CharSequence chars = editor.text();
|
||||||
final int offset = ((IjVimCaret) caret).getCaret().getOffset();
|
final int offset = caret.getOffset().getPoint();
|
||||||
int fileSize = EditorHelperRt.getFileSize(((IjVimEditor) editor).getEditor());
|
int fileSize = ((int)editor.fileSize());
|
||||||
if (fileSize > 0 && offset < fileSize) {
|
if (fileSize > 0 && offset < fileSize) {
|
||||||
final CharacterHelper.CharacterType charType = CharacterHelper.charType(chars.charAt(offset), bigWord);
|
final CharacterHelper.CharacterType charType = CharacterHelper.charType(chars.charAt(offset), bigWord);
|
||||||
if (charType != CharacterHelper.CharacterType.WHITESPACE) {
|
if (charType != CharacterHelper.CharacterType.WHITESPACE) {
|
||||||
final boolean lastWordChar =
|
final boolean lastWordChar =
|
||||||
offset >= fileSize - 1 || CharacterHelper.charType(chars.charAt(offset + 1), bigWord) != charType;
|
offset >= fileSize - 1 || CharacterHelper.charType(chars.charAt(offset + 1), bigWord) != charType;
|
||||||
if (wordMotions.contains(id) && lastWordChar && motion.getCount() == 1) {
|
if (wordMotions.contains(id) && lastWordChar && motion.getCount() == 1) {
|
||||||
final boolean res = deleteCharacter(editor, caret, 1, true);
|
final boolean res = deleteCharacter(editor, caret, 1, true, operatorArguments);
|
||||||
if (res) {
|
if (res) {
|
||||||
UserDataManager.setVimChangeActionSwitchMode(((IjVimEditor) editor).getEditor(), CommandState.Mode.INSERT);
|
editor.setVimChangeActionSwitchMode(VimStateMachine.Mode.INSERT);
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
switch (id) {
|
switch (id) {
|
||||||
case VIM_MOTION_WORD_RIGHT:
|
case VIM_MOTION_WORD_RIGHT:
|
||||||
kludge = true;
|
kludge = true;
|
||||||
motion.setAction(RegisterActions.findActionOrDie(VIM_MOTION_WORD_END_RIGHT));
|
motion.setAction(injector.getActionExecutor().findVimActionOrDie(VIM_MOTION_WORD_END_RIGHT));
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case VIM_MOTION_BIG_WORD_RIGHT:
|
case VIM_MOTION_BIG_WORD_RIGHT:
|
||||||
kludge = true;
|
kludge = true;
|
||||||
motion.setAction(RegisterActions.findActionOrDie(VIM_MOTION_BIG_WORD_END_RIGHT));
|
motion.setAction(injector.getActionExecutor().findVimActionOrDie(VIM_MOTION_BIG_WORD_END_RIGHT));
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case VIM_MOTION_CAMEL_RIGHT:
|
case VIM_MOTION_CAMEL_RIGHT:
|
||||||
kludge = true;
|
kludge = true;
|
||||||
motion.setAction(RegisterActions.findActionOrDie(VIM_MOTION_CAMEL_END_RIGHT));
|
motion.setAction(injector.getActionExecutor().findVimActionOrDie(VIM_MOTION_CAMEL_END_RIGHT));
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -405,8 +273,8 @@ public class ChangeGroup extends VimChangeGroupBase {
|
|||||||
|
|
||||||
if (kludge) {
|
if (kludge) {
|
||||||
int cnt = operatorArguments.getCount1() * motion.getCount();
|
int cnt = operatorArguments.getCount1() * motion.getCount();
|
||||||
int pos1 = SearchHelper.findNextWordEnd(chars, offset, fileSize, cnt, bigWord, false);
|
int pos1 = injector.getSearchHelper().findNextWordEnd(chars, offset, fileSize, cnt, bigWord, false);
|
||||||
int pos2 = SearchHelper.findNextWordEnd(chars, pos1, fileSize, -cnt, bigWord, false);
|
int pos2 = injector.getSearchHelper().findNextWordEnd(chars, pos1, fileSize, -cnt, bigWord, false);
|
||||||
if (logger.isDebugEnabled()) {
|
if (logger.isDebugEnabled()) {
|
||||||
logger.debug("pos=" + offset);
|
logger.debug("pos=" + offset);
|
||||||
logger.debug("pos1=" + pos1);
|
logger.debug("pos1=" + pos1);
|
||||||
@@ -427,38 +295,22 @@ public class ChangeGroup extends VimChangeGroupBase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (VimPlugin.getOptionService().isSet(OptionScope.GLOBAL.INSTANCE, OptionConstants.experimentalapiName, OptionConstants.experimentalapiName)) {
|
if (injector.getOptionService().isSet(OptionScope.GLOBAL.INSTANCE, OptionConstants.experimentalapiName, OptionConstants.experimentalapiName)) {
|
||||||
Pair<TextRange, SelectionType> deleteRangeAndType =
|
Pair<TextRange, SelectionType> deleteRangeAndType =
|
||||||
getDeleteRangeAndType2(editor, caret, context, argument, true, operatorArguments.withCount0(count0));
|
getDeleteRangeAndType2(editor, caret, context, argument, true, operatorArguments.withCount0(count0));
|
||||||
if (deleteRangeAndType == null) return false;
|
if (deleteRangeAndType == null) return false;
|
||||||
ChangeGroupKt.changeRange(((IjVimEditor) editor).getEditor(), ((IjVimCaret) caret).getCaret(), deleteRangeAndType.getFirst(), deleteRangeAndType.getSecond(), ((IjExecutionContext) context).getContext());
|
//ChangeGroupKt.changeRange(((IjVimEditor) editor).getEditor(), ((IjVimCaret) caret).getCaret(), deleteRangeAndType.getFirst(), deleteRangeAndType.getSecond(), ((IjExecutionContext) context).getContext());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Pair<TextRange, SelectionType> deleteRangeAndType =
|
Pair<TextRange, SelectionType> deleteRangeAndType =
|
||||||
getDeleteRangeAndType(editor, caret, context, argument, true, operatorArguments.withCount0(count0));
|
getDeleteRangeAndType(editor, caret, context, argument, true, operatorArguments.withCount0(count0));
|
||||||
if (deleteRangeAndType == null) return false;
|
if (deleteRangeAndType == null) return false;
|
||||||
return changeRange(editor, caret, deleteRangeAndType.getFirst(), deleteRangeAndType.getSecond(), context);
|
return changeRange(editor, caret, deleteRangeAndType.getFirst(), deleteRangeAndType.getSecond(), context,
|
||||||
|
operatorArguments);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Counts number of lines in the visual block.
|
|
||||||
* <p>
|
|
||||||
* The result includes empty and short lines which does not have explicit start position (caret).
|
|
||||||
*
|
|
||||||
* @param editor The editor the block was selected in
|
|
||||||
* @param range The range corresponding to the selected block
|
|
||||||
* @return total number of lines
|
|
||||||
*/
|
|
||||||
public static int getLinesCountInVisualBlock(@NotNull VimEditor editor, @NotNull TextRange range) {
|
|
||||||
final int[] startOffsets = range.getStartOffsets();
|
|
||||||
if (startOffsets.length == 0) return 0;
|
|
||||||
final VimLogicalPosition firstStart = editor.offsetToLogicalPosition(startOffsets[0]);
|
|
||||||
final VimLogicalPosition lastStart = editor.offsetToLogicalPosition(startOffsets[range.size() - 1]);
|
|
||||||
return lastStart.getLine() - firstStart.getLine() + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Toggles the case of count characters
|
* Toggles the case of count characters
|
||||||
*
|
*
|
||||||
@@ -484,11 +336,11 @@ public class ChangeGroup extends VimChangeGroupBase {
|
|||||||
@NotNull TextRange range,
|
@NotNull TextRange range,
|
||||||
boolean append,
|
boolean append,
|
||||||
@NotNull OperatorArguments operatorArguments) {
|
@NotNull OperatorArguments operatorArguments) {
|
||||||
final int lines = getLinesCountInVisualBlock(editor, range);
|
final int lines = VimChangeGroupBase.Companion.getLinesCountInVisualBlock(editor, range);
|
||||||
final VimLogicalPosition startPosition = editor.offsetToLogicalPosition(range.getStartOffset());
|
final VimLogicalPosition startPosition = editor.offsetToLogicalPosition(range.getStartOffset());
|
||||||
|
|
||||||
boolean visualBlockMode = operatorArguments.getMode() == CommandState.Mode.VISUAL &&
|
boolean visualBlockMode = operatorArguments.getMode() == VimStateMachine.Mode.VISUAL &&
|
||||||
operatorArguments.getSubMode() == CommandState.SubMode.VISUAL_BLOCK;
|
operatorArguments.getSubMode() == VimStateMachine.SubMode.VISUAL_BLOCK;
|
||||||
for (Caret caret : ((IjVimEditor) editor).getEditor().getCaretModel().getAllCarets()) {
|
for (Caret caret : ((IjVimEditor) editor).getEditor().getCaretModel().getAllCarets()) {
|
||||||
final int line = startPosition.getLine();
|
final int line = startPosition.getLine();
|
||||||
int column = startPosition.getColumn();
|
int column = startPosition.getColumn();
|
||||||
@@ -578,6 +430,7 @@ public class ChangeGroup extends VimChangeGroupBase {
|
|||||||
* @param caret The caret to be moved after range deletion
|
* @param caret The caret to be moved after range deletion
|
||||||
* @param range The range to change
|
* @param range The range to change
|
||||||
* @param type The type of the range
|
* @param type The type of the range
|
||||||
|
* @param operatorArguments
|
||||||
* @return true if able to delete the range, false if not
|
* @return true if able to delete the range, false if not
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
@@ -585,28 +438,29 @@ public class ChangeGroup extends VimChangeGroupBase {
|
|||||||
@NotNull VimCaret caret,
|
@NotNull VimCaret caret,
|
||||||
@NotNull TextRange range,
|
@NotNull TextRange range,
|
||||||
@NotNull SelectionType type,
|
@NotNull SelectionType type,
|
||||||
ExecutionContext context) {
|
@Nullable ExecutionContext context,
|
||||||
|
@NotNull OperatorArguments operatorArguments) {
|
||||||
int col = 0;
|
int col = 0;
|
||||||
int lines = 0;
|
int lines = 0;
|
||||||
if (type == SelectionType.BLOCK_WISE) {
|
if (type == SelectionType.BLOCK_WISE) {
|
||||||
lines = getLinesCountInVisualBlock(editor, range);
|
lines = VimChangeGroupBase.Companion.getLinesCountInVisualBlock(editor, range);
|
||||||
col = editor.offsetToLogicalPosition(range.getStartOffset()).getColumn();
|
col = editor.offsetToLogicalPosition(range.getStartOffset()).getColumn();
|
||||||
if (UserDataManager.getVimLastColumn(((IjVimCaret) caret).getCaret()) == VimMotionGroupBase.LAST_COLUMN) {
|
if (caret.getVimLastColumn() == VimMotionGroupBase.LAST_COLUMN) {
|
||||||
col = VimMotionGroupBase.LAST_COLUMN;
|
col = VimMotionGroupBase.LAST_COLUMN;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
boolean after = range.getEndOffset() >= EditorHelperRt.getFileSize(((IjVimEditor) editor).getEditor());
|
boolean after = range.getEndOffset() >= editor.fileSize();
|
||||||
|
|
||||||
final VimLogicalPosition lp = editor.offsetToLogicalPosition(VimPlugin.getMotion().moveCaretToLineStartSkipLeading(editor, caret));
|
final VimLogicalPosition lp = editor.offsetToLogicalPosition(injector.getMotion().moveCaretToLineStartSkipLeading(editor, caret));
|
||||||
|
|
||||||
boolean res = deleteRange(editor, caret, range, type, true);
|
boolean res = deleteRange(editor, caret, range, type, true, operatorArguments);
|
||||||
if (res) {
|
if (res) {
|
||||||
if (type == SelectionType.LINE_WISE) {
|
if (type == SelectionType.LINE_WISE) {
|
||||||
// Please don't use `getDocument().getText().isEmpty()` because it converts CharSequence into String
|
// Please don't use `getDocument().getText().isEmpty()` because it converts CharSequence into String
|
||||||
if (((IjVimEditor) editor).getEditor().getDocument().getTextLength() == 0) {
|
if (editor.fileSize() == 0) {
|
||||||
insertBeforeCursor(editor, context);
|
insertBeforeCursor(editor, context);
|
||||||
}
|
}
|
||||||
else if (after && !EditorHelperRt.endsWithNewLine(((IjVimEditor) editor).getEditor())) {
|
else if (after && !EngineEditorHelperKt.endsWithNewLine(editor)) {
|
||||||
insertNewLineBelow(editor, caret, lp.getColumn());
|
insertNewLineBelow(editor, caret, lp.getColumn());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -617,7 +471,7 @@ public class ChangeGroup extends VimChangeGroupBase {
|
|||||||
if (type == SelectionType.BLOCK_WISE) {
|
if (type == SelectionType.BLOCK_WISE) {
|
||||||
setInsertRepeat(lines, col, false);
|
setInsertRepeat(lines, col, false);
|
||||||
}
|
}
|
||||||
UserDataManager.setVimChangeActionSwitchMode(((IjVimEditor) editor).getEditor(), CommandState.Mode.INSERT);
|
UserDataManager.setVimChangeActionSwitchMode(((IjVimEditor) editor).getEditor(), VimStateMachine.Mode.INSERT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -735,10 +589,11 @@ public class ChangeGroup extends VimChangeGroupBase {
|
|||||||
@NotNull VimCaret caret,
|
@NotNull VimCaret caret,
|
||||||
@NotNull ExecutionContext context,
|
@NotNull ExecutionContext context,
|
||||||
int lines,
|
int lines,
|
||||||
int dir) {
|
int dir,
|
||||||
|
@NotNull OperatorArguments operatorArguments) {
|
||||||
int start = ((IjVimCaret) caret).getCaret().getOffset();
|
int start = ((IjVimCaret) caret).getCaret().getOffset();
|
||||||
int end = VimPlugin.getMotion().moveCaretToLineEndOffset(editor, caret, lines - 1, true);
|
int end = VimPlugin.getMotion().moveCaretToLineEndOffset(editor, caret, lines - 1, true);
|
||||||
indentRange(editor, caret, context, new TextRange(start, end), 1, dir);
|
indentRange(editor, caret, context, new TextRange(start, end), 1, dir, operatorArguments);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -751,7 +606,7 @@ public class ChangeGroup extends VimChangeGroupBase {
|
|||||||
final TextRange range =
|
final TextRange range =
|
||||||
injector.getMotion().getMotionRange(editor, caret, context, argument, operatorArguments);
|
injector.getMotion().getMotionRange(editor, caret, context, argument, operatorArguments);
|
||||||
if (range != null) {
|
if (range != null) {
|
||||||
indentRange(editor, caret, context, range, 1, dir);
|
indentRange(editor, caret, context, range, 1, dir, operatorArguments);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -778,7 +633,8 @@ public class ChangeGroup extends VimChangeGroupBase {
|
|||||||
@NotNull ExecutionContext context,
|
@NotNull ExecutionContext context,
|
||||||
@NotNull TextRange range,
|
@NotNull TextRange range,
|
||||||
int count,
|
int count,
|
||||||
int dir) {
|
int dir,
|
||||||
|
@NotNull OperatorArguments operatorArguments) {
|
||||||
if (logger.isDebugEnabled()) {
|
if (logger.isDebugEnabled()) {
|
||||||
logger.debug("count=" + count);
|
logger.debug("count=" + count);
|
||||||
}
|
}
|
||||||
@@ -824,7 +680,7 @@ public class ChangeGroup extends VimChangeGroupBase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (pos > wsoff) {
|
if (pos > wsoff) {
|
||||||
deleteText(editor, new TextRange(wsoff, pos), null);
|
deleteText(editor, new TextRange(wsoff, pos), null, caret, operatorArguments);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -38,8 +38,7 @@ import com.intellij.openapi.vfs.VirtualFile;
|
|||||||
import com.intellij.openapi.vfs.VirtualFileVisitor;
|
import com.intellij.openapi.vfs.VirtualFileVisitor;
|
||||||
import com.maddyhome.idea.vim.VimPlugin;
|
import com.maddyhome.idea.vim.VimPlugin;
|
||||||
import com.maddyhome.idea.vim.api.*;
|
import com.maddyhome.idea.vim.api.*;
|
||||||
import com.maddyhome.idea.vim.command.CommandState;
|
import com.maddyhome.idea.vim.command.VimStateMachine;
|
||||||
import com.maddyhome.idea.vim.common.GoalCommand;
|
|
||||||
import com.maddyhome.idea.vim.common.TextRange;
|
import com.maddyhome.idea.vim.common.TextRange;
|
||||||
import com.maddyhome.idea.vim.helper.EditorHelper;
|
import com.maddyhome.idea.vim.helper.EditorHelper;
|
||||||
import com.maddyhome.idea.vim.helper.EditorHelperRt;
|
import com.maddyhome.idea.vim.helper.EditorHelperRt;
|
||||||
@@ -48,7 +47,6 @@ import com.maddyhome.idea.vim.helper.SearchHelper;
|
|||||||
import com.maddyhome.idea.vim.newapi.ExecuteExtensionKt;
|
import com.maddyhome.idea.vim.newapi.ExecuteExtensionKt;
|
||||||
import com.maddyhome.idea.vim.newapi.IjExecutionContext;
|
import com.maddyhome.idea.vim.newapi.IjExecutionContext;
|
||||||
import com.maddyhome.idea.vim.newapi.IjVimEditor;
|
import com.maddyhome.idea.vim.newapi.IjVimEditor;
|
||||||
import com.maddyhome.idea.vim.options.OptionConstants;
|
|
||||||
import com.maddyhome.idea.vim.options.OptionScope;
|
import com.maddyhome.idea.vim.options.OptionScope;
|
||||||
import com.maddyhome.idea.vim.vimscript.model.datatypes.VimString;
|
import com.maddyhome.idea.vim.vimscript.model.datatypes.VimString;
|
||||||
import com.maddyhome.idea.vim.vimscript.services.IjVimOptionService;
|
import com.maddyhome.idea.vim.vimscript.services.IjVimOptionService;
|
||||||
@@ -290,7 +288,7 @@ public class FileGroup extends VimFileBase {
|
|||||||
StringBuilder msg = new StringBuilder();
|
StringBuilder msg = new StringBuilder();
|
||||||
Document doc = editor.getDocument();
|
Document doc = editor.getDocument();
|
||||||
|
|
||||||
if (CommandState.getInstance(new IjVimEditor(editor)).getMode() != CommandState.Mode.VISUAL) {
|
if (VimStateMachine.getInstance(new IjVimEditor(editor)).getMode() != VimStateMachine.Mode.VISUAL) {
|
||||||
LogicalPosition lp = editor.getCaretModel().getLogicalPosition();
|
LogicalPosition lp = editor.getCaretModel().getLogicalPosition();
|
||||||
int col = editor.getCaretModel().getOffset() - doc.getLineStartOffset(lp.line);
|
int col = editor.getCaretModel().getOffset() - doc.getLineStartOffset(lp.line);
|
||||||
int endoff = doc.getLineEndOffset(lp.line);
|
int endoff = doc.getLineEndOffset(lp.line);
|
||||||
|
@@ -36,6 +36,7 @@ class IjVimStorageService : VimStorageServiceBase() {
|
|||||||
editor.ij.putUserData(getOrCreateIjKey(key), data)
|
editor.ij.putUserData(getOrCreateIjKey(key), data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
override fun <T> getDataFromBuffer(editor: VimEditor, key: com.maddyhome.idea.vim.api.Key<T>): T? {
|
override fun <T> getDataFromBuffer(editor: VimEditor, key: com.maddyhome.idea.vim.api.Key<T>): T? {
|
||||||
val buffer = EditorHelper.getVirtualFile(editor.ij)?.path ?: "empty path"
|
val buffer = EditorHelper.getVirtualFile(editor.ij)?.path ?: "empty path"
|
||||||
return bufferToKey[buffer]?.get(key.name) as T?
|
return bufferToKey[buffer]?.get(key.name) as T?
|
||||||
@@ -60,6 +61,7 @@ class IjVimStorageService : VimStorageServiceBase() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private val ijKeys = mutableMapOf<String, Key<out Any?>>()
|
private val ijKeys = mutableMapOf<String, Key<out Any?>>()
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
private fun <T> getOrCreateIjKey(key: com.maddyhome.idea.vim.api.Key<T>): Key<T> {
|
private fun <T> getOrCreateIjKey(key: com.maddyhome.idea.vim.api.Key<T>): Key<T> {
|
||||||
val storedIjKey = ijKeys[key.name]
|
val storedIjKey = ijKeys[key.name]
|
||||||
if (storedIjKey != null) {
|
if (storedIjKey != null) {
|
||||||
|
@@ -37,9 +37,8 @@ import com.maddyhome.idea.vim.VimPlugin;
|
|||||||
import com.maddyhome.idea.vim.action.ComplicatedKeysAction;
|
import com.maddyhome.idea.vim.action.ComplicatedKeysAction;
|
||||||
import com.maddyhome.idea.vim.action.VimShortcutKeyAction;
|
import com.maddyhome.idea.vim.action.VimShortcutKeyAction;
|
||||||
import com.maddyhome.idea.vim.api.*;
|
import com.maddyhome.idea.vim.api.*;
|
||||||
import com.maddyhome.idea.vim.common.MappingMode;
|
import com.maddyhome.idea.vim.command.MappingMode;
|
||||||
import com.maddyhome.idea.vim.common.Node;
|
import com.maddyhome.idea.vim.key.Node;
|
||||||
import com.maddyhome.idea.vim.common.NodesKt;
|
|
||||||
import com.maddyhome.idea.vim.ex.ExOutputModel;
|
import com.maddyhome.idea.vim.ex.ExOutputModel;
|
||||||
import com.maddyhome.idea.vim.handler.EditorActionHandlerBase;
|
import com.maddyhome.idea.vim.handler.EditorActionHandlerBase;
|
||||||
import com.maddyhome.idea.vim.helper.HelperKt;
|
import com.maddyhome.idea.vim.helper.HelperKt;
|
||||||
|
@@ -108,7 +108,9 @@ public class MacroGroup extends VimMacroBase {
|
|||||||
KeyHandler.getInstance().handleKey(editor, key, context);
|
KeyHandler.getInstance().handleKey(editor, key, context);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
keyStack.resetFirst();
|
||||||
}
|
}
|
||||||
|
keyStack.removeFirst();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -44,7 +44,6 @@ import com.maddyhome.idea.vim.helper.EditorHelper;
|
|||||||
import com.maddyhome.idea.vim.helper.HelperKt;
|
import com.maddyhome.idea.vim.helper.HelperKt;
|
||||||
import com.maddyhome.idea.vim.mark.*;
|
import com.maddyhome.idea.vim.mark.*;
|
||||||
import com.maddyhome.idea.vim.newapi.IjVimEditor;
|
import com.maddyhome.idea.vim.newapi.IjVimEditor;
|
||||||
import com.maddyhome.idea.vim.options.OptionConstants;
|
|
||||||
import com.maddyhome.idea.vim.options.OptionScope;
|
import com.maddyhome.idea.vim.options.OptionScope;
|
||||||
import com.maddyhome.idea.vim.vimscript.services.IjVimOptionService;
|
import com.maddyhome.idea.vim.vimscript.services.IjVimOptionService;
|
||||||
import org.jdom.Element;
|
import org.jdom.Element;
|
||||||
@@ -60,8 +59,7 @@ import static com.maddyhome.idea.vim.mark.VimMarkConstants.SAVE_FILE_MARKS;
|
|||||||
* This class contains all the mark related functionality
|
* This class contains all the mark related functionality
|
||||||
*/
|
*/
|
||||||
@State(name = "VimMarksSettings", storages = {
|
@State(name = "VimMarksSettings", storages = {
|
||||||
@Storage(value = "$APP_CONFIG$/vim_settings_local.xml", roamingType = RoamingType.DISABLED)
|
@Storage(value = "$APP_CONFIG$/vim_settings_local.xml", roamingType = RoamingType.DISABLED)})
|
||||||
})
|
|
||||||
public class MarkGroup extends VimMarkGroupBase implements PersistentStateComponent<Element> {
|
public class MarkGroup extends VimMarkGroupBase implements PersistentStateComponent<Element> {
|
||||||
public void editorReleased(@NotNull EditorFactoryEvent event) {
|
public void editorReleased(@NotNull EditorFactoryEvent event) {
|
||||||
// Save off the last caret position of the file before it is closed
|
// Save off the last caret position of the file before it is closed
|
||||||
@@ -127,7 +125,8 @@ public class MarkGroup extends VimMarkGroupBase implements PersistentStateCompon
|
|||||||
|
|
||||||
public void saveData(@NotNull Element element) {
|
public void saveData(@NotNull Element element) {
|
||||||
Element marksElem = new Element("globalmarks");
|
Element marksElem = new Element("globalmarks");
|
||||||
if (!VimPlugin.getOptionService().isSet(OptionScope.GLOBAL.INSTANCE, IjVimOptionService.ideamarksName, IjVimOptionService.ideamarksName)) {
|
if (!VimPlugin.getOptionService()
|
||||||
|
.isSet(OptionScope.GLOBAL.INSTANCE, IjVimOptionService.ideamarksName, IjVimOptionService.ideamarksName)) {
|
||||||
for (Mark mark : globalMarks.values()) {
|
for (Mark mark : globalMarks.values()) {
|
||||||
if (!mark.isClear()) {
|
if (!mark.isClear()) {
|
||||||
Element markElem = new Element("mark");
|
Element markElem = new Element("mark");
|
||||||
@@ -165,8 +164,7 @@ public class MarkGroup extends VimMarkGroupBase implements PersistentStateCompon
|
|||||||
fileMarkElem.setAttribute("name", file);
|
fileMarkElem.setAttribute("name", file);
|
||||||
fileMarkElem.setAttribute("timestamp", Long.toString(marks.getMyTimestamp().getTime()));
|
fileMarkElem.setAttribute("timestamp", Long.toString(marks.getMyTimestamp().getTime()));
|
||||||
for (Mark mark : marks.values()) {
|
for (Mark mark : marks.values()) {
|
||||||
if (!mark.isClear() && !Character.isUpperCase(mark.getKey()) &&
|
if (!mark.isClear() && !Character.isUpperCase(mark.getKey()) && SAVE_FILE_MARKS.indexOf(mark.getKey()) >= 0) {
|
||||||
SAVE_FILE_MARKS.indexOf(mark.getKey()) >= 0) {
|
|
||||||
Element markElem = new Element("mark");
|
Element markElem = new Element("mark");
|
||||||
markElem.setAttribute("key", Character.toString(mark.getKey()));
|
markElem.setAttribute("key", Character.toString(mark.getKey()));
|
||||||
markElem.setAttribute("line", Integer.toString(mark.getLogicalLine()));
|
markElem.setAttribute("line", Integer.toString(mark.getLogicalLine()));
|
||||||
@@ -200,14 +198,15 @@ public class MarkGroup extends VimMarkGroupBase implements PersistentStateCompon
|
|||||||
// (see com.intellij.openapi.application.Application.runReadAction())
|
// (see com.intellij.openapi.application.Application.runReadAction())
|
||||||
|
|
||||||
Element marksElem = element.getChild("globalmarks");
|
Element marksElem = element.getChild("globalmarks");
|
||||||
if (marksElem != null && !VimPlugin.getOptionService().isSet(OptionScope.GLOBAL.INSTANCE, IjVimOptionService.ideamarksName, IjVimOptionService.ideamarksName)) {
|
if (marksElem != null &&
|
||||||
|
!VimPlugin.getOptionService()
|
||||||
|
.isSet(OptionScope.GLOBAL.INSTANCE, IjVimOptionService.ideamarksName, IjVimOptionService.ideamarksName)) {
|
||||||
List<Element> markList = marksElem.getChildren("mark");
|
List<Element> markList = marksElem.getChildren("mark");
|
||||||
for (Element aMarkList : markList) {
|
for (Element aMarkList : markList) {
|
||||||
Mark mark = VimMark.create(aMarkList.getAttributeValue("key").charAt(0),
|
Mark mark = VimMark.create(aMarkList.getAttributeValue("key").charAt(0),
|
||||||
Integer.parseInt(aMarkList.getAttributeValue("line")),
|
Integer.parseInt(aMarkList.getAttributeValue("line")),
|
||||||
Integer.parseInt(aMarkList.getAttributeValue("column")),
|
Integer.parseInt(aMarkList.getAttributeValue("column")),
|
||||||
aMarkList.getAttributeValue("filename"),
|
aMarkList.getAttributeValue("filename"), aMarkList.getAttributeValue("protocol"));
|
||||||
aMarkList.getAttributeValue("protocol"));
|
|
||||||
|
|
||||||
if (mark != null) {
|
if (mark != null) {
|
||||||
globalMarks.put(mark.getKey(), mark);
|
globalMarks.put(mark.getKey(), mark);
|
||||||
@@ -239,8 +238,7 @@ public class MarkGroup extends VimMarkGroupBase implements PersistentStateCompon
|
|||||||
for (Element aMarkList : markList) {
|
for (Element aMarkList : markList) {
|
||||||
Mark mark = VimMark.create(aMarkList.getAttributeValue("key").charAt(0),
|
Mark mark = VimMark.create(aMarkList.getAttributeValue("key").charAt(0),
|
||||||
Integer.parseInt(aMarkList.getAttributeValue("line")),
|
Integer.parseInt(aMarkList.getAttributeValue("line")),
|
||||||
Integer.parseInt(aMarkList.getAttributeValue("column")),
|
Integer.parseInt(aMarkList.getAttributeValue("column")), filename,
|
||||||
filename,
|
|
||||||
aMarkList.getAttributeValue("protocol"));
|
aMarkList.getAttributeValue("protocol"));
|
||||||
|
|
||||||
if (mark != null) fmarks.put(mark.getKey(), mark);
|
if (mark != null) fmarks.put(mark.getKey(), mark);
|
||||||
@@ -290,6 +288,7 @@ public class MarkGroup extends VimMarkGroupBase implements PersistentStateCompon
|
|||||||
public static class MarkUpdater implements DocumentListener {
|
public static class MarkUpdater implements DocumentListener {
|
||||||
|
|
||||||
public static MarkUpdater INSTANCE = new MarkUpdater();
|
public static MarkUpdater INSTANCE = new MarkUpdater();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates the listener for the supplied editor
|
* Creates the listener for the supplied editor
|
||||||
*/
|
*/
|
||||||
@@ -313,8 +312,7 @@ public class MarkGroup extends VimMarkGroupBase implements PersistentStateCompon
|
|||||||
Editor anEditor = getAnEditor(doc);
|
Editor anEditor = getAnEditor(doc);
|
||||||
VimInjectorKt.getInjector().getMarkGroup()
|
VimInjectorKt.getInjector().getMarkGroup()
|
||||||
.updateMarkFromDelete(anEditor == null ? null : new IjVimEditor(anEditor),
|
.updateMarkFromDelete(anEditor == null ? null : new IjVimEditor(anEditor),
|
||||||
VimPlugin.getMark().getAllFileMarks(doc),
|
VimPlugin.getMark().getAllFileMarks(doc), event.getOffset(), event.getOldLength());
|
||||||
event.getOffset(), event.getOldLength());
|
|
||||||
// TODO - update jumps
|
// TODO - update jumps
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -361,7 +359,10 @@ public class MarkGroup extends VimMarkGroupBase implements PersistentStateCompon
|
|||||||
@Override
|
@Override
|
||||||
public void bookmarkAdded(@NotNull BookmarkGroup group, com.intellij.ide.bookmark.@NotNull Bookmark bookmark) {
|
public void bookmarkAdded(@NotNull BookmarkGroup group, com.intellij.ide.bookmark.@NotNull Bookmark bookmark) {
|
||||||
if (!VimPlugin.isEnabled()) return;
|
if (!VimPlugin.isEnabled()) return;
|
||||||
if (!VimPlugin.getOptionService().isSet(OptionScope.GLOBAL.INSTANCE, IjVimOptionService.ideamarksName, IjVimOptionService.ideamarksName)) return;
|
if (!VimPlugin.getOptionService()
|
||||||
|
.isSet(OptionScope.GLOBAL.INSTANCE, IjVimOptionService.ideamarksName, IjVimOptionService.ideamarksName)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!(bookmark instanceof LineBookmark)) return;
|
if (!(bookmark instanceof LineBookmark)) return;
|
||||||
BookmarksManager bookmarksManager = BookmarksManager.getInstance(myProject);
|
BookmarksManager bookmarksManager = BookmarksManager.getInstance(myProject);
|
||||||
@@ -378,7 +379,10 @@ public class MarkGroup extends VimMarkGroupBase implements PersistentStateCompon
|
|||||||
@Override
|
@Override
|
||||||
public void bookmarkRemoved(@NotNull BookmarkGroup group, com.intellij.ide.bookmark.@NotNull Bookmark bookmark) {
|
public void bookmarkRemoved(@NotNull BookmarkGroup group, com.intellij.ide.bookmark.@NotNull Bookmark bookmark) {
|
||||||
if (!VimPlugin.isEnabled()) return;
|
if (!VimPlugin.isEnabled()) return;
|
||||||
if (!VimPlugin.getOptionService().isSet(OptionScope.GLOBAL.INSTANCE, IjVimOptionService.ideamarksName, IjVimOptionService.ideamarksName)) return;
|
if (!VimPlugin.getOptionService()
|
||||||
|
.isSet(OptionScope.GLOBAL.INSTANCE, IjVimOptionService.ideamarksName, IjVimOptionService.ideamarksName)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!(bookmark instanceof LineBookmark)) return;
|
if (!(bookmark instanceof LineBookmark)) return;
|
||||||
BookmarksManager bookmarksManager = BookmarksManager.getInstance(myProject);
|
BookmarksManager bookmarksManager = BookmarksManager.getInstance(myProject);
|
||||||
@@ -387,7 +391,8 @@ public class MarkGroup extends VimMarkGroupBase implements PersistentStateCompon
|
|||||||
if (type == null) return;
|
if (type == null) return;
|
||||||
char ch = type.getMnemonic();
|
char ch = type.getMnemonic();
|
||||||
if (GLOBAL_MARKS.indexOf(ch) != -1) {
|
if (GLOBAL_MARKS.indexOf(ch) != -1) {
|
||||||
FileMarks<Character, Mark> fmarks = VimPlugin.getMark().getFileMarks(((LineBookmark)bookmark).getFile().getPath());
|
FileMarks<Character, Mark> fmarks =
|
||||||
|
VimPlugin.getMark().getFileMarks(((LineBookmark)bookmark).getFile().getPath());
|
||||||
fmarks.remove(ch);
|
fmarks.remove(ch);
|
||||||
VimPlugin.getMark().globalMarks.remove(ch);
|
VimPlugin.getMark().globalMarks.remove(ch);
|
||||||
}
|
}
|
||||||
@@ -404,6 +409,17 @@ public class MarkGroup extends VimMarkGroupBase implements PersistentStateCompon
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* COMPATIBILITY-LAYER: Method added
|
||||||
|
* Please see: <a href="https://jb.gg/zo8n0r">doc</a>
|
||||||
|
*
|
||||||
|
* @deprecated Please use method with VimEditor
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
public void saveJumpLocation(Editor editor) {
|
||||||
|
this.saveJumpLocation(new IjVimEditor(editor));
|
||||||
|
}
|
||||||
|
|
||||||
private static final int SAVE_MARK_COUNT = 20;
|
private static final int SAVE_MARK_COUNT = 20;
|
||||||
|
|
||||||
private static final Logger logger = Logger.getInstance(MarkGroup.class.getName());
|
private static final Logger logger = Logger.getInstance(MarkGroup.class.getName());
|
||||||
|
@@ -711,7 +711,7 @@ public class MotionGroup extends VimMotionGroupBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static int getScrollJump(@NotNull Editor editor, int height) {
|
private static int getScrollJump(@NotNull Editor editor, int height) {
|
||||||
final EnumSet<CommandFlags> flags = CommandState.getInstance(new IjVimEditor(editor)).getExecutingCommandFlags();
|
final EnumSet<CommandFlags> flags = VimStateMachine.getInstance(new IjVimEditor(editor)).getExecutingCommandFlags();
|
||||||
final boolean scrollJump = !flags.contains(CommandFlags.FLAG_IGNORE_SCROLL_JUMP);
|
final boolean scrollJump = !flags.contains(CommandFlags.FLAG_IGNORE_SCROLL_JUMP);
|
||||||
|
|
||||||
// Default value is 1. Zero is a valid value, but we normalise to 1 - we always want to scroll at least one line
|
// Default value is 1. Zero is a valid value, but we normalise to 1 - we always want to scroll at least one line
|
||||||
@@ -736,7 +736,7 @@ public class MotionGroup extends VimMotionGroupBase {
|
|||||||
final int halfWidth = getApproximateScreenWidth(editor) / 2;
|
final int halfWidth = getApproximateScreenWidth(editor) / 2;
|
||||||
final int scrollOffset = getNormalizedSideScrollOffset(editor);
|
final int scrollOffset = getNormalizedSideScrollOffset(editor);
|
||||||
|
|
||||||
final EnumSet<CommandFlags> flags = CommandState.getInstance(new IjVimEditor(editor)).getExecutingCommandFlags();
|
final EnumSet<CommandFlags> flags = VimStateMachine.getInstance(new IjVimEditor(editor)).getExecutingCommandFlags();
|
||||||
final boolean allowSidescroll = !flags.contains(CommandFlags.FLAG_IGNORE_SIDE_SCROLL_JUMP);
|
final boolean allowSidescroll = !flags.contains(CommandFlags.FLAG_IGNORE_SIDE_SCROLL_JUMP);
|
||||||
int sidescroll = ((VimInt) VimPlugin.getOptionService().getOptionValue(new OptionScope.LOCAL(new IjVimEditor(editor)), OptionConstants.sidescrollName, OptionConstants.sidescrollName)).getValue();
|
int sidescroll = ((VimInt) VimPlugin.getOptionService().getOptionValue(new OptionScope.LOCAL(new IjVimEditor(editor)), OptionConstants.sidescrollName, OptionConstants.sidescrollName)).getValue();
|
||||||
|
|
||||||
@@ -1200,7 +1200,7 @@ public class MotionGroup extends VimMotionGroupBase {
|
|||||||
if (fileEditor instanceof TextEditor) {
|
if (fileEditor instanceof TextEditor) {
|
||||||
final Editor editor = ((TextEditor)fileEditor).getEditor();
|
final Editor editor = ((TextEditor)fileEditor).getEditor();
|
||||||
ExOutputModel.getInstance(editor).clear();
|
ExOutputModel.getInstance(editor).clear();
|
||||||
if (CommandState.getInstance(new IjVimEditor(editor)).getMode() == CommandState.Mode.VISUAL) {
|
if (VimStateMachine.getInstance(new IjVimEditor(editor)).getMode() == VimStateMachine.Mode.VISUAL) {
|
||||||
ModeHelper.exitVisualMode(editor);
|
ModeHelper.exitVisualMode(editor);
|
||||||
KeyHandler.getInstance().reset(new IjVimEditor(editor));
|
KeyHandler.getInstance().reset(new IjVimEditor(editor));
|
||||||
}
|
}
|
||||||
|
@@ -20,26 +20,23 @@ package com.maddyhome.idea.vim.group
|
|||||||
|
|
||||||
import com.intellij.icons.AllIcons
|
import com.intellij.icons.AllIcons
|
||||||
import com.intellij.ide.BrowserUtil
|
import com.intellij.ide.BrowserUtil
|
||||||
import com.intellij.ide.IdeBundle
|
|
||||||
import com.intellij.ide.actions.OpenFileAction
|
import com.intellij.ide.actions.OpenFileAction
|
||||||
import com.intellij.ide.actions.RevealFileAction
|
import com.intellij.ide.actions.RevealFileAction
|
||||||
|
import com.intellij.notification.ActionCenter
|
||||||
import com.intellij.notification.Notification
|
import com.intellij.notification.Notification
|
||||||
import com.intellij.notification.NotificationGroup
|
import com.intellij.notification.NotificationGroup
|
||||||
import com.intellij.notification.NotificationGroupManager
|
import com.intellij.notification.NotificationGroupManager
|
||||||
import com.intellij.notification.NotificationListener
|
|
||||||
import com.intellij.notification.NotificationType
|
import com.intellij.notification.NotificationType
|
||||||
import com.intellij.openapi.actionSystem.AnAction
|
import com.intellij.openapi.actionSystem.AnAction
|
||||||
import com.intellij.openapi.actionSystem.AnActionEvent
|
import com.intellij.openapi.actionSystem.AnActionEvent
|
||||||
import com.intellij.openapi.actionSystem.KeyboardShortcut
|
import com.intellij.openapi.actionSystem.KeyboardShortcut
|
||||||
import com.intellij.openapi.ide.CopyPasteManager
|
import com.intellij.openapi.ide.CopyPasteManager
|
||||||
import com.intellij.openapi.keymap.Keymap
|
|
||||||
import com.intellij.openapi.keymap.KeymapUtil
|
import com.intellij.openapi.keymap.KeymapUtil
|
||||||
import com.intellij.openapi.options.ShowSettingsUtil
|
import com.intellij.openapi.options.ShowSettingsUtil
|
||||||
import com.intellij.openapi.project.DumbAwareAction
|
import com.intellij.openapi.project.DumbAwareAction
|
||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
import com.intellij.openapi.ui.Messages
|
import com.intellij.openapi.ui.Messages
|
||||||
import com.intellij.openapi.util.SystemInfo
|
import com.intellij.openapi.util.SystemInfo
|
||||||
import com.intellij.openapi.util.registry.Registry
|
|
||||||
import com.maddyhome.idea.vim.VimPlugin
|
import com.maddyhome.idea.vim.VimPlugin
|
||||||
import com.maddyhome.idea.vim.helper.MessageHelper
|
import com.maddyhome.idea.vim.helper.MessageHelper
|
||||||
import com.maddyhome.idea.vim.key.ShortcutOwner
|
import com.maddyhome.idea.vim.key.ShortcutOwner
|
||||||
@@ -50,7 +47,6 @@ import com.maddyhome.idea.vim.statistic.ActionTracker
|
|||||||
import com.maddyhome.idea.vim.ui.VimEmulationConfigurable
|
import com.maddyhome.idea.vim.ui.VimEmulationConfigurable
|
||||||
import com.maddyhome.idea.vim.vimscript.services.IjVimOptionService
|
import com.maddyhome.idea.vim.vimscript.services.IjVimOptionService
|
||||||
import com.maddyhome.idea.vim.vimscript.services.VimRcService
|
import com.maddyhome.idea.vim.vimscript.services.VimRcService
|
||||||
import org.jetbrains.annotations.Nls
|
|
||||||
import java.awt.datatransfer.StringSelection
|
import java.awt.datatransfer.StringSelection
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import javax.swing.KeyStroke
|
import javax.swing.KeyStroke
|
||||||
@@ -115,23 +111,6 @@ class NotificationService(private val project: Project?) {
|
|||||||
Messages.getQuestionIcon()
|
Messages.getQuestionIcon()
|
||||||
)
|
)
|
||||||
|
|
||||||
fun specialKeymap(keymap: Keymap, listener: NotificationListener.Adapter) {
|
|
||||||
val notification = IDEAVIM_STICKY_GROUP.createNotification(
|
|
||||||
IDEAVIM_NOTIFICATION_TITLE,
|
|
||||||
"IdeaVim plugin doesn't use the special \"Vim\" keymap any longer. " +
|
|
||||||
"Switching to \"${keymap.presentableName}\" keymap.<br/><br/>" +
|
|
||||||
"Now it is possible to set up:<br/>" +
|
|
||||||
"<ul>" +
|
|
||||||
"<li>Vim keys in your ~/.ideavimrc file using key mapping commands</li>" +
|
|
||||||
"<li>IDE action shortcuts in \"File | Settings | Keymap\"</li>" +
|
|
||||||
"<li>Vim or IDE handlers for conflicting shortcuts in <a href='#settings'>Vim Emulation</a> settings</li>" +
|
|
||||||
"</ul>",
|
|
||||||
NotificationType.INFORMATION
|
|
||||||
)
|
|
||||||
notification.setListener(listener)
|
|
||||||
notification.notify(project)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun noVimrcAsDefault() {
|
fun noVimrcAsDefault() {
|
||||||
val notification = IDEAVIM_STICKY_GROUP.createNotification(
|
val notification = IDEAVIM_STICKY_GROUP.createNotification(
|
||||||
IDEAVIM_NOTIFICATION_TITLE,
|
IDEAVIM_NOTIFICATION_TITLE,
|
||||||
@@ -208,7 +187,7 @@ class NotificationService(private val project: Project?) {
|
|||||||
Notification(IDEAVIM_NOTIFICATION_ID, IDEAVIM_NOTIFICATION_TITLE, content, NotificationType.INFORMATION).let {
|
Notification(IDEAVIM_NOTIFICATION_ID, IDEAVIM_NOTIFICATION_TITLE, content, NotificationType.INFORMATION).let {
|
||||||
notification = it
|
notification = it
|
||||||
it.whenExpired { notification = null }
|
it.whenExpired { notification = null }
|
||||||
it.setContent(it.content + "<br><br><small>Use ${getToolwindowName()} to see previous ids</small>")
|
it.setContent(it.content + "<br><br><small>Use ${ActionCenter.getToolwindowName()} to see previous ids</small>")
|
||||||
|
|
||||||
it.addAction(StopTracking())
|
it.addAction(StopTracking())
|
||||||
|
|
||||||
@@ -222,15 +201,6 @@ class NotificationService(private val project: Project?) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// [VERSION UPDATE] 221+ Use ActionCenter.getToolWindowName
|
|
||||||
private fun getToolwindowName(): @Nls String {
|
|
||||||
return IdeBundle.message(if (isEnabled()) "toolwindow.stripe.Notifications" else "toolwindow.stripe.Event_Log")
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun isEnabled(): Boolean {
|
|
||||||
return Registry.`is`("ide.notification.action.center", true)
|
|
||||||
}
|
|
||||||
|
|
||||||
class CopyActionId(val id: String?, val project: Project?) : DumbAwareAction(MessageHelper.message("action.copy.action.id.text")) {
|
class CopyActionId(val id: String?, val project: Project?) : DumbAwareAction(MessageHelper.message("action.copy.action.id.text")) {
|
||||||
override fun actionPerformed(e: AnActionEvent) {
|
override fun actionPerformed(e: AnActionEvent) {
|
||||||
CopyPasteManager.getInstance().setContents(StringSelection(id ?: ""))
|
CopyPasteManager.getInstance().setContents(StringSelection(id ?: ""))
|
||||||
|
@@ -37,7 +37,7 @@ import com.maddyhome.idea.vim.KeyHandler;
|
|||||||
import com.maddyhome.idea.vim.VimPlugin;
|
import com.maddyhome.idea.vim.VimPlugin;
|
||||||
import com.maddyhome.idea.vim.api.*;
|
import com.maddyhome.idea.vim.api.*;
|
||||||
import com.maddyhome.idea.vim.command.Command;
|
import com.maddyhome.idea.vim.command.Command;
|
||||||
import com.maddyhome.idea.vim.command.CommandState;
|
import com.maddyhome.idea.vim.command.VimStateMachine;
|
||||||
import com.maddyhome.idea.vim.ex.ExException;
|
import com.maddyhome.idea.vim.ex.ExException;
|
||||||
import com.maddyhome.idea.vim.ex.InvalidCommandException;
|
import com.maddyhome.idea.vim.ex.InvalidCommandException;
|
||||||
import com.maddyhome.idea.vim.helper.UiHelper;
|
import com.maddyhome.idea.vim.helper.UiHelper;
|
||||||
@@ -90,7 +90,7 @@ public class ProcessGroup extends VimProcessGroupBase {
|
|||||||
if (editor.isOneLineMode()) return;
|
if (editor.isOneLineMode()) return;
|
||||||
|
|
||||||
String initText = getRange(((IjVimEditor) editor).getEditor(), cmd);
|
String initText = getRange(((IjVimEditor) editor).getEditor(), cmd);
|
||||||
CommandState.getInstance(editor).pushModes(CommandState.Mode.CMD_LINE, CommandState.SubMode.NONE);
|
VimStateMachine.getInstance(editor).pushModes(VimStateMachine.Mode.CMD_LINE, VimStateMachine.SubMode.NONE);
|
||||||
ExEntryPanel panel = ExEntryPanel.getInstance();
|
ExEntryPanel panel = ExEntryPanel.getInstance();
|
||||||
panel.activate(((IjVimEditor) editor).getEditor(), ((IjExecutionContext) context).getContext(), ":", initText, 1);
|
panel.activate(((IjVimEditor) editor).getEditor(), ((IjExecutionContext) context).getContext(), ":", initText, 1);
|
||||||
}
|
}
|
||||||
@@ -108,7 +108,7 @@ public class ProcessGroup extends VimProcessGroupBase {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
CommandState.getInstance(editor).popModes();
|
VimStateMachine.getInstance(editor).popModes();
|
||||||
KeyHandler.getInstance().reset(editor);
|
KeyHandler.getInstance().reset(editor);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -119,7 +119,7 @@ public class ProcessGroup extends VimProcessGroupBase {
|
|||||||
panel.deactivate(true);
|
panel.deactivate(true);
|
||||||
boolean res = true;
|
boolean res = true;
|
||||||
try {
|
try {
|
||||||
CommandState.getInstance(editor).popModes();
|
VimStateMachine.getInstance(editor).popModes();
|
||||||
|
|
||||||
logger.debug("processing command");
|
logger.debug("processing command");
|
||||||
|
|
||||||
@@ -152,11 +152,11 @@ public class ProcessGroup extends VimProcessGroupBase {
|
|||||||
|
|
||||||
// commands executed from map command / macro should not be added to history
|
// commands executed from map command / macro should not be added to history
|
||||||
private boolean skipHistory(VimEditor editor) {
|
private boolean skipHistory(VimEditor editor) {
|
||||||
return CommandState.getInstance(editor).getMappingState().isExecutingMap() || injector.getMacro().isExecutingMacro();
|
return VimStateMachine.getInstance(editor).getMappingState().isExecutingMap() || injector.getMacro().isExecutingMacro();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void cancelExEntry(final @NotNull VimEditor editor, boolean resetCaret) {
|
public void cancelExEntry(final @NotNull VimEditor editor, boolean resetCaret) {
|
||||||
CommandState.getInstance(editor).popModes();
|
VimStateMachine.getInstance(editor).popModes();
|
||||||
KeyHandler.getInstance().reset(editor);
|
KeyHandler.getInstance().reset(editor);
|
||||||
ExEntryPanel panel = ExEntryPanel.getInstance();
|
ExEntryPanel panel = ExEntryPanel.getInstance();
|
||||||
panel.deactivate(true, resetCaret);
|
panel.deactivate(true, resetCaret);
|
||||||
@@ -165,14 +165,14 @@ public class ProcessGroup extends VimProcessGroupBase {
|
|||||||
@Override
|
@Override
|
||||||
public void startFilterCommand(@NotNull VimEditor editor, ExecutionContext context, @NotNull Command cmd) {
|
public void startFilterCommand(@NotNull VimEditor editor, ExecutionContext context, @NotNull Command cmd) {
|
||||||
String initText = getRange(((IjVimEditor) editor).getEditor(), cmd) + "!";
|
String initText = getRange(((IjVimEditor) editor).getEditor(), cmd) + "!";
|
||||||
CommandState.getInstance(editor).pushModes(CommandState.Mode.CMD_LINE, CommandState.SubMode.NONE);
|
VimStateMachine.getInstance(editor).pushModes(VimStateMachine.Mode.CMD_LINE, VimStateMachine.SubMode.NONE);
|
||||||
ExEntryPanel panel = ExEntryPanel.getInstance();
|
ExEntryPanel panel = ExEntryPanel.getInstance();
|
||||||
panel.activate(((IjVimEditor) editor).getEditor(), ((IjExecutionContext) context).getContext(), ":", initText, 1);
|
panel.activate(((IjVimEditor) editor).getEditor(), ((IjExecutionContext) context).getContext(), ":", initText, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
private @NotNull String getRange(Editor editor, @NotNull Command cmd) {
|
private @NotNull String getRange(Editor editor, @NotNull Command cmd) {
|
||||||
String initText = "";
|
String initText = "";
|
||||||
if (CommandState.getInstance(new IjVimEditor(editor)).getMode() == CommandState.Mode.VISUAL) {
|
if (VimStateMachine.getInstance(new IjVimEditor(editor)).getMode() == VimStateMachine.Mode.VISUAL) {
|
||||||
initText = "'<,'>";
|
initText = "'<,'>";
|
||||||
}
|
}
|
||||||
else if (cmd.getRawCount() > 0) {
|
else if (cmd.getRawCount() > 0) {
|
||||||
|
@@ -890,6 +890,10 @@ public class SearchGroup extends VimSearchGroupBase implements PersistentStateCo
|
|||||||
@Override
|
@Override
|
||||||
public void setLastSearchPattern(@Nullable String lastSearchPattern) {
|
public void setLastSearchPattern(@Nullable String lastSearchPattern) {
|
||||||
this.lastSearch = lastSearchPattern;
|
this.lastSearch = lastSearchPattern;
|
||||||
|
if (showSearchHighlight) {
|
||||||
|
resetIncsearchHighlights();
|
||||||
|
updateSearchHighlights();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@@ -21,8 +21,8 @@ package com.maddyhome.idea.vim.group;
|
|||||||
import com.intellij.openapi.actionSystem.DataContext;
|
import com.intellij.openapi.actionSystem.DataContext;
|
||||||
import com.intellij.openapi.actionSystem.PlatformDataKeys;
|
import com.intellij.openapi.actionSystem.PlatformDataKeys;
|
||||||
import com.intellij.openapi.fileEditor.ex.FileEditorManagerEx;
|
import com.intellij.openapi.fileEditor.ex.FileEditorManagerEx;
|
||||||
|
import com.intellij.openapi.fileEditor.impl.EditorComposite;
|
||||||
import com.intellij.openapi.fileEditor.impl.EditorWindow;
|
import com.intellij.openapi.fileEditor.impl.EditorWindow;
|
||||||
import com.intellij.openapi.fileEditor.impl.EditorWithProviderComposite;
|
|
||||||
import com.intellij.openapi.project.Project;
|
import com.intellij.openapi.project.Project;
|
||||||
import com.intellij.openapi.vfs.VirtualFile;
|
import com.intellij.openapi.vfs.VirtualFile;
|
||||||
import com.intellij.util.concurrency.annotations.RequiresReadLock;
|
import com.intellij.util.concurrency.annotations.RequiresReadLock;
|
||||||
@@ -183,7 +183,7 @@ public class WindowGroup extends WindowGroupBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static @Nullable Rectangle getEditorWindowRectangle(@NotNull EditorWindow window) {
|
private static @Nullable Rectangle getEditorWindowRectangle(@NotNull EditorWindow window) {
|
||||||
final EditorWithProviderComposite editor = window.getSelectedEditor();
|
final EditorComposite editor = window.getSelectedComposite();
|
||||||
if (editor != null) {
|
if (editor != null) {
|
||||||
final Point point = editor.getComponent().getLocationOnScreen();
|
final Point point = editor.getComponent().getLocationOnScreen();
|
||||||
final Dimension dimension = editor.getComponent().getSize();
|
final Dimension dimension = editor.getComponent().getSize();
|
||||||
|
@@ -34,8 +34,9 @@ import com.maddyhome.idea.vim.api.ExecutionContext
|
|||||||
import com.maddyhome.idea.vim.api.VimCaret
|
import com.maddyhome.idea.vim.api.VimCaret
|
||||||
import com.maddyhome.idea.vim.api.VimEditor
|
import com.maddyhome.idea.vim.api.VimEditor
|
||||||
import com.maddyhome.idea.vim.api.injector
|
import com.maddyhome.idea.vim.api.injector
|
||||||
import com.maddyhome.idea.vim.command.CommandState
|
import com.maddyhome.idea.vim.command.OperatorArguments
|
||||||
import com.maddyhome.idea.vim.command.SelectionType
|
import com.maddyhome.idea.vim.command.SelectionType
|
||||||
|
import com.maddyhome.idea.vim.command.VimStateMachine
|
||||||
import com.maddyhome.idea.vim.command.isBlock
|
import com.maddyhome.idea.vim.command.isBlock
|
||||||
import com.maddyhome.idea.vim.command.isChar
|
import com.maddyhome.idea.vim.command.isChar
|
||||||
import com.maddyhome.idea.vim.command.isLine
|
import com.maddyhome.idea.vim.command.isLine
|
||||||
@@ -43,7 +44,9 @@ import com.maddyhome.idea.vim.common.TextRange
|
|||||||
import com.maddyhome.idea.vim.helper.EditorHelper
|
import com.maddyhome.idea.vim.helper.EditorHelper
|
||||||
import com.maddyhome.idea.vim.helper.TestClipboardModel
|
import com.maddyhome.idea.vim.helper.TestClipboardModel
|
||||||
import com.maddyhome.idea.vim.helper.fileSize
|
import com.maddyhome.idea.vim.helper.fileSize
|
||||||
|
import com.maddyhome.idea.vim.helper.mode
|
||||||
import com.maddyhome.idea.vim.helper.moveToInlayAwareOffset
|
import com.maddyhome.idea.vim.helper.moveToInlayAwareOffset
|
||||||
|
import com.maddyhome.idea.vim.helper.subMode
|
||||||
import com.maddyhome.idea.vim.mark.VimMarkConstants.MARK_CHANGE_POS
|
import com.maddyhome.idea.vim.mark.VimMarkConstants.MARK_CHANGE_POS
|
||||||
import com.maddyhome.idea.vim.newapi.IjVimCaret
|
import com.maddyhome.idea.vim.newapi.IjVimCaret
|
||||||
import com.maddyhome.idea.vim.newapi.IjVimEditor
|
import com.maddyhome.idea.vim.newapi.IjVimEditor
|
||||||
@@ -60,10 +63,20 @@ import java.awt.datatransfer.DataFlavor
|
|||||||
import kotlin.math.min
|
import kotlin.math.min
|
||||||
|
|
||||||
class PutGroup : VimPutBase() {
|
class PutGroup : VimPutBase() {
|
||||||
override fun putTextForCaret(editor: VimEditor, caret: VimCaret, context: ExecutionContext, data: PutData): Boolean {
|
override fun putTextForCaret(editor: VimEditor, caret: VimCaret, context: ExecutionContext, data: PutData, updateVisualMarks: Boolean): Boolean {
|
||||||
val additionalData = collectPreModificationData(editor, data)
|
val additionalData = collectPreModificationData(editor, data)
|
||||||
|
data.visualSelection?.let {
|
||||||
|
deleteSelectedText(
|
||||||
|
editor,
|
||||||
|
data,
|
||||||
|
OperatorArguments(false, 0, editor.mode, editor.subMode)
|
||||||
|
)
|
||||||
|
}
|
||||||
val processedText = processText(editor, data) ?: return false
|
val processedText = processText(editor, data) ?: return false
|
||||||
putForCaret(editor, caret, data, additionalData, context, processedText)
|
putForCaret(editor, caret, data, additionalData, context, processedText)
|
||||||
|
if (editor.primaryCaret() == caret && updateVisualMarks) {
|
||||||
|
wrapInsertedTextWithVisualMarks(editor, data, processedText)
|
||||||
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,7 +88,7 @@ class PutGroup : VimPutBase() {
|
|||||||
additionalData: Map<String, Any>,
|
additionalData: Map<String, Any>,
|
||||||
) {
|
) {
|
||||||
val visualSelection = data.visualSelection
|
val visualSelection = data.visualSelection
|
||||||
val subMode = visualSelection?.typeInEditor?.toSubMode() ?: CommandState.SubMode.NONE
|
val subMode = visualSelection?.typeInEditor?.toSubMode() ?: VimStateMachine.SubMode.NONE
|
||||||
if (OptionConstants.clipboard_ideaput in (
|
if (OptionConstants.clipboard_ideaput in (
|
||||||
injector.optionService
|
injector.optionService
|
||||||
.getOptionValue(OptionScope.GLOBAL, OptionConstants.clipboardName) as VimString
|
.getOptionValue(OptionScope.GLOBAL, OptionConstants.clipboardName) as VimString
|
||||||
@@ -89,7 +102,6 @@ class PutGroup : VimPutBase() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
notifyAboutIdeaPut(editor)
|
|
||||||
logger.debug("Perform put via plugin")
|
logger.debug("Perform put via plugin")
|
||||||
val myCarets = if (visualSelection != null) {
|
val myCarets = if (visualSelection != null) {
|
||||||
visualSelection.caretsAndSelections.keys.sortedByDescending { it.getLogicalPosition() }
|
visualSelection.caretsAndSelections.keys.sortedByDescending { it.getLogicalPosition() }
|
||||||
@@ -109,16 +121,19 @@ class PutGroup : VimPutBase() {
|
|||||||
context: ExecutionContext,
|
context: ExecutionContext,
|
||||||
text: ProcessedTextData,
|
text: ProcessedTextData,
|
||||||
) {
|
) {
|
||||||
|
notifyAboutIdeaPut(editor)
|
||||||
if (data.visualSelection?.typeInEditor?.isLine == true && editor.isOneLineMode()) return
|
if (data.visualSelection?.typeInEditor?.isLine == true && editor.isOneLineMode()) return
|
||||||
val startOffsets = prepareDocumentAndGetStartOffsets(editor, caret, text.typeInRegister, data, additionalData)
|
val startOffsets = prepareDocumentAndGetStartOffsets(editor, caret, text.typeInRegister, data, additionalData)
|
||||||
|
|
||||||
startOffsets.forEach { startOffset ->
|
startOffsets.forEach { startOffset ->
|
||||||
val subMode = data.visualSelection?.typeInEditor?.toSubMode() ?: CommandState.SubMode.NONE
|
val subMode = data.visualSelection?.typeInEditor?.toSubMode() ?: VimStateMachine.SubMode.NONE
|
||||||
val endOffset = putTextInternal(
|
val endOffset = putTextInternal(
|
||||||
editor, caret, context, text.text, text.typeInRegister, subMode,
|
editor, caret, context, text.text, text.typeInRegister, subMode,
|
||||||
startOffset, data.count, data.indent, data.caretAfterInsertedText
|
startOffset, data.count, data.indent, data.caretAfterInsertedText
|
||||||
)
|
)
|
||||||
|
if (caret == editor.primaryCaret()) {
|
||||||
VimPlugin.getMark().setChangeMarks(editor, TextRange(startOffset, endOffset))
|
VimPlugin.getMark().setChangeMarks(editor, TextRange(startOffset, endOffset))
|
||||||
|
}
|
||||||
moveCaretToEndPosition(
|
moveCaretToEndPosition(
|
||||||
editor,
|
editor,
|
||||||
caret,
|
caret,
|
||||||
@@ -233,7 +248,7 @@ class PutGroup : VimPutBase() {
|
|||||||
vimEditor: VimEditor,
|
vimEditor: VimEditor,
|
||||||
vimContext: ExecutionContext,
|
vimContext: ExecutionContext,
|
||||||
text: ProcessedTextData,
|
text: ProcessedTextData,
|
||||||
subMode: CommandState.SubMode,
|
subMode: VimStateMachine.SubMode,
|
||||||
data: PutData,
|
data: PutData,
|
||||||
additionalData: Map<String, Any>,
|
additionalData: Map<String, Any>,
|
||||||
) {
|
) {
|
||||||
|
@@ -18,23 +18,20 @@
|
|||||||
|
|
||||||
package com.maddyhome.idea.vim.group.copy
|
package com.maddyhome.idea.vim.group.copy
|
||||||
|
|
||||||
import com.intellij.openapi.editor.Caret
|
|
||||||
import com.intellij.openapi.editor.Editor
|
|
||||||
import com.intellij.util.containers.ContainerUtil
|
import com.intellij.util.containers.ContainerUtil
|
||||||
import com.maddyhome.idea.vim.VimPlugin
|
|
||||||
import com.maddyhome.idea.vim.action.motion.updown.MotionDownLess1FirstNonSpaceAction
|
import com.maddyhome.idea.vim.action.motion.updown.MotionDownLess1FirstNonSpaceAction
|
||||||
import com.maddyhome.idea.vim.api.ExecutionContext
|
import com.maddyhome.idea.vim.api.ExecutionContext
|
||||||
|
import com.maddyhome.idea.vim.api.VimCaret
|
||||||
import com.maddyhome.idea.vim.api.VimEditor
|
import com.maddyhome.idea.vim.api.VimEditor
|
||||||
|
import com.maddyhome.idea.vim.api.injector
|
||||||
import com.maddyhome.idea.vim.command.Argument
|
import com.maddyhome.idea.vim.command.Argument
|
||||||
import com.maddyhome.idea.vim.command.OperatorArguments
|
import com.maddyhome.idea.vim.command.OperatorArguments
|
||||||
import com.maddyhome.idea.vim.command.SelectionType
|
import com.maddyhome.idea.vim.command.SelectionType
|
||||||
import com.maddyhome.idea.vim.common.TextRange
|
import com.maddyhome.idea.vim.common.TextRange
|
||||||
import com.maddyhome.idea.vim.group.MotionGroup
|
|
||||||
import com.maddyhome.idea.vim.helper.EditorHelper
|
import com.maddyhome.idea.vim.helper.EditorHelper
|
||||||
import com.maddyhome.idea.vim.helper.fileSize
|
import com.maddyhome.idea.vim.helper.fileSize
|
||||||
import com.maddyhome.idea.vim.listener.VimYankListener
|
import com.maddyhome.idea.vim.listener.VimYankListener
|
||||||
import com.maddyhome.idea.vim.newapi.ij
|
import com.maddyhome.idea.vim.newapi.ij
|
||||||
import com.maddyhome.idea.vim.newapi.vim
|
|
||||||
import com.maddyhome.idea.vim.yank.YankGroupBase
|
import com.maddyhome.idea.vim.yank.YankGroupBase
|
||||||
import org.jetbrains.annotations.Contract
|
import org.jetbrains.annotations.Contract
|
||||||
import kotlin.math.min
|
import kotlin.math.min
|
||||||
@@ -46,8 +43,8 @@ class YankGroup : YankGroupBase() {
|
|||||||
|
|
||||||
fun removeListener(listener: VimYankListener) = yankListeners.remove(listener)
|
fun removeListener(listener: VimYankListener) = yankListeners.remove(listener)
|
||||||
|
|
||||||
private fun notifyListeners(editor: Editor, textRange: TextRange) = yankListeners.forEach {
|
private fun notifyListeners(editor: VimEditor, textRange: TextRange) = yankListeners.forEach {
|
||||||
it.yankPerformed(editor, textRange)
|
it.yankPerformed(editor.ij, textRange)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -67,32 +64,38 @@ class YankGroup : YankGroupBase() {
|
|||||||
operatorArguments: OperatorArguments
|
operatorArguments: OperatorArguments
|
||||||
): Boolean {
|
): Boolean {
|
||||||
val motion = argument.motion
|
val motion = argument.motion
|
||||||
|
val type = if (motion.isLinewiseMotion()) SelectionType.LINE_WISE else SelectionType.CHARACTER_WISE
|
||||||
|
|
||||||
val caretModel = editor.ij.caretModel
|
val nativeCaretCount = editor.nativeCarets().size
|
||||||
if (caretModel.caretCount <= 0) return false
|
if (nativeCaretCount <= 0) return false
|
||||||
|
|
||||||
val ranges = ArrayList<Pair<Int, Int>>(caretModel.caretCount)
|
val carretToRange = HashMap<VimCaret, TextRange>(nativeCaretCount)
|
||||||
|
val ranges = ArrayList<Pair<Int, Int>>(nativeCaretCount)
|
||||||
|
|
||||||
// This logic is from original vim
|
// This logic is from original vim
|
||||||
val startOffsets =
|
val startOffsets = if (argument.motion.action is MotionDownLess1FirstNonSpaceAction) null else HashMap<VimCaret, Int>(nativeCaretCount)
|
||||||
if (argument.motion.action is MotionDownLess1FirstNonSpaceAction) null else HashMap<Caret, Int>(caretModel.caretCount)
|
|
||||||
|
|
||||||
for (caret in caretModel.allCarets) {
|
for (caret in editor.nativeCarets()) {
|
||||||
val motionRange = MotionGroup.getMotionRange(editor.ij, caret, context.ij, argument, operatorArguments)
|
val motionRange = injector.motion.getMotionRange(editor, caret, context, argument, operatorArguments)
|
||||||
?: continue
|
?: continue
|
||||||
|
|
||||||
assert(motionRange.size() == 1)
|
assert(motionRange.size() == 1)
|
||||||
ranges.add(motionRange.startOffset to motionRange.endOffset)
|
ranges.add(motionRange.startOffset to motionRange.endOffset)
|
||||||
startOffsets?.put(caret, motionRange.normalize().startOffset)
|
startOffsets?.put(caret, motionRange.normalize().startOffset)
|
||||||
|
carretToRange[caret] = TextRange(motionRange.startOffset, motionRange.endOffset)
|
||||||
}
|
}
|
||||||
|
|
||||||
val type = if (motion.isLinewiseMotion()) SelectionType.LINE_WISE else SelectionType.CHARACTER_WISE
|
|
||||||
val range = getTextRange(ranges, type) ?: return false
|
val range = getTextRange(ranges, type) ?: return false
|
||||||
|
|
||||||
if (range.size() == 0) return false
|
if (range.size() == 0) return false
|
||||||
|
|
||||||
val selectionType = if (type == SelectionType.CHARACTER_WISE && range.isMultiple) SelectionType.BLOCK_WISE else type
|
return yankRange(
|
||||||
return yankRange(editor.ij, range, selectionType, startOffsets)
|
editor,
|
||||||
|
carretToRange,
|
||||||
|
range,
|
||||||
|
type,
|
||||||
|
startOffsets
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -103,19 +106,21 @@ class YankGroup : YankGroupBase() {
|
|||||||
* @return true if able to yank the lines, false if not
|
* @return true if able to yank the lines, false if not
|
||||||
*/
|
*/
|
||||||
override fun yankLine(editor: VimEditor, count: Int): Boolean {
|
override fun yankLine(editor: VimEditor, count: Int): Boolean {
|
||||||
val caretModel = editor.ij.caretModel
|
val caretCount = editor.nativeCarets().size
|
||||||
val ranges = ArrayList<Pair<Int, Int>>(caretModel.caretCount)
|
val ranges = ArrayList<Pair<Int, Int>>(caretCount)
|
||||||
for (caret in caretModel.allCarets) {
|
val caretToRange = HashMap<VimCaret, TextRange>(caretCount)
|
||||||
val start = VimPlugin.getMotion().moveCaretToLineStart(editor, caret.vim)
|
for (caret in editor.nativeCarets()) {
|
||||||
val end = min(VimPlugin.getMotion().moveCaretToLineEndOffset(editor, caret.vim, count - 1, true) + 1, editor.fileSize().toInt())
|
val start = injector.motion.moveCaretToLineStart(editor, caret)
|
||||||
|
val end = min(injector.motion.moveCaretToLineEndOffset(editor, caret, count - 1, true) + 1, editor.fileSize().toInt())
|
||||||
|
|
||||||
if (end == -1) continue
|
if (end == -1) continue
|
||||||
|
|
||||||
ranges.add(start to end)
|
ranges.add(start to end)
|
||||||
|
caretToRange[caret] = TextRange(start, end)
|
||||||
}
|
}
|
||||||
|
|
||||||
val range = getTextRange(ranges, SelectionType.LINE_WISE) ?: return false
|
val range = getTextRange(ranges, SelectionType.LINE_WISE) ?: return false
|
||||||
return yankRange(editor.ij, range, SelectionType.LINE_WISE, null)
|
return yankRange(editor, caretToRange, range, SelectionType.LINE_WISE, null)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -129,6 +134,7 @@ class YankGroup : YankGroupBase() {
|
|||||||
override fun yankRange(editor: VimEditor, range: TextRange?, type: SelectionType, moveCursor: Boolean): Boolean {
|
override fun yankRange(editor: VimEditor, range: TextRange?, type: SelectionType, moveCursor: Boolean): Boolean {
|
||||||
range ?: return false
|
range ?: return false
|
||||||
|
|
||||||
|
val caretToRange = HashMap<VimCaret, TextRange>()
|
||||||
val selectionType = if (type == SelectionType.CHARACTER_WISE && range.isMultiple) SelectionType.BLOCK_WISE else type
|
val selectionType = if (type == SelectionType.CHARACTER_WISE && range.isMultiple) SelectionType.BLOCK_WISE else type
|
||||||
|
|
||||||
if (type == SelectionType.LINE_WISE) {
|
if (type == SelectionType.LINE_WISE) {
|
||||||
@@ -143,24 +149,25 @@ class YankGroup : YankGroupBase() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val caretModel = editor.ij.caretModel
|
|
||||||
val rangeStartOffsets = range.startOffsets
|
val rangeStartOffsets = range.startOffsets
|
||||||
val rangeEndOffsets = range.endOffsets
|
val rangeEndOffsets = range.endOffsets
|
||||||
|
|
||||||
return if (moveCursor) {
|
val startOffsets = HashMap<VimCaret, Int>(editor.nativeCarets().size)
|
||||||
val startOffsets = HashMap<Caret, Int>(caretModel.caretCount)
|
|
||||||
if (type == SelectionType.BLOCK_WISE) {
|
if (type == SelectionType.BLOCK_WISE) {
|
||||||
startOffsets[caretModel.primaryCaret] = range.normalize().startOffset
|
startOffsets[editor.primaryCaret()] = range.normalize().startOffset
|
||||||
|
caretToRange[editor.primaryCaret()] = range
|
||||||
} else {
|
} else {
|
||||||
val carets = caretModel.allCarets
|
for ((i, caret) in editor.nativeCarets().withIndex()) {
|
||||||
for (i in carets.indices) {
|
val textRange = TextRange(rangeStartOffsets[i], rangeEndOffsets[i])
|
||||||
startOffsets[carets[i]] = TextRange(rangeStartOffsets[i], rangeEndOffsets[i]).normalize().startOffset
|
startOffsets[caret] = textRange.normalize().startOffset
|
||||||
|
caretToRange[caret] = textRange
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
yankRange(editor.ij, range, selectionType, startOffsets)
|
return if (moveCursor) {
|
||||||
|
yankRange(editor, caretToRange, range, selectionType, startOffsets)
|
||||||
} else {
|
} else {
|
||||||
yankRange(editor.ij, range, selectionType, null)
|
yankRange(editor, caretToRange, range, selectionType, null)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -192,15 +199,20 @@ class YankGroup : YankGroupBase() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun yankRange(
|
private fun yankRange(
|
||||||
editor: Editor,
|
editor: VimEditor,
|
||||||
|
caretToRange: Map<VimCaret, TextRange>,
|
||||||
range: TextRange,
|
range: TextRange,
|
||||||
type: SelectionType,
|
type: SelectionType,
|
||||||
startOffsets: Map<Caret, Int>?,
|
startOffsets: Map<VimCaret, Int>?,
|
||||||
): Boolean {
|
): Boolean {
|
||||||
startOffsets?.forEach { (caret, offset) -> MotionGroup.moveCaret(editor, caret, offset) }
|
startOffsets?.forEach { (caret, offset) -> injector.motion.moveCaret(editor, caret, offset) }
|
||||||
|
|
||||||
notifyListeners(editor, range)
|
notifyListeners(editor, range)
|
||||||
|
|
||||||
return VimPlugin.getRegister().storeText(editor.vim, range, type, false)
|
var result = true
|
||||||
|
for ((caret, myRange) in caretToRange) {
|
||||||
|
result = caret.registerStorage.storeText(editor, myRange, type, false) && result
|
||||||
|
}
|
||||||
|
return result
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -23,9 +23,9 @@ import com.intellij.openapi.diagnostic.trace
|
|||||||
import com.intellij.openapi.editor.Editor
|
import com.intellij.openapi.editor.Editor
|
||||||
import com.maddyhome.idea.vim.KeyHandler
|
import com.maddyhome.idea.vim.KeyHandler
|
||||||
import com.maddyhome.idea.vim.VimPlugin
|
import com.maddyhome.idea.vim.VimPlugin
|
||||||
import com.maddyhome.idea.vim.command.CommandState
|
import com.maddyhome.idea.vim.command.VimStateMachine
|
||||||
import com.maddyhome.idea.vim.helper.EditorDataContext
|
import com.maddyhome.idea.vim.helper.EditorDataContext
|
||||||
import com.maddyhome.idea.vim.helper.commandState
|
import com.maddyhome.idea.vim.helper.editorMode
|
||||||
import com.maddyhome.idea.vim.helper.exitSelectMode
|
import com.maddyhome.idea.vim.helper.exitSelectMode
|
||||||
import com.maddyhome.idea.vim.helper.exitVisualMode
|
import com.maddyhome.idea.vim.helper.exitVisualMode
|
||||||
import com.maddyhome.idea.vim.helper.hasVisualSelection
|
import com.maddyhome.idea.vim.helper.hasVisualSelection
|
||||||
@@ -35,8 +35,8 @@ import com.maddyhome.idea.vim.helper.inSelectMode
|
|||||||
import com.maddyhome.idea.vim.helper.inVisualMode
|
import com.maddyhome.idea.vim.helper.inVisualMode
|
||||||
import com.maddyhome.idea.vim.helper.isIdeaVimDisabledHere
|
import com.maddyhome.idea.vim.helper.isIdeaVimDisabledHere
|
||||||
import com.maddyhome.idea.vim.helper.isTemplateActive
|
import com.maddyhome.idea.vim.helper.isTemplateActive
|
||||||
import com.maddyhome.idea.vim.helper.mode
|
|
||||||
import com.maddyhome.idea.vim.helper.popAllModes
|
import com.maddyhome.idea.vim.helper.popAllModes
|
||||||
|
import com.maddyhome.idea.vim.helper.vimStateMachine
|
||||||
import com.maddyhome.idea.vim.listener.VimListenerManager
|
import com.maddyhome.idea.vim.listener.VimListenerManager
|
||||||
import com.maddyhome.idea.vim.newapi.IjVimEditor
|
import com.maddyhome.idea.vim.newapi.IjVimEditor
|
||||||
import com.maddyhome.idea.vim.newapi.vim
|
import com.maddyhome.idea.vim.newapi.vim
|
||||||
@@ -58,7 +58,7 @@ object IdeaSelectionControl {
|
|||||||
editor: Editor,
|
editor: Editor,
|
||||||
selectionSource: VimListenerManager.SelectionSource = VimListenerManager.SelectionSource.OTHER,
|
selectionSource: VimListenerManager.SelectionSource = VimListenerManager.SelectionSource.OTHER,
|
||||||
) {
|
) {
|
||||||
VimVisualTimer.singleTask(editor.mode) { initialMode ->
|
VimVisualTimer.singleTask(editor.editorMode) { initialMode ->
|
||||||
|
|
||||||
if (editor.isIdeaVimDisabledHere) return@singleTask
|
if (editor.isIdeaVimDisabledHere) return@singleTask
|
||||||
|
|
||||||
@@ -80,13 +80,13 @@ object IdeaSelectionControl {
|
|||||||
return@singleTask
|
return@singleTask
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.debug("Some carets have selection. State before adjustment: ${editor.vim.commandState.toSimpleString()}")
|
logger.debug("Some carets have selection. State before adjustment: ${editor.vim.vimStateMachine.toSimpleString()}")
|
||||||
|
|
||||||
editor.popAllModes()
|
editor.popAllModes()
|
||||||
|
|
||||||
activateMode(editor, chooseSelectionMode(editor, selectionSource, true))
|
activateMode(editor, chooseSelectionMode(editor, selectionSource, true))
|
||||||
} else {
|
} else {
|
||||||
logger.debug("None of carets have selection. State before adjustment: ${editor.vim.commandState.toSimpleString()}")
|
logger.debug("None of carets have selection. State before adjustment: ${editor.vim.vimStateMachine.toSimpleString()}")
|
||||||
if (editor.inVisualMode) editor.exitVisualMode()
|
if (editor.inVisualMode) editor.exitVisualMode()
|
||||||
if (editor.inSelectMode) editor.exitSelectMode(false)
|
if (editor.inSelectMode) editor.exitSelectMode(false)
|
||||||
|
|
||||||
@@ -96,7 +96,7 @@ object IdeaSelectionControl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
KeyHandler.getInstance().reset(editor.vim)
|
KeyHandler.getInstance().reset(editor.vim)
|
||||||
logger.debug("${editor.mode} is enabled")
|
logger.debug("${editor.editorMode} is enabled")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -110,68 +110,68 @@ object IdeaSelectionControl {
|
|||||||
* This method is created to improve user experience. It allows avoiding delay in some operations
|
* This method is created to improve user experience. It allows avoiding delay in some operations
|
||||||
* (because [controlNonVimSelectionChange] is not executed immediately)
|
* (because [controlNonVimSelectionChange] is not executed immediately)
|
||||||
*/
|
*/
|
||||||
fun predictMode(editor: Editor, selectionSource: VimListenerManager.SelectionSource): CommandState.Mode {
|
fun predictMode(editor: Editor, selectionSource: VimListenerManager.SelectionSource): VimStateMachine.Mode {
|
||||||
if (editor.selectionModel.hasSelection(true)) {
|
if (editor.selectionModel.hasSelection(true)) {
|
||||||
if (dontChangeMode(editor)) return editor.mode
|
if (dontChangeMode(editor)) return editor.editorMode
|
||||||
return chooseSelectionMode(editor, selectionSource, false)
|
return chooseSelectionMode(editor, selectionSource, false)
|
||||||
} else {
|
} else {
|
||||||
return chooseNonSelectionMode(editor)
|
return chooseNonSelectionMode(editor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun activateMode(editor: Editor, mode: CommandState.Mode) {
|
private fun activateMode(editor: Editor, mode: VimStateMachine.Mode) {
|
||||||
when (mode) {
|
when (mode) {
|
||||||
CommandState.Mode.VISUAL -> VimPlugin.getVisualMotion()
|
VimStateMachine.Mode.VISUAL -> VimPlugin.getVisualMotion()
|
||||||
.enterVisualMode(editor.vim, VimPlugin.getVisualMotion().autodetectVisualSubmode(editor.vim))
|
.enterVisualMode(editor.vim, VimPlugin.getVisualMotion().autodetectVisualSubmode(editor.vim))
|
||||||
CommandState.Mode.SELECT -> VimPlugin.getVisualMotion()
|
VimStateMachine.Mode.SELECT -> VimPlugin.getVisualMotion()
|
||||||
.enterSelectMode(editor.vim, VimPlugin.getVisualMotion().autodetectVisualSubmode(editor.vim))
|
.enterSelectMode(editor.vim, VimPlugin.getVisualMotion().autodetectVisualSubmode(editor.vim))
|
||||||
CommandState.Mode.INSERT -> VimPlugin.getChange().insertBeforeCursor(
|
VimStateMachine.Mode.INSERT -> VimPlugin.getChange().insertBeforeCursor(
|
||||||
editor.vim,
|
editor.vim,
|
||||||
EditorDataContext.init(editor).vim
|
EditorDataContext.init(editor).vim
|
||||||
)
|
)
|
||||||
CommandState.Mode.COMMAND -> Unit
|
VimStateMachine.Mode.COMMAND -> Unit
|
||||||
else -> error("Unexpected mode: $mode")
|
else -> error("Unexpected mode: $mode")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun dontChangeMode(editor: Editor): Boolean =
|
private fun dontChangeMode(editor: Editor): Boolean =
|
||||||
editor.isTemplateActive() && (IdeaRefactorModeHelper.keepMode() || editor.mode.hasVisualSelection)
|
editor.isTemplateActive() && (IdeaRefactorModeHelper.keepMode() || editor.editorMode.hasVisualSelection)
|
||||||
|
|
||||||
private fun chooseNonSelectionMode(editor: Editor): CommandState.Mode {
|
private fun chooseNonSelectionMode(editor: Editor): VimStateMachine.Mode {
|
||||||
val templateActive = editor.isTemplateActive()
|
val templateActive = editor.isTemplateActive()
|
||||||
if (templateActive && editor.inNormalMode || editor.inInsertMode) {
|
if (templateActive && editor.inNormalMode || editor.inInsertMode) {
|
||||||
return CommandState.Mode.INSERT
|
return VimStateMachine.Mode.INSERT
|
||||||
}
|
}
|
||||||
return CommandState.Mode.COMMAND
|
return VimStateMachine.Mode.COMMAND
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun chooseSelectionMode(
|
private fun chooseSelectionMode(
|
||||||
editor: Editor,
|
editor: Editor,
|
||||||
selectionSource: VimListenerManager.SelectionSource,
|
selectionSource: VimListenerManager.SelectionSource,
|
||||||
logReason: Boolean,
|
logReason: Boolean,
|
||||||
): CommandState.Mode {
|
): VimStateMachine.Mode {
|
||||||
val selectmode = (VimPlugin.getOptionService().getOptionValue(OptionScope.LOCAL(IjVimEditor(editor)), OptionConstants.selectmodeName) as VimString).value
|
val selectmode = (VimPlugin.getOptionService().getOptionValue(OptionScope.LOCAL(IjVimEditor(editor)), OptionConstants.selectmodeName) as VimString).value
|
||||||
return when {
|
return when {
|
||||||
editor.isOneLineMode -> {
|
editor.isOneLineMode -> {
|
||||||
if (logReason) logger.debug("Enter select mode. Reason: one line mode")
|
if (logReason) logger.debug("Enter select mode. Reason: one line mode")
|
||||||
CommandState.Mode.SELECT
|
VimStateMachine.Mode.SELECT
|
||||||
}
|
}
|
||||||
selectionSource == VimListenerManager.SelectionSource.MOUSE && OptionConstants.selectmode_mouse in selectmode -> {
|
selectionSource == VimListenerManager.SelectionSource.MOUSE && OptionConstants.selectmode_mouse in selectmode -> {
|
||||||
if (logReason) logger.debug("Enter select mode. Selection source is mouse and selectMode option has mouse")
|
if (logReason) logger.debug("Enter select mode. Selection source is mouse and selectMode option has mouse")
|
||||||
CommandState.Mode.SELECT
|
VimStateMachine.Mode.SELECT
|
||||||
}
|
}
|
||||||
editor.isTemplateActive() && IdeaRefactorModeHelper.selectMode() -> {
|
editor.isTemplateActive() && IdeaRefactorModeHelper.selectMode() -> {
|
||||||
if (logReason) logger.debug("Enter select mode. Template is active and selectMode has template")
|
if (logReason) logger.debug("Enter select mode. Template is active and selectMode has template")
|
||||||
CommandState.Mode.SELECT
|
VimStateMachine.Mode.SELECT
|
||||||
}
|
}
|
||||||
selectionSource == VimListenerManager.SelectionSource.OTHER &&
|
selectionSource == VimListenerManager.SelectionSource.OTHER &&
|
||||||
OptionConstants.selectmode_ideaselection in (VimPlugin.getOptionService().getOptionValue(OptionScope.GLOBAL, OptionConstants.selectmodeName) as VimString).value -> {
|
OptionConstants.selectmode_ideaselection in (VimPlugin.getOptionService().getOptionValue(OptionScope.GLOBAL, OptionConstants.selectmodeName) as VimString).value -> {
|
||||||
if (logReason) logger.debug("Enter select mode. Selection source is OTHER and selectMode has refactoring")
|
if (logReason) logger.debug("Enter select mode. Selection source is OTHER and selectMode has refactoring")
|
||||||
CommandState.Mode.SELECT
|
VimStateMachine.Mode.SELECT
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
if (logReason) logger.debug("Enter visual mode")
|
if (logReason) logger.debug("Enter visual mode")
|
||||||
CommandState.Mode.VISUAL
|
VimStateMachine.Mode.VISUAL
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -19,7 +19,7 @@
|
|||||||
package com.maddyhome.idea.vim.group.visual
|
package com.maddyhome.idea.vim.group.visual
|
||||||
|
|
||||||
import com.maddyhome.idea.vim.VimPlugin
|
import com.maddyhome.idea.vim.VimPlugin
|
||||||
import com.maddyhome.idea.vim.command.CommandState
|
import com.maddyhome.idea.vim.command.VimStateMachine
|
||||||
import com.maddyhome.idea.vim.group.visual.VimVisualTimer.mode
|
import com.maddyhome.idea.vim.group.visual.VimVisualTimer.mode
|
||||||
import com.maddyhome.idea.vim.group.visual.VimVisualTimer.singleTask
|
import com.maddyhome.idea.vim.group.visual.VimVisualTimer.singleTask
|
||||||
import com.maddyhome.idea.vim.options.OptionScope
|
import com.maddyhome.idea.vim.options.OptionScope
|
||||||
@@ -66,9 +66,9 @@ import javax.swing.Timer
|
|||||||
object VimVisualTimer {
|
object VimVisualTimer {
|
||||||
|
|
||||||
var swingTimer: Timer? = null
|
var swingTimer: Timer? = null
|
||||||
var mode: CommandState.Mode? = null
|
var mode: VimStateMachine.Mode? = null
|
||||||
|
|
||||||
inline fun singleTask(currentMode: CommandState.Mode, crossinline task: (initialMode: CommandState.Mode?) -> Unit) {
|
inline fun singleTask(currentMode: VimStateMachine.Mode, crossinline task: (initialMode: VimStateMachine.Mode?) -> Unit) {
|
||||||
swingTimer?.stop()
|
swingTimer?.stop()
|
||||||
|
|
||||||
if (mode == null) mode = currentMode
|
if (mode == null) mode = currentMode
|
||||||
@@ -92,7 +92,7 @@ object VimVisualTimer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline fun timerAction(task: (initialMode: CommandState.Mode?) -> Unit) {
|
inline fun timerAction(task: (initialMode: VimStateMachine.Mode?) -> Unit) {
|
||||||
task(mode)
|
task(mode)
|
||||||
swingTimer = null
|
swingTimer = null
|
||||||
mode = null
|
mode = null
|
||||||
|
@@ -23,13 +23,13 @@ import com.intellij.openapi.editor.Editor
|
|||||||
import com.intellij.openapi.editor.VisualPosition
|
import com.intellij.openapi.editor.VisualPosition
|
||||||
import com.maddyhome.idea.vim.VimPlugin
|
import com.maddyhome.idea.vim.VimPlugin
|
||||||
import com.maddyhome.idea.vim.api.VimMotionGroupBase
|
import com.maddyhome.idea.vim.api.VimMotionGroupBase
|
||||||
import com.maddyhome.idea.vim.command.CommandState
|
import com.maddyhome.idea.vim.command.VimStateMachine
|
||||||
import com.maddyhome.idea.vim.helper.EditorHelper
|
import com.maddyhome.idea.vim.helper.EditorHelper
|
||||||
|
import com.maddyhome.idea.vim.helper.editorMode
|
||||||
import com.maddyhome.idea.vim.helper.inBlockSubMode
|
import com.maddyhome.idea.vim.helper.inBlockSubMode
|
||||||
import com.maddyhome.idea.vim.helper.inSelectMode
|
import com.maddyhome.idea.vim.helper.inSelectMode
|
||||||
import com.maddyhome.idea.vim.helper.inVisualMode
|
import com.maddyhome.idea.vim.helper.inVisualMode
|
||||||
import com.maddyhome.idea.vim.helper.isEndAllowed
|
import com.maddyhome.idea.vim.helper.isEndAllowed
|
||||||
import com.maddyhome.idea.vim.helper.mode
|
|
||||||
import com.maddyhome.idea.vim.helper.moveToInlayAwareOffset
|
import com.maddyhome.idea.vim.helper.moveToInlayAwareOffset
|
||||||
import com.maddyhome.idea.vim.helper.subMode
|
import com.maddyhome.idea.vim.helper.subMode
|
||||||
import com.maddyhome.idea.vim.helper.updateCaretsVisualAttributes
|
import com.maddyhome.idea.vim.helper.updateCaretsVisualAttributes
|
||||||
@@ -108,7 +108,7 @@ val Caret.vimLeadSelectionOffset: Int
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return if (editor.subMode == CommandState.SubMode.VISUAL_LINE) {
|
return if (editor.subMode == VimStateMachine.SubMode.VISUAL_LINE) {
|
||||||
val selectionStartLine = editor.offsetToLogicalPosition(selectionStart).line
|
val selectionStartLine = editor.offsetToLogicalPosition(selectionStart).line
|
||||||
val caretLine = editor.offsetToLogicalPosition(this.offset).line
|
val caretLine = editor.offsetToLogicalPosition(this.offset).line
|
||||||
if (caretLine == selectionStartLine) {
|
if (caretLine == selectionStartLine) {
|
||||||
@@ -132,8 +132,8 @@ val Caret.vimLeadSelectionOffset: Int
|
|||||||
return caretOffset
|
return caretOffset
|
||||||
}
|
}
|
||||||
|
|
||||||
fun moveCaretOneCharLeftFromSelectionEnd(editor: Editor, predictedMode: CommandState.Mode) {
|
fun moveCaretOneCharLeftFromSelectionEnd(editor: Editor, predictedMode: VimStateMachine.Mode) {
|
||||||
if (predictedMode != CommandState.Mode.VISUAL) {
|
if (predictedMode != VimStateMachine.Mode.VISUAL) {
|
||||||
if (!predictedMode.isEndAllowed) {
|
if (!predictedMode.isEndAllowed) {
|
||||||
editor.caretModel.allCarets.forEach { caret ->
|
editor.caretModel.allCarets.forEach { caret ->
|
||||||
val lineEnd = EditorHelper.getLineEndForOffset(editor, caret.offset)
|
val lineEnd = EditorHelper.getLineEndForOffset(editor, caret.offset)
|
||||||
@@ -161,18 +161,18 @@ private fun setVisualSelection(selectionStart: Int, selectionEnd: Int, caret: Ca
|
|||||||
val (start, end) = if (selectionStart > selectionEnd) selectionEnd to selectionStart else selectionStart to selectionEnd
|
val (start, end) = if (selectionStart > selectionEnd) selectionEnd to selectionStart else selectionStart to selectionEnd
|
||||||
val editor = caret.editor
|
val editor = caret.editor
|
||||||
val subMode = editor.subMode
|
val subMode = editor.subMode
|
||||||
val mode = editor.mode
|
val mode = editor.editorMode
|
||||||
val vimEditor = IjVimEditor(editor)
|
val vimEditor = IjVimEditor(editor)
|
||||||
when (subMode) {
|
when (subMode) {
|
||||||
CommandState.SubMode.VISUAL_CHARACTER -> {
|
VimStateMachine.SubMode.VISUAL_CHARACTER -> {
|
||||||
val (nativeStart, nativeEnd) = charToNativeSelection(vimEditor, start, end, mode)
|
val (nativeStart, nativeEnd) = charToNativeSelection(vimEditor, start, end, mode)
|
||||||
caret.vimSetSystemSelectionSilently(nativeStart, nativeEnd)
|
caret.vimSetSystemSelectionSilently(nativeStart, nativeEnd)
|
||||||
}
|
}
|
||||||
CommandState.SubMode.VISUAL_LINE -> {
|
VimStateMachine.SubMode.VISUAL_LINE -> {
|
||||||
val (nativeStart, nativeEnd) = lineToNativeSelection(vimEditor, start, end)
|
val (nativeStart, nativeEnd) = lineToNativeSelection(vimEditor, start, end)
|
||||||
caret.vimSetSystemSelectionSilently(nativeStart, nativeEnd)
|
caret.vimSetSystemSelectionSilently(nativeStart, nativeEnd)
|
||||||
}
|
}
|
||||||
CommandState.SubMode.VISUAL_BLOCK -> {
|
VimStateMachine.SubMode.VISUAL_BLOCK -> {
|
||||||
editor.caretModel.removeSecondaryCarets()
|
editor.caretModel.removeSecondaryCarets()
|
||||||
|
|
||||||
// Set system selection
|
// Set system selection
|
||||||
@@ -200,7 +200,7 @@ private fun setVisualSelection(selectionStart: Int, selectionEnd: Int, caret: Ca
|
|||||||
// Put right caret position for tab character
|
// Put right caret position for tab character
|
||||||
aCaret.moveToVisualPosition(visualPosition)
|
aCaret.moveToVisualPosition(visualPosition)
|
||||||
}
|
}
|
||||||
if (mode != CommandState.Mode.SELECT &&
|
if (mode != VimStateMachine.Mode.SELECT &&
|
||||||
!EditorHelper.isLineEmpty(editor, line, false) &&
|
!EditorHelper.isLineEmpty(editor, line, false) &&
|
||||||
aCaret.offset == aCaret.selectionEnd &&
|
aCaret.offset == aCaret.selectionEnd &&
|
||||||
aCaret.selectionEnd - 1 >= lineStartOffset &&
|
aCaret.selectionEnd - 1 >= lineStartOffset &&
|
||||||
|
@@ -19,22 +19,34 @@
|
|||||||
package com.maddyhome.idea.vim.group.visual
|
package com.maddyhome.idea.vim.group.visual
|
||||||
|
|
||||||
import com.intellij.find.FindManager
|
import com.intellij.find.FindManager
|
||||||
|
import com.intellij.openapi.editor.Editor
|
||||||
import com.maddyhome.idea.vim.api.VimEditor
|
import com.maddyhome.idea.vim.api.VimEditor
|
||||||
import com.maddyhome.idea.vim.api.VimVisualMotionGroupBase
|
import com.maddyhome.idea.vim.api.VimVisualMotionGroupBase
|
||||||
import com.maddyhome.idea.vim.command.CommandState
|
import com.maddyhome.idea.vim.command.CommandState
|
||||||
|
import com.maddyhome.idea.vim.command.VimStateMachine
|
||||||
|
import com.maddyhome.idea.vim.command.engine
|
||||||
import com.maddyhome.idea.vim.newapi.ij
|
import com.maddyhome.idea.vim.newapi.ij
|
||||||
|
import com.maddyhome.idea.vim.newapi.vim
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Alex Plate
|
* @author Alex Plate
|
||||||
*/
|
*/
|
||||||
class VisualMotionGroup : VimVisualMotionGroupBase() {
|
class VisualMotionGroup : VimVisualMotionGroupBase() {
|
||||||
override fun autodetectVisualSubmode(editor: VimEditor): CommandState.SubMode {
|
override fun autodetectVisualSubmode(editor: VimEditor): VimStateMachine.SubMode {
|
||||||
// IJ specific. See https://youtrack.jetbrains.com/issue/VIM-1924.
|
// IJ specific. See https://youtrack.jetbrains.com/issue/VIM-1924.
|
||||||
val project = editor.ij.project
|
val project = editor.ij.project
|
||||||
if (project != null && FindManager.getInstance(project).selectNextOccurrenceWasPerformed()) {
|
if (project != null && FindManager.getInstance(project).selectNextOccurrenceWasPerformed()) {
|
||||||
return CommandState.SubMode.VISUAL_CHARACTER
|
return VimStateMachine.SubMode.VISUAL_CHARACTER
|
||||||
}
|
}
|
||||||
|
|
||||||
return super.autodetectVisualSubmode(editor)
|
return super.autodetectVisualSubmode(editor)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* COMPATIBILITY-LAYER: Added a method
|
||||||
|
* Please see: https://jb.gg/zo8n0r
|
||||||
|
*/
|
||||||
|
fun enterVisualMode(editor: Editor, subMode: CommandState.SubMode? = null): Boolean {
|
||||||
|
return this.enterVisualMode(editor.vim, subMode?.engine)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -21,7 +21,7 @@ package com.maddyhome.idea.vim.handler
|
|||||||
import com.intellij.serviceContainer.BaseKeyedLazyInstance
|
import com.intellij.serviceContainer.BaseKeyedLazyInstance
|
||||||
import com.intellij.util.SmartList
|
import com.intellij.util.SmartList
|
||||||
import com.intellij.util.xmlb.annotations.Attribute
|
import com.intellij.util.xmlb.annotations.Attribute
|
||||||
import com.maddyhome.idea.vim.common.MappingMode
|
import com.maddyhome.idea.vim.command.MappingMode
|
||||||
import javax.swing.KeyStroke
|
import javax.swing.KeyStroke
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -23,7 +23,7 @@ import com.intellij.openapi.editor.CaretVisualAttributes
|
|||||||
import com.intellij.openapi.editor.Editor
|
import com.intellij.openapi.editor.Editor
|
||||||
import com.intellij.openapi.editor.ex.EditorEx
|
import com.intellij.openapi.editor.ex.EditorEx
|
||||||
import com.intellij.openapi.editor.ex.EditorSettingsExternalizable
|
import com.intellij.openapi.editor.ex.EditorSettingsExternalizable
|
||||||
import com.maddyhome.idea.vim.command.CommandState
|
import com.maddyhome.idea.vim.command.VimStateMachine
|
||||||
import com.maddyhome.idea.vim.newapi.vim
|
import com.maddyhome.idea.vim.newapi.vim
|
||||||
import com.maddyhome.idea.vim.options.OptionChangeListener
|
import com.maddyhome.idea.vim.options.OptionChangeListener
|
||||||
import com.maddyhome.idea.vim.options.helpers.GuiCursorMode
|
import com.maddyhome.idea.vim.options.helpers.GuiCursorMode
|
||||||
@@ -75,7 +75,7 @@ object GuicursorChangeListener : OptionChangeListener<VimDataType> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun Editor.guicursorMode(): GuiCursorMode {
|
private fun Editor.guicursorMode(): GuiCursorMode {
|
||||||
if (this.vim.commandState.isReplaceCharacter) {
|
if (this.vim.vimStateMachine.isReplaceCharacter) {
|
||||||
// Can be true for NORMAL and VISUAL
|
// Can be true for NORMAL and VISUAL
|
||||||
return GuiCursorMode.REPLACE
|
return GuiCursorMode.REPLACE
|
||||||
}
|
}
|
||||||
@@ -84,18 +84,18 @@ private fun Editor.guicursorMode(): GuiCursorMode {
|
|||||||
// makes much more use of SELECT than Vim does (e.g. it's the default for idearefactormode) so it makes sense for us
|
// makes much more use of SELECT than Vim does (e.g. it's the default for idearefactormode) so it makes sense for us
|
||||||
// to more visually distinguish VISUAL and SELECT. So we use INSERT; a selection and the insert caret is intuitively
|
// to more visually distinguish VISUAL and SELECT. So we use INSERT; a selection and the insert caret is intuitively
|
||||||
// the same as SELECT
|
// the same as SELECT
|
||||||
return when (mode) {
|
return when (editorMode) {
|
||||||
CommandState.Mode.COMMAND -> GuiCursorMode.NORMAL
|
VimStateMachine.Mode.COMMAND -> GuiCursorMode.NORMAL
|
||||||
CommandState.Mode.VISUAL -> GuiCursorMode.VISUAL // TODO: VISUAL_EXCLUSIVE
|
VimStateMachine.Mode.VISUAL -> GuiCursorMode.VISUAL // TODO: VISUAL_EXCLUSIVE
|
||||||
CommandState.Mode.SELECT -> GuiCursorMode.INSERT
|
VimStateMachine.Mode.SELECT -> GuiCursorMode.INSERT
|
||||||
CommandState.Mode.INSERT -> GuiCursorMode.INSERT
|
VimStateMachine.Mode.INSERT -> GuiCursorMode.INSERT
|
||||||
CommandState.Mode.OP_PENDING -> GuiCursorMode.OP_PENDING
|
VimStateMachine.Mode.OP_PENDING -> GuiCursorMode.OP_PENDING
|
||||||
CommandState.Mode.REPLACE -> GuiCursorMode.REPLACE
|
VimStateMachine.Mode.REPLACE -> GuiCursorMode.REPLACE
|
||||||
// This doesn't handle ci and cr, but we don't care - our CMD_LINE will never call this
|
// This doesn't handle ci and cr, but we don't care - our CMD_LINE will never call this
|
||||||
CommandState.Mode.CMD_LINE -> GuiCursorMode.CMD_LINE
|
VimStateMachine.Mode.CMD_LINE -> GuiCursorMode.CMD_LINE
|
||||||
CommandState.Mode.INSERT_NORMAL -> GuiCursorMode.NORMAL
|
VimStateMachine.Mode.INSERT_NORMAL -> GuiCursorMode.NORMAL
|
||||||
CommandState.Mode.INSERT_VISUAL -> GuiCursorMode.VISUAL
|
VimStateMachine.Mode.INSERT_VISUAL -> GuiCursorMode.VISUAL
|
||||||
CommandState.Mode.INSERT_SELECT -> GuiCursorMode.INSERT
|
VimStateMachine.Mode.INSERT_SELECT -> GuiCursorMode.INSERT
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -34,7 +34,7 @@ class CommandLineHelper : VimCommandLineHelper {
|
|||||||
|
|
||||||
override fun inputString(vimEditor: VimEditor, prompt: String, finishOn: Char?): String? {
|
override fun inputString(vimEditor: VimEditor, prompt: String, finishOn: Char?): String? {
|
||||||
val editor = vimEditor.ij
|
val editor = vimEditor.ij
|
||||||
if (vimEditor.commandState.isDotRepeatInProgress) {
|
if (vimEditor.vimStateMachine.isDotRepeatInProgress) {
|
||||||
val input = Extension.consumeString()
|
val input = Extension.consumeString()
|
||||||
return input ?: error("Not enough strings saved: ${Extension.lastExtensionHandler}")
|
return input ?: error("Not enough strings saved: ${Extension.lastExtensionHandler}")
|
||||||
}
|
}
|
||||||
|
@@ -23,89 +23,106 @@ package com.maddyhome.idea.vim.helper
|
|||||||
import com.intellij.openapi.editor.Editor
|
import com.intellij.openapi.editor.Editor
|
||||||
import com.maddyhome.idea.vim.api.VimEditor
|
import com.maddyhome.idea.vim.api.VimEditor
|
||||||
import com.maddyhome.idea.vim.command.CommandState
|
import com.maddyhome.idea.vim.command.CommandState
|
||||||
|
import com.maddyhome.idea.vim.command.VimStateMachine
|
||||||
|
import com.maddyhome.idea.vim.command.engine
|
||||||
|
import com.maddyhome.idea.vim.command.ij
|
||||||
import com.maddyhome.idea.vim.newapi.vim
|
import com.maddyhome.idea.vim.newapi.vim
|
||||||
|
|
||||||
val Editor.isEndAllowed: Boolean
|
val Editor.isEndAllowed: Boolean
|
||||||
get() = when (this.mode) {
|
get() = when (this.editorMode) {
|
||||||
CommandState.Mode.INSERT, CommandState.Mode.VISUAL, CommandState.Mode.SELECT, CommandState.Mode.INSERT_VISUAL, CommandState.Mode.INSERT_SELECT -> true
|
VimStateMachine.Mode.INSERT, VimStateMachine.Mode.VISUAL, VimStateMachine.Mode.SELECT, VimStateMachine.Mode.INSERT_VISUAL, VimStateMachine.Mode.INSERT_SELECT -> true
|
||||||
CommandState.Mode.COMMAND, CommandState.Mode.CMD_LINE, CommandState.Mode.REPLACE, CommandState.Mode.OP_PENDING, CommandState.Mode.INSERT_NORMAL -> {
|
VimStateMachine.Mode.COMMAND, VimStateMachine.Mode.CMD_LINE, VimStateMachine.Mode.REPLACE, VimStateMachine.Mode.OP_PENDING, VimStateMachine.Mode.INSERT_NORMAL -> {
|
||||||
// One day we'll use a proper insert_normal mode
|
// One day we'll use a proper insert_normal mode
|
||||||
if (this.mode.inSingleMode) true else usesVirtualSpace
|
if (this.editorMode.inSingleMode) true else usesVirtualSpace
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val CommandState.Mode.isEndAllowedIgnoringOnemore: Boolean
|
val VimStateMachine.Mode.isEndAllowedIgnoringOnemore: Boolean
|
||||||
get() = when (this) {
|
get() = when (this) {
|
||||||
CommandState.Mode.INSERT, CommandState.Mode.VISUAL, CommandState.Mode.SELECT -> true
|
VimStateMachine.Mode.INSERT, VimStateMachine.Mode.VISUAL, VimStateMachine.Mode.SELECT -> true
|
||||||
CommandState.Mode.COMMAND, CommandState.Mode.CMD_LINE, CommandState.Mode.REPLACE, CommandState.Mode.OP_PENDING -> false
|
VimStateMachine.Mode.COMMAND, VimStateMachine.Mode.CMD_LINE, VimStateMachine.Mode.REPLACE, VimStateMachine.Mode.OP_PENDING -> false
|
||||||
CommandState.Mode.INSERT_NORMAL -> false
|
VimStateMachine.Mode.INSERT_NORMAL -> false
|
||||||
CommandState.Mode.INSERT_VISUAL -> true
|
VimStateMachine.Mode.INSERT_VISUAL -> true
|
||||||
CommandState.Mode.INSERT_SELECT -> true
|
VimStateMachine.Mode.INSERT_SELECT -> true
|
||||||
}
|
}
|
||||||
|
|
||||||
val CommandState.Mode.hasVisualSelection
|
val VimStateMachine.Mode.hasVisualSelection
|
||||||
get() = when (this) {
|
get() = when (this) {
|
||||||
CommandState.Mode.VISUAL, CommandState.Mode.SELECT -> true
|
VimStateMachine.Mode.VISUAL, VimStateMachine.Mode.SELECT -> true
|
||||||
CommandState.Mode.REPLACE, CommandState.Mode.CMD_LINE, CommandState.Mode.COMMAND, CommandState.Mode.INSERT, CommandState.Mode.OP_PENDING -> false
|
VimStateMachine.Mode.REPLACE, VimStateMachine.Mode.CMD_LINE, VimStateMachine.Mode.COMMAND, VimStateMachine.Mode.INSERT, VimStateMachine.Mode.OP_PENDING -> false
|
||||||
CommandState.Mode.INSERT_NORMAL -> false
|
VimStateMachine.Mode.INSERT_NORMAL -> false
|
||||||
CommandState.Mode.INSERT_VISUAL -> true
|
VimStateMachine.Mode.INSERT_VISUAL -> true
|
||||||
CommandState.Mode.INSERT_SELECT -> true
|
VimStateMachine.Mode.INSERT_SELECT -> true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val Editor.editorMode
|
||||||
|
get() = this.vim.vimStateMachine.mode
|
||||||
|
|
||||||
|
/**
|
||||||
|
* COMPATIBILITY-LAYER: New method
|
||||||
|
* Please see: https://jb.gg/zo8n0r
|
||||||
|
*/
|
||||||
val Editor.mode
|
val Editor.mode
|
||||||
get() = this.vim.commandState.mode
|
get() = this.vim.vimStateMachine.mode.ij
|
||||||
|
|
||||||
|
/**
|
||||||
|
* COMPATIBILITY-LAYER: New method
|
||||||
|
* Please see: https://jb.gg/zo8n0r
|
||||||
|
*/
|
||||||
|
val CommandState.Mode.isEndAllowed: Boolean
|
||||||
|
get() = this.engine.isEndAllowed
|
||||||
|
|
||||||
var Editor.subMode
|
var Editor.subMode
|
||||||
get() = this.vim.commandState.subMode
|
get() = this.vim.vimStateMachine.subMode
|
||||||
set(value) {
|
set(value) {
|
||||||
this.vim.commandState.subMode = value
|
this.vim.vimStateMachine.subMode = value
|
||||||
}
|
}
|
||||||
|
|
||||||
@get:JvmName("inNormalMode")
|
@get:JvmName("inNormalMode")
|
||||||
val Editor.inNormalMode
|
val Editor.inNormalMode
|
||||||
get() = this.mode.inNormalMode
|
get() = this.editorMode.inNormalMode
|
||||||
|
|
||||||
@get:JvmName("inNormalMode")
|
@get:JvmName("inNormalMode")
|
||||||
val CommandState.Mode.inNormalMode
|
val VimStateMachine.Mode.inNormalMode
|
||||||
get() = this == CommandState.Mode.COMMAND || this == CommandState.Mode.INSERT_NORMAL
|
get() = this == VimStateMachine.Mode.COMMAND || this == VimStateMachine.Mode.INSERT_NORMAL
|
||||||
|
|
||||||
@get:JvmName("inInsertMode")
|
@get:JvmName("inInsertMode")
|
||||||
val Editor.inInsertMode
|
val Editor.inInsertMode
|
||||||
get() = this.mode == CommandState.Mode.INSERT || this.mode == CommandState.Mode.REPLACE
|
get() = this.editorMode == VimStateMachine.Mode.INSERT || this.editorMode == VimStateMachine.Mode.REPLACE
|
||||||
|
|
||||||
@get:JvmName("inRepeatMode")
|
@get:JvmName("inRepeatMode")
|
||||||
val Editor.inRepeatMode
|
val Editor.inRepeatMode
|
||||||
get() = this.vim.commandState.isDotRepeatInProgress
|
get() = this.vim.vimStateMachine.isDotRepeatInProgress
|
||||||
|
|
||||||
@get:JvmName("inVisualMode")
|
@get:JvmName("inVisualMode")
|
||||||
val Editor.inVisualMode
|
val Editor.inVisualMode
|
||||||
get() = this.mode.inVisualMode
|
get() = this.editorMode.inVisualMode
|
||||||
|
|
||||||
@get:JvmName("inSelectMode")
|
@get:JvmName("inSelectMode")
|
||||||
val Editor.inSelectMode
|
val Editor.inSelectMode
|
||||||
get() = this.mode == CommandState.Mode.SELECT || this.mode == CommandState.Mode.INSERT_SELECT
|
get() = this.editorMode == VimStateMachine.Mode.SELECT || this.editorMode == VimStateMachine.Mode.INSERT_SELECT
|
||||||
|
|
||||||
val VimEditor.inSelectMode
|
val VimEditor.inSelectMode
|
||||||
get() = this.mode == CommandState.Mode.SELECT || this.mode == CommandState.Mode.INSERT_SELECT
|
get() = this.mode == VimStateMachine.Mode.SELECT || this.mode == VimStateMachine.Mode.INSERT_SELECT
|
||||||
|
|
||||||
@get:JvmName("inBlockSubMode")
|
@get:JvmName("inBlockSubMode")
|
||||||
val Editor.inBlockSubMode
|
val Editor.inBlockSubMode
|
||||||
get() = this.subMode == CommandState.SubMode.VISUAL_BLOCK
|
get() = this.subMode == VimStateMachine.SubMode.VISUAL_BLOCK
|
||||||
|
|
||||||
@get:JvmName("inSingleCommandMode")
|
@get:JvmName("inSingleCommandMode")
|
||||||
val Editor.inSingleCommandMode: Boolean
|
val Editor.inSingleCommandMode: Boolean
|
||||||
get() = this.mode.inSingleMode
|
get() = this.editorMode.inSingleMode
|
||||||
|
|
||||||
@get:JvmName("inSingleMode")
|
@get:JvmName("inSingleMode")
|
||||||
val CommandState.Mode.inSingleMode: Boolean
|
val VimStateMachine.Mode.inSingleMode: Boolean
|
||||||
get() = when (this) {
|
get() = when (this) {
|
||||||
CommandState.Mode.INSERT_NORMAL, CommandState.Mode.INSERT_SELECT, CommandState.Mode.INSERT_VISUAL -> true
|
VimStateMachine.Mode.INSERT_NORMAL, VimStateMachine.Mode.INSERT_SELECT, VimStateMachine.Mode.INSERT_VISUAL -> true
|
||||||
else -> false
|
else -> false
|
||||||
}
|
}
|
||||||
|
|
||||||
@get:JvmName("inSingleNormalMode")
|
@get:JvmName("inSingleNormalMode")
|
||||||
val CommandState.Mode.inSingleNormalMode: Boolean
|
val VimStateMachine.Mode.inSingleNormalMode: Boolean
|
||||||
get() = when (this) {
|
get() = when (this) {
|
||||||
CommandState.Mode.INSERT_NORMAL -> true
|
VimStateMachine.Mode.INSERT_NORMAL -> true
|
||||||
else -> false
|
else -> false
|
||||||
}
|
}
|
||||||
|
@@ -37,6 +37,7 @@ import org.jetbrains.annotations.Nullable;
|
|||||||
import org.jetbrains.annotations.Range;
|
import org.jetbrains.annotations.Range;
|
||||||
|
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
|
import java.awt.geom.Point2D;
|
||||||
import java.nio.CharBuffer;
|
import java.nio.CharBuffer;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
@@ -152,6 +153,14 @@ public class EditorHelper {
|
|||||||
: VimInjectorKt.getInjector().getEngineEditorHelper().logicalLineToVisualLine(editor, count - 1) + 1;
|
: VimInjectorKt.getInjector().getEngineEditorHelper().logicalLineToVisualLine(editor, count - 1) + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* COMPATIBILITY-LAYER: Created a function
|
||||||
|
* Please see: <a href="https://jb.gg/zo8n0r">doc</a>
|
||||||
|
*/
|
||||||
|
public static int getVisualLineCount(final @NotNull Editor editor) {
|
||||||
|
return getVisualLineCount(new IjVimEditor(editor));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the number of actual lines in the file
|
* Gets the number of actual lines in the file
|
||||||
*
|
*
|
||||||
@@ -238,12 +247,27 @@ public class EditorHelper {
|
|||||||
* font. It does not include inlays or folds.
|
* font. It does not include inlays or folds.
|
||||||
* <p>
|
* <p>
|
||||||
* Note that this value is only approximate and should be avoided whenever possible!
|
* Note that this value is only approximate and should be avoided whenever possible!
|
||||||
|
* </p>
|
||||||
*
|
*
|
||||||
* @param editor The editor
|
* @param editor The editor
|
||||||
* @return The number of screen columns
|
* @return The number of screen columns
|
||||||
*/
|
*/
|
||||||
public static int getApproximateScreenWidth(final @NotNull Editor editor) {
|
public static int getApproximateScreenWidth(final @NotNull Editor editor) {
|
||||||
return getVisibleArea(editor).width / EditorUtil.getPlainSpaceWidth(editor);
|
return (int)(getVisibleArea(editor).width / getPlainSpaceWidthFloat(editor));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the width of the space character in the editor's plain font as a float.
|
||||||
|
* <p>
|
||||||
|
* Font width can be fractional, but {@link EditorUtil#getPlainSpaceWidth(Editor)} returns it as an int, which can
|
||||||
|
* lead to rounding errors.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param editor The editor
|
||||||
|
* @return The width of the space character in the editor's plain font in pixels. It might be a fractional value.
|
||||||
|
*/
|
||||||
|
public static float getPlainSpaceWidthFloat(final @NotNull Editor editor) {
|
||||||
|
return EditorUtil.fontForChar(' ', Font.PLAIN, editor).charWidth2D(' ');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -795,19 +819,20 @@ public class EditorHelper {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final int columnLeftX = editor.visualPositionToXY(new VisualPosition(visualLine, targetVisualColumn)).x;
|
final int columnLeftX = (int) Math.round(editor.visualPositionToPoint2D(new VisualPosition(visualLine, targetVisualColumn)).getX());
|
||||||
scrollHorizontally(editor, columnLeftX);
|
scrollHorizontally(editor, columnLeftX);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void scrollColumnToMiddleOfScreen(@NotNull Editor editor, int visualLine, int visualColumn) {
|
public static void scrollColumnToMiddleOfScreen(@NotNull Editor editor, int visualLine, int visualColumn) {
|
||||||
final Point point = editor.visualPositionToXY(new VisualPosition(visualLine, visualColumn));
|
final Point2D point = editor.visualPositionToPoint2D(new VisualPosition(visualLine, visualColumn));
|
||||||
final int screenWidth = getVisibleArea(editor).width;
|
final int screenWidth = getVisibleArea(editor).width;
|
||||||
|
|
||||||
// Snap the column to the nearest standard column grid. This positions us nicely if there are an odd or even number
|
// Snap the column to the nearest standard column grid. This positions us nicely if there are an odd or even number
|
||||||
// of columns. It also works with inline inlays and folds. It is slightly inaccurate for proportional fonts, but is
|
// of columns. It also works with inline inlays and folds. It is slightly inaccurate for proportional fonts, but is
|
||||||
// still a good solution. Besides, what kind of monster uses Vim with proportional fonts?
|
// still a good solution. Besides, what kind of monster uses Vim with proportional fonts?
|
||||||
final int standardColumnWidth = EditorUtil.getPlainSpaceWidth(editor);
|
final float standardColumnWidth = EditorHelper.getPlainSpaceWidthFloat(editor);
|
||||||
final int x = max(0, point.x - (screenWidth / standardColumnWidth / 2 * standardColumnWidth));
|
final int screenMidColumn = (int) (screenWidth / standardColumnWidth / 2);
|
||||||
|
final int x = max(0, (int) Math.round(point.getX() - (screenMidColumn * standardColumnWidth)));
|
||||||
scrollHorizontally(editor, x);
|
scrollHorizontally(editor, x);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -832,7 +857,7 @@ public class EditorHelper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Scroll to the left edge of the target column, minus a screenwidth, and adjusted for inlays
|
// Scroll to the left edge of the target column, minus a screenwidth, and adjusted for inlays
|
||||||
final int targetColumnRightX = editor.visualPositionToXY(new VisualPosition(visualLine, targetVisualColumn + 1)).x;
|
final int targetColumnRightX = (int) Math.round(editor.visualPositionToPoint2D(new VisualPosition(visualLine, targetVisualColumn + 1)).getX());
|
||||||
final int screenWidth = getVisibleArea(editor).width;
|
final int screenWidth = getVisibleArea(editor).width;
|
||||||
scrollHorizontally(editor, targetColumnRightX - screenWidth);
|
scrollHorizontally(editor, targetColumnRightX - screenWidth);
|
||||||
}
|
}
|
||||||
@@ -853,7 +878,7 @@ public class EditorHelper {
|
|||||||
if (inlayAwareOffset == vimLastColumn) return vimLastColumn;
|
if (inlayAwareOffset == vimLastColumn) return vimLastColumn;
|
||||||
|
|
||||||
Editor editor = caret.getEditor();
|
Editor editor = caret.getEditor();
|
||||||
boolean isEndAllowed = CommandStateHelper.isEndAllowedIgnoringOnemore(CommandStateHelper.getMode(editor));
|
boolean isEndAllowed = CommandStateHelper.isEndAllowedIgnoringOnemore(CommandStateHelper.getEditorMode(editor));
|
||||||
final LogicalPosition logicalPosition = caret.getLogicalPosition();
|
final LogicalPosition logicalPosition = caret.getLogicalPosition();
|
||||||
int lastColumn = EditorHelper.lastColumnForLine(editor, logicalPosition.line, isEndAllowed);
|
int lastColumn = EditorHelper.lastColumnForLine(editor, logicalPosition.line, isEndAllowed);
|
||||||
|
|
||||||
@@ -994,18 +1019,18 @@ public class EditorHelper {
|
|||||||
// Note that visualPos.leansRight will be true for the right half side of the character grid
|
// Note that visualPos.leansRight will be true for the right half side of the character grid
|
||||||
VisualPosition closestVisualPosition = editor.xyToVisualPosition(new Point(x, y));
|
VisualPosition closestVisualPosition = editor.xyToVisualPosition(new Point(x, y));
|
||||||
|
|
||||||
// Make sure we get the character that contains this XY, not the editor's decision about closest character. The
|
// Make sure we get the character that contains this XY, not the editor's decision about the closest character. The
|
||||||
// editor will give us the next character if X is over half way through the character grid.
|
// editor will give us the next character if X is over halfway through the character grid. Take into account that
|
||||||
int xActualLeft = editor.visualPositionToXY(closestVisualPosition).x;
|
// the font size might be fractional, but the editor's area is integer. Use floating point values and round.
|
||||||
|
long xActualLeft = Math.round(editor.visualPositionToPoint2D(closestVisualPosition).getX());
|
||||||
if (xActualLeft > x) {
|
if (xActualLeft > x) {
|
||||||
closestVisualPosition = getPreviousNonInlayVisualPosition(editor, closestVisualPosition);
|
closestVisualPosition = getPreviousNonInlayVisualPosition(editor, closestVisualPosition);
|
||||||
xActualLeft = editor.visualPositionToXY(closestVisualPosition).x;
|
xActualLeft = Math.round(editor.visualPositionToPoint2D(closestVisualPosition).getX());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (xActualLeft >= leftBound) {
|
if (xActualLeft >= leftBound) {
|
||||||
final int xActualRight =
|
final VisualPosition nextVisualPosition = new VisualPosition(closestVisualPosition.line, closestVisualPosition.column + 1);
|
||||||
editor.visualPositionToXY(new VisualPosition(closestVisualPosition.line, closestVisualPosition.column + 1)).x -
|
final long xActualRight = Math.round(editor.visualPositionToPoint2D(nextVisualPosition).getX()) - 1;
|
||||||
1;
|
|
||||||
if (xActualRight <= rightBound) {
|
if (xActualRight <= rightBound) {
|
||||||
return closestVisualPosition.column;
|
return closestVisualPosition.column;
|
||||||
}
|
}
|
||||||
|
@@ -22,6 +22,7 @@ import com.intellij.codeInsight.template.TemplateManager
|
|||||||
import com.intellij.codeWithMe.ClientId
|
import com.intellij.codeWithMe.ClientId
|
||||||
import com.intellij.injected.editor.EditorWindow
|
import com.intellij.injected.editor.EditorWindow
|
||||||
import com.intellij.openapi.editor.Caret
|
import com.intellij.openapi.editor.Caret
|
||||||
|
import com.intellij.openapi.editor.ClientEditorManager
|
||||||
import com.intellij.openapi.editor.Document
|
import com.intellij.openapi.editor.Document
|
||||||
import com.intellij.openapi.editor.Editor
|
import com.intellij.openapi.editor.Editor
|
||||||
import com.intellij.openapi.editor.EditorFactory
|
import com.intellij.openapi.editor.EditorFactory
|
||||||
@@ -30,6 +31,7 @@ import com.intellij.openapi.util.Key
|
|||||||
import com.maddyhome.idea.vim.VimPlugin
|
import com.maddyhome.idea.vim.VimPlugin
|
||||||
import com.maddyhome.idea.vim.options.OptionConstants
|
import com.maddyhome.idea.vim.options.OptionConstants
|
||||||
import com.maddyhome.idea.vim.options.OptionScope
|
import com.maddyhome.idea.vim.options.OptionScope
|
||||||
|
import kotlin.streams.toList
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This annotation is created for test functions (methods).
|
* This annotation is created for test functions (methods).
|
||||||
@@ -83,10 +85,9 @@ fun Editor.getTopLevelEditor() = if (this is EditorWindow) this.delegate else th
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Return list of editors for local host (for code with me plugin)
|
* Return list of editors for local host (for code with me plugin)
|
||||||
* [VERSION UPDATE] 212+ ClientEditorManager.editors()
|
|
||||||
*/
|
*/
|
||||||
fun localEditors(): List<Editor> {
|
fun localEditors(): List<Editor> {
|
||||||
return EditorFactory.getInstance().allEditors.filter { editor -> editor.editorClientId.let { it == null || it == ClientId.currentOrNull } }
|
return ClientEditorManager.getCurrentInstance().editors().toList()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun localEditors(doc: Document): List<Editor> {
|
fun localEditors(doc: Document): List<Editor> {
|
||||||
|
@@ -21,18 +21,21 @@ package com.maddyhome.idea.vim.helper
|
|||||||
import com.intellij.openapi.actionSystem.ActionGroup
|
import com.intellij.openapi.actionSystem.ActionGroup
|
||||||
import com.intellij.openapi.actionSystem.ActionManager
|
import com.intellij.openapi.actionSystem.ActionManager
|
||||||
import com.intellij.openapi.actionSystem.ActionPlaces
|
import com.intellij.openapi.actionSystem.ActionPlaces
|
||||||
|
import com.intellij.openapi.actionSystem.AnAction
|
||||||
import com.intellij.openapi.actionSystem.AnActionEvent
|
import com.intellij.openapi.actionSystem.AnActionEvent
|
||||||
import com.intellij.openapi.actionSystem.DataContext
|
import com.intellij.openapi.actionSystem.AnActionResult
|
||||||
import com.intellij.openapi.actionSystem.IdeActions
|
import com.intellij.openapi.actionSystem.IdeActions
|
||||||
import com.intellij.openapi.actionSystem.PlatformDataKeys
|
import com.intellij.openapi.actionSystem.PlatformDataKeys
|
||||||
import com.intellij.openapi.actionSystem.Presentation
|
import com.intellij.openapi.actionSystem.ex.ActionManagerEx
|
||||||
import com.intellij.openapi.actionSystem.ex.ActionUtil
|
import com.intellij.openapi.actionSystem.ex.ActionUtil
|
||||||
import com.intellij.openapi.command.CommandProcessor
|
import com.intellij.openapi.command.CommandProcessor
|
||||||
import com.intellij.openapi.command.UndoConfirmationPolicy
|
import com.intellij.openapi.command.UndoConfirmationPolicy
|
||||||
import com.intellij.openapi.components.Service
|
import com.intellij.openapi.components.Service
|
||||||
import com.intellij.openapi.editor.actionSystem.DocCommandGroupId
|
import com.intellij.openapi.editor.actionSystem.DocCommandGroupId
|
||||||
|
import com.intellij.openapi.project.IndexNotReadyException
|
||||||
import com.intellij.openapi.ui.popup.JBPopupFactory
|
import com.intellij.openapi.ui.popup.JBPopupFactory
|
||||||
import com.intellij.openapi.util.NlsContexts
|
import com.intellij.openapi.util.NlsContexts
|
||||||
|
import com.intellij.util.SlowOperations
|
||||||
import com.maddyhome.idea.vim.RegisterActions
|
import com.maddyhome.idea.vim.RegisterActions
|
||||||
import com.maddyhome.idea.vim.api.ExecutionContext
|
import com.maddyhome.idea.vim.api.ExecutionContext
|
||||||
import com.maddyhome.idea.vim.api.NativeAction
|
import com.maddyhome.idea.vim.api.NativeAction
|
||||||
@@ -80,7 +83,7 @@ class IjActionExecutor : VimActionExecutor {
|
|||||||
// This method executes inside of lastUpdateAndCheckDumb
|
// This method executes inside of lastUpdateAndCheckDumb
|
||||||
// Another related issue: VIM-2604
|
// Another related issue: VIM-2604
|
||||||
if (!ActionUtil.lastUpdateAndCheckDumb(ijAction, event, false)) return false
|
if (!ActionUtil.lastUpdateAndCheckDumb(ijAction, event, false)) return false
|
||||||
if (ijAction is ActionGroup && !canBePerformed(event, ijAction, context.ij)) {
|
if (ijAction is ActionGroup && !event.presentation.isPerformGroup) {
|
||||||
// Some ActionGroups should not be performed, but shown as a popup
|
// Some ActionGroups should not be performed, but shown as a popup
|
||||||
val popup = JBPopupFactory.getInstance()
|
val popup = JBPopupFactory.getInstance()
|
||||||
.createActionGroupPopup(event.presentation.text, ijAction, context.ij, false, null, -1)
|
.createActionGroupPopup(event.presentation.text, ijAction, context.ij, false, null, -1)
|
||||||
@@ -95,19 +98,44 @@ class IjActionExecutor : VimActionExecutor {
|
|||||||
popup.showInFocusCenter()
|
popup.showInFocusCenter()
|
||||||
return true
|
return true
|
||||||
} else {
|
} else {
|
||||||
ActionUtil.performActionDumbAwareWithCallbacks(ijAction, event)
|
performDumbAwareWithCallbacks(ijAction, event) { ijAction.actionPerformed(event) }
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun canBePerformed(event: AnActionEvent, action: ActionGroup, context: DataContext): Boolean {
|
// This is taken directly from ActionUtil.performActionDumbAwareWithCallbacks
|
||||||
val presentation = event.presentation
|
// But with one check removed. With this check some actions (like `:w` doesn't work)
|
||||||
return try {
|
// https://youtrack.jetbrains.com/issue/VIM-2691/File-is-not-saved-on-w
|
||||||
// [VERSION UPDATE] 221+ Just use Presentation.isPerformGroup
|
private fun performDumbAwareWithCallbacks(
|
||||||
val method = Presentation::class.java.getMethod("isPerformGroup")
|
action: AnAction,
|
||||||
method.invoke(presentation) as Boolean
|
event: AnActionEvent,
|
||||||
} catch (e: Exception) {
|
performRunnable: Runnable,
|
||||||
action.canBePerformed(context)
|
) {
|
||||||
|
val project = event.project
|
||||||
|
var indexError: IndexNotReadyException? = null
|
||||||
|
val manager = ActionManagerEx.getInstanceEx()
|
||||||
|
manager.fireBeforeActionPerformed(action, event)
|
||||||
|
var result: AnActionResult? = null
|
||||||
|
try {
|
||||||
|
SlowOperations.allowSlowOperations(SlowOperations.ACTION_PERFORM).use {
|
||||||
|
performRunnable.run()
|
||||||
|
result = AnActionResult.PERFORMED
|
||||||
|
}
|
||||||
|
} catch (ex: IndexNotReadyException) {
|
||||||
|
indexError = ex
|
||||||
|
result = AnActionResult.failed(ex)
|
||||||
|
} catch (ex: RuntimeException) {
|
||||||
|
result = AnActionResult.failed(ex)
|
||||||
|
throw ex
|
||||||
|
} catch (ex: Error) {
|
||||||
|
result = AnActionResult.failed(ex)
|
||||||
|
throw ex
|
||||||
|
} finally {
|
||||||
|
if (result == null) result = AnActionResult.failed(Throwable())
|
||||||
|
manager.fireAfterActionPerformed(action, event, result!!)
|
||||||
|
}
|
||||||
|
if (indexError != null) {
|
||||||
|
ActionUtil.showDumbModeWarning(project, event)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -155,6 +183,10 @@ class IjActionExecutor : VimActionExecutor {
|
|||||||
return RegisterActions.findAction(id)
|
return RegisterActions.findAction(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun findVimActionOrDie(id: String): EditorActionHandlerBase {
|
||||||
|
return RegisterActions.findActionOrDie(id)
|
||||||
|
}
|
||||||
|
|
||||||
override fun getAction(actionId: String): NativeAction? {
|
override fun getAction(actionId: String): NativeAction? {
|
||||||
return ActionManager.getInstance().getAction(actionId)?.let { IjNativeAction(it) }
|
return ActionManager.getInstance().getAction(actionId)?.let { IjNativeAction(it) }
|
||||||
}
|
}
|
||||||
|
@@ -143,4 +143,8 @@ class IjEditorHelper : EngineEditorHelper {
|
|||||||
override fun getLeadingWhitespace(editor: VimEditor, line: Int): String {
|
override fun getLeadingWhitespace(editor: VimEditor, line: Int): String {
|
||||||
return EditorHelper.getLeadingWhitespace(editor.ij, line)
|
return EditorHelper.getLeadingWhitespace(editor.ij, line)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun anyNonWhitespace(editor: VimEditor, offset: Int, dir: Int): Boolean {
|
||||||
|
return SearchHelper.anyNonWhitespace(editor.ij, offset, dir)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -25,9 +25,9 @@ import com.intellij.openapi.editor.Caret
|
|||||||
import com.intellij.openapi.editor.Editor
|
import com.intellij.openapi.editor.Editor
|
||||||
import com.maddyhome.idea.vim.VimPlugin
|
import com.maddyhome.idea.vim.VimPlugin
|
||||||
import com.maddyhome.idea.vim.api.VimEditor
|
import com.maddyhome.idea.vim.api.VimEditor
|
||||||
import com.maddyhome.idea.vim.command.CommandState
|
|
||||||
import com.maddyhome.idea.vim.command.OperatorArguments
|
import com.maddyhome.idea.vim.command.OperatorArguments
|
||||||
import com.maddyhome.idea.vim.command.SelectionType
|
import com.maddyhome.idea.vim.command.SelectionType
|
||||||
|
import com.maddyhome.idea.vim.command.VimStateMachine
|
||||||
import com.maddyhome.idea.vim.common.TextRange
|
import com.maddyhome.idea.vim.common.TextRange
|
||||||
import com.maddyhome.idea.vim.listener.SelectionVimListenerSuppressor
|
import com.maddyhome.idea.vim.listener.SelectionVimListenerSuppressor
|
||||||
import com.maddyhome.idea.vim.newapi.IjExecutionContext
|
import com.maddyhome.idea.vim.newapi.IjExecutionContext
|
||||||
@@ -39,8 +39,8 @@ import com.maddyhome.idea.vim.newapi.vim
|
|||||||
* Pop all modes, but leave editor state. E.g. editor selection is not removed.
|
* Pop all modes, but leave editor state. E.g. editor selection is not removed.
|
||||||
*/
|
*/
|
||||||
fun Editor.popAllModes() {
|
fun Editor.popAllModes() {
|
||||||
val commandState = this.vim.commandState
|
val commandState = this.vim.vimStateMachine
|
||||||
while (commandState.mode != CommandState.Mode.COMMAND) {
|
while (commandState.mode != VimStateMachine.Mode.COMMAND) {
|
||||||
commandState.popModes()
|
commandState.popModes()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -63,7 +63,7 @@ fun Editor.exitVisualMode() {
|
|||||||
VimPlugin.getMark().setVisualSelectionMarks(this.vim, TextRange(vimSelectionStart, primaryCaret.offset))
|
VimPlugin.getMark().setVisualSelectionMarks(this.vim, TextRange(vimSelectionStart, primaryCaret.offset))
|
||||||
this.caretModel.allCarets.forEach { it.vimSelectionStartClear() }
|
this.caretModel.allCarets.forEach { it.vimSelectionStartClear() }
|
||||||
|
|
||||||
this.vim.commandState.popModes()
|
this.vim.vimStateMachine.popModes()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -71,7 +71,7 @@ fun Editor.exitVisualMode() {
|
|||||||
fun Editor.exitSelectMode(adjustCaretPosition: Boolean) {
|
fun Editor.exitSelectMode(adjustCaretPosition: Boolean) {
|
||||||
if (!this.inSelectMode) return
|
if (!this.inSelectMode) return
|
||||||
|
|
||||||
this.vim.commandState.popModes()
|
this.vim.vimStateMachine.popModes()
|
||||||
SelectionVimListenerSuppressor.lock().use {
|
SelectionVimListenerSuppressor.lock().use {
|
||||||
this.caretModel.allCarets.forEach {
|
this.caretModel.allCarets.forEach {
|
||||||
it.removeSelection()
|
it.removeSelection()
|
||||||
@@ -91,7 +91,7 @@ fun Editor.exitSelectMode(adjustCaretPosition: Boolean) {
|
|||||||
fun VimEditor.exitSelectMode(adjustCaretPosition: Boolean) {
|
fun VimEditor.exitSelectMode(adjustCaretPosition: Boolean) {
|
||||||
if (!this.inSelectMode) return
|
if (!this.inSelectMode) return
|
||||||
|
|
||||||
this.commandState.popModes()
|
this.vimStateMachine.popModes()
|
||||||
SelectionVimListenerSuppressor.lock().use {
|
SelectionVimListenerSuppressor.lock().use {
|
||||||
this.carets().forEach { vimCaret ->
|
this.carets().forEach { vimCaret ->
|
||||||
val caret = (vimCaret as IjVimCaret).caret
|
val caret = (vimCaret as IjVimCaret).caret
|
||||||
|
@@ -31,7 +31,7 @@ import com.intellij.psi.PsiElement;
|
|||||||
import com.intellij.psi.PsiFile;
|
import com.intellij.psi.PsiFile;
|
||||||
import com.intellij.psi.util.PsiTreeUtil;
|
import com.intellij.psi.util.PsiTreeUtil;
|
||||||
import com.maddyhome.idea.vim.VimPlugin;
|
import com.maddyhome.idea.vim.VimPlugin;
|
||||||
import com.maddyhome.idea.vim.command.CommandState;
|
import com.maddyhome.idea.vim.command.VimStateMachine;
|
||||||
import com.maddyhome.idea.vim.common.CharacterPosition;
|
import com.maddyhome.idea.vim.common.CharacterPosition;
|
||||||
import com.maddyhome.idea.vim.common.Direction;
|
import com.maddyhome.idea.vim.common.Direction;
|
||||||
import com.maddyhome.idea.vim.common.TextRange;
|
import com.maddyhome.idea.vim.common.TextRange;
|
||||||
@@ -529,6 +529,9 @@ public class SearchHelper {
|
|||||||
CharSequence subSequence = chars.subSequence(startOffset, endOffset);
|
CharSequence subSequence = chars.subSequence(startOffset, endOffset);
|
||||||
int inQuotePos = pos - startOffset;
|
int inQuotePos = pos - startOffset;
|
||||||
int inQuoteStart = findBlockLocation(subSequence, close, type, Direction.BACKWARDS, inQuotePos, count, false);
|
int inQuoteStart = findBlockLocation(subSequence, close, type, Direction.BACKWARDS, inQuotePos, count, false);
|
||||||
|
if (inQuoteStart == -1) {
|
||||||
|
inQuoteStart = findBlockLocation(subSequence, close, type, Direction.FORWARDS, inQuotePos, count, false);
|
||||||
|
}
|
||||||
if (inQuoteStart != -1) {
|
if (inQuoteStart != -1) {
|
||||||
startPosInStringFound = true;
|
startPosInStringFound = true;
|
||||||
int inQuoteEnd = findBlockLocation(subSequence, type, close, Direction.FORWARDS, inQuoteStart, 1, false);
|
int inQuoteEnd = findBlockLocation(subSequence, type, close, Direction.FORWARDS, inQuoteStart, 1, false);
|
||||||
@@ -542,6 +545,9 @@ public class SearchHelper {
|
|||||||
|
|
||||||
if (!startPosInStringFound) {
|
if (!startPosInStringFound) {
|
||||||
bstart = findBlockLocation(chars, close, type, Direction.BACKWARDS, pos, count, false);
|
bstart = findBlockLocation(chars, close, type, Direction.BACKWARDS, pos, count, false);
|
||||||
|
if (bstart == -1) {
|
||||||
|
bstart = findBlockLocation(chars, close, type, Direction.FORWARDS, pos, count, false);
|
||||||
|
}
|
||||||
if (bstart != -1) {
|
if (bstart != -1) {
|
||||||
bend = findBlockLocation(chars, type, close, Direction.FORWARDS, bstart, 1, false);
|
bend = findBlockLocation(chars, type, close, Direction.FORWARDS, bstart, 1, false);
|
||||||
}
|
}
|
||||||
@@ -893,8 +899,8 @@ public class SearchHelper {
|
|||||||
selectionEndWithoutNewline++;
|
selectionEndWithoutNewline++;
|
||||||
}
|
}
|
||||||
|
|
||||||
final CommandState.Mode mode = CommandState.getInstance(new IjVimEditor(editor)).getMode();
|
final VimStateMachine.Mode mode = VimStateMachine.getInstance(new IjVimEditor(editor)).getMode();
|
||||||
if (mode == CommandState.Mode.VISUAL) {
|
if (mode == VimStateMachine.Mode.VISUAL) {
|
||||||
if (closingTagTextRange.getStartOffset() == selectionEndWithoutNewline &&
|
if (closingTagTextRange.getStartOffset() == selectionEndWithoutNewline &&
|
||||||
openingTag.getEndOffset() == selectionStart) {
|
openingTag.getEndOffset() == selectionStart) {
|
||||||
// Special case: if the inner tag is already selected we should like isOuter is active
|
// Special case: if the inner tag is already selected we should like isOuter is active
|
||||||
|
45
src/main/java/com/maddyhome/idea/vim/helper/StringHelper.kt
Normal file
45
src/main/java/com/maddyhome/idea/vim/helper/StringHelper.kt
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
/*
|
||||||
|
* IdeaVim - Vim emulator for IDEs based on the IntelliJ platform
|
||||||
|
* Copyright (C) 2003-2022 The IdeaVim authors
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package com.maddyhome.idea.vim.helper
|
||||||
|
|
||||||
|
import com.maddyhome.idea.vim.api.injector
|
||||||
|
import java.util.*
|
||||||
|
import java.util.stream.Collectors
|
||||||
|
import javax.swing.KeyStroke
|
||||||
|
|
||||||
|
/**
|
||||||
|
* COMPATIBILITY-LAYER: Created a helper class
|
||||||
|
* Please see: https://jb.gg/zo8n0r
|
||||||
|
*/
|
||||||
|
object StringHelper {
|
||||||
|
@JvmStatic
|
||||||
|
fun parseKeys(string: String): List<KeyStroke> {
|
||||||
|
return injector.parser.parseKeys(string)
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun parseKeys(vararg string: String): List<KeyStroke> {
|
||||||
|
return Arrays.stream(string).flatMap { o: String -> injector.parser.parseKeys(o).stream() }
|
||||||
|
.collect(Collectors.toList())
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun isCloseKeyStroke(stroke: KeyStroke): Boolean {
|
||||||
|
return stroke.isCloseKeyStroke()
|
||||||
|
}
|
||||||
|
}
|
@@ -21,6 +21,8 @@ package com.maddyhome.idea.vim.helper
|
|||||||
import com.intellij.openapi.actionSystem.CommonDataKeys
|
import com.intellij.openapi.actionSystem.CommonDataKeys
|
||||||
import com.intellij.openapi.actionSystem.DataContext
|
import com.intellij.openapi.actionSystem.DataContext
|
||||||
import com.intellij.openapi.actionSystem.PlatformDataKeys
|
import com.intellij.openapi.actionSystem.PlatformDataKeys
|
||||||
|
import com.intellij.openapi.command.CommandProcessor
|
||||||
|
import com.intellij.openapi.command.impl.UndoManagerImpl
|
||||||
import com.intellij.openapi.command.undo.UndoManager
|
import com.intellij.openapi.command.undo.UndoManager
|
||||||
import com.intellij.openapi.components.Service
|
import com.intellij.openapi.components.Service
|
||||||
import com.maddyhome.idea.vim.api.ExecutionContext
|
import com.maddyhome.idea.vim.api.ExecutionContext
|
||||||
@@ -39,22 +41,29 @@ import com.maddyhome.idea.vim.vimscript.services.IjVimOptionService
|
|||||||
*/
|
*/
|
||||||
@Service
|
@Service
|
||||||
class UndoRedoHelper : UndoRedoBase() {
|
class UndoRedoHelper : UndoRedoBase() {
|
||||||
|
init {
|
||||||
|
injector.optionService.addListener(IjVimOptionService.oldUndo, { UndoManagerImpl.ourNeverAskUser = !injector.optionService.isSet(OptionScope.GLOBAL, IjVimOptionService.oldUndo) }, true)
|
||||||
|
}
|
||||||
|
|
||||||
override fun undo(context: ExecutionContext): Boolean {
|
override fun undo(context: ExecutionContext): Boolean {
|
||||||
val ijContext = context.context as DataContext
|
val ijContext = context.context as DataContext
|
||||||
val project = PlatformDataKeys.PROJECT.getData(ijContext) ?: return false
|
val project = PlatformDataKeys.PROJECT.getData(ijContext) ?: return false
|
||||||
val fileEditor = PlatformDataKeys.FILE_EDITOR.getData(ijContext)
|
val fileEditor = PlatformDataKeys.FILE_EDITOR.getData(ijContext)
|
||||||
val undoManager = UndoManager.getInstance(project)
|
val undoManager = UndoManager.getInstance(project)
|
||||||
if (fileEditor != null && undoManager.isUndoAvailable(fileEditor)) {
|
if (fileEditor != null && undoManager.isUndoAvailable(fileEditor)) {
|
||||||
|
val editor = CommonDataKeys.EDITOR.getData(context.ij)?.vim
|
||||||
if (injector.optionService.isSet(OptionScope.GLOBAL, IjVimOptionService.oldUndo)) {
|
if (injector.optionService.isSet(OptionScope.GLOBAL, IjVimOptionService.oldUndo)) {
|
||||||
SelectionVimListenerSuppressor.lock().use { undoManager.undo(fileEditor) }
|
SelectionVimListenerSuppressor.lock().use { undoManager.undo(fileEditor) }
|
||||||
} else {
|
} else {
|
||||||
val editor = CommonDataKeys.EDITOR.getData(context.ij)?.vim
|
|
||||||
performUntilFileChanges(editor, { undoManager.isUndoAvailable(fileEditor) }, { undoManager.undo(fileEditor) })
|
performUntilFileChanges(editor, { undoManager.isUndoAvailable(fileEditor) }, { undoManager.undo(fileEditor) })
|
||||||
|
}
|
||||||
|
|
||||||
editor?.carets()?.forEach {
|
editor?.carets()?.forEach {
|
||||||
val ijCaret = it.ij
|
val ijCaret = it.ij
|
||||||
val hasSelection = ijCaret.hasSelection()
|
val hasSelection = ijCaret.hasSelection()
|
||||||
if (hasSelection) {
|
if (hasSelection) {
|
||||||
val selectionStart = ijCaret.selectionStart
|
val selectionStart = ijCaret.selectionStart
|
||||||
|
CommandProcessor.getInstance().runUndoTransparentAction {
|
||||||
it.ij.removeSelection()
|
it.ij.removeSelection()
|
||||||
it.ij.moveToOffset(selectionStart)
|
it.ij.moveToOffset(selectionStart)
|
||||||
}
|
}
|
||||||
@@ -70,12 +79,14 @@ class UndoRedoHelper : UndoRedoBase() {
|
|||||||
val project = PlatformDataKeys.PROJECT.getData(ijContext) ?: return false
|
val project = PlatformDataKeys.PROJECT.getData(ijContext) ?: return false
|
||||||
val fileEditor = PlatformDataKeys.FILE_EDITOR.getData(ijContext)
|
val fileEditor = PlatformDataKeys.FILE_EDITOR.getData(ijContext)
|
||||||
val undoManager = UndoManager.getInstance(project)
|
val undoManager = UndoManager.getInstance(project)
|
||||||
|
val editor = CommonDataKeys.EDITOR.getData(context.ij)?.vim
|
||||||
if (fileEditor != null && undoManager.isRedoAvailable(fileEditor)) {
|
if (fileEditor != null && undoManager.isRedoAvailable(fileEditor)) {
|
||||||
if (injector.optionService.isSet(OptionScope.GLOBAL, IjVimOptionService.oldUndo)) {
|
if (injector.optionService.isSet(OptionScope.GLOBAL, IjVimOptionService.oldUndo)) {
|
||||||
SelectionVimListenerSuppressor.lock().use { undoManager.redo(fileEditor) }
|
SelectionVimListenerSuppressor.lock().use { undoManager.redo(fileEditor) }
|
||||||
} else {
|
} else {
|
||||||
val editor = CommonDataKeys.EDITOR.getData(context.ij)?.vim
|
|
||||||
performUntilFileChanges(editor, { undoManager.isRedoAvailable(fileEditor) }, { undoManager.redo(fileEditor) })
|
performUntilFileChanges(editor, { undoManager.isRedoAvailable(fileEditor) }, { undoManager.redo(fileEditor) })
|
||||||
|
}
|
||||||
|
CommandProcessor.getInstance().runUndoTransparentAction {
|
||||||
editor?.carets()?.forEach { it.ij.removeSelection() }
|
editor?.carets()?.forEach { it.ij.removeSelection() }
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
@@ -95,9 +106,15 @@ class UndoRedoHelper : UndoRedoBase() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val oldPath = editor.getPath()
|
||||||
vimDocument.addChangeListener(changeListener)
|
vimDocument.addChangeListener(changeListener)
|
||||||
while (check() && !changeListener.hasChanged) {
|
while (check() && !changeListener.hasChanged && !ifFilePathChanged(editor, oldPath)) {
|
||||||
action.run()
|
action.run()
|
||||||
}
|
}
|
||||||
|
vimDocument.removeChangeListener(changeListener)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun ifFilePathChanged(editor: IjVimEditor, oldPath: String?): Boolean {
|
||||||
|
return editor.getPath() != oldPath
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -27,8 +27,9 @@ import com.intellij.openapi.editor.RangeMarker
|
|||||||
import com.intellij.openapi.editor.markup.RangeHighlighter
|
import com.intellij.openapi.editor.markup.RangeHighlighter
|
||||||
import com.intellij.openapi.util.Key
|
import com.intellij.openapi.util.Key
|
||||||
import com.intellij.openapi.util.UserDataHolder
|
import com.intellij.openapi.util.UserDataHolder
|
||||||
import com.maddyhome.idea.vim.command.CommandState
|
import com.maddyhome.idea.vim.api.CaretRegisterStorageBase
|
||||||
import com.maddyhome.idea.vim.command.SelectionType
|
import com.maddyhome.idea.vim.command.SelectionType
|
||||||
|
import com.maddyhome.idea.vim.command.VimStateMachine
|
||||||
import com.maddyhome.idea.vim.ex.ExOutputModel
|
import com.maddyhome.idea.vim.ex.ExOutputModel
|
||||||
import com.maddyhome.idea.vim.group.visual.VisualChange
|
import com.maddyhome.idea.vim.group.visual.VisualChange
|
||||||
import com.maddyhome.idea.vim.group.visual.vimLeadSelectionOffset
|
import com.maddyhome.idea.vim.group.visual.vimLeadSelectionOffset
|
||||||
@@ -73,11 +74,12 @@ var Caret.vimInsertStart: RangeMarker by userDataOr {
|
|||||||
this.offset
|
this.offset
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
var Caret.registerStorage: CaretRegisterStorageBase? by userDataCaretToEditor()
|
||||||
|
|
||||||
// ------------------ Editor
|
// ------------------ Editor
|
||||||
fun unInitializeEditor(editor: Editor) {
|
fun unInitializeEditor(editor: Editor) {
|
||||||
editor.vimLastSelectionType = null
|
editor.vimLastSelectionType = null
|
||||||
editor.vimCommandState = null
|
editor.vimStateMachine = null
|
||||||
editor.vimMorePanel = null
|
editor.vimMorePanel = null
|
||||||
editor.vimExOutput = null
|
editor.vimExOutput = null
|
||||||
editor.vimLastHighlighters = null
|
editor.vimLastHighlighters = null
|
||||||
@@ -91,7 +93,7 @@ var Editor.vimIncsearchCurrentMatchOffset: Int? by userData()
|
|||||||
* @see :help visualmode()
|
* @see :help visualmode()
|
||||||
*/
|
*/
|
||||||
var Editor.vimLastSelectionType: SelectionType? by userData()
|
var Editor.vimLastSelectionType: SelectionType? by userData()
|
||||||
var Editor.vimCommandState: CommandState? by userData()
|
var Editor.vimStateMachine: VimStateMachine? by userData()
|
||||||
var Editor.vimEditorGroup: Boolean by userDataOr { false }
|
var Editor.vimEditorGroup: Boolean by userDataOr { false }
|
||||||
var Editor.vimLineNumbersInitialState: Boolean by userDataOr { false }
|
var Editor.vimLineNumbersInitialState: Boolean by userDataOr { false }
|
||||||
var Editor.vimHasRelativeLineNumbersInstalled: Boolean by userDataOr { false }
|
var Editor.vimHasRelativeLineNumbersInstalled: Boolean by userDataOr { false }
|
||||||
@@ -103,7 +105,7 @@ var Editor.vimTestInputModel: TestInputModel? by userData()
|
|||||||
* Checks whether a keeping visual mode visual operator action is performed on editor.
|
* Checks whether a keeping visual mode visual operator action is performed on editor.
|
||||||
*/
|
*/
|
||||||
var Editor.vimKeepingVisualOperatorAction: Boolean by userDataOr { false }
|
var Editor.vimKeepingVisualOperatorAction: Boolean by userDataOr { false }
|
||||||
var Editor.vimChangeActionSwitchMode: CommandState.Mode? by userData()
|
var Editor.vimChangeActionSwitchMode: VimStateMachine.Mode? by userData()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function for delegated properties.
|
* Function for delegated properties.
|
||||||
|
@@ -19,8 +19,6 @@
|
|||||||
package com.maddyhome.idea.vim.key
|
package com.maddyhome.idea.vim.key
|
||||||
|
|
||||||
import com.maddyhome.idea.vim.api.injector
|
import com.maddyhome.idea.vim.api.injector
|
||||||
import com.maddyhome.idea.vim.common.Node
|
|
||||||
import com.maddyhome.idea.vim.common.addLeafs
|
|
||||||
|
|
||||||
fun <T> Node<T>.addLeafs(keys: String, actionHolder: T) {
|
fun <T> Node<T>.addLeafs(keys: String, actionHolder: T) {
|
||||||
addLeafs(injector.parser.parseKeys(keys), actionHolder)
|
addLeafs(injector.parser.parseKeys(keys), actionHolder)
|
||||||
|
@@ -21,8 +21,8 @@ package com.maddyhome.idea.vim.listener
|
|||||||
import com.intellij.openapi.actionSystem.ActionManager
|
import com.intellij.openapi.actionSystem.ActionManager
|
||||||
import com.intellij.openapi.actionSystem.AnAction
|
import com.intellij.openapi.actionSystem.AnAction
|
||||||
import com.intellij.openapi.actionSystem.AnActionEvent
|
import com.intellij.openapi.actionSystem.AnActionEvent
|
||||||
|
import com.intellij.openapi.actionSystem.AnActionResult
|
||||||
import com.intellij.openapi.actionSystem.CommonDataKeys
|
import com.intellij.openapi.actionSystem.CommonDataKeys
|
||||||
import com.intellij.openapi.actionSystem.DataContext
|
|
||||||
import com.intellij.openapi.actionSystem.IdeActions
|
import com.intellij.openapi.actionSystem.IdeActions
|
||||||
import com.intellij.openapi.actionSystem.ex.AnActionListener
|
import com.intellij.openapi.actionSystem.ex.AnActionListener
|
||||||
import com.intellij.openapi.editor.Caret
|
import com.intellij.openapi.editor.Caret
|
||||||
@@ -35,7 +35,6 @@ import com.maddyhome.idea.vim.group.visual.VimVisualTimer
|
|||||||
import com.maddyhome.idea.vim.helper.fileSize
|
import com.maddyhome.idea.vim.helper.fileSize
|
||||||
import com.maddyhome.idea.vim.helper.inVisualMode
|
import com.maddyhome.idea.vim.helper.inVisualMode
|
||||||
import com.maddyhome.idea.vim.newapi.vim
|
import com.maddyhome.idea.vim.newapi.vim
|
||||||
import org.jetbrains.annotations.NotNull
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A collection of hacks to improve the interaction with fancy AppCode templates
|
* A collection of hacks to improve the interaction with fancy AppCode templates
|
||||||
@@ -50,16 +49,16 @@ object AppCodeTemplates {
|
|||||||
|
|
||||||
private var editor: Editor? = null
|
private var editor: Editor? = null
|
||||||
|
|
||||||
override fun beforeActionPerformed(action: AnAction, dataContext: DataContext, event: AnActionEvent) {
|
override fun beforeActionPerformed(action: AnAction, event: AnActionEvent) {
|
||||||
if (!VimPlugin.isEnabled()) return
|
if (!VimPlugin.isEnabled()) return
|
||||||
|
|
||||||
val hostEditor = dataContext.getData(CommonDataKeys.HOST_EDITOR)
|
val hostEditor = event.dataContext.getData(CommonDataKeys.HOST_EDITOR)
|
||||||
if (hostEditor != null) {
|
if (hostEditor != null) {
|
||||||
editor = hostEditor
|
editor = hostEditor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun afterActionPerformed(action: AnAction, dataContext: DataContext, event: AnActionEvent) {
|
override fun afterActionPerformed(action: AnAction, event: AnActionEvent, result: AnActionResult) {
|
||||||
if (!VimPlugin.isEnabled()) return
|
if (!VimPlugin.isEnabled()) return
|
||||||
|
|
||||||
if (ActionManager.getInstance().getId(action) == IdeActions.ACTION_CHOOSE_LOOKUP_ITEM) {
|
if (ActionManager.getInstance().getId(action) == IdeActions.ACTION_CHOOSE_LOOKUP_ITEM) {
|
||||||
@@ -77,8 +76,8 @@ object AppCodeTemplates {
|
|||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun onMovement(
|
fun onMovement(
|
||||||
editor: @NotNull Editor,
|
editor: Editor,
|
||||||
caret: @NotNull Caret,
|
caret: Caret,
|
||||||
toRight: Boolean,
|
toRight: Boolean,
|
||||||
) {
|
) {
|
||||||
val offset = caret.offset
|
val offset = caret.offset
|
||||||
|
@@ -29,19 +29,20 @@ import com.intellij.find.FindModelListener
|
|||||||
import com.intellij.openapi.actionSystem.ActionManager
|
import com.intellij.openapi.actionSystem.ActionManager
|
||||||
import com.intellij.openapi.actionSystem.AnAction
|
import com.intellij.openapi.actionSystem.AnAction
|
||||||
import com.intellij.openapi.actionSystem.AnActionEvent
|
import com.intellij.openapi.actionSystem.AnActionEvent
|
||||||
|
import com.intellij.openapi.actionSystem.AnActionResult
|
||||||
import com.intellij.openapi.actionSystem.CommonDataKeys
|
import com.intellij.openapi.actionSystem.CommonDataKeys
|
||||||
import com.intellij.openapi.actionSystem.DataContext
|
|
||||||
import com.intellij.openapi.actionSystem.ex.AnActionListener
|
import com.intellij.openapi.actionSystem.ex.AnActionListener
|
||||||
|
import com.intellij.openapi.actionSystem.impl.ProxyShortcutSet
|
||||||
import com.intellij.openapi.editor.Editor
|
import com.intellij.openapi.editor.Editor
|
||||||
import com.intellij.openapi.project.DumbAwareToggleAction
|
import com.intellij.openapi.project.DumbAwareToggleAction
|
||||||
import com.maddyhome.idea.vim.KeyHandler
|
import com.maddyhome.idea.vim.KeyHandler
|
||||||
import com.maddyhome.idea.vim.VimPlugin
|
import com.maddyhome.idea.vim.VimPlugin
|
||||||
import com.maddyhome.idea.vim.command.CommandState
|
import com.maddyhome.idea.vim.command.VimStateMachine
|
||||||
import com.maddyhome.idea.vim.group.NotificationService
|
import com.maddyhome.idea.vim.group.NotificationService
|
||||||
import com.maddyhome.idea.vim.helper.EditorDataContext
|
import com.maddyhome.idea.vim.helper.EditorDataContext
|
||||||
import com.maddyhome.idea.vim.helper.commandState
|
|
||||||
import com.maddyhome.idea.vim.helper.inNormalMode
|
import com.maddyhome.idea.vim.helper.inNormalMode
|
||||||
import com.maddyhome.idea.vim.helper.isIdeaVimDisabledHere
|
import com.maddyhome.idea.vim.helper.isIdeaVimDisabledHere
|
||||||
|
import com.maddyhome.idea.vim.helper.vimStateMachine
|
||||||
import com.maddyhome.idea.vim.newapi.vim
|
import com.maddyhome.idea.vim.newapi.vim
|
||||||
import com.maddyhome.idea.vim.options.OptionConstants
|
import com.maddyhome.idea.vim.options.OptionConstants
|
||||||
import com.maddyhome.idea.vim.options.OptionScope
|
import com.maddyhome.idea.vim.options.OptionScope
|
||||||
@@ -59,10 +60,10 @@ object IdeaSpecifics {
|
|||||||
private val surrounderAction =
|
private val surrounderAction =
|
||||||
"com.intellij.codeInsight.generation.surroundWith.SurroundWithHandler\$InvokeSurrounderAction"
|
"com.intellij.codeInsight.generation.surroundWith.SurroundWithHandler\$InvokeSurrounderAction"
|
||||||
private var editor: Editor? = null
|
private var editor: Editor? = null
|
||||||
override fun beforeActionPerformed(action: AnAction, dataContext: DataContext, event: AnActionEvent) {
|
override fun beforeActionPerformed(action: AnAction, event: AnActionEvent) {
|
||||||
if (!VimPlugin.isEnabled()) return
|
if (!VimPlugin.isEnabled()) return
|
||||||
|
|
||||||
val hostEditor = dataContext.getData(CommonDataKeys.HOST_EDITOR)
|
val hostEditor = event.dataContext.getData(CommonDataKeys.HOST_EDITOR)
|
||||||
if (hostEditor != null) {
|
if (hostEditor != null) {
|
||||||
editor = hostEditor
|
editor = hostEditor
|
||||||
}
|
}
|
||||||
@@ -70,14 +71,14 @@ object IdeaSpecifics {
|
|||||||
//region Track action id
|
//region Track action id
|
||||||
if (VimPlugin.getOptionService().isSet(OptionScope.GLOBAL, OptionConstants.trackactionidsName)) {
|
if (VimPlugin.getOptionService().isSet(OptionScope.GLOBAL, OptionConstants.trackactionidsName)) {
|
||||||
if (action !is NotificationService.ActionIdNotifier.CopyActionId && action !is NotificationService.ActionIdNotifier.StopTracking) {
|
if (action !is NotificationService.ActionIdNotifier.CopyActionId && action !is NotificationService.ActionIdNotifier.StopTracking) {
|
||||||
val id: String? = ActionManager.getInstance().getId(action)
|
val id: String? = ActionManager.getInstance().getId(action) ?: (action.shortcutSet as? ProxyShortcutSet)?.actionId
|
||||||
VimPlugin.getNotifications(dataContext.getData(CommonDataKeys.PROJECT)).notifyActionId(id)
|
VimPlugin.getNotifications(event.dataContext.getData(CommonDataKeys.PROJECT)).notifyActionId(id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//endregion
|
//endregion
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun afterActionPerformed(action: AnAction, dataContext: DataContext, event: AnActionEvent) {
|
override fun afterActionPerformed(action: AnAction, event: AnActionEvent, result: AnActionResult) {
|
||||||
if (!VimPlugin.isEnabled()) return
|
if (!VimPlugin.isEnabled()) return
|
||||||
|
|
||||||
//region Enter insert mode after surround with if
|
//region Enter insert mode after surround with if
|
||||||
@@ -88,11 +89,11 @@ object IdeaSpecifics {
|
|||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
editor?.let {
|
editor?.let {
|
||||||
val commandState = it.vim.commandState
|
val commandState = it.vim.vimStateMachine
|
||||||
while (commandState.mode != CommandState.Mode.COMMAND) {
|
while (commandState.mode != VimStateMachine.Mode.COMMAND) {
|
||||||
commandState.popModes()
|
commandState.popModes()
|
||||||
}
|
}
|
||||||
VimPlugin.getChange().insertBeforeCursor(it.vim, dataContext.vim)
|
VimPlugin.getChange().insertBeforeCursor(it.vim, event.dataContext.vim)
|
||||||
KeyHandler.getInstance().reset(it.vim)
|
KeyHandler.getInstance().reset(it.vim)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -21,8 +21,8 @@ package com.maddyhome.idea.vim.listener
|
|||||||
import com.intellij.openapi.actionSystem.ActionManager
|
import com.intellij.openapi.actionSystem.ActionManager
|
||||||
import com.intellij.openapi.actionSystem.AnAction
|
import com.intellij.openapi.actionSystem.AnAction
|
||||||
import com.intellij.openapi.actionSystem.AnActionEvent
|
import com.intellij.openapi.actionSystem.AnActionEvent
|
||||||
|
import com.intellij.openapi.actionSystem.AnActionResult
|
||||||
import com.intellij.openapi.actionSystem.CommonDataKeys
|
import com.intellij.openapi.actionSystem.CommonDataKeys
|
||||||
import com.intellij.openapi.actionSystem.DataContext
|
|
||||||
import com.intellij.openapi.actionSystem.IdeActions
|
import com.intellij.openapi.actionSystem.IdeActions
|
||||||
import com.intellij.openapi.actionSystem.ex.AnActionListener
|
import com.intellij.openapi.actionSystem.ex.AnActionListener
|
||||||
import com.intellij.openapi.editor.Editor
|
import com.intellij.openapi.editor.Editor
|
||||||
@@ -36,16 +36,16 @@ import com.maddyhome.idea.vim.helper.getTopLevelEditor
|
|||||||
class RiderActionListener : AnActionListener {
|
class RiderActionListener : AnActionListener {
|
||||||
|
|
||||||
private var editor: Editor? = null
|
private var editor: Editor? = null
|
||||||
override fun beforeActionPerformed(action: AnAction, dataContext: DataContext, event: AnActionEvent) {
|
override fun beforeActionPerformed(action: AnAction, event: AnActionEvent) {
|
||||||
if (!VimPlugin.isEnabled()) return
|
if (!VimPlugin.isEnabled()) return
|
||||||
|
|
||||||
val hostEditor = dataContext.getData(CommonDataKeys.HOST_EDITOR)
|
val hostEditor = event.dataContext.getData(CommonDataKeys.HOST_EDITOR)
|
||||||
if (hostEditor != null) {
|
if (hostEditor != null) {
|
||||||
editor = hostEditor
|
editor = hostEditor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun afterActionPerformed(action: AnAction, dataContext: DataContext, event: AnActionEvent) {
|
override fun afterActionPerformed(action: AnAction, event: AnActionEvent, result: AnActionResult) {
|
||||||
if (!VimPlugin.isEnabled()) return
|
if (!VimPlugin.isEnabled()) return
|
||||||
|
|
||||||
//region Extend Selection for Rider
|
//region Extend Selection for Rider
|
||||||
|
@@ -44,7 +44,7 @@ import com.maddyhome.idea.vim.KeyHandler
|
|||||||
import com.maddyhome.idea.vim.VimKeyListener
|
import com.maddyhome.idea.vim.VimKeyListener
|
||||||
import com.maddyhome.idea.vim.VimPlugin
|
import com.maddyhome.idea.vim.VimPlugin
|
||||||
import com.maddyhome.idea.vim.VimTypedActionHandler
|
import com.maddyhome.idea.vim.VimTypedActionHandler
|
||||||
import com.maddyhome.idea.vim.command.CommandState
|
import com.maddyhome.idea.vim.command.VimStateMachine
|
||||||
import com.maddyhome.idea.vim.ex.ExOutputModel
|
import com.maddyhome.idea.vim.ex.ExOutputModel
|
||||||
import com.maddyhome.idea.vim.group.EditorGroup
|
import com.maddyhome.idea.vim.group.EditorGroup
|
||||||
import com.maddyhome.idea.vim.group.FileGroup
|
import com.maddyhome.idea.vim.group.FileGroup
|
||||||
@@ -122,9 +122,9 @@ object VimListenerManager {
|
|||||||
VimPlugin.getOptionService().addListener(OptionConstants.guicursorName, GuicursorChangeListener)
|
VimPlugin.getOptionService().addListener(OptionConstants.guicursorName, GuicursorChangeListener)
|
||||||
VimPlugin.getOptionService().addListener(OptionConstants.iskeywordName, KeywordOptionChangeListener, true)
|
VimPlugin.getOptionService().addListener(OptionConstants.iskeywordName, KeywordOptionChangeListener, true)
|
||||||
|
|
||||||
EventFacade.getInstance().addEditorFactoryListener(VimEditorFactoryListener, VimPlugin.getInstance())
|
EventFacade.getInstance().addEditorFactoryListener(VimEditorFactoryListener, VimPlugin.getInstance().onOffDisposable)
|
||||||
|
|
||||||
EditorFactory.getInstance().eventMulticaster.addCaretListener(VimCaretListener, VimPlugin.getInstance())
|
EditorFactory.getInstance().eventMulticaster.addCaretListener(VimCaretListener, VimPlugin.getInstance().onOffDisposable)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun disable() {
|
fun disable() {
|
||||||
@@ -136,10 +136,6 @@ object VimListenerManager {
|
|||||||
VimPlugin.getOptionService().removeListener(OptionConstants.showcmdName, ShowCmdOptionChangeListener)
|
VimPlugin.getOptionService().removeListener(OptionConstants.showcmdName, ShowCmdOptionChangeListener)
|
||||||
VimPlugin.getOptionService().removeListener(OptionConstants.guicursorName, GuicursorChangeListener)
|
VimPlugin.getOptionService().removeListener(OptionConstants.guicursorName, GuicursorChangeListener)
|
||||||
VimPlugin.getOptionService().removeListener(OptionConstants.iskeywordName, KeywordOptionChangeListener)
|
VimPlugin.getOptionService().removeListener(OptionConstants.iskeywordName, KeywordOptionChangeListener)
|
||||||
|
|
||||||
EventFacade.getInstance().removeEditorFactoryListener(VimEditorFactoryListener)
|
|
||||||
|
|
||||||
EditorFactory.getInstance().eventMulticaster.removeCaretListener(VimCaretListener)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -425,7 +421,7 @@ object VimListenerManager {
|
|||||||
ExOutputModel.getInstance(editor).clear()
|
ExOutputModel.getInstance(editor).clear()
|
||||||
|
|
||||||
val caretModel = editor.caretModel
|
val caretModel = editor.caretModel
|
||||||
if (editor.subMode != CommandState.SubMode.NONE) {
|
if (editor.subMode != VimStateMachine.SubMode.NONE) {
|
||||||
caretModel.removeSecondaryCarets()
|
caretModel.removeSecondaryCarets()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -28,11 +28,12 @@ import com.maddyhome.idea.vim.VimPlugin
|
|||||||
import com.maddyhome.idea.vim.api.ExecutionContext
|
import com.maddyhome.idea.vim.api.ExecutionContext
|
||||||
import com.maddyhome.idea.vim.api.LineDeleteShift
|
import com.maddyhome.idea.vim.api.LineDeleteShift
|
||||||
import com.maddyhome.idea.vim.api.VimCaret
|
import com.maddyhome.idea.vim.api.VimCaret
|
||||||
|
import com.maddyhome.idea.vim.api.VimChangeGroupBase
|
||||||
import com.maddyhome.idea.vim.api.VimEditor
|
import com.maddyhome.idea.vim.api.VimEditor
|
||||||
import com.maddyhome.idea.vim.api.VimMotionGroupBase
|
import com.maddyhome.idea.vim.api.VimMotionGroupBase
|
||||||
import com.maddyhome.idea.vim.api.injector
|
import com.maddyhome.idea.vim.api.injector
|
||||||
import com.maddyhome.idea.vim.command.CommandState
|
|
||||||
import com.maddyhome.idea.vim.command.SelectionType
|
import com.maddyhome.idea.vim.command.SelectionType
|
||||||
|
import com.maddyhome.idea.vim.command.VimStateMachine
|
||||||
import com.maddyhome.idea.vim.common.EditorLine
|
import com.maddyhome.idea.vim.common.EditorLine
|
||||||
import com.maddyhome.idea.vim.common.IndentConfig
|
import com.maddyhome.idea.vim.common.IndentConfig
|
||||||
import com.maddyhome.idea.vim.common.OperatedRange
|
import com.maddyhome.idea.vim.common.OperatedRange
|
||||||
@@ -40,7 +41,6 @@ import com.maddyhome.idea.vim.common.TextRange
|
|||||||
import com.maddyhome.idea.vim.common.VimRange
|
import com.maddyhome.idea.vim.common.VimRange
|
||||||
import com.maddyhome.idea.vim.common.including
|
import com.maddyhome.idea.vim.common.including
|
||||||
import com.maddyhome.idea.vim.common.offset
|
import com.maddyhome.idea.vim.common.offset
|
||||||
import com.maddyhome.idea.vim.group.ChangeGroup
|
|
||||||
import com.maddyhome.idea.vim.group.MotionGroup
|
import com.maddyhome.idea.vim.group.MotionGroup
|
||||||
import com.maddyhome.idea.vim.helper.EditorHelper
|
import com.maddyhome.idea.vim.helper.EditorHelper
|
||||||
import com.maddyhome.idea.vim.helper.inlayAwareVisualColumn
|
import com.maddyhome.idea.vim.helper.inlayAwareVisualColumn
|
||||||
@@ -62,7 +62,7 @@ fun changeRange(
|
|||||||
var col = 0
|
var col = 0
|
||||||
var lines = 0
|
var lines = 0
|
||||||
if (type === SelectionType.BLOCK_WISE) {
|
if (type === SelectionType.BLOCK_WISE) {
|
||||||
lines = ChangeGroup.getLinesCountInVisualBlock(IjVimEditor(editor), range)
|
lines = VimChangeGroupBase.getLinesCountInVisualBlock(IjVimEditor(editor), range)
|
||||||
col = editor.offsetToLogicalPosition(range.startOffset).column
|
col = editor.offsetToLogicalPosition(range.startOffset).column
|
||||||
if (caret.vimLastColumn == VimMotionGroupBase.LAST_COLUMN) {
|
if (caret.vimLastColumn == VimMotionGroupBase.LAST_COLUMN) {
|
||||||
col = VimMotionGroupBase.LAST_COLUMN
|
col = VimMotionGroupBase.LAST_COLUMN
|
||||||
@@ -99,11 +99,12 @@ fun changeRange(
|
|||||||
vimCaret.moveToOffset(deletedInfo.leftOffset.point)
|
vimCaret.moveToOffset(deletedInfo.leftOffset.point)
|
||||||
}
|
}
|
||||||
is OperatedRange.Block -> TODO()
|
is OperatedRange.Block -> TODO()
|
||||||
|
else -> TODO()
|
||||||
}
|
}
|
||||||
if (type == SelectionType.BLOCK_WISE) {
|
if (type == SelectionType.BLOCK_WISE) {
|
||||||
VimPlugin.getChange().setInsertRepeat(lines, col, false)
|
VimPlugin.getChange().setInsertRepeat(lines, col, false)
|
||||||
}
|
}
|
||||||
editor.vimChangeActionSwitchMode = CommandState.Mode.INSERT
|
editor.vimChangeActionSwitchMode = VimStateMachine.Mode.INSERT
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
VimPlugin.getChange().insertBeforeCursor(editor.vim, context.vim)
|
VimPlugin.getChange().insertBeforeCursor(editor.vim, context.vim)
|
||||||
@@ -158,9 +159,9 @@ fun deleteRange(
|
|||||||
fun insertLineAround(editor: VimEditor, context: ExecutionContext, shift: Int) {
|
fun insertLineAround(editor: VimEditor, context: ExecutionContext, shift: Int) {
|
||||||
val project = (editor as IjVimEditor).editor.project
|
val project = (editor as IjVimEditor).editor.project
|
||||||
|
|
||||||
VimPlugin.getChange().initInsert(editor, context, CommandState.Mode.INSERT)
|
VimPlugin.getChange().initInsert(editor, context, VimStateMachine.Mode.INSERT)
|
||||||
|
|
||||||
if (!CommandState.getInstance(editor).isDotRepeatInProgress) {
|
if (!VimStateMachine.getInstance(editor).isDotRepeatInProgress) {
|
||||||
for (vimCaret in editor.carets()) {
|
for (vimCaret in editor.carets()) {
|
||||||
val caret = (vimCaret as IjVimCaret).caret
|
val caret = (vimCaret as IjVimCaret).caret
|
||||||
val line = vimCaret.getLine()
|
val line = vimCaret.getLine()
|
||||||
@@ -179,7 +180,7 @@ fun insertLineAround(editor: VimEditor, context: ExecutionContext, shift: Int) {
|
|||||||
}
|
}
|
||||||
val position = EditorLine.Offset.init(editor.offsetToLogicalPosition(lineEndOffset).line + shift, editor)
|
val position = EditorLine.Offset.init(editor.offsetToLogicalPosition(lineEndOffset).line + shift, editor)
|
||||||
|
|
||||||
val insertedLine = editor.addLine(position) ?: continue
|
val insertedLine = editor.addLine(position)
|
||||||
VimPlugin.getChange().saveStrokes("\n")
|
VimPlugin.getChange().saveStrokes("\n")
|
||||||
|
|
||||||
var lineStart = editor.getLineRange(insertedLine).first
|
var lineStart = editor.getLineRange(insertedLine).first
|
||||||
|
@@ -49,6 +49,7 @@ class IjClipboardManager : VimClipboardManager {
|
|||||||
return Pair(res, transferableData)
|
return Pair(res, transferableData)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
override fun setClipboardText(text: String, rawText: String, transferableData: List<Any>): Any? {
|
override fun setClipboardText(text: String, rawText: String, transferableData: List<Any>): Any? {
|
||||||
val transferableData1 = (transferableData as List<TextBlockTransferableData>).toMutableList()
|
val transferableData1 = (transferableData as List<TextBlockTransferableData>).toMutableList()
|
||||||
try {
|
try {
|
||||||
@@ -97,6 +98,7 @@ class IjClipboardManager : VimClipboardManager {
|
|||||||
return transferableData
|
return transferableData
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
override fun preprocessText(
|
override fun preprocessText(
|
||||||
vimEditor: VimEditor,
|
vimEditor: VimEditor,
|
||||||
textRange: TextRange,
|
textRange: TextRange,
|
||||||
|
@@ -33,11 +33,11 @@ class IjExecutionContextManager : ExecutionContextManagerBase() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onCaret(caret: VimCaret, prevContext: ExecutionContext): ExecutionContext {
|
override fun onCaret(caret: VimCaret, prevContext: ExecutionContext): ExecutionContext {
|
||||||
return IjExecutionContext(CaretSpecificDataContext(prevContext.ij, caret.ij))
|
return IjExecutionContext(CaretSpecificDataContext.create(prevContext.ij, caret.ij))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun createCaretSpecificDataContext(context: ExecutionContext, caret: VimCaret): ExecutionContext {
|
override fun createCaretSpecificDataContext(context: ExecutionContext, caret: VimCaret): ExecutionContext {
|
||||||
return IjExecutionContext(CaretSpecificDataContext(context.ij, caret.ij))
|
return IjExecutionContext(CaretSpecificDataContext.create(context.ij, caret.ij))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun createEditorDataContext(editor: VimEditor, context: ExecutionContext): ExecutionContext {
|
override fun createEditorDataContext(editor: VimEditor, context: ExecutionContext): ExecutionContext {
|
||||||
|
@@ -22,7 +22,10 @@ import com.intellij.openapi.editor.Caret
|
|||||||
import com.intellij.openapi.editor.LogicalPosition
|
import com.intellij.openapi.editor.LogicalPosition
|
||||||
import com.intellij.openapi.editor.VisualPosition
|
import com.intellij.openapi.editor.VisualPosition
|
||||||
import com.maddyhome.idea.vim.VimPlugin
|
import com.maddyhome.idea.vim.VimPlugin
|
||||||
|
import com.maddyhome.idea.vim.api.CaretRegisterStorage
|
||||||
|
import com.maddyhome.idea.vim.api.CaretRegisterStorageBase
|
||||||
import com.maddyhome.idea.vim.api.VimCaret
|
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.VimEditor
|
||||||
import com.maddyhome.idea.vim.api.VimLogicalPosition
|
import com.maddyhome.idea.vim.api.VimLogicalPosition
|
||||||
import com.maddyhome.idea.vim.api.VimVisualPosition
|
import com.maddyhome.idea.vim.api.VimVisualPosition
|
||||||
@@ -38,13 +41,23 @@ import com.maddyhome.idea.vim.group.visual.vimSetSystemSelectionSilently
|
|||||||
import com.maddyhome.idea.vim.group.visual.vimUpdateEditorSelection
|
import com.maddyhome.idea.vim.group.visual.vimUpdateEditorSelection
|
||||||
import com.maddyhome.idea.vim.helper.inlayAwareVisualColumn
|
import com.maddyhome.idea.vim.helper.inlayAwareVisualColumn
|
||||||
import com.maddyhome.idea.vim.helper.moveToInlayAwareOffset
|
import com.maddyhome.idea.vim.helper.moveToInlayAwareOffset
|
||||||
|
import com.maddyhome.idea.vim.helper.registerStorage
|
||||||
import com.maddyhome.idea.vim.helper.vimInsertStart
|
import com.maddyhome.idea.vim.helper.vimInsertStart
|
||||||
import com.maddyhome.idea.vim.helper.vimLastColumn
|
import com.maddyhome.idea.vim.helper.vimLastColumn
|
||||||
import com.maddyhome.idea.vim.helper.vimLastVisualOperatorRange
|
import com.maddyhome.idea.vim.helper.vimLastVisualOperatorRange
|
||||||
import com.maddyhome.idea.vim.helper.vimLine
|
import com.maddyhome.idea.vim.helper.vimLine
|
||||||
import com.maddyhome.idea.vim.helper.vimSelectionStart
|
import com.maddyhome.idea.vim.helper.vimSelectionStart
|
||||||
|
|
||||||
class IjVimCaret(val caret: Caret) : VimCaret {
|
class IjVimCaret(val caret: Caret) : VimCaretBase() {
|
||||||
|
override val registerStorage: CaretRegisterStorage
|
||||||
|
get() {
|
||||||
|
var storage = this.caret.registerStorage
|
||||||
|
if (storage == null) {
|
||||||
|
storage = CaretRegisterStorageBase(editor.primaryCaret().ij == caret)
|
||||||
|
this.caret.registerStorage = storage
|
||||||
|
}
|
||||||
|
return storage
|
||||||
|
}
|
||||||
override val editor: VimEditor
|
override val editor: VimEditor
|
||||||
get() = IjVimEditor(caret.editor)
|
get() = IjVimEditor(caret.editor)
|
||||||
override val offset: Offset
|
override val offset: Offset
|
||||||
|
@@ -38,9 +38,9 @@ import com.maddyhome.idea.vim.api.VimLogicalPosition
|
|||||||
import com.maddyhome.idea.vim.api.VimSelectionModel
|
import com.maddyhome.idea.vim.api.VimSelectionModel
|
||||||
import com.maddyhome.idea.vim.api.VimVisualPosition
|
import com.maddyhome.idea.vim.api.VimVisualPosition
|
||||||
import com.maddyhome.idea.vim.api.VirtualFile
|
import com.maddyhome.idea.vim.api.VirtualFile
|
||||||
import com.maddyhome.idea.vim.command.CommandState
|
|
||||||
import com.maddyhome.idea.vim.command.OperatorArguments
|
import com.maddyhome.idea.vim.command.OperatorArguments
|
||||||
import com.maddyhome.idea.vim.command.SelectionType
|
import com.maddyhome.idea.vim.command.SelectionType
|
||||||
|
import com.maddyhome.idea.vim.command.VimStateMachine
|
||||||
import com.maddyhome.idea.vim.common.EditorLine
|
import com.maddyhome.idea.vim.common.EditorLine
|
||||||
import com.maddyhome.idea.vim.common.LiveRange
|
import com.maddyhome.idea.vim.common.LiveRange
|
||||||
import com.maddyhome.idea.vim.common.Offset
|
import com.maddyhome.idea.vim.common.Offset
|
||||||
@@ -62,7 +62,9 @@ import com.maddyhome.idea.vim.helper.updateCaretsVisualPosition
|
|||||||
import com.maddyhome.idea.vim.helper.vimChangeActionSwitchMode
|
import com.maddyhome.idea.vim.helper.vimChangeActionSwitchMode
|
||||||
import com.maddyhome.idea.vim.helper.vimKeepingVisualOperatorAction
|
import com.maddyhome.idea.vim.helper.vimKeepingVisualOperatorAction
|
||||||
import com.maddyhome.idea.vim.helper.vimLastSelectionType
|
import com.maddyhome.idea.vim.helper.vimLastSelectionType
|
||||||
|
import org.jetbrains.annotations.ApiStatus
|
||||||
|
|
||||||
|
@ApiStatus.Internal
|
||||||
class IjVimEditor(editor: Editor) : MutableLinearEditor() {
|
class IjVimEditor(editor: Editor) : MutableLinearEditor() {
|
||||||
|
|
||||||
// All the editor actions should be performed with top level editor!!!
|
// All the editor actions should be performed with top level editor!!!
|
||||||
@@ -72,7 +74,7 @@ class IjVimEditor(editor: Editor) : MutableLinearEditor() {
|
|||||||
val originalEditor = editor
|
val originalEditor = editor
|
||||||
|
|
||||||
override val lfMakesNewLine: Boolean = true
|
override val lfMakesNewLine: Boolean = true
|
||||||
override var vimChangeActionSwitchMode: CommandState.Mode?
|
override var vimChangeActionSwitchMode: VimStateMachine.Mode?
|
||||||
get() = editor.vimChangeActionSwitchMode
|
get() = editor.vimChangeActionSwitchMode
|
||||||
set(value) {
|
set(value) {
|
||||||
editor.vimChangeActionSwitchMode = value
|
editor.vimChangeActionSwitchMode = value
|
||||||
|
@@ -3,6 +3,7 @@ package com.maddyhome.idea.vim.newapi
|
|||||||
import com.intellij.openapi.components.service
|
import com.intellij.openapi.components.service
|
||||||
import com.intellij.openapi.components.serviceIfCreated
|
import com.intellij.openapi.components.serviceIfCreated
|
||||||
import com.intellij.openapi.diagnostic.Logger
|
import com.intellij.openapi.diagnostic.Logger
|
||||||
|
import com.intellij.openapi.editor.Editor
|
||||||
import com.maddyhome.idea.vim.api.EngineEditorHelper
|
import com.maddyhome.idea.vim.api.EngineEditorHelper
|
||||||
import com.maddyhome.idea.vim.api.ExEntryPanel
|
import com.maddyhome.idea.vim.api.ExEntryPanel
|
||||||
import com.maddyhome.idea.vim.api.ExecutionContextManager
|
import com.maddyhome.idea.vim.api.ExecutionContextManager
|
||||||
@@ -39,7 +40,7 @@ import com.maddyhome.idea.vim.api.VimrcFileState
|
|||||||
import com.maddyhome.idea.vim.api.VimscriptExecutor
|
import com.maddyhome.idea.vim.api.VimscriptExecutor
|
||||||
import com.maddyhome.idea.vim.api.VimscriptFunctionService
|
import com.maddyhome.idea.vim.api.VimscriptFunctionService
|
||||||
import com.maddyhome.idea.vim.api.VimscriptParser
|
import com.maddyhome.idea.vim.api.VimscriptParser
|
||||||
import com.maddyhome.idea.vim.command.CommandState
|
import com.maddyhome.idea.vim.command.VimStateMachine
|
||||||
import com.maddyhome.idea.vim.common.VimMachine
|
import com.maddyhome.idea.vim.common.VimMachine
|
||||||
import com.maddyhome.idea.vim.diagnostic.VimLogger
|
import com.maddyhome.idea.vim.diagnostic.VimLogger
|
||||||
import com.maddyhome.idea.vim.ex.ExOutputModel
|
import com.maddyhome.idea.vim.ex.ExOutputModel
|
||||||
@@ -63,19 +64,19 @@ import com.maddyhome.idea.vim.helper.IjEditorHelper
|
|||||||
import com.maddyhome.idea.vim.helper.IjVimStringParser
|
import com.maddyhome.idea.vim.helper.IjVimStringParser
|
||||||
import com.maddyhome.idea.vim.helper.UndoRedoHelper
|
import com.maddyhome.idea.vim.helper.UndoRedoHelper
|
||||||
import com.maddyhome.idea.vim.helper.VimCommandLineHelper
|
import com.maddyhome.idea.vim.helper.VimCommandLineHelper
|
||||||
import com.maddyhome.idea.vim.helper.vimCommandState
|
import com.maddyhome.idea.vim.helper.vimStateMachine
|
||||||
import com.maddyhome.idea.vim.history.VimHistory
|
import com.maddyhome.idea.vim.history.VimHistory
|
||||||
import com.maddyhome.idea.vim.macro.VimMacro
|
import com.maddyhome.idea.vim.macro.VimMacro
|
||||||
import com.maddyhome.idea.vim.mark.VimMarkGroup
|
import com.maddyhome.idea.vim.mark.VimMarkGroup
|
||||||
import com.maddyhome.idea.vim.options.OptionService
|
|
||||||
import com.maddyhome.idea.vim.put.VimPut
|
import com.maddyhome.idea.vim.put.VimPut
|
||||||
import com.maddyhome.idea.vim.register.VimRegisterGroup
|
import com.maddyhome.idea.vim.register.VimRegisterGroup
|
||||||
import com.maddyhome.idea.vim.ui.VimRcFileState
|
import com.maddyhome.idea.vim.ui.VimRcFileState
|
||||||
import com.maddyhome.idea.vim.undo.VimUndoRedo
|
import com.maddyhome.idea.vim.undo.VimUndoRedo
|
||||||
import com.maddyhome.idea.vim.vimscript.Executor
|
import com.maddyhome.idea.vim.vimscript.Executor
|
||||||
import com.maddyhome.idea.vim.vimscript.services.FunctionStorage
|
import com.maddyhome.idea.vim.vimscript.services.FunctionStorage
|
||||||
|
import com.maddyhome.idea.vim.vimscript.services.OptionService
|
||||||
import com.maddyhome.idea.vim.vimscript.services.PatternService
|
import com.maddyhome.idea.vim.vimscript.services.PatternService
|
||||||
import com.maddyhome.idea.vim.vimscript.services.VimVariableService
|
import com.maddyhome.idea.vim.vimscript.services.VariableService
|
||||||
import com.maddyhome.idea.vim.yank.VimYankGroup
|
import com.maddyhome.idea.vim.yank.VimYankGroup
|
||||||
|
|
||||||
class IjVimInjector : VimInjectorBase() {
|
class IjVimInjector : VimInjectorBase() {
|
||||||
@@ -160,7 +161,7 @@ class IjVimInjector : VimInjectorBase() {
|
|||||||
|
|
||||||
override val functionService: VimscriptFunctionService
|
override val functionService: VimscriptFunctionService
|
||||||
get() = FunctionStorage
|
get() = FunctionStorage
|
||||||
override val variableService: VimVariableService
|
override val variableService: VariableService
|
||||||
get() = service()
|
get() = service()
|
||||||
override val vimrcFileState: VimrcFileState
|
override val vimrcFileState: VimrcFileState
|
||||||
get() = VimRcFileState
|
get() = VimRcFileState
|
||||||
@@ -179,15 +180,23 @@ class IjVimInjector : VimInjectorBase() {
|
|||||||
override val vimStorageService: VimStorageService
|
override val vimStorageService: VimStorageService
|
||||||
get() = service()
|
get() = service()
|
||||||
|
|
||||||
override fun commandStateFor(editor: VimEditor): CommandState {
|
override fun commandStateFor(editor: VimEditor): VimStateMachine {
|
||||||
var res = editor.ij.vimCommandState
|
var res = editor.ij.vimStateMachine
|
||||||
if (res == null) {
|
if (res == null) {
|
||||||
res = CommandState(editor)
|
res = VimStateMachine(editor)
|
||||||
editor.ij.vimCommandState = res
|
editor.ij.vimStateMachine = res
|
||||||
}
|
}
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun commandStateFor(editor: Any): VimStateMachine {
|
||||||
|
return when (editor) {
|
||||||
|
is VimEditor -> this.commandStateFor(editor)
|
||||||
|
is Editor -> this.commandStateFor(IjVimEditor(editor))
|
||||||
|
else -> error("Unexpected type: $editor")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override val engineEditorHelper: EngineEditorHelper
|
override val engineEditorHelper: EngineEditorHelper
|
||||||
get() = service<IjEditorHelper>()
|
get() = service<IjEditorHelper>()
|
||||||
override val editorGroup: VimEditorGroup
|
override val editorGroup: VimEditorGroup
|
||||||
|
@@ -37,19 +37,19 @@ class IjVimMessages : VimMessagesBase() {
|
|||||||
private var error = false
|
private var error = false
|
||||||
private var lastBeepTimeMillis = 0L
|
private var lastBeepTimeMillis = 0L
|
||||||
|
|
||||||
override fun showStatusBarMessage(msg: String?) {
|
override fun showStatusBarMessage(message: String?) {
|
||||||
if (ApplicationManager.getApplication().isUnitTestMode) {
|
if (ApplicationManager.getApplication().isUnitTestMode) {
|
||||||
message = msg
|
this.message = message
|
||||||
}
|
}
|
||||||
val pm = ProjectManager.getInstance()
|
val pm = ProjectManager.getInstance()
|
||||||
val projects = pm.openProjects
|
val projects = pm.openProjects
|
||||||
for (project in projects) {
|
for (project in projects) {
|
||||||
val bar = WindowManager.getInstance().getStatusBar(project)
|
val bar = WindowManager.getInstance().getStatusBar(project)
|
||||||
if (bar != null) {
|
if (bar != null) {
|
||||||
if (msg.isNullOrEmpty()) {
|
if (message.isNullOrEmpty()) {
|
||||||
bar.info = ""
|
bar.info = ""
|
||||||
} else {
|
} else {
|
||||||
bar.info = "VIM - $msg"
|
bar.info = "VIM - $message"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -110,6 +110,17 @@ class IjVimSearchHelper : VimSearchHelper {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun findNextWordEnd(
|
||||||
|
chars: CharSequence,
|
||||||
|
pos: Int,
|
||||||
|
size: Int,
|
||||||
|
count: Int,
|
||||||
|
bigWord: Boolean,
|
||||||
|
spaceWords: Boolean,
|
||||||
|
): Int {
|
||||||
|
return SearchHelper.findNextWordEnd(chars, pos, size, count, bigWord, spaceWords)
|
||||||
|
}
|
||||||
|
|
||||||
override fun findNextWord(editor: VimEditor, searchFrom: Int, count: Int, bigWord: Boolean): Int {
|
override fun findNextWord(editor: VimEditor, searchFrom: Int, count: Int, bigWord: Boolean): Int {
|
||||||
return SearchHelper.findNextWord(
|
return SearchHelper.findNextWord(
|
||||||
(editor as IjVimEditor).editor,
|
(editor as IjVimEditor).editor,
|
||||||
|
@@ -0,0 +1,60 @@
|
|||||||
|
/*
|
||||||
|
* IdeaVim - Vim emulator for IDEs based on the IntelliJ platform
|
||||||
|
* Copyright (C) 2003-2022 The IdeaVim authors
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.maddyhome.idea.vim.option
|
||||||
|
|
||||||
|
import com.maddyhome.idea.vim.api.injector
|
||||||
|
import com.maddyhome.idea.vim.options.OptionConstants
|
||||||
|
import com.maddyhome.idea.vim.options.OptionConstants.Companion.ignorecaseName
|
||||||
|
import com.maddyhome.idea.vim.options.OptionConstants.Companion.smartcaseName
|
||||||
|
import com.maddyhome.idea.vim.options.OptionConstants.Companion.timeoutName
|
||||||
|
import com.maddyhome.idea.vim.options.OptionConstants.Companion.timeoutlenName
|
||||||
|
import com.maddyhome.idea.vim.options.OptionScope
|
||||||
|
import com.maddyhome.idea.vim.options.helpers.KeywordOptionHelper
|
||||||
|
import com.maddyhome.idea.vim.vimscript.services.IjVimOptionService
|
||||||
|
|
||||||
|
/**
|
||||||
|
* COMPATIBILITY-LAYER: Added a class and package
|
||||||
|
* Please see: https://jb.gg/zo8n0r
|
||||||
|
*/
|
||||||
|
object OptionsManager {
|
||||||
|
val ignorecase: ToggleOption
|
||||||
|
get() = (injector.optionService as IjVimOptionService).getOptionByNameOrAbbr(ignorecaseName) as ToggleOption
|
||||||
|
val smartcase: ToggleOption
|
||||||
|
get() = (injector.optionService as IjVimOptionService).getOptionByNameOrAbbr(smartcaseName) as ToggleOption
|
||||||
|
val timeout: ToggleOption
|
||||||
|
get() = (injector.optionService as IjVimOptionService).getOptionByNameOrAbbr(timeoutName) as ToggleOption
|
||||||
|
val timeoutlen: NumberOption
|
||||||
|
get() = (injector.optionService as IjVimOptionService).getOptionByNameOrAbbr(timeoutlenName) as NumberOption
|
||||||
|
val iskeyword: KeywordOption
|
||||||
|
get() = KeywordOption(KeywordOptionHelper)
|
||||||
|
}
|
||||||
|
|
||||||
|
class KeywordOption(val helper: KeywordOptionHelper) {
|
||||||
|
fun toRegex(): List<String> {
|
||||||
|
return helper.toRegex()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object StrictMode {
|
||||||
|
fun fail(message: String) {
|
||||||
|
if (injector.optionService.isSet(OptionScope.GLOBAL, OptionConstants.ideastrictmodeName)) {
|
||||||
|
error(message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -18,6 +18,7 @@
|
|||||||
|
|
||||||
package com.maddyhome.idea.vim.statistic
|
package com.maddyhome.idea.vim.statistic
|
||||||
|
|
||||||
|
import com.intellij.internal.statistic.collectors.fus.actions.persistence.ActionRuleValidator
|
||||||
import com.intellij.internal.statistic.eventLog.EventLogGroup
|
import com.intellij.internal.statistic.eventLog.EventLogGroup
|
||||||
import com.intellij.internal.statistic.eventLog.events.EventFields
|
import com.intellij.internal.statistic.eventLog.events.EventFields
|
||||||
import com.intellij.internal.statistic.service.fus.collectors.CounterUsagesCollector
|
import com.intellij.internal.statistic.service.fus.collectors.CounterUsagesCollector
|
||||||
@@ -25,8 +26,14 @@ import com.intellij.internal.statistic.service.fus.collectors.CounterUsagesColle
|
|||||||
internal class ActionTracker : CounterUsagesCollector() {
|
internal class ActionTracker : CounterUsagesCollector() {
|
||||||
companion object {
|
companion object {
|
||||||
private val GROUP = EventLogGroup("vim.actions", 1)
|
private val GROUP = EventLogGroup("vim.actions", 1)
|
||||||
private val TRACKED_ACTIONS = GROUP.registerEvent("tracked", EventFields.StringValidatedByCustomRule("action_id", "action"))
|
private val TRACKED_ACTIONS = GROUP.registerEvent(
|
||||||
private val COPIED_ACTIONS = GROUP.registerEvent("copied", EventFields.StringValidatedByCustomRule("action_id", "action"))
|
"tracked",
|
||||||
|
EventFields.StringValidatedByCustomRule("action_id", ActionRuleValidator::class.java)
|
||||||
|
)
|
||||||
|
private val COPIED_ACTIONS = GROUP.registerEvent(
|
||||||
|
"copied",
|
||||||
|
EventFields.StringValidatedByCustomRule("action_id", ActionRuleValidator::class.java)
|
||||||
|
)
|
||||||
|
|
||||||
fun logTrackedAction(actionId: String) {
|
fun logTrackedAction(actionId: String) {
|
||||||
TRACKED_ACTIONS.log(actionId)
|
TRACKED_ACTIONS.log(actionId)
|
||||||
|
@@ -4,7 +4,7 @@ import com.intellij.openapi.components.Service
|
|||||||
import com.intellij.openapi.components.service
|
import com.intellij.openapi.components.service
|
||||||
import com.intellij.util.containers.MultiMap
|
import com.intellij.util.containers.MultiMap
|
||||||
import com.maddyhome.idea.vim.api.injector
|
import com.maddyhome.idea.vim.api.injector
|
||||||
import com.maddyhome.idea.vim.common.MappingMode
|
import com.maddyhome.idea.vim.command.MappingMode
|
||||||
import com.maddyhome.idea.vim.key.MappingOwner
|
import com.maddyhome.idea.vim.key.MappingOwner
|
||||||
import com.maddyhome.idea.vim.key.ToKeysMappingInfo
|
import com.maddyhome.idea.vim.key.ToKeysMappingInfo
|
||||||
|
|
||||||
|
@@ -20,8 +20,8 @@ package com.maddyhome.idea.vim.ui
|
|||||||
|
|
||||||
import com.maddyhome.idea.vim.KeyHandler
|
import com.maddyhome.idea.vim.KeyHandler
|
||||||
import com.maddyhome.idea.vim.api.VimEditor
|
import com.maddyhome.idea.vim.api.VimEditor
|
||||||
import com.maddyhome.idea.vim.helper.commandState
|
|
||||||
import com.maddyhome.idea.vim.helper.isCloseKeyStroke
|
import com.maddyhome.idea.vim.helper.isCloseKeyStroke
|
||||||
|
import com.maddyhome.idea.vim.helper.vimStateMachine
|
||||||
import java.awt.KeyEventDispatcher
|
import java.awt.KeyEventDispatcher
|
||||||
import java.awt.KeyboardFocusManager
|
import java.awt.KeyboardFocusManager
|
||||||
import java.awt.Toolkit
|
import java.awt.Toolkit
|
||||||
@@ -62,7 +62,7 @@ object ModalEntry {
|
|||||||
} else {
|
} else {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
if (editor.commandState.isRecording) {
|
if (editor.vimStateMachine.isRecording) {
|
||||||
KeyHandler.getInstance().modalEntryKeys += stroke
|
KeyHandler.getInstance().modalEntryKeys += stroke
|
||||||
}
|
}
|
||||||
if (!processor(stroke)) {
|
if (!processor(stroke)) {
|
||||||
|
@@ -33,7 +33,7 @@ import com.intellij.util.Consumer
|
|||||||
import com.maddyhome.idea.vim.VimPlugin
|
import com.maddyhome.idea.vim.VimPlugin
|
||||||
import com.maddyhome.idea.vim.helper.EngineStringHelper
|
import com.maddyhome.idea.vim.helper.EngineStringHelper
|
||||||
import com.maddyhome.idea.vim.helper.VimNlsSafe
|
import com.maddyhome.idea.vim.helper.VimNlsSafe
|
||||||
import com.maddyhome.idea.vim.helper.commandState
|
import com.maddyhome.idea.vim.helper.vimStateMachine
|
||||||
import com.maddyhome.idea.vim.newapi.vim
|
import com.maddyhome.idea.vim.newapi.vim
|
||||||
import com.maddyhome.idea.vim.options.OptionChangeListener
|
import com.maddyhome.idea.vim.options.OptionChangeListener
|
||||||
import com.maddyhome.idea.vim.options.OptionConstants
|
import com.maddyhome.idea.vim.options.OptionConstants
|
||||||
@@ -70,7 +70,7 @@ object ShowCmd {
|
|||||||
fun getFullText(editor: Editor?): String {
|
fun getFullText(editor: Editor?): String {
|
||||||
if (!VimPlugin.getOptionService().isSet(OptionScope.GLOBAL, OptionConstants.showcmdName) || editor == null || editor.isDisposed) return ""
|
if (!VimPlugin.getOptionService().isSet(OptionScope.GLOBAL, OptionConstants.showcmdName) || editor == null || editor.isDisposed) return ""
|
||||||
|
|
||||||
val editorState = editor.vim.commandState
|
val editorState = editor.vim.vimStateMachine
|
||||||
return EngineStringHelper.toPrintableCharacters(editorState.commandBuilder.keys + editorState.mappingState.keys)
|
return EngineStringHelper.toPrintableCharacters(editorState.commandBuilder.keys + editorState.mappingState.keys)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -48,13 +48,13 @@ class Executor : VimScriptExecutorBase() {
|
|||||||
override var executingVimscript = false
|
override var executingVimscript = false
|
||||||
|
|
||||||
@Throws(ExException::class)
|
@Throws(ExException::class)
|
||||||
override fun execute(scriptString: String, editor: VimEditor, context: ExecutionContext, skipHistory: Boolean, indicateErrors: Boolean, vimContext: VimLContext?): ExecutionResult {
|
override fun execute(script: String, editor: VimEditor, context: ExecutionContext, skipHistory: Boolean, indicateErrors: Boolean, vimContext: VimLContext?): ExecutionResult {
|
||||||
var finalResult: ExecutionResult = ExecutionResult.Success
|
var finalResult: ExecutionResult = ExecutionResult.Success
|
||||||
|
|
||||||
val script = VimscriptParser.parse(scriptString)
|
val myScript = VimscriptParser.parse(script)
|
||||||
script.units.forEach { it.vimContext = vimContext ?: script }
|
myScript.units.forEach { it.vimContext = vimContext ?: myScript }
|
||||||
|
|
||||||
for (unit in script.units) {
|
for (unit in myScript.units) {
|
||||||
try {
|
try {
|
||||||
val result = unit.execute(editor, context)
|
val result = unit.execute(editor, context)
|
||||||
if (result is ExecutionResult.Error) {
|
if (result is ExecutionResult.Error) {
|
||||||
@@ -89,18 +89,18 @@ class Executor : VimScriptExecutorBase() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!skipHistory) {
|
if (!skipHistory) {
|
||||||
VimPlugin.getHistory().addEntry(HistoryConstants.COMMAND, scriptString)
|
VimPlugin.getHistory().addEntry(HistoryConstants.COMMAND, script)
|
||||||
if (script.units.size == 1 && script.units[0] is Command && script.units[0] !is RepeatCommand) {
|
if (myScript.units.size == 1 && myScript.units[0] is Command && myScript.units[0] !is RepeatCommand) {
|
||||||
VimPlugin.getRegister().storeTextSpecial(LAST_COMMAND_REGISTER, scriptString)
|
VimPlugin.getRegister().storeTextSpecial(LAST_COMMAND_REGISTER, script)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return finalResult
|
return finalResult
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun execute(scriptString: String, skipHistory: Boolean) {
|
override fun execute(script: String, skipHistory: Boolean) {
|
||||||
val editor = TextComponentEditorImpl(null, JTextArea()).vim
|
val editor = TextComponentEditorImpl(null, JTextArea()).vim
|
||||||
val context = DataContext.EMPTY_CONTEXT.vim
|
val context = DataContext.EMPTY_CONTEXT.vim
|
||||||
execute(scriptString, editor, context, skipHistory, indicateErrors = true, CommandLineVimLContext)
|
execute(script, editor, context, skipHistory, indicateErrors = true, CommandLineVimLContext)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun executeFile(file: File, indicateErrors: Boolean) {
|
override fun executeFile(file: File, indicateErrors: Boolean) {
|
||||||
|
@@ -23,6 +23,7 @@ import com.intellij.openapi.actionSystem.KeyboardShortcut
|
|||||||
import com.maddyhome.idea.vim.api.ExecutionContext
|
import com.maddyhome.idea.vim.api.ExecutionContext
|
||||||
import com.maddyhome.idea.vim.api.VimEditor
|
import com.maddyhome.idea.vim.api.VimEditor
|
||||||
import com.maddyhome.idea.vim.api.injector
|
import com.maddyhome.idea.vim.api.injector
|
||||||
|
import com.maddyhome.idea.vim.command.OperatorArguments
|
||||||
import com.maddyhome.idea.vim.ex.ExOutputModel
|
import com.maddyhome.idea.vim.ex.ExOutputModel
|
||||||
import com.maddyhome.idea.vim.ex.ranges.Ranges
|
import com.maddyhome.idea.vim.ex.ranges.Ranges
|
||||||
import com.maddyhome.idea.vim.helper.MessageHelper
|
import com.maddyhome.idea.vim.helper.MessageHelper
|
||||||
@@ -36,7 +37,7 @@ import java.util.*
|
|||||||
data class ActionListCommand(val ranges: Ranges, val argument: String) : Command.SingleExecution(ranges) {
|
data class ActionListCommand(val ranges: Ranges, val argument: String) : Command.SingleExecution(ranges) {
|
||||||
override val argFlags = flags(RangeFlag.RANGE_FORBIDDEN, ArgumentFlag.ARGUMENT_OPTIONAL, Access.READ_ONLY)
|
override val argFlags = flags(RangeFlag.RANGE_FORBIDDEN, ArgumentFlag.ARGUMENT_OPTIONAL, Access.READ_ONLY)
|
||||||
|
|
||||||
override fun processCommand(editor: VimEditor, context: ExecutionContext): ExecutionResult {
|
override fun processCommand(editor: VimEditor, context: ExecutionContext, operatorArguments: OperatorArguments): ExecutionResult {
|
||||||
val lineSeparator = "\n"
|
val lineSeparator = "\n"
|
||||||
val searchPattern = argument.trim().lowercase(Locale.getDefault()).split("*")
|
val searchPattern = argument.trim().lowercase(Locale.getDefault()).split("*")
|
||||||
val actionManager = ActionManager.getInstance()
|
val actionManager = ActionManager.getInstance()
|
||||||
|
@@ -23,6 +23,7 @@ import com.intellij.openapi.fileEditor.FileEditorManager
|
|||||||
import com.maddyhome.idea.vim.VimPlugin
|
import com.maddyhome.idea.vim.VimPlugin
|
||||||
import com.maddyhome.idea.vim.api.ExecutionContext
|
import com.maddyhome.idea.vim.api.ExecutionContext
|
||||||
import com.maddyhome.idea.vim.api.VimEditor
|
import com.maddyhome.idea.vim.api.VimEditor
|
||||||
|
import com.maddyhome.idea.vim.command.OperatorArguments
|
||||||
import com.maddyhome.idea.vim.ex.ranges.Ranges
|
import com.maddyhome.idea.vim.ex.ranges.Ranges
|
||||||
import com.maddyhome.idea.vim.helper.EditorHelper
|
import com.maddyhome.idea.vim.helper.EditorHelper
|
||||||
import com.maddyhome.idea.vim.helper.MessageHelper
|
import com.maddyhome.idea.vim.helper.MessageHelper
|
||||||
@@ -38,7 +39,7 @@ import com.maddyhome.idea.vim.vimscript.model.ExecutionResult
|
|||||||
data class BufferCommand(val ranges: Ranges, val argument: String) : Command.SingleExecution(ranges) {
|
data class BufferCommand(val ranges: Ranges, val argument: String) : Command.SingleExecution(ranges) {
|
||||||
override val argFlags = flags(RangeFlag.RANGE_FORBIDDEN, ArgumentFlag.ARGUMENT_OPTIONAL, Access.READ_ONLY)
|
override val argFlags = flags(RangeFlag.RANGE_FORBIDDEN, ArgumentFlag.ARGUMENT_OPTIONAL, Access.READ_ONLY)
|
||||||
|
|
||||||
override fun processCommand(editor: VimEditor, context: ExecutionContext): ExecutionResult {
|
override fun processCommand(editor: VimEditor, context: ExecutionContext, operatorArguments: OperatorArguments): ExecutionResult {
|
||||||
val arg = argument.trim()
|
val arg = argument.trim()
|
||||||
val overrideModified = arg.startsWith('!')
|
val overrideModified = arg.startsWith('!')
|
||||||
val buffer = if (overrideModified) arg.replace(Regex("^!\\s*"), "") else arg
|
val buffer = if (overrideModified) arg.replace(Regex("^!\\s*"), "") else arg
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user