mirror of
https://github.com/chylex/IntelliJ-IdeaVim.git
synced 2024-11-25 07:42:59 +01:00
Compare commits
21 Commits
87b45da4ee
...
a7def05aa8
Author | SHA1 | Date | |
---|---|---|---|
a7def05aa8 | |||
51e13a5f20 | |||
9b67260d5a | |||
ac37432db6 | |||
4c946568e4 | |||
7e70eed1ab | |||
43ae90044b | |||
d79f7c23c5 | |||
6033450158 | |||
ea86d7132c | |||
711d1f0329 | |||
338e137347 | |||
2b0e9bfec5 | |||
b42346b9e1 | |||
d58d3ca8b0 | |||
22b2ca2352 | |||
1c98daa180 | |||
de906bcbac | |||
05fac8bf00 | |||
a985d260f7 | |||
9f4c679d77 |
2
.github/workflows/mergePr.yml
vendored
2
.github/workflows/mergePr.yml
vendored
@ -11,7 +11,7 @@ on:
|
|||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
|
|
||||||
if: false
|
if: github.event.pull_request.merged == true && github.repository == 'JetBrains/ideavim'
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
|
6
.github/workflows/runUiOctopusTests.yml
vendored
6
.github/workflows/runUiOctopusTests.yml
vendored
@ -9,6 +9,9 @@ jobs:
|
|||||||
runs-on: macos-latest
|
runs-on: macos-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
- name: Apply Patch
|
||||||
|
run: |
|
||||||
|
git apply tests/ui-ij-tests/src/test/kotlin/ui/octopus.patch
|
||||||
- name: Setup Java
|
- name: Setup Java
|
||||||
uses: actions/setup-java@v4
|
uses: actions/setup-java@v4
|
||||||
with:
|
with:
|
||||||
@ -27,7 +30,7 @@ jobs:
|
|||||||
- name: Run Idea
|
- name: Run Idea
|
||||||
run: |
|
run: |
|
||||||
mkdir -p build/reports
|
mkdir -p build/reports
|
||||||
gradle runIdeForUiTests -Doctopus.handler=false > build/reports/idea.log &
|
gradle runIdeForUiTests > build/reports/idea.log &
|
||||||
- name: Wait for Idea started
|
- name: Wait for Idea started
|
||||||
uses: jtalk/url-health-check-action@v3
|
uses: jtalk/url-health-check-action@v3
|
||||||
with:
|
with:
|
||||||
@ -49,7 +52,6 @@ jobs:
|
|||||||
name: ui-test-fails-report-mac
|
name: ui-test-fails-report-mac
|
||||||
path: |
|
path: |
|
||||||
build/reports
|
build/reports
|
||||||
tests/ui-ij-tests/build/reports
|
|
||||||
sandbox-idea-log
|
sandbox-idea-log
|
||||||
# build-for-ui-test-linux:
|
# build-for-ui-test-linux:
|
||||||
# runs-on: ubuntu-latest
|
# runs-on: ubuntu-latest
|
||||||
|
1
.github/workflows/runUiPyTests.yml
vendored
1
.github/workflows/runUiPyTests.yml
vendored
@ -52,5 +52,4 @@ jobs:
|
|||||||
name: ui-test-fails-report-mac
|
name: ui-test-fails-report-mac
|
||||||
path: |
|
path: |
|
||||||
build/reports
|
build/reports
|
||||||
tests/ui-py-tests/build/reports
|
|
||||||
sandbox-idea-log
|
sandbox-idea-log
|
1
.github/workflows/runUiTests.yml
vendored
1
.github/workflows/runUiTests.yml
vendored
@ -49,7 +49,6 @@ jobs:
|
|||||||
name: ui-test-fails-report-mac
|
name: ui-test-fails-report-mac
|
||||||
path: |
|
path: |
|
||||||
build/reports
|
build/reports
|
||||||
tests/ui-ij-tests/build/reports
|
|
||||||
sandbox-idea-log
|
sandbox-idea-log
|
||||||
# build-for-ui-test-linux:
|
# build-for-ui-test-linux:
|
||||||
# runs-on: ubuntu-latest
|
# runs-on: ubuntu-latest
|
||||||
|
5
.github/workflows/updateChangelog.yml
vendored
5
.github/workflows/updateChangelog.yml
vendored
@ -7,12 +7,15 @@ on:
|
|||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
schedule:
|
schedule:
|
||||||
- cron: '0 10 * * *'
|
- cron: '0 10 * * *'
|
||||||
|
# Workflow run on push is disabled to avoid conflicts when merging PR
|
||||||
|
# push:
|
||||||
|
# branches: [ master ]
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
if: false
|
if: github.repository == 'JetBrains/ideavim'
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
|
3
.teamcity/_Self/buildTypes/Qodana.kt
vendored
3
.teamcity/_Self/buildTypes/Qodana.kt
vendored
@ -46,8 +46,8 @@ object Qodana : IdeaVimBuildType({
|
|||||||
version = Qodana.JVMVersion.LATEST
|
version = Qodana.JVMVersion.LATEST
|
||||||
}
|
}
|
||||||
reportAsTests = true
|
reportAsTests = true
|
||||||
|
additionalDockerArguments = "-e QODANA_TOKEN=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJvcmdhbml6YXRpb24iOiIzUFZrQSIsInByb2plY3QiOiIzN1FlQSIsInRva2VuIjoiM0t2bXoifQ.uohp81tM7iAfvvB6k8faarfpV-OjusAaEbWQ8iNrOgs"
|
||||||
additionalQodanaArguments = "--baseline qodana.sarif.json"
|
additionalQodanaArguments = "--baseline qodana.sarif.json"
|
||||||
cloudToken = "credentialsJSON:6b79412e-9198-4862-9223-c5019488f903"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,6 +63,7 @@ object Qodana : IdeaVimBuildType({
|
|||||||
timezone = "SERVER"
|
timezone = "SERVER"
|
||||||
}
|
}
|
||||||
param("dayOfWeek", "Sunday")
|
param("dayOfWeek", "Sunday")
|
||||||
|
enabled = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
55
.teamcity/_Self/buildTypes/ReleasePlugin.kt
vendored
55
.teamcity/_Self/buildTypes/ReleasePlugin.kt
vendored
@ -97,14 +97,14 @@ sealed class ReleasePlugin(private val releaseType: String) : IdeaVimBuildType({
|
|||||||
name = "Set TeamCity build number"
|
name = "Set TeamCity build number"
|
||||||
tasks = "scripts:setTeamCityBuildNumber"
|
tasks = "scripts:setTeamCityBuildNumber"
|
||||||
}
|
}
|
||||||
// gradle {
|
gradle {
|
||||||
// name = "Update change log"
|
name = "Update change log"
|
||||||
// tasks = "scripts:changelogUpdateUnreleased"
|
tasks = "scripts:changelogUpdateUnreleased"
|
||||||
// }
|
}
|
||||||
// gradle {
|
gradle {
|
||||||
// name = "Commit preparation changes"
|
name = "Commit preparation changes"
|
||||||
// tasks = "scripts:commitChanges"
|
tasks = "scripts:commitChanges"
|
||||||
// }
|
}
|
||||||
gradle {
|
gradle {
|
||||||
name = "Add release tag"
|
name = "Add release tag"
|
||||||
tasks = "scripts:addReleaseTag"
|
tasks = "scripts:addReleaseTag"
|
||||||
@ -117,24 +117,33 @@ sealed class ReleasePlugin(private val releaseType: String) : IdeaVimBuildType({
|
|||||||
name = "Publish release"
|
name = "Publish release"
|
||||||
tasks = "publishPlugin"
|
tasks = "publishPlugin"
|
||||||
}
|
}
|
||||||
// script {
|
script {
|
||||||
// name = "Checkout master branch"
|
name = "Checkout master branch"
|
||||||
// scriptContent = """
|
scriptContent = """
|
||||||
// echo Checkout master
|
echo Checkout master
|
||||||
// git checkout master
|
git checkout master
|
||||||
// """.trimIndent()
|
""".trimIndent()
|
||||||
// }
|
}
|
||||||
// gradle {
|
gradle {
|
||||||
// name = "Update change log in master"
|
name = "Update change log in master"
|
||||||
// tasks = "scripts:changelogUpdateUnreleased"
|
tasks = "scripts:changelogUpdateUnreleased"
|
||||||
// }
|
}
|
||||||
// gradle {
|
gradle {
|
||||||
// name = "Commit preparation changes in master"
|
name = "Commit preparation changes in master"
|
||||||
// tasks = "scripts:commitChanges"
|
tasks = "scripts:commitChanges"
|
||||||
// }
|
}
|
||||||
script {
|
script {
|
||||||
name = "Push changes to the repo"
|
name = "Push changes to the repo"
|
||||||
scriptContent = """
|
scriptContent = """
|
||||||
|
branch=$(git branch --show-current)
|
||||||
|
echo Current branch is ${'$'}branch
|
||||||
|
if [ "master" != "${'$'}branch" ];
|
||||||
|
then
|
||||||
|
git checkout master
|
||||||
|
fi
|
||||||
|
|
||||||
|
git push origin
|
||||||
|
|
||||||
git checkout release
|
git checkout release
|
||||||
echo checkout release branch
|
echo checkout release branch
|
||||||
git branch --set-upstream-to=origin/release release
|
git branch --set-upstream-to=origin/release release
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
package patches.buildTypes
|
package patches.buildTypes
|
||||||
|
|
||||||
import jetbrains.buildServer.configs.kotlin.v2019_2.*
|
import jetbrains.buildServer.configs.kotlin.v2019_2.RelativeId
|
||||||
import jetbrains.buildServer.configs.kotlin.v2019_2.buildSteps.GradleBuildStep
|
import jetbrains.buildServer.configs.kotlin.v2019_2.buildSteps.GradleBuildStep
|
||||||
import jetbrains.buildServer.configs.kotlin.v2019_2.buildSteps.gradle
|
import jetbrains.buildServer.configs.kotlin.v2019_2.buildSteps.gradle
|
||||||
import jetbrains.buildServer.configs.kotlin.v2019_2.ui.*
|
import jetbrains.buildServer.configs.kotlin.v2019_2.ui.changeBuildType
|
||||||
|
import jetbrains.buildServer.configs.kotlin.v2019_2.ui.expectSteps
|
||||||
|
import jetbrains.buildServer.configs.kotlin.v2019_2.ui.update
|
||||||
|
|
||||||
/*
|
/*
|
||||||
This patch script was generated by TeamCity on settings change in UI.
|
This patch script was generated by TeamCity on settings change in UI.
|
||||||
@ -11,18 +13,6 @@ To apply the patch, change the buildType with id = 'IdeaVimTests_Latest_EAP'
|
|||||||
accordingly, and delete the patch script.
|
accordingly, and delete the patch script.
|
||||||
*/
|
*/
|
||||||
changeBuildType(RelativeId("IdeaVimTests_Latest_EAP")) {
|
changeBuildType(RelativeId("IdeaVimTests_Latest_EAP")) {
|
||||||
check(artifactRules == """
|
|
||||||
+:build/reports => build/reports
|
|
||||||
+:/mnt/agent/temp/buildTmp/ => /mnt/agent/temp/buildTmp/
|
|
||||||
""".trimIndent()) {
|
|
||||||
"Unexpected option value: artifactRules = $artifactRules"
|
|
||||||
}
|
|
||||||
artifactRules = """
|
|
||||||
+:build/reports => build/reports
|
|
||||||
+:/mnt/agent/temp/buildTmp/ => /mnt/agent/temp/buildTmp/
|
|
||||||
+:tests/java-tests/build/reports => tests/java-tests/build/reports
|
|
||||||
""".trimIndent()
|
|
||||||
|
|
||||||
expectSteps {
|
expectSteps {
|
||||||
gradle {
|
gradle {
|
||||||
tasks = "clean test"
|
tasks = "clean test"
|
||||||
|
@ -495,14 +495,6 @@ Contributors:
|
|||||||
[![icon][github]](https://github.com/emanuelgestosa)
|
[![icon][github]](https://github.com/emanuelgestosa)
|
||||||
|
|
||||||
Emanuel Gestosa
|
Emanuel Gestosa
|
||||||
* [![icon][mail]](mailto:81118900+lippfi@users.noreply.github.com)
|
|
||||||
[![icon][github]](https://github.com/lippfi)
|
|
||||||
|
|
||||||
lippfi,
|
|
||||||
* [![icon][mail]](mailto:fillipser143@gmail.com)
|
|
||||||
[![icon][github]](https://github.com/Parker7123)
|
|
||||||
|
|
||||||
FilipParker
|
|
||||||
|
|
||||||
Previous contributors:
|
Previous contributors:
|
||||||
|
|
||||||
|
12
CHANGES.md
12
CHANGES.md
@ -23,19 +23,15 @@ It is important to distinguish EAP from traditional pre-release software.
|
|||||||
Please note that the quality of EAP versions may at times be way below even
|
Please note that the quality of EAP versions may at times be way below even
|
||||||
usual beta standards.
|
usual beta standards.
|
||||||
|
|
||||||
## End of changelog file maintenance
|
## To Be Released
|
||||||
|
|
||||||
Since version 2.9.0, the changelog can be found on YouTrack
|
|
||||||
|
|
||||||
To Be Released: https://youtrack.jetbrains.com/issues/VIM?q=%23%7BReady%20To%20Release%7D%20
|
|
||||||
Latest Fixes: https://youtrack.jetbrains.com/issues/VIM?q=State:%20Fixed%20sort%20by:%20updated%20
|
|
||||||
|
|
||||||
## 2.9.0, 2024-02-20
|
|
||||||
|
|
||||||
### Fixes:
|
### Fixes:
|
||||||
* [VIM-3055](https://youtrack.jetbrains.com/issue/VIM-3055) Fix the issue with double deleting after dot
|
* [VIM-3055](https://youtrack.jetbrains.com/issue/VIM-3055) Fix the issue with double deleting after dot
|
||||||
|
* [VIM-3291](https://youtrack.jetbrains.com/issue/VIM-3291) Remove sync of editor selection between different opened editors
|
||||||
|
* [VIM-3234](https://youtrack.jetbrains.com/issue/VIM-3234) The space character won't mix in the tab chars after >> and << commands
|
||||||
|
|
||||||
### Merged PRs:
|
### Merged PRs:
|
||||||
|
* [725](https://github.com/JetBrains/ideavim/pull/725) by [Emanuel Gestosa](https://github.com/emanuelgestosa): Regex
|
||||||
* [805](https://github.com/JetBrains/ideavim/pull/805) by [chylex](https://github.com/chylex): VIM-3238 Fix recording a macro that replays another macro
|
* [805](https://github.com/JetBrains/ideavim/pull/805) by [chylex](https://github.com/chylex): VIM-3238 Fix recording a macro that replays another macro
|
||||||
|
|
||||||
## 2.8.0, 2024-01-30
|
## 2.8.0, 2024-01-30
|
||||||
|
@ -21,7 +21,7 @@ repositories {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
compileOnly("com.google.devtools.ksp:symbol-processing-api:1.9.23-1.0.19")
|
compileOnly("com.google.devtools.ksp:symbol-processing-api:1.9.22-1.0.17")
|
||||||
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json-jvm:$kotlinxSerializationVersion") {
|
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json-jvm:$kotlinxSerializationVersion") {
|
||||||
// kotlin stdlib is provided by IJ, so there is no need to include it into the distribution
|
// kotlin stdlib is provided by IJ, so there is no need to include it into the distribution
|
||||||
exclude("org.jetbrains.kotlin", "kotlin-stdlib")
|
exclude("org.jetbrains.kotlin", "kotlin-stdlib")
|
||||||
|
@ -32,6 +32,7 @@ import org.eclipse.jgit.api.Git
|
|||||||
import org.eclipse.jgit.lib.RepositoryBuilder
|
import org.eclipse.jgit.lib.RepositoryBuilder
|
||||||
import org.intellij.markdown.ast.getTextInNode
|
import org.intellij.markdown.ast.getTextInNode
|
||||||
import org.jetbrains.changelog.Changelog
|
import org.jetbrains.changelog.Changelog
|
||||||
|
import org.jetbrains.changelog.exceptions.MissingVersionException
|
||||||
import org.kohsuke.github.GHUser
|
import org.kohsuke.github.GHUser
|
||||||
import java.net.HttpURLConnection
|
import java.net.HttpURLConnection
|
||||||
import java.net.URL
|
import java.net.URL
|
||||||
@ -48,14 +49,14 @@ buildscript {
|
|||||||
classpath("org.eclipse.jgit:org.eclipse.jgit:6.6.0.202305301015-r")
|
classpath("org.eclipse.jgit:org.eclipse.jgit:6.6.0.202305301015-r")
|
||||||
|
|
||||||
// This is needed for jgit to connect to ssh
|
// This is needed for jgit to connect to ssh
|
||||||
classpath("org.eclipse.jgit:org.eclipse.jgit.ssh.apache:6.9.0.202403050737-r")
|
classpath("org.eclipse.jgit:org.eclipse.jgit.ssh.apache:6.8.0.202311291450-r")
|
||||||
classpath("org.kohsuke:github-api:1.305")
|
classpath("org.kohsuke:github-api:1.305")
|
||||||
|
|
||||||
classpath("io.ktor:ktor-client-core:2.3.9")
|
classpath("io.ktor:ktor-client-core:2.3.7")
|
||||||
classpath("io.ktor:ktor-client-cio:2.3.9")
|
classpath("io.ktor:ktor-client-cio:2.3.7")
|
||||||
classpath("io.ktor:ktor-client-auth:2.3.9")
|
classpath("io.ktor:ktor-client-auth:2.3.7")
|
||||||
classpath("io.ktor:ktor-client-content-negotiation:2.3.9")
|
classpath("io.ktor:ktor-client-content-negotiation:2.3.7")
|
||||||
classpath("io.ktor:ktor-serialization-kotlinx-json:2.3.9")
|
classpath("io.ktor:ktor-serialization-kotlinx-json:2.3.7")
|
||||||
|
|
||||||
// This comes from the changelog plugin
|
// This comes from the changelog plugin
|
||||||
// classpath("org.jetbrains:markdown:0.3.1")
|
// classpath("org.jetbrains:markdown:0.3.1")
|
||||||
@ -69,7 +70,7 @@ plugins {
|
|||||||
application
|
application
|
||||||
id("java-test-fixtures")
|
id("java-test-fixtures")
|
||||||
|
|
||||||
id("org.jetbrains.intellij") version "1.17.2"
|
id("org.jetbrains.intellij") version "1.17.1"
|
||||||
id("org.jetbrains.changelog") version "2.2.0"
|
id("org.jetbrains.changelog") version "2.2.0"
|
||||||
|
|
||||||
id("org.jetbrains.kotlinx.kover") version "0.6.1"
|
id("org.jetbrains.kotlinx.kover") version "0.6.1"
|
||||||
@ -143,12 +144,12 @@ dependencies {
|
|||||||
// https://mvnrepository.com/artifact/org.mockito.kotlin/mockito-kotlin
|
// https://mvnrepository.com/artifact/org.mockito.kotlin/mockito-kotlin
|
||||||
testImplementation("org.mockito.kotlin:mockito-kotlin:5.2.1")
|
testImplementation("org.mockito.kotlin:mockito-kotlin:5.2.1")
|
||||||
|
|
||||||
testImplementation("org.junit.jupiter:junit-jupiter-api:5.10.2")
|
testImplementation("org.junit.jupiter:junit-jupiter-api:5.10.1")
|
||||||
testImplementation("org.junit.jupiter:junit-jupiter-engine:5.10.2")
|
testImplementation("org.junit.jupiter:junit-jupiter-engine:5.10.1")
|
||||||
testImplementation("org.junit.jupiter:junit-jupiter-params:5.10.2")
|
testImplementation("org.junit.jupiter:junit-jupiter-params:5.10.1")
|
||||||
testFixturesImplementation("org.junit.jupiter:junit-jupiter-api:5.10.2")
|
testFixturesImplementation("org.junit.jupiter:junit-jupiter-api:5.10.1")
|
||||||
testFixturesImplementation("org.junit.jupiter:junit-jupiter-engine:5.10.2")
|
testFixturesImplementation("org.junit.jupiter:junit-jupiter-engine:5.10.1")
|
||||||
testFixturesImplementation("org.junit.jupiter:junit-jupiter-params:5.10.2")
|
testFixturesImplementation("org.junit.jupiter:junit-jupiter-params:5.10.1")
|
||||||
}
|
}
|
||||||
|
|
||||||
configurations {
|
configurations {
|
||||||
@ -206,11 +207,6 @@ tasks {
|
|||||||
systemProperty("jb.privacy.policy.text", "<!--999.999-->")
|
systemProperty("jb.privacy.policy.text", "<!--999.999-->")
|
||||||
systemProperty("jb.consents.confirmation.enabled", "false")
|
systemProperty("jb.consents.confirmation.enabled", "false")
|
||||||
systemProperty("ide.show.tips.on.startup.default.value", "false")
|
systemProperty("ide.show.tips.on.startup.default.value", "false")
|
||||||
systemProperty("octopus.handler", System.getProperty("octopus.handler") ?: true)
|
|
||||||
}
|
|
||||||
|
|
||||||
runIde {
|
|
||||||
systemProperty("octopus.handler", System.getProperty("octopus.handler") ?: true)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -264,9 +260,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"))
|
||||||
// The latest version of the plugin verifier is broken, so temporally use the stable version
|
|
||||||
verifierVersion = "1.307"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
generateGrammarSource {
|
generateGrammarSource {
|
||||||
@ -311,12 +305,24 @@ tasks {
|
|||||||
from(createOpenApiSourceJar) { into("lib/src") }
|
from(createOpenApiSourceJar) { into("lib/src") }
|
||||||
}
|
}
|
||||||
|
|
||||||
patchPluginXml {
|
val pluginVersion = version
|
||||||
// Don't forget to update plugin.xml
|
// Don't forget to update plugin.xml
|
||||||
sinceBuild.set("233.11799.67")
|
patchPluginXml {
|
||||||
|
// Get the latest available change notes from the changelog file
|
||||||
changeNotes.set(
|
changeNotes.set(
|
||||||
"""<a href="https://youtrack.jetbrains.com/issues/VIM?q=State:%20Fixed%20Fix%20versions:%20${version.get()}">Changelog</a>"""
|
provider {
|
||||||
|
with(changelog) {
|
||||||
|
val log = try {
|
||||||
|
getUnreleased()
|
||||||
|
} catch (e: MissingVersionException) {
|
||||||
|
getOrNull(pluginVersion.toString()) ?: getLatest()
|
||||||
|
}
|
||||||
|
renderItem(
|
||||||
|
log,
|
||||||
|
org.jetbrains.changelog.Changelog.OutputType.HTML,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -423,14 +429,12 @@ val prId: String by project
|
|||||||
|
|
||||||
tasks.register("updateMergedPr") {
|
tasks.register("updateMergedPr") {
|
||||||
doLast {
|
doLast {
|
||||||
val x = changelog.getUnreleased()
|
if (project.hasProperty("prId")) {
|
||||||
println("x")
|
println("Got pr id: $prId")
|
||||||
// if (project.hasProperty("prId")) {
|
updateMergedPr(prId.toInt())
|
||||||
// println("Got pr id: $prId")
|
} else {
|
||||||
// updateMergedPr(prId.toInt())
|
error("Cannot get prId")
|
||||||
// } else {
|
}
|
||||||
// error("Cannot get prId")
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,13 +8,12 @@
|
|||||||
|
|
||||||
# suppress inspection "UnusedProperty" for whole file
|
# suppress inspection "UnusedProperty" for whole file
|
||||||
|
|
||||||
#ideaVersion=LATEST-EAP-SNAPSHOT
|
|
||||||
ideaVersion=2023.3.3
|
ideaVersion=2023.3.3
|
||||||
# Values for type: https://plugins.jetbrains.com/docs/intellij/tools-gradle-intellij-plugin.html#intellij-extension-type
|
# Values for type: https://plugins.jetbrains.com/docs/intellij/tools-gradle-intellij-plugin.html#intellij-extension-type
|
||||||
ideaType=IC
|
ideaType=IC
|
||||||
downloadIdeaSources=true
|
downloadIdeaSources=true
|
||||||
instrumentPluginCode=true
|
instrumentPluginCode=true
|
||||||
version=chylex-29
|
version=chylex-28
|
||||||
javaVersion=17
|
javaVersion=17
|
||||||
remoteRobotVersion=0.11.22
|
remoteRobotVersion=0.11.22
|
||||||
antlrVersion=4.10.1
|
antlrVersion=4.10.1
|
||||||
@ -29,7 +28,7 @@ publishChannels=eap
|
|||||||
|
|
||||||
# Kotlinx serialization also uses some version of kotlin stdlib under the hood. However,
|
# Kotlinx serialization also uses some version of kotlin stdlib under the hood. However,
|
||||||
# we exclude this version from the dependency and use our own version of kotlin that is specified above
|
# we exclude this version from the dependency and use our own version of kotlin that is specified above
|
||||||
kotlinxSerializationVersion=1.6.2
|
kotlinxSerializationVersion=1.5.1
|
||||||
|
|
||||||
slackUrl=
|
slackUrl=
|
||||||
youtrackToken=
|
youtrackToken=
|
||||||
@ -42,4 +41,3 @@ kotlin.stdlib.default.dependency=false
|
|||||||
|
|
||||||
# Disable incremental annotation processing
|
# Disable incremental annotation processing
|
||||||
ksp.incremental=false
|
ksp.incremental=false
|
||||||
|
|
||||||
|
135372
qodana.sarif.json
135372
qodana.sarif.json
File diff suppressed because one or more lines are too long
@ -21,9 +21,6 @@ exclude:
|
|||||||
- src/test/java/org/jetbrains/plugins/ideavim/propertybased/samples/SimpleText.kt
|
- src/test/java/org/jetbrains/plugins/ideavim/propertybased/samples/SimpleText.kt
|
||||||
- src/main/java/com/maddyhome/idea/vim/vimscript/parser/generated
|
- src/main/java/com/maddyhome/idea/vim/vimscript/parser/generated
|
||||||
- src/main/java/com/maddyhome/idea/vim/package-info.java
|
- src/main/java/com/maddyhome/idea/vim/package-info.java
|
||||||
- vim-engine/src/main/java/com/maddyhome/idea/vim/regexp/parser/generated
|
|
||||||
- src/main/java/com/maddyhome/idea/vim/group/SearchGroup.java
|
|
||||||
- tests/ui-fixtures
|
|
||||||
dependencyIgnores:
|
dependencyIgnores:
|
||||||
- name: "acejump"
|
- name: "acejump"
|
||||||
- name: "icu4j"
|
- name: "icu4j"
|
||||||
|
@ -20,17 +20,17 @@ repositories {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
compileOnly("org.jetbrains.kotlin:kotlin-stdlib:1.9.23")
|
compileOnly("org.jetbrains.kotlin:kotlin-stdlib:1.9.22")
|
||||||
|
|
||||||
implementation("io.ktor:ktor-client-core:2.3.9")
|
implementation("io.ktor:ktor-client-core:2.3.7")
|
||||||
implementation("io.ktor:ktor-client-cio:2.3.9")
|
implementation("io.ktor:ktor-client-cio:2.3.7")
|
||||||
implementation("io.ktor:ktor-client-content-negotiation:2.3.9")
|
implementation("io.ktor:ktor-client-content-negotiation:2.3.7")
|
||||||
implementation("io.ktor:ktor-serialization-kotlinx-json:2.3.9")
|
implementation("io.ktor:ktor-serialization-kotlinx-json:2.3.7")
|
||||||
implementation("io.ktor:ktor-client-auth:2.3.9")
|
implementation("io.ktor:ktor-client-auth:2.3.7")
|
||||||
implementation("org.eclipse.jgit:org.eclipse.jgit:6.6.0.202305301015-r")
|
implementation("org.eclipse.jgit:org.eclipse.jgit:6.6.0.202305301015-r")
|
||||||
|
|
||||||
// This is needed for jgit to connect to ssh
|
// This is needed for jgit to connect to ssh
|
||||||
implementation("org.eclipse.jgit:org.eclipse.jgit.ssh.apache:6.9.0.202403050737-r")
|
implementation("org.eclipse.jgit:org.eclipse.jgit.ssh.apache:6.8.0.202311291450-r")
|
||||||
implementation("com.vdurmont:semver4j:3.1.0")
|
implementation("com.vdurmont:semver4j:3.1.0")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ import kotlinx.serialization.json.jsonPrimitive
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
@Suppress("SpellCheckingInspection")
|
@Suppress("SpellCheckingInspection")
|
||||||
val knownPlugins = setOf(
|
val knownPlugins = listOf(
|
||||||
"IdeaVimExtension",
|
"IdeaVimExtension",
|
||||||
"github.zgqq.intellij-enhance",
|
"github.zgqq.intellij-enhance",
|
||||||
"org.jetbrains.IdeaVim-EasyMotion",
|
"org.jetbrains.IdeaVim-EasyMotion",
|
||||||
@ -31,12 +31,7 @@ val knownPlugins = setOf(
|
|||||||
"com.github.copilot",
|
"com.github.copilot",
|
||||||
"com.github.dankinsoid.multicursor",
|
"com.github.dankinsoid.multicursor",
|
||||||
"com.joshestein.ideavim-quickscope",
|
"com.joshestein.ideavim-quickscope",
|
||||||
|
|
||||||
"ca.alexgirard.HarpoonIJ",
|
"ca.alexgirard.HarpoonIJ",
|
||||||
"me.kyren223.harpoonforjb", // https://plugins.jetbrains.com/plugin/23771-harpoonforjb
|
|
||||||
"com.github.erotourtes.harpoon", // https://plugins.jetbrains.com/plugin/21796-harpooner
|
|
||||||
"me.kyren223.trident", // https://plugins.jetbrains.com/plugin/23818-trident
|
|
||||||
|
|
||||||
"com.protoseo.input-source-auto-converter",
|
"com.protoseo.input-source-auto-converter",
|
||||||
|
|
||||||
// "cc.implicated.intellij.plugins.bunny", // I don't want to include this plugin in the list of IdeaVim plugins as I don't understand what this is for
|
// "cc.implicated.intellij.plugins.bunny", // I don't want to include this plugin in the list of IdeaVim plugins as I don't understand what this is for
|
||||||
@ -47,7 +42,7 @@ suspend fun main() {
|
|||||||
parameter("dependency", "IdeaVIM")
|
parameter("dependency", "IdeaVIM")
|
||||||
parameter("includeOptional", true)
|
parameter("includeOptional", true)
|
||||||
}
|
}
|
||||||
val output = response.body<List<String>>().toSet()
|
val output = response.body<List<String>>()
|
||||||
println(output)
|
println(output)
|
||||||
if (knownPlugins != output) {
|
if (knownPlugins != output) {
|
||||||
val newPlugins = (output - knownPlugins).map { it to (getPluginLinkByXmlId(it) ?: "Can't find plugin link") }
|
val newPlugins = (output - knownPlugins).map { it to (getPluginLinkByXmlId(it) ?: "Can't find plugin link") }
|
||||||
|
@ -8,12 +8,6 @@
|
|||||||
|
|
||||||
package scripts.release
|
package scripts.release
|
||||||
|
|
||||||
import org.eclipse.jgit.lib.ObjectId
|
|
||||||
import org.eclipse.jgit.revwalk.RevCommit
|
|
||||||
import org.eclipse.jgit.revwalk.RevWalk
|
|
||||||
import org.eclipse.jgit.revwalk.filter.RevFilter
|
|
||||||
|
|
||||||
|
|
||||||
fun main(args: Array<String>) {
|
fun main(args: Array<String>) {
|
||||||
println("HI!")
|
println("HI!")
|
||||||
val projectDir = args[0]
|
val projectDir = args[0]
|
||||||
@ -25,12 +19,10 @@ fun main(args: Array<String>) {
|
|||||||
check(branch == "master") {
|
check(branch == "master") {
|
||||||
"We should be on master branch"
|
"We should be on master branch"
|
||||||
}
|
}
|
||||||
val mergeBaseCommit = getMergeBaseWithMaster(projectDir, objectId)
|
|
||||||
println("Base commit $mergeBaseCommit")
|
|
||||||
withGit(projectDir) { git ->
|
withGit(projectDir) { git ->
|
||||||
val log = git.log().setMaxCount(500).call().toList()
|
val log = git.log().setMaxCount(500).call().toList()
|
||||||
println("First commit hash in log: " + log.first().name + " log size: ${log.size}")
|
println("First commit hash in log: " + log.first().name + " log size: ${log.size}")
|
||||||
val logDiff = log.takeWhile { it.id.name != mergeBaseCommit }
|
val logDiff = log.takeWhile { it.id.name != objectId.name }
|
||||||
val numCommits = logDiff.size
|
val numCommits = logDiff.size
|
||||||
println("Log diff size is $numCommits")
|
println("Log diff size is $numCommits")
|
||||||
check(numCommits < 450) {
|
check(numCommits < 450) {
|
||||||
@ -43,18 +35,3 @@ fun main(args: Array<String>) {
|
|||||||
println("##teamcity[setParameter name='env.ORG_GRADLE_PROJECT_version' value='$nextVersion']")
|
println("##teamcity[setParameter name='env.ORG_GRADLE_PROJECT_version' value='$nextVersion']")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getMergeBaseWithMaster(projectDir: String, tag: ObjectId): String {
|
|
||||||
withRepo(projectDir) { repo ->
|
|
||||||
val master = repo.resolve("master")
|
|
||||||
RevWalk(repo).use { walk ->
|
|
||||||
val tagRevCommit = walk.parseCommit(tag)
|
|
||||||
val masterRevCommit = walk.parseCommit(master)
|
|
||||||
walk.setRevFilter(RevFilter.MERGE_BASE)
|
|
||||||
walk.markStart(tagRevCommit)
|
|
||||||
walk.markStart(masterRevCommit)
|
|
||||||
val mergeBase: RevCommit = walk.next()
|
|
||||||
return mergeBase.name
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -11,6 +11,7 @@ package com.maddyhome.idea.vim;
|
|||||||
import com.intellij.openapi.Disposable;
|
import com.intellij.openapi.Disposable;
|
||||||
import com.intellij.openapi.actionSystem.AnAction;
|
import com.intellij.openapi.actionSystem.AnAction;
|
||||||
import com.intellij.openapi.actionSystem.ShortcutSet;
|
import com.intellij.openapi.actionSystem.ShortcutSet;
|
||||||
|
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;
|
||||||
import com.intellij.openapi.editor.actionSystem.TypedAction;
|
import com.intellij.openapi.editor.actionSystem.TypedAction;
|
||||||
@ -79,6 +80,14 @@ public class EventFacade {
|
|||||||
action.unregisterCustomShortcutSet(component);
|
action.unregisterCustomShortcutSet(component);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void addDocumentListener(@NotNull Document document, @NotNull DocumentListener listener) {
|
||||||
|
document.addDocumentListener(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeDocumentListener(@NotNull Document document, @NotNull DocumentListener listener) {
|
||||||
|
document.removeDocumentListener(listener);
|
||||||
|
}
|
||||||
|
|
||||||
public void addEditorFactoryListener(@NotNull EditorFactoryListener listener, @NotNull Disposable parentDisposable) {
|
public void addEditorFactoryListener(@NotNull EditorFactoryListener listener, @NotNull Disposable parentDisposable) {
|
||||||
EditorFactory.getInstance().addEditorFactoryListener(listener, parentDisposable);
|
EditorFactory.getInstance().addEditorFactoryListener(listener, parentDisposable);
|
||||||
}
|
}
|
||||||
@ -89,12 +98,20 @@ public class EventFacade {
|
|||||||
editor.getCaretModel().addCaretListener(listener, disposable);
|
editor.getCaretModel().addCaretListener(listener, disposable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void removeCaretListener(@NotNull Editor editor, @NotNull CaretListener listener) {
|
||||||
|
editor.getCaretModel().removeCaretListener(listener);
|
||||||
|
}
|
||||||
|
|
||||||
public void addEditorMouseListener(@NotNull Editor editor,
|
public void addEditorMouseListener(@NotNull Editor editor,
|
||||||
@NotNull EditorMouseListener listener,
|
@NotNull EditorMouseListener listener,
|
||||||
@NotNull Disposable disposable) {
|
@NotNull Disposable disposable) {
|
||||||
editor.addEditorMouseListener(listener, disposable);
|
editor.addEditorMouseListener(listener, disposable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void removeEditorMouseListener(@NotNull Editor editor, @NotNull EditorMouseListener listener) {
|
||||||
|
editor.removeEditorMouseListener(listener);
|
||||||
|
}
|
||||||
|
|
||||||
public void addComponentMouseListener(@NotNull Component component,
|
public void addComponentMouseListener(@NotNull Component component,
|
||||||
@NotNull MouseListener mouseListener,
|
@NotNull MouseListener mouseListener,
|
||||||
@NotNull Disposable disposable) {
|
@NotNull Disposable disposable) {
|
||||||
@ -102,18 +119,30 @@ public class EventFacade {
|
|||||||
Disposer.register(disposable, () -> component.removeMouseListener(mouseListener));
|
Disposer.register(disposable, () -> component.removeMouseListener(mouseListener));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void removeComponentMouseListener(@NotNull Component component, @NotNull MouseListener mouseListener) {
|
||||||
|
component.removeMouseListener(mouseListener);
|
||||||
|
}
|
||||||
|
|
||||||
public void addEditorMouseMotionListener(@NotNull Editor editor,
|
public void addEditorMouseMotionListener(@NotNull Editor editor,
|
||||||
@NotNull EditorMouseMotionListener listener,
|
@NotNull EditorMouseMotionListener listener,
|
||||||
@NotNull Disposable disposable) {
|
@NotNull Disposable disposable) {
|
||||||
editor.addEditorMouseMotionListener(listener, disposable);
|
editor.addEditorMouseMotionListener(listener, disposable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void removeEditorMouseMotionListener(@NotNull Editor editor, @NotNull EditorMouseMotionListener listener) {
|
||||||
|
editor.removeEditorMouseMotionListener(listener);
|
||||||
|
}
|
||||||
|
|
||||||
public void addEditorSelectionListener(@NotNull Editor editor,
|
public void addEditorSelectionListener(@NotNull Editor editor,
|
||||||
@NotNull SelectionListener listener,
|
@NotNull SelectionListener listener,
|
||||||
@NotNull Disposable disposable) {
|
@NotNull Disposable disposable) {
|
||||||
editor.getSelectionModel().addSelectionListener(listener, disposable);
|
editor.getSelectionModel().addSelectionListener(listener, disposable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void removeEditorSelectionListener(@NotNull Editor editor, @NotNull SelectionListener listener) {
|
||||||
|
editor.getSelectionModel().removeSelectionListener(listener);
|
||||||
|
}
|
||||||
|
|
||||||
private @NotNull TypedAction getTypedAction() {
|
private @NotNull TypedAction getTypedAction() {
|
||||||
return TypedAction.getInstance();
|
return TypedAction.getInstance();
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,7 @@ import com.intellij.openapi.project.ProjectManagerListener
|
|||||||
import com.intellij.openapi.startup.ProjectActivity
|
import com.intellij.openapi.startup.ProjectActivity
|
||||||
import com.maddyhome.idea.vim.api.injector
|
import com.maddyhome.idea.vim.api.injector
|
||||||
import com.maddyhome.idea.vim.helper.EditorHelper
|
import com.maddyhome.idea.vim.helper.EditorHelper
|
||||||
import com.maddyhome.idea.vim.newapi.IjVimEditor
|
import com.maddyhome.idea.vim.helper.localEditors
|
||||||
import com.maddyhome.idea.vim.newapi.globalIjOptions
|
import com.maddyhome.idea.vim.newapi.globalIjOptions
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -36,10 +36,8 @@ internal class PluginStartup : ProjectActivity/*, LightEditCompatible*/ {
|
|||||||
// This is a temporal workaround for VIM-2487
|
// This is a temporal workaround for VIM-2487
|
||||||
internal class PyNotebooksCloseWorkaround : ProjectManagerListener {
|
internal class PyNotebooksCloseWorkaround : ProjectManagerListener {
|
||||||
override fun projectClosingBeforeSave(project: Project) {
|
override fun projectClosingBeforeSave(project: Project) {
|
||||||
// TODO: Confirm context in CWM scenario
|
|
||||||
if (injector.globalIjOptions().closenotebooks) {
|
if (injector.globalIjOptions().closenotebooks) {
|
||||||
injector.editorGroup.getEditors().forEach { vimEditor ->
|
localEditors().forEach { editor ->
|
||||||
val editor = (vimEditor as IjVimEditor).editor
|
|
||||||
val virtualFile = EditorHelper.getVirtualFile(editor)
|
val virtualFile = EditorHelper.getVirtualFile(editor)
|
||||||
if (virtualFile?.extension == "ipynb") {
|
if (virtualFile?.extension == "ipynb") {
|
||||||
val fileEditorManager = FileEditorManagerEx.getInstanceEx(project)
|
val fileEditorManager = FileEditorManagerEx.getInstanceEx(project)
|
||||||
|
@ -21,7 +21,7 @@ public object RegisterActions {
|
|||||||
@JvmStatic
|
@JvmStatic
|
||||||
public fun registerActions() {
|
public fun registerActions() {
|
||||||
registerVimCommandActions()
|
registerVimCommandActions()
|
||||||
registerShortcutsWithoutActions()
|
registerEmptyShortcuts() // todo most likely it is not needed
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun findAction(id: String): EditorActionHandlerBase? {
|
public fun findAction(id: String): EditorActionHandlerBase? {
|
||||||
@ -46,11 +46,12 @@ public object RegisterActions {
|
|||||||
IntellijCommandProvider.getCommands().forEach { parser.registerCommandAction(it) }
|
IntellijCommandProvider.getCommands().forEach { parser.registerCommandAction(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun registerShortcutsWithoutActions() {
|
private fun registerEmptyShortcuts() {
|
||||||
val parser = VimPlugin.getKey()
|
val parser = VimPlugin.getKey()
|
||||||
|
|
||||||
// The {char1} <BS> {char2} shortcut is handled directly by KeyHandler#handleKey, so doesn't have an action. But we
|
// The {char1} <BS> {char2} shortcut is handled directly by KeyHandler#handleKey, so doesn't have an action. But we
|
||||||
// still need to register the shortcut, to make sure the editor doesn't swallow it.
|
// still need to register the shortcut, to make sure the editor doesn't swallow it.
|
||||||
parser.registerShortcutWithoutAction(KeyStroke.getKeyStroke(KeyEvent.VK_BACK_SPACE, 0), MappingOwner.IdeaVim.System)
|
parser
|
||||||
|
.registerShortcutWithoutAction(KeyStroke.getKeyStroke(KeyEvent.VK_BACK_SPACE, 0), MappingOwner.IdeaVim.System)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -211,22 +211,22 @@ public class VimPlugin implements PersistentStateComponent<Element>, Disposable
|
|||||||
public static void setEnabled(final boolean enabled) {
|
public static void setEnabled(final boolean enabled) {
|
||||||
if (isEnabled() == enabled) return;
|
if (isEnabled() == enabled) return;
|
||||||
|
|
||||||
|
if (!enabled) {
|
||||||
|
getInstance().turnOffPlugin(true);
|
||||||
|
}
|
||||||
|
|
||||||
getInstance().enabled = enabled;
|
getInstance().enabled = enabled;
|
||||||
|
|
||||||
|
if (enabled) {
|
||||||
|
getInstance().turnOnPlugin();
|
||||||
|
}
|
||||||
|
|
||||||
if (enabled) {
|
if (enabled) {
|
||||||
VimInjectorKt.getInjector().getListenersNotifier().notifyPluginTurnedOn();
|
VimInjectorKt.getInjector().getListenersNotifier().notifyPluginTurnedOn();
|
||||||
} else {
|
} else {
|
||||||
VimInjectorKt.getInjector().getListenersNotifier().notifyPluginTurnedOff();
|
VimInjectorKt.getInjector().getListenersNotifier().notifyPluginTurnedOff();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!enabled) {
|
|
||||||
getInstance().turnOffPlugin(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (enabled) {
|
|
||||||
getInstance().turnOnPlugin();
|
|
||||||
}
|
|
||||||
|
|
||||||
StatusBarIconFactory.Util.INSTANCE.updateIcon();
|
StatusBarIconFactory.Util.INSTANCE.updateIcon();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -353,7 +353,6 @@ public class VimPlugin implements PersistentStateComponent<Element>, Disposable
|
|||||||
|
|
||||||
if (onOffDisposable != null) {
|
if (onOffDisposable != null) {
|
||||||
Disposer.dispose(onOffDisposable);
|
Disposer.dispose(onOffDisposable);
|
||||||
onOffDisposable = null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@ import com.intellij.openapi.components.service
|
|||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
import com.maddyhome.idea.vim.group.EditorHolderService
|
import com.maddyhome.idea.vim.group.EditorHolderService
|
||||||
|
|
||||||
@Service(Service.Level.PROJECT)
|
@Service
|
||||||
internal class VimProjectService(val project: Project) : Disposable {
|
internal class VimProjectService(val project: Project) : Disposable {
|
||||||
override fun dispose() {
|
override fun dispose() {
|
||||||
// Not sure if this is a best solution
|
// Not sure if this is a best solution
|
||||||
|
@ -77,7 +77,7 @@ public class VimTypedActionHandler(origHandler: TypedActionHandler) : TypedActio
|
|||||||
val modifiers = if (charTyped == ' ' && VimKeyListener.isSpaceShift) KeyEvent.SHIFT_DOWN_MASK else 0
|
val modifiers = if (charTyped == ' ' && VimKeyListener.isSpaceShift) KeyEvent.SHIFT_DOWN_MASK else 0
|
||||||
val keyStroke = KeyStroke.getKeyStroke(charTyped, modifiers)
|
val keyStroke = KeyStroke.getKeyStroke(charTyped, modifiers)
|
||||||
val startTime = if (traceTime) System.currentTimeMillis() else null
|
val startTime = if (traceTime) System.currentTimeMillis() else null
|
||||||
handler.handleKey(editor.vim, keyStroke, injector.executionContextManager.onEditor(editor.vim, context.vim), handler.keyHandlerState)
|
handler.handleKey(editor.vim, keyStroke, injector.executionContextManager.onEditor(editor.vim, context.vim))
|
||||||
if (startTime != null) {
|
if (startTime != null) {
|
||||||
val duration = System.currentTimeMillis() - startTime
|
val duration = System.currentTimeMillis() - startTime
|
||||||
LOG.info("VimTypedAction '$charTyped': $duration ms")
|
LOG.info("VimTypedAction '$charTyped': $duration ms")
|
||||||
|
@ -44,6 +44,7 @@ import com.maddyhome.idea.vim.listener.AceJumpService
|
|||||||
import com.maddyhome.idea.vim.listener.AppCodeTemplates.appCodeTemplateCaptured
|
import com.maddyhome.idea.vim.listener.AppCodeTemplates.appCodeTemplateCaptured
|
||||||
import com.maddyhome.idea.vim.newapi.globalIjOptions
|
import com.maddyhome.idea.vim.newapi.globalIjOptions
|
||||||
import com.maddyhome.idea.vim.newapi.vim
|
import com.maddyhome.idea.vim.newapi.vim
|
||||||
|
import com.maddyhome.idea.vim.state.mode.mode
|
||||||
import com.maddyhome.idea.vim.vimscript.model.datatypes.VimString
|
import com.maddyhome.idea.vim.vimscript.model.datatypes.VimString
|
||||||
import java.awt.event.InputEvent
|
import java.awt.event.InputEvent
|
||||||
import java.awt.event.KeyEvent
|
import java.awt.event.KeyEvent
|
||||||
@ -78,12 +79,10 @@ public class VimShortcutKeyAction : AnAction(), DumbAware/*, LightEditCompatible
|
|||||||
// Should we use HelperKt.getTopLevelEditor(editor) here, as we did in former EditorKeyHandler?
|
// Should we use HelperKt.getTopLevelEditor(editor) here, as we did in former EditorKeyHandler?
|
||||||
try {
|
try {
|
||||||
val start = if (traceTime) System.currentTimeMillis() else null
|
val start = if (traceTime) System.currentTimeMillis() else null
|
||||||
val keyHandler = KeyHandler.getInstance()
|
KeyHandler.getInstance().handleKey(
|
||||||
keyHandler.handleKey(
|
|
||||||
editor.vim,
|
editor.vim,
|
||||||
keyStroke,
|
keyStroke,
|
||||||
injector.executionContextManager.onEditor(editor.vim, e.dataContext.vim),
|
injector.executionContextManager.onEditor(editor.vim, e.dataContext.vim),
|
||||||
keyHandler.keyHandlerState,
|
|
||||||
)
|
)
|
||||||
if (start != null) {
|
if (start != null) {
|
||||||
val duration = System.currentTimeMillis() - start
|
val duration = System.currentTimeMillis() - start
|
||||||
|
@ -14,7 +14,6 @@ import com.maddyhome.idea.vim.VimPlugin
|
|||||||
import com.maddyhome.idea.vim.api.ExecutionContext
|
import com.maddyhome.idea.vim.api.ExecutionContext
|
||||||
import com.maddyhome.idea.vim.api.VimCaret
|
import com.maddyhome.idea.vim.api.VimCaret
|
||||||
import com.maddyhome.idea.vim.api.VimEditor
|
import com.maddyhome.idea.vim.api.VimEditor
|
||||||
import com.maddyhome.idea.vim.api.globalOptions
|
|
||||||
import com.maddyhome.idea.vim.api.injector
|
import com.maddyhome.idea.vim.api.injector
|
||||||
import com.maddyhome.idea.vim.api.setChangeMarks
|
import com.maddyhome.idea.vim.api.setChangeMarks
|
||||||
import com.maddyhome.idea.vim.command.Argument
|
import com.maddyhome.idea.vim.command.Argument
|
||||||
@ -22,7 +21,6 @@ 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.common.TextRange
|
import com.maddyhome.idea.vim.common.TextRange
|
||||||
import com.maddyhome.idea.vim.common.argumentCaptured
|
import com.maddyhome.idea.vim.common.argumentCaptured
|
||||||
import com.maddyhome.idea.vim.ex.ExException
|
|
||||||
import com.maddyhome.idea.vim.group.MotionGroup
|
import com.maddyhome.idea.vim.group.MotionGroup
|
||||||
import com.maddyhome.idea.vim.group.visual.VimSelection
|
import com.maddyhome.idea.vim.group.visual.VimSelection
|
||||||
import com.maddyhome.idea.vim.handler.VimActionHandler
|
import com.maddyhome.idea.vim.handler.VimActionHandler
|
||||||
@ -31,67 +29,21 @@ import com.maddyhome.idea.vim.helper.MessageHelper
|
|||||||
import com.maddyhome.idea.vim.helper.vimStateMachine
|
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.state.mode.SelectionType
|
import com.maddyhome.idea.vim.state.mode.SelectionType
|
||||||
import com.maddyhome.idea.vim.vimscript.model.CommandLineVimLContext
|
|
||||||
import com.maddyhome.idea.vim.vimscript.model.datatypes.VimFuncref
|
|
||||||
import com.maddyhome.idea.vim.vimscript.model.expressions.FunctionCallExpression
|
|
||||||
import com.maddyhome.idea.vim.vimscript.model.expressions.SimpleExpression
|
|
||||||
|
|
||||||
// todo make it multicaret
|
// todo make it multicaret
|
||||||
private fun doOperatorAction(editor: VimEditor, context: ExecutionContext, textRange: TextRange, selectionType: SelectionType): Boolean {
|
private fun doOperatorAction(editor: VimEditor, context: ExecutionContext, textRange: TextRange, selectionType: SelectionType): Boolean {
|
||||||
val func = injector.globalOptions().operatorfunc
|
val operatorFunction = injector.keyGroup.operatorFunction
|
||||||
if (func.isEmpty()) {
|
if (operatorFunction == null) {
|
||||||
VimPlugin.showMessage(MessageHelper.message("E774"))
|
VimPlugin.showMessage(MessageHelper.message("E774"))
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
val scriptContext = CommandLineVimLContext
|
|
||||||
|
|
||||||
// The option value is either a function name, which should have a handler, or it might be a lambda expression, or a
|
|
||||||
// `function` or `funcref` call expression, all of which will return a funcref (with a handler)
|
|
||||||
var handler = injector.functionService.getFunctionHandlerOrNull(null, func, scriptContext)
|
|
||||||
if (handler == null) {
|
|
||||||
val expression = injector.vimscriptParser.parseExpression(func)
|
|
||||||
if (expression != null) {
|
|
||||||
try {
|
|
||||||
val value = expression.evaluate(editor, context, scriptContext)
|
|
||||||
if (value is VimFuncref) {
|
|
||||||
handler = value.handler
|
|
||||||
}
|
|
||||||
} catch (ex: ExException) {
|
|
||||||
// Get the argument for function('...') or funcref('...') for the error message
|
|
||||||
val functionName = if (expression is FunctionCallExpression && expression.arguments.size > 0) {
|
|
||||||
expression.arguments[0].evaluate(editor, context, scriptContext).toString()
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
func
|
|
||||||
}
|
|
||||||
|
|
||||||
VimPlugin.showMessage("E117: Unknown function: $functionName")
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (handler == null) {
|
|
||||||
VimPlugin.showMessage("E117: Unknown function: $func")
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
val arg = when (selectionType) {
|
|
||||||
SelectionType.LINE_WISE -> "line"
|
|
||||||
SelectionType.CHARACTER_WISE -> "char"
|
|
||||||
SelectionType.BLOCK_WISE -> "block"
|
|
||||||
}
|
|
||||||
|
|
||||||
val saveRepeatHandler = VimRepeater.repeatHandler
|
val saveRepeatHandler = VimRepeater.repeatHandler
|
||||||
injector.markService.setChangeMarks(editor.primaryCaret(), textRange)
|
injector.markService.setChangeMarks(editor.primaryCaret(), textRange)
|
||||||
KeyHandler.getInstance().reset(editor)
|
KeyHandler.getInstance().reset(editor)
|
||||||
|
val result = operatorFunction.apply(editor, context, selectionType)
|
||||||
val arguments = listOf(SimpleExpression(arg))
|
|
||||||
handler.executeFunction(arguments, editor, context, scriptContext)
|
|
||||||
|
|
||||||
VimRepeater.repeatHandler = saveRepeatHandler
|
VimRepeater.repeatHandler = saveRepeatHandler
|
||||||
return true
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
@CommandOrMotion(keys = ["g@"], modes = [Mode.NORMAL])
|
@CommandOrMotion(keys = ["g@"], modes = [Mode.NORMAL])
|
||||||
|
@ -7,9 +7,9 @@
|
|||||||
*/
|
*/
|
||||||
package com.maddyhome.idea.vim.action.change
|
package com.maddyhome.idea.vim.action.change
|
||||||
|
|
||||||
import com.intellij.openapi.command.CommandProcessor
|
|
||||||
import com.intellij.vim.annotations.CommandOrMotion
|
import com.intellij.vim.annotations.CommandOrMotion
|
||||||
import com.intellij.vim.annotations.Mode
|
import com.intellij.vim.annotations.Mode
|
||||||
|
import com.intellij.openapi.command.CommandProcessor
|
||||||
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
|
||||||
|
@ -21,19 +21,19 @@ import com.maddyhome.idea.vim.state.mode.SelectionType
|
|||||||
public class CommandState(private val machine: VimStateMachine) {
|
public class CommandState(private val machine: VimStateMachine) {
|
||||||
|
|
||||||
public val isOperatorPending: Boolean
|
public val isOperatorPending: Boolean
|
||||||
get() = machine.isOperatorPending(machine.mode)
|
get() = machine.isOperatorPending
|
||||||
|
|
||||||
public val mode: Mode
|
public val mode: CommandState.Mode
|
||||||
get() {
|
get() {
|
||||||
val myMode = machine.mode
|
val myMode = machine.mode
|
||||||
return when (myMode) {
|
return when (myMode) {
|
||||||
is com.maddyhome.idea.vim.state.mode.Mode.CMD_LINE -> Mode.CMD_LINE
|
is com.maddyhome.idea.vim.state.mode.Mode.CMD_LINE -> CommandState.Mode.CMD_LINE
|
||||||
com.maddyhome.idea.vim.state.mode.Mode.INSERT -> Mode.INSERT
|
com.maddyhome.idea.vim.state.mode.Mode.INSERT -> CommandState.Mode.INSERT
|
||||||
is com.maddyhome.idea.vim.state.mode.Mode.NORMAL -> Mode.COMMAND
|
is com.maddyhome.idea.vim.state.mode.Mode.NORMAL -> CommandState.Mode.COMMAND
|
||||||
is com.maddyhome.idea.vim.state.mode.Mode.OP_PENDING -> Mode.OP_PENDING
|
is com.maddyhome.idea.vim.state.mode.Mode.OP_PENDING -> CommandState.Mode.OP_PENDING
|
||||||
com.maddyhome.idea.vim.state.mode.Mode.REPLACE -> Mode.REPLACE
|
com.maddyhome.idea.vim.state.mode.Mode.REPLACE -> CommandState.Mode.REPLACE
|
||||||
is com.maddyhome.idea.vim.state.mode.Mode.SELECT -> Mode.SELECT
|
is com.maddyhome.idea.vim.state.mode.Mode.SELECT -> CommandState.Mode.SELECT
|
||||||
is com.maddyhome.idea.vim.state.mode.Mode.VISUAL -> Mode.VISUAL
|
is com.maddyhome.idea.vim.state.mode.Mode.VISUAL -> CommandState.Mode.VISUAL
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,34 +14,21 @@ 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.ExecutionContext
|
|
||||||
import com.maddyhome.idea.vim.api.ImmutableVimCaret
|
import com.maddyhome.idea.vim.api.ImmutableVimCaret
|
||||||
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.injector
|
import com.maddyhome.idea.vim.api.injector
|
||||||
import com.maddyhome.idea.vim.command.MappingMode
|
import com.maddyhome.idea.vim.command.MappingMode
|
||||||
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.TextRange
|
|
||||||
import com.maddyhome.idea.vim.helper.CommandLineHelper
|
import com.maddyhome.idea.vim.helper.CommandLineHelper
|
||||||
import com.maddyhome.idea.vim.helper.TestInputModel
|
import com.maddyhome.idea.vim.helper.TestInputModel
|
||||||
import com.maddyhome.idea.vim.helper.noneOfEnum
|
|
||||||
import com.maddyhome.idea.vim.helper.vimStateMachine
|
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
|
||||||
import com.maddyhome.idea.vim.state.mode.SelectionType
|
import com.maddyhome.idea.vim.state.mode.SelectionType
|
||||||
import com.maddyhome.idea.vim.ui.ModalEntry
|
import com.maddyhome.idea.vim.ui.ModalEntry
|
||||||
import com.maddyhome.idea.vim.vimscript.model.Executable
|
|
||||||
import com.maddyhome.idea.vim.vimscript.model.ExecutionResult
|
|
||||||
import com.maddyhome.idea.vim.vimscript.model.VimLContext
|
|
||||||
import com.maddyhome.idea.vim.vimscript.model.datatypes.VimDataType
|
|
||||||
import com.maddyhome.idea.vim.vimscript.model.expressions.Expression
|
|
||||||
import com.maddyhome.idea.vim.vimscript.model.expressions.Scope
|
|
||||||
import com.maddyhome.idea.vim.vimscript.model.statements.FunctionDeclaration
|
|
||||||
import com.maddyhome.idea.vim.vimscript.model.statements.FunctionFlag
|
|
||||||
import java.awt.event.KeyEvent
|
import java.awt.event.KeyEvent
|
||||||
import java.util.*
|
|
||||||
import javax.swing.KeyStroke
|
import javax.swing.KeyStroke
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -133,6 +120,12 @@ public object VimExtensionFacade {
|
|||||||
.setAlias(name, CommandAlias.Call(minimumNumberOfArguments, maximumNumberOfArguments, name, handler))
|
.setAlias(name, CommandAlias.Call(minimumNumberOfArguments, maximumNumberOfArguments, name, handler))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Sets the value of 'operatorfunc' to be used as the operator function in 'g@'. */
|
||||||
|
@JvmStatic
|
||||||
|
public fun setOperatorFunction(function: OperatorFunction) {
|
||||||
|
VimPlugin.getKey().operatorFunction = function
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Runs normal mode commands similar to ':normal! {commands}'.
|
* Runs normal mode commands similar to ':normal! {commands}'.
|
||||||
* Mappings doesn't work with this function
|
* Mappings doesn't work with this function
|
||||||
@ -143,8 +136,7 @@ public object VimExtensionFacade {
|
|||||||
@JvmStatic
|
@JvmStatic
|
||||||
public fun executeNormalWithoutMapping(keys: List<KeyStroke>, editor: Editor) {
|
public fun executeNormalWithoutMapping(keys: List<KeyStroke>, editor: Editor) {
|
||||||
val context = injector.executionContextManager.onEditor(editor.vim)
|
val context = injector.executionContextManager.onEditor(editor.vim)
|
||||||
val keyHandler = KeyHandler.getInstance()
|
keys.forEach { KeyHandler.getInstance().handleKey(editor.vim, it, context, false, false) }
|
||||||
keys.forEach { keyHandler.handleKey(editor.vim, it, context, false, false, keyHandler.keyHandlerState) }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns a single key stroke from the user input similar to 'getchar()'. */
|
/** Returns a single key stroke from the user input similar to 'getchar()'. */
|
||||||
@ -160,7 +152,7 @@ public object VimExtensionFacade {
|
|||||||
LOG.trace("Unit test mode is active")
|
LOG.trace("Unit test mode is active")
|
||||||
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 (injector.registerGroup.isRecording) {
|
if (editor.vim.vimStateMachine.isRecording) {
|
||||||
KeyHandler.getInstance().modalEntryKeys += it
|
KeyHandler.getInstance().modalEntryKeys += it
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -215,65 +207,4 @@ public object VimExtensionFacade {
|
|||||||
public fun setRegister(register: Char, keys: List<KeyStroke?>?, type: SelectionType) {
|
public fun setRegister(register: Char, keys: List<KeyStroke?>?, type: SelectionType) {
|
||||||
VimPlugin.getRegister().setKeys(register, keys?.filterNotNull() ?: emptyList(), type)
|
VimPlugin.getRegister().setKeys(register, keys?.filterNotNull() ?: emptyList(), type)
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmStatic
|
|
||||||
public fun exportScriptFunction(
|
|
||||||
scope: Scope?,
|
|
||||||
name: String,
|
|
||||||
args: List<String>,
|
|
||||||
defaultArgs: List<Pair<String, Expression>>,
|
|
||||||
hasOptionalArguments: Boolean,
|
|
||||||
flags: EnumSet<FunctionFlag>,
|
|
||||||
function: ScriptFunction
|
|
||||||
) {
|
|
||||||
var functionDeclaration: FunctionDeclaration? = null
|
|
||||||
val body = listOf(object : Executable {
|
|
||||||
// This context is set to the function declaration during initialisation and then set to the function execution
|
|
||||||
// context during execution
|
|
||||||
override lateinit var vimContext: VimLContext
|
|
||||||
override var rangeInScript: TextRange = TextRange(0, 0)
|
|
||||||
|
|
||||||
override fun execute(editor: VimEditor, context: ExecutionContext): ExecutionResult {
|
|
||||||
return function.execute(editor, context, functionDeclaration!!.functionVariables)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
functionDeclaration = FunctionDeclaration(
|
|
||||||
scope,
|
|
||||||
name,
|
|
||||||
args,
|
|
||||||
defaultArgs,
|
|
||||||
body,
|
|
||||||
replaceExisting = true,
|
|
||||||
flags,
|
|
||||||
hasOptionalArguments
|
|
||||||
)
|
|
||||||
functionDeclaration.rangeInScript = TextRange(0, 0)
|
|
||||||
body.forEach { it.vimContext = functionDeclaration }
|
|
||||||
injector.functionService.storeFunction(functionDeclaration)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public fun VimExtensionFacade.exportOperatorFunction(name: String, function: OperatorFunction) {
|
|
||||||
exportScriptFunction(null, name, listOf("type"), emptyList(), false, noneOfEnum()) {
|
|
||||||
editor, context, args ->
|
|
||||||
|
|
||||||
val type = args["type"]?.asString()
|
|
||||||
val selectionType = when (type) {
|
|
||||||
"line" -> SelectionType.LINE_WISE
|
|
||||||
"block" -> SelectionType.BLOCK_WISE
|
|
||||||
"char" -> SelectionType.CHARACTER_WISE
|
|
||||||
else -> return@exportScriptFunction ExecutionResult.Error
|
|
||||||
}
|
|
||||||
|
|
||||||
if (function.apply(editor, context, selectionType)) {
|
|
||||||
ExecutionResult.Success
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
ExecutionResult.Error
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public fun interface ScriptFunction {
|
|
||||||
public fun execute(editor: VimEditor, context: ExecutionContext, args: Map<String, VimDataType>): ExecutionResult
|
|
||||||
}
|
}
|
@ -67,7 +67,7 @@ internal object VimExtensionRegistrar : VimExtensionRegistrator {
|
|||||||
VimPlugin.getOptionGroup().addGlobalOptionChangeListener(option) {
|
VimPlugin.getOptionGroup().addGlobalOptionChangeListener(option) {
|
||||||
if (injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL(null)).asBoolean()) {
|
if (injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL(null)).asBoolean()) {
|
||||||
initExtension(extensionBean, name)
|
initExtension(extensionBean, name)
|
||||||
PluginState.Util.enabledExtensions.add(name)
|
PluginState.enabledExtensions.add(name)
|
||||||
} else {
|
} else {
|
||||||
extensionBean.instance.dispose()
|
extensionBean.instance.dispose()
|
||||||
}
|
}
|
||||||
|
@ -251,7 +251,7 @@ public class VimArgTextObjExtension implements VimExtension {
|
|||||||
|
|
||||||
final ArgumentTextObjectHandler textObjectHandler = new ArgumentTextObjectHandler(isInner);
|
final ArgumentTextObjectHandler textObjectHandler = new ArgumentTextObjectHandler(isInner);
|
||||||
//noinspection DuplicatedCode
|
//noinspection DuplicatedCode
|
||||||
if (!vimStateMachine.isOperatorPending(editor.getMode())) {
|
if (!vimStateMachine.isOperatorPending()) {
|
||||||
editor.nativeCarets().forEach((VimCaret caret) -> {
|
editor.nativeCarets().forEach((VimCaret caret) -> {
|
||||||
final TextRange range = textObjectHandler.getRange(editor, caret, context, count, 0);
|
final TextRange range = textObjectHandler.getRange(editor, caret, context, count, 0);
|
||||||
if (range != null) {
|
if (range != null) {
|
||||||
|
@ -22,26 +22,26 @@ import com.maddyhome.idea.vim.api.ExecutionContext
|
|||||||
import com.maddyhome.idea.vim.api.ImmutableVimCaret
|
import com.maddyhome.idea.vim.api.ImmutableVimCaret
|
||||||
import com.maddyhome.idea.vim.api.VimEditor
|
import com.maddyhome.idea.vim.api.VimEditor
|
||||||
import com.maddyhome.idea.vim.api.getLineEndOffset
|
import com.maddyhome.idea.vim.api.getLineEndOffset
|
||||||
import com.maddyhome.idea.vim.api.globalOptions
|
|
||||||
import com.maddyhome.idea.vim.api.injector
|
import com.maddyhome.idea.vim.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.MappingMode
|
||||||
|
import com.maddyhome.idea.vim.state.mode.Mode
|
||||||
import com.maddyhome.idea.vim.command.OperatorArguments
|
import com.maddyhome.idea.vim.command.OperatorArguments
|
||||||
|
import com.maddyhome.idea.vim.state.mode.SelectionType
|
||||||
import com.maddyhome.idea.vim.command.TextObjectVisualType
|
import com.maddyhome.idea.vim.command.TextObjectVisualType
|
||||||
import com.maddyhome.idea.vim.common.CommandAliasHandler
|
import com.maddyhome.idea.vim.common.CommandAliasHandler
|
||||||
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.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.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
|
||||||
import com.maddyhome.idea.vim.extension.VimExtensionFacade.putExtensionHandlerMapping
|
import com.maddyhome.idea.vim.extension.VimExtensionFacade.putExtensionHandlerMapping
|
||||||
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.exportOperatorFunction
|
import com.maddyhome.idea.vim.extension.VimExtensionFacade.setOperatorFunction
|
||||||
import com.maddyhome.idea.vim.handler.TextObjectActionHandler
|
import com.maddyhome.idea.vim.handler.TextObjectActionHandler
|
||||||
import com.maddyhome.idea.vim.helper.PsiHelper
|
import com.maddyhome.idea.vim.helper.PsiHelper
|
||||||
import com.maddyhome.idea.vim.helper.vimStateMachine
|
import com.maddyhome.idea.vim.helper.vimStateMachine
|
||||||
@ -49,19 +49,17 @@ import com.maddyhome.idea.vim.key.OperatorFunction
|
|||||||
import com.maddyhome.idea.vim.newapi.IjVimEditor
|
import com.maddyhome.idea.vim.newapi.IjVimEditor
|
||||||
import com.maddyhome.idea.vim.newapi.ij
|
import com.maddyhome.idea.vim.newapi.ij
|
||||||
import com.maddyhome.idea.vim.newapi.vim
|
import com.maddyhome.idea.vim.newapi.vim
|
||||||
import com.maddyhome.idea.vim.state.mode.Mode
|
|
||||||
import com.maddyhome.idea.vim.state.mode.SelectionType
|
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
internal class CommentaryExtension : VimExtension {
|
internal class CommentaryExtension : VimExtension {
|
||||||
|
|
||||||
object Util {
|
companion object {
|
||||||
fun doCommentary(
|
fun doCommentary(
|
||||||
editor: VimEditor,
|
editor: VimEditor,
|
||||||
context: ExecutionContext,
|
context: ExecutionContext,
|
||||||
range: TextRange,
|
range: TextRange,
|
||||||
selectionType: SelectionType,
|
selectionType: SelectionType,
|
||||||
resetCaret: Boolean = true,
|
resetCaret: Boolean,
|
||||||
): Boolean {
|
): Boolean {
|
||||||
val mode = editor.vimStateMachine.mode
|
val mode = editor.vimStateMachine.mode
|
||||||
if (mode !is Mode.VISUAL) {
|
if (mode !is Mode.VISUAL) {
|
||||||
@ -69,7 +67,8 @@ internal class CommentaryExtension : VimExtension {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return runWriteAction {
|
return runWriteAction {
|
||||||
// Treat block- and character-wise selections as block comments. Fall back if the first action isn't available
|
// Treat block- and character-wise selections as block comments. Be ready to fall back to if the first action
|
||||||
|
// isn't available
|
||||||
val actions = if (selectionType === SelectionType.LINE_WISE) {
|
val actions = if (selectionType === SelectionType.LINE_WISE) {
|
||||||
listOf(IdeActions.ACTION_COMMENT_LINE, IdeActions.ACTION_COMMENT_BLOCK)
|
listOf(IdeActions.ACTION_COMMENT_LINE, IdeActions.ACTION_COMMENT_BLOCK)
|
||||||
} else {
|
} else {
|
||||||
@ -114,17 +113,12 @@ internal class CommentaryExtension : VimExtension {
|
|||||||
// first non-whitespace character, then the caret is in the right place. If it's inserted at the first column,
|
// first non-whitespace character, then the caret is in the right place. If it's inserted at the first column,
|
||||||
// then the caret is now in a bit of a weird place. We can't detect this scenario, so we just have to accept
|
// then the caret is now in a bit of a weird place. We can't detect this scenario, so we just have to accept
|
||||||
// the difference
|
// the difference
|
||||||
// TODO: If we don't move the caret to the start offset, we should maintain the current logical position
|
|
||||||
if (resetCaret) {
|
if (resetCaret) {
|
||||||
editor.primaryCaret().moveToOffset(range.startOffset)
|
editor.primaryCaret().moveToOffset(range.startOffset)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
|
||||||
private const val OPERATOR_FUNC = "CommentaryOperatorFunc"
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getName() = "commentary"
|
override fun getName() = "commentary"
|
||||||
|
|
||||||
override fun init() {
|
override fun init() {
|
||||||
@ -151,16 +145,6 @@ internal class CommentaryExtension : VimExtension {
|
|||||||
putKeyMapping(MappingMode.N, injector.parser.parseKeys("<Plug>(CommentLine)"), owner, plugCommentaryLineKeys, true)
|
putKeyMapping(MappingMode.N, injector.parser.parseKeys("<Plug>(CommentLine)"), owner, plugCommentaryLineKeys, true)
|
||||||
|
|
||||||
addCommand("Commentary", CommentaryCommandAliasHandler())
|
addCommand("Commentary", CommentaryCommandAliasHandler())
|
||||||
|
|
||||||
VimExtensionFacade.exportOperatorFunction(OPERATOR_FUNC, CommentaryOperatorFunction())
|
|
||||||
}
|
|
||||||
|
|
||||||
private class CommentaryOperatorFunction : OperatorFunction {
|
|
||||||
// todo make it multicaret
|
|
||||||
override fun apply(editor: VimEditor, context: ExecutionContext, selectionType: SelectionType?): Boolean {
|
|
||||||
val range = injector.markService.getChangeMarks(editor.primaryCaret()) ?: return false
|
|
||||||
return Util.doCommentary(editor, context, range, selectionType ?: SelectionType.CHARACTER_WISE, true)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -169,13 +153,19 @@ internal 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 : ExtensionHandler {
|
private class CommentaryOperatorHandler : OperatorFunction, ExtensionHandler {
|
||||||
override val isRepeatable = true
|
override val isRepeatable = true
|
||||||
|
|
||||||
override fun execute(editor: VimEditor, context: ExecutionContext, operatorArguments: OperatorArguments) {
|
override fun execute(editor: VimEditor, context: ExecutionContext, operatorArguments: OperatorArguments) {
|
||||||
injector.globalOptions().operatorfunc = OPERATOR_FUNC
|
setOperatorFunction(this)
|
||||||
executeNormalWithoutMapping(injector.parser.parseKeys("g@"), editor.ij)
|
executeNormalWithoutMapping(injector.parser.parseKeys("g@"), editor.ij)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// todo make it multicaret
|
||||||
|
override fun apply(editor: VimEditor, context: ExecutionContext, selectionType: SelectionType?): Boolean {
|
||||||
|
val range = injector.markService.getChangeMarks(editor.primaryCaret()) ?: return false
|
||||||
|
return doCommentary(editor, context, range, selectionType ?: SelectionType.CHARACTER_WISE, true)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class CommentaryMappingHandler : ExtensionHandler {
|
private class CommentaryMappingHandler : ExtensionHandler {
|
||||||
@ -249,7 +239,7 @@ internal class CommentaryExtension : VimExtension {
|
|||||||
*/
|
*/
|
||||||
private class CommentaryCommandAliasHandler : CommandAliasHandler {
|
private class CommentaryCommandAliasHandler : CommandAliasHandler {
|
||||||
override fun execute(command: String, ranges: Ranges, editor: VimEditor, context: ExecutionContext) {
|
override fun execute(command: String, ranges: Ranges, editor: VimEditor, context: ExecutionContext) {
|
||||||
Util.doCommentary(editor, context, ranges.getTextRange(editor, -1), SelectionType.LINE_WISE, false)
|
doCommentary(editor, context, ranges.getTextRange(editor, -1), SelectionType.LINE_WISE, false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,22 +19,24 @@ import com.intellij.openapi.util.Key
|
|||||||
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.getOffset
|
import com.maddyhome.idea.vim.api.getOffset
|
||||||
import com.maddyhome.idea.vim.api.globalOptions
|
|
||||||
import com.maddyhome.idea.vim.api.injector
|
import com.maddyhome.idea.vim.api.injector
|
||||||
import com.maddyhome.idea.vim.api.setChangeMarks
|
import com.maddyhome.idea.vim.api.setChangeMarks
|
||||||
import com.maddyhome.idea.vim.command.MappingMode
|
import com.maddyhome.idea.vim.command.MappingMode
|
||||||
import com.maddyhome.idea.vim.command.OperatorArguments
|
import com.maddyhome.idea.vim.command.OperatorArguments
|
||||||
|
import com.maddyhome.idea.vim.state.mode.SelectionType
|
||||||
|
import com.maddyhome.idea.vim.state.mode.SelectionType.CHARACTER_WISE
|
||||||
|
import com.maddyhome.idea.vim.state.mode.selectionType
|
||||||
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.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.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
|
||||||
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.setRegister
|
import com.maddyhome.idea.vim.extension.VimExtensionFacade.setRegister
|
||||||
import com.maddyhome.idea.vim.extension.exportOperatorFunction
|
|
||||||
import com.maddyhome.idea.vim.helper.fileSize
|
import com.maddyhome.idea.vim.helper.fileSize
|
||||||
|
import com.maddyhome.idea.vim.state.mode.mode
|
||||||
import com.maddyhome.idea.vim.helper.moveToInlayAwareLogicalPosition
|
import com.maddyhome.idea.vim.helper.moveToInlayAwareLogicalPosition
|
||||||
import com.maddyhome.idea.vim.helper.moveToInlayAwareOffset
|
import com.maddyhome.idea.vim.helper.moveToInlayAwareOffset
|
||||||
import com.maddyhome.idea.vim.key.OperatorFunction
|
import com.maddyhome.idea.vim.key.OperatorFunction
|
||||||
@ -43,8 +45,6 @@ import com.maddyhome.idea.vim.mark.VimMarkConstants
|
|||||||
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.state.mode.SelectionType
|
|
||||||
import com.maddyhome.idea.vim.state.mode.selectionType
|
|
||||||
import org.jetbrains.annotations.NonNls
|
import org.jetbrains.annotations.NonNls
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -72,13 +72,30 @@ internal class VimExchangeExtension : VimExtension {
|
|||||||
putKeyMappingIfMissing(MappingMode.X, injector.parser.parseKeys("X"), owner, injector.parser.parseKeys(EXCHANGE_CMD), true)
|
putKeyMappingIfMissing(MappingMode.X, injector.parser.parseKeys("X"), owner, injector.parser.parseKeys(EXCHANGE_CMD), true)
|
||||||
putKeyMappingIfMissing(MappingMode.N, injector.parser.parseKeys("cxc"), owner, injector.parser.parseKeys(EXCHANGE_CLEAR_CMD), true)
|
putKeyMappingIfMissing(MappingMode.N, injector.parser.parseKeys("cxc"), owner, injector.parser.parseKeys(EXCHANGE_CLEAR_CMD), true)
|
||||||
putKeyMappingIfMissing(MappingMode.N, injector.parser.parseKeys("cxx"), owner, injector.parser.parseKeys(EXCHANGE_LINE_CMD), true)
|
putKeyMappingIfMissing(MappingMode.N, injector.parser.parseKeys("cxx"), owner, injector.parser.parseKeys(EXCHANGE_LINE_CMD), true)
|
||||||
|
|
||||||
VimExtensionFacade.exportOperatorFunction(OPERATOR_FUNC, Operator())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
object Util {
|
companion object {
|
||||||
|
@NonNls
|
||||||
|
const val EXCHANGE_CMD = "<Plug>(Exchange)"
|
||||||
|
|
||||||
|
@NonNls
|
||||||
|
const val EXCHANGE_CLEAR_CMD = "<Plug>(ExchangeClear)"
|
||||||
|
|
||||||
|
@NonNls
|
||||||
|
const val EXCHANGE_LINE_CMD = "<Plug>(ExchangeLine)"
|
||||||
|
|
||||||
val EXCHANGE_KEY = Key<Exchange>("exchange")
|
val EXCHANGE_KEY = Key<Exchange>("exchange")
|
||||||
|
|
||||||
|
// End mark has always greater of eq offset than start mark
|
||||||
|
class Exchange(val type: SelectionType, val start: Mark, val end: Mark, val text: String) {
|
||||||
|
private var myHighlighter: RangeHighlighter? = null
|
||||||
|
fun setHighlighter(highlighter: RangeHighlighter) {
|
||||||
|
myHighlighter = highlighter
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getHighlighter(): RangeHighlighter? = myHighlighter
|
||||||
|
}
|
||||||
|
|
||||||
fun clearExchange(editor: Editor) {
|
fun clearExchange(editor: Editor) {
|
||||||
editor.getUserData(EXCHANGE_KEY)?.getHighlighter()?.let {
|
editor.getUserData(EXCHANGE_KEY)?.getHighlighter()?.let {
|
||||||
editor.markupModel.removeHighlighter(it)
|
editor.markupModel.removeHighlighter(it)
|
||||||
@ -87,25 +104,18 @@ internal class VimExchangeExtension : VimExtension {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
|
||||||
@NonNls private const val EXCHANGE_CMD = "<Plug>(Exchange)"
|
|
||||||
@NonNls private const val EXCHANGE_CLEAR_CMD = "<Plug>(ExchangeClear)"
|
|
||||||
@NonNls private const val EXCHANGE_LINE_CMD = "<Plug>(ExchangeLine)"
|
|
||||||
@NonNls private const val OPERATOR_FUNC = "ExchangeOperatorFunc"
|
|
||||||
}
|
|
||||||
|
|
||||||
private class ExchangeHandler(private val isLine: Boolean) : ExtensionHandler {
|
private class ExchangeHandler(private val isLine: Boolean) : ExtensionHandler {
|
||||||
override val isRepeatable = true
|
override val isRepeatable = true
|
||||||
|
|
||||||
override fun execute(editor: VimEditor, context: ExecutionContext, operatorArguments: OperatorArguments) {
|
override fun execute(editor: VimEditor, context: ExecutionContext, operatorArguments: OperatorArguments) {
|
||||||
injector.globalOptions().operatorfunc = OPERATOR_FUNC
|
setOperatorFunction(Operator(false))
|
||||||
executeNormalWithoutMapping(injector.parser.parseKeys(if (isLine) "g@_" else "g@"), editor.ij)
|
executeNormalWithoutMapping(injector.parser.parseKeys(if (isLine) "g@_" else "g@"), editor.ij)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class ExchangeClearHandler : ExtensionHandler {
|
private class ExchangeClearHandler : ExtensionHandler {
|
||||||
override fun execute(editor: VimEditor, context: ExecutionContext, operatorArguments: OperatorArguments) {
|
override fun execute(editor: VimEditor, context: ExecutionContext, operatorArguments: OperatorArguments) {
|
||||||
Util.clearExchange(editor.ij)
|
clearExchange(editor.ij)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,12 +125,12 @@ internal class VimExchangeExtension : VimExtension {
|
|||||||
val mode = editor.mode
|
val mode = editor.mode
|
||||||
// Leave visual mode to create selection marks
|
// Leave visual mode to create selection marks
|
||||||
executeNormalWithoutMapping(injector.parser.parseKeys("<Esc>"), editor.ij)
|
executeNormalWithoutMapping(injector.parser.parseKeys("<Esc>"), editor.ij)
|
||||||
Operator(true).apply(editor, context, mode.selectionType ?: SelectionType.CHARACTER_WISE)
|
Operator(true).apply(editor, context, mode.selectionType ?: CHARACTER_WISE)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class Operator(private val isVisual: Boolean = false) : OperatorFunction {
|
private class Operator(private val isVisual: Boolean) : OperatorFunction {
|
||||||
fun Editor.getMarkOffset(mark: Mark) = IjVimEditor(this).getOffset(mark.line, mark.col)
|
fun Editor.getMarkOffset(mark: Mark) = IjVimEditor(this).getOffset(mark.line, mark.col)
|
||||||
fun SelectionType.getString() = when (this) {
|
fun SelectionType.getString() = when (this) {
|
||||||
SelectionType.CHARACTER_WISE -> "v"
|
SelectionType.CHARACTER_WISE -> "v"
|
||||||
@ -138,7 +148,7 @@ internal class VimExchangeExtension : VimExtension {
|
|||||||
else -> HighlighterTargetArea.EXACT_RANGE
|
else -> HighlighterTargetArea.EXACT_RANGE
|
||||||
}
|
}
|
||||||
val isVisualLine = ex.type == SelectionType.LINE_WISE
|
val isVisualLine = ex.type == SelectionType.LINE_WISE
|
||||||
val endAdj = if (!(isVisualLine) && (hlArea == HighlighterTargetArea.EXACT_RANGE || isVisual)) 1 else 0
|
val endAdj = if (!(isVisualLine) && (hlArea == HighlighterTargetArea.EXACT_RANGE || (isVisual))) 1 else 0
|
||||||
return ijEditor.markupModel.addRangeHighlighter(
|
return ijEditor.markupModel.addRangeHighlighter(
|
||||||
ijEditor.getMarkOffset(ex.start),
|
ijEditor.getMarkOffset(ex.start),
|
||||||
(ijEditor.getMarkOffset(ex.end) + endAdj).coerceAtMost(ijEditor.fileSize),
|
(ijEditor.getMarkOffset(ex.end) + endAdj).coerceAtMost(ijEditor.fileSize),
|
||||||
@ -148,12 +158,12 @@ internal class VimExchangeExtension : VimExtension {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
val currentExchange = getExchange(ijEditor, isVisual, selectionType ?: SelectionType.CHARACTER_WISE)
|
val currentExchange = getExchange(ijEditor, isVisual, selectionType ?: CHARACTER_WISE)
|
||||||
val exchange1 = ijEditor.getUserData(Util.EXCHANGE_KEY)
|
val exchange1 = ijEditor.getUserData(EXCHANGE_KEY)
|
||||||
if (exchange1 == null) {
|
if (exchange1 == null) {
|
||||||
val highlighter = highlightExchange(currentExchange)
|
val highlighter = highlightExchange(currentExchange)
|
||||||
currentExchange.setHighlighter(highlighter)
|
currentExchange.setHighlighter(highlighter)
|
||||||
ijEditor.putUserData(Util.EXCHANGE_KEY, currentExchange)
|
ijEditor.putUserData(EXCHANGE_KEY, currentExchange)
|
||||||
return true
|
return true
|
||||||
} else {
|
} else {
|
||||||
val cmp = compareExchanges(exchange1, currentExchange)
|
val cmp = compareExchanges(exchange1, currentExchange)
|
||||||
@ -179,7 +189,7 @@ internal class VimExchangeExtension : VimExtension {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
exchange(ijEditor, ex1, ex2, reverse, expand)
|
exchange(ijEditor, ex1, ex2, reverse, expand)
|
||||||
Util.clearExchange(ijEditor)
|
clearExchange(ijEditor)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -344,14 +354,4 @@ internal class VimExchangeExtension : VimExtension {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// End mark has always greater of eq offset than start mark
|
|
||||||
class Exchange(val type: SelectionType, val start: Mark, val end: Mark, val text: String) {
|
|
||||||
private var myHighlighter: RangeHighlighter? = null
|
|
||||||
fun setHighlighter(highlighter: RangeHighlighter) {
|
|
||||||
myHighlighter = highlighter
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getHighlighter(): RangeHighlighter? = myHighlighter
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -99,7 +99,7 @@ internal class Matchit : VimExtension {
|
|||||||
|
|
||||||
// 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.
|
||||||
val isInOpPending = commandState.isOperatorPending(editor.mode)
|
val isInOpPending = commandState.isOperatorPending
|
||||||
|
|
||||||
if (isInOpPending) {
|
if (isInOpPending) {
|
||||||
val matchitAction = MatchitAction()
|
val matchitAction = MatchitAction()
|
||||||
|
@ -130,15 +130,15 @@ internal class NerdTree : VimExtension {
|
|||||||
addCommand("NERDTreeFind", IjCommandHandler("SelectInProjectView"))
|
addCommand("NERDTreeFind", IjCommandHandler("SelectInProjectView"))
|
||||||
addCommand("NERDTreeRefreshRoot", IjCommandHandler("Synchronize"))
|
addCommand("NERDTreeRefreshRoot", IjCommandHandler("Synchronize"))
|
||||||
|
|
||||||
synchronized(Util.monitor) {
|
synchronized(monitor) {
|
||||||
Util.commandsRegistered = true
|
commandsRegistered = true
|
||||||
ProjectManager.getInstance().openProjects.forEach { project -> installDispatcher(project) }
|
ProjectManager.getInstance().openProjects.forEach { project -> installDispatcher(project) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class IjCommandHandler(private val actionId: String) : CommandAliasHandler {
|
class IjCommandHandler(private val actionId: String) : CommandAliasHandler {
|
||||||
override fun execute(command: String, ranges: Ranges, editor: VimEditor, context: ExecutionContext) {
|
override fun execute(command: String, ranges: Ranges, editor: VimEditor, context: ExecutionContext) {
|
||||||
Util.callAction(editor, actionId, context)
|
callAction(editor, actionId, context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -149,7 +149,7 @@ internal class NerdTree : VimExtension {
|
|||||||
if (toolWindow.isVisible) {
|
if (toolWindow.isVisible) {
|
||||||
toolWindow.hide()
|
toolWindow.hide()
|
||||||
} else {
|
} else {
|
||||||
Util.callAction(editor, "ActivateProjectToolWindow", context)
|
callAction(editor, "ActivateProjectToolWindow", context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -187,8 +187,8 @@ internal class NerdTree : VimExtension {
|
|||||||
// TODO I'm not sure is this activity runs at all? Should we use [RunOnceUtil] instead?
|
// TODO I'm not sure is this activity runs at all? Should we use [RunOnceUtil] instead?
|
||||||
class NerdStartupActivity : ProjectActivity {
|
class NerdStartupActivity : ProjectActivity {
|
||||||
override suspend fun execute(project: Project) {
|
override suspend fun execute(project: Project) {
|
||||||
synchronized(Util.monitor) {
|
synchronized(monitor) {
|
||||||
if (!Util.commandsRegistered) return
|
if (!commandsRegistered) return
|
||||||
installDispatcher(project)
|
installDispatcher(project)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -214,7 +214,7 @@ internal class NerdTree : VimExtension {
|
|||||||
|
|
||||||
val action = nextNode.actionHolder
|
val action = nextNode.actionHolder
|
||||||
when (action) {
|
when (action) {
|
||||||
is NerdAction.ToIj -> Util.callAction(null, action.name, e.dataContext.vim)
|
is NerdAction.ToIj -> callAction(null, action.name, e.dataContext.vim)
|
||||||
is NerdAction.Code -> e.project?.let { action.action(it, e.dataContext, e) }
|
is NerdAction.Code -> e.project?.let { action.action(it, e.dataContext, e) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -356,7 +356,7 @@ internal class NerdTree : VimExtension {
|
|||||||
currentWindow?.split(SwingConstants.VERTICAL, true, file, true)
|
currentWindow?.split(SwingConstants.VERTICAL, true, file, true)
|
||||||
|
|
||||||
// FIXME: 22.01.2021 This solution bouncing a bit
|
// FIXME: 22.01.2021 This solution bouncing a bit
|
||||||
Util.callAction(null, "ActivateProjectToolWindow", context.vim)
|
callAction(null, "ActivateProjectToolWindow", context.vim)
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
registerCommand(
|
registerCommand(
|
||||||
@ -368,7 +368,7 @@ internal class NerdTree : VimExtension {
|
|||||||
val currentWindow = splitters.currentWindow
|
val currentWindow = splitters.currentWindow
|
||||||
currentWindow?.split(SwingConstants.HORIZONTAL, true, file, true)
|
currentWindow?.split(SwingConstants.HORIZONTAL, true, file, true)
|
||||||
|
|
||||||
Util.callAction(null, "ActivateProjectToolWindow", context.vim)
|
callAction(null, "ActivateProjectToolWindow", context.vim)
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
registerCommand(
|
registerCommand(
|
||||||
@ -511,9 +511,14 @@ internal class NerdTree : VimExtension {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
object Util {
|
companion object {
|
||||||
|
const val pluginName = "NERDTree"
|
||||||
|
|
||||||
internal val monitor = Any()
|
internal val monitor = Any()
|
||||||
internal var commandsRegistered = false
|
internal var commandsRegistered = false
|
||||||
|
|
||||||
|
private val LOG = logger<NerdTree>()
|
||||||
|
|
||||||
fun callAction(editor: VimEditor?, name: String, context: ExecutionContext) {
|
fun callAction(editor: VimEditor?, name: String, context: ExecutionContext) {
|
||||||
val action = ActionManager.getInstance().getAction(name) ?: run {
|
val action = ActionManager.getInstance().getAction(name) ?: run {
|
||||||
VimPlugin.showMessage(MessageHelper.message("action.not.found.0", name))
|
VimPlugin.showMessage(MessageHelper.message("action.not.found.0", name))
|
||||||
@ -528,19 +533,12 @@ internal class NerdTree : VimExtension {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
private fun addCommand(alias: String, handler: CommandAliasHandler) {
|
||||||
const val pluginName = "NERDTree"
|
|
||||||
private val LOG = logger<NerdTree>()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun addCommand(alias: String, handler: CommandAliasHandler) {
|
|
||||||
VimPlugin.getCommand().setAlias(alias, CommandAlias.Call(0, -1, alias, handler))
|
VimPlugin.getCommand().setAlias(alias, CommandAlias.Call(0, -1, alias, handler))
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun registerCommand(variable: String, default: String, action: NerdAction) {
|
private fun registerCommand(variable: String, default: String, action: NerdAction) {
|
||||||
val variableValue = VimPlugin.getVariableService().getGlobalVariableValue(variable)
|
val variableValue = VimPlugin.getVariableService().getGlobalVariableValue(variable)
|
||||||
val mappings = if (variableValue is VimString) {
|
val mappings = if (variableValue is VimString) {
|
||||||
variableValue.value
|
variableValue.value
|
||||||
@ -548,16 +546,16 @@ private fun registerCommand(variable: String, default: String, action: NerdActio
|
|||||||
default
|
default
|
||||||
}
|
}
|
||||||
actionsRoot.addLeafs(mappings, action)
|
actionsRoot.addLeafs(mappings, action)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun registerCommand(default: String, action: NerdAction) {
|
private fun registerCommand(default: String, action: NerdAction) {
|
||||||
actionsRoot.addLeafs(default, action)
|
actionsRoot.addLeafs(default, action)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val actionsRoot: RootNode<NerdAction> = RootNode()
|
||||||
|
private var currentNode: CommandPartNode<NerdAction> = actionsRoot
|
||||||
|
|
||||||
private val actionsRoot: RootNode<NerdAction> = RootNode()
|
private fun collectShortcuts(node: Node<NerdAction>): Set<KeyStroke> {
|
||||||
private var currentNode: CommandPartNode<NerdAction> = actionsRoot
|
|
||||||
private fun collectShortcuts(node: Node<NerdAction>): Set<KeyStroke> {
|
|
||||||
return if (node is CommandPartNode<NerdAction>) {
|
return if (node is CommandPartNode<NerdAction>) {
|
||||||
val res = node.keys.toMutableSet()
|
val res = node.keys.toMutableSet()
|
||||||
res += node.values.map { collectShortcuts(it) }.flatten()
|
res += node.values.map { collectShortcuts(it) }.flatten()
|
||||||
@ -565,14 +563,15 @@ private fun collectShortcuts(node: Node<NerdAction>): Set<KeyStroke> {
|
|||||||
} else {
|
} else {
|
||||||
emptySet()
|
emptySet()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun installDispatcher(project: Project) {
|
private fun installDispatcher(project: Project) {
|
||||||
val dispatcher = NerdTree.NerdDispatcher.getInstance(project)
|
val dispatcher = NerdDispatcher.getInstance(project)
|
||||||
val shortcuts =
|
val shortcuts = collectShortcuts(actionsRoot).map { RequiredShortcut(it, MappingOwner.Plugin.get(pluginName)) }
|
||||||
collectShortcuts(actionsRoot).map { RequiredShortcut(it, MappingOwner.Plugin.get(NerdTree.pluginName)) }
|
|
||||||
dispatcher.registerCustomShortcutSet(
|
dispatcher.registerCustomShortcutSet(
|
||||||
KeyGroup.toShortcutSet(shortcuts),
|
KeyGroup.toShortcutSet(shortcuts),
|
||||||
(ProjectView.getInstance(project) as ProjectViewImpl).component,
|
(ProjectView.getInstance(project) as ProjectViewImpl).component,
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,11 +9,10 @@
|
|||||||
package com.maddyhome.idea.vim.extension.paragraphmotion
|
package com.maddyhome.idea.vim.extension.paragraphmotion
|
||||||
|
|
||||||
import com.intellij.openapi.editor.Caret
|
import com.intellij.openapi.editor.Caret
|
||||||
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.getLineEndForOffset
|
||||||
import com.maddyhome.idea.vim.api.injector
|
import com.maddyhome.idea.vim.api.injector
|
||||||
import com.maddyhome.idea.vim.api.normalizeOffset
|
|
||||||
import com.maddyhome.idea.vim.command.MappingMode
|
import com.maddyhome.idea.vim.command.MappingMode
|
||||||
import com.maddyhome.idea.vim.command.OperatorArguments
|
import com.maddyhome.idea.vim.command.OperatorArguments
|
||||||
import com.maddyhome.idea.vim.extension.ExtensionHandler
|
import com.maddyhome.idea.vim.extension.ExtensionHandler
|
||||||
@ -21,10 +20,8 @@ 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.helper.vimForEachCaret
|
import com.maddyhome.idea.vim.helper.vimForEachCaret
|
||||||
import com.maddyhome.idea.vim.key.MappingOwner
|
|
||||||
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 javax.swing.KeyStroke
|
|
||||||
|
|
||||||
internal class ParagraphMotion : VimExtension {
|
internal class ParagraphMotion : VimExtension {
|
||||||
override fun getName(): String = "vim-paragraph-motion"
|
override fun getName(): String = "vim-paragraph-motion"
|
||||||
@ -33,8 +30,8 @@ internal class ParagraphMotion : VimExtension {
|
|||||||
VimExtensionFacade.putExtensionHandlerMapping(MappingMode.NXO, injector.parser.parseKeys("<Plug>(ParagraphNextMotion)"), owner, ParagraphMotionHandler(1), false)
|
VimExtensionFacade.putExtensionHandlerMapping(MappingMode.NXO, injector.parser.parseKeys("<Plug>(ParagraphNextMotion)"), owner, ParagraphMotionHandler(1), false)
|
||||||
VimExtensionFacade.putExtensionHandlerMapping(MappingMode.NXO, injector.parser.parseKeys("<Plug>(ParagraphPrevMotion)"), owner, ParagraphMotionHandler(-1), false)
|
VimExtensionFacade.putExtensionHandlerMapping(MappingMode.NXO, injector.parser.parseKeys("<Plug>(ParagraphPrevMotion)"), owner, ParagraphMotionHandler(-1), false)
|
||||||
|
|
||||||
putKeyMappingIfMissingFromAndToKeys(MappingMode.NXO, injector.parser.parseKeys("}"), owner, injector.parser.parseKeys("<Plug>(ParagraphNextMotion)"), true)
|
putKeyMappingIfMissing(MappingMode.NXO, injector.parser.parseKeys("}"), owner, injector.parser.parseKeys("<Plug>(ParagraphNextMotion)"), true)
|
||||||
putKeyMappingIfMissingFromAndToKeys(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) : ExtensionHandler {
|
private class ParagraphMotionHandler(private val count: Int) : ExtensionHandler {
|
||||||
@ -48,21 +45,7 @@ internal class ParagraphMotion : VimExtension {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun moveCaretToNextParagraph(editor: VimEditor, caret: Caret, count: Int): Int? {
|
fun moveCaretToNextParagraph(editor: VimEditor, caret: Caret, count: Int): Int? {
|
||||||
return injector.searchHelper.findNextParagraph(editor, caret.vim, count, true)
|
return injector.searchHelper.findNextParagraph(editor, caret.vim, count, true)?.let(editor::getLineEndForOffset)
|
||||||
?.let { editor.normalizeOffset(it, true) }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// For VIM-3306
|
|
||||||
@Suppress("SameParameterValue")
|
|
||||||
private fun putKeyMappingIfMissingFromAndToKeys(
|
|
||||||
modes: Set<MappingMode>,
|
|
||||||
fromKeys: List<KeyStroke>,
|
|
||||||
pluginOwner: MappingOwner,
|
|
||||||
toKeys: List<KeyStroke>,
|
|
||||||
recursive: Boolean,
|
|
||||||
) {
|
|
||||||
val filteredModes = modes.filterNotTo(HashSet()) { VimPlugin.getKey().hasmapfrom(it, fromKeys) }
|
|
||||||
putKeyMappingIfMissing(filteredModes, fromKeys, pluginOwner, toKeys, recursive)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -14,19 +14,24 @@ import com.maddyhome.idea.vim.api.ExecutionContext
|
|||||||
import com.maddyhome.idea.vim.api.ImmutableVimCaret
|
import com.maddyhome.idea.vim.api.ImmutableVimCaret
|
||||||
import com.maddyhome.idea.vim.api.VimEditor
|
import com.maddyhome.idea.vim.api.VimEditor
|
||||||
import com.maddyhome.idea.vim.api.getLineEndOffset
|
import com.maddyhome.idea.vim.api.getLineEndOffset
|
||||||
import com.maddyhome.idea.vim.api.globalOptions
|
|
||||||
import com.maddyhome.idea.vim.api.injector
|
import com.maddyhome.idea.vim.api.injector
|
||||||
import com.maddyhome.idea.vim.command.MappingMode
|
import com.maddyhome.idea.vim.command.MappingMode
|
||||||
|
import com.maddyhome.idea.vim.state.mode.Mode
|
||||||
import com.maddyhome.idea.vim.command.OperatorArguments
|
import com.maddyhome.idea.vim.command.OperatorArguments
|
||||||
|
import com.maddyhome.idea.vim.state.mode.SelectionType
|
||||||
|
import com.maddyhome.idea.vim.state.mode.SelectionType.CHARACTER_WISE
|
||||||
|
import com.maddyhome.idea.vim.state.mode.isLine
|
||||||
|
import com.maddyhome.idea.vim.state.mode.selectionType
|
||||||
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.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.exportOperatorFunction
|
import com.maddyhome.idea.vim.extension.VimExtensionFacade.setOperatorFunction
|
||||||
import com.maddyhome.idea.vim.group.visual.VimSelection
|
import com.maddyhome.idea.vim.group.visual.VimSelection
|
||||||
import com.maddyhome.idea.vim.helper.exitVisualMode
|
import com.maddyhome.idea.vim.helper.exitVisualMode
|
||||||
|
import com.maddyhome.idea.vim.state.mode.mode
|
||||||
import com.maddyhome.idea.vim.helper.vimStateMachine
|
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
|
||||||
@ -34,10 +39,6 @@ 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 com.maddyhome.idea.vim.put.PutData
|
||||||
import com.maddyhome.idea.vim.state.mode.Mode
|
|
||||||
import com.maddyhome.idea.vim.state.mode.SelectionType
|
|
||||||
import com.maddyhome.idea.vim.state.mode.isLine
|
|
||||||
import com.maddyhome.idea.vim.state.mode.selectionType
|
|
||||||
import org.jetbrains.annotations.NonNls
|
import org.jetbrains.annotations.NonNls
|
||||||
|
|
||||||
internal class ReplaceWithRegister : VimExtension {
|
internal class ReplaceWithRegister : VimExtension {
|
||||||
@ -52,13 +53,11 @@ internal class ReplaceWithRegister : VimExtension {
|
|||||||
putKeyMappingIfMissing(MappingMode.N, injector.parser.parseKeys("gr"), owner, injector.parser.parseKeys(RWR_OPERATOR), true)
|
putKeyMappingIfMissing(MappingMode.N, injector.parser.parseKeys("gr"), owner, injector.parser.parseKeys(RWR_OPERATOR), true)
|
||||||
putKeyMappingIfMissing(MappingMode.N, injector.parser.parseKeys("grr"), owner, injector.parser.parseKeys(RWR_LINE), true)
|
putKeyMappingIfMissing(MappingMode.N, injector.parser.parseKeys("grr"), owner, injector.parser.parseKeys(RWR_LINE), true)
|
||||||
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)
|
||||||
|
|
||||||
VimExtensionFacade.exportOperatorFunction(OPERATOR_FUNC, Operator())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private class RwrVisual : ExtensionHandler {
|
private class RwrVisual : ExtensionHandler {
|
||||||
override fun execute(editor: VimEditor, context: ExecutionContext, operatorArguments: OperatorArguments) {
|
override fun execute(editor: VimEditor, context: ExecutionContext, operatorArguments: OperatorArguments) {
|
||||||
val typeInEditor = editor.mode.selectionType ?: SelectionType.CHARACTER_WISE
|
val typeInEditor = editor.mode.selectionType ?: CHARACTER_WISE
|
||||||
editor.sortedCarets().forEach { caret ->
|
editor.sortedCarets().forEach { caret ->
|
||||||
val selectionStart = caret.selectionStart
|
val selectionStart = caret.selectionStart
|
||||||
val selectionEnd = caret.selectionEnd
|
val selectionEnd = caret.selectionEnd
|
||||||
@ -74,7 +73,7 @@ internal class ReplaceWithRegister : VimExtension {
|
|||||||
override val isRepeatable: Boolean = true
|
override val isRepeatable: Boolean = true
|
||||||
|
|
||||||
override fun execute(editor: VimEditor, context: ExecutionContext, operatorArguments: OperatorArguments) {
|
override fun execute(editor: VimEditor, context: ExecutionContext, operatorArguments: OperatorArguments) {
|
||||||
injector.globalOptions().operatorfunc = OPERATOR_FUNC
|
setOperatorFunction(Operator())
|
||||||
executeNormalWithoutMapping(injector.parser.parseKeys("g@"), editor.ij)
|
executeNormalWithoutMapping(injector.parser.parseKeys("g@"), editor.ij)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -113,11 +112,11 @@ internal class ReplaceWithRegister : VimExtension {
|
|||||||
editor.primaryCaret() to VimSelection.create(
|
editor.primaryCaret() to VimSelection.create(
|
||||||
range.startOffset,
|
range.startOffset,
|
||||||
range.endOffset - 1,
|
range.endOffset - 1,
|
||||||
selectionType ?: SelectionType.CHARACTER_WISE,
|
selectionType ?: CHARACTER_WISE,
|
||||||
editor,
|
editor,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
selectionType ?: SelectionType.CHARACTER_WISE,
|
selectionType ?: CHARACTER_WISE,
|
||||||
)
|
)
|
||||||
// todo multicaret
|
// todo multicaret
|
||||||
doReplace(ijEditor, editor.primaryCaret(), visualSelection)
|
doReplace(ijEditor, editor.primaryCaret(), visualSelection)
|
||||||
@ -133,14 +132,16 @@ internal class ReplaceWithRegister : VimExtension {
|
|||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@NonNls private const val RWR_OPERATOR = "<Plug>ReplaceWithRegisterOperator"
|
@NonNls
|
||||||
@NonNls private const val RWR_LINE = "<Plug>ReplaceWithRegisterLine"
|
private const val RWR_OPERATOR = "<Plug>ReplaceWithRegisterOperator"
|
||||||
@NonNls private const val RWR_VISUAL = "<Plug>ReplaceWithRegisterVisual"
|
|
||||||
@NonNls private const val OPERATOR_FUNC = "ReplaceWithRegisterOperatorFunc"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun doReplace(editor: Editor, caret: ImmutableVimCaret, visualSelection: PutData.VisualSelection) {
|
@NonNls
|
||||||
|
private const val RWR_LINE = "<Plug>ReplaceWithRegisterLine"
|
||||||
|
|
||||||
|
@NonNls
|
||||||
|
private const val RWR_VISUAL = "<Plug>ReplaceWithRegisterVisual"
|
||||||
|
|
||||||
|
private fun doReplace(editor: Editor, caret: ImmutableVimCaret, visualSelection: PutData.VisualSelection) {
|
||||||
val registerGroup = injector.registerGroup
|
val registerGroup = injector.registerGroup
|
||||||
val lastRegisterChar = if (editor.caretModel.caretCount == 1) registerGroup.currentRegister else registerGroup.getCurrentRegisterForMulticaret()
|
val lastRegisterChar = if (editor.caretModel.caretCount == 1) registerGroup.currentRegister else registerGroup.getCurrentRegisterForMulticaret()
|
||||||
val savedRegister = caret.registerStorage.getRegister(lastRegisterChar) ?: return
|
val savedRegister = caret.registerStorage.getRegister(lastRegisterChar) ?: return
|
||||||
@ -164,18 +165,19 @@ private fun doReplace(editor: Editor, caret: ImmutableVimCaret, visualSelection:
|
|||||||
caretAfterInsertedText = false,
|
caretAfterInsertedText = false,
|
||||||
putToLine = -1,
|
putToLine = -1,
|
||||||
)
|
)
|
||||||
val vimEditor = editor.vim
|
|
||||||
ClipboardOptionHelper.IdeaputDisabler().use {
|
ClipboardOptionHelper.IdeaputDisabler().use {
|
||||||
VimPlugin.getPut().putText(
|
VimPlugin.getPut().putText(
|
||||||
vimEditor,
|
IjVimEditor(editor),
|
||||||
injector.executionContextManager.onEditor(editor.vim),
|
injector.executionContextManager.onEditor(editor.vim),
|
||||||
putData,
|
putData,
|
||||||
operatorArguments = OperatorArguments(
|
operatorArguments = OperatorArguments(
|
||||||
editor.vimStateMachine?.isOperatorPending(vimEditor.mode) ?: false,
|
editor.vimStateMachine?.isOperatorPending ?: false,
|
||||||
0,
|
0,
|
||||||
editor.vim.mode,
|
editor.vim.mode,
|
||||||
),
|
),
|
||||||
saveToRegister = false
|
saveToRegister = false
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@ -36,7 +36,6 @@ import com.maddyhome.idea.vim.helper.StrictMode
|
|||||||
import com.maddyhome.idea.vim.newapi.ij
|
import com.maddyhome.idea.vim.newapi.ij
|
||||||
import java.awt.Font
|
import java.awt.Font
|
||||||
import java.awt.event.KeyEvent
|
import java.awt.event.KeyEvent
|
||||||
import java.util.*
|
|
||||||
import javax.swing.Timer
|
import javax.swing.Timer
|
||||||
|
|
||||||
|
|
||||||
@ -49,20 +48,17 @@ internal class IdeaVimSneakExtension : VimExtension {
|
|||||||
|
|
||||||
override fun init() {
|
override fun init() {
|
||||||
val highlightHandler = HighlightHandler()
|
val highlightHandler = HighlightHandler()
|
||||||
mapToFunctionAndProvideKeys("s", SneakHandler(highlightHandler, Direction.FORWARD), MappingMode.NXO)
|
mapToFunctionAndProvideKeys("s", SneakHandler(highlightHandler, Direction.FORWARD))
|
||||||
|
mapToFunctionAndProvideKeys("S", SneakHandler(highlightHandler, Direction.BACKWARD))
|
||||||
// vim-sneak uses `Z` for visual mode because `S` conflict with vim-sneak plugin VIM-3330
|
|
||||||
mapToFunctionAndProvideKeys("S", SneakHandler(highlightHandler, Direction.BACKWARD), MappingMode.NO)
|
|
||||||
mapToFunctionAndProvideKeys("Z", SneakHandler(highlightHandler, Direction.BACKWARD), MappingMode.X)
|
|
||||||
|
|
||||||
// workaround to support ; and , commands
|
// workaround to support ; and , commands
|
||||||
mapToFunctionAndProvideKeys("f", SneakMemoryHandler("f"), MappingMode.NXO)
|
mapToFunctionAndProvideKeys("f", SneakMemoryHandler("f"))
|
||||||
mapToFunctionAndProvideKeys("F", SneakMemoryHandler("F"), MappingMode.NXO)
|
mapToFunctionAndProvideKeys("F", SneakMemoryHandler("F"))
|
||||||
mapToFunctionAndProvideKeys("t", SneakMemoryHandler("t"), MappingMode.NXO)
|
mapToFunctionAndProvideKeys("t", SneakMemoryHandler("t"))
|
||||||
mapToFunctionAndProvideKeys("T", SneakMemoryHandler("T"), MappingMode.NXO)
|
mapToFunctionAndProvideKeys("T", SneakMemoryHandler("T"))
|
||||||
|
|
||||||
mapToFunctionAndProvideKeys(";", SneakRepeatHandler(highlightHandler, RepeatDirection.IDENTICAL), MappingMode.NXO)
|
mapToFunctionAndProvideKeys(";", SneakRepeatHandler(highlightHandler, RepeatDirection.IDENTICAL))
|
||||||
mapToFunctionAndProvideKeys(",", SneakRepeatHandler(highlightHandler, RepeatDirection.REVERSE), MappingMode.NXO)
|
mapToFunctionAndProvideKeys(",", SneakRepeatHandler(highlightHandler, RepeatDirection.REVERSE))
|
||||||
}
|
}
|
||||||
|
|
||||||
private class SneakHandler(
|
private class SneakHandler(
|
||||||
@ -277,18 +273,16 @@ internal class IdeaVimSneakExtension : VimExtension {
|
|||||||
* Map some <Plug>(keys) command to given handler
|
* Map some <Plug>(keys) command to given handler
|
||||||
* and create mapping to <Plug>(prefix)[keys]
|
* and create mapping to <Plug>(prefix)[keys]
|
||||||
*/
|
*/
|
||||||
private fun VimExtension.mapToFunctionAndProvideKeys(
|
private fun VimExtension.mapToFunctionAndProvideKeys(keys: String, handler: ExtensionHandler) {
|
||||||
keys: String, handler: ExtensionHandler, mappingModes: EnumSet<MappingMode>
|
|
||||||
) {
|
|
||||||
VimExtensionFacade.putExtensionHandlerMapping(
|
VimExtensionFacade.putExtensionHandlerMapping(
|
||||||
mappingModes,
|
MappingMode.NXO,
|
||||||
injector.parser.parseKeys(command(keys)),
|
injector.parser.parseKeys(command(keys)),
|
||||||
owner,
|
owner,
|
||||||
handler,
|
handler,
|
||||||
false
|
false
|
||||||
)
|
)
|
||||||
VimExtensionFacade.putExtensionHandlerMapping(
|
VimExtensionFacade.putExtensionHandlerMapping(
|
||||||
mappingModes,
|
MappingMode.NXO,
|
||||||
injector.parser.parseKeys(commandFromOriginalPlugin(keys)),
|
injector.parser.parseKeys(commandFromOriginalPlugin(keys)),
|
||||||
owner,
|
owner,
|
||||||
handler,
|
handler,
|
||||||
@ -300,17 +294,17 @@ private fun VimExtension.mapToFunctionAndProvideKeys(
|
|||||||
// - The shortcut should not be registered if any of these mappings is overridden in .ideavimrc
|
// - The shortcut should not be registered if any of these mappings is overridden in .ideavimrc
|
||||||
// - The shortcut should not be registered if some other shortcut for this key exists
|
// - The shortcut should not be registered if some other shortcut for this key exists
|
||||||
val fromKeys = injector.parser.parseKeys(keys)
|
val fromKeys = injector.parser.parseKeys(keys)
|
||||||
val filteredModes = mappingModes.filterNotTo(HashSet()) {
|
val filteredModes = MappingMode.NXO.filterNotTo(HashSet()) {
|
||||||
VimPlugin.getKey().hasmapto(it, injector.parser.parseKeys(command(keys)))
|
VimPlugin.getKey().hasmapto(it, injector.parser.parseKeys(command(keys)))
|
||||||
}
|
}
|
||||||
val filteredModes2 = mappingModes.filterNotTo(HashSet()) {
|
val filteredModes2 = MappingMode.NXO.filterNotTo(HashSet()) {
|
||||||
VimPlugin.getKey().hasmapto(it, injector.parser.parseKeys(commandFromOriginalPlugin(keys)))
|
VimPlugin.getKey().hasmapto(it, injector.parser.parseKeys(commandFromOriginalPlugin(keys)))
|
||||||
}
|
}
|
||||||
val filteredFromModes = mappingModes.filterNotTo(HashSet()) {
|
val filteredFromModes = MappingMode.NXO.filterNotTo(HashSet()) {
|
||||||
injector.keyGroup.hasmapfrom(it, fromKeys)
|
injector.keyGroup.hasmapfrom(it, fromKeys)
|
||||||
}
|
}
|
||||||
|
|
||||||
val doubleFiltered = mappingModes
|
val doubleFiltered = MappingMode.NXO
|
||||||
.filter { it in filteredModes2 && it in filteredModes && it in filteredFromModes }
|
.filter { it in filteredModes2 && it in filteredModes && it in filteredFromModes }
|
||||||
.toSet()
|
.toSet()
|
||||||
putKeyMapping(doubleFiltered, fromKeys, owner, injector.parser.parseKeys(command(keys)), true)
|
putKeyMapping(doubleFiltered, fromKeys, owner, injector.parser.parseKeys(command(keys)), true)
|
||||||
|
@ -17,7 +17,6 @@ import com.maddyhome.idea.vim.api.VimChangeGroup
|
|||||||
import com.maddyhome.idea.vim.api.VimEditor
|
import com.maddyhome.idea.vim.api.VimEditor
|
||||||
import com.maddyhome.idea.vim.api.endsWithNewLine
|
import com.maddyhome.idea.vim.api.endsWithNewLine
|
||||||
import com.maddyhome.idea.vim.api.getLeadingCharacterOffset
|
import com.maddyhome.idea.vim.api.getLeadingCharacterOffset
|
||||||
import com.maddyhome.idea.vim.api.globalOptions
|
|
||||||
import com.maddyhome.idea.vim.api.injector
|
import com.maddyhome.idea.vim.api.injector
|
||||||
import com.maddyhome.idea.vim.api.setChangeMarks
|
import com.maddyhome.idea.vim.api.setChangeMarks
|
||||||
import com.maddyhome.idea.vim.command.MappingMode
|
import com.maddyhome.idea.vim.command.MappingMode
|
||||||
@ -25,15 +24,14 @@ import com.maddyhome.idea.vim.command.OperatorArguments
|
|||||||
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.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.executeNormalWithoutMapping
|
import com.maddyhome.idea.vim.extension.VimExtensionFacade.executeNormalWithoutMapping
|
||||||
import com.maddyhome.idea.vim.extension.VimExtensionFacade.getRegisterForCaret
|
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.setRegisterForCaret
|
import com.maddyhome.idea.vim.extension.VimExtensionFacade.setRegisterForCaret
|
||||||
import com.maddyhome.idea.vim.extension.exportOperatorFunction
|
|
||||||
import com.maddyhome.idea.vim.helper.runWithEveryCaretAndRestore
|
import com.maddyhome.idea.vim.helper.runWithEveryCaretAndRestore
|
||||||
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
|
||||||
@ -80,15 +78,13 @@ internal class VimSurroundExtension : VimExtension {
|
|||||||
putKeyMappingIfMissing(MappingMode.N, injector.parser.parseKeys("ds"), owner, injector.parser.parseKeys("<Plug>DSurround"), true)
|
putKeyMappingIfMissing(MappingMode.N, injector.parser.parseKeys("ds"), owner, injector.parser.parseKeys("<Plug>DSurround"), true)
|
||||||
putKeyMappingIfMissing(MappingMode.XO, injector.parser.parseKeys("S"), owner, injector.parser.parseKeys("<Plug>VSurround"), true)
|
putKeyMappingIfMissing(MappingMode.XO, injector.parser.parseKeys("S"), owner, injector.parser.parseKeys("<Plug>VSurround"), true)
|
||||||
}
|
}
|
||||||
|
|
||||||
VimExtensionFacade.exportOperatorFunction(OPERATOR_FUNC, Operator(supportsMultipleCursors = false, count = 1)) // TODO
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private class YSurroundHandler : ExtensionHandler {
|
private class YSurroundHandler : ExtensionHandler {
|
||||||
override val isRepeatable = true
|
override val isRepeatable = true
|
||||||
|
|
||||||
override fun execute(editor: VimEditor, context: ExecutionContext, operatorArguments: OperatorArguments) {
|
override fun execute(editor: VimEditor, context: ExecutionContext, operatorArguments: OperatorArguments) {
|
||||||
injector.globalOptions().operatorfunc = OPERATOR_FUNC
|
setOperatorFunction(Operator(supportsMultipleCursors = false, count = 1)) // TODO
|
||||||
executeNormalWithoutMapping(injector.parser.parseKeys("g@"), editor.ij)
|
executeNormalWithoutMapping(injector.parser.parseKeys("g@"), editor.ij)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -319,9 +315,7 @@ private val LOG = logger<VimSurroundExtension>()
|
|||||||
|
|
||||||
private const val REGISTER = '"'
|
private const val REGISTER = '"'
|
||||||
|
|
||||||
private const val OPERATOR_FUNC = "SurroundOperatorFunc"
|
private val tagNameAndAttributesCapturePattern = "(\\S+)([^>]*)>".toPattern()
|
||||||
|
|
||||||
private val tagNameAndAttributesCapturePattern = "(\\S+)([^>]*)>".toPattern()
|
|
||||||
|
|
||||||
private val SURROUND_PAIRS = mapOf(
|
private val SURROUND_PAIRS = mapOf(
|
||||||
'b' to ("(" to ")"),
|
'b' to ("(" to ")"),
|
||||||
|
@ -138,7 +138,7 @@ public class VimTextObjEntireExtension implements VimExtension {
|
|||||||
|
|
||||||
final EntireTextObjectHandler textObjectHandler = new EntireTextObjectHandler(ignoreLeadingAndTrailing);
|
final EntireTextObjectHandler textObjectHandler = new EntireTextObjectHandler(ignoreLeadingAndTrailing);
|
||||||
//noinspection DuplicatedCode
|
//noinspection DuplicatedCode
|
||||||
if (!vimStateMachine.isOperatorPending(editor.getMode())) {
|
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);
|
final TextRange range = textObjectHandler.getRange(editor, new IjVimCaret(caret), context, count, 0);
|
||||||
if (range != null) {
|
if (range != null) {
|
||||||
|
@ -267,7 +267,7 @@ public class VimIndentObject implements VimExtension {
|
|||||||
|
|
||||||
final IndentObjectHandler textObjectHandler = new IndentObjectHandler(includeAbove, includeBelow);
|
final IndentObjectHandler textObjectHandler = new IndentObjectHandler(includeAbove, includeBelow);
|
||||||
|
|
||||||
if (!vimStateMachine.isOperatorPending(editor.getMode())) {
|
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);
|
final TextRange range = textObjectHandler.getRange(vimEditor, new IjVimCaret(caret), context, count, 0);
|
||||||
if (range != null) {
|
if (range != null) {
|
||||||
|
@ -68,11 +68,10 @@ import com.maddyhome.idea.vim.newapi.IjEditorExecutionContext
|
|||||||
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.regexp.VimRegex
|
|
||||||
import com.maddyhome.idea.vim.regexp.match.VimMatchResult
|
|
||||||
import com.maddyhome.idea.vim.state.mode.Mode
|
import com.maddyhome.idea.vim.state.mode.Mode
|
||||||
import com.maddyhome.idea.vim.state.mode.Mode.VISUAL
|
import com.maddyhome.idea.vim.state.mode.Mode.VISUAL
|
||||||
import com.maddyhome.idea.vim.state.mode.SelectionType
|
import com.maddyhome.idea.vim.state.mode.SelectionType
|
||||||
|
import com.maddyhome.idea.vim.state.mode.mode
|
||||||
import com.maddyhome.idea.vim.vimscript.model.commands.SortOption
|
import com.maddyhome.idea.vim.vimscript.model.commands.SortOption
|
||||||
import org.jetbrains.annotations.TestOnly
|
import org.jetbrains.annotations.TestOnly
|
||||||
import java.math.BigInteger
|
import java.math.BigInteger
|
||||||
@ -574,62 +573,48 @@ public class ChangeGroup : VimChangeGroupBase() {
|
|||||||
}
|
}
|
||||||
val startOffset = editor.getLineStartOffset(startLine)
|
val startOffset = editor.getLineStartOffset(startLine)
|
||||||
val endOffset = editor.getLineEndOffset(endLine)
|
val endOffset = editor.getLineEndOffset(endLine)
|
||||||
|
return sortTextRange(editor, caret, startOffset, endOffset, lineComparator, sortOptions)
|
||||||
val selectedText = (editor as IjVimEditor).editor.document.getText(TextRangeInterval(startOffset, endOffset))
|
|
||||||
val lines = selectedText.split("\n")
|
|
||||||
val modifiedLines = sortOptions.pattern?.let {
|
|
||||||
if (sortOptions.sortOnPattern) {
|
|
||||||
extractPatternFromLines(editor, lines, startLine, it)
|
|
||||||
} else {
|
|
||||||
deletePatternFromLines(editor, lines, startLine, it)
|
|
||||||
}
|
}
|
||||||
} ?: lines
|
|
||||||
val sortedLines = lines.zip(modifiedLines)
|
|
||||||
.sortedWith { l1, l2 -> lineComparator.compare(l1.second, l2.second) }
|
|
||||||
.map {it.first}
|
|
||||||
.toMutableList()
|
|
||||||
|
|
||||||
if (sortOptions.unique) {
|
/**
|
||||||
val iterator = sortedLines.iterator()
|
* Sorts a text range with a comparator. Returns true if a replace was performed, false otherwise.
|
||||||
|
*
|
||||||
|
* @param editor The editor to replace text in
|
||||||
|
* @param start The starting position for the sort
|
||||||
|
* @param end The ending position for the sort
|
||||||
|
* @param lineComparator The comparator to use to sort
|
||||||
|
* @param sortOption The option to sort the range
|
||||||
|
* @return true if able to sort the text, false if not
|
||||||
|
*/
|
||||||
|
private fun sortTextRange(
|
||||||
|
editor: VimEditor,
|
||||||
|
caret: VimCaret,
|
||||||
|
start: Int,
|
||||||
|
end: Int,
|
||||||
|
lineComparator: Comparator<String>,
|
||||||
|
sortOption: SortOption,
|
||||||
|
): Boolean {
|
||||||
|
val selectedText = (editor as IjVimEditor).editor.document.getText(TextRangeInterval(start, end))
|
||||||
|
val lines: MutableList<String> = selectedText.split("\n").sortedWith(lineComparator).toMutableList()
|
||||||
|
if (sortOption.unique) {
|
||||||
|
val iterator = lines.iterator()
|
||||||
var previous: String? = null
|
var previous: String? = null
|
||||||
while (iterator.hasNext()) {
|
while (iterator.hasNext()) {
|
||||||
val current = iterator.next()
|
val current = iterator.next()
|
||||||
if (current == previous || sortOptions.ignoreCase && current.equals(previous, ignoreCase = true)) {
|
if (current == previous || sortOption.ignoreCase && current.equals(previous, ignoreCase = true)) {
|
||||||
iterator.remove()
|
iterator.remove()
|
||||||
} else {
|
} else {
|
||||||
previous = current
|
previous = current
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (sortedLines.isEmpty()) {
|
if (lines.size < 1) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
replaceText(editor, caret, startOffset, endOffset, StringUtil.join(sortedLines, "\n"))
|
replaceText(editor, caret, start, end, StringUtil.join(lines, "\n"))
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun extractPatternFromLines(editor: VimEditor, lines: List<String>, startLine: Int, pattern: String): List<String> {
|
|
||||||
val regex = VimRegex(pattern)
|
|
||||||
return lines.mapIndexed { i: Int, line: String ->
|
|
||||||
val result = regex.findInLine(editor, startLine + i, 0)
|
|
||||||
when (result) {
|
|
||||||
is VimMatchResult.Success -> result.value
|
|
||||||
is VimMatchResult.Failure -> line
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun deletePatternFromLines(editor: VimEditor, lines: List<String>, startLine: Int, pattern: String): List<String> {
|
|
||||||
val regex = VimRegex(pattern)
|
|
||||||
return lines.mapIndexed { i: Int, line: String ->
|
|
||||||
val result = regex.findInLine(editor, startLine + i, 0)
|
|
||||||
when (result) {
|
|
||||||
is VimMatchResult.Success -> line.substring(result.value.length, line.length)
|
|
||||||
is VimMatchResult.Failure -> line
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Perform increment and decrement for numbers in visual mode
|
* Perform increment and decrement for numbers in visual mode
|
||||||
*
|
*
|
||||||
|
@ -8,11 +8,9 @@
|
|||||||
|
|
||||||
package com.maddyhome.idea.vim.group
|
package com.maddyhome.idea.vim.group
|
||||||
|
|
||||||
import com.intellij.openapi.components.Service
|
|
||||||
import com.maddyhome.idea.vim.api.VimCommandGroupBase
|
import com.maddyhome.idea.vim.api.VimCommandGroupBase
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Elliot Courant
|
* @author Elliot Courant
|
||||||
*/
|
*/
|
||||||
@Service
|
|
||||||
internal class CommandGroup : VimCommandGroupBase()
|
internal class CommandGroup : VimCommandGroupBase()
|
||||||
|
@ -11,9 +11,6 @@ package com.maddyhome.idea.vim.group;
|
|||||||
import com.intellij.execution.impl.ConsoleViewImpl;
|
import com.intellij.execution.impl.ConsoleViewImpl;
|
||||||
import com.intellij.find.EditorSearchSession;
|
import com.intellij.find.EditorSearchSession;
|
||||||
import com.intellij.openapi.application.ApplicationManager;
|
import com.intellij.openapi.application.ApplicationManager;
|
||||||
import com.intellij.openapi.client.ClientAppSession;
|
|
||||||
import com.intellij.openapi.client.ClientKind;
|
|
||||||
import com.intellij.openapi.client.ClientSessionsManager;
|
|
||||||
import com.intellij.openapi.components.PersistentStateComponent;
|
import com.intellij.openapi.components.PersistentStateComponent;
|
||||||
import com.intellij.openapi.components.State;
|
import com.intellij.openapi.components.State;
|
||||||
import com.intellij.openapi.components.Storage;
|
import com.intellij.openapi.components.Storage;
|
||||||
@ -25,10 +22,7 @@ import com.intellij.openapi.project.Project;
|
|||||||
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.api.*;
|
import com.maddyhome.idea.vim.api.*;
|
||||||
import com.maddyhome.idea.vim.helper.CaretVisualAttributesHelperKt;
|
import com.maddyhome.idea.vim.helper.*;
|
||||||
import com.maddyhome.idea.vim.helper.CommandStateHelper;
|
|
||||||
import com.maddyhome.idea.vim.helper.EditorHelper;
|
|
||||||
import com.maddyhome.idea.vim.helper.UserDataManager;
|
|
||||||
import com.maddyhome.idea.vim.newapi.IjVimDocument;
|
import com.maddyhome.idea.vim.newapi.IjVimDocument;
|
||||||
import com.maddyhome.idea.vim.newapi.IjVimEditor;
|
import com.maddyhome.idea.vim.newapi.IjVimEditor;
|
||||||
import com.maddyhome.idea.vim.options.EffectiveOptionValueChangeListener;
|
import com.maddyhome.idea.vim.options.EffectiveOptionValueChangeListener;
|
||||||
@ -40,10 +34,10 @@ import org.jetbrains.annotations.Nullable;
|
|||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.Stream;
|
|
||||||
|
|
||||||
import static com.maddyhome.idea.vim.api.VimInjectorKt.injector;
|
import static com.maddyhome.idea.vim.api.VimInjectorKt.injector;
|
||||||
import static com.maddyhome.idea.vim.api.VimInjectorKt.options;
|
import static com.maddyhome.idea.vim.api.VimInjectorKt.options;
|
||||||
|
import static com.maddyhome.idea.vim.helper.CaretVisualAttributesHelperKt.updateCaretsVisualAttributes;
|
||||||
import static com.maddyhome.idea.vim.newapi.IjVimInjectorKt.ijOptions;
|
import static com.maddyhome.idea.vim.newapi.IjVimInjectorKt.ijOptions;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -210,8 +204,7 @@ public class EditorGroup implements PersistentStateComponent<Element>, VimEditor
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void editorCreated(@NotNull Editor editor) {
|
public void editorCreated(@NotNull Editor editor) {
|
||||||
UserDataManager.setVimInitialised(editor, true);
|
DocumentManager.INSTANCE.addListeners(editor.getDocument());
|
||||||
|
|
||||||
VimPlugin.getKey().registerRequiredShortcutKeys(new IjVimEditor(editor));
|
VimPlugin.getKey().registerRequiredShortcutKeys(new IjVimEditor(editor));
|
||||||
|
|
||||||
initLineNumbers(editor);
|
initLineNumbers(editor);
|
||||||
@ -253,13 +246,14 @@ public class EditorGroup implements PersistentStateComponent<Element>, VimEditor
|
|||||||
switchToInsertMode.run();
|
switchToInsertMode.run();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
updateCaretsVisualAttributes(new IjVimEditor(editor));
|
updateCaretsVisualAttributes(editor);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void editorDeinit(@NotNull Editor editor, boolean isReleased) {
|
public void editorDeinit(@NotNull Editor editor, boolean isReleased) {
|
||||||
deinitLineNumbers(editor, isReleased);
|
deinitLineNumbers(editor, isReleased);
|
||||||
UserDataManager.unInitializeEditor(editor);
|
UserDataManager.unInitializeEditor(editor);
|
||||||
VimPlugin.getKey().unregisterShortcutKeys(new IjVimEditor(editor));
|
VimPlugin.getKey().unregisterShortcutKeys(new IjVimEditor(editor));
|
||||||
|
DocumentManager.INSTANCE.removeListeners(editor.getDocument());
|
||||||
CaretVisualAttributesHelperKt.removeCaretsVisualAttributes(editor);
|
CaretVisualAttributesHelperKt.removeCaretsVisualAttributes(editor);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -290,18 +284,6 @@ public class EditorGroup implements PersistentStateComponent<Element>, VimEditor
|
|||||||
notifyIdeaJoin(((IjVimEditor) editor).getEditor().getProject(), editor);
|
notifyIdeaJoin(((IjVimEditor) editor).getEditor().getProject(), editor);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void updateCaretsVisualAttributes(@NotNull VimEditor editor) {
|
|
||||||
Editor ijEditor = ((IjVimEditor) editor).getEditor();
|
|
||||||
CaretVisualAttributesHelperKt.updateCaretsVisualAttributes(ijEditor);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void updateCaretsVisualPosition(@NotNull VimEditor editor) {
|
|
||||||
Editor ijEditor = ((IjVimEditor) editor).getEditor();
|
|
||||||
CaretVisualAttributesHelperKt.updateCaretsVisualAttributes(ijEditor);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class NumberChangeListener implements EffectiveOptionValueChangeListener {
|
public static class NumberChangeListener implements EffectiveOptionValueChangeListener {
|
||||||
public static NumberChangeListener INSTANCE = new NumberChangeListener();
|
public static NumberChangeListener INSTANCE = new NumberChangeListener();
|
||||||
|
|
||||||
@ -342,45 +324,20 @@ public class EditorGroup implements PersistentStateComponent<Element>, VimEditor
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public @NotNull Collection<VimEditor> getEditorsRaw() {
|
public Collection<VimEditor> localEditors() {
|
||||||
return getLocalEditors()
|
return HelperKt.localEditors().stream()
|
||||||
.map(IjVimEditor::new)
|
.map(IjVimEditor::new)
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public Collection<VimEditor> getEditors() {
|
public Collection<VimEditor> localEditors(@NotNull VimDocument buffer) {
|
||||||
return getLocalEditors()
|
|
||||||
.filter(UserDataManager::getVimInitialised)
|
|
||||||
.map(IjVimEditor::new)
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
@Override
|
|
||||||
public Collection<VimEditor> getEditors(@NotNull VimDocument buffer) {
|
|
||||||
final Document document = ((IjVimDocument)buffer).getDocument();
|
final Document document = ((IjVimDocument)buffer).getDocument();
|
||||||
return getLocalEditors()
|
return HelperKt.localEditors(document).stream()
|
||||||
.filter(editor -> UserDataManager.getVimInitialised(editor) && editor.getDocument().equals(document))
|
|
||||||
.map(IjVimEditor::new)
|
.map(IjVimEditor::new)
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
private Stream<Editor> getLocalEditors() {
|
|
||||||
// Always fetch local editors. If we're hosting a Code With Me session, any connected guests will create hidden
|
|
||||||
// editors to handle syntax highlighting, completion requests, etc. We need to make sure that IdeaVim only makes
|
|
||||||
// changes (e.g. adding search highlights) to local editors, so things don't incorrectly flow through to any Clients.
|
|
||||||
// In non-CWM scenarios, or if IdeaVim is installed on the Client, there are only ever local editors, so this will
|
|
||||||
// also work there. In Gateway remote development scenarios, IdeaVim should not be installed on the host, only the
|
|
||||||
// Client, so all should work there too.
|
|
||||||
// Note that most IdeaVim operations are in response to interactive keystrokes, which would mean that
|
|
||||||
// ClientEditorManager.getCurrentInstance would return local editors. However, some operations are in response to
|
|
||||||
// events such as document change (to update search highlights) and these can come from CWM guests, and we'd get the
|
|
||||||
// remote editors.
|
|
||||||
// This invocation will always get local editors, regardless of current context.
|
|
||||||
final ClientAppSession localSession = ClientSessionsManager.getAppSessions(ClientKind.LOCAL).get(0);
|
|
||||||
return localSession.getService(ClientEditorManager.class).editors();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -30,6 +30,8 @@ import com.intellij.psi.search.GlobalSearchScope;
|
|||||||
import com.intellij.psi.search.ProjectScope;
|
import com.intellij.psi.search.ProjectScope;
|
||||||
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.state.mode.Mode;
|
||||||
|
import com.maddyhome.idea.vim.state.VimStateMachine;
|
||||||
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;
|
||||||
@ -38,8 +40,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.IjEditorExecutionContext;
|
import com.maddyhome.idea.vim.newapi.IjEditorExecutionContext;
|
||||||
import com.maddyhome.idea.vim.newapi.IjVimEditor;
|
import com.maddyhome.idea.vim.newapi.IjVimEditor;
|
||||||
import com.maddyhome.idea.vim.state.VimStateMachine;
|
|
||||||
import com.maddyhome.idea.vim.state.mode.Mode;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
@ -438,11 +438,14 @@ public class FileGroup extends VimFileBase {
|
|||||||
private static final @NotNull Logger logger = Logger.getInstance(FileGroup.class.getName());
|
private static final @NotNull Logger logger = Logger.getInstance(FileGroup.class.getName());
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Respond to editor tab selection and remember the last used tab
|
* This method listens for editor tab changes so any insert/replace modes that need to be reset can be.
|
||||||
*/
|
*/
|
||||||
public static void fileEditorManagerSelectionChangedCallback(@NotNull FileEditorManagerEvent event) {
|
public static void fileEditorManagerSelectionChangedCallback(@NotNull FileEditorManagerEvent event) {
|
||||||
|
// The user has changed the editor they are working with - exit insert/replace mode, and complete any
|
||||||
|
// appropriate repeat
|
||||||
if (event.getOldFile() != null) {
|
if (event.getOldFile() != null) {
|
||||||
LastTabService.getInstance(event.getManager().getProject()).setLastTab(event.getOldFile());
|
LastTabService.getInstance(event.getManager().getProject()).setLastTab(event.getOldFile());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,6 +20,7 @@ import com.maddyhome.idea.vim.options.OptionAccessScope
|
|||||||
*/
|
*/
|
||||||
@Suppress("SpellCheckingInspection")
|
@Suppress("SpellCheckingInspection")
|
||||||
public open class GlobalIjOptions(scope: OptionAccessScope) : OptionsPropertiesBase(scope) {
|
public open class GlobalIjOptions(scope: OptionAccessScope) : OptionsPropertiesBase(scope) {
|
||||||
|
public var closenotebooks: Boolean by optionProperty(IjOptions.closenotebooks)
|
||||||
public var ide: String by optionProperty(IjOptions.ide)
|
public var ide: String by optionProperty(IjOptions.ide)
|
||||||
public var ideamarks: Boolean by optionProperty(IjOptions.ideamarks)
|
public var ideamarks: Boolean by optionProperty(IjOptions.ideamarks)
|
||||||
public var ideastatusicon: String by optionProperty(IjOptions.ideastatusicon)
|
public var ideastatusicon: String by optionProperty(IjOptions.ideastatusicon)
|
||||||
@ -28,15 +29,15 @@ public open class GlobalIjOptions(scope: OptionAccessScope) : OptionsPropertiesB
|
|||||||
public val lookupkeys: StringListOptionValue by optionProperty(IjOptions.lookupkeys)
|
public val lookupkeys: StringListOptionValue by optionProperty(IjOptions.lookupkeys)
|
||||||
public var trackactionids: Boolean by optionProperty(IjOptions.trackactionids)
|
public var trackactionids: Boolean by optionProperty(IjOptions.trackactionids)
|
||||||
public var visualdelay: Int by optionProperty(IjOptions.visualdelay)
|
public var visualdelay: Int by optionProperty(IjOptions.visualdelay)
|
||||||
|
public var showmodewidget: Boolean by optionProperty(IjOptions.showmodewidget)
|
||||||
|
|
||||||
// Temporary options to control work-in-progress behaviour
|
// Temporary options to control work-in-progress behaviour
|
||||||
public var closenotebooks: Boolean by optionProperty(IjOptions.closenotebooks)
|
|
||||||
public var commandOrMotionAnnotation: Boolean by optionProperty(IjOptions.commandOrMotionAnnotation)
|
|
||||||
public var exCommandAnnotation: Boolean by optionProperty(IjOptions.exCommandAnnotation)
|
|
||||||
public var oldundo: Boolean by optionProperty(IjOptions.oldundo)
|
public var oldundo: Boolean by optionProperty(IjOptions.oldundo)
|
||||||
public var unifyjumps: Boolean by optionProperty(IjOptions.unifyjumps)
|
public var unifyjumps: Boolean by optionProperty(IjOptions.unifyjumps)
|
||||||
public var useNewRegex: Boolean by optionProperty(IjOptions.useNewRegex)
|
public var exCommandAnnotation: Boolean by optionProperty(IjOptions.exCommandAnnotation)
|
||||||
public var vimscriptFunctionAnnotation: Boolean by optionProperty(IjOptions.vimscriptFunctionAnnotation)
|
public var vimscriptFunctionAnnotation: Boolean by optionProperty(IjOptions.vimscriptFunctionAnnotation)
|
||||||
|
public var commandOrMotionAnnotation: Boolean by optionProperty(IjOptions.commandOrMotionAnnotation)
|
||||||
|
public var useNewRegex: Boolean by optionProperty(IjOptions.useNewRegex)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -33,6 +33,8 @@ public object IjOptions {
|
|||||||
Options.overrideDefaultValue(Options.clipboard, VimString("ideaput,autoselect,exclude:cons\\|linux"))
|
Options.overrideDefaultValue(Options.clipboard, VimString("ideaput,autoselect,exclude:cons\\|linux"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public val closenotebooks: ToggleOption = addOption(ToggleOption("closenotebooks", GLOBAL, "closenotebooks", true))
|
||||||
|
public val exCommandAnnotation: ToggleOption = addOption(ToggleOption("excommandannotation", GLOBAL, "excommandannotation", true))
|
||||||
public val ide: StringOption = addOption(
|
public val ide: StringOption = addOption(
|
||||||
StringOption("ide", GLOBAL, "ide", ApplicationNamesInfo.getInstance().fullProductNameWithEdition)
|
StringOption("ide", GLOBAL, "ide", ApplicationNamesInfo.getInstance().fullProductNameWithEdition)
|
||||||
)
|
)
|
||||||
@ -79,16 +81,13 @@ public object IjOptions {
|
|||||||
"<Tab>,<Down>,<Up>,<Enter>,<Left>,<Right>,<C-Down>,<C-Up>,<PageUp>,<PageDown>,<C-J>,<C-Q>")
|
"<Tab>,<Down>,<Up>,<Enter>,<Left>,<Right>,<C-Down>,<C-Up>,<PageUp>,<PageDown>,<C-J>,<C-Q>")
|
||||||
)
|
)
|
||||||
public val trackactionids: ToggleOption = addOption(ToggleOption("trackactionids", GLOBAL, "tai", false))
|
public val trackactionids: ToggleOption = addOption(ToggleOption("trackactionids", GLOBAL, "tai", false))
|
||||||
|
public val unifyjumps: ToggleOption = addOption(ToggleOption("unifyjumps", GLOBAL, "unifyjumps", true))
|
||||||
public val visualdelay: UnsignedNumberOption = addOption(UnsignedNumberOption("visualdelay", GLOBAL, "visualdelay", 100))
|
public val visualdelay: UnsignedNumberOption = addOption(UnsignedNumberOption("visualdelay", GLOBAL, "visualdelay", 100))
|
||||||
|
public val oldundo: ToggleOption = addOption(ToggleOption("oldundo", GLOBAL, "oldundo", true, isTemporary = true))
|
||||||
// Temporary feature flags during development, not really intended for external use
|
public val vimscriptFunctionAnnotation: ToggleOption = addOption(ToggleOption("vimscriptfunctionannotation", GLOBAL, "vimscriptfunctionannotation", true, isTemporary = true))
|
||||||
public val closenotebooks: ToggleOption = addOption(ToggleOption("closenotebooks", GLOBAL, "closenotebooks", true, isHidden = true))
|
public val commandOrMotionAnnotation: ToggleOption = addOption(ToggleOption("commandormotionannotation", GLOBAL, "commandormotionannotation", true, isTemporary = true))
|
||||||
public val commandOrMotionAnnotation: ToggleOption = addOption(ToggleOption("commandormotionannotation", GLOBAL, "commandormotionannotation", true, isHidden = true))
|
public val showmodewidget: ToggleOption = addOption(ToggleOption("showmodewidget", GLOBAL, "showmodewidget", false, isTemporary = true))
|
||||||
public val exCommandAnnotation: ToggleOption = addOption(ToggleOption("excommandannotation", GLOBAL, "excommandannotation", true, isHidden = true))
|
public val useNewRegex: ToggleOption = addOption(ToggleOption("usenewregex", GLOBAL, "usenewregex", true, isTemporary = true))
|
||||||
public val oldundo: ToggleOption = addOption(ToggleOption("oldundo", GLOBAL, "oldundo", true, isHidden = true))
|
|
||||||
public val unifyjumps: ToggleOption = addOption(ToggleOption("unifyjumps", GLOBAL, "unifyjumps", true, isHidden = true))
|
|
||||||
public val useNewRegex: ToggleOption = addOption(ToggleOption("usenewregex", GLOBAL, "usenewregex", true, isHidden = true))
|
|
||||||
public val vimscriptFunctionAnnotation: ToggleOption = addOption(ToggleOption("vimscriptfunctionannotation", GLOBAL, "vimscriptfunctionannotation", true, isHidden = true))
|
|
||||||
|
|
||||||
// This needs to be Option<out VimDataType> so that it can work with derived option types, such as NumberOption, which
|
// This needs to be Option<out VimDataType> so that it can work with derived option types, such as NumberOption, which
|
||||||
// derives from Option<VimInt>
|
// derives from Option<VimInt>
|
||||||
|
@ -15,38 +15,38 @@ import com.maddyhome.idea.vim.statistic.VimscriptState
|
|||||||
internal class IjStatisticsService : VimStatistics {
|
internal class IjStatisticsService : VimStatistics {
|
||||||
|
|
||||||
override fun logTrackedAction(actionId: String) {
|
override fun logTrackedAction(actionId: String) {
|
||||||
ActionTracker.Util.logTrackedAction(actionId)
|
ActionTracker.logTrackedAction(actionId)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun logCopiedAction(actionId: String) {
|
override fun logCopiedAction(actionId: String) {
|
||||||
ActionTracker.Util.logCopiedAction(actionId)
|
ActionTracker.logCopiedAction(actionId)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setIfLoopUsed(value: Boolean) {
|
override fun setIfLoopUsed(value: Boolean) {
|
||||||
VimscriptState.Util.isLoopUsed = value
|
VimscriptState.isLoopUsed = value
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setIfMapExprUsed(value: Boolean) {
|
override fun setIfMapExprUsed(value: Boolean) {
|
||||||
VimscriptState.Util.isMapExprUsed = value
|
VimscriptState.isMapExprUsed = value
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setIfFunctionCallUsed(value: Boolean) {
|
override fun setIfFunctionCallUsed(value: Boolean) {
|
||||||
VimscriptState.Util.isFunctionCallUsed = value
|
VimscriptState.isFunctionCallUsed = value
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setIfFunctionDeclarationUsed(value: Boolean) {
|
override fun setIfFunctionDeclarationUsed(value: Boolean) {
|
||||||
VimscriptState.Util.isFunctionDeclarationUsed = value
|
VimscriptState.isFunctionDeclarationUsed = value
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setIfIfUsed(value: Boolean) {
|
override fun setIfIfUsed(value: Boolean) {
|
||||||
VimscriptState.Util.isIfUsed = value
|
VimscriptState.isIfUsed = value
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun addExtensionEnabledWithPlug(extension: String) {
|
override fun addExtensionEnabledWithPlug(extension: String) {
|
||||||
VimscriptState.Util.extensionsEnabledWithPlug.add(extension)
|
VimscriptState.extensionsEnabledWithPlug.add(extension)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun addSourcedFile(path: String) {
|
override fun addSourcedFile(path: String) {
|
||||||
VimscriptState.Util.sourcedFiles.add(path)
|
VimscriptState.sourcedFiles.add(path)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,12 +26,10 @@ import com.maddyhome.idea.vim.EventFacade;
|
|||||||
import com.maddyhome.idea.vim.VimPlugin;
|
import com.maddyhome.idea.vim.VimPlugin;
|
||||||
import com.maddyhome.idea.vim.action.VimShortcutKeyAction;
|
import com.maddyhome.idea.vim.action.VimShortcutKeyAction;
|
||||||
import com.maddyhome.idea.vim.action.change.LazyVimCommand;
|
import com.maddyhome.idea.vim.action.change.LazyVimCommand;
|
||||||
import com.maddyhome.idea.vim.api.NativeAction;
|
import com.maddyhome.idea.vim.api.*;
|
||||||
import com.maddyhome.idea.vim.api.VimEditor;
|
|
||||||
import com.maddyhome.idea.vim.api.VimInjectorKt;
|
|
||||||
import com.maddyhome.idea.vim.api.VimKeyGroupBase;
|
|
||||||
import com.maddyhome.idea.vim.command.MappingMode;
|
import com.maddyhome.idea.vim.command.MappingMode;
|
||||||
import com.maddyhome.idea.vim.ex.ExOutputModel;
|
import com.maddyhome.idea.vim.ex.ExOutputModel;
|
||||||
|
import com.maddyhome.idea.vim.helper.HelperKt;
|
||||||
import com.maddyhome.idea.vim.key.*;
|
import com.maddyhome.idea.vim.key.*;
|
||||||
import com.maddyhome.idea.vim.newapi.IjNativeAction;
|
import com.maddyhome.idea.vim.newapi.IjNativeAction;
|
||||||
import com.maddyhome.idea.vim.newapi.IjVimEditor;
|
import com.maddyhome.idea.vim.newapi.IjVimEditor;
|
||||||
@ -101,9 +99,9 @@ public class KeyGroup extends VimKeyGroupBase implements PersistentStateComponen
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateShortcutKeysRegistration() {
|
public void updateShortcutKeysRegistration() {
|
||||||
for (VimEditor editor : injector.getEditorGroup().getEditors()) {
|
for (Editor editor : HelperKt.localEditors()) {
|
||||||
unregisterShortcutKeys(editor);
|
unregisterShortcutKeys(new IjVimEditor(editor));
|
||||||
registerRequiredShortcutKeys(editor);
|
registerRequiredShortcutKeys(new IjVimEditor(editor));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -230,7 +228,7 @@ public class KeyGroup extends VimKeyGroupBase implements PersistentStateComponen
|
|||||||
private void registerRequiredShortcut(@NotNull List<KeyStroke> keys, MappingOwner owner) {
|
private void registerRequiredShortcut(@NotNull List<KeyStroke> keys, MappingOwner owner) {
|
||||||
for (KeyStroke key : keys) {
|
for (KeyStroke key : keys) {
|
||||||
if (key.getKeyChar() == KeyEvent.CHAR_UNDEFINED) {
|
if (key.getKeyChar() == KeyEvent.CHAR_UNDEFINED) {
|
||||||
if (!injector.getApplication().isOctopusEnabled() ||
|
if (!injector.getOptionGroup().getGlobalOptions().getOctopushandler() ||
|
||||||
!(key.getKeyCode() == KeyEvent.VK_ESCAPE && key.getModifiers() == 0) &&
|
!(key.getKeyCode() == KeyEvent.VK_ESCAPE && key.getModifiers() == 0) &&
|
||||||
!(key.getKeyCode() == KeyEvent.VK_ENTER && key.getModifiers() == 0)) {
|
!(key.getKeyCode() == KeyEvent.VK_ENTER && key.getModifiers() == 0)) {
|
||||||
getRequiredShortcutKeys().add(new RequiredShortcut(key, owner));
|
getRequiredShortcutKeys().add(new RequiredShortcut(key, owner));
|
||||||
|
@ -10,7 +10,6 @@ package com.maddyhome.idea.vim.group
|
|||||||
import com.intellij.codeInsight.completion.CompletionPhase
|
import com.intellij.codeInsight.completion.CompletionPhase
|
||||||
import com.intellij.codeInsight.completion.impl.CompletionServiceImpl
|
import com.intellij.codeInsight.completion.impl.CompletionServiceImpl
|
||||||
import com.intellij.openapi.application.ApplicationManager
|
import com.intellij.openapi.application.ApplicationManager
|
||||||
import com.intellij.openapi.components.Service
|
|
||||||
import com.intellij.openapi.diagnostic.logger
|
import com.intellij.openapi.diagnostic.logger
|
||||||
import com.intellij.openapi.progress.ProcessCanceledException
|
import com.intellij.openapi.progress.ProcessCanceledException
|
||||||
import com.intellij.openapi.progress.ProgressManager
|
import com.intellij.openapi.progress.ProgressManager
|
||||||
@ -27,7 +26,6 @@ import com.maddyhome.idea.vim.newapi.ij
|
|||||||
/**
|
/**
|
||||||
* Used to handle playback of macros
|
* Used to handle playback of macros
|
||||||
*/
|
*/
|
||||||
@Service
|
|
||||||
internal class MacroGroup : VimMacroBase() {
|
internal class MacroGroup : VimMacroBase() {
|
||||||
|
|
||||||
// If it's null, this is the top macro (as in most cases). If it's not null, this macro is executed from top macro
|
// If it's null, this is the top macro (as in most cases). If it's not null, this macro is executed from top macro
|
||||||
@ -78,12 +76,11 @@ internal class MacroGroup : VimMacroBase() {
|
|||||||
} catch (e: ProcessCanceledException) {
|
} catch (e: ProcessCanceledException) {
|
||||||
return@runnable
|
return@runnable
|
||||||
}
|
}
|
||||||
val keyHandler = getInstance()
|
|
||||||
ProgressManager.getInstance().executeNonCancelableSection {
|
ProgressManager.getInstance().executeNonCancelableSection {
|
||||||
// Prevent autocompletion during macros.
|
// Prevent autocompletion during macros.
|
||||||
// See https://github.com/JetBrains/ideavim/pull/772 for details
|
// See https://github.com/JetBrains/ideavim/pull/772 for details
|
||||||
CompletionServiceImpl.setCompletionPhase(CompletionPhase.NoCompletion)
|
CompletionServiceImpl.setCompletionPhase(CompletionPhase.NoCompletion)
|
||||||
keyHandler.handleKey(editor, key, context, keyHandler.keyHandlerState)
|
getInstance().handleKey(editor, key, context)
|
||||||
}
|
}
|
||||||
if (injector.messages.isError()) return@runnable
|
if (injector.messages.isError()) return@runnable
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,6 @@
|
|||||||
package com.maddyhome.idea.vim.group
|
package com.maddyhome.idea.vim.group
|
||||||
|
|
||||||
import com.intellij.openapi.actionSystem.DataContext
|
import com.intellij.openapi.actionSystem.DataContext
|
||||||
import com.intellij.openapi.components.Service
|
|
||||||
import com.intellij.openapi.editor.Caret
|
import com.intellij.openapi.editor.Caret
|
||||||
import com.intellij.openapi.editor.Editor
|
import com.intellij.openapi.editor.Editor
|
||||||
import com.intellij.openapi.editor.LogicalPosition
|
import com.intellij.openapi.editor.LogicalPosition
|
||||||
@ -84,7 +83,6 @@ import kotlin.math.min
|
|||||||
/**
|
/**
|
||||||
* This handles all motion related commands and marks
|
* This handles all motion related commands and marks
|
||||||
*/
|
*/
|
||||||
@Service
|
|
||||||
internal class MotionGroup : VimMotionGroupBase() {
|
internal class MotionGroup : VimMotionGroupBase() {
|
||||||
override fun onAppCodeMovement(editor: VimEditor, caret: VimCaret, offset: Int, oldOffset: Int) {
|
override fun onAppCodeMovement(editor: VimEditor, caret: VimCaret, offset: Int, oldOffset: Int) {
|
||||||
AppCodeTemplates.onMovement(editor.ij, caret.ij, oldOffset < offset)
|
AppCodeTemplates.onMovement(editor.ij, caret.ij, oldOffset < offset)
|
||||||
|
@ -21,7 +21,6 @@ import com.intellij.openapi.actionSystem.ActionUpdateThread
|
|||||||
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.components.Service
|
|
||||||
import com.intellij.openapi.diagnostic.logger
|
import com.intellij.openapi.diagnostic.logger
|
||||||
import com.intellij.openapi.ide.CopyPasteManager
|
import com.intellij.openapi.ide.CopyPasteManager
|
||||||
import com.intellij.openapi.keymap.KeymapUtil
|
import com.intellij.openapi.keymap.KeymapUtil
|
||||||
@ -56,7 +55,6 @@ import javax.swing.KeyStroke
|
|||||||
* This service is can be used as application level and as project level service.
|
* This service is can be used as application level and as project level service.
|
||||||
* If project is null, this means that this is an application level service and notification will be shown for all projects
|
* If project is null, this means that this is an application level service and notification will be shown for all projects
|
||||||
*/
|
*/
|
||||||
@Service(Service.Level.PROJECT, Service.Level.APP)
|
|
||||||
internal class NotificationService(private val project: Project?) {
|
internal class NotificationService(private val project: Project?) {
|
||||||
// This constructor is used to create an applicationService
|
// This constructor is used to create an applicationService
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
@ -278,7 +276,7 @@ internal class NotificationService(private val project: Project?) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (id != null) {
|
if (id != null) {
|
||||||
ActionTracker.Util.logTrackedAction(id)
|
ActionTracker.logTrackedAction(id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -286,7 +284,7 @@ internal class NotificationService(private val project: Project?) {
|
|||||||
override fun actionPerformed(e: AnActionEvent) {
|
override fun actionPerformed(e: AnActionEvent) {
|
||||||
CopyPasteManager.getInstance().setContents(StringSelection(id ?: ""))
|
CopyPasteManager.getInstance().setContents(StringSelection(id ?: ""))
|
||||||
if (id != null) {
|
if (id != null) {
|
||||||
ActionTracker.Util.logCopiedAction(id)
|
ActionTracker.logCopiedAction(id)
|
||||||
}
|
}
|
||||||
notification?.expire()
|
notification?.expire()
|
||||||
|
|
||||||
|
@ -20,7 +20,6 @@ import com.intellij.openapi.progress.ProgressManager
|
|||||||
import com.intellij.util.execution.ParametersListUtil
|
import com.intellij.util.execution.ParametersListUtil
|
||||||
import com.intellij.util.text.CharSequenceReader
|
import com.intellij.util.text.CharSequenceReader
|
||||||
import com.maddyhome.idea.vim.KeyHandler.Companion.getInstance
|
import com.maddyhome.idea.vim.KeyHandler.Companion.getInstance
|
||||||
import com.maddyhome.idea.vim.KeyProcessResult
|
|
||||||
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
|
||||||
@ -38,6 +37,7 @@ import com.maddyhome.idea.vim.state.mode.Mode
|
|||||||
import com.maddyhome.idea.vim.state.mode.Mode.NORMAL
|
import com.maddyhome.idea.vim.state.mode.Mode.NORMAL
|
||||||
import com.maddyhome.idea.vim.state.mode.Mode.VISUAL
|
import com.maddyhome.idea.vim.state.mode.Mode.VISUAL
|
||||||
import com.maddyhome.idea.vim.state.mode.ReturnableFromCmd
|
import com.maddyhome.idea.vim.state.mode.ReturnableFromCmd
|
||||||
|
import com.maddyhome.idea.vim.state.mode.mode
|
||||||
import com.maddyhome.idea.vim.ui.ex.ExEntryPanel
|
import com.maddyhome.idea.vim.ui.ex.ExEntryPanel
|
||||||
import com.maddyhome.idea.vim.vimscript.model.CommandLineVimLContext
|
import com.maddyhome.idea.vim.vimscript.model.CommandLineVimLContext
|
||||||
import java.io.BufferedWriter
|
import java.io.BufferedWriter
|
||||||
@ -85,27 +85,24 @@ public class ProcessGroup : VimProcessGroupBase() {
|
|||||||
modeBeforeCommandProcessing = currentMode
|
modeBeforeCommandProcessing = currentMode
|
||||||
val initText = getRange(editor, cmd)
|
val initText = getRange(editor, cmd)
|
||||||
injector.markService.setVisualSelectionMarks(editor)
|
injector.markService.setVisualSelectionMarks(editor)
|
||||||
editor.mode = Mode.CMD_LINE(currentMode)
|
editor.vimStateMachine.mode = Mode.CMD_LINE(currentMode)
|
||||||
val panel = ExEntryPanel.getInstance()
|
val panel = ExEntryPanel.getInstance()
|
||||||
panel.activate(editor.ij, context.ij, ":", initText, 1)
|
panel.activate(editor.ij, context.ij, ":", initText, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
public override fun processExKey(editor: VimEditor, stroke: KeyStroke, processResultBuilder: KeyProcessResult.KeyProcessResultBuilder): Boolean {
|
public override fun processExKey(editor: VimEditor, stroke: KeyStroke): Boolean {
|
||||||
// This will only get called if somehow the key focus ended up in the editor while the ex entry window
|
// This will only get called if somehow the key focus ended up in the editor while the ex entry window
|
||||||
// is open. So I'll put focus back in the editor and process the key.
|
// is open. So I'll put focus back in the editor and process the key.
|
||||||
|
|
||||||
val panel = ExEntryPanel.getInstance()
|
val panel = ExEntryPanel.getInstance()
|
||||||
if (panel.isActive) {
|
if (panel.isActive) {
|
||||||
processResultBuilder.addExecutionStep { _, _, _ ->
|
|
||||||
requestFocus(panel.entry)
|
requestFocus(panel.entry)
|
||||||
panel.handleKey(stroke)
|
panel.handleKey(stroke)
|
||||||
}
|
|
||||||
return true
|
return true
|
||||||
} else {
|
} else {
|
||||||
processResultBuilder.addExecutionStep { _, lambdaEditor, _ ->
|
getInstance(editor).mode = NORMAL()
|
||||||
lambdaEditor.mode = NORMAL()
|
getInstance().reset(editor)
|
||||||
getInstance().reset(lambdaEditor)
|
|
||||||
}
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -115,7 +112,7 @@ public class ProcessGroup : VimProcessGroupBase() {
|
|||||||
panel.deactivate(true)
|
panel.deactivate(true)
|
||||||
var res = true
|
var res = true
|
||||||
try {
|
try {
|
||||||
editor.mode = NORMAL()
|
getInstance(editor).mode = NORMAL()
|
||||||
|
|
||||||
logger.debug("processing command")
|
logger.debug("processing command")
|
||||||
|
|
||||||
@ -155,7 +152,7 @@ public class ProcessGroup : VimProcessGroupBase() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public override fun cancelExEntry(editor: VimEditor, resetCaret: Boolean) {
|
public override fun cancelExEntry(editor: VimEditor, resetCaret: Boolean) {
|
||||||
editor.mode = NORMAL()
|
editor.vimStateMachine.mode = NORMAL()
|
||||||
getInstance().reset(editor)
|
getInstance().reset(editor)
|
||||||
val panel = ExEntryPanel.getInstance()
|
val panel = ExEntryPanel.getInstance()
|
||||||
panel.deactivate(true, resetCaret)
|
panel.deactivate(true, resetCaret)
|
||||||
@ -165,7 +162,7 @@ public class ProcessGroup : VimProcessGroupBase() {
|
|||||||
val initText = getRange(editor, cmd) + "!"
|
val initText = getRange(editor, cmd) + "!"
|
||||||
val currentMode = editor.mode
|
val currentMode = editor.mode
|
||||||
check(currentMode is ReturnableFromCmd) { "Cannot enable cmd mode from $currentMode" }
|
check(currentMode is ReturnableFromCmd) { "Cannot enable cmd mode from $currentMode" }
|
||||||
editor.mode = Mode.CMD_LINE(currentMode)
|
editor.vimStateMachine.mode = Mode.CMD_LINE(currentMode)
|
||||||
val panel = ExEntryPanel.getInstance()
|
val panel = ExEntryPanel.getInstance()
|
||||||
panel.activate(editor.ij, context.ij, ":", initText, 1)
|
panel.activate(editor.ij, context.ij, ":", initText, 1)
|
||||||
}
|
}
|
||||||
|
@ -14,9 +14,9 @@ import com.intellij.openapi.components.State;
|
|||||||
import com.intellij.openapi.components.Storage;
|
import com.intellij.openapi.components.Storage;
|
||||||
import com.intellij.openapi.diagnostic.Logger;
|
import com.intellij.openapi.diagnostic.Logger;
|
||||||
import com.maddyhome.idea.vim.VimPlugin;
|
import com.maddyhome.idea.vim.VimPlugin;
|
||||||
|
import com.maddyhome.idea.vim.state.mode.SelectionType;
|
||||||
import com.maddyhome.idea.vim.register.Register;
|
import com.maddyhome.idea.vim.register.Register;
|
||||||
import com.maddyhome.idea.vim.register.VimRegisterGroupBase;
|
import com.maddyhome.idea.vim.register.VimRegisterGroupBase;
|
||||||
import com.maddyhome.idea.vim.state.mode.SelectionType;
|
|
||||||
import org.jdom.Element;
|
import org.jdom.Element;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
@ -37,10 +37,6 @@ public class RegisterGroup extends VimRegisterGroupBase implements PersistentSta
|
|||||||
|
|
||||||
private static final Logger logger = Logger.getInstance(RegisterGroup.class);
|
private static final Logger logger = Logger.getInstance(RegisterGroup.class);
|
||||||
|
|
||||||
public RegisterGroup() {
|
|
||||||
this.initClipboardOptionListener();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void saveData(final @NotNull Element element) {
|
public void saveData(final @NotNull Element element) {
|
||||||
logger.debug("Save registers data");
|
logger.debug("Save registers data");
|
||||||
final Element registersElement = new Element("registers");
|
final Element registersElement = new Element("registers");
|
||||||
|
@ -21,6 +21,8 @@ import com.intellij.openapi.editor.event.DocumentEvent;
|
|||||||
import com.intellij.openapi.editor.event.DocumentListener;
|
import com.intellij.openapi.editor.event.DocumentListener;
|
||||||
import com.intellij.openapi.editor.markup.RangeHighlighter;
|
import com.intellij.openapi.editor.markup.RangeHighlighter;
|
||||||
import com.intellij.openapi.fileEditor.FileEditorManagerEvent;
|
import com.intellij.openapi.fileEditor.FileEditorManagerEvent;
|
||||||
|
import com.intellij.openapi.project.Project;
|
||||||
|
import com.intellij.openapi.project.ProjectManager;
|
||||||
import com.intellij.openapi.util.Ref;
|
import com.intellij.openapi.util.Ref;
|
||||||
import com.maddyhome.idea.vim.VimPlugin;
|
import com.maddyhome.idea.vim.VimPlugin;
|
||||||
import com.maddyhome.idea.vim.api.*;
|
import com.maddyhome.idea.vim.api.*;
|
||||||
@ -31,11 +33,12 @@ import com.maddyhome.idea.vim.ex.ExException;
|
|||||||
import com.maddyhome.idea.vim.ex.ranges.LineRange;
|
import com.maddyhome.idea.vim.ex.ranges.LineRange;
|
||||||
import com.maddyhome.idea.vim.helper.*;
|
import com.maddyhome.idea.vim.helper.*;
|
||||||
import com.maddyhome.idea.vim.history.HistoryConstants;
|
import com.maddyhome.idea.vim.history.HistoryConstants;
|
||||||
import com.maddyhome.idea.vim.newapi.*;
|
import com.maddyhome.idea.vim.newapi.IjEditorExecutionContext;
|
||||||
|
import com.maddyhome.idea.vim.newapi.IjVimCaret;
|
||||||
|
import com.maddyhome.idea.vim.newapi.IjVimEditor;
|
||||||
|
import com.maddyhome.idea.vim.newapi.IjVimSearchGroup;
|
||||||
import com.maddyhome.idea.vim.options.GlobalOptionChangeListener;
|
import com.maddyhome.idea.vim.options.GlobalOptionChangeListener;
|
||||||
import com.maddyhome.idea.vim.regexp.CharPointer;
|
import com.maddyhome.idea.vim.regexp.*;
|
||||||
import com.maddyhome.idea.vim.regexp.CharacterClasses;
|
|
||||||
import com.maddyhome.idea.vim.regexp.RegExp;
|
|
||||||
import com.maddyhome.idea.vim.ui.ModalEntry;
|
import com.maddyhome.idea.vim.ui.ModalEntry;
|
||||||
import com.maddyhome.idea.vim.ui.ex.ExEntryPanel;
|
import com.maddyhome.idea.vim.ui.ex.ExEntryPanel;
|
||||||
import com.maddyhome.idea.vim.vimscript.model.VimLContext;
|
import com.maddyhome.idea.vim.vimscript.model.VimLContext;
|
||||||
@ -56,6 +59,7 @@ import java.text.ParsePosition;
|
|||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
import static com.maddyhome.idea.vim.api.VimInjectorKt.*;
|
import static com.maddyhome.idea.vim.api.VimInjectorKt.*;
|
||||||
|
import static com.maddyhome.idea.vim.helper.HelperKt.localEditors;
|
||||||
import static com.maddyhome.idea.vim.helper.SearchHelperKtKt.shouldIgnoreCase;
|
import static com.maddyhome.idea.vim.helper.SearchHelperKtKt.shouldIgnoreCase;
|
||||||
import static com.maddyhome.idea.vim.newapi.IjVimInjectorKt.globalIjOptions;
|
import static com.maddyhome.idea.vim.newapi.IjVimInjectorKt.globalIjOptions;
|
||||||
import static com.maddyhome.idea.vim.register.RegisterConstants.LAST_SEARCH_REGISTER;
|
import static com.maddyhome.idea.vim.register.RegisterConstants.LAST_SEARCH_REGISTER;
|
||||||
@ -1196,18 +1200,15 @@ public class SearchGroup extends IjVimSearchGroup implements PersistentStateComp
|
|||||||
public static DocumentSearchListener INSTANCE = new DocumentSearchListener();
|
public static DocumentSearchListener INSTANCE = new DocumentSearchListener();
|
||||||
|
|
||||||
@Contract(pure = true)
|
@Contract(pure = true)
|
||||||
private DocumentSearchListener() {
|
private DocumentSearchListener () {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void documentChanged(@NotNull DocumentEvent event) {
|
public void documentChanged(@NotNull DocumentEvent event) {
|
||||||
// Loop over all local editors for the changed document, across all projects, and update search highlights.
|
for (Project project : ProjectManager.getInstance().getOpenProjects()) {
|
||||||
// Note that the change may have come from a remote guest in Code With Me scenarios (in which case
|
|
||||||
// ClientId.current will be a guest ID), but we don't care - we still need to add/remove highlights for the
|
|
||||||
// changed text. Make sure we only update local editors, though.
|
|
||||||
final Document document = event.getDocument();
|
final Document document = event.getDocument();
|
||||||
for (VimEditor vimEditor : injector.getEditorGroup().getEditors(new IjVimDocument(document))) {
|
|
||||||
final Editor editor = ((IjVimEditor)vimEditor).getEditor();
|
for (Editor editor : localEditors(document, project)) {
|
||||||
Collection<RangeHighlighter> hls = UserDataManager.getVimLastHighlighters(editor);
|
Collection<RangeHighlighter> hls = UserDataManager.getVimLastHighlighters(editor);
|
||||||
if (hls == null) {
|
if (hls == null) {
|
||||||
continue;
|
continue;
|
||||||
@ -1227,8 +1228,7 @@ public class SearchGroup extends IjVimSearchGroup implements PersistentStateComp
|
|||||||
final Iterator<RangeHighlighter> iter = hls.iterator();
|
final Iterator<RangeHighlighter> iter = hls.iterator();
|
||||||
while (iter.hasNext()) {
|
while (iter.hasNext()) {
|
||||||
final RangeHighlighter highlighter = iter.next();
|
final RangeHighlighter highlighter = iter.next();
|
||||||
if (!highlighter.isValid() ||
|
if (!highlighter.isValid() || (highlighter.getStartOffset() >= startLineOffset && highlighter.getEndOffset() <= endLineOffset)) {
|
||||||
(highlighter.getStartOffset() >= startLineOffset && highlighter.getEndOffset() <= endLineOffset)) {
|
|
||||||
iter.remove();
|
iter.remove();
|
||||||
editor.getMarkupModel().removeHighlighter(highlighter);
|
editor.getMarkupModel().removeHighlighter(highlighter);
|
||||||
}
|
}
|
||||||
@ -1244,6 +1244,7 @@ public class SearchGroup extends IjVimSearchGroup implements PersistentStateComp
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
//endregion
|
//endregion
|
||||||
|
|
||||||
|
|
||||||
|
@ -111,7 +111,7 @@ internal class JumpsListener(val project: Project) : RecentPlacesListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun buildJump(place: PlaceInfo): Jump? {
|
private fun buildJump(place: PlaceInfo): Jump? {
|
||||||
val editor = injector.editorGroup.getEditors().firstOrNull { it.ij.virtualFile == place.file } ?: return null
|
val editor = injector.editorGroup.localEditors().firstOrNull { it.ij.virtualFile == place.file } ?: return null
|
||||||
val offset = place.caretPosition?.startOffset ?: return null
|
val offset = place.caretPosition?.startOffset ?: return null
|
||||||
|
|
||||||
val bufferPosition = editor.offsetToBufferPosition(offset)
|
val bufferPosition = editor.offsetToBufferPosition(offset)
|
||||||
|
@ -7,7 +7,6 @@
|
|||||||
*/
|
*/
|
||||||
package com.maddyhome.idea.vim.group
|
package com.maddyhome.idea.vim.group
|
||||||
|
|
||||||
import com.intellij.codeWithMe.ClientId
|
|
||||||
import com.intellij.ide.bookmark.Bookmark
|
import com.intellij.ide.bookmark.Bookmark
|
||||||
import com.intellij.ide.bookmark.BookmarkGroup
|
import com.intellij.ide.bookmark.BookmarkGroup
|
||||||
import com.intellij.ide.bookmark.BookmarksListener
|
import com.intellij.ide.bookmark.BookmarksListener
|
||||||
@ -19,7 +18,7 @@ import com.intellij.openapi.components.State
|
|||||||
import com.intellij.openapi.components.Storage
|
import com.intellij.openapi.components.Storage
|
||||||
import com.intellij.openapi.diagnostic.Logger
|
import com.intellij.openapi.diagnostic.Logger
|
||||||
import com.intellij.openapi.editor.Document
|
import com.intellij.openapi.editor.Document
|
||||||
import com.intellij.openapi.editor.EditorFactory
|
import com.intellij.openapi.editor.Editor
|
||||||
import com.intellij.openapi.editor.event.DocumentEvent
|
import com.intellij.openapi.editor.event.DocumentEvent
|
||||||
import com.intellij.openapi.editor.event.DocumentListener
|
import com.intellij.openapi.editor.event.DocumentListener
|
||||||
import com.intellij.openapi.fileEditor.FileEditorManager
|
import com.intellij.openapi.fileEditor.FileEditorManager
|
||||||
@ -29,11 +28,11 @@ import com.intellij.openapi.util.text.StringUtil
|
|||||||
import com.intellij.util.asSafely
|
import com.intellij.util.asSafely
|
||||||
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.api.VimEditorGroup
|
|
||||||
import com.maddyhome.idea.vim.api.VimMarkService
|
import com.maddyhome.idea.vim.api.VimMarkService
|
||||||
import com.maddyhome.idea.vim.api.VimMarkServiceBase
|
import com.maddyhome.idea.vim.api.VimMarkServiceBase
|
||||||
import com.maddyhome.idea.vim.api.injector
|
import com.maddyhome.idea.vim.api.injector
|
||||||
import com.maddyhome.idea.vim.group.SystemMarks.Companion.createOrGetSystemMark
|
import com.maddyhome.idea.vim.group.SystemMarks.Companion.createOrGetSystemMark
|
||||||
|
import com.maddyhome.idea.vim.helper.localEditors
|
||||||
import com.maddyhome.idea.vim.mark.IntellijMark
|
import com.maddyhome.idea.vim.mark.IntellijMark
|
||||||
import com.maddyhome.idea.vim.mark.Mark
|
import com.maddyhome.idea.vim.mark.Mark
|
||||||
import com.maddyhome.idea.vim.mark.VimMark.Companion.create
|
import com.maddyhome.idea.vim.mark.VimMark.Companion.create
|
||||||
@ -194,10 +193,6 @@ internal class VimMarkServiceImpl : VimMarkServiceBase(), PersistentStateCompone
|
|||||||
* This event indicates that a document is about to be changed. We use this event to update all the
|
* This event indicates that a document is about to be changed. We use this event to update all the
|
||||||
* editor's marks if text is about to be deleted.
|
* editor's marks if text is about to be deleted.
|
||||||
*
|
*
|
||||||
* Note that the event is fired for both local changes and changes from remote guests in Code With Me scenarios (in
|
|
||||||
* which case [ClientId.current] will be the remote client). We don't care who caused it, we just need to update the
|
|
||||||
* stored marks.
|
|
||||||
*
|
|
||||||
* @param event The change event
|
* @param event The change event
|
||||||
*/
|
*/
|
||||||
override fun beforeDocumentChange(event: DocumentEvent) {
|
override fun beforeDocumentChange(event: DocumentEvent) {
|
||||||
@ -205,18 +200,15 @@ internal class VimMarkServiceImpl : VimMarkServiceBase(), PersistentStateCompone
|
|||||||
if (logger.isDebugEnabled) logger.debug("MarkUpdater before, event = $event")
|
if (logger.isDebugEnabled) logger.debug("MarkUpdater before, event = $event")
|
||||||
if (event.oldLength == 0) return
|
if (event.oldLength == 0) return
|
||||||
val doc = event.document
|
val doc = event.document
|
||||||
val anEditor = getAnyEditorForDocument(doc) ?: return
|
val anEditor = getAnEditor(doc) ?: return
|
||||||
injector.markService.updateMarksFromDelete(anEditor, event.offset, event.oldLength)
|
injector.markService
|
||||||
|
.updateMarksFromDelete(IjVimEditor(anEditor), event.offset, event.oldLength)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This event indicates that a document was just changed. We use this event to update all the editor's
|
* This event indicates that a document was just changed. We use this event to update all the editor's
|
||||||
* marks if text was just added.
|
* marks if text was just added.
|
||||||
*
|
*
|
||||||
* Note that the event is fired for both local changes and changes from remote guests in Code With Me scenarios (in
|
|
||||||
* which case [ClientId.current] will be the remote client). We don't care who caused it, we just need to update the
|
|
||||||
* stored marks.
|
|
||||||
*
|
|
||||||
* @param event The change event
|
* @param event The change event
|
||||||
*/
|
*/
|
||||||
override fun documentChanged(event: DocumentEvent) {
|
override fun documentChanged(event: DocumentEvent) {
|
||||||
@ -224,19 +216,19 @@ internal class VimMarkServiceImpl : VimMarkServiceBase(), PersistentStateCompone
|
|||||||
if (logger.isDebugEnabled) logger.debug("MarkUpdater after, event = $event")
|
if (logger.isDebugEnabled) logger.debug("MarkUpdater after, event = $event")
|
||||||
if (event.newLength == 0 || event.newLength == 1 && event.newFragment[0] != '\n') return
|
if (event.newLength == 0 || event.newLength == 1 && event.newFragment[0] != '\n') return
|
||||||
val doc = event.document
|
val doc = event.document
|
||||||
val anEditor = getAnyEditorForDocument(doc) ?: return
|
val anEditor = getAnEditor(doc) ?: return
|
||||||
injector.markService.updateMarksFromInsert(anEditor, event.offset, event.newLength)
|
injector.markService
|
||||||
|
.updateMarksFromInsert(IjVimEditor(anEditor), event.offset, event.newLength)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private fun getAnEditor(doc: Document): Editor? {
|
||||||
* Get any editor for the given document
|
val editors = localEditors(doc)
|
||||||
*
|
return if (editors.size > 0) {
|
||||||
* We need an editor to help calculate offsets for marks, and it doesn't matter which one we use, because they would
|
editors[0]
|
||||||
* all return the same results. However, we cannot use [VimEditorGroup.getEditors] because the change might have
|
} else {
|
||||||
* come from a remote guest and there might not be an open local editor.
|
null
|
||||||
*/
|
}
|
||||||
private fun getAnyEditorForDocument(doc: Document) =
|
}
|
||||||
EditorFactory.getInstance().getEditors(doc).firstOrNull()?.let { IjVimEditor(it) }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class VimBookmarksListener(private val myProject: Project) : BookmarksListener {
|
class VimBookmarksListener(private val myProject: Project) : BookmarksListener {
|
||||||
|
@ -8,11 +8,9 @@
|
|||||||
|
|
||||||
package com.maddyhome.idea.vim.group
|
package com.maddyhome.idea.vim.group
|
||||||
|
|
||||||
import com.intellij.openapi.components.Service
|
|
||||||
import org.apache.commons.codec.binary.Base64
|
import org.apache.commons.codec.binary.Base64
|
||||||
import org.jdom.Element
|
import org.jdom.Element
|
||||||
|
|
||||||
@Service
|
|
||||||
internal class XMLGroup {
|
internal class XMLGroup {
|
||||||
/**
|
/**
|
||||||
* Set the text of an XML element, safely encode it if needed.
|
* Set the text of an XML element, safely encode it if needed.
|
||||||
|
@ -14,7 +14,6 @@ import com.intellij.ide.DataManager
|
|||||||
import com.intellij.ide.PasteProvider
|
import com.intellij.ide.PasteProvider
|
||||||
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.components.Service
|
|
||||||
import com.intellij.openapi.editor.Caret
|
import com.intellij.openapi.editor.Caret
|
||||||
import com.intellij.openapi.editor.RangeMarker
|
import com.intellij.openapi.editor.RangeMarker
|
||||||
import com.intellij.openapi.editor.ex.EditorEx
|
import com.intellij.openapi.editor.ex.EditorEx
|
||||||
@ -52,7 +51,6 @@ import com.maddyhome.idea.vim.state.mode.isChar
|
|||||||
import com.maddyhome.idea.vim.state.mode.isLine
|
import com.maddyhome.idea.vim.state.mode.isLine
|
||||||
import java.awt.datatransfer.DataFlavor
|
import java.awt.datatransfer.DataFlavor
|
||||||
|
|
||||||
@Service
|
|
||||||
internal class PutGroup : VimPutBase() {
|
internal class PutGroup : VimPutBase() {
|
||||||
|
|
||||||
override fun getProviderForPasteViaIde(
|
override fun getProviderForPasteViaIde(
|
||||||
|
@ -20,8 +20,9 @@ import com.maddyhome.idea.vim.helper.exitVisualMode
|
|||||||
import com.maddyhome.idea.vim.helper.hasVisualSelection
|
import com.maddyhome.idea.vim.helper.hasVisualSelection
|
||||||
import com.maddyhome.idea.vim.helper.inInsertMode
|
import com.maddyhome.idea.vim.helper.inInsertMode
|
||||||
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.isTemplateActive
|
import com.maddyhome.idea.vim.helper.isTemplateActive
|
||||||
import com.maddyhome.idea.vim.helper.vimDisabled
|
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.vim
|
import com.maddyhome.idea.vim.newapi.vim
|
||||||
import com.maddyhome.idea.vim.options.OptionConstants
|
import com.maddyhome.idea.vim.options.OptionConstants
|
||||||
@ -29,6 +30,7 @@ import com.maddyhome.idea.vim.state.mode.Mode
|
|||||||
import com.maddyhome.idea.vim.state.mode.inNormalMode
|
import com.maddyhome.idea.vim.state.mode.inNormalMode
|
||||||
import com.maddyhome.idea.vim.state.mode.inSelectMode
|
import com.maddyhome.idea.vim.state.mode.inSelectMode
|
||||||
import com.maddyhome.idea.vim.state.mode.inVisualMode
|
import com.maddyhome.idea.vim.state.mode.inVisualMode
|
||||||
|
import com.maddyhome.idea.vim.state.mode.mode
|
||||||
import com.maddyhome.idea.vim.vimscript.model.options.helpers.IdeaRefactorModeHelper
|
import com.maddyhome.idea.vim.vimscript.model.options.helpers.IdeaRefactorModeHelper
|
||||||
import com.maddyhome.idea.vim.vimscript.model.options.helpers.isIdeaRefactorModeKeep
|
import com.maddyhome.idea.vim.vimscript.model.options.helpers.isIdeaRefactorModeKeep
|
||||||
import com.maddyhome.idea.vim.vimscript.model.options.helpers.isIdeaRefactorModeSelect
|
import com.maddyhome.idea.vim.vimscript.model.options.helpers.isIdeaRefactorModeSelect
|
||||||
@ -53,7 +55,9 @@ internal object IdeaSelectionControl {
|
|||||||
selectionSource: VimListenerManager.SelectionSource = VimListenerManager.SelectionSource.OTHER,
|
selectionSource: VimListenerManager.SelectionSource = VimListenerManager.SelectionSource.OTHER,
|
||||||
) {
|
) {
|
||||||
VimVisualTimer.singleTask(editor.vim.mode) { initialMode ->
|
VimVisualTimer.singleTask(editor.vim.mode) { initialMode ->
|
||||||
if (vimDisabled(editor)) return@singleTask
|
|
||||||
|
if (VimPlugin.isNotEnabled()) return@singleTask
|
||||||
|
if (editor.isIdeaVimDisabledHere) return@singleTask
|
||||||
|
|
||||||
logger.debug("Adjust non-vim selection. Source: $selectionSource, initialMode: $initialMode")
|
logger.debug("Adjust non-vim selection. Source: $selectionSource, initialMode: $initialMode")
|
||||||
|
|
||||||
@ -75,7 +79,7 @@ internal object IdeaSelectionControl {
|
|||||||
|
|
||||||
logger.debug("Some carets have selection. State before adjustment: ${editor.vim.mode}")
|
logger.debug("Some carets have selection. State before adjustment: ${editor.vim.mode}")
|
||||||
|
|
||||||
editor.vim.mode = Mode.NORMAL()
|
editor.vim.vimStateMachine.mode = Mode.NORMAL()
|
||||||
|
|
||||||
activateMode(editor, chooseSelectionMode(editor, selectionSource, true))
|
activateMode(editor, chooseSelectionMode(editor, selectionSource, true))
|
||||||
} else {
|
} else {
|
||||||
|
@ -12,13 +12,13 @@ import com.intellij.openapi.editor.Caret
|
|||||||
import com.intellij.openapi.editor.Editor
|
import com.intellij.openapi.editor.Editor
|
||||||
import com.maddyhome.idea.vim.api.getLineEndForOffset
|
import com.maddyhome.idea.vim.api.getLineEndForOffset
|
||||||
import com.maddyhome.idea.vim.api.getLineStartForOffset
|
import com.maddyhome.idea.vim.api.getLineStartForOffset
|
||||||
|
import com.maddyhome.idea.vim.state.mode.Mode
|
||||||
|
import com.maddyhome.idea.vim.state.mode.inBlockSelection
|
||||||
import com.maddyhome.idea.vim.helper.isEndAllowed
|
import com.maddyhome.idea.vim.helper.isEndAllowed
|
||||||
import com.maddyhome.idea.vim.helper.moveToInlayAwareOffset
|
import com.maddyhome.idea.vim.helper.moveToInlayAwareOffset
|
||||||
import com.maddyhome.idea.vim.helper.vimSelectionStart
|
import com.maddyhome.idea.vim.helper.vimSelectionStart
|
||||||
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
|
||||||
import com.maddyhome.idea.vim.state.mode.Mode
|
|
||||||
import com.maddyhome.idea.vim.state.mode.inBlockSelection
|
|
||||||
|
|
||||||
internal fun moveCaretOneCharLeftFromSelectionEnd(editor: Editor, predictedMode: Mode) {
|
internal fun moveCaretOneCharLeftFromSelectionEnd(editor: Editor, predictedMode: Mode) {
|
||||||
if (predictedMode !is Mode.VISUAL) {
|
if (predictedMode !is Mode.VISUAL) {
|
||||||
|
@ -13,10 +13,10 @@ 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.state.mode.SelectionType
|
||||||
import com.maddyhome.idea.vim.command.engine
|
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
|
import com.maddyhome.idea.vim.newapi.vim
|
||||||
import com.maddyhome.idea.vim.state.mode.SelectionType
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Alex Plate
|
* @author Alex Plate
|
||||||
|
@ -27,6 +27,7 @@ import com.intellij.openapi.util.UserDataHolder
|
|||||||
import com.intellij.openapi.util.removeUserData
|
import com.intellij.openapi.util.removeUserData
|
||||||
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.api.globalOptions
|
||||||
import com.maddyhome.idea.vim.api.injector
|
import com.maddyhome.idea.vim.api.injector
|
||||||
import com.maddyhome.idea.vim.api.key
|
import com.maddyhome.idea.vim.api.key
|
||||||
import com.maddyhome.idea.vim.group.IjOptionConstants
|
import com.maddyhome.idea.vim.group.IjOptionConstants
|
||||||
@ -38,6 +39,7 @@ import com.maddyhome.idea.vim.newapi.actionStartedFromVim
|
|||||||
import com.maddyhome.idea.vim.newapi.globalIjOptions
|
import com.maddyhome.idea.vim.newapi.globalIjOptions
|
||||||
import com.maddyhome.idea.vim.newapi.vim
|
import com.maddyhome.idea.vim.newapi.vim
|
||||||
import com.maddyhome.idea.vim.state.mode.Mode
|
import com.maddyhome.idea.vim.state.mode.Mode
|
||||||
|
import com.maddyhome.idea.vim.state.mode.mode
|
||||||
import java.awt.event.KeyEvent
|
import java.awt.event.KeyEvent
|
||||||
import javax.swing.KeyStroke
|
import javax.swing.KeyStroke
|
||||||
|
|
||||||
@ -338,8 +340,7 @@ internal abstract class VimKeyHandler(nextHandler: EditorActionHandler?) : Octop
|
|||||||
override fun executeHandler(editor: Editor, caret: Caret?, dataContext: DataContext?) {
|
override fun executeHandler(editor: Editor, caret: Caret?, dataContext: DataContext?) {
|
||||||
val enterKey = key(key)
|
val enterKey = key(key)
|
||||||
val context = injector.executionContextManager.onEditor(editor.vim, dataContext?.vim)
|
val context = injector.executionContextManager.onEditor(editor.vim, dataContext?.vim)
|
||||||
val keyHandler = KeyHandler.getInstance()
|
KeyHandler.getInstance().handleKey(editor.vim, enterKey, context)
|
||||||
keyHandler.handleKey(editor.vim, enterKey, context, keyHandler.keyHandlerState)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun isHandlerEnabled(editor: Editor, dataContext: DataContext?): Boolean {
|
override fun isHandlerEnabled(editor: Editor, dataContext: DataContext?): Boolean {
|
||||||
@ -361,4 +362,4 @@ internal fun isOctopusEnabled(s: KeyStroke, editor: Editor): Boolean {
|
|||||||
}
|
}
|
||||||
|
|
||||||
internal val enableOctopus: Boolean
|
internal val enableOctopus: Boolean
|
||||||
get() = injector.application.isOctopusEnabled()
|
get() = injector.globalOptions().octopushandler
|
||||||
|
@ -8,7 +8,6 @@
|
|||||||
|
|
||||||
package com.maddyhome.idea.vim.helper
|
package com.maddyhome.idea.vim.helper
|
||||||
|
|
||||||
import com.intellij.openapi.application.ApplicationManager
|
|
||||||
import com.intellij.openapi.diagnostic.thisLogger
|
import com.intellij.openapi.diagnostic.thisLogger
|
||||||
import com.intellij.openapi.editor.Caret
|
import com.intellij.openapi.editor.Caret
|
||||||
import com.intellij.openapi.editor.CaretVisualAttributes
|
import com.intellij.openapi.editor.CaretVisualAttributes
|
||||||
@ -19,17 +18,14 @@ 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.api.globalOptions
|
import com.maddyhome.idea.vim.api.globalOptions
|
||||||
import com.maddyhome.idea.vim.api.injector
|
import com.maddyhome.idea.vim.api.injector
|
||||||
import com.maddyhome.idea.vim.common.IsReplaceCharListener
|
|
||||||
import com.maddyhome.idea.vim.common.ModeChangeListener
|
|
||||||
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.EffectiveOptionValueChangeListener
|
import com.maddyhome.idea.vim.options.EffectiveOptionValueChangeListener
|
||||||
import com.maddyhome.idea.vim.options.helpers.GuiCursorMode
|
import com.maddyhome.idea.vim.options.helpers.GuiCursorMode
|
||||||
import com.maddyhome.idea.vim.options.helpers.GuiCursorOptionHelper
|
import com.maddyhome.idea.vim.options.helpers.GuiCursorOptionHelper
|
||||||
import com.maddyhome.idea.vim.options.helpers.GuiCursorType
|
import com.maddyhome.idea.vim.options.helpers.GuiCursorType
|
||||||
import com.maddyhome.idea.vim.state.mode.Mode
|
|
||||||
import com.maddyhome.idea.vim.state.mode.inBlockSelection
|
import com.maddyhome.idea.vim.state.mode.inBlockSelection
|
||||||
|
import com.maddyhome.idea.vim.state.mode.mode
|
||||||
import org.jetbrains.annotations.TestOnly
|
import org.jetbrains.annotations.TestOnly
|
||||||
import java.awt.Color
|
import java.awt.Color
|
||||||
|
|
||||||
@ -89,10 +85,7 @@ private fun Editor.updatePrimaryCaretVisualAttributes() {
|
|||||||
caretModel.primaryCaret.visualAttributes = AttributesCache.getCaretVisualAttributes(this)
|
caretModel.primaryCaret.visualAttributes = AttributesCache.getCaretVisualAttributes(this)
|
||||||
|
|
||||||
// Make sure the caret is visible as soon as it's set. It might be invisible while blinking
|
// Make sure the caret is visible as soon as it's set. It might be invisible while blinking
|
||||||
// NOTE: At the moment, this causes project leak in tests
|
|
||||||
if (!ApplicationManager.getApplication().isUnitTestMode) {
|
|
||||||
(this as? EditorEx)?.setCaretVisible(true)
|
(this as? EditorEx)?.setCaretVisible(true)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun Editor.updateSecondaryCaretsVisualAttributes() {
|
private fun Editor.updateSecondaryCaretsVisualAttributes() {
|
||||||
@ -141,31 +134,3 @@ private object AttributesCache {
|
|||||||
|
|
||||||
@TestOnly
|
@TestOnly
|
||||||
internal fun getGuiCursorMode(editor: Editor) = editor.guicursorMode()
|
internal fun getGuiCursorMode(editor: Editor) = editor.guicursorMode()
|
||||||
|
|
||||||
public class CaretVisualAttributesListener : IsReplaceCharListener, ModeChangeListener {
|
|
||||||
override fun isReplaceCharChanged(editor: VimEditor) {
|
|
||||||
updateCaretsVisual(editor)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun modeChanged(editor: VimEditor, oldMode: Mode) {
|
|
||||||
updateCaretsVisual(editor)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun updateCaretsVisual(editor: VimEditor) {
|
|
||||||
if (injector.globalOptions().ideaglobalmode) {
|
|
||||||
updateAllEditorsCaretsVisual()
|
|
||||||
} else {
|
|
||||||
val ijEditor = (editor as IjVimEditor).editor
|
|
||||||
ijEditor.updateCaretsVisualAttributes()
|
|
||||||
ijEditor.updateCaretsVisualPosition()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public fun updateAllEditorsCaretsVisual() {
|
|
||||||
injector.editorGroup.getEditors().forEach { editor ->
|
|
||||||
val ijEditor = (editor as IjVimEditor).editor
|
|
||||||
ijEditor.updateCaretsVisualAttributes()
|
|
||||||
ijEditor.updateCaretsVisualPosition()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -20,6 +20,7 @@ import com.maddyhome.idea.vim.options.OptionAccessScope
|
|||||||
import com.maddyhome.idea.vim.options.OptionConstants
|
import com.maddyhome.idea.vim.options.OptionConstants
|
||||||
import com.maddyhome.idea.vim.state.mode.Mode
|
import com.maddyhome.idea.vim.state.mode.Mode
|
||||||
import com.maddyhome.idea.vim.state.mode.inVisualMode
|
import com.maddyhome.idea.vim.state.mode.inVisualMode
|
||||||
|
import com.maddyhome.idea.vim.state.mode.mode
|
||||||
|
|
||||||
internal val Mode.hasVisualSelection
|
internal val Mode.hasVisualSelection
|
||||||
get() = when (this) {
|
get() = when (this) {
|
||||||
|
@ -0,0 +1,45 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2003-2023 The IdeaVim authors
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by an MIT-style
|
||||||
|
* license that can be found in the LICENSE.txt file or at
|
||||||
|
* https://opensource.org/licenses/MIT.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.maddyhome.idea.vim.helper
|
||||||
|
|
||||||
|
import com.intellij.openapi.editor.Document
|
||||||
|
import com.intellij.openapi.editor.event.DocumentListener
|
||||||
|
import com.intellij.openapi.util.Key
|
||||||
|
import com.maddyhome.idea.vim.EventFacade
|
||||||
|
import com.maddyhome.idea.vim.group.SearchGroup
|
||||||
|
import com.maddyhome.idea.vim.group.VimMarkServiceImpl
|
||||||
|
|
||||||
|
internal object DocumentManager {
|
||||||
|
private val docListeners = mutableSetOf<DocumentListener>()
|
||||||
|
private val LISTENER_MARKER = Key<String>("VimlistenerMarker")
|
||||||
|
|
||||||
|
init {
|
||||||
|
docListeners += VimMarkServiceImpl.MarkUpdater
|
||||||
|
docListeners += SearchGroup.DocumentSearchListener.INSTANCE
|
||||||
|
}
|
||||||
|
|
||||||
|
fun addListeners(doc: Document) {
|
||||||
|
val marker = doc.getUserData(LISTENER_MARKER)
|
||||||
|
if (marker != null) return
|
||||||
|
|
||||||
|
doc.putUserData(LISTENER_MARKER, "foo")
|
||||||
|
for (docListener in docListeners) {
|
||||||
|
EventFacade.getInstance().addDocumentListener(doc, docListener)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun removeListeners(doc: Document) {
|
||||||
|
doc.getUserData(LISTENER_MARKER) ?: return
|
||||||
|
|
||||||
|
doc.putUserData(LISTENER_MARKER, null)
|
||||||
|
for (docListener in docListeners) {
|
||||||
|
EventFacade.getInstance().removeDocumentListener(doc, docListener)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -17,7 +17,6 @@ import com.intellij.testFramework.LightVirtualFile;
|
|||||||
import com.maddyhome.idea.vim.api.EngineEditorHelperKt;
|
import com.maddyhome.idea.vim.api.EngineEditorHelperKt;
|
||||||
import com.maddyhome.idea.vim.api.VimEditor;
|
import com.maddyhome.idea.vim.api.VimEditor;
|
||||||
import com.maddyhome.idea.vim.common.IndentConfig;
|
import com.maddyhome.idea.vim.common.IndentConfig;
|
||||||
import com.maddyhome.idea.vim.newapi.IjVimDocument;
|
|
||||||
import com.maddyhome.idea.vim.newapi.IjVimEditor;
|
import com.maddyhome.idea.vim.newapi.IjVimEditor;
|
||||||
import com.maddyhome.idea.vim.ui.ex.ExEntryPanel;
|
import com.maddyhome.idea.vim.ui.ex.ExEntryPanel;
|
||||||
import kotlin.Pair;
|
import kotlin.Pair;
|
||||||
@ -30,7 +29,6 @@ import java.util.Collections;
|
|||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static com.maddyhome.idea.vim.api.VimInjectorKt.injector;
|
|
||||||
import static java.lang.Integer.max;
|
import static java.lang.Integer.max;
|
||||||
import static java.lang.Integer.min;
|
import static java.lang.Integer.min;
|
||||||
|
|
||||||
@ -199,7 +197,7 @@ public class EditorHelper {
|
|||||||
* @param file The virtual file get the editor for
|
* @param file The virtual file get the editor for
|
||||||
* @return The matching editor or null if no match was found
|
* @return The matching editor or null if no match was found
|
||||||
*/
|
*/
|
||||||
public static @Nullable VimEditor getEditor(final @Nullable VirtualFile file) {
|
public static @Nullable Editor getEditor(final @Nullable VirtualFile file) {
|
||||||
if (file == null) {
|
if (file == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -208,7 +206,12 @@ public class EditorHelper {
|
|||||||
if (doc == null) {
|
if (doc == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return injector.getEditorGroup().getEditors(new IjVimDocument(doc)).stream().findFirst().orElse(null);
|
final List<Editor> editors = HelperKt.localEditors(doc);
|
||||||
|
if (editors.size() > 0) {
|
||||||
|
return editors.get(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static @NotNull String pad(final @NotNull Editor editor,
|
public static @NotNull String pad(final @NotNull Editor editor,
|
||||||
|
@ -17,7 +17,6 @@ import com.intellij.openapi.editor.Editor
|
|||||||
import com.intellij.openapi.editor.ex.util.EditorUtil
|
import com.intellij.openapi.editor.ex.util.EditorUtil
|
||||||
import com.intellij.openapi.fileEditor.ex.FileEditorManagerEx
|
import com.intellij.openapi.fileEditor.ex.FileEditorManagerEx
|
||||||
import com.intellij.util.ui.table.JBTableRowEditor
|
import com.intellij.util.ui.table.JBTableRowEditor
|
||||||
import com.maddyhome.idea.vim.api.StringListOptionValue
|
|
||||||
import com.maddyhome.idea.vim.api.injector
|
import com.maddyhome.idea.vim.api.injector
|
||||||
import com.maddyhome.idea.vim.group.IjOptionConstants
|
import com.maddyhome.idea.vim.group.IjOptionConstants
|
||||||
import com.maddyhome.idea.vim.newapi.globalIjOptions
|
import com.maddyhome.idea.vim.newapi.globalIjOptions
|
||||||
@ -38,27 +37,25 @@ public val Editor.fileSize: Int
|
|||||||
internal val Editor.isIdeaVimDisabledHere: Boolean
|
internal val Editor.isIdeaVimDisabledHere: Boolean
|
||||||
get() {
|
get() {
|
||||||
val ideaVimSupportValue = injector.globalIjOptions().ideavimsupport
|
val ideaVimSupportValue = injector.globalIjOptions().ideavimsupport
|
||||||
return (ideaVimDisabledInDialog(ideaVimSupportValue) && isInDialog()) ||
|
return disabledInDialog ||
|
||||||
!ClientId.isCurrentlyUnderLocalId || // CWM-927
|
(!ClientId.isCurrentlyUnderLocalId) || // CWM-927
|
||||||
(ideaVimDisabledForSingleLine(ideaVimSupportValue) && isSingleLine())
|
(!ideaVimSupportValue.contains(IjOptionConstants.ideavimsupport_singleline) && isDatabaseCell()) ||
|
||||||
|
(!ideaVimSupportValue.contains(IjOptionConstants.ideavimsupport_singleline) && isOneLineMode)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun ideaVimDisabledInDialog(ideaVimSupportValue: StringListOptionValue): Boolean {
|
private fun Editor.isDatabaseCell(): Boolean {
|
||||||
return !ideaVimSupportValue.contains(IjOptionConstants.ideavimsupport_dialog)
|
return isTableCellEditor(this.component)
|
||||||
&& !ideaVimSupportValue.contains(IjOptionConstants.ideavimsupport_dialoglegacy)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun ideaVimDisabledForSingleLine(ideaVimSupportValue: StringListOptionValue): Boolean {
|
private val Editor.disabledInDialog: Boolean
|
||||||
return !ideaVimSupportValue.contains(IjOptionConstants.ideavimsupport_singleline)
|
get() {
|
||||||
}
|
val ideaVimSupportValue = injector.globalIjOptions().ideavimsupport
|
||||||
|
return (
|
||||||
private fun Editor.isInDialog(): Boolean {
|
!ideaVimSupportValue.contains(IjOptionConstants.ideavimsupport_dialog) &&
|
||||||
return !this.isPrimaryEditor() && !EditorHelper.isFileEditor(this)
|
!ideaVimSupportValue.contains(IjOptionConstants.ideavimsupport_dialoglegacy)
|
||||||
}
|
) &&
|
||||||
|
(!this.isPrimaryEditor() && !EditorHelper.isFileEditor(this))
|
||||||
private fun Editor.isSingleLine(): Boolean {
|
}
|
||||||
return isTableCellEditor(this.component) || isOneLineMode
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if the editor is a primary editor in the main editing area.
|
* Checks if the editor is a primary editor in the main editing area.
|
||||||
|
@ -9,12 +9,19 @@
|
|||||||
package com.maddyhome.idea.vim.helper
|
package com.maddyhome.idea.vim.helper
|
||||||
|
|
||||||
import com.intellij.codeInsight.template.TemplateManager
|
import com.intellij.codeInsight.template.TemplateManager
|
||||||
|
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.Editor
|
import com.intellij.openapi.editor.Editor
|
||||||
|
import com.intellij.openapi.editor.EditorFactory
|
||||||
|
import com.intellij.openapi.project.Project
|
||||||
|
import com.intellij.openapi.util.Key
|
||||||
import com.maddyhome.idea.vim.VimPlugin
|
import com.maddyhome.idea.vim.VimPlugin
|
||||||
import com.maddyhome.idea.vim.newapi.vim
|
import com.maddyhome.idea.vim.newapi.vim
|
||||||
import com.maddyhome.idea.vim.state.mode.inBlockSelection
|
import com.maddyhome.idea.vim.state.mode.inBlockSelection
|
||||||
|
import java.util.stream.Collectors
|
||||||
|
|
||||||
internal fun <T : Comparable<T>> sort(a: T, b: T) = if (a > b) b to a else a to b
|
internal fun <T : Comparable<T>> sort(a: T, b: T) = if (a > b) b to a else a to b
|
||||||
|
|
||||||
@ -29,6 +36,34 @@ internal inline fun Editor.vimForEachCaret(action: (caret: Caret) -> Unit) {
|
|||||||
|
|
||||||
internal fun Editor.getTopLevelEditor() = if (this is EditorWindow) this.delegate else this
|
internal fun Editor.getTopLevelEditor() = if (this is EditorWindow) this.delegate else this
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return list of editors for local host (for code with me plugin)
|
||||||
|
*/
|
||||||
|
public fun localEditors(): List<Editor> {
|
||||||
|
return ClientEditorManager.getCurrentInstance().editors().collect(Collectors.toList())
|
||||||
|
}
|
||||||
|
|
||||||
|
public fun localEditors(doc: Document): List<Editor> {
|
||||||
|
return EditorFactory.getInstance().getEditors(doc)
|
||||||
|
.filter { editor -> editor.editorClientId.let { it == null || it == ClientId.currentOrNull } }
|
||||||
|
}
|
||||||
|
|
||||||
|
public fun localEditors(doc: Document, project: Project): List<Editor> {
|
||||||
|
return EditorFactory.getInstance().getEditors(doc, project)
|
||||||
|
.filter { editor -> editor.editorClientId.let { it == null || it == ClientId.currentOrNull } }
|
||||||
|
}
|
||||||
|
|
||||||
|
private val Editor.editorClientId: ClientId?
|
||||||
|
get() {
|
||||||
|
if (editorClientKey == null) {
|
||||||
|
@Suppress("DEPRECATION")
|
||||||
|
editorClientKey = Key.findKeyByName("editorClientIdby userData()") ?: return null
|
||||||
|
}
|
||||||
|
return editorClientKey?.let { this.getUserData(it) as? ClientId }
|
||||||
|
}
|
||||||
|
|
||||||
|
private var editorClientKey: Key<*>? = null
|
||||||
|
|
||||||
@Suppress("IncorrectParentDisposable")
|
@Suppress("IncorrectParentDisposable")
|
||||||
internal fun Editor.isTemplateActive(): Boolean {
|
internal fun Editor.isTemplateActive(): Boolean {
|
||||||
val project = this.project ?: return false
|
val project = this.project ?: return false
|
||||||
|
@ -90,8 +90,7 @@ internal class IjActionExecutor : VimActionExecutor {
|
|||||||
// because rider use async update method. See VIM-1819.
|
// because rider use async update method. See VIM-1819.
|
||||||
// This method executes inside of lastUpdateAndCheckDumb
|
// This method executes inside of lastUpdateAndCheckDumb
|
||||||
// Another related issue: VIM-2604
|
// Another related issue: VIM-2604
|
||||||
ijAction.beforeActionPerformedUpdate(event)
|
if (!ActionUtil.lastUpdateAndCheckDumb(ijAction, event, false)) return false
|
||||||
if (!event.presentation.isEnabled) return false
|
|
||||||
if (ijAction is ActionGroup && !event.presentation.isPerformGroup) {
|
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()
|
||||||
|
@ -34,15 +34,15 @@ internal fun Editor.exitSelectMode(adjustCaretPosition: Boolean) {
|
|||||||
val returnTo = this.vim.vimStateMachine.mode.returnTo
|
val returnTo = this.vim.vimStateMachine.mode.returnTo
|
||||||
when (returnTo) {
|
when (returnTo) {
|
||||||
ReturnTo.INSERT -> {
|
ReturnTo.INSERT -> {
|
||||||
this.vim.mode = Mode.INSERT
|
this.vim.vimStateMachine.mode = Mode.INSERT
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnTo.REPLACE -> {
|
ReturnTo.REPLACE -> {
|
||||||
this.vim.mode = Mode.REPLACE
|
this.vim.vimStateMachine.mode = Mode.REPLACE
|
||||||
}
|
}
|
||||||
|
|
||||||
null -> {
|
null -> {
|
||||||
this.vim.mode = Mode.NORMAL()
|
this.vim.vimStateMachine.mode = Mode.NORMAL()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SelectionVimListenerSuppressor.lock().use {
|
SelectionVimListenerSuppressor.lock().use {
|
||||||
@ -67,15 +67,15 @@ internal fun VimEditor.exitSelectMode(adjustCaretPosition: Boolean) {
|
|||||||
val returnTo = this.vimStateMachine.mode.returnTo
|
val returnTo = this.vimStateMachine.mode.returnTo
|
||||||
when (returnTo) {
|
when (returnTo) {
|
||||||
ReturnTo.INSERT -> {
|
ReturnTo.INSERT -> {
|
||||||
this.mode = Mode.INSERT
|
this.vimStateMachine.mode = Mode.INSERT
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnTo.REPLACE -> {
|
ReturnTo.REPLACE -> {
|
||||||
this.mode = Mode.REPLACE
|
this.vimStateMachine.mode = Mode.REPLACE
|
||||||
}
|
}
|
||||||
|
|
||||||
null -> {
|
null -> {
|
||||||
this.mode = Mode.NORMAL()
|
this.vimStateMachine.mode = Mode.NORMAL()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SelectionVimListenerSuppressor.lock().use {
|
SelectionVimListenerSuppressor.lock().use {
|
||||||
|
@ -26,13 +26,15 @@ import com.intellij.spellchecker.SpellCheckerSeveritiesProvider;
|
|||||||
import com.maddyhome.idea.vim.VimPlugin;
|
import com.maddyhome.idea.vim.VimPlugin;
|
||||||
import com.maddyhome.idea.vim.api.EngineEditorHelperKt;
|
import com.maddyhome.idea.vim.api.EngineEditorHelperKt;
|
||||||
import com.maddyhome.idea.vim.api.VimEditor;
|
import com.maddyhome.idea.vim.api.VimEditor;
|
||||||
|
import com.maddyhome.idea.vim.regexp.*;
|
||||||
|
import com.maddyhome.idea.vim.regexp.match.VimMatchResult;
|
||||||
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;
|
||||||
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.regexp.*;
|
import com.maddyhome.idea.vim.regexp.CharPointer;
|
||||||
import com.maddyhome.idea.vim.regexp.match.VimMatchResult;
|
import com.maddyhome.idea.vim.regexp.RegExp;
|
||||||
import com.maddyhome.idea.vim.state.VimStateMachine;
|
import com.maddyhome.idea.vim.state.VimStateMachine;
|
||||||
import com.maddyhome.idea.vim.state.mode.Mode;
|
import com.maddyhome.idea.vim.state.mode.Mode;
|
||||||
import it.unimi.dsi.fastutil.ints.IntComparator;
|
import it.unimi.dsi.fastutil.ints.IntComparator;
|
||||||
@ -1611,17 +1613,11 @@ public class SearchHelper {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
IntIterator offsetIterator = offsets.iterator();
|
IntIterator offsetIterator = offsets.iterator();
|
||||||
skip(offsetIterator, skipCount);
|
offsetIterator.skip(skipCount);
|
||||||
return offsetIterator.nextInt();
|
return offsetIterator.nextInt();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void skip(IntIterator iterator, final int n) {
|
|
||||||
if (n < 0) throw new IllegalArgumentException("Argument must be nonnegative: " + n);
|
|
||||||
int i = n;
|
|
||||||
while (i-- != 0 && iterator.hasNext()) iterator.nextInt();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static @NotNull String parseMatchPairsOption(final VimEditor vimEditor) {
|
private static @NotNull String parseMatchPairsOption(final VimEditor vimEditor) {
|
||||||
List<String> pairs = options(injector, vimEditor).getMatchpairs();
|
List<String> pairs = options(injector, vimEditor).getMatchpairs();
|
||||||
StringBuilder res = new StringBuilder();
|
StringBuilder res = new StringBuilder();
|
||||||
|
@ -26,7 +26,6 @@ import com.maddyhome.idea.vim.api.injector
|
|||||||
import com.maddyhome.idea.vim.api.options
|
import com.maddyhome.idea.vim.api.options
|
||||||
import com.maddyhome.idea.vim.common.TextRange
|
import com.maddyhome.idea.vim.common.TextRange
|
||||||
import com.maddyhome.idea.vim.ex.ranges.LineRange
|
import com.maddyhome.idea.vim.ex.ranges.LineRange
|
||||||
import com.maddyhome.idea.vim.newapi.IjVimDocument
|
|
||||||
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
|
||||||
import org.jetbrains.annotations.Contract
|
import org.jetbrains.annotations.Contract
|
||||||
@ -87,24 +86,11 @@ private fun updateSearchHighlights(
|
|||||||
): Int {
|
): Int {
|
||||||
var currentMatchOffset = -1
|
var currentMatchOffset = -1
|
||||||
val projectManager = ProjectManager.getInstanceIfCreated() ?: return currentMatchOffset
|
val projectManager = ProjectManager.getInstanceIfCreated() ?: return currentMatchOffset
|
||||||
|
|
||||||
// TODO: This implementation needs rethinking
|
|
||||||
// It's a bit weird that we update search highlights across all open projects. It would make more sense to treat top
|
|
||||||
// level project frame windows as separate applications, but we can't do this because IdeaVim does not maintain state
|
|
||||||
// per-project.
|
|
||||||
// So, to be clear, this will loop over each project, and therefore, for each project top-level frame, will update
|
|
||||||
// search highlights in all editors for the document of the currently selected editor. It does not update highlights
|
|
||||||
// for editors for the document that are in other projects.
|
|
||||||
|
|
||||||
for (project in projectManager.openProjects) {
|
for (project in projectManager.openProjects) {
|
||||||
val current = FileEditorManager.getInstance(project).selectedTextEditor ?: continue
|
val current = FileEditorManager.getInstance(project).selectedTextEditor ?: continue
|
||||||
val editors = injector.editorGroup.getEditors(IjVimDocument(current.document))
|
// [VERSION UPDATE] 202+ Use editors
|
||||||
for (vimEditor in editors) {
|
val editors = localEditors(current.document, project)
|
||||||
val editor = (vimEditor as IjVimEditor).editor
|
for (editor in editors) {
|
||||||
if (editor.project != project) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try to keep existing highlights if possible. Update if hlsearch has changed or if the pattern has changed.
|
// Try to keep existing highlights if possible. Update if hlsearch has changed or if the pattern has changed.
|
||||||
// Force update for the situations where the text is the same, but the ignore case values have changed.
|
// Force update for the situations where the text is the same, but the ignore case values have changed.
|
||||||
// E.g. Use `*` to search for a word (which ignores smartcase), then use `/<Up>` to search for the same pattern,
|
// E.g. Use `*` to search for a word (which ignores smartcase), then use `/<Up>` to search for the same pattern,
|
||||||
|
@ -31,8 +31,4 @@ public object StringHelper {
|
|||||||
return Arrays.stream(string).flatMap { o: String -> injector.parser.parseKeys(o).stream() }
|
return Arrays.stream(string).flatMap { o: String -> injector.parser.parseKeys(o).stream() }
|
||||||
.collect(Collectors.toList())
|
.collect(Collectors.toList())
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmStatic
|
|
||||||
@Deprecated("Use key.isCloseKeyStroke()", ReplaceWith("key.isCloseKeyStroke()"))
|
|
||||||
public fun isCloseKeyStroke(key: KeyStroke): Boolean = key.isCloseKeyStroke()
|
|
||||||
}
|
}
|
||||||
|
@ -21,13 +21,13 @@ import com.intellij.openapi.util.UserDataHolder
|
|||||||
import com.maddyhome.idea.vim.api.CaretRegisterStorageBase
|
import com.maddyhome.idea.vim.api.CaretRegisterStorageBase
|
||||||
import com.maddyhome.idea.vim.api.LocalMarkStorage
|
import com.maddyhome.idea.vim.api.LocalMarkStorage
|
||||||
import com.maddyhome.idea.vim.api.SelectionInfo
|
import com.maddyhome.idea.vim.api.SelectionInfo
|
||||||
|
import com.maddyhome.idea.vim.state.mode.Mode
|
||||||
|
import com.maddyhome.idea.vim.state.mode.SelectionType
|
||||||
|
import com.maddyhome.idea.vim.state.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
|
||||||
import com.maddyhome.idea.vim.newapi.vim
|
import com.maddyhome.idea.vim.newapi.vim
|
||||||
import com.maddyhome.idea.vim.state.VimStateMachine
|
|
||||||
import com.maddyhome.idea.vim.state.mode.Mode
|
|
||||||
import com.maddyhome.idea.vim.state.mode.SelectionType
|
|
||||||
import com.maddyhome.idea.vim.ui.ExOutputPanel
|
import com.maddyhome.idea.vim.ui.ExOutputPanel
|
||||||
import kotlin.properties.ReadWriteProperty
|
import kotlin.properties.ReadWriteProperty
|
||||||
import kotlin.reflect.KProperty
|
import kotlin.reflect.KProperty
|
||||||
@ -99,8 +99,6 @@ internal var Caret.registerStorage: CaretRegisterStorageBase? by userDataCaretTo
|
|||||||
internal var Caret.markStorage: LocalMarkStorage? by userDataCaretToEditor()
|
internal var Caret.markStorage: LocalMarkStorage? by userDataCaretToEditor()
|
||||||
internal var Caret.lastSelectionInfo: SelectionInfo? by userDataCaretToEditor()
|
internal var Caret.lastSelectionInfo: SelectionInfo? by userDataCaretToEditor()
|
||||||
|
|
||||||
internal var Editor.vimInitialised: Boolean by userDataOr { false }
|
|
||||||
|
|
||||||
// ------------------ Editor
|
// ------------------ Editor
|
||||||
internal fun unInitializeEditor(editor: Editor) {
|
internal fun unInitializeEditor(editor: Editor) {
|
||||||
editor.vimLastSelectionType = null
|
editor.vimLastSelectionType = null
|
||||||
@ -108,7 +106,6 @@ internal fun unInitializeEditor(editor: Editor) {
|
|||||||
editor.vimMorePanel = null
|
editor.vimMorePanel = null
|
||||||
editor.vimExOutput = null
|
editor.vimExOutput = null
|
||||||
editor.vimLastHighlighters = null
|
editor.vimLastHighlighters = null
|
||||||
editor.vimInitialised = false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal var Editor.vimLastSearch: String? by userData()
|
internal var Editor.vimLastSearch: String? by userData()
|
||||||
|
@ -21,6 +21,6 @@ public final class VimIcons {
|
|||||||
public static final @NotNull Icon YOUTRACK = load("/icons/youtrack.svg");
|
public static final @NotNull Icon YOUTRACK = load("/icons/youtrack.svg");
|
||||||
|
|
||||||
private static @NotNull Icon load(@NotNull @NonNls String path) {
|
private static @NotNull Icon load(@NotNull @NonNls String path) {
|
||||||
return IconManager.getInstance().getIcon(path, VimIcons.class.getClassLoader());
|
return IconManager.getInstance().getIcon(path, VimIcons.class);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,19 +9,11 @@
|
|||||||
package com.maddyhome.idea.vim.inspections
|
package com.maddyhome.idea.vim.inspections
|
||||||
|
|
||||||
import com.intellij.codeInspection.LocalInspectionTool
|
import com.intellij.codeInspection.LocalInspectionTool
|
||||||
import com.intellij.codeInspection.LocalQuickFix
|
|
||||||
import com.intellij.codeInspection.ProblemDescriptor
|
|
||||||
import com.intellij.codeInspection.ProblemsHolder
|
import com.intellij.codeInspection.ProblemsHolder
|
||||||
import com.intellij.openapi.project.Project
|
|
||||||
import com.intellij.openapi.util.TextRange
|
import com.intellij.openapi.util.TextRange
|
||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
import com.intellij.psi.PsiElementVisitor
|
import com.intellij.psi.PsiElementVisitor
|
||||||
import com.intellij.psi.impl.source.tree.LeafPsiElement
|
import com.intellij.psi.impl.source.tree.LeafPsiElement
|
||||||
import com.intellij.psi.util.PsiEditorUtil
|
|
||||||
import com.maddyhome.idea.vim.extension.ExtensionBeanClass
|
|
||||||
import com.maddyhome.idea.vim.extension.VimExtension
|
|
||||||
import com.maddyhome.idea.vim.vimscript.model.commands.SetCommand
|
|
||||||
import com.maddyhome.idea.vim.vimscript.parser.VimscriptParser
|
|
||||||
|
|
||||||
internal class UsePlugSyntaxInspection : LocalInspectionTool() {
|
internal class UsePlugSyntaxInspection : LocalInspectionTool() {
|
||||||
override fun getGroupDisplayName(): String {
|
override fun getGroupDisplayName(): String {
|
||||||
@ -31,54 +23,11 @@ internal class UsePlugSyntaxInspection : LocalInspectionTool() {
|
|||||||
override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor {
|
override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor {
|
||||||
val file = holder.file
|
val file = holder.file
|
||||||
if (file.name != ".ideavimrc" && file.name != "_ideavimrc") return PsiElementVisitor.EMPTY_VISITOR
|
if (file.name != ".ideavimrc" && file.name != "_ideavimrc") return PsiElementVisitor.EMPTY_VISITOR
|
||||||
val plugins = buildPlugins()
|
|
||||||
return object : PsiElementVisitor() {
|
return object : PsiElementVisitor() {
|
||||||
override fun visitElement(element: PsiElement) {
|
override fun visitElement(element: PsiElement) {
|
||||||
if (element !is LeafPsiElement) return
|
if (element !is LeafPsiElement) return
|
||||||
val myScript = VimscriptParser.parse(element.text)
|
holder.registerProblem(element, TextRange.create(10, 20), "Hi there")
|
||||||
myScript.units.forEach { unit ->
|
|
||||||
if (unit is SetCommand) {
|
|
||||||
val argument = unit.argument
|
|
||||||
val alias = plugins[argument]
|
|
||||||
if (alias != null) {
|
|
||||||
holder.registerProblem(
|
|
||||||
element,
|
|
||||||
unit.rangeInScript.let { TextRange(it.startOffset, it.endOffset - 1) },
|
|
||||||
"""
|
|
||||||
Use `Plug` syntax for defining extensions
|
|
||||||
""".trimIndent(),
|
|
||||||
object : LocalQuickFix {
|
|
||||||
override fun getFamilyName(): String {
|
|
||||||
return "Use Plug syntax"
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun applyFix(p0: Project, p1: ProblemDescriptor) {
|
|
||||||
val editor = PsiEditorUtil.findEditor(file)
|
|
||||||
editor?.document?.replaceString(
|
|
||||||
unit.rangeInScript.startOffset,
|
|
||||||
unit.rangeInScript.endOffset - 1,
|
|
||||||
"Plug '$alias'"
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun buildPlugins(): HashMap<String, String> {
|
|
||||||
val res = HashMap<String, String>()
|
|
||||||
VimExtension.EP_NAME.extensions.forEach { extension: ExtensionBeanClass ->
|
|
||||||
val alias = extension.aliases?.first { it.name?.count { it == '/' } == 1 }?.name
|
|
||||||
?: extension.aliases?.firstOrNull()?.name
|
|
||||||
val name = extension.name
|
|
||||||
if (alias != null && name != null) {
|
|
||||||
res[name] = alias
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return res
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
package com.maddyhome.idea.vim.listener
|
package com.maddyhome.idea.vim.listener
|
||||||
|
|
||||||
import com.intellij.openapi.application.ApplicationManager
|
import com.intellij.openapi.components.ServiceManager
|
||||||
import com.intellij.openapi.editor.Editor
|
import com.intellij.openapi.editor.Editor
|
||||||
import org.acejump.session.SessionManager
|
import org.acejump.session.SessionManager
|
||||||
|
|
||||||
@ -16,11 +16,12 @@ import org.acejump.session.SessionManager
|
|||||||
* Key handling for IdeaVim should be updated to editorHandler usage. In this case this class can be safely removed.
|
* Key handling for IdeaVim should be updated to editorHandler usage. In this case this class can be safely removed.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@Suppress("DEPRECATION")
|
||||||
internal interface AceJumpService {
|
internal interface AceJumpService {
|
||||||
fun isActive(editor: Editor): Boolean
|
fun isActive(editor: Editor): Boolean
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun getInstance(): AceJumpService? = ApplicationManager.getApplication().getService(AceJumpService::class.java)
|
fun getInstance(): AceJumpService? = ServiceManager.getService(AceJumpService::class.java)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,7 +77,7 @@ internal object IdeaSpecifics {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hostEditor != null && action is ChooseItemAction && injector.registerGroup.isRecording) {
|
if (hostEditor != null && action is ChooseItemAction && hostEditor.vimStateMachine?.isRecording == true) {
|
||||||
val lookup = LookupManager.getActiveLookup(hostEditor)
|
val lookup = LookupManager.getActiveLookup(hostEditor)
|
||||||
if (lookup != null) {
|
if (lookup != null) {
|
||||||
val charsToRemove = hostEditor.caretModel.primaryCaret.offset - lookup.lookupStart
|
val charsToRemove = hostEditor.caretModel.primaryCaret.offset - lookup.lookupStart
|
||||||
@ -99,7 +99,7 @@ internal object IdeaSpecifics {
|
|||||||
|
|
||||||
val editor = editor
|
val editor = editor
|
||||||
if (editor != null) {
|
if (editor != null) {
|
||||||
if (action is ChooseItemAction && injector.registerGroup.isRecording) {
|
if (action is ChooseItemAction && editor.vimStateMachine?.isRecording == true) {
|
||||||
val prevDocumentLength = completionPrevDocumentLength
|
val prevDocumentLength = completionPrevDocumentLength
|
||||||
val prevDocumentOffset = completionPrevDocumentOffset
|
val prevDocumentOffset = completionPrevDocumentOffset
|
||||||
|
|
||||||
@ -126,12 +126,10 @@ internal object IdeaSpecifics {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
editor?.let {
|
val commandState = editor.vim.vimStateMachine
|
||||||
val commandState = it.vim.vimStateMachine
|
commandState.mode = Mode.NORMAL()
|
||||||
it.vim.mode = Mode.NORMAL()
|
VimPlugin.getChange().insertBeforeCursor(editor.vim, event.dataContext.vim)
|
||||||
VimPlugin.getChange().insertBeforeCursor(it.vim, event.dataContext.vim)
|
KeyHandler.getInstance().reset(editor.vim)
|
||||||
KeyHandler.getInstance().reset(it.vim)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
//endregion
|
//endregion
|
||||||
|
|
||||||
|
@ -8,7 +8,6 @@
|
|||||||
|
|
||||||
package com.maddyhome.idea.vim.listener
|
package com.maddyhome.idea.vim.listener
|
||||||
|
|
||||||
import com.intellij.codeWithMe.ClientId
|
|
||||||
import com.intellij.ide.ui.UISettings
|
import com.intellij.ide.ui.UISettings
|
||||||
import com.intellij.openapi.Disposable
|
import com.intellij.openapi.Disposable
|
||||||
import com.intellij.openapi.application.ApplicationManager
|
import com.intellij.openapi.application.ApplicationManager
|
||||||
@ -21,8 +20,6 @@ import com.intellij.openapi.editor.EditorKind
|
|||||||
import com.intellij.openapi.editor.actionSystem.TypedAction
|
import com.intellij.openapi.editor.actionSystem.TypedAction
|
||||||
import com.intellij.openapi.editor.event.CaretEvent
|
import com.intellij.openapi.editor.event.CaretEvent
|
||||||
import com.intellij.openapi.editor.event.CaretListener
|
import com.intellij.openapi.editor.event.CaretListener
|
||||||
import com.intellij.openapi.editor.event.DocumentEvent
|
|
||||||
import com.intellij.openapi.editor.event.DocumentListener
|
|
||||||
import com.intellij.openapi.editor.event.EditorFactoryEvent
|
import com.intellij.openapi.editor.event.EditorFactoryEvent
|
||||||
import com.intellij.openapi.editor.event.EditorFactoryListener
|
import com.intellij.openapi.editor.event.EditorFactoryListener
|
||||||
import com.intellij.openapi.editor.event.EditorMouseEvent
|
import com.intellij.openapi.editor.event.EditorMouseEvent
|
||||||
@ -52,7 +49,6 @@ import com.intellij.openapi.vfs.VirtualFile
|
|||||||
import com.intellij.util.ExceptionUtil
|
import com.intellij.util.ExceptionUtil
|
||||||
import com.maddyhome.idea.vim.EventFacade
|
import com.maddyhome.idea.vim.EventFacade
|
||||||
import com.maddyhome.idea.vim.KeyHandler
|
import com.maddyhome.idea.vim.KeyHandler
|
||||||
import com.maddyhome.idea.vim.KeyHandlerStateResetter
|
|
||||||
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
|
||||||
@ -66,17 +62,15 @@ import com.maddyhome.idea.vim.api.injector
|
|||||||
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
|
||||||
|
import com.maddyhome.idea.vim.group.IjOptions
|
||||||
import com.maddyhome.idea.vim.group.MotionGroup
|
import com.maddyhome.idea.vim.group.MotionGroup
|
||||||
import com.maddyhome.idea.vim.group.OptionGroup
|
import com.maddyhome.idea.vim.group.OptionGroup
|
||||||
import com.maddyhome.idea.vim.group.ScrollGroup
|
import com.maddyhome.idea.vim.group.ScrollGroup
|
||||||
import com.maddyhome.idea.vim.group.SearchGroup
|
|
||||||
import com.maddyhome.idea.vim.group.VimMarkServiceImpl
|
|
||||||
import com.maddyhome.idea.vim.group.visual.IdeaSelectionControl
|
import com.maddyhome.idea.vim.group.visual.IdeaSelectionControl
|
||||||
import com.maddyhome.idea.vim.group.visual.VimVisualTimer
|
import com.maddyhome.idea.vim.group.visual.VimVisualTimer
|
||||||
import com.maddyhome.idea.vim.group.visual.moveCaretOneCharLeftFromSelectionEnd
|
import com.maddyhome.idea.vim.group.visual.moveCaretOneCharLeftFromSelectionEnd
|
||||||
import com.maddyhome.idea.vim.handler.correctorRequester
|
import com.maddyhome.idea.vim.handler.correctorRequester
|
||||||
import com.maddyhome.idea.vim.handler.keyCheckRequests
|
import com.maddyhome.idea.vim.handler.keyCheckRequests
|
||||||
import com.maddyhome.idea.vim.helper.CaretVisualAttributesListener
|
|
||||||
import com.maddyhome.idea.vim.helper.GuicursorChangeListener
|
import com.maddyhome.idea.vim.helper.GuicursorChangeListener
|
||||||
import com.maddyhome.idea.vim.helper.StrictMode
|
import com.maddyhome.idea.vim.helper.StrictMode
|
||||||
import com.maddyhome.idea.vim.helper.exitSelectMode
|
import com.maddyhome.idea.vim.helper.exitSelectMode
|
||||||
@ -84,23 +78,25 @@ import com.maddyhome.idea.vim.helper.exitVisualMode
|
|||||||
import com.maddyhome.idea.vim.helper.forceBarCursor
|
import com.maddyhome.idea.vim.helper.forceBarCursor
|
||||||
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.isIdeaVimDisabledHere
|
||||||
|
import com.maddyhome.idea.vim.helper.localEditors
|
||||||
import com.maddyhome.idea.vim.helper.moveToInlayAwareOffset
|
import com.maddyhome.idea.vim.helper.moveToInlayAwareOffset
|
||||||
import com.maddyhome.idea.vim.helper.resetVimLastColumn
|
import com.maddyhome.idea.vim.helper.resetVimLastColumn
|
||||||
import com.maddyhome.idea.vim.helper.updateCaretsVisualAttributes
|
import com.maddyhome.idea.vim.helper.updateCaretsVisualAttributes
|
||||||
import com.maddyhome.idea.vim.helper.vimDisabled
|
import com.maddyhome.idea.vim.helper.vimDisabled
|
||||||
|
import com.maddyhome.idea.vim.listener.MouseEventsDataHolder.skipEvents
|
||||||
|
import com.maddyhome.idea.vim.listener.MouseEventsDataHolder.skipNDragEvents
|
||||||
|
import com.maddyhome.idea.vim.listener.VimListenerManager.EditorListeners.add
|
||||||
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.vim
|
import com.maddyhome.idea.vim.newapi.vim
|
||||||
import com.maddyhome.idea.vim.state.VimStateMachine
|
import com.maddyhome.idea.vim.state.VimStateMachine
|
||||||
import com.maddyhome.idea.vim.state.mode.Mode
|
import com.maddyhome.idea.vim.state.mode.Mode
|
||||||
import com.maddyhome.idea.vim.state.mode.inSelectMode
|
import com.maddyhome.idea.vim.state.mode.inSelectMode
|
||||||
|
import com.maddyhome.idea.vim.state.mode.mode
|
||||||
import com.maddyhome.idea.vim.state.mode.selectionType
|
import com.maddyhome.idea.vim.state.mode.selectionType
|
||||||
import com.maddyhome.idea.vim.ui.ShowCmdOptionChangeListener
|
import com.maddyhome.idea.vim.ui.ShowCmdOptionChangeListener
|
||||||
import com.maddyhome.idea.vim.ui.ShowCmdWidgetUpdater
|
|
||||||
import com.maddyhome.idea.vim.ui.ex.ExEntryPanel
|
import com.maddyhome.idea.vim.ui.ex.ExEntryPanel
|
||||||
import com.maddyhome.idea.vim.ui.widgets.macro.MacroWidgetListener
|
|
||||||
import com.maddyhome.idea.vim.ui.widgets.macro.macroWidgetOptionListener
|
import com.maddyhome.idea.vim.ui.widgets.macro.macroWidgetOptionListener
|
||||||
import com.maddyhome.idea.vim.ui.widgets.mode.listeners.ModeWidgetListener
|
|
||||||
import com.maddyhome.idea.vim.ui.widgets.mode.modeWidgetOptionListener
|
import com.maddyhome.idea.vim.ui.widgets.mode.modeWidgetOptionListener
|
||||||
import com.maddyhome.idea.vim.vimDisposable
|
import com.maddyhome.idea.vim.vimDisposable
|
||||||
import java.awt.event.MouseAdapter
|
import java.awt.event.MouseAdapter
|
||||||
@ -132,7 +128,6 @@ private fun getOpeningEditor(newEditor: Editor) = newEditor.project?.let { proje
|
|||||||
internal object VimListenerManager {
|
internal object VimListenerManager {
|
||||||
|
|
||||||
private val logger = Logger.getInstance(VimListenerManager::class.java)
|
private val logger = Logger.getInstance(VimListenerManager::class.java)
|
||||||
private val editorListenersDisposableKey = Key.create<Disposable>("IdeaVim listeners disposable")
|
|
||||||
private var firstEditorInitialised = false
|
private var firstEditorInitialised = false
|
||||||
|
|
||||||
fun turnOn() {
|
fun turnOn() {
|
||||||
@ -140,30 +135,11 @@ internal object VimListenerManager {
|
|||||||
EditorListeners.addAll()
|
EditorListeners.addAll()
|
||||||
check(correctorRequester.tryEmit(Unit))
|
check(correctorRequester.tryEmit(Unit))
|
||||||
check(keyCheckRequests.tryEmit(Unit))
|
check(keyCheckRequests.tryEmit(Unit))
|
||||||
|
|
||||||
val caretVisualAttributesListener = CaretVisualAttributesListener()
|
|
||||||
injector.listenersNotifier.modeChangeListeners.add(caretVisualAttributesListener)
|
|
||||||
injector.listenersNotifier.isReplaceCharListeners.add(caretVisualAttributesListener)
|
|
||||||
caretVisualAttributesListener.updateAllEditorsCaretsVisual()
|
|
||||||
|
|
||||||
val modeWidgetListener = ModeWidgetListener()
|
|
||||||
injector.listenersNotifier.modeChangeListeners.add(modeWidgetListener)
|
|
||||||
injector.listenersNotifier.myEditorListeners.add(modeWidgetListener)
|
|
||||||
injector.listenersNotifier.vimPluginListeners.add(modeWidgetListener)
|
|
||||||
|
|
||||||
val macroWidgetListener = MacroWidgetListener()
|
|
||||||
injector.listenersNotifier.macroRecordingListeners.add(macroWidgetListener)
|
|
||||||
injector.listenersNotifier.vimPluginListeners.add(macroWidgetListener)
|
|
||||||
|
|
||||||
injector.listenersNotifier.myEditorListeners.add(KeyHandlerStateResetter())
|
|
||||||
injector.listenersNotifier.myEditorListeners.add(ShowCmdWidgetUpdater())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun turnOff() {
|
fun turnOff() {
|
||||||
GlobalListeners.disable()
|
GlobalListeners.disable()
|
||||||
EditorListeners.removeAll()
|
EditorListeners.removeAll()
|
||||||
injector.listenersNotifier.reset()
|
|
||||||
|
|
||||||
check(correctorRequester.tryEmit(Unit))
|
check(correctorRequester.tryEmit(Unit))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -181,29 +157,23 @@ internal object VimListenerManager {
|
|||||||
optionGroup.addEffectiveOptionValueChangeListener(Options.number, EditorGroup.NumberChangeListener.INSTANCE)
|
optionGroup.addEffectiveOptionValueChangeListener(Options.number, EditorGroup.NumberChangeListener.INSTANCE)
|
||||||
optionGroup.addEffectiveOptionValueChangeListener(Options.relativenumber, EditorGroup.NumberChangeListener.INSTANCE)
|
optionGroup.addEffectiveOptionValueChangeListener(Options.relativenumber, EditorGroup.NumberChangeListener.INSTANCE)
|
||||||
optionGroup.addEffectiveOptionValueChangeListener(Options.scrolloff, ScrollGroup.ScrollOptionsChangeListener)
|
optionGroup.addEffectiveOptionValueChangeListener(Options.scrolloff, ScrollGroup.ScrollOptionsChangeListener)
|
||||||
optionGroup.addEffectiveOptionValueChangeListener(Options.guicursor, GuicursorChangeListener)
|
|
||||||
optionGroup.addGlobalOptionChangeListener(Options.showcmd, ShowCmdOptionChangeListener)
|
optionGroup.addGlobalOptionChangeListener(Options.showcmd, ShowCmdOptionChangeListener)
|
||||||
|
|
||||||
// This code is executed after ideavimrc execution, so we trigger onGlobalOptionChanged just in case
|
// This code is executed after ideavimrc execution, so we trigger onGlobalOptionChanged just in case
|
||||||
optionGroup.addGlobalOptionChangeListener(Options.showmode, modeWidgetOptionListener)
|
optionGroup.addGlobalOptionChangeListener(IjOptions.showmodewidget, modeWidgetOptionListener)
|
||||||
optionGroup.addGlobalOptionChangeListener(Options.showmode, macroWidgetOptionListener)
|
optionGroup.addGlobalOptionChangeListener(IjOptions.showmodewidget, macroWidgetOptionListener)
|
||||||
modeWidgetOptionListener.onGlobalOptionChanged()
|
modeWidgetOptionListener.onGlobalOptionChanged()
|
||||||
macroWidgetOptionListener.onGlobalOptionChanged()
|
macroWidgetOptionListener.onGlobalOptionChanged()
|
||||||
|
|
||||||
// Listen for and initialise new editors
|
optionGroup.addEffectiveOptionValueChangeListener(Options.guicursor, GuicursorChangeListener)
|
||||||
|
|
||||||
EventFacade.getInstance().addEditorFactoryListener(VimEditorFactoryListener, VimPlugin.getInstance().onOffDisposable)
|
EventFacade.getInstance().addEditorFactoryListener(VimEditorFactoryListener, VimPlugin.getInstance().onOffDisposable)
|
||||||
val busConnection = ApplicationManager.getApplication().messageBus.connect(VimPlugin.getInstance().onOffDisposable)
|
val busConnection = ApplicationManager.getApplication().messageBus.connect(VimPlugin.getInstance().onOffDisposable)
|
||||||
busConnection.subscribe(FileOpenedSyncListener.TOPIC, VimEditorFactoryListener)
|
busConnection.subscribe(FileOpenedSyncListener.TOPIC, VimEditorFactoryListener)
|
||||||
|
|
||||||
// Listen for focus change to update various features such as mode widget
|
EditorFactory.getInstance().eventMulticaster.addCaretListener(VimCaretListener, VimPlugin.getInstance().onOffDisposable)
|
||||||
val eventMulticaster = EditorFactory.getInstance().eventMulticaster
|
val eventMulticaster = EditorFactory.getInstance().eventMulticaster as? EditorEventMulticasterEx
|
||||||
(eventMulticaster as? EditorEventMulticasterEx)?.addFocusChangeListener(
|
eventMulticaster?.addFocusChangeListener(VimFocusListener, VimPlugin.getInstance().onOffDisposable)
|
||||||
VimFocusListener,
|
|
||||||
VimPlugin.getInstance().onOffDisposable
|
|
||||||
)
|
|
||||||
|
|
||||||
// Listen for document changes to update document state such as marks
|
|
||||||
eventMulticaster.addDocumentListener(VimDocumentListener, VimPlugin.getInstance().onOffDisposable)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun disable() {
|
fun disable() {
|
||||||
@ -214,8 +184,8 @@ internal object VimListenerManager {
|
|||||||
optionGroup.removeEffectiveOptionValueChangeListener(Options.relativenumber, EditorGroup.NumberChangeListener.INSTANCE)
|
optionGroup.removeEffectiveOptionValueChangeListener(Options.relativenumber, EditorGroup.NumberChangeListener.INSTANCE)
|
||||||
optionGroup.removeEffectiveOptionValueChangeListener(Options.scrolloff, ScrollGroup.ScrollOptionsChangeListener)
|
optionGroup.removeEffectiveOptionValueChangeListener(Options.scrolloff, ScrollGroup.ScrollOptionsChangeListener)
|
||||||
optionGroup.removeGlobalOptionChangeListener(Options.showcmd, ShowCmdOptionChangeListener)
|
optionGroup.removeGlobalOptionChangeListener(Options.showcmd, ShowCmdOptionChangeListener)
|
||||||
optionGroup.removeGlobalOptionChangeListener(Options.showmode, modeWidgetOptionListener)
|
optionGroup.removeGlobalOptionChangeListener(IjOptions.showmodewidget, modeWidgetOptionListener)
|
||||||
optionGroup.removeGlobalOptionChangeListener(Options.showmode, macroWidgetOptionListener)
|
optionGroup.removeGlobalOptionChangeListener(IjOptions.showmodewidget, macroWidgetOptionListener)
|
||||||
optionGroup.removeEffectiveOptionValueChangeListener(Options.guicursor, GuicursorChangeListener)
|
optionGroup.removeEffectiveOptionValueChangeListener(Options.guicursor, GuicursorChangeListener)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -244,9 +214,7 @@ internal object VimListenerManager {
|
|||||||
|
|
||||||
// We could have a split window in this list, but since they're all being initialised from the same opening editor
|
// We could have a split window in this list, but since they're all being initialised from the same opening editor
|
||||||
// there's no need to use the SPLIT scenario
|
// there's no need to use the SPLIT scenario
|
||||||
// Make sure we get all editors, including uninitialised
|
localEditors().forEach { editor ->
|
||||||
injector.editorGroup.getEditorsRaw().forEach { vimEditor ->
|
|
||||||
val editor = vimEditor.ij
|
|
||||||
if (!initialisedEditors.contains(editor)) {
|
if (!initialisedEditors.contains(editor)) {
|
||||||
add(editor, getOpeningEditor(editor)?.vim ?: injector.fallbackWindow, LocalOptionInitialisationScenario.NEW)
|
add(editor, getOpeningEditor(editor)?.vim ?: injector.fallbackWindow, LocalOptionInitialisationScenario.NEW)
|
||||||
}
|
}
|
||||||
@ -254,26 +222,18 @@ internal object VimListenerManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun removeAll() {
|
fun removeAll() {
|
||||||
injector.editorGroup.getEditors().forEach { editor ->
|
localEditors().forEach { editor ->
|
||||||
remove(editor.ij)
|
remove(editor, false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun add(editor: Editor, openingEditor: VimEditor, scenario: LocalOptionInitialisationScenario) {
|
fun add(editor: Editor, openingEditor: VimEditor, scenario: LocalOptionInitialisationScenario) {
|
||||||
// We shouldn't be called with anything other than local editors, but let's just be sure. This will prevent any
|
|
||||||
// unsupported editor from incorrectly being initialised.
|
|
||||||
// TODO: If the user changes the 'ideavimsupport' option, existing editors won't be initialised
|
|
||||||
if (vimDisabled(editor)) return
|
|
||||||
|
|
||||||
// As I understand, there is no need to pass a disposable that also disposes on editor close
|
// As I understand, there is no need to pass a disposable that also disposes on editor close
|
||||||
// because all editor resources will be garbage collected anyway on editor close
|
// because all editor resources will be garbage collected anyway on editor close
|
||||||
// Note that this uses the plugin's main disposable, rather than VimPlugin.onOffDisposable, because we don't need
|
|
||||||
// to - we explicitly call VimListenerManager.removeAll from VimPlugin.turnOffPlugin, and this disposes each
|
|
||||||
// editor's disposable individually.
|
|
||||||
val disposable = editor.project?.vimDisposable ?: return
|
val disposable = editor.project?.vimDisposable ?: return
|
||||||
|
|
||||||
val listenersDisposable = Disposer.newDisposable(disposable)
|
val listenersDisposable = Disposer.newDisposable(disposable)
|
||||||
editor.putUserData(editorListenersDisposableKey, listenersDisposable)
|
editor.putUserData(editorListenersDisposable, listenersDisposable)
|
||||||
|
|
||||||
Disposer.register(listenersDisposable) {
|
Disposer.register(listenersDisposable) {
|
||||||
if (VimListenerTestObject.enabled) {
|
if (VimListenerTestObject.enabled) {
|
||||||
@ -296,69 +256,54 @@ internal object VimListenerManager {
|
|||||||
eventFacade.addCaretListener(editor, EditorCaretHandler, listenersDisposable)
|
eventFacade.addCaretListener(editor, EditorCaretHandler, listenersDisposable)
|
||||||
|
|
||||||
VimPlugin.getEditor().editorCreated(editor)
|
VimPlugin.getEditor().editorCreated(editor)
|
||||||
|
|
||||||
VimPlugin.getChange().editorCreated(editor, listenersDisposable)
|
VimPlugin.getChange().editorCreated(editor, listenersDisposable)
|
||||||
|
|
||||||
injector.listenersNotifier.notifyEditorCreated(vimEditor)
|
injector.listenersNotifier.notifyEditorCreated(vimEditor)
|
||||||
|
|
||||||
Disposer.register(listenersDisposable) {
|
Disposer.register(listenersDisposable) {
|
||||||
VimPlugin.getEditor().editorDeinit(editor, true)
|
VimPlugin.getEditorIfCreated()?.editorDeinit(editor, true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun remove(editor: Editor) {
|
fun remove(editor: Editor, isReleased: Boolean) {
|
||||||
val editorDisposable = editor.removeUserData(editorListenersDisposableKey)
|
val editorDisposable = editor.getUserData(editorListenersDisposable)
|
||||||
if (editorDisposable != null) {
|
if (editorDisposable != null) {
|
||||||
Disposer.dispose(editorDisposable)
|
Disposer.dispose(editorDisposable)
|
||||||
}
|
}
|
||||||
else {
|
else StrictMode.fail("Editor doesn't have disposable attached. $editor")
|
||||||
// We definitely do not expect this to happen
|
|
||||||
StrictMode.fail("Editor doesn't have disposable attached. $editor")
|
VimPlugin.getEditorIfCreated()?.editorDeinit(editor, isReleased)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Notifies other IdeaVim components of focus gain/loss, e.g. the mode widget. This will be called with non-local Code
|
|
||||||
* With Me editors.
|
|
||||||
*/
|
|
||||||
private object VimFocusListener : FocusChangeListener {
|
private object VimFocusListener : FocusChangeListener {
|
||||||
override fun focusGained(editor: Editor) {
|
override fun focusGained(editor: Editor) {
|
||||||
if (vimDisabled(editor)) return
|
|
||||||
injector.listenersNotifier.notifyEditorFocusGained(editor.vim)
|
injector.listenersNotifier.notifyEditorFocusGained(editor.vim)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun focusLost(editor: Editor) {
|
override fun focusLost(editor: Editor) {
|
||||||
if (vimDisabled(editor)) return
|
|
||||||
injector.listenersNotifier.notifyEditorFocusLost(editor.vim)
|
injector.listenersNotifier.notifyEditorFocusLost(editor.vim)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
val editorListenersDisposable = Key.create<Disposable>("IdeaVim listeners disposable")
|
||||||
* Notifies other IdeaVim components of document changes. This will be called for all documents, even those only
|
|
||||||
* open in non-local Code With Me guest editors, which we still want to process (e.g. to update marks when a guest
|
object VimCaretListener : CaretListener {
|
||||||
* edits a file. Updating search highlights will be a no-op if there are no open local editors)
|
override fun caretAdded(event: CaretEvent) {
|
||||||
*/
|
if (vimDisabled(event.editor)) return
|
||||||
private object VimDocumentListener : DocumentListener {
|
event.editor.updateCaretsVisualAttributes()
|
||||||
override fun beforeDocumentChange(event: DocumentEvent) {
|
|
||||||
VimMarkServiceImpl.MarkUpdater.beforeDocumentChange(event)
|
|
||||||
SearchGroup.DocumentSearchListener.INSTANCE.beforeDocumentChange(event)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun documentChanged(event: DocumentEvent) {
|
override fun caretRemoved(event: CaretEvent) {
|
||||||
VimMarkServiceImpl.MarkUpdater.documentChanged(event)
|
if (vimDisabled(event.editor)) return
|
||||||
SearchGroup.DocumentSearchListener.INSTANCE.documentChanged(event)
|
event.editor.updateCaretsVisualAttributes()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when the selected file editor changes. In other words, when the user selects a new tab. Used to remember the
|
|
||||||
* last selected file, update search highlights in the new tab, etc. This will be called with non-local Code With Me
|
|
||||||
* guest editors.
|
|
||||||
*/
|
|
||||||
class VimFileEditorManagerListener : FileEditorManagerListener {
|
class VimFileEditorManagerListener : FileEditorManagerListener {
|
||||||
override fun selectionChanged(event: FileEditorManagerEvent) {
|
override fun selectionChanged(event: FileEditorManagerEvent) {
|
||||||
// We can't rely on being passed a non-null editor, so check for Code With Me scenarios explicitly
|
if (VimPlugin.isNotEnabled()) return
|
||||||
if (VimPlugin.isNotEnabled() || !ClientId.isCurrentlyUnderLocalId) return
|
|
||||||
|
|
||||||
val newEditor = event.newEditor
|
val newEditor = event.newEditor
|
||||||
if (newEditor is TextEditor) {
|
if (newEditor is TextEditor) {
|
||||||
@ -376,10 +321,6 @@ internal object VimListenerManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Listen to editor creation events in order to initialise IdeaVim compatible editors. This listener is called for all
|
|
||||||
* editors, including non-local hidden Code With Me editors.
|
|
||||||
*/
|
|
||||||
private object VimEditorFactoryListener : EditorFactoryListener, FileOpenedSyncListener {
|
private object VimEditorFactoryListener : EditorFactoryListener, FileOpenedSyncListener {
|
||||||
private data class OpeningEditor(
|
private data class OpeningEditor(
|
||||||
val editor: Editor,
|
val editor: Editor,
|
||||||
@ -391,8 +332,6 @@ internal object VimListenerManager {
|
|||||||
private val openingEditorKey: Key<OpeningEditor> = Key("IdeaVim::OpeningEditor")
|
private val openingEditorKey: Key<OpeningEditor> = Key("IdeaVim::OpeningEditor")
|
||||||
|
|
||||||
override fun editorCreated(event: EditorFactoryEvent) {
|
override fun editorCreated(event: EditorFactoryEvent) {
|
||||||
if (vimDisabled(event.editor)) return
|
|
||||||
|
|
||||||
// This callback is called when an editor is created, but we cannot completely rely on it to initialise options.
|
// This callback is called when an editor is created, but we cannot completely rely on it to initialise options.
|
||||||
// We can find the currently selected editor, which we can use as the opening editor, and we're given the new
|
// We can find the currently selected editor, which we can use as the opening editor, and we're given the new
|
||||||
// editor, but we don't know enough about it - this function is called before the new editor is added to an
|
// editor, but we don't know enough about it - this function is called before the new editor is added to an
|
||||||
@ -413,7 +352,7 @@ internal object VimListenerManager {
|
|||||||
openingEditor == null -> LocalOptionInitialisationScenario.EDIT
|
openingEditor == null -> LocalOptionInitialisationScenario.EDIT
|
||||||
else -> LocalOptionInitialisationScenario.NEW
|
else -> LocalOptionInitialisationScenario.NEW
|
||||||
}
|
}
|
||||||
EditorListeners.add(event.editor, openingEditor?.vim ?: injector.fallbackWindow, scenario)
|
add(event.editor, openingEditor?.vim ?: injector.fallbackWindow, scenario)
|
||||||
firstEditorInitialised = true
|
firstEditorInitialised = true
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -442,7 +381,6 @@ internal object VimListenerManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun editorReleased(event: EditorFactoryEvent) {
|
override fun editorReleased(event: EditorFactoryEvent) {
|
||||||
if (vimDisabled(event.editor)) return
|
|
||||||
val vimEditor = event.editor.vim
|
val vimEditor = event.editor.vim
|
||||||
injector.listenersNotifier.notifyEditorReleased(vimEditor)
|
injector.listenersNotifier.notifyEditorReleased(vimEditor)
|
||||||
injector.markService.editorReleased(vimEditor)
|
injector.markService.editorReleased(vimEditor)
|
||||||
@ -466,8 +404,6 @@ internal object VimListenerManager {
|
|||||||
// editor is modified
|
// editor is modified
|
||||||
editorsWithProviders.forEach {
|
editorsWithProviders.forEach {
|
||||||
(it.fileEditor as? TextEditor)?.editor?.let { editor ->
|
(it.fileEditor as? TextEditor)?.editor?.let { editor ->
|
||||||
if (vimDisabled(editor)) return@let
|
|
||||||
|
|
||||||
val openingEditor = editor.removeUserData(openingEditorKey)
|
val openingEditor = editor.removeUserData(openingEditorKey)
|
||||||
val owningEditorWindow = getOwningEditorWindow(editor)
|
val owningEditorWindow = getOwningEditorWindow(editor)
|
||||||
val isInSameSplit = owningEditorWindow == openingEditor?.owningEditorWindow
|
val isInSameSplit = owningEditorWindow == openingEditor?.owningEditorWindow
|
||||||
@ -488,7 +424,7 @@ internal object VimListenerManager {
|
|||||||
(openingEditor.canBeReused || openingEditor.isPreview) && isInSameSplit && openingEditorIsClosed -> LocalOptionInitialisationScenario.EDIT
|
(openingEditor.canBeReused || openingEditor.isPreview) && isInSameSplit && openingEditorIsClosed -> LocalOptionInitialisationScenario.EDIT
|
||||||
else -> LocalOptionInitialisationScenario.NEW
|
else -> LocalOptionInitialisationScenario.NEW
|
||||||
}
|
}
|
||||||
EditorListeners.add(editor, openingEditor?.editor?.vim ?: injector.fallbackWindow, scenario)
|
add(editor, openingEditor?.editor?.vim ?: injector.fallbackWindow, scenario)
|
||||||
firstEditorInitialised = true
|
firstEditorInitialised = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -503,16 +439,12 @@ internal object VimListenerManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Callback for when an editor's text selection changes. Only registered for editors that we're interested in (so only
|
|
||||||
* local editors). Fixes incorrect mouse selection at end of line, and synchronises selections across other editors.
|
|
||||||
*/
|
|
||||||
private object EditorSelectionHandler : SelectionListener {
|
private object EditorSelectionHandler : SelectionListener {
|
||||||
/**
|
/**
|
||||||
* This event is executed for each caret using [com.intellij.openapi.editor.CaretModel.runForEachCaret]
|
* This event is executed for each caret using [com.intellij.openapi.editor.CaretModel.runForEachCaret]
|
||||||
*/
|
*/
|
||||||
override fun selectionChanged(selectionEvent: SelectionEvent) {
|
override fun selectionChanged(selectionEvent: SelectionEvent) {
|
||||||
|
if (selectionEvent.editor.isIdeaVimDisabledHere) return
|
||||||
VimVisualTimer.drop()
|
VimVisualTimer.drop()
|
||||||
val editor = selectionEvent.editor
|
val editor = selectionEvent.editor
|
||||||
val document = editor.document
|
val document = editor.document
|
||||||
@ -532,9 +464,7 @@ internal object VimListenerManager {
|
|||||||
val startOffset = selectionEvent.newRange.startOffset
|
val startOffset = selectionEvent.newRange.startOffset
|
||||||
val endOffset = selectionEvent.newRange.endOffset
|
val endOffset = selectionEvent.newRange.endOffset
|
||||||
|
|
||||||
// TODO: It is very confusing that this logic is split between EditorSelectionHandler and EditorMouseHandler
|
if (skipNDragEvents < skipEvents && lineStart != lineEnd && startOffset == caretOffset) {
|
||||||
if (MouseEventsDataHolder.dragEventCount < MouseEventsDataHolder.allowedSkippedDragEvents
|
|
||||||
&& lineStart != lineEnd && startOffset == caretOffset) {
|
|
||||||
if (lineEnd == endOffset - 1) {
|
if (lineEnd == endOffset - 1) {
|
||||||
// When starting on an empty line and dragging vertically upwards onto
|
// When starting on an empty line and dragging vertically upwards onto
|
||||||
// another line, the selection should include the entirety of the empty line
|
// another line, the selection should include the entirety of the empty line
|
||||||
@ -564,24 +494,13 @@ internal object VimListenerManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Listener for mouse events registered with editors that we are interested (so only local editors). Responsible for:
|
|
||||||
* * Hiding ex entry and output panels when clicking inside editor area (but not when right-clicking)
|
|
||||||
* * Removing secondary carets on mouse click (such as visual block selection)
|
|
||||||
* * Exiting visual or select mode on mouse click
|
|
||||||
* * Resets the dragEventCount on mouse press + release
|
|
||||||
* * Fix up Vim selected mode on mouse release, after dragging
|
|
||||||
* * Force bar cursor while dragging, which looks better because IntelliJ selects a character once selection has got
|
|
||||||
* over halfway through the char, while Vim selects when it enters the character bounding box
|
|
||||||
*
|
|
||||||
* @see ComponentMouseListener
|
|
||||||
*/
|
|
||||||
// TODO: Can we merge this with ComponentMouseListener to fully handle all mouse actions in one place?
|
|
||||||
private object EditorMouseHandler : EditorMouseListener, EditorMouseMotionListener {
|
private object EditorMouseHandler : EditorMouseListener, EditorMouseMotionListener {
|
||||||
private var mouseDragging = false
|
private var mouseDragging = false
|
||||||
private var cutOffFixed = false
|
private var cutOffFixed = false
|
||||||
|
|
||||||
override fun mouseDragged(e: EditorMouseEvent) {
|
override fun mouseDragged(e: EditorMouseEvent) {
|
||||||
|
if (e.editor.isIdeaVimDisabledHere) return
|
||||||
|
|
||||||
val caret = e.editor.caretModel.primaryCaret
|
val caret = e.editor.caretModel.primaryCaret
|
||||||
|
|
||||||
clearFirstSelectionEvents(e)
|
clearFirstSelectionEvents(e)
|
||||||
@ -633,7 +552,7 @@ internal object VimListenerManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
MouseEventsDataHolder.dragEventCount -= 1
|
skipNDragEvents -= 1
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -648,7 +567,7 @@ internal object VimListenerManager {
|
|||||||
* (Both with mouse and with v$. IdeaVim treats v$ as an exclusive selection)
|
* (Both with mouse and with v$. IdeaVim treats v$ as an exclusive selection)
|
||||||
*/
|
*/
|
||||||
private fun clearFirstSelectionEvents(e: EditorMouseEvent) {
|
private fun clearFirstSelectionEvents(e: EditorMouseEvent) {
|
||||||
if (MouseEventsDataHolder.dragEventCount > 0) {
|
if (skipNDragEvents > 0) {
|
||||||
logger.debug("Mouse dragging")
|
logger.debug("Mouse dragging")
|
||||||
VimVisualTimer.swingTimer?.stop()
|
VimVisualTimer.swingTimer?.stop()
|
||||||
if (!mouseDragging) {
|
if (!mouseDragging) {
|
||||||
@ -674,7 +593,9 @@ internal object VimListenerManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun mousePressed(event: EditorMouseEvent) {
|
override fun mousePressed(event: EditorMouseEvent) {
|
||||||
MouseEventsDataHolder.dragEventCount = MouseEventsDataHolder.allowedSkippedDragEvents
|
if (event.editor.isIdeaVimDisabledHere) return
|
||||||
|
|
||||||
|
skipNDragEvents = skipEvents
|
||||||
SelectionVimListenerSuppressor.reset()
|
SelectionVimListenerSuppressor.reset()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -685,10 +606,12 @@ internal object VimListenerManager {
|
|||||||
* - Click-hold and switch editor (ctrl-tab)
|
* - Click-hold and switch editor (ctrl-tab)
|
||||||
*/
|
*/
|
||||||
override fun mouseReleased(event: EditorMouseEvent) {
|
override fun mouseReleased(event: EditorMouseEvent) {
|
||||||
|
if (event.editor.isIdeaVimDisabledHere) return
|
||||||
|
|
||||||
SelectionVimListenerSuppressor.unlock()
|
SelectionVimListenerSuppressor.unlock()
|
||||||
|
|
||||||
clearFirstSelectionEvents(event)
|
clearFirstSelectionEvents(event)
|
||||||
MouseEventsDataHolder.dragEventCount = MouseEventsDataHolder.allowedSkippedDragEvents
|
skipNDragEvents = skipEvents
|
||||||
if (mouseDragging) {
|
if (mouseDragging) {
|
||||||
logger.debug("Release mouse after dragging")
|
logger.debug("Release mouse after dragging")
|
||||||
val editor = event.editor
|
val editor = event.editor
|
||||||
@ -708,6 +631,7 @@ internal object VimListenerManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun mouseClicked(event: EditorMouseEvent) {
|
override fun mouseClicked(event: EditorMouseEvent) {
|
||||||
|
if (event.editor.isIdeaVimDisabledHere) return
|
||||||
logger.debug("Mouse clicked")
|
logger.debug("Mouse clicked")
|
||||||
|
|
||||||
if (event.area == EditorMouseEventArea.EDITING_AREA) {
|
if (event.area == EditorMouseEventArea.EDITING_AREA) {
|
||||||
@ -753,21 +677,13 @@ internal object VimListenerManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* A mouse listener registered to the editor component for editors that we are interested in (so only local editors).
|
|
||||||
* Fixes some issues with mouse selection, namely:
|
|
||||||
* * Clicking at the end of the line will place the caret on the last character rather than after it
|
|
||||||
* * Double-clicking a word will place the caret on the last character rather than after it
|
|
||||||
*
|
|
||||||
* @see EditorMouseHandler
|
|
||||||
*/
|
|
||||||
// TODO: Can we merge this with ComponentMouseListener to fully handle all mouse actions in one place?
|
|
||||||
private object ComponentMouseListener : MouseAdapter() {
|
private object ComponentMouseListener : MouseAdapter() {
|
||||||
|
|
||||||
var cutOffEnd = false
|
var cutOffEnd = false
|
||||||
|
|
||||||
override fun mousePressed(e: MouseEvent?) {
|
override fun mousePressed(e: MouseEvent?) {
|
||||||
val editor = (e?.component as? EditorComponentImpl)?.editor ?: return
|
val editor = (e?.component as? EditorComponentImpl)?.editor ?: return
|
||||||
|
if (editor.isIdeaVimDisabledHere) return
|
||||||
val predictedMode = IdeaSelectionControl.predictMode(editor, SelectionSource.MOUSE)
|
val predictedMode = IdeaSelectionControl.predictMode(editor, SelectionSource.MOUSE)
|
||||||
when (e.clickCount) {
|
when (e.clickCount) {
|
||||||
1 -> {
|
1 -> {
|
||||||
@ -804,22 +720,10 @@ internal object VimListenerManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Caret listener registered only for editors that we're interested in. Used to update caret shapes when carets are
|
|
||||||
* added/removed. Also tracks the expected last column location of the caret.
|
|
||||||
*/
|
|
||||||
private object EditorCaretHandler : CaretListener {
|
private object EditorCaretHandler : CaretListener {
|
||||||
override fun caretPositionChanged(event: CaretEvent) {
|
override fun caretPositionChanged(event: CaretEvent) {
|
||||||
event.caret?.resetVimLastColumn()
|
event.caret?.resetVimLastColumn()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun caretAdded(event: CaretEvent) {
|
|
||||||
event.editor.updateCaretsVisualAttributes()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun caretRemoved(event: CaretEvent) {
|
|
||||||
event.editor.updateCaretsVisualAttributes()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
enum class SelectionSource {
|
enum class SelectionSource {
|
||||||
@ -834,6 +738,6 @@ internal object VimListenerTestObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private object MouseEventsDataHolder {
|
private object MouseEventsDataHolder {
|
||||||
const val allowedSkippedDragEvents = 3
|
const val skipEvents = 3
|
||||||
var dragEventCount = allowedSkippedDragEvents
|
var skipNDragEvents = skipEvents
|
||||||
}
|
}
|
||||||
|
@ -43,10 +43,6 @@ internal class IjVimApplication : VimApplicationBase() {
|
|||||||
return ApplicationManager.getApplication().isUnitTestMode
|
return ApplicationManager.getApplication().isUnitTestMode
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun isInternal(): Boolean {
|
|
||||||
return ApplicationManager.getApplication().isInternal
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun postKey(stroke: KeyStroke, editor: VimEditor) {
|
override fun postKey(stroke: KeyStroke, editor: VimEditor) {
|
||||||
val component: Component = SwingUtilities.getAncestorOfClass(Window::class.java, editor.ij.component)
|
val component: Component = SwingUtilities.getAncestorOfClass(Window::class.java, editor.ij.component)
|
||||||
val event = createKeyEvent(stroke, component)
|
val event = createKeyEvent(stroke, component)
|
||||||
@ -58,6 +54,10 @@ internal class IjVimApplication : VimApplicationBase() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun localEditors(): List<VimEditor> {
|
||||||
|
return com.maddyhome.idea.vim.helper.localEditors().map { IjVimEditor(it) }
|
||||||
|
}
|
||||||
|
|
||||||
override fun runWriteCommand(editor: VimEditor, name: String?, groupId: Any?, command: Runnable) {
|
override fun runWriteCommand(editor: VimEditor, name: String?, groupId: Any?, command: Runnable) {
|
||||||
RunnableHelper.runWriteCommand((editor as IjVimEditor).editor.project, command, name, groupId)
|
RunnableHelper.runWriteCommand((editor as IjVimEditor).editor.project, command, name, groupId)
|
||||||
}
|
}
|
||||||
@ -82,12 +82,6 @@ internal class IjVimApplication : VimApplicationBase() {
|
|||||||
com.maddyhome.idea.vim.helper.runAfterGotFocus(runnable)
|
com.maddyhome.idea.vim.helper.runAfterGotFocus(runnable)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun isOctopusEnabled(): Boolean {
|
|
||||||
val property = System.getProperty("octopus.handler") ?: "true"
|
|
||||||
if (property.isBlank()) return true
|
|
||||||
return property.toBoolean()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun createKeyEvent(stroke: KeyStroke, component: Component): KeyEvent {
|
private fun createKeyEvent(stroke: KeyStroke, component: Component): KeyEvent {
|
||||||
return KeyEvent(
|
return KeyEvent(
|
||||||
component,
|
component,
|
||||||
|
@ -11,6 +11,7 @@ package com.maddyhome.idea.vim.newapi
|
|||||||
import com.intellij.openapi.editor.Caret
|
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.intellij.openapi.util.Disposer
|
||||||
import com.maddyhome.idea.vim.api.BufferPosition
|
import com.maddyhome.idea.vim.api.BufferPosition
|
||||||
import com.maddyhome.idea.vim.api.CaretRegisterStorage
|
import com.maddyhome.idea.vim.api.CaretRegisterStorage
|
||||||
import com.maddyhome.idea.vim.api.CaretRegisterStorageBase
|
import com.maddyhome.idea.vim.api.CaretRegisterStorageBase
|
||||||
@ -41,6 +42,14 @@ import com.maddyhome.idea.vim.state.mode.SelectionType
|
|||||||
|
|
||||||
internal class IjVimCaret(val caret: Caret) : VimCaretBase() {
|
internal class IjVimCaret(val caret: Caret) : VimCaretBase() {
|
||||||
|
|
||||||
|
init {
|
||||||
|
if (caret.isValid) {
|
||||||
|
Disposer.register(caret) {
|
||||||
|
(registerStorage as CaretRegisterStorageBase).clearListener()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override val registerStorage: CaretRegisterStorage
|
override val registerStorage: CaretRegisterStorage
|
||||||
get() {
|
get() {
|
||||||
var storage = this.caret.registerStorage
|
var storage = this.caret.registerStorage
|
||||||
|
@ -51,6 +51,8 @@ import com.maddyhome.idea.vim.helper.fileSize
|
|||||||
import com.maddyhome.idea.vim.helper.getTopLevelEditor
|
import com.maddyhome.idea.vim.helper.getTopLevelEditor
|
||||||
import com.maddyhome.idea.vim.helper.inExMode
|
import com.maddyhome.idea.vim.helper.inExMode
|
||||||
import com.maddyhome.idea.vim.helper.isTemplateActive
|
import com.maddyhome.idea.vim.helper.isTemplateActive
|
||||||
|
import com.maddyhome.idea.vim.helper.updateCaretsVisualAttributes
|
||||||
|
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.vimLastSelectionType
|
import com.maddyhome.idea.vim.helper.vimLastSelectionType
|
||||||
import com.maddyhome.idea.vim.state.mode.Mode
|
import com.maddyhome.idea.vim.state.mode.Mode
|
||||||
@ -241,6 +243,14 @@ internal class IjVimEditor(editor: Editor) : MutableLinearEditor() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun updateCaretsVisualAttributes() {
|
||||||
|
editor.updateCaretsVisualAttributes()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun updateCaretsVisualPosition() {
|
||||||
|
editor.updateCaretsVisualPosition()
|
||||||
|
}
|
||||||
|
|
||||||
override fun offsetToVisualPosition(offset: Int): VimVisualPosition {
|
override fun offsetToVisualPosition(offset: Int): VimVisualPosition {
|
||||||
return editor.offsetToVisualPosition(offset).let { VimVisualPosition(it.line, it.column, it.leansRight) }
|
return editor.offsetToVisualPosition(offset).let { VimVisualPosition(it.line, it.column, it.leansRight) }
|
||||||
}
|
}
|
||||||
|
@ -80,11 +80,11 @@ 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.vimStateMachine
|
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.impl.state.VimStateMachineImpl
|
|
||||||
import com.maddyhome.idea.vim.macro.VimMacro
|
import com.maddyhome.idea.vim.macro.VimMacro
|
||||||
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.state.VimStateMachine
|
import com.maddyhome.idea.vim.state.VimStateMachine
|
||||||
|
import com.maddyhome.idea.vim.impl.state.VimStateMachineImpl
|
||||||
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
|
||||||
@ -207,7 +207,7 @@ internal class IjVimInjector : VimInjectorBase() {
|
|||||||
override fun commandStateFor(editor: VimEditor): VimStateMachine {
|
override fun commandStateFor(editor: VimEditor): VimStateMachine {
|
||||||
var res = editor.ij.vimStateMachine
|
var res = editor.ij.vimStateMachine
|
||||||
if (res == null) {
|
if (res == null) {
|
||||||
res = VimStateMachineImpl()
|
res = VimStateMachineImpl(editor)
|
||||||
editor.ij.vimStateMachine = res
|
editor.ij.vimStateMachine = res
|
||||||
}
|
}
|
||||||
return res
|
return res
|
||||||
|
@ -14,7 +14,17 @@ 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
|
||||||
|
|
||||||
internal class ActionTracker : CounterUsagesCollector() {
|
internal class ActionTracker : CounterUsagesCollector() {
|
||||||
object Util {
|
companion object {
|
||||||
|
private val GROUP = EventLogGroup("vim.actions", 1, "FUS")
|
||||||
|
private val TRACKED_ACTIONS = GROUP.registerEvent(
|
||||||
|
"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)
|
||||||
}
|
}
|
||||||
@ -26,14 +36,3 @@ internal class ActionTracker : CounterUsagesCollector() {
|
|||||||
|
|
||||||
override fun getGroup(): EventLogGroup = GROUP
|
override fun getGroup(): EventLogGroup = GROUP
|
||||||
}
|
}
|
||||||
|
|
||||||
private val GROUP = EventLogGroup("vim.actions", 1)
|
|
||||||
private val TRACKED_ACTIONS = GROUP.registerEvent(
|
|
||||||
"tracked",
|
|
||||||
EventFields.StringValidatedByCustomRule("action_id", ActionRuleValidator::class.java),
|
|
||||||
)
|
|
||||||
private val COPIED_ACTIONS = GROUP.registerEvent(
|
|
||||||
"copied",
|
|
||||||
EventFields.StringValidatedByCustomRule("action_id", ActionRuleValidator::class.java),
|
|
||||||
)
|
|
||||||
|
|
||||||
|
@ -47,21 +47,19 @@ internal class OptionsState : ApplicationUsagesCollector() {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
companion object {
|
||||||
|
private val GROUP = EventLogGroup("vim.options", 1, "FUS")
|
||||||
|
|
||||||
private val GROUP = EventLogGroup("vim.options", 1)
|
private val IDEAJOIN = BooleanEventField(IjOptions.ideajoin.name)
|
||||||
private val IDEAJOIN = BooleanEventField(IjOptions.ideajoin.name)
|
private val IDEAMARKS = BooleanEventField(IjOptions.ideamarks.name)
|
||||||
private val IDEAMARKS = BooleanEventField(IjOptions.ideamarks.name)
|
private val IDEAREFACTOR = EventFields.String(IjOptions.idearefactormode.name, IjOptionConstants.ideaRefactorModeValues.toList())
|
||||||
private val IDEAREFACTOR =
|
private val IDEAPUT = BooleanEventField(OptionConstants.clipboard_ideaput)
|
||||||
EventFields.String(IjOptions.idearefactormode.name, IjOptionConstants.ideaRefactorModeValues.toList())
|
private val IDEASTATUSICON = EventFields.String(IjOptions.ideastatusicon.name, IjOptionConstants.ideaStatusIconValues.toList())
|
||||||
private val IDEAPUT = BooleanEventField(OptionConstants.clipboard_ideaput)
|
private val IDEAWRITE = EventFields.String(IjOptions.ideawrite.name, IjOptionConstants.ideaWriteValues.toList())
|
||||||
private val IDEASTATUSICON =
|
private val IDEASELECTION = BooleanEventField(OptionConstants.selectmode_ideaselection)
|
||||||
EventFields.String(IjOptions.ideastatusicon.name, IjOptionConstants.ideaStatusIconValues.toList())
|
private val IDEAVIMSUPPORT = EventFields.StringList(IjOptions.ideavimsupport.name, IjOptionConstants.ideavimsupportValues.toList())
|
||||||
private val IDEAWRITE = EventFields.String(IjOptions.ideawrite.name, IjOptionConstants.ideaWriteValues.toList())
|
|
||||||
private val IDEASELECTION = BooleanEventField(OptionConstants.selectmode_ideaselection)
|
private val OPTIONS: VarargEventId = GROUP.registerVarargEvent(
|
||||||
private val IDEAVIMSUPPORT =
|
|
||||||
EventFields.StringList(IjOptions.ideavimsupport.name, IjOptionConstants.ideavimsupportValues.toList())
|
|
||||||
private val OPTIONS: VarargEventId = GROUP.registerVarargEvent(
|
|
||||||
"vim.options",
|
"vim.options",
|
||||||
IDEAJOIN,
|
IDEAJOIN,
|
||||||
IDEAMARKS,
|
IDEAMARKS,
|
||||||
@ -71,4 +69,6 @@ private val OPTIONS: VarargEventId = GROUP.registerVarargEvent(
|
|||||||
IDEAWRITE,
|
IDEAWRITE,
|
||||||
IDEASELECTION,
|
IDEASELECTION,
|
||||||
IDEAVIMSUPPORT,
|
IDEAVIMSUPPORT,
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -14,8 +14,6 @@ import com.intellij.internal.statistic.eventLog.events.EventFields
|
|||||||
import com.intellij.internal.statistic.eventLog.events.VarargEventId
|
import com.intellij.internal.statistic.eventLog.events.VarargEventId
|
||||||
import com.intellij.internal.statistic.service.fus.collectors.ApplicationUsagesCollector
|
import com.intellij.internal.statistic.service.fus.collectors.ApplicationUsagesCollector
|
||||||
import com.maddyhome.idea.vim.VimPlugin
|
import com.maddyhome.idea.vim.VimPlugin
|
||||||
import com.maddyhome.idea.vim.statistic.PluginState.Util.enabledExtensions
|
|
||||||
import com.maddyhome.idea.vim.statistic.PluginState.Util.extensionNames
|
|
||||||
import com.maddyhome.idea.vim.ui.JoinEap
|
import com.maddyhome.idea.vim.ui.JoinEap
|
||||||
|
|
||||||
internal class PluginState : ApplicationUsagesCollector() {
|
internal class PluginState : ApplicationUsagesCollector() {
|
||||||
@ -32,32 +30,21 @@ internal class PluginState : ApplicationUsagesCollector() {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
object Util {
|
companion object {
|
||||||
internal val extensionNames = listOf(
|
private val GROUP = EventLogGroup("vim.common", 1, "FUS")
|
||||||
"textobj-entire",
|
|
||||||
"argtextobj",
|
|
||||||
"ReplaceWithRegister",
|
|
||||||
"vim-paragraph-motion",
|
|
||||||
"highlightedyank",
|
|
||||||
"multiple-cursors",
|
|
||||||
"exchange",
|
|
||||||
"NERDTree",
|
|
||||||
"surround",
|
|
||||||
"commentary",
|
|
||||||
"matchit",
|
|
||||||
"textobj-indent"
|
|
||||||
)
|
|
||||||
internal val enabledExtensions = HashSet<String>()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private val GROUP = EventLogGroup("vim.common", 1)
|
val extensionNames = listOf("textobj-entire", "argtextobj", "ReplaceWithRegister", "vim-paragraph-motion", "highlightedyank", "multiple-cursors", "exchange", "NERDTree", "surround", "commentary", "matchit", "textobj-indent")
|
||||||
private val PLUGIN_ENABLED = EventFields.Boolean("is_plugin_enabled")
|
val enabledExtensions = HashSet<String>()
|
||||||
private val IS_EAP = EventFields.Boolean("is_EAP_active")
|
|
||||||
private val ENABLED_EXTENSIONS = EventFields.StringList("enabled_extensions", extensionNames)
|
private val PLUGIN_ENABLED = EventFields.Boolean("is_plugin_enabled")
|
||||||
private val PLUGIN_STATE: VarargEventId = GROUP.registerVarargEvent(
|
private val IS_EAP = EventFields.Boolean("is_EAP_active")
|
||||||
|
private val ENABLED_EXTENSIONS = EventFields.StringList("enabled_extensions", extensionNames)
|
||||||
|
|
||||||
|
private val PLUGIN_STATE: VarargEventId = GROUP.registerVarargEvent(
|
||||||
"vim.common",
|
"vim.common",
|
||||||
PLUGIN_ENABLED,
|
PLUGIN_ENABLED,
|
||||||
IS_EAP,
|
IS_EAP,
|
||||||
ENABLED_EXTENSIONS,
|
ENABLED_EXTENSIONS,
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -70,37 +70,11 @@ internal class ShortcutConflictState : ApplicationUsagesCollector() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private fun KeyStroke.toReadableString(): String {
|
companion object {
|
||||||
val result = StringBuilder()
|
private val GROUP = EventLogGroup("vim.handlers", 1, "FUS")
|
||||||
val modifiers = this.modifiers
|
|
||||||
if (modifiers > 0) {
|
|
||||||
result.append(preprocessKeys(InputEvent.getModifiersExText(modifiers)))
|
|
||||||
.append("+")
|
|
||||||
}
|
|
||||||
result.append(KeyEvent.getKeyText(this.keyCode))
|
|
||||||
return result.toString()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun preprocessKeys(string: String): String {
|
private val keyStrokes = listOf(
|
||||||
return string.replace("⌃", "Ctrl").replace("⇧", "Shift")
|
|
||||||
}
|
|
||||||
|
|
||||||
private enum class HandledModes {
|
|
||||||
NORMAL_UNDEFINED,
|
|
||||||
NORMAL_IDE,
|
|
||||||
NORMAL_VIM,
|
|
||||||
INSERT_UNDEFINED,
|
|
||||||
INSERT_IDE,
|
|
||||||
INSERT_VIM,
|
|
||||||
VISUAL_AND_SELECT_UNDEFINED,
|
|
||||||
VISUAL_AND_SELECT_IDE,
|
|
||||||
VISUAL_AND_SELECT_VIM,
|
|
||||||
}
|
|
||||||
|
|
||||||
private val GROUP = EventLogGroup("vim.handlers", 1)
|
|
||||||
private val keyStrokes = listOf(
|
|
||||||
KeyStroke.getKeyStroke('1'.code, CTRL_DOWN_MASK),
|
KeyStroke.getKeyStroke('1'.code, CTRL_DOWN_MASK),
|
||||||
KeyStroke.getKeyStroke('2'.code, CTRL_DOWN_MASK),
|
KeyStroke.getKeyStroke('2'.code, CTRL_DOWN_MASK),
|
||||||
KeyStroke.getKeyStroke('3'.code, CTRL_DOWN_MASK),
|
KeyStroke.getKeyStroke('3'.code, CTRL_DOWN_MASK),
|
||||||
@ -180,7 +154,36 @@ private val keyStrokes = listOf(
|
|||||||
KeyStroke.getKeyStroke('Z'.code, CTRL_DOWN_MASK + SHIFT_DOWN_MASK),
|
KeyStroke.getKeyStroke('Z'.code, CTRL_DOWN_MASK + SHIFT_DOWN_MASK),
|
||||||
KeyStroke.getKeyStroke('['.code, CTRL_DOWN_MASK + SHIFT_DOWN_MASK),
|
KeyStroke.getKeyStroke('['.code, CTRL_DOWN_MASK + SHIFT_DOWN_MASK),
|
||||||
KeyStroke.getKeyStroke(']'.code, CTRL_DOWN_MASK + SHIFT_DOWN_MASK),
|
KeyStroke.getKeyStroke(']'.code, CTRL_DOWN_MASK + SHIFT_DOWN_MASK),
|
||||||
)
|
)
|
||||||
private val KEY_STROKE = EventFields.String("key_stroke", keyStrokes.map { it.toReadableString() })
|
private val KEY_STROKE = EventFields.String("key_stroke", keyStrokes.map { it.toReadableString() })
|
||||||
private val HANDLER_MODE = EventFields.Enum<HandledModes>("handler")
|
private val HANDLER_MODE = EventFields.Enum<HandledModes>("handler")
|
||||||
private val HANDLER = GROUP.registerEvent("vim.handler", KEY_STROKE, HANDLER_MODE)
|
private val HANDLER = GROUP.registerEvent("vim.handler", KEY_STROKE, HANDLER_MODE)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun KeyStroke.toReadableString(): String {
|
||||||
|
val result = StringBuilder()
|
||||||
|
val modifiers = this.modifiers
|
||||||
|
if (modifiers > 0) {
|
||||||
|
result.append(preprocessKeys(InputEvent.getModifiersExText(modifiers)))
|
||||||
|
.append("+")
|
||||||
|
}
|
||||||
|
result.append(KeyEvent.getKeyText(this.keyCode))
|
||||||
|
return result.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun preprocessKeys(string: String): String {
|
||||||
|
return string.replace("⌃", "Ctrl").replace("⇧", "Shift")
|
||||||
|
}
|
||||||
|
|
||||||
|
private enum class HandledModes {
|
||||||
|
NORMAL_UNDEFINED,
|
||||||
|
NORMAL_IDE,
|
||||||
|
NORMAL_VIM,
|
||||||
|
INSERT_UNDEFINED,
|
||||||
|
INSERT_IDE,
|
||||||
|
INSERT_VIM,
|
||||||
|
VISUAL_AND_SELECT_UNDEFINED,
|
||||||
|
VISUAL_AND_SELECT_IDE,
|
||||||
|
VISUAL_AND_SELECT_VIM,
|
||||||
|
}
|
||||||
|
@ -13,7 +13,6 @@ import com.intellij.internal.statistic.eventLog.EventLogGroup
|
|||||||
import com.intellij.internal.statistic.eventLog.events.EventFields
|
import com.intellij.internal.statistic.eventLog.events.EventFields
|
||||||
import com.intellij.internal.statistic.eventLog.events.VarargEventId
|
import com.intellij.internal.statistic.eventLog.events.VarargEventId
|
||||||
import com.intellij.internal.statistic.service.fus.collectors.ApplicationUsagesCollector
|
import com.intellij.internal.statistic.service.fus.collectors.ApplicationUsagesCollector
|
||||||
import com.maddyhome.idea.vim.statistic.PluginState.Util.extensionNames
|
|
||||||
import com.maddyhome.idea.vim.vimscript.services.VimRcService
|
import com.maddyhome.idea.vim.vimscript.services.VimRcService
|
||||||
|
|
||||||
internal class VimscriptState : ApplicationUsagesCollector() {
|
internal class VimscriptState : ApplicationUsagesCollector() {
|
||||||
@ -23,47 +22,45 @@ internal class VimscriptState : ApplicationUsagesCollector() {
|
|||||||
override fun getMetrics(): Set<MetricEvent> {
|
override fun getMetrics(): Set<MetricEvent> {
|
||||||
return setOf(
|
return setOf(
|
||||||
VIMSCRIPT.metric(
|
VIMSCRIPT.metric(
|
||||||
SOURCED_FILES with Util.sourcedFiles.size,
|
SOURCED_FILES with sourcedFiles.size,
|
||||||
IDEAVIMRC_SIZE with (VimRcService.findIdeaVimRc()?.readLines()?.filter { !it.matches(Regex("\\s*\".*")) && it.isNotBlank() }?.size ?: -1),
|
IDEAVIMRC_SIZE with (VimRcService.findIdeaVimRc()?.readLines()?.filter { !it.matches(Regex("\\s*\".*")) && it.isNotBlank() }?.size ?: -1),
|
||||||
EXTENSIONS_ENABLED_BY_SET with (PluginState.Util.enabledExtensions - Util.extensionsEnabledWithPlug).toList(),
|
EXTENSIONS_ENABLED_BY_SET with (PluginState.enabledExtensions - extensionsEnabledWithPlug).toList(),
|
||||||
EXTENSIONS_ENABLED_BY_PLUG with Util.extensionsEnabledWithPlug.toList(),
|
EXTENSIONS_ENABLED_BY_PLUG with extensionsEnabledWithPlug.toList(),
|
||||||
IS_IDE_SPECIFIC_CONFIGURATION_USED with Util.isIDESpecificConfigurationUsed,
|
IS_IDE_SPECIFIC_CONFIGURATION_USED with isIDESpecificConfigurationUsed,
|
||||||
IS_LOOP_USED with Util.isLoopUsed,
|
IS_LOOP_USED with isLoopUsed,
|
||||||
IS_IF_USED with Util.isIfUsed,
|
IS_IF_USED with isIfUsed,
|
||||||
IS_MAP_EXPR_USED with Util.isMapExprUsed,
|
IS_MAP_EXPR_USED with isMapExprUsed,
|
||||||
IS_FUNCTION_DEF_USED with Util.isFunctionDeclarationUsed,
|
IS_FUNCTION_DEF_USED with isFunctionDeclarationUsed,
|
||||||
IS_FUNCTION_CALL_USED with Util.isFunctionCallUsed,
|
IS_FUNCTION_CALL_USED with isFunctionCallUsed,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
object Util {
|
companion object {
|
||||||
|
private val GROUP = EventLogGroup("vim.vimscript", 1, "FUS")
|
||||||
|
|
||||||
val sourcedFiles = HashSet<String>()
|
val sourcedFiles = HashSet<String>()
|
||||||
val extensionsEnabledWithPlug = HashSet<String>()
|
val extensionsEnabledWithPlug = HashSet<String>()
|
||||||
|
|
||||||
var isIDESpecificConfigurationUsed = false
|
var isIDESpecificConfigurationUsed = false
|
||||||
|
|
||||||
var isLoopUsed = false
|
var isLoopUsed = false
|
||||||
var isIfUsed = false
|
var isIfUsed = false
|
||||||
var isMapExprUsed = false
|
var isMapExprUsed = false
|
||||||
var isFunctionDeclarationUsed = false
|
var isFunctionDeclarationUsed = false
|
||||||
var isFunctionCallUsed = false
|
var isFunctionCallUsed = false
|
||||||
}
|
|
||||||
|
|
||||||
}
|
private val SOURCED_FILES = EventFields.RoundedInt("number_of_sourced_files")
|
||||||
|
private val IDEAVIMRC_SIZE = EventFields.RoundedInt("ideavimrc_size")
|
||||||
|
private val EXTENSIONS_ENABLED_BY_SET = EventFields.StringList("extensions_enabled_by_set", PluginState.extensionNames)
|
||||||
|
private val EXTENSIONS_ENABLED_BY_PLUG = EventFields.StringList("extensions_enabled_by_plug", PluginState.extensionNames)
|
||||||
|
private val IS_IDE_SPECIFIC_CONFIGURATION_USED = EventFields.Boolean("is_IDE-specific_configuration_used")
|
||||||
|
private val IS_LOOP_USED = EventFields.Boolean("is_loop_used")
|
||||||
|
private val IS_IF_USED = EventFields.Boolean("is_if_used")
|
||||||
|
private val IS_MAP_EXPR_USED = EventFields.Boolean("is_map_expr_used")
|
||||||
|
private val IS_FUNCTION_DEF_USED = EventFields.Boolean("is_function_declaration_used")
|
||||||
|
private val IS_FUNCTION_CALL_USED = EventFields.Boolean("is_function_call_used")
|
||||||
|
|
||||||
private val GROUP = EventLogGroup("vim.vimscript", 1)
|
private val VIMSCRIPT: VarargEventId = GROUP.registerVarargEvent(
|
||||||
private val SOURCED_FILES = EventFields.RoundedInt("number_of_sourced_files")
|
|
||||||
private val IDEAVIMRC_SIZE = EventFields.RoundedInt("ideavimrc_size")
|
|
||||||
private val EXTENSIONS_ENABLED_BY_SET = EventFields.StringList("extensions_enabled_by_set", extensionNames)
|
|
||||||
private val EXTENSIONS_ENABLED_BY_PLUG = EventFields.StringList("extensions_enabled_by_plug", extensionNames)
|
|
||||||
private val IS_IDE_SPECIFIC_CONFIGURATION_USED = EventFields.Boolean("is_IDE-specific_configuration_used")
|
|
||||||
private val IS_LOOP_USED = EventFields.Boolean("is_loop_used")
|
|
||||||
private val IS_IF_USED = EventFields.Boolean("is_if_used")
|
|
||||||
private val IS_MAP_EXPR_USED = EventFields.Boolean("is_map_expr_used")
|
|
||||||
private val IS_FUNCTION_DEF_USED = EventFields.Boolean("is_function_declaration_used")
|
|
||||||
private val IS_FUNCTION_CALL_USED = EventFields.Boolean("is_function_call_used")
|
|
||||||
|
|
||||||
private val VIMSCRIPT: VarargEventId = GROUP.registerVarargEvent(
|
|
||||||
"vim.vimscript",
|
"vim.vimscript",
|
||||||
SOURCED_FILES,
|
SOURCED_FILES,
|
||||||
IDEAVIMRC_SIZE,
|
IDEAVIMRC_SIZE,
|
||||||
@ -75,4 +72,6 @@ private val VIMSCRIPT: VarargEventId = GROUP.registerVarargEvent(
|
|||||||
IS_MAP_EXPR_USED,
|
IS_MAP_EXPR_USED,
|
||||||
IS_FUNCTION_DEF_USED,
|
IS_FUNCTION_DEF_USED,
|
||||||
IS_FUNCTION_CALL_USED,
|
IS_FUNCTION_CALL_USED,
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,71 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2003-2024 The IdeaVim authors
|
|
||||||
*
|
|
||||||
* Use of this source code is governed by an MIT-style
|
|
||||||
* license that can be found in the LICENSE.txt file or at
|
|
||||||
* https://opensource.org/licenses/MIT.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.maddyhome.idea.vim.statistic
|
|
||||||
|
|
||||||
import com.intellij.internal.statistic.beans.MetricEvent
|
|
||||||
import com.intellij.internal.statistic.eventLog.EventLogGroup
|
|
||||||
import com.intellij.internal.statistic.eventLog.events.EventFields
|
|
||||||
import com.intellij.internal.statistic.eventLog.events.VarargEventId
|
|
||||||
import com.intellij.internal.statistic.service.fus.collectors.ApplicationUsagesCollector
|
|
||||||
import com.intellij.openapi.project.ProjectManager
|
|
||||||
import com.intellij.openapi.wm.WindowManager
|
|
||||||
import com.maddyhome.idea.vim.api.injector
|
|
||||||
import com.maddyhome.idea.vim.ui.widgets.mode.ModeWidgetFactory
|
|
||||||
|
|
||||||
public class WidgetState : ApplicationUsagesCollector() {
|
|
||||||
override fun getGroup(): EventLogGroup = GROUP
|
|
||||||
|
|
||||||
override fun getMetrics(): Set<MetricEvent> {
|
|
||||||
return setOf(
|
|
||||||
WIDGET.metric(
|
|
||||||
IS_MODE_WIDGET_SHOWN with isWidgetShown(),
|
|
||||||
MODE_WIDGET_THEME_LIGHT with getModeWidgetTheme("_light"),
|
|
||||||
MODE_WIDGET_THEME_DARK with getModeWidgetTheme("_dark"),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun isWidgetShown(): Boolean {
|
|
||||||
for (project in ProjectManager.getInstance().openProjects) {
|
|
||||||
val statusBar = WindowManager.getInstance()?.getStatusBar(project) ?: continue
|
|
||||||
val widgets = statusBar.allWidgets ?: continue
|
|
||||||
if (widgets.any { it.ID() == ModeWidgetFactory.ID }) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getModeWidgetTheme(postfix: String): String {
|
|
||||||
if (injector.variableService.getVimVariable("widget_mode_is_full_customization$postfix")?.asBoolean() == true) {
|
|
||||||
return "ADVANCED CUSTOMIZATION"
|
|
||||||
}
|
|
||||||
val themeString = injector.variableService.getVimVariable("widget_mode_theme$postfix")?.asString()
|
|
||||||
return if (themeString?.lowercase() == "colorless") {
|
|
||||||
"COLORLESS"
|
|
||||||
} else {
|
|
||||||
"TERM"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public companion object {
|
|
||||||
private val GROUP = EventLogGroup("vim.widget", 1, "FUS")
|
|
||||||
|
|
||||||
private val IS_MODE_WIDGET_SHOWN = EventFields.Boolean("is-mode-widget-shown")
|
|
||||||
private val MODE_WIDGET_THEME_LIGHT = EventFields.String("mode-widget-theme-light", listOf("TERM", "COLORLESS", "ADVANCED CUSTOMIZATION"))
|
|
||||||
private val MODE_WIDGET_THEME_DARK = EventFields.String("mode-widget-theme-dark", listOf("TERM", "COLORLESS", "ADVANCED CUSTOMIZATION"))
|
|
||||||
|
|
||||||
private val WIDGET: VarargEventId = GROUP.registerVarargEvent(
|
|
||||||
"vim.widget",
|
|
||||||
IS_MODE_WIDGET_SHOWN,
|
|
||||||
MODE_WIDGET_THEME_LIGHT,
|
|
||||||
MODE_WIDGET_THEME_DARK,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
@ -31,7 +31,7 @@ internal class Troubleshooter {
|
|||||||
|
|
||||||
fun findIncorrectMappings(): List<Problem> {
|
fun findIncorrectMappings(): List<Problem> {
|
||||||
val problems = ArrayList<Problem>()
|
val problems = ArrayList<Problem>()
|
||||||
MappingMode.entries.forEach { mode ->
|
MappingMode.values().forEach { mode ->
|
||||||
injector.keyGroup.getKeyMapping(mode).getByOwner(MappingOwner.IdeaVim.InitScript).forEach { (_, to) ->
|
injector.keyGroup.getKeyMapping(mode).getByOwner(MappingOwner.IdeaVim.InitScript).forEach { (_, to) ->
|
||||||
if (to is ToKeysMappingInfo) {
|
if (to is ToKeysMappingInfo) {
|
||||||
if (":action" in to.toKeys.joinToString { it.keyChar.toString() }) {
|
if (":action" in to.toKeys.joinToString { it.keyChar.toString() }) {
|
||||||
|
@ -18,8 +18,8 @@ import com.intellij.util.IJSwingUtilities;
|
|||||||
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.api.ExecutionContext;
|
import com.maddyhome.idea.vim.api.ExecutionContext;
|
||||||
import com.maddyhome.idea.vim.api.VimEditor;
|
|
||||||
import com.maddyhome.idea.vim.diagnostic.VimLogger;
|
import com.maddyhome.idea.vim.diagnostic.VimLogger;
|
||||||
|
import com.maddyhome.idea.vim.helper.HelperKt;
|
||||||
import com.maddyhome.idea.vim.helper.MessageHelper;
|
import com.maddyhome.idea.vim.helper.MessageHelper;
|
||||||
import com.maddyhome.idea.vim.helper.UiHelper;
|
import com.maddyhome.idea.vim.helper.UiHelper;
|
||||||
import com.maddyhome.idea.vim.helper.UserDataManager;
|
import com.maddyhome.idea.vim.helper.UserDataManager;
|
||||||
@ -104,7 +104,7 @@ public class ExOutputPanel extends JPanel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static int countLines(@NotNull String text) {
|
private static int countLines(@NotNull String text) {
|
||||||
if (text.isEmpty()) {
|
if (text.length() == 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -139,14 +139,14 @@ public class ExOutputPanel extends JPanel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void setText(@NotNull @Nls(capitalization = Nls.Capitalization.Sentence) String data) {
|
public void setText(@NotNull @Nls(capitalization = Nls.Capitalization.Sentence) String data) {
|
||||||
if (!data.isEmpty() && data.charAt(data.length() - 1) == '\n') {
|
if (data.length() > 0 && data.charAt(data.length() - 1) == '\n') {
|
||||||
data = data.substring(0, data.length() - 1);
|
data = data.substring(0, data.length() - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
myText.setText(data);
|
myText.setText(data);
|
||||||
myText.setFont(UiHelper.selectFont(data));
|
myText.setFont(UiHelper.selectFont(data));
|
||||||
myText.setCaretPosition(0);
|
myText.setCaretPosition(0);
|
||||||
if (!data.isEmpty()) {
|
if (data.length() > 0) {
|
||||||
activate();
|
activate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -366,11 +366,8 @@ public class ExOutputPanel extends JPanel {
|
|||||||
@Override
|
@Override
|
||||||
public void lookAndFeelChanged(@NotNull LafManager source) {
|
public void lookAndFeelChanged(@NotNull LafManager source) {
|
||||||
if (VimPlugin.isNotEnabled()) return;
|
if (VimPlugin.isNotEnabled()) return;
|
||||||
|
// Calls updateUI on this and child components
|
||||||
// This listener is only invoked for local scenarios, and we only need to update local editor UI. This will invoke
|
for (Editor editor : HelperKt.localEditors()) {
|
||||||
// updateUI on the output pane and it's child components
|
|
||||||
for (VimEditor vimEditor : injector.getEditorGroup().getEditors()) {
|
|
||||||
Editor editor = ((IjVimEditor)vimEditor).getEditor();
|
|
||||||
if (!ExOutputPanel.isPanelActive(editor)) continue;
|
if (!ExOutputPanel.isPanelActive(editor)) continue;
|
||||||
IJSwingUtilities.updateComponentTreeUI(ExOutputPanel.getInstance(editor));
|
IJSwingUtilities.updateComponentTreeUI(ExOutputPanel.getInstance(editor));
|
||||||
}
|
}
|
||||||
|
@ -13,8 +13,8 @@ import com.intellij.openapi.diagnostic.logger
|
|||||||
import com.intellij.openapi.diagnostic.trace
|
import com.intellij.openapi.diagnostic.trace
|
||||||
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.api.injector
|
|
||||||
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
|
||||||
@ -60,7 +60,7 @@ public object ModalEntry {
|
|||||||
} else {
|
} else {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
if (injector.registerGroup.isRecording) {
|
if (editor.vimStateMachine.isRecording) {
|
||||||
KeyHandler.getInstance().modalEntryKeys += stroke
|
KeyHandler.getInstance().modalEntryKeys += stroke
|
||||||
}
|
}
|
||||||
if (!processor(stroke)) {
|
if (!processor(stroke)) {
|
||||||
|
@ -12,7 +12,6 @@ import com.intellij.icons.AllIcons
|
|||||||
import com.intellij.openapi.Disposable
|
import com.intellij.openapi.Disposable
|
||||||
import com.intellij.openapi.actionSystem.ActionUpdateThread
|
import com.intellij.openapi.actionSystem.ActionUpdateThread
|
||||||
import com.intellij.openapi.actionSystem.AnActionEvent
|
import com.intellij.openapi.actionSystem.AnActionEvent
|
||||||
import com.intellij.openapi.actionSystem.DataContext
|
|
||||||
import com.intellij.openapi.actionSystem.DefaultActionGroup
|
import com.intellij.openapi.actionSystem.DefaultActionGroup
|
||||||
import com.intellij.openapi.actionSystem.PlatformDataKeys
|
import com.intellij.openapi.actionSystem.PlatformDataKeys
|
||||||
import com.intellij.openapi.diagnostic.logger
|
import com.intellij.openapi.diagnostic.logger
|
||||||
@ -160,8 +159,8 @@ internal class ReloadVimRc : DumbAwareAction() {
|
|||||||
internal class ReloadFloatingToolbar : AbstractFloatingToolbarProvider(ACTION_GROUP) {
|
internal class ReloadFloatingToolbar : AbstractFloatingToolbarProvider(ACTION_GROUP) {
|
||||||
override val autoHideable: Boolean = false
|
override val autoHideable: Boolean = false
|
||||||
|
|
||||||
override fun register(dataContext: DataContext, component: FloatingToolbarComponent, parentDisposable: Disposable) {
|
override fun register(component: FloatingToolbarComponent, parentDisposable: Disposable) {
|
||||||
super.register(dataContext, component, parentDisposable)
|
super.register(component, parentDisposable)
|
||||||
val action = {
|
val action = {
|
||||||
component.scheduleShow()
|
component.scheduleShow()
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
package com.maddyhome.idea.vim.ui
|
package com.maddyhome.idea.vim.ui
|
||||||
|
|
||||||
import com.intellij.openapi.editor.Editor
|
import com.intellij.openapi.editor.Editor
|
||||||
|
import com.intellij.openapi.fileEditor.FileEditorManagerEvent
|
||||||
import com.intellij.openapi.fileEditor.FileEditorManagerListener
|
import com.intellij.openapi.fileEditor.FileEditorManagerListener
|
||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
import com.intellij.openapi.project.ProjectManager
|
import com.intellij.openapi.project.ProjectManager
|
||||||
@ -20,14 +21,11 @@ import com.intellij.openapi.wm.WindowManager
|
|||||||
import com.intellij.openapi.wm.impl.status.EditorBasedWidget
|
import com.intellij.openapi.wm.impl.status.EditorBasedWidget
|
||||||
import com.intellij.util.Consumer
|
import com.intellij.util.Consumer
|
||||||
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.globalOptions
|
import com.maddyhome.idea.vim.api.globalOptions
|
||||||
import com.maddyhome.idea.vim.api.injector
|
import com.maddyhome.idea.vim.api.injector
|
||||||
import com.maddyhome.idea.vim.common.EditorListener
|
|
||||||
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.vimStateMachine
|
import com.maddyhome.idea.vim.helper.vimStateMachine
|
||||||
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.GlobalOptionChangeListener
|
import com.maddyhome.idea.vim.options.GlobalOptionChangeListener
|
||||||
import org.jetbrains.annotations.NonNls
|
import org.jetbrains.annotations.NonNls
|
||||||
@ -132,18 +130,11 @@ internal class Widget(project: Project) :
|
|||||||
override fun copy(): StatusBarWidget = Widget(project)
|
override fun copy(): StatusBarWidget = Widget(project)
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class ShowCmdWidgetUpdater : EditorListener {
|
internal class WidgetUpdater : FileEditorManagerListener {
|
||||||
override fun focusGained(editor: VimEditor) {
|
override fun selectionChanged(event: FileEditorManagerEvent) {
|
||||||
editor.ij.project?.let { selectionChanged(it) }
|
// Update when changing selected editor
|
||||||
}
|
|
||||||
|
|
||||||
override fun focusLost(editor: VimEditor) {
|
|
||||||
editor.ij.project?.let { selectionChanged(it) }
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun selectionChanged(project: Project) {
|
|
||||||
val windowManager = WindowManager.getInstance()
|
val windowManager = WindowManager.getInstance()
|
||||||
val statusBar = windowManager.getStatusBar(project)
|
val statusBar = windowManager.getStatusBar(event.manager.project)
|
||||||
statusBar.updateWidget(ShowCmd.ID)
|
statusBar.updateWidget(ShowCmd.ID)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,16 +9,15 @@ package com.maddyhome.idea.vim.ui
|
|||||||
|
|
||||||
import com.intellij.icons.AllIcons
|
import com.intellij.icons.AllIcons
|
||||||
import com.intellij.openapi.actionSystem.ActionToolbarPosition
|
import com.intellij.openapi.actionSystem.ActionToolbarPosition
|
||||||
import com.intellij.openapi.actionSystem.ActionUpdateThread
|
|
||||||
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.keymap.KeymapUtil
|
import com.intellij.openapi.keymap.KeymapUtil
|
||||||
import com.intellij.openapi.options.Configurable
|
import com.intellij.openapi.options.Configurable
|
||||||
import com.intellij.openapi.project.DumbAwareAction
|
|
||||||
import com.intellij.openapi.ui.ComboBoxTableRenderer
|
import com.intellij.openapi.ui.ComboBoxTableRenderer
|
||||||
import com.intellij.openapi.ui.StripeTable
|
import com.intellij.openapi.ui.StripeTable
|
||||||
import com.intellij.openapi.wm.IdeFocusManager
|
import com.intellij.openapi.wm.IdeFocusManager
|
||||||
|
import com.intellij.ui.DumbAwareActionButton
|
||||||
import com.intellij.ui.HyperlinkLabel
|
import com.intellij.ui.HyperlinkLabel
|
||||||
import com.intellij.ui.IdeBorderFactory
|
import com.intellij.ui.IdeBorderFactory
|
||||||
import com.intellij.ui.JBColor
|
import com.intellij.ui.JBColor
|
||||||
@ -170,7 +169,7 @@ internal class VimEmulationConfigurable : Configurable {
|
|||||||
return getColumnModel().getColumn(column.index)
|
return getColumnModel().getColumn(column.index)
|
||||||
}
|
}
|
||||||
|
|
||||||
private class ShortcutOwnerRenderer : ComboBoxTableRenderer<ShortcutOwner>(ShortcutOwner.entries.toTypedArray()) {
|
private class ShortcutOwnerRenderer : ComboBoxTableRenderer<ShortcutOwner>(ShortcutOwner.values()) {
|
||||||
override fun customizeComponent(owner: ShortcutOwner, table: JTable, isSelected: Boolean) {
|
override fun customizeComponent(owner: ShortcutOwner, table: JTable, isSelected: Boolean) {
|
||||||
super.customizeComponent(owner, table, isSelected)
|
super.customizeComponent(owner, table, isSelected)
|
||||||
if (owner == ShortcutOwner.UNDEFINED) {
|
if (owner == ShortcutOwner.UNDEFINED) {
|
||||||
@ -193,7 +192,7 @@ internal class VimEmulationConfigurable : Configurable {
|
|||||||
private val ourMembers: MutableMap<Int, Column> = HashMap()
|
private val ourMembers: MutableMap<Int, Column> = HashMap()
|
||||||
|
|
||||||
init {
|
init {
|
||||||
for (column in entries) {
|
for (column in values()) {
|
||||||
ourMembers[column.index] = column
|
ourMembers[column.index] = column
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -225,7 +224,7 @@ internal class VimEmulationConfigurable : Configurable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun getColumnCount(): Int {
|
override fun getColumnCount(): Int {
|
||||||
return Column.entries.size
|
return Column.values().size
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getValueAt(rowIndex: Int, columnIndex: Int): Any? {
|
override fun getValueAt(rowIndex: Int, columnIndex: Int): Any? {
|
||||||
@ -295,21 +294,19 @@ internal class VimEmulationConfigurable : Configurable {
|
|||||||
|
|
||||||
private class CopyForRcAction(
|
private class CopyForRcAction(
|
||||||
private val myModel: VimShortcutConflictsTable.Model,
|
private val myModel: VimShortcutConflictsTable.Model,
|
||||||
) : DumbAwareAction(
|
) : DumbAwareActionButton(
|
||||||
"Copy Config for .ideavimrc",
|
"Copy Config for .ideavimrc",
|
||||||
"Copy config for .ideavimrc in sethandler format",
|
"Copy config for .ideavimrc in sethandler format",
|
||||||
AllIcons.Actions.Copy,
|
AllIcons.Actions.Copy,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
override fun update(e: AnActionEvent) {
|
override fun updateButton(e: AnActionEvent) {
|
||||||
val enabled: Boolean = myModel.rows.stream().anyMatch {
|
val enabled: Boolean = myModel.rows.stream().anyMatch {
|
||||||
it.owner is AllModes && (it.owner as AllModes).owner != ShortcutOwner.UNDEFINED
|
it.owner is AllModes && (it.owner as AllModes).owner != ShortcutOwner.UNDEFINED
|
||||||
}
|
}
|
||||||
e.presentation.isEnabled = enabled
|
e.presentation.isEnabled = enabled
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getActionUpdateThread(): ActionUpdateThread = ActionUpdateThread.EDT
|
|
||||||
|
|
||||||
override fun actionPerformed(e: AnActionEvent) {
|
override fun actionPerformed(e: AnActionEvent) {
|
||||||
val stringBuilder = StringBuilder()
|
val stringBuilder = StringBuilder()
|
||||||
for (row in myModel.rows) {
|
for (row in myModel.rows) {
|
||||||
@ -331,16 +328,14 @@ internal class VimEmulationConfigurable : Configurable {
|
|||||||
class ResetHandlersAction(
|
class ResetHandlersAction(
|
||||||
private val myModel: VimShortcutConflictsTable.Model,
|
private val myModel: VimShortcutConflictsTable.Model,
|
||||||
private val myTable: VimShortcutConflictsTable,
|
private val myTable: VimShortcutConflictsTable,
|
||||||
) : DumbAwareAction("Reset Handlers", "Reset handlers", AllIcons.General.Reset) {
|
) : DumbAwareActionButton("Reset Handlers", "Reset handlers", AllIcons.General.Reset) {
|
||||||
override fun update(e: AnActionEvent) {
|
override fun updateButton(e: AnActionEvent) {
|
||||||
val enabled: Boolean = myModel.rows.stream().anyMatch {
|
val enabled: Boolean = myModel.rows.stream().anyMatch {
|
||||||
it.owner is AllModes && (it.owner as AllModes).owner != ShortcutOwner.UNDEFINED
|
it.owner is AllModes && (it.owner as AllModes).owner != ShortcutOwner.UNDEFINED
|
||||||
}
|
}
|
||||||
e.presentation.isEnabled = enabled
|
e.presentation.isEnabled = enabled
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getActionUpdateThread(): ActionUpdateThread = ActionUpdateThread.EDT
|
|
||||||
|
|
||||||
override fun actionPerformed(e: AnActionEvent) {
|
override fun actionPerformed(e: AnActionEvent) {
|
||||||
TableUtil.stopEditing(myTable)
|
TableUtil.stopEditing(myTable)
|
||||||
for (row in myModel.rows) {
|
for (row in myModel.rows) {
|
||||||
|
@ -114,8 +114,7 @@ internal class CompleteEntryAction : TextAction(ExEditorKit.CompleteEntry) {
|
|||||||
// write action
|
// write action
|
||||||
// * The key handler routines get the chance to clean up and reset state
|
// * The key handler routines get the chance to clean up and reset state
|
||||||
val entry = ExEntryPanel.getInstance().entry
|
val entry = ExEntryPanel.getInstance().entry
|
||||||
val keyHandler = KeyHandler.getInstance()
|
KeyHandler.getInstance().handleKey(entry.editor.vim, stroke, entry.context.vim)
|
||||||
keyHandler.handleKey(entry.editor.vim, stroke, entry.context.vim, keyHandler.keyHandlerState)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
@ -125,12 +125,10 @@ internal object ExEditorKit : DefaultEditorKit() {
|
|||||||
if (target.useHandleKeyFromEx) {
|
if (target.useHandleKeyFromEx) {
|
||||||
val entry = ExEntryPanel.getInstance().entry
|
val entry = ExEntryPanel.getInstance().entry
|
||||||
val editor = entry.editor
|
val editor = entry.editor
|
||||||
val keyHandler = KeyHandler.getInstance()
|
KeyHandler.getInstance().handleKey(
|
||||||
keyHandler.handleKey(
|
|
||||||
editor.vim,
|
editor.vim,
|
||||||
key,
|
key,
|
||||||
injector.executionContextManager.onEditor(editor.vim, entry.context.vim),
|
injector.executionContextManager.onEditor(editor.vim, entry.context.vim),
|
||||||
keyHandler.keyHandlerState,
|
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
val event = ActionEvent(e.source, e.id, c.toString(), e.getWhen(), e.modifiers)
|
val event = ActionEvent(e.source, e.id, c.toString(), e.getWhen(), e.modifiers)
|
||||||
|
@ -36,12 +36,10 @@ internal class ExShortcutKeyAction(private val exEntryPanel: ExEntryPanel) : Dum
|
|||||||
val keyStroke = getKeyStroke(e)
|
val keyStroke = getKeyStroke(e)
|
||||||
if (keyStroke != null) {
|
if (keyStroke != null) {
|
||||||
val editor = exEntryPanel.entry.editor
|
val editor = exEntryPanel.entry.editor
|
||||||
val keyHandler = KeyHandler.getInstance()
|
KeyHandler.getInstance().handleKey(
|
||||||
keyHandler.handleKey(
|
|
||||||
editor.vim,
|
editor.vim,
|
||||||
keyStroke,
|
keyStroke,
|
||||||
injector.executionContextManager.onEditor(editor.vim, e.dataContext.vim),
|
injector.executionContextManager.onEditor(editor.vim, e.dataContext.vim),
|
||||||
keyHandler.keyHandlerState
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -121,11 +121,16 @@ public class ExTextField extends JTextField {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void setType(@NotNull String type) {
|
void setType(@NotNull String type) {
|
||||||
String hkey = switch (type.charAt(0)) {
|
String hkey = null;
|
||||||
case '/', '?' -> HistoryConstants.SEARCH;
|
switch (type.charAt(0)) {
|
||||||
case ':' -> HistoryConstants.COMMAND;
|
case '/':
|
||||||
default -> null;
|
case '?':
|
||||||
};
|
hkey = HistoryConstants.SEARCH;
|
||||||
|
break;
|
||||||
|
case ':':
|
||||||
|
hkey = HistoryConstants.COMMAND;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (hkey != null) {
|
if (hkey != null) {
|
||||||
history = VimPlugin.getHistory().getEntries(hkey, 0, 0);
|
history = VimPlugin.getHistory().getEntries(hkey, 0, 0);
|
||||||
@ -135,7 +140,7 @@ public class ExTextField extends JTextField {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Stores the current text for use in filtering history. Required for scrolling through multiple history entries
|
* Stores the current text for use in filtering history. Required for scrolling through multiple history entries
|
||||||
* <p>
|
*
|
||||||
* Called whenever the text is changed, either by typing, or by special characters altering the text (e.g. Delete)
|
* Called whenever the text is changed, either by typing, or by special characters altering the text (e.g. Delete)
|
||||||
*/
|
*/
|
||||||
void saveLastEntry() {
|
void saveLastEntry() {
|
||||||
@ -299,10 +304,7 @@ public class ExTextField extends JTextField {
|
|||||||
*/
|
*/
|
||||||
void cancel() {
|
void cancel() {
|
||||||
clearCurrentAction();
|
clearCurrentAction();
|
||||||
Editor editor = EditorHolderService.getInstance().getEditor();
|
VimPlugin.getProcess().cancelExEntry(new IjVimEditor(EditorHolderService.getInstance().getEditor()), true);
|
||||||
if (editor != null) {
|
|
||||||
VimPlugin.getProcess().cancelExEntry(new IjVimEditor(editor), true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCurrentAction(@NotNull MultiStepAction action, char pendingIndicator) {
|
public void setCurrentAction(@NotNull MultiStepAction action, char pendingIndicator) {
|
||||||
@ -320,7 +322,7 @@ public class ExTextField extends JTextField {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Text to show while composing a digraph or inserting a literal or register
|
* Text to show while composing a digraph or inserting a literal or register
|
||||||
* <p>
|
*
|
||||||
* The prompt character is inserted directly into the text of the text field, rather than drawn over the top of the
|
* The prompt character is inserted directly into the text of the text field, rather than drawn over the top of the
|
||||||
* current character. When the action has been completed, the new character(s) are either inserted or overwritten,
|
* current character. When the action has been completed, the new character(s) are either inserted or overwritten,
|
||||||
* depending on the insert/overwrite status of the text field. This mimics Vim's behaviour.
|
* depending on the insert/overwrite status of the text field. This mimics Vim's behaviour.
|
||||||
@ -489,7 +491,7 @@ public class ExTextField extends JTextField {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates the bounds of the caret and repaints those bounds.
|
* Updates the bounds of the caret and repaints those bounds.
|
||||||
* <p>
|
*
|
||||||
* This method is not guaranteed to be called before paint(). The bounds are for use by repaint().
|
* This method is not guaranteed to be called before paint(). The bounds are for use by repaint().
|
||||||
*
|
*
|
||||||
* @param r The current location of the caret, usually provided by MapToView. The x and y appear to be the upper
|
* @param r The current location of the caret, usually provided by MapToView. The x and y appear to be the upper
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user