mirror of
https://github.com/chylex/IntelliJ-IdeaVim.git
synced 2025-08-17 16:31:45 +02:00
Compare commits
64 Commits
0f0a73c139
...
b7c1ba4f02
Author | SHA1 | Date | |
---|---|---|---|
b7c1ba4f02
|
|||
fca7b518b3
|
|||
8aa4178449
|
|||
2e035f1260
|
|||
c5f17a68f5
|
|||
68b7788fe4
|
|||
3299059ab9
|
|||
548ed30b5b
|
|||
b171ccb96c
|
|||
93affef6d3
|
|||
0b788153cd
|
|||
70d8167e17
|
|||
67c3dec51b
|
|||
3dab706f37
|
|||
5228bca65e
|
|||
853a208eba
|
|||
fd9297edb1
|
|||
e01e4d8ecd
|
|||
b304692c4e
|
|||
05b9f44a0b
|
|||
d878b119c4
|
|||
def57128b0
|
|||
fd4422bf95
|
|||
d10a0c4ee7
|
|||
![]() |
f12b0b04f6 | ||
![]() |
ea4fc85e5b | ||
![]() |
4af8fc1868 | ||
![]() |
1482ac0335 | ||
![]() |
79168b00f3 | ||
![]() |
07990847c6 | ||
![]() |
8c40e19c44 | ||
![]() |
371769c508 | ||
![]() |
7ee34d0b27 | ||
![]() |
d1ec7d617d | ||
![]() |
898fd0537d | ||
![]() |
353603b546 | ||
![]() |
2f7f0dcacb | ||
![]() |
af9023af4b | ||
![]() |
c393c902b2 | ||
![]() |
c355cb7ed7 | ||
![]() |
0803a1c195 | ||
![]() |
5208412b46 | ||
![]() |
78c463cf7b | ||
![]() |
8f5a44bf44 | ||
![]() |
2377408028 | ||
![]() |
246425b1fb | ||
![]() |
4eadfc1fba | ||
![]() |
d3c945cd6d | ||
![]() |
2ac46129ac | ||
![]() |
c8d40be1ce | ||
![]() |
97159a33fe | ||
![]() |
861d585102 | ||
![]() |
126925b4eb | ||
![]() |
9302c0a057 | ||
![]() |
ddea72f803 | ||
![]() |
e991aa922c | ||
![]() |
5ffaa7b084 | ||
![]() |
0d4183129d | ||
![]() |
8a7fbac389 | ||
![]() |
dbab006f83 | ||
![]() |
3149de7b73 | ||
![]() |
28a71f0e09 | ||
![]() |
fc7d4e614b | ||
![]() |
5b1aade876 |
3
.idea/runConfigurations/IdeaVim_tests.xml
generated
3
.idea/runConfigurations/IdeaVim_tests.xml
generated
@@ -5,7 +5,7 @@
|
||||
<option name="executionName" />
|
||||
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
||||
<option name="externalSystemIdString" value="GRADLE" />
|
||||
<option name="scriptParameters" value="" />
|
||||
<option name="scriptParameters" value="-x :tests:property-tests:test -x :tests:long-running-tests:test" />
|
||||
<option name="taskDescriptions">
|
||||
<list />
|
||||
</option>
|
||||
@@ -19,6 +19,7 @@
|
||||
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
|
||||
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
|
||||
<DebugAllEnabled>false</DebugAllEnabled>
|
||||
<RunAsTest>false</RunAsTest>
|
||||
<method v="2" />
|
||||
</configuration>
|
||||
</component>
|
1
.teamcity/_Self/buildTypes/Compatibility.kt
vendored
1
.teamcity/_Self/buildTypes/Compatibility.kt
vendored
@@ -45,6 +45,7 @@ object Compatibility : IdeaVimBuildType({
|
||||
java -jar verifier1/verifier-cli-dev-all-2.jar check-plugin '${'$'}com.julienphalip.ideavim.functiontextobj' [latest-IU] -team-city
|
||||
java -jar verifier1/verifier-cli-dev-all-2.jar check-plugin '${'$'}com.miksuki.HighlightCursor' [latest-IU] -team-city
|
||||
java -jar verifier1/verifier-cli-dev-all-2.jar check-plugin '${'$'}com.ugarosa.idea.edgemotion' [latest-IU] -team-city
|
||||
java -jar verifier1/verifier-cli-dev-all-2.jar check-plugin '${'$'}cn.mumukehao.plugin' [latest-IU] -team-city
|
||||
""".trimIndent()
|
||||
}
|
||||
}
|
||||
|
2
.teamcity/_Self/buildTypes/LongRunning.kt
vendored
2
.teamcity/_Self/buildTypes/LongRunning.kt
vendored
@@ -25,7 +25,7 @@ object LongRunning : IdeaVimBuildType({
|
||||
|
||||
steps {
|
||||
gradle {
|
||||
tasks = "clean :tests:long-running-tests:testLongRunning"
|
||||
tasks = "clean :tests:long-running-tests:test"
|
||||
buildFile = ""
|
||||
enableStacktrace = true
|
||||
jdkHome = "/usr/lib/jvm/java-21-amazon-corretto"
|
||||
|
2
.teamcity/_Self/buildTypes/Nvim.kt
vendored
2
.teamcity/_Self/buildTypes/Nvim.kt
vendored
@@ -39,7 +39,7 @@ object Nvim : IdeaVimBuildType({
|
||||
""".trimIndent()
|
||||
}
|
||||
gradle {
|
||||
tasks = "clean test -Dnvim"
|
||||
tasks = "clean test -x :tests:property-tests:test -x :tests:long-running-tests:test -Dnvim"
|
||||
buildFile = ""
|
||||
enableStacktrace = true
|
||||
jdkHome = "/usr/lib/jvm/java-21-amazon-corretto"
|
||||
|
2
.teamcity/_Self/buildTypes/PropertyBased.kt
vendored
2
.teamcity/_Self/buildTypes/PropertyBased.kt
vendored
@@ -25,7 +25,7 @@ object PropertyBased : IdeaVimBuildType({
|
||||
steps {
|
||||
gradle {
|
||||
clearConditions()
|
||||
tasks = "clean :tests:property-tests:testPropertyBased"
|
||||
tasks = "clean :tests:property-tests:test"
|
||||
buildFile = ""
|
||||
enableStacktrace = true
|
||||
jdkHome = "/usr/lib/jvm/java-21-amazon-corretto"
|
||||
|
2
.teamcity/_Self/buildTypes/ReleasePlugin.kt
vendored
2
.teamcity/_Self/buildTypes/ReleasePlugin.kt
vendored
@@ -115,7 +115,7 @@ sealed class ReleasePlugin(private val releaseType: String) : IdeaVimBuildType({
|
||||
}
|
||||
script {
|
||||
name = "Run tests"
|
||||
scriptContent = "./gradlew test"
|
||||
scriptContent = "./gradlew test -x :tests:property-tests:test -x :tests:long-running-tests:test"
|
||||
}
|
||||
gradle {
|
||||
name = "Publish release"
|
||||
|
@@ -40,7 +40,7 @@ open class TestingBuildType(
|
||||
steps {
|
||||
gradle {
|
||||
clearConditions()
|
||||
tasks = "clean test"
|
||||
tasks = "clean test -x :tests:property-tests:test -x :tests:long-running-tests:test"
|
||||
buildFile = ""
|
||||
enableStacktrace = true
|
||||
jdkHome = "/usr/lib/jvm/java-21-amazon-corretto"
|
||||
|
2
.teamcity/_Self/subprojects/GitHub.kt
vendored
2
.teamcity/_Self/subprojects/GitHub.kt
vendored
@@ -15,7 +15,7 @@ object GitHub : Project({
|
||||
name = "Pull Requests checks"
|
||||
description = "Automatic checking of GitHub Pull Requests"
|
||||
|
||||
buildType(GithubBuildType("clean test", "Tests"))
|
||||
buildType(GithubBuildType("clean test -x :tests:property-tests:test -x :tests:long-running-tests:test", "Tests"))
|
||||
})
|
||||
|
||||
class GithubBuildType(command: String, desc: String) : IdeaVimBuildType({
|
||||
|
@@ -614,6 +614,14 @@ Contributors:
|
||||
[![icon][github]](https://github.com/Malandril)
|
||||
|
||||
Thomas Canava
|
||||
* [![icon][mail]](mailto:xinhe.wang@jetbrains.com)
|
||||
[![icon][github]](https://github.com/wxh06)
|
||||
|
||||
Xinhe Wang
|
||||
* [![icon][mail]](mailto:zuber.kuba@gmail.com)
|
||||
[![icon][github]](https://github.com/zuberol)
|
||||
|
||||
Jakub Zuber
|
||||
|
||||
Previous contributors:
|
||||
|
||||
|
@@ -65,7 +65,7 @@ We've prepared some useful configurations for you:
|
||||
And here are useful gradle commands:
|
||||
|
||||
* `./gradlew runIde` — start the dev version of IntelliJ IDEA with IdeaVim installed.
|
||||
* `./gradlew test` — run tests.
|
||||
* `./gradlew test -x :tests:property-tests:test -x :tests:long-running-tests:test` — run tests.
|
||||
* `./gradlew buildPlugin` — build the plugin. The result will be located in `build/distributions`. This file can be
|
||||
installed by using `Settings | Plugin | >Gear Icon< | Install Plugin from Disk...`. You can stay with your personal build
|
||||
for a few days or send it to a friend for testing.
|
||||
|
@@ -8,7 +8,7 @@
|
||||
|
||||
plugins {
|
||||
kotlin("jvm")
|
||||
kotlin("plugin.serialization") version "2.0.21"
|
||||
kotlin("plugin.serialization") version "2.2.0"
|
||||
}
|
||||
|
||||
val kotlinxSerializationVersion: String by project
|
||||
@@ -21,7 +21,7 @@ repositories {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly("com.google.devtools.ksp:symbol-processing-api:2.1.21-2.0.1")
|
||||
compileOnly("com.google.devtools.ksp:symbol-processing-api:2.1.21-2.0.2")
|
||||
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json-jvm:$kotlinxSerializationVersion") {
|
||||
// kotlin stdlib is provided by IJ, so there is no need to include it into the distribution
|
||||
exclude("org.jetbrains.kotlin", "kotlin-stdlib")
|
||||
|
@@ -35,6 +35,8 @@ import org.intellij.markdown.ast.impl.ListCompositeNode
|
||||
import org.jetbrains.changelog.Changelog
|
||||
import org.jetbrains.intellij.platform.gradle.TestFrameworkType
|
||||
import org.jetbrains.intellij.platform.gradle.tasks.aware.SplitModeAware
|
||||
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
|
||||
import org.jetbrains.kotlin.gradle.dsl.KotlinVersion
|
||||
import org.kohsuke.github.GHUser
|
||||
import java.net.HttpURLConnection
|
||||
import java.net.URL
|
||||
@@ -46,19 +48,19 @@ buildscript {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:2.0.21")
|
||||
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:2.2.0")
|
||||
classpath("com.github.AlexPl292:mark-down-to-slack:1.1.2")
|
||||
classpath("org.eclipse.jgit:org.eclipse.jgit:6.6.0.202305301015-r")
|
||||
|
||||
// This is needed for jgit to connect to ssh
|
||||
classpath("org.eclipse.jgit:org.eclipse.jgit.ssh.apache:7.2.1.202505142326-r")
|
||||
classpath("org.eclipse.jgit:org.eclipse.jgit.ssh.apache:7.3.0.202506031305-r")
|
||||
classpath("org.kohsuke:github-api:1.305")
|
||||
|
||||
classpath("io.ktor:ktor-client-core:3.1.3")
|
||||
classpath("io.ktor:ktor-client-cio:3.1.3")
|
||||
classpath("io.ktor:ktor-client-auth:3.1.3")
|
||||
classpath("io.ktor:ktor-client-content-negotiation:3.1.3")
|
||||
classpath("io.ktor:ktor-serialization-kotlinx-json:3.1.3")
|
||||
classpath("io.ktor:ktor-client-core:3.2.2")
|
||||
classpath("io.ktor:ktor-client-cio:3.2.2")
|
||||
classpath("io.ktor:ktor-client-auth:3.2.2")
|
||||
classpath("io.ktor:ktor-client-content-negotiation:3.2.2")
|
||||
classpath("io.ktor:ktor-serialization-kotlinx-json:3.2.2")
|
||||
|
||||
// This comes from the changelog plugin
|
||||
// classpath("org.jetbrains:markdown:0.3.1")
|
||||
@@ -67,7 +69,7 @@ buildscript {
|
||||
|
||||
plugins {
|
||||
java
|
||||
kotlin("jvm") version "2.0.21"
|
||||
kotlin("jvm") version "2.2.0"
|
||||
application
|
||||
id("java-test-fixtures")
|
||||
|
||||
@@ -79,7 +81,7 @@ plugins {
|
||||
id("org.jetbrains.changelog") version "2.2.1"
|
||||
id("org.jetbrains.kotlinx.kover") version "0.6.1"
|
||||
id("com.dorongold.task-tree") version "4.0.1"
|
||||
id("com.google.devtools.ksp") version "2.0.21-1.0.25"
|
||||
id("com.google.devtools.ksp") version "2.2.0-2.0.2"
|
||||
}
|
||||
|
||||
val moduleSources by configurations.registering
|
||||
@@ -140,6 +142,11 @@ dependencies {
|
||||
plugin("com.intellij.classic.ui", "251.23774.318")
|
||||
|
||||
bundledPlugins("org.jetbrains.plugins.terminal")
|
||||
|
||||
// VERSION UPDATE: This module is required since 2025.2
|
||||
if (ideaVersion == "LATEST-EAP-SNAPSHOT") {
|
||||
bundledModule("intellij.spellchecker")
|
||||
}
|
||||
}
|
||||
|
||||
moduleSources(project(":vim-engine", "sourcesJarArtifacts"))
|
||||
@@ -159,19 +166,19 @@ dependencies {
|
||||
testFixturesImplementation("org.jetbrains.kotlin:kotlin-test:$kotlinVersion")
|
||||
|
||||
// https://mvnrepository.com/artifact/org.mockito.kotlin/mockito-kotlin
|
||||
testImplementation("org.mockito.kotlin:mockito-kotlin:5.4.0")
|
||||
testImplementation("org.mockito.kotlin:mockito-kotlin:6.0.0")
|
||||
|
||||
testImplementation("org.junit.jupiter:junit-jupiter-api:5.13.0")
|
||||
testImplementation("org.junit.jupiter:junit-jupiter-engine:5.13.0")
|
||||
testImplementation("org.junit.jupiter:junit-jupiter-params:5.13.0")
|
||||
testFixturesImplementation("org.junit.jupiter:junit-jupiter-api:5.13.0")
|
||||
testFixturesImplementation("org.junit.jupiter:junit-jupiter-engine:5.13.0")
|
||||
testFixturesImplementation("org.junit.jupiter:junit-jupiter-params:5.13.0")
|
||||
testImplementation("org.junit.jupiter:junit-jupiter-api:5.13.3")
|
||||
testImplementation("org.junit.jupiter:junit-jupiter-engine:5.13.3")
|
||||
testImplementation("org.junit.jupiter:junit-jupiter-params:5.13.3")
|
||||
testFixturesImplementation("org.junit.jupiter:junit-jupiter-api:5.13.3")
|
||||
testFixturesImplementation("org.junit.jupiter:junit-jupiter-engine:5.13.3")
|
||||
testFixturesImplementation("org.junit.jupiter:junit-jupiter-params:5.13.3")
|
||||
|
||||
// Temp workaround suggested in https://plugins.jetbrains.com/docs/intellij/tools-intellij-platform-gradle-plugin-faq.html#junit5-test-framework-refers-to-junit4
|
||||
// Can be removed when IJPL-159134 is fixed
|
||||
// testRuntimeOnly("junit:junit:4.13.2")
|
||||
testImplementation("org.junit.vintage:junit-vintage-engine:5.13.0")
|
||||
testImplementation("org.junit.vintage:junit-vintage-engine:5.13.2")
|
||||
// testFixturesImplementation("org.junit.vintage:junit-vintage-engine:5.10.3")
|
||||
}
|
||||
|
||||
@@ -221,38 +228,6 @@ tasks {
|
||||
options.encoding = "UTF-8"
|
||||
}
|
||||
|
||||
compileKotlin {
|
||||
kotlinOptions {
|
||||
jvmTarget = javaVersion
|
||||
// See https://plugins.jetbrains.com/docs/intellij/using-kotlin.html#kotlin-standard-library
|
||||
// For the list of bundled versions
|
||||
apiVersion = "2.0"
|
||||
freeCompilerArgs = listOf(
|
||||
"-Xjvm-default=all-compatibility",
|
||||
|
||||
// Needed to compile the AceJump which uses kotlin beta
|
||||
// Without these two option compilation fails
|
||||
"-Xskip-prerelease-check",
|
||||
"-Xallow-unstable-dependencies",
|
||||
)
|
||||
// allWarningsAsErrors = true
|
||||
}
|
||||
}
|
||||
|
||||
compileTestKotlin {
|
||||
enabled = false
|
||||
|
||||
kotlinOptions {
|
||||
jvmTarget = javaVersion
|
||||
apiVersion = "2.0"
|
||||
|
||||
// Needed to compile the AceJump which uses kotlin beta
|
||||
// Without these two option compilation fails
|
||||
freeCompilerArgs += listOf("-Xskip-prerelease-check", "-Xallow-unstable-dependencies")
|
||||
// allWarningsAsErrors = true
|
||||
}
|
||||
}
|
||||
|
||||
// Note that this will run the plugin installed in the IDE specified in dependencies. To run in a different IDE, use
|
||||
// a custom task (see below)
|
||||
runIde {
|
||||
@@ -326,6 +301,23 @@ kotlin {
|
||||
jvmToolchain {
|
||||
languageVersion.set(JavaLanguageVersion.of(javaVersion))
|
||||
}
|
||||
|
||||
compilerOptions {
|
||||
jvmTarget.set(JvmTarget.fromTarget(javaVersion))
|
||||
|
||||
// See https://plugins.jetbrains.com/docs/intellij/using-kotlin.html#kotlin-standard-library
|
||||
// For the list of bundled versions
|
||||
apiVersion.set(KotlinVersion.KOTLIN_2_0)
|
||||
freeCompilerArgs = listOf(
|
||||
"-Xjvm-default=all-compatibility",
|
||||
|
||||
// Needed to compile the AceJump which uses kotlin beta
|
||||
// Without these two option compilation fails
|
||||
"-Xskip-prerelease-check",
|
||||
"-Xallow-unstable-dependencies",
|
||||
)
|
||||
// allWarningsAsErrors = true
|
||||
}
|
||||
}
|
||||
|
||||
gradle.projectsEvaluated {
|
||||
|
@@ -20,7 +20,7 @@ ideaVersion=2025.1
|
||||
# Values for type: https://plugins.jetbrains.com/docs/intellij/tools-gradle-intellij-plugin.html#intellij-extension-type
|
||||
ideaType=IC
|
||||
instrumentPluginCode=true
|
||||
version=chylex-49
|
||||
version=chylex-50
|
||||
javaVersion=21
|
||||
remoteRobotVersion=0.11.23
|
||||
antlrVersion=4.10.1
|
||||
@@ -28,7 +28,7 @@ antlrVersion=4.10.1
|
||||
|
||||
# Please don't forget to update kotlin version in buildscript section
|
||||
# Also update kotlinxSerializationVersion version
|
||||
kotlinVersion=2.0.21
|
||||
kotlinVersion=2.2.0
|
||||
publishToken=token
|
||||
publishChannels=eap
|
||||
|
||||
|
@@ -20,27 +20,25 @@ repositories {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly("org.jetbrains.kotlin:kotlin-stdlib:2.1.21")
|
||||
compileOnly("org.jetbrains.kotlin:kotlin-stdlib:2.2.0")
|
||||
|
||||
implementation("io.ktor:ktor-client-core:3.1.3")
|
||||
implementation("io.ktor:ktor-client-cio:3.1.3")
|
||||
implementation("io.ktor:ktor-client-content-negotiation:3.1.3")
|
||||
implementation("io.ktor:ktor-serialization-kotlinx-json:3.1.3")
|
||||
implementation("io.ktor:ktor-client-auth:3.1.3")
|
||||
implementation("io.ktor:ktor-client-core:3.2.2")
|
||||
implementation("io.ktor:ktor-client-cio:3.2.2")
|
||||
implementation("io.ktor:ktor-client-content-negotiation:3.2.2")
|
||||
implementation("io.ktor:ktor-serialization-kotlinx-json:3.2.2")
|
||||
implementation("io.ktor:ktor-client-auth:3.2.2")
|
||||
implementation("org.eclipse.jgit:org.eclipse.jgit:6.6.0.202305301015-r")
|
||||
|
||||
// This is needed for jgit to connect to ssh
|
||||
implementation("org.eclipse.jgit:org.eclipse.jgit.ssh.apache:7.2.1.202505142326-r")
|
||||
implementation("org.eclipse.jgit:org.eclipse.jgit.ssh.apache:7.3.0.202506031305-r")
|
||||
implementation("com.vdurmont:semver4j:3.1.0")
|
||||
}
|
||||
|
||||
val releaseType: String? by project
|
||||
|
||||
tasks {
|
||||
compileKotlin {
|
||||
kotlinOptions {
|
||||
freeCompilerArgs = listOf("-Xjvm-default=all-compatibility")
|
||||
}
|
||||
kotlin {
|
||||
compilerOptions {
|
||||
freeCompilerArgs = listOf("-Xjvm-default=all-compatibility")
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -45,6 +45,8 @@ val knownPlugins = setOf(
|
||||
"com.julienphalip.ideavim.functiontextobj", // https://plugins.jetbrains.com/plugin/25897-vim-functiontextobj
|
||||
"com.miksuki.HighlightCursor", // https://plugins.jetbrains.com/plugin/26743-highlightcursor
|
||||
"com.ugarosa.idea.edgemotion", // https://plugins.jetbrains.com/plugin/27211-edgemotion
|
||||
|
||||
"cn.mumukehao.plugin",
|
||||
)
|
||||
|
||||
suspend fun main() {
|
||||
|
@@ -1,52 +0,0 @@
|
||||
package com.maddyhome.idea.vim.action
|
||||
|
||||
import com.intellij.openapi.actionSystem.ActionUpdateThread
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent
|
||||
import com.intellij.openapi.command.UndoConfirmationPolicy
|
||||
import com.intellij.openapi.command.WriteCommandAction
|
||||
import com.intellij.openapi.fileEditor.TextEditor
|
||||
import com.intellij.openapi.fileEditor.ex.FileEditorManagerEx
|
||||
import com.intellij.openapi.project.DumbAwareAction
|
||||
import com.maddyhome.idea.vim.KeyHandler
|
||||
import com.maddyhome.idea.vim.api.injector
|
||||
import com.maddyhome.idea.vim.newapi.IjEditorExecutionContext
|
||||
import com.maddyhome.idea.vim.newapi.vim
|
||||
import com.maddyhome.idea.vim.state.mode.Mode
|
||||
|
||||
class VimRunLastMacroInOpenFiles : DumbAwareAction() {
|
||||
override fun update(e: AnActionEvent) {
|
||||
val lastRegister = injector.macro.lastRegister
|
||||
val isEnabled = lastRegister != 0.toChar()
|
||||
|
||||
e.presentation.isEnabled = isEnabled
|
||||
e.presentation.text = if (isEnabled) "Run Macro '${lastRegister}' in Open Files" else "Run Last Macro in Open Files"
|
||||
}
|
||||
|
||||
override fun getActionUpdateThread(): ActionUpdateThread {
|
||||
return ActionUpdateThread.EDT
|
||||
}
|
||||
|
||||
override fun actionPerformed(e: AnActionEvent) {
|
||||
val project = e.project ?: return
|
||||
val fileEditorManager = FileEditorManagerEx.getInstanceExIfCreated(project) ?: return
|
||||
val editors = fileEditorManager.allEditors.filterIsInstance<TextEditor>()
|
||||
|
||||
WriteCommandAction.writeCommandAction(project)
|
||||
.withName(e.presentation.text)
|
||||
.withGlobalUndo()
|
||||
.withUndoConfirmationPolicy(UndoConfirmationPolicy.REQUEST_CONFIRMATION)
|
||||
.run<RuntimeException> {
|
||||
val reg = injector.macro.lastRegister
|
||||
|
||||
for (editor in editors) {
|
||||
fileEditorManager.openFile(editor.file, true)
|
||||
|
||||
val vimEditor = editor.editor.vim
|
||||
vimEditor.mode = Mode.NORMAL()
|
||||
KeyHandler.getInstance().reset(vimEditor)
|
||||
|
||||
injector.macro.playbackRegister(vimEditor, IjEditorExecutionContext(e.dataContext), reg, 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,67 @@
|
||||
package com.maddyhome.idea.vim.action.macro
|
||||
|
||||
import com.intellij.openapi.command.CommandProcessor
|
||||
import com.intellij.openapi.command.UndoConfirmationPolicy
|
||||
import com.intellij.openapi.command.impl.FinishMarkAction
|
||||
import com.intellij.openapi.command.impl.StartMarkAction
|
||||
import com.intellij.openapi.fileEditor.TextEditor
|
||||
import com.intellij.openapi.fileEditor.ex.FileEditorManagerEx
|
||||
import com.intellij.vim.annotations.CommandOrMotion
|
||||
import com.intellij.vim.annotations.Mode
|
||||
import com.maddyhome.idea.vim.KeyHandler
|
||||
import com.maddyhome.idea.vim.api.ExecutionContext
|
||||
import com.maddyhome.idea.vim.api.VimEditor
|
||||
import com.maddyhome.idea.vim.api.injector
|
||||
import com.maddyhome.idea.vim.command.Argument
|
||||
import com.maddyhome.idea.vim.command.Command
|
||||
import com.maddyhome.idea.vim.command.OperatorArguments
|
||||
import com.maddyhome.idea.vim.handler.VimActionHandler
|
||||
import com.maddyhome.idea.vim.newapi.ij
|
||||
import com.maddyhome.idea.vim.newapi.vim
|
||||
|
||||
@CommandOrMotion(keys = ["z@"], modes = [Mode.NORMAL])
|
||||
class PlaybackRegisterInOpenFilesAction : VimActionHandler.SingleExecution() {
|
||||
override val type: Command.Type = Command.Type.OTHER_SELF_SYNCHRONIZED
|
||||
|
||||
override val argumentType: Argument.Type = Argument.Type.CHARACTER
|
||||
|
||||
private val playbackRegisterAction = PlaybackRegisterAction()
|
||||
|
||||
override fun execute(
|
||||
editor: VimEditor,
|
||||
context: ExecutionContext,
|
||||
cmd: Command,
|
||||
operatorArguments: OperatorArguments,
|
||||
): Boolean {
|
||||
val argument = cmd.argument as? Argument.Character ?: return false
|
||||
|
||||
val project = editor.ij.project ?: return false
|
||||
val fileEditorManager = FileEditorManagerEx.getInstanceExIfCreated(project) ?: return false
|
||||
|
||||
val register = argument.character.let { if (it == '@') injector.macro.lastRegister else it }
|
||||
val commandName = "Execute Macro '$register' in All Open Files"
|
||||
|
||||
val action = Runnable {
|
||||
CommandProcessor.getInstance().markCurrentCommandAsGlobal(project)
|
||||
|
||||
for (textEditor in fileEditorManager.allEditors.filterIsInstance<TextEditor>()) {
|
||||
fileEditorManager.openFile(textEditor.file, true)
|
||||
|
||||
val editor = textEditor.editor
|
||||
val vimEditor = editor.vim
|
||||
|
||||
vimEditor.mode = com.maddyhome.idea.vim.state.mode.Mode.NORMAL()
|
||||
KeyHandler.Companion.getInstance().reset(vimEditor)
|
||||
|
||||
val startMarkAction = StartMarkAction.start(editor, project, commandName)
|
||||
playbackRegisterAction.execute(vimEditor, context, cmd, operatorArguments)
|
||||
FinishMarkAction.finish(project, editor, startMarkAction)
|
||||
}
|
||||
}
|
||||
|
||||
CommandProcessor.getInstance()
|
||||
.executeCommand(project, action, commandName, null, UndoConfirmationPolicy.REQUEST_CONFIRMATION)
|
||||
|
||||
return true
|
||||
}
|
||||
}
|
@@ -455,6 +455,17 @@ internal class NerdTree : VimExtension {
|
||||
tree.scrollRowToVisible(expectedRow)
|
||||
},
|
||||
)
|
||||
registerCommand("gg", NerdAction.Code { project, _, _ ->
|
||||
val tree = ProjectView.getInstance(project).currentProjectViewPane.tree
|
||||
tree.setSelectionRow(0)
|
||||
tree.scrollRowToVisible(0)
|
||||
})
|
||||
registerCommand("G", NerdAction.Code { project, _, _ ->
|
||||
val tree = ProjectView.getInstance(project).currentProjectViewPane.tree
|
||||
val lastRowIndex = tree.rowCount -1
|
||||
tree.setSelectionRow(lastRowIndex)
|
||||
tree.scrollRowToVisible(lastRowIndex)
|
||||
})
|
||||
registerCommand(
|
||||
"NERDTreeMapJumpNextSibling",
|
||||
"<C-J>",
|
||||
|
@@ -134,7 +134,7 @@ internal object IdeaSelectionControl {
|
||||
is Mode.VISUAL -> VimPlugin.getVisualMotion().enterVisualMode(editor.vim, mode.selectionType)
|
||||
is Mode.SELECT -> VimPlugin.getVisualMotion().enterSelectMode(editor.vim, mode.selectionType)
|
||||
is Mode.INSERT -> VimPlugin.getChange()
|
||||
.insertBeforeCursor(editor.vim, injector.executionContextManager.getEditorExecutionContext(editor.vim))
|
||||
.insertBeforeCaret(editor.vim, injector.executionContextManager.getEditorExecutionContext(editor.vim))
|
||||
|
||||
is Mode.NORMAL -> Unit
|
||||
else -> error("Unexpected mode: $mode")
|
||||
|
@@ -61,7 +61,7 @@ class IJEditorFocusListener : EditorListener {
|
||||
|
||||
val switchToInsertMode = Runnable {
|
||||
val context: ExecutionContext = injector.executionContextManager.getEditorExecutionContext(editor)
|
||||
VimPlugin.getChange().insertBeforeCursor(editor, context)
|
||||
VimPlugin.getChange().insertBeforeCaret(editor, context)
|
||||
KeyHandler.getInstance().lastUsedEditorInfo = LastUsedEditorInfo(currentEditorHashCode, true)
|
||||
}
|
||||
if (isCurrentEditorTerminal) {
|
||||
|
@@ -169,7 +169,7 @@ internal object IdeaSpecifics {
|
||||
) {
|
||||
editor?.let {
|
||||
it.vim.mode = Mode.NORMAL()
|
||||
VimPlugin.getChange().insertBeforeCursor(it.vim, event.dataContext.vim)
|
||||
VimPlugin.getChange().insertBeforeCaret(it.vim, event.dataContext.vim)
|
||||
KeyHandler.getInstance().reset(it.vim)
|
||||
}
|
||||
}
|
||||
@@ -223,7 +223,7 @@ internal object IdeaSpecifics {
|
||||
// Enable insert mode if there is no selection in template
|
||||
// Template with selection is handled by [com.maddyhome.idea.vim.group.visual.VisualMotionGroup.controlNonVimSelectionChange]
|
||||
if (editor.vim.inNormalMode) {
|
||||
VimPlugin.getChange().insertBeforeCursor(
|
||||
VimPlugin.getChange().insertBeforeCaret(
|
||||
editor.vim,
|
||||
injector.executionContextManager.getEditorExecutionContext(editor.vim),
|
||||
)
|
||||
|
@@ -20,6 +20,7 @@ import com.intellij.openapi.editor.ex.ScrollingModelEx
|
||||
import com.intellij.openapi.editor.ex.util.EditorUtil
|
||||
import com.intellij.openapi.editor.impl.CaretModelImpl
|
||||
import com.intellij.openapi.editor.impl.EditorImpl
|
||||
import com.intellij.openapi.util.text.StringUtil
|
||||
import com.intellij.openapi.vfs.VirtualFileManager
|
||||
import com.maddyhome.idea.vim.api.BufferPosition
|
||||
import com.maddyhome.idea.vim.api.ExecutionContext
|
||||
@@ -150,7 +151,7 @@ internal class IjVimEditor(editor: Editor) : MutableLinearEditor, VimEditorBase(
|
||||
}
|
||||
}
|
||||
}
|
||||
editor.document.insertString(atPosition, text)
|
||||
editor.document.insertString(atPosition, StringUtil.convertLineSeparators(text, "\n"))
|
||||
}
|
||||
|
||||
override fun replaceString(start: Int, end: Int, newString: String) {
|
||||
|
@@ -135,6 +135,8 @@
|
||||
|
||||
<editorNotificationProvider
|
||||
implementation="com.maddyhome.idea.vim.troubleshooting.AccidentalInstallDetectorEditorNotificationProvider"/>
|
||||
|
||||
<dependencySupport coordinate="configuration" kind="vim" displayName="IdeaVim"/>
|
||||
</extensions>
|
||||
|
||||
<xi:include href="/META-INF/includes/ApplicationServices.xml" xpointer="xpointer(/idea-plugin/*)"/>
|
||||
@@ -142,11 +144,9 @@
|
||||
<xi:include href="/META-INF/includes/VimListeners.xml" xpointer="xpointer(/idea-plugin/*)"/>
|
||||
|
||||
<actions resource-bundle="messages.IdeaVimBundle">
|
||||
<group id="com.chylex.intellij.vim" text="Vim" popup="true">
|
||||
<action id="VimPluginToggle" class="com.maddyhome.idea.vim.action.VimPluginToggleAction">
|
||||
<add-to-group group-id="ToolsMenu" anchor="last"/>
|
||||
<action id="VimPluginToggle" class="com.maddyhome.idea.vim.action.VimPluginToggleAction"/>
|
||||
<action id="VimRunLastMacroInOpenFiles" class="com.maddyhome.idea.vim.action.VimRunLastMacroInOpenFiles"/>
|
||||
</group>
|
||||
</action>
|
||||
|
||||
<!-- Internal -->
|
||||
<!--suppress PluginXmlI18n -->
|
||||
|
@@ -78,5 +78,10 @@
|
||||
"keys": "gJ",
|
||||
"class": "com.maddyhome.idea.vim.action.change.delete.DeleteJoinVisualLinesAction",
|
||||
"modes": "X"
|
||||
},
|
||||
{
|
||||
"keys": "z@",
|
||||
"class": "com.maddyhome.idea.vim.action.macro.PlaybackRegisterInOpenFilesAction",
|
||||
"modes": "N"
|
||||
}
|
||||
]
|
@@ -1144,6 +1144,12 @@ $c tw${c}o
|
||||
"O${c}NcE thIs ${c}TEXt wIlL n${c}Ot lOoK s${c}O rIdIcuLoUs\n",
|
||||
)
|
||||
assertState("O${c}nce this text will n${c}ot look s${c}o ridiculous\n")
|
||||
|
||||
typeTextInFile(
|
||||
injector.parser.parseKeys("v2wgu"),
|
||||
"O${c}NcE thIs ${c}TEXt wIlL n${c}Ot lOoK s${c}O rIdIcuLoUs\n",
|
||||
)
|
||||
assertState("O${c}nce this text will n${c}ot look s${c}o ridiculous\n")
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -1180,6 +1186,12 @@ $c tw${c}o
|
||||
"O${c}NcE thIs ${c}TEXt wIlL N${c}Ot lOoK S${c}O rIdIcuLoUs\n",
|
||||
)
|
||||
assertState("O${c}NCE THIS TEXT WILL N${c}OT LOOK S${c}O RIDICULOUS\n")
|
||||
|
||||
typeTextInFile(
|
||||
injector.parser.parseKeys("v2wgU"),
|
||||
"O${c}NcE thIs ${c}TEXt wIlL N${c}Ot lOoK S${c}O rIdIcuLoUs\n",
|
||||
)
|
||||
assertState("O${c}NCE THIS TEXT WILL N${c}OT LOOK S${c}O RIDICULOUS\n")
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@@ -320,4 +320,61 @@ class ChangeCaseToggleCharacterActionTest : VimTestCase() {
|
||||
enterCommand("set nooldundo")
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `test toggle case line caret position`() {
|
||||
configureByText(" Hello ${c}World")
|
||||
typeText("g~~")
|
||||
assertState(" ${c}hELLO wORLD")
|
||||
typeText("u")
|
||||
assertState(" Hello ${c}World")
|
||||
|
||||
typeText("^g~~")
|
||||
assertState(" ${c}hELLO wORLD")
|
||||
typeText("u")
|
||||
assertState(" ${c}Hello World")
|
||||
|
||||
typeText("hg~~")
|
||||
assertState(" $c hELLO wORLD")
|
||||
typeText("u")
|
||||
assertState(" $c Hello World")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `test uppercase line caret position`() {
|
||||
configureByText(" Hello ${c}World")
|
||||
typeText("gUU")
|
||||
assertState(" ${c}HELLO WORLD")
|
||||
typeText("u")
|
||||
assertState(" Hello ${c}World")
|
||||
|
||||
typeText("^gUU")
|
||||
assertState(" ${c}HELLO WORLD")
|
||||
typeText("u")
|
||||
assertState(" ${c}Hello World")
|
||||
|
||||
typeText("hgUU")
|
||||
assertState(" $c HELLO WORLD")
|
||||
typeText("u")
|
||||
assertState(" $c Hello World")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `test lowercase line caret position`() {
|
||||
configureByText(" Hello ${c}World")
|
||||
typeText("guu")
|
||||
assertState(" ${c}hello world")
|
||||
typeText("u")
|
||||
assertState(" Hello ${c}World")
|
||||
|
||||
typeText("^guu")
|
||||
assertState(" ${c}hello world")
|
||||
typeText("u")
|
||||
assertState(" ${c}Hello World")
|
||||
|
||||
typeText("hguu")
|
||||
assertState(" $c hello world")
|
||||
typeText("u")
|
||||
assertState(" $c Hello World")
|
||||
}
|
||||
}
|
||||
|
@@ -17,7 +17,7 @@ import org.jetbrains.plugins.ideavim.TestWithoutNeovim
|
||||
import org.jetbrains.plugins.ideavim.VimTestCase
|
||||
import org.junit.jupiter.api.Test
|
||||
|
||||
class VisualBlockInsertActionTest : VimTestCase() {
|
||||
class VisualInsertActionTest : VimTestCase() {
|
||||
// VIM-1379 |CTRL-V| |j| |v_b_I|
|
||||
@TestWithoutNeovim(SkipNeovimReason.VISUAL_BLOCK_MODE)
|
||||
@Test
|
||||
@@ -101,28 +101,70 @@ class VisualBlockInsertActionTest : VimTestCase() {
|
||||
)
|
||||
}
|
||||
|
||||
@TestWithoutNeovim(SkipNeovimReason.VISUAL_BLOCK_MODE)
|
||||
@Test
|
||||
fun `test insert in non block mode`() {
|
||||
doTest(
|
||||
listOf("vwIHello<esc>"),
|
||||
"""
|
||||
${c}A Discovery
|
||||
fun `test insert in non-block visual within single line`() {
|
||||
val before = """
|
||||
| A ${c}Discovery
|
||||
|
||||
${c}I found it in a legendary land
|
||||
all rocks and ${c}lavender and tufted grass,
|
||||
where it was settled on some sodden sand
|
||||
hard by the torrent of a mountain pass.
|
||||
""".trimIndent(),
|
||||
"""
|
||||
Hell${c}oA Discovery
|
||||
| I ${c}found it in a legendary land
|
||||
| all rocks and lavender and tufted grass,
|
||||
| where it was settled on some sodden sand
|
||||
| hard by the torrent of a mountain pass.
|
||||
""".trimMargin()
|
||||
val after = """
|
||||
|Hell${c}o A Discovery
|
||||
|
||||
Hell${c}oI found it in a legendary land
|
||||
Hell${c}oall rocks and lavender and tufted grass,
|
||||
where it was settled on some sodden sand
|
||||
hard by the torrent of a mountain pass.
|
||||
""".trimIndent(),
|
||||
)
|
||||
|Hell${c}o I found it in a legendary land
|
||||
| all rocks and lavender and tufted grass,
|
||||
| where it was settled on some sodden sand
|
||||
| hard by the torrent of a mountain pass.
|
||||
""".trimMargin()
|
||||
doTest(listOf($$"v$IHello<esc>"), before, after)
|
||||
doTest(listOf("VIHello<esc>"), before, after)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `test insert in non-block visual spanning multiple lines down`() {
|
||||
val before = """
|
||||
| A ${c}Discovery
|
||||
|
||||
| I ${c}found it in a legendary land
|
||||
| all rocks and lavender and tufted grass,
|
||||
| where it was settled on some sodden sand
|
||||
| hard by the torrent of a mountain pass.
|
||||
""".trimMargin()
|
||||
val after = """
|
||||
|Hell${c}o A Discovery
|
||||
|
||||
|Hell${c}o I found it in a legendary land
|
||||
| all rocks and lavender and tufted grass,
|
||||
| where it was settled on some sodden sand
|
||||
| hard by the torrent of a mountain pass.
|
||||
""".trimMargin()
|
||||
doTest(listOf("vjIHello<esc>"), before, after)
|
||||
doTest(listOf("VjIHello<esc>"), before, after)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `test insert in non-block visual spanning multiple lines up`() {
|
||||
val before = """
|
||||
| A Discovery
|
||||
|
||||
| I found it in a legendary land
|
||||
| all rocks and lavender and tufted grass${c},
|
||||
| where it was settled on some sodden sand
|
||||
| hard ${c}by the torrent of a mountain pass.
|
||||
""".trimMargin()
|
||||
val after = """
|
||||
| A Discovery
|
||||
|
||||
| I found it in a legendary landHell${c}o
|
||||
| all rocks and lavender and tufted grass,
|
||||
| whereHell${c}o it was settled on some sodden sand
|
||||
| hard by the torrent of a mountain pass.
|
||||
""".trimMargin()
|
||||
doTest(listOf("vkIHello<esc>"), before, after)
|
||||
doTest(listOf("VkIHello<esc>"), before, after)
|
||||
}
|
||||
|
||||
@TestWithoutNeovim(SkipNeovimReason.VISUAL_BLOCK_MODE)
|
@@ -241,12 +241,7 @@ class RegistersCommandTest : VimTestCase() {
|
||||
|
||||
val vimEditor = fixture.editor.vim
|
||||
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
|
||||
injector.registerGroup.saveRegister(
|
||||
vimEditor,
|
||||
context,
|
||||
'+',
|
||||
Register('+', injector.clipboardManager.dumbCopiedText("Lorem ipsum dolor"), SelectionType.LINE_WISE)
|
||||
)
|
||||
injector.registerGroup.saveRegister(vimEditor, context, '+', Register('+', SelectionType.LINE_WISE, "Lorem ipsum dolor", mutableListOf()))
|
||||
val clipboardContent = injector.clipboardManager.dumbCopiedText("clipboard content")
|
||||
injector.clipboardManager.setClipboardContent(vimEditor, context, clipboardContent)
|
||||
typeText("V<Esc>")
|
||||
@@ -453,12 +448,7 @@ class RegistersCommandTest : VimTestCase() {
|
||||
val vimEditor = fixture.editor.vim
|
||||
val context = injector.executionContextManager.getEditorExecutionContext(vimEditor)
|
||||
val clipboardContent = injector.clipboardManager.dumbCopiedText("clipboard content")
|
||||
injector.registerGroup.saveRegister(
|
||||
vimEditor,
|
||||
context,
|
||||
'+',
|
||||
Register('+', injector.clipboardManager.dumbCopiedText("Lorem ipsum dolor"), SelectionType.LINE_WISE)
|
||||
)
|
||||
injector.registerGroup.saveRegister(vimEditor, context, '+', Register('+', SelectionType.LINE_WISE, "Lorem ipsum dolor", mutableListOf()))
|
||||
injector.clipboardManager.setClipboardContent(vimEditor, context, clipboardContent)
|
||||
typeText("V<Esc>")
|
||||
|
||||
|
@@ -32,7 +32,7 @@ dependencies {
|
||||
compileOnly("org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion")
|
||||
testImplementation("org.jetbrains.kotlin:kotlin-test:$kotlinVersion")
|
||||
testImplementation(testFixtures(project(":"))) // The root project
|
||||
testImplementation("org.junit.vintage:junit-vintage-engine:5.13.0")
|
||||
testImplementation("org.junit.vintage:junit-vintage-engine:5.13.2")
|
||||
|
||||
intellijPlatform {
|
||||
// Snapshots don't use installers
|
||||
|
@@ -17,7 +17,7 @@ import org.jetbrains.plugins.ideavim.TestWithoutNeovim
|
||||
import org.jetbrains.plugins.ideavim.VimJavaTestCase
|
||||
import org.junit.jupiter.api.Test
|
||||
|
||||
class VisualBlockInsertActionJavaTest : VimJavaTestCase() {
|
||||
class VisualInsertActionJavaTest : VimJavaTestCase() {
|
||||
// VIM-1110 |CTRL-V| |v_b_i| |zc|
|
||||
@TestWithoutNeovim(SkipNeovimReason.FOLDING)
|
||||
@Test
|
@@ -25,7 +25,7 @@ dependencies {
|
||||
compileOnly("org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion")
|
||||
testImplementation("org.jetbrains.kotlin:kotlin-test:$kotlinVersion")
|
||||
testImplementation(testFixtures(project(":"))) // The root project
|
||||
testImplementation("org.junit.vintage:junit-vintage-engine:5.13.0")
|
||||
testImplementation("org.junit.vintage:junit-vintage-engine:5.13.2")
|
||||
|
||||
intellijPlatform {
|
||||
// Snapshots don't use installers
|
||||
@@ -47,17 +47,8 @@ tasks {
|
||||
// I didn't find a better way to exclude except disabling and defining a new task with a different name
|
||||
// Note that useJUnitTestPlatform() is required to prevent red code
|
||||
test {
|
||||
enabled = false
|
||||
useJUnitPlatform()
|
||||
}
|
||||
|
||||
// The `test` task is automatically set up with IntelliJ goodness. A custom test task needs to be configured for it
|
||||
val testLongRunning by intellijPlatformTesting.testIde.registering {
|
||||
task {
|
||||
group = "verification"
|
||||
useJUnitPlatform()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
java {
|
||||
|
@@ -25,7 +25,7 @@ dependencies {
|
||||
compileOnly("org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion")
|
||||
testImplementation("org.jetbrains.kotlin:kotlin-test:$kotlinVersion")
|
||||
testImplementation(testFixtures(project(":"))) // The root project
|
||||
testImplementation("org.junit.vintage:junit-vintage-engine:5.13.0")
|
||||
testImplementation("org.junit.vintage:junit-vintage-engine:5.13.2")
|
||||
|
||||
intellijPlatform {
|
||||
// Snapshots don't use installers
|
||||
@@ -48,15 +48,6 @@ tasks {
|
||||
// I didn't find a better way to exclude except disabling and defining a new task with a different name
|
||||
test {
|
||||
useJUnitPlatform()
|
||||
enabled = false
|
||||
}
|
||||
|
||||
// The `test` task is automatically set up with IntelliJ goodness. A custom test task needs to be configured for it
|
||||
val testPropertyBased by intellijPlatformTesting.testIde.registering {
|
||||
task {
|
||||
group = "verification"
|
||||
useJUnitPlatform()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -15,7 +15,7 @@ val javaVersion: String by project
|
||||
val remoteRobotVersion: String by project
|
||||
|
||||
dependencies {
|
||||
testFixturesImplementation("org.junit.jupiter:junit-jupiter:5.13.0")
|
||||
testFixturesImplementation("org.junit.jupiter:junit-jupiter:5.13.3")
|
||||
compileOnly("org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion")
|
||||
testFixturesImplementation("org.jetbrains.kotlin:kotlin-test:$kotlinVersion")
|
||||
testFixturesImplementation(testFixtures(project(":"))) // The root project
|
||||
|
@@ -11,6 +11,7 @@ import com.intellij.remoterobot.data.RemoteComponent
|
||||
import com.intellij.remoterobot.fixtures.CommonContainerFixture
|
||||
import com.intellij.remoterobot.fixtures.DefaultXpath
|
||||
import com.intellij.remoterobot.fixtures.FixtureName
|
||||
import com.intellij.remoterobot.fixtures.JButtonFixture
|
||||
import com.intellij.remoterobot.search.locators.byXpath
|
||||
import java.time.Duration
|
||||
|
||||
@@ -28,6 +29,6 @@ class ManageLicensesFrame(remoteRobot: RemoteRobot, remoteComponent: RemoteCompo
|
||||
/// Note: The license code is obfuscated, so we use the class `W`. But a better solution is required.
|
||||
textFields(byXpath("//div[@class='W']")).first().text = System.getenv("RIDER_LICENSE")
|
||||
button("Activate").click()
|
||||
button("Close").click()
|
||||
button(JButtonFixture.byText("Close"), timeout = Duration.ofSeconds(20)).click()
|
||||
}
|
||||
}
|
||||
|
@@ -10,8 +10,8 @@ plugins {
|
||||
java
|
||||
kotlin("jvm")
|
||||
// id("org.jlleitschuh.gradle.ktlint")
|
||||
id("com.google.devtools.ksp") version "2.0.21-1.0.25"
|
||||
kotlin("plugin.serialization") version "2.0.21"
|
||||
id("com.google.devtools.ksp") version "2.2.0-2.0.2"
|
||||
kotlin("plugin.serialization") version "2.2.0"
|
||||
`maven-publish`
|
||||
antlr
|
||||
}
|
||||
@@ -45,13 +45,13 @@ afterEvaluate {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
testImplementation("org.junit.jupiter:junit-jupiter-api:5.13.0")
|
||||
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.13.0")
|
||||
testImplementation("org.junit.jupiter:junit-jupiter-api:5.13.3")
|
||||
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.13.3")
|
||||
|
||||
// Temp workaround suggested in https://plugins.jetbrains.com/docs/intellij/tools-intellij-platform-gradle-plugin-faq.html#junit5-test-framework-refers-to-junit4
|
||||
// Can be removed when IJPL-159134 is fixed
|
||||
// testRuntimeOnly("junit:junit:4.13.2")
|
||||
testRuntimeOnly("org.junit.vintage:junit-vintage-engine:5.13.0")
|
||||
testRuntimeOnly("org.junit.vintage:junit-vintage-engine:5.13.2")
|
||||
|
||||
// https://mvnrepository.com/artifact/org.jetbrains.kotlin/kotlin-test
|
||||
testImplementation("org.jetbrains.kotlin:kotlin-test:$kotlinVersion")
|
||||
@@ -68,7 +68,7 @@ dependencies {
|
||||
|
||||
compileOnly(kotlin("reflect"))
|
||||
|
||||
testImplementation("org.mockito.kotlin:mockito-kotlin:5.4.0")
|
||||
testImplementation("org.mockito.kotlin:mockito-kotlin:6.0.0")
|
||||
}
|
||||
|
||||
tasks {
|
||||
@@ -88,13 +88,13 @@ tasks {
|
||||
named("compileTestKotlin") {
|
||||
dependsOn("generateTestGrammarSource")
|
||||
}
|
||||
}
|
||||
|
||||
compileKotlin {
|
||||
kotlinOptions {
|
||||
apiVersion = "2.0"
|
||||
freeCompilerArgs = listOf("-Xjvm-default=all-compatibility")
|
||||
}
|
||||
}
|
||||
kotlin {
|
||||
compilerOptions {
|
||||
apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_0)
|
||||
freeCompilerArgs = listOf("-Xjvm-default=all-compatibility")
|
||||
}
|
||||
}
|
||||
|
||||
// --- Linting
|
||||
|
@@ -18,10 +18,13 @@ import com.maddyhome.idea.vim.command.Argument
|
||||
import com.maddyhome.idea.vim.command.Command
|
||||
import com.maddyhome.idea.vim.command.DuplicableOperatorAction
|
||||
import com.maddyhome.idea.vim.command.OperatorArguments
|
||||
import com.maddyhome.idea.vim.diagnostic.vimLogger
|
||||
import com.maddyhome.idea.vim.handler.ChangeEditorActionHandler
|
||||
|
||||
@CommandOrMotion(keys = ["gu"], modes = [Mode.NORMAL])
|
||||
class ChangeCaseLowerMotionAction : ChangeEditorActionHandler.ForEachCaret(), DuplicableOperatorAction {
|
||||
private val logger = vimLogger<ChangeCaseLowerMotionAction>()
|
||||
|
||||
override val type: Command.Type = Command.Type.CHANGE
|
||||
|
||||
override val argumentType: Argument.Type = Argument.Type.MOTION
|
||||
@@ -35,15 +38,18 @@ class ChangeCaseLowerMotionAction : ChangeEditorActionHandler.ForEachCaret(), Du
|
||||
argument: Argument?,
|
||||
operatorArguments: OperatorArguments,
|
||||
): Boolean {
|
||||
return argument != null &&
|
||||
injector.changeGroup
|
||||
.changeCaseMotion(
|
||||
editor,
|
||||
caret,
|
||||
context,
|
||||
VimChangeGroup.ChangeCaseType.LOWER,
|
||||
argument,
|
||||
operatorArguments,
|
||||
)
|
||||
if (argument == null || argument !is Argument.Motion) {
|
||||
logger.error("Argument is null or not Argument.Motion. argument=$argument")
|
||||
return false
|
||||
}
|
||||
|
||||
return injector.changeGroup.changeCaseMotion(
|
||||
editor,
|
||||
caret,
|
||||
context,
|
||||
VimChangeGroup.ChangeCaseType.LOWER,
|
||||
argument,
|
||||
operatorArguments,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@@ -18,10 +18,13 @@ import com.maddyhome.idea.vim.command.Argument
|
||||
import com.maddyhome.idea.vim.command.Command
|
||||
import com.maddyhome.idea.vim.command.DuplicableOperatorAction
|
||||
import com.maddyhome.idea.vim.command.OperatorArguments
|
||||
import com.maddyhome.idea.vim.diagnostic.vimLogger
|
||||
import com.maddyhome.idea.vim.handler.ChangeEditorActionHandler
|
||||
|
||||
@CommandOrMotion(keys = ["g~"], modes = [Mode.NORMAL])
|
||||
class ChangeCaseToggleMotionAction : ChangeEditorActionHandler.ForEachCaret(), DuplicableOperatorAction {
|
||||
private val logger = vimLogger<ChangeCaseToggleMotionAction>()
|
||||
|
||||
override val type: Command.Type = Command.Type.CHANGE
|
||||
|
||||
override val argumentType: Argument.Type = Argument.Type.MOTION
|
||||
@@ -35,15 +38,18 @@ class ChangeCaseToggleMotionAction : ChangeEditorActionHandler.ForEachCaret(), D
|
||||
argument: Argument?,
|
||||
operatorArguments: OperatorArguments,
|
||||
): Boolean {
|
||||
return argument != null &&
|
||||
injector.changeGroup
|
||||
.changeCaseMotion(
|
||||
editor,
|
||||
caret,
|
||||
context,
|
||||
VimChangeGroup.ChangeCaseType.TOGGLE,
|
||||
argument,
|
||||
operatorArguments,
|
||||
)
|
||||
if (argument == null || argument !is Argument.Motion) {
|
||||
logger.error("Argument is null or not Argument.Motion. argument=$argument")
|
||||
return false
|
||||
}
|
||||
|
||||
return injector.changeGroup.changeCaseMotion(
|
||||
editor,
|
||||
caret,
|
||||
context,
|
||||
VimChangeGroup.ChangeCaseType.TOGGLE,
|
||||
argument,
|
||||
operatorArguments,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@@ -18,10 +18,13 @@ import com.maddyhome.idea.vim.command.Argument
|
||||
import com.maddyhome.idea.vim.command.Command
|
||||
import com.maddyhome.idea.vim.command.DuplicableOperatorAction
|
||||
import com.maddyhome.idea.vim.command.OperatorArguments
|
||||
import com.maddyhome.idea.vim.diagnostic.vimLogger
|
||||
import com.maddyhome.idea.vim.handler.ChangeEditorActionHandler
|
||||
|
||||
@CommandOrMotion(keys = ["gU"], modes = [Mode.NORMAL])
|
||||
class ChangeCaseUpperMotionAction : ChangeEditorActionHandler.ForEachCaret(), DuplicableOperatorAction {
|
||||
private val logger = vimLogger<ChangeCaseUpperMotionAction>()
|
||||
|
||||
override val type: Command.Type = Command.Type.CHANGE
|
||||
|
||||
override val argumentType: Argument.Type = Argument.Type.MOTION
|
||||
@@ -35,15 +38,18 @@ class ChangeCaseUpperMotionAction : ChangeEditorActionHandler.ForEachCaret(), Du
|
||||
argument: Argument?,
|
||||
operatorArguments: OperatorArguments,
|
||||
): Boolean {
|
||||
return argument != null &&
|
||||
injector.changeGroup
|
||||
.changeCaseMotion(
|
||||
editor,
|
||||
caret,
|
||||
context,
|
||||
VimChangeGroup.ChangeCaseType.UPPER,
|
||||
argument,
|
||||
operatorArguments,
|
||||
)
|
||||
if (argument == null || argument !is Argument.Motion) {
|
||||
logger.error("Argument is null or not Argument.Motion. argument=$argument")
|
||||
return false
|
||||
}
|
||||
|
||||
return injector.changeGroup.changeCaseMotion(
|
||||
editor,
|
||||
caret,
|
||||
context,
|
||||
VimChangeGroup.ChangeCaseType.UPPER,
|
||||
argument,
|
||||
operatorArguments,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@@ -27,7 +27,7 @@ class InsertAfterCursorAction : ChangeEditorActionHandler.SingleExecution() {
|
||||
argument: Argument?,
|
||||
operatorArguments: OperatorArguments,
|
||||
): Boolean {
|
||||
injector.changeGroup.insertAfterCursor(editor, context)
|
||||
injector.changeGroup.insertAfterCaret(editor, context)
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
@@ -47,5 +47,5 @@ private fun insertAtPreviousInsert(editor: VimEditor, context: ExecutionContext)
|
||||
if (motion is Motion.AbsoluteOffset) {
|
||||
caret.moveToOffset(motion.offset)
|
||||
}
|
||||
injector.changeGroup.insertBeforeCursor(editor, context)
|
||||
injector.changeGroup.insertBeforeCaret(editor, context)
|
||||
}
|
||||
|
@@ -29,7 +29,7 @@ class InsertBeforeCursorAction : ChangeEditorActionHandler.SingleExecution() {
|
||||
argument: Argument?,
|
||||
operatorArguments: OperatorArguments,
|
||||
): Boolean {
|
||||
injector.changeGroup.insertBeforeCursor(editor, context)
|
||||
injector.changeGroup.insertBeforeCaret(editor, context)
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
@@ -13,6 +13,7 @@ import com.maddyhome.idea.vim.api.ExecutionContext
|
||||
import com.maddyhome.idea.vim.api.VimCaret
|
||||
import com.maddyhome.idea.vim.api.VimEditor
|
||||
import com.maddyhome.idea.vim.api.injector
|
||||
import com.maddyhome.idea.vim.api.normalizeLine
|
||||
import com.maddyhome.idea.vim.command.Command
|
||||
import com.maddyhome.idea.vim.command.OperatorArguments
|
||||
import com.maddyhome.idea.vim.group.visual.VimSelection
|
||||
@@ -20,10 +21,17 @@ import com.maddyhome.idea.vim.handler.VisualOperatorActionHandler
|
||||
import com.maddyhome.idea.vim.state.mode.SelectionType
|
||||
|
||||
/**
|
||||
* @author vlan
|
||||
* Handles the 'I' command in Visual mode.
|
||||
*
|
||||
* For (linewise) Visual mode, the caret positioning follows these rules (based on observation in Vim):
|
||||
* - If text on multiple lines is selected AND the caret is on the first line (e.g., when selecting from bottom to top),
|
||||
* the caret position remains unchanged
|
||||
* - In all other cases, the caret is moved to the start of the first selected line
|
||||
*
|
||||
* For blockwise Visual mode, it initiates insert at the start of block on each line in the selection
|
||||
*/
|
||||
@CommandOrMotion(keys = ["I"], modes = [Mode.VISUAL])
|
||||
class VisualBlockInsertAction : VisualOperatorActionHandler.SingleExecution() {
|
||||
class VisualInsertAction : VisualOperatorActionHandler.SingleExecution() {
|
||||
override val type: Command.Type = Command.Type.INSERT
|
||||
|
||||
override fun executeForAllCarets(
|
||||
@@ -38,7 +46,17 @@ class VisualBlockInsertAction : VisualOperatorActionHandler.SingleExecution() {
|
||||
return if (vimSelection.type == SelectionType.BLOCK_WISE) {
|
||||
injector.changeGroup.initBlockInsert(editor, context, vimSelection.toVimTextRange(false), false)
|
||||
} else {
|
||||
injector.changeGroup.insertBeforeFirstNonBlank(editor, context)
|
||||
// For visual selections spanning multiple lines, keep caret position if it's on the first line
|
||||
// Otherwise move the caret to the start of the first selected line
|
||||
for ((caret, selection) in caretsAndSelections) {
|
||||
val range = selection.toVimTextRange()
|
||||
val posStart = editor.offsetToBufferPosition(range.startOffset)
|
||||
val nextLineStart = editor.getLineStartOffset(editor.normalizeLine(posStart.line + 1))
|
||||
if (caret.offset >= nextLineStart || nextLineStart >= range.endOffset) {
|
||||
caret.moveToOffset(injector.motion.moveCaretToLineStart(editor, posStart.line))
|
||||
}
|
||||
}
|
||||
injector.changeGroup.insertBeforeCaret(editor, context)
|
||||
true
|
||||
}
|
||||
}
|
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright 2003-2025 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.action.file
|
||||
|
||||
import com.intellij.vim.annotations.CommandOrMotion
|
||||
import com.intellij.vim.annotations.Mode
|
||||
import com.maddyhome.idea.vim.api.ExecutionContext
|
||||
import com.maddyhome.idea.vim.api.VimEditor
|
||||
import com.maddyhome.idea.vim.api.injector
|
||||
import com.maddyhome.idea.vim.command.Command
|
||||
import com.maddyhome.idea.vim.command.OperatorArguments
|
||||
import com.maddyhome.idea.vim.handler.VimActionHandler
|
||||
|
||||
@CommandOrMotion(keys = ["ZQ"], modes = [Mode.NORMAL])
|
||||
class FileCloseAction : VimActionHandler.SingleExecution() {
|
||||
override val type: Command.Type = Command.Type.OTHER_SELF_SYNCHRONIZED
|
||||
|
||||
override fun execute(
|
||||
editor: VimEditor,
|
||||
context: ExecutionContext,
|
||||
cmd: Command,
|
||||
operatorArguments: OperatorArguments,
|
||||
): Boolean {
|
||||
injector.file.closeFile(editor, context)
|
||||
return true
|
||||
}
|
||||
}
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2003-2023 The IdeaVim authors
|
||||
* Copyright 2003-2025 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
|
||||
@@ -16,9 +16,9 @@ import com.maddyhome.idea.vim.command.Command
|
||||
import com.maddyhome.idea.vim.command.OperatorArguments
|
||||
import com.maddyhome.idea.vim.handler.VimActionHandler
|
||||
|
||||
@CommandOrMotion(keys = ["ZQ", "ZZ"], modes = [Mode.NORMAL])
|
||||
@CommandOrMotion(keys = ["ZZ"], modes = [Mode.NORMAL])
|
||||
class FileSaveCloseAction : VimActionHandler.SingleExecution() {
|
||||
override val type: Command.Type = Command.Type.OTHER_WRITABLE
|
||||
override val type: Command.Type = Command.Type.OTHER_SELF_SYNCHRONIZED
|
||||
|
||||
override fun execute(
|
||||
editor: VimEditor,
|
||||
|
@@ -48,7 +48,7 @@ class SelectMotionArrowLeftAction : MotionActionHandler.ForEachCaret() {
|
||||
editor.exitSelectModeNative(false)
|
||||
if (editor.isTemplateActive()) {
|
||||
logger.debug("Template is active. Activate insert mode")
|
||||
injector.changeGroup.insertBeforeCursor(editor, context)
|
||||
injector.changeGroup.insertBeforeCaret(editor, context)
|
||||
if (caret.offset in startSelection..endSelection) {
|
||||
return startSelection.toMotion()
|
||||
}
|
||||
|
@@ -48,7 +48,7 @@ class SelectMotionArrowRightAction : MotionActionHandler.ForEachCaret() {
|
||||
editor.exitSelectModeNative(false)
|
||||
if (editor.isTemplateActive()) {
|
||||
logger.debug("Template is active. Activate insert mode")
|
||||
injector.changeGroup.insertBeforeCursor(editor, context)
|
||||
injector.changeGroup.insertBeforeCaret(editor, context)
|
||||
if (caret.offset in startSelection..endSelection) {
|
||||
return endSelection.toMotion()
|
||||
}
|
||||
|
@@ -23,13 +23,13 @@ import javax.swing.KeyStroke
|
||||
interface VimChangeGroup {
|
||||
fun setInsertRepeat(lines: Int, column: Int, append: Boolean)
|
||||
|
||||
fun insertBeforeCursor(editor: VimEditor, context: ExecutionContext)
|
||||
fun insertBeforeCaret(editor: VimEditor, context: ExecutionContext)
|
||||
|
||||
fun insertBeforeFirstNonBlank(editor: VimEditor, context: ExecutionContext)
|
||||
|
||||
fun insertLineStart(editor: VimEditor, context: ExecutionContext)
|
||||
|
||||
fun insertAfterCursor(editor: VimEditor, context: ExecutionContext)
|
||||
fun insertAfterCaret(editor: VimEditor, context: ExecutionContext)
|
||||
|
||||
fun insertAfterLineEnd(editor: VimEditor, context: ExecutionContext)
|
||||
|
||||
@@ -198,7 +198,7 @@ interface VimChangeGroup {
|
||||
caret: VimCaret,
|
||||
context: ExecutionContext?,
|
||||
type: ChangeCaseType,
|
||||
argument: Argument,
|
||||
argument: Argument.Motion,
|
||||
operatorArguments: OperatorArguments,
|
||||
): Boolean
|
||||
|
||||
|
@@ -401,7 +401,7 @@ abstract class VimChangeGroupBase : VimChangeGroup {
|
||||
* @param editor The editor to insert into
|
||||
* @param context The data context
|
||||
*/
|
||||
override fun insertBeforeCursor(editor: VimEditor, context: ExecutionContext) {
|
||||
override fun insertBeforeCaret(editor: VimEditor, context: ExecutionContext) {
|
||||
initInsert(editor, context, Mode.INSERT)
|
||||
}
|
||||
|
||||
@@ -417,7 +417,7 @@ abstract class VimChangeGroupBase : VimChangeGroup {
|
||||
* @param editor The editor to insert into
|
||||
* @param context The data context
|
||||
*/
|
||||
override fun insertAfterCursor(editor: VimEditor, context: ExecutionContext) {
|
||||
override fun insertAfterCaret(editor: VimEditor, context: ExecutionContext) {
|
||||
for (caret in editor.nativeCarets()) {
|
||||
caret.moveToMotion(injector.motion.getHorizontalMotion(editor, caret, 1, true))
|
||||
}
|
||||
@@ -781,7 +781,7 @@ abstract class VimChangeGroupBase : VimChangeGroup {
|
||||
lambdaEditor.exitSelectModeNative(false)
|
||||
KeyHandler.getInstance().reset(lambdaEditor)
|
||||
if (isPrintableChar(key.keyChar) || activeTemplateWithLeftRightMotion(lambdaEditor, key)) {
|
||||
injector.changeGroup.insertBeforeCursor(lambdaEditor, lambdaContext)
|
||||
injector.changeGroup.insertBeforeCaret(lambdaEditor, lambdaContext)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1302,7 +1302,7 @@ abstract class VimChangeGroupBase : VimChangeGroup {
|
||||
if (type === SelectionType.LINE_WISE) {
|
||||
// Please don't use `getDocument().getText().isEmpty()` because it converts CharSequence into String
|
||||
if (editor.fileSize() == 0L) {
|
||||
insertBeforeCursor(editor, context)
|
||||
insertBeforeCaret(editor, context)
|
||||
} else if (after && !editor.endsWithNewLine()) {
|
||||
insertNewLineBelow(editor, updatedCaret, lp.column)
|
||||
} else {
|
||||
@@ -1315,7 +1315,7 @@ abstract class VimChangeGroupBase : VimChangeGroup {
|
||||
editor.vimChangeActionSwitchMode = Mode.INSERT
|
||||
}
|
||||
} else {
|
||||
insertBeforeCursor(editor, context)
|
||||
insertBeforeCaret(editor, context)
|
||||
}
|
||||
return true
|
||||
}
|
||||
@@ -1867,14 +1867,22 @@ abstract class VimChangeGroupBase : VimChangeGroup {
|
||||
caret: VimCaret,
|
||||
context: ExecutionContext?,
|
||||
type: VimChangeGroup.ChangeCaseType,
|
||||
argument: Argument,
|
||||
argument: Argument.Motion,
|
||||
operatorArguments: OperatorArguments,
|
||||
): Boolean {
|
||||
val range = injector.motion.getMotionRange(
|
||||
editor, caret, context!!, argument,
|
||||
operatorArguments
|
||||
var range = injector.motion.getMotionRange(
|
||||
editor, caret, context!!, argument, operatorArguments
|
||||
)
|
||||
return range != null && changeCaseRange(editor, caret, range, type)
|
||||
if (range == null) return false
|
||||
|
||||
// If the motion is linewise, we need to adjust range.startOffset to match the observed Vim behavior
|
||||
if (argument.isLinewiseMotion()) {
|
||||
val pos = editor.offsetToBufferPosition(range.startOffset)
|
||||
// The leftmost non-whitespace character OR the current caret position, whichever is closer to the left
|
||||
val start = editor.getLeadingCharacterOffset(pos.line).coerceAtMost(caret.offset)
|
||||
range = TextRange(start, range.endOffset)
|
||||
}
|
||||
return changeCaseRange(editor, caret, range, type)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2040,7 +2048,7 @@ abstract class VimChangeGroupBase : VimChangeGroup {
|
||||
caret.moveToInlayAwareOffset(editor.bufferPositionToOffset(BufferPosition(line, column)))
|
||||
setInsertRepeat(lines, column, append)
|
||||
}
|
||||
insertBeforeCursor(editor, context)
|
||||
insertBeforeCaret(editor, context)
|
||||
return true
|
||||
}
|
||||
|
||||
|
@@ -400,12 +400,11 @@ abstract class VimMotionGroupBase : VimMotionGroup {
|
||||
// If we are a linewise motion we need to normalize the start and stop then move the start to the beginning
|
||||
// of the line and move the end to the end of the line.
|
||||
if (argument.isLinewiseMotion()) {
|
||||
if (caret.getBufferPosition().line != editor.lineCount() - 1) {
|
||||
start = editor.getLineStartForOffset(start)
|
||||
end = min((editor.getLineEndForOffset(end) + 1).toLong(), editor.fileSize()).toInt()
|
||||
start = editor.getLineStartForOffset(start)
|
||||
end = if (caret.getBufferPosition().line != editor.lineCount() - 1) {
|
||||
min((editor.getLineEndForOffset(end) + 1).toLong(), editor.fileSize()).toInt()
|
||||
} else {
|
||||
start = editor.getLineStartForOffset(start)
|
||||
end = editor.getLineEndForOffset(end)
|
||||
editor.getLineEndForOffset(end)
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -53,15 +53,11 @@ sealed class Argument {
|
||||
|
||||
fun getMotionType() = if (isLinewiseMotion()) SelectionType.LINE_WISE else SelectionType.CHARACTER_WISE
|
||||
|
||||
fun isLinewiseMotion(): Boolean {
|
||||
return motion.let {
|
||||
when (it) {
|
||||
is TextObjectActionHandler -> it.visualType == TextObjectVisualType.LINE_WISE
|
||||
is MotionActionHandler -> it.motionType == MotionType.LINE_WISE
|
||||
is ExternalActionHandler -> it.isLinewiseMotion
|
||||
else -> error("Command is not a motion: $motion")
|
||||
}
|
||||
}
|
||||
fun isLinewiseMotion(): Boolean = when (motion) {
|
||||
is TextObjectActionHandler -> motion.visualType == TextObjectVisualType.LINE_WISE
|
||||
is MotionActionHandler -> motion.motionType == MotionType.LINE_WISE
|
||||
is ExternalActionHandler -> motion.isLinewiseMotion
|
||||
else -> error("Command is not a motion: $motion")
|
||||
}
|
||||
|
||||
fun withArgument(argument: Argument) = Motion(motion, argument)
|
||||
|
@@ -1106,7 +1106,7 @@
|
||||
},
|
||||
{
|
||||
"keys": "I",
|
||||
"class": "com.maddyhome.idea.vim.action.change.insert.VisualBlockInsertAction",
|
||||
"class": "com.maddyhome.idea.vim.action.change.insert.VisualInsertAction",
|
||||
"modes": "X"
|
||||
},
|
||||
{
|
||||
@@ -1211,7 +1211,7 @@
|
||||
},
|
||||
{
|
||||
"keys": "ZQ",
|
||||
"class": "com.maddyhome.idea.vim.action.file.FileSaveCloseAction",
|
||||
"class": "com.maddyhome.idea.vim.action.file.FileCloseAction",
|
||||
"modes": "N"
|
||||
},
|
||||
{
|
||||
|
Reference in New Issue
Block a user