mirror of
https://github.com/chylex/IntelliJ-IdeaVim.git
synced 2026-04-07 07:46:51 +02:00
Compare commits
48 Commits
customized
...
customized
| Author | SHA1 | Date | |
|---|---|---|---|
|
2d79870c0f
|
|||
|
551c6286ab
|
|||
|
e17e93d143
|
|||
|
18722c240c
|
|||
|
945fdf3fe9
|
|||
|
40e9d6ff7a
|
|||
|
6bce1110e5
|
|||
|
d8876b525a
|
|||
|
069815326a
|
|||
|
755bf21d35
|
|||
|
565ce9f9e4
|
|||
|
8cb78e26f8
|
|||
|
430bdc2a82
|
|||
|
fe55e3e6eb
|
|||
|
b7ac7acaf5
|
|||
|
8cd0e2c266
|
|||
|
902c005826
|
|||
|
b09ded236f
|
|||
|
221b5474c9
|
|||
|
2a91e67f39
|
|||
|
e2bd6a2828
|
|||
|
52ff8012cc
|
|||
|
0bac02e40e
|
|||
|
33740616da
|
|||
|
57d0ef1dd5
|
|||
|
d2f017887f
|
|||
|
cfe196ed30
|
|||
|
536942f514
|
|||
|
36e3cd1adb
|
|||
|
7c874f834a
|
|||
|
a4e963c98e
|
|||
|
|
46823abcda | ||
| d85e7dba19 | |||
|
|
a9c3277a51 | ||
|
|
6e6039c22a | ||
|
|
b49e896b41 | ||
|
|
122b066b75 | ||
|
|
cb24ac2bfa | ||
|
|
b14324a3e6 | ||
|
|
e40a839f52 | ||
|
|
a45cc0891b | ||
|
|
89bad651c0 | ||
|
|
5150dc0c9e | ||
|
|
c6c7d68876 | ||
|
|
02130a87c9 | ||
|
|
40ba977e58 | ||
|
|
21f304a560 | ||
|
|
36e8bd4663 |
16
.idea/runConfigurations/Split_Frontend_Debugger.xml
generated
Normal file
16
.idea/runConfigurations/Split_Frontend_Debugger.xml
generated
Normal file
@@ -0,0 +1,16 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="Split Frontend Debugger" type="Remote" folderName="Split Mode">
|
||||
<module name="ideavim" />
|
||||
<option name="USE_SOCKET_TRANSPORT" value="true" />
|
||||
<option name="SERVER_MODE" value="false" />
|
||||
<option name="SHMEM_ADDRESS" />
|
||||
<option name="HOST" value="localhost" />
|
||||
<option name="PORT" value="5006" />
|
||||
<option name="AUTO_RESTART" value="false" />
|
||||
<RunnerSettings RunnerId="Debug">
|
||||
<option name="DEBUG_PORT" value="5006" />
|
||||
<option name="LOCAL" value="false" />
|
||||
</RunnerSettings>
|
||||
<method v="2" />
|
||||
</configuration>
|
||||
</component>
|
||||
24
.idea/runConfigurations/Start_CLion_with_IdeaVim.xml
generated
Normal file
24
.idea/runConfigurations/Start_CLion_with_IdeaVim.xml
generated
Normal file
@@ -0,0 +1,24 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="Start CLion with IdeaVim" type="GradleRunConfiguration" factoryName="Gradle" folderName="Platforms">
|
||||
<log_file alias="idea.log" path="$PROJECT_DIR$/build/idea-sandbox/system/log/idea.log" />
|
||||
<ExternalSystemSettings>
|
||||
<option name="executionName" />
|
||||
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
||||
<option name="externalSystemIdString" value="GRADLE" />
|
||||
<option name="scriptParameters" value="" />
|
||||
<option name="taskDescriptions">
|
||||
<list />
|
||||
</option>
|
||||
<option name="taskNames">
|
||||
<list>
|
||||
<option value="runClion" />
|
||||
</list>
|
||||
</option>
|
||||
<option name="vmOptions" value="" />
|
||||
</ExternalSystemSettings>
|
||||
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
|
||||
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
|
||||
<DebugAllEnabled>false</DebugAllEnabled>
|
||||
<method v="2" />
|
||||
</configuration>
|
||||
</component>
|
||||
25
.idea/runConfigurations/Start_CLion_with_IdeaVim__Split_Mode_.xml
generated
Normal file
25
.idea/runConfigurations/Start_CLion_with_IdeaVim__Split_Mode_.xml
generated
Normal file
@@ -0,0 +1,25 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="Start CLion with IdeaVim (Split Mode)" type="GradleRunConfiguration" factoryName="Gradle" folderName="Platforms (Split)">
|
||||
<log_file alias="idea.log" path="$PROJECT_DIR$/build/idea-sandbox/system/log/idea.log" />
|
||||
<ExternalSystemSettings>
|
||||
<option name="executionName" />
|
||||
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
||||
<option name="externalSystemIdString" value="GRADLE" />
|
||||
<option name="scriptParameters" value="" />
|
||||
<option name="taskDescriptions">
|
||||
<list />
|
||||
</option>
|
||||
<option name="taskNames">
|
||||
<list>
|
||||
<option value="runCLionSplitMode" />
|
||||
</list>
|
||||
</option>
|
||||
<option name="vmOptions" value="" />
|
||||
</ExternalSystemSettings>
|
||||
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
|
||||
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
|
||||
<DebugAllEnabled>false</DebugAllEnabled>
|
||||
<RunAsTest>false</RunAsTest>
|
||||
<method v="2" />
|
||||
</configuration>
|
||||
</component>
|
||||
@@ -1,5 +1,5 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="Start IJ with IdeaVim (Split Mode)" type="GradleRunConfiguration" factoryName="Gradle">
|
||||
<configuration default="false" name="Start IJ with IdeaVim (Split Mode)" type="GradleRunConfiguration" factoryName="Gradle" folderName="Split Mode">
|
||||
<log_file alias="idea.log" path="$PROJECT_DIR$/build/idea-sandbox/system/log/idea.log" />
|
||||
<ExternalSystemSettings>
|
||||
<option name="executionName" />
|
||||
|
||||
25
.idea/runConfigurations/Start_IJ_with_IdeaVim__Split_Mode_Debug_Frontend_.xml
generated
Normal file
25
.idea/runConfigurations/Start_IJ_with_IdeaVim__Split_Mode_Debug_Frontend_.xml
generated
Normal file
@@ -0,0 +1,25 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="Start IJ with IdeaVim (Split Mode Debug Frontend)" type="GradleRunConfiguration" factoryName="Gradle" folderName="Split Mode">
|
||||
<log_file alias="idea.log" path="$PROJECT_DIR$/build/idea-sandbox/system/log/idea.log" />
|
||||
<ExternalSystemSettings>
|
||||
<option name="executionName" />
|
||||
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
||||
<option name="externalSystemIdString" value="GRADLE" />
|
||||
<option name="scriptParameters" value="" />
|
||||
<option name="taskDescriptions">
|
||||
<list />
|
||||
</option>
|
||||
<option name="taskNames">
|
||||
<list>
|
||||
<option value="runIdeSplitModeDebugFrontend" />
|
||||
</list>
|
||||
</option>
|
||||
<option name="vmOptions" value="" />
|
||||
</ExternalSystemSettings>
|
||||
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
|
||||
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
|
||||
<DebugAllEnabled>false</DebugAllEnabled>
|
||||
<RunAsTest>false</RunAsTest>
|
||||
<method v="2" />
|
||||
</configuration>
|
||||
</component>
|
||||
24
.idea/runConfigurations/Start_PyCharm_with_IdeaVim.xml
generated
Normal file
24
.idea/runConfigurations/Start_PyCharm_with_IdeaVim.xml
generated
Normal file
@@ -0,0 +1,24 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="Start PyCharm with IdeaVim" type="GradleRunConfiguration" factoryName="Gradle" folderName="Platforms">
|
||||
<log_file alias="idea.log" path="$PROJECT_DIR$/build/idea-sandbox/system/log/idea.log" />
|
||||
<ExternalSystemSettings>
|
||||
<option name="executionName" />
|
||||
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
||||
<option name="externalSystemIdString" value="GRADLE" />
|
||||
<option name="scriptParameters" value="" />
|
||||
<option name="taskDescriptions">
|
||||
<list />
|
||||
</option>
|
||||
<option name="taskNames">
|
||||
<list>
|
||||
<option value="runPycharm" />
|
||||
</list>
|
||||
</option>
|
||||
<option name="vmOptions" value="" />
|
||||
</ExternalSystemSettings>
|
||||
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
|
||||
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
|
||||
<DebugAllEnabled>false</DebugAllEnabled>
|
||||
<method v="2" />
|
||||
</configuration>
|
||||
</component>
|
||||
25
.idea/runConfigurations/Start_PyCharm_with_IdeaVim__Split_Mode_.xml
generated
Normal file
25
.idea/runConfigurations/Start_PyCharm_with_IdeaVim__Split_Mode_.xml
generated
Normal file
@@ -0,0 +1,25 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="Start PyCharm with IdeaVim (Split Mode)" type="GradleRunConfiguration" factoryName="Gradle" folderName="Platforms (Split)">
|
||||
<log_file alias="idea.log" path="$PROJECT_DIR$/build/idea-sandbox/system/log/idea.log" />
|
||||
<ExternalSystemSettings>
|
||||
<option name="executionName" />
|
||||
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
||||
<option name="externalSystemIdString" value="GRADLE" />
|
||||
<option name="scriptParameters" value="" />
|
||||
<option name="taskDescriptions">
|
||||
<list />
|
||||
</option>
|
||||
<option name="taskNames">
|
||||
<list>
|
||||
<option value="runPycharmSplitMode" />
|
||||
</list>
|
||||
</option>
|
||||
<option name="vmOptions" value="" />
|
||||
</ExternalSystemSettings>
|
||||
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
|
||||
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
|
||||
<DebugAllEnabled>false</DebugAllEnabled>
|
||||
<RunAsTest>false</RunAsTest>
|
||||
<method v="2" />
|
||||
</configuration>
|
||||
</component>
|
||||
24
.idea/runConfigurations/Start_Rider_with_IdeaVim.xml
generated
Normal file
24
.idea/runConfigurations/Start_Rider_with_IdeaVim.xml
generated
Normal file
@@ -0,0 +1,24 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="Start Rider with IdeaVim" type="GradleRunConfiguration" factoryName="Gradle" folderName="Platforms">
|
||||
<log_file alias="idea.log" path="$PROJECT_DIR$/build/idea-sandbox/system/log/idea.log" />
|
||||
<ExternalSystemSettings>
|
||||
<option name="executionName" />
|
||||
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
||||
<option name="externalSystemIdString" value="GRADLE" />
|
||||
<option name="scriptParameters" value="" />
|
||||
<option name="taskDescriptions">
|
||||
<list />
|
||||
</option>
|
||||
<option name="taskNames">
|
||||
<list>
|
||||
<option value="runRider" />
|
||||
</list>
|
||||
</option>
|
||||
<option name="vmOptions" value="" />
|
||||
</ExternalSystemSettings>
|
||||
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
|
||||
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
|
||||
<DebugAllEnabled>false</DebugAllEnabled>
|
||||
<method v="2" />
|
||||
</configuration>
|
||||
</component>
|
||||
24
.idea/runConfigurations/Start_WebStorm_with_IdeaVim.xml
generated
Normal file
24
.idea/runConfigurations/Start_WebStorm_with_IdeaVim.xml
generated
Normal file
@@ -0,0 +1,24 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="Start WebStorm with IdeaVim" type="GradleRunConfiguration" factoryName="Gradle" folderName="Platforms">
|
||||
<log_file alias="idea.log" path="$PROJECT_DIR$/build/idea-sandbox/system/log/idea.log" />
|
||||
<ExternalSystemSettings>
|
||||
<option name="executionName" />
|
||||
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
||||
<option name="externalSystemIdString" value="GRADLE" />
|
||||
<option name="scriptParameters" value="" />
|
||||
<option name="taskDescriptions">
|
||||
<list />
|
||||
</option>
|
||||
<option name="taskNames">
|
||||
<list>
|
||||
<option value="runWebstorm" />
|
||||
</list>
|
||||
</option>
|
||||
<option name="vmOptions" value="" />
|
||||
</ExternalSystemSettings>
|
||||
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
|
||||
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
|
||||
<DebugAllEnabled>false</DebugAllEnabled>
|
||||
<method v="2" />
|
||||
</configuration>
|
||||
</component>
|
||||
25
.idea/runConfigurations/Start_WebStorm_with_IdeaVim__Split_Mode_.xml
generated
Normal file
25
.idea/runConfigurations/Start_WebStorm_with_IdeaVim__Split_Mode_.xml
generated
Normal file
@@ -0,0 +1,25 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="Start WebStorm with IdeaVim (Split Mode)" type="GradleRunConfiguration" factoryName="Gradle" folderName="Platforms (Split)">
|
||||
<log_file alias="idea.log" path="$PROJECT_DIR$/build/idea-sandbox/system/log/idea.log" />
|
||||
<ExternalSystemSettings>
|
||||
<option name="executionName" />
|
||||
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
||||
<option name="externalSystemIdString" value="GRADLE" />
|
||||
<option name="scriptParameters" value="" />
|
||||
<option name="taskDescriptions">
|
||||
<list />
|
||||
</option>
|
||||
<option name="taskNames">
|
||||
<list>
|
||||
<option value="runWebstormSplitMode" />
|
||||
</list>
|
||||
</option>
|
||||
<option name="vmOptions" value="" />
|
||||
</ExternalSystemSettings>
|
||||
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
|
||||
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
|
||||
<DebugAllEnabled>false</DebugAllEnabled>
|
||||
<RunAsTest>false</RunAsTest>
|
||||
<method v="2" />
|
||||
</configuration>
|
||||
</component>
|
||||
@@ -6,6 +6,7 @@
|
||||
* https://opensource.org/licenses/MIT.
|
||||
*/
|
||||
|
||||
import org.jetbrains.intellij.platform.gradle.IntelliJPlatformType
|
||||
import org.jetbrains.intellij.platform.gradle.TestFrameworkType
|
||||
import org.jetbrains.intellij.platform.gradle.tasks.aware.SplitModeAware
|
||||
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
|
||||
@@ -26,11 +27,11 @@ buildscript {
|
||||
classpath("org.eclipse.jgit:org.eclipse.jgit.ssh.apache:7.6.0.202603022253-r")
|
||||
classpath("org.kohsuke:github-api:1.305")
|
||||
|
||||
classpath("io.ktor:ktor-client-core:3.4.1")
|
||||
classpath("io.ktor:ktor-client-cio:3.4.1")
|
||||
classpath("io.ktor:ktor-client-auth:3.4.1")
|
||||
classpath("io.ktor:ktor-client-content-negotiation:3.4.1")
|
||||
classpath("io.ktor:ktor-serialization-kotlinx-json:3.4.1")
|
||||
classpath("io.ktor:ktor-client-core:3.4.2")
|
||||
classpath("io.ktor:ktor-client-cio:3.4.2")
|
||||
classpath("io.ktor:ktor-client-auth:3.4.2")
|
||||
classpath("io.ktor:ktor-client-content-negotiation:3.4.2")
|
||||
classpath("io.ktor:ktor-serialization-kotlinx-json:3.4.2")
|
||||
|
||||
// This comes from the changelog plugin
|
||||
// classpath("org.jetbrains:markdown:0.3.1")
|
||||
@@ -112,7 +113,7 @@ dependencies {
|
||||
testFramework(TestFrameworkType.Platform)
|
||||
testFramework(TestFrameworkType.JUnit5)
|
||||
|
||||
plugin("com.intellij.classic.ui", "261.22158.185")
|
||||
compatiblePlugin("com.intellij.classic.ui")
|
||||
|
||||
pluginModule(runtimeOnly(project(":modules:ideavim-common")))
|
||||
pluginModule(runtimeOnly(project(":modules:ideavim-frontend")))
|
||||
@@ -225,6 +226,30 @@ tasks {
|
||||
// localPath = file("/Users/{user}/Applications/WebStorm.app")
|
||||
// }
|
||||
|
||||
val runPycharm by intellijPlatformTesting.runIde.registering {
|
||||
type = IntelliJPlatformType.PyCharmProfessional
|
||||
version = "2025.3.2"
|
||||
task {
|
||||
systemProperty("octopus.handler", System.getProperty("octopus.handler") ?: true)
|
||||
}
|
||||
}
|
||||
|
||||
val runWebstorm by intellijPlatformTesting.runIde.registering {
|
||||
type = IntelliJPlatformType.WebStorm
|
||||
version = "2025.3.2"
|
||||
task {
|
||||
systemProperty("octopus.handler", System.getProperty("octopus.handler") ?: true)
|
||||
}
|
||||
}
|
||||
|
||||
val runClion by intellijPlatformTesting.runIde.registering {
|
||||
type = IntelliJPlatformType.CLion
|
||||
version = "2025.3.2"
|
||||
task {
|
||||
systemProperty("octopus.handler", System.getProperty("octopus.handler") ?: true)
|
||||
}
|
||||
}
|
||||
|
||||
val runIdeForUiTests by intellijPlatformTesting.runIde.registering {
|
||||
task {
|
||||
jvmArgumentProviders += CommandLineArgumentProvider {
|
||||
@@ -247,6 +272,55 @@ tasks {
|
||||
val runIdeSplitMode by intellijPlatformTesting.runIde.registering {
|
||||
splitMode = true
|
||||
splitModeTarget = SplitModeAware.SplitModeTarget.BOTH
|
||||
|
||||
plugins {
|
||||
plugin("AceJump", "3.8.22")
|
||||
plugin("org.jetbrains.IdeaVim-EasyMotion", "1.16")
|
||||
}
|
||||
}
|
||||
val runWebstormSplitMode by intellijPlatformTesting.runIde.registering {
|
||||
type = IntelliJPlatformType.WebStorm
|
||||
version = "2025.3.2"
|
||||
splitMode = true
|
||||
splitModeTarget = SplitModeAware.SplitModeTarget.BOTH
|
||||
|
||||
plugins {
|
||||
plugin("AceJump", "3.8.22")
|
||||
plugin("org.jetbrains.IdeaVim-EasyMotion", "1.16")
|
||||
}
|
||||
}
|
||||
val runRider by intellijPlatformTesting.runIde.registering {
|
||||
type = IntelliJPlatformType.Rider
|
||||
version = "2026.1"
|
||||
task {
|
||||
systemProperty("idea.log.debug.categories", "com.maddyhome.idea.vim.handler.EditorHandlersChainLogger")
|
||||
}
|
||||
plugins {
|
||||
plugin("AceJump", "3.8.22")
|
||||
plugin("org.jetbrains.IdeaVim-EasyMotion", "1.16")
|
||||
}
|
||||
}
|
||||
val runCLionSplitMode by intellijPlatformTesting.runIde.registering {
|
||||
type = IntelliJPlatformType.CLion
|
||||
version = "2025.3.2"
|
||||
splitMode = true
|
||||
splitModeTarget = SplitModeAware.SplitModeTarget.BOTH
|
||||
|
||||
plugins {
|
||||
plugin("AceJump", "3.8.22")
|
||||
plugin("org.jetbrains.IdeaVim-EasyMotion", "1.16")
|
||||
}
|
||||
}
|
||||
val runPycharmSplitMode by intellijPlatformTesting.runIde.registering {
|
||||
type = IntelliJPlatformType.PyCharmProfessional
|
||||
version = "2025.3.2"
|
||||
splitMode = true
|
||||
splitModeTarget = SplitModeAware.SplitModeTarget.BOTH
|
||||
|
||||
plugins {
|
||||
plugin("AceJump", "3.8.22")
|
||||
plugin("org.jetbrains.IdeaVim-EasyMotion", "1.16")
|
||||
}
|
||||
}
|
||||
|
||||
// Run split mode with a JDWP debug agent on the frontend (JetBrains Client) process.
|
||||
@@ -255,6 +329,11 @@ tasks {
|
||||
splitMode = true
|
||||
splitModeTarget = SplitModeAware.SplitModeTarget.BOTH
|
||||
|
||||
plugins {
|
||||
plugin("AceJump", "3.8.22")
|
||||
plugin("org.jetbrains.IdeaVim-EasyMotion", "1.16")
|
||||
}
|
||||
|
||||
prepareSandboxTask {
|
||||
val sandboxDir = project.layout.buildDirectory.dir("idea-sandbox").map { it.asFile }
|
||||
doLast {
|
||||
@@ -286,6 +365,12 @@ tasks {
|
||||
val testIdeSplitMode by intellijPlatformTesting.testIde.registering {
|
||||
splitMode = true
|
||||
splitModeTarget = SplitModeAware.SplitModeTarget.BOTH
|
||||
|
||||
plugins {
|
||||
plugin("AceJump", "3.8.22")
|
||||
plugin("org.jetbrains.IdeaVim-EasyMotion", "1.16")
|
||||
}
|
||||
|
||||
task {
|
||||
useJUnitPlatform()
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ ideaVersion=2026.1
|
||||
# Values for type: https://plugins.jetbrains.com/docs/intellij/tools-gradle-intellij-plugin.html#intellij-extension-type
|
||||
ideaType=IU
|
||||
instrumentPluginCode=true
|
||||
version=chylex-54
|
||||
version=chylex-55
|
||||
javaVersion=21
|
||||
remoteRobotVersion=0.11.23
|
||||
antlrVersion=4.10.1
|
||||
|
||||
2
gradlew
vendored
2
gradlew
vendored
@@ -57,7 +57,7 @@
|
||||
# Darwin, MinGW, and NonStop.
|
||||
#
|
||||
# (3) This script is generated from the Groovy template
|
||||
# https://github.com/gradle/gradle/blob/b631911858264c0b6e4d6603d677ff5218766cee/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||
# https://github.com/gradle/gradle/blob/2d6327017519d23b96af35865dc997fcb544fb40/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||
# within the Gradle project.
|
||||
#
|
||||
# You can find Gradle at https://github.com/gradle/gradle/.
|
||||
|
||||
@@ -165,25 +165,27 @@ internal class FileRemoteApiImpl : FileRemoteApi {
|
||||
// ======================== Private helpers ========================
|
||||
|
||||
private fun findFile(filename: String, project: Project): VirtualFile? {
|
||||
var found: VirtualFile?
|
||||
if (filename.startsWith("~/") || filename.startsWith("~\\")) {
|
||||
val relativePath = filename.substring(2)
|
||||
val dir = System.getProperty("user.home")
|
||||
logger.debug { "home dir file" }
|
||||
logger.debug { "looking for $relativePath in $dir" }
|
||||
found = LocalFileSystem.getInstance().refreshAndFindFileByNioFile(Path(dir, relativePath))
|
||||
} else {
|
||||
found = VirtualFileManager.getInstance().findFileByNioPath(Path(filename))
|
||||
|
||||
if (found == null) {
|
||||
found = findByNameInContentRoots(filename, project)
|
||||
if (found == null) {
|
||||
found = findByNameInProject(filename, project)
|
||||
}
|
||||
}
|
||||
return LocalFileSystem.getInstance().refreshAndFindFileByNioFile(Path(dir, relativePath))
|
||||
}
|
||||
|
||||
return found
|
||||
val basePath = project.basePath
|
||||
if (basePath != null) {
|
||||
val baseDir = LocalFileSystem.getInstance().refreshAndFindFileByNioFile(Path(basePath))
|
||||
baseDir?.findFileByRelativePath(filename)?.let { return it }
|
||||
}
|
||||
|
||||
VirtualFileManager.getInstance().findFileByNioPath(Path(filename))?.let { return it }
|
||||
|
||||
findByNameInContentRoots(filename, project)?.let { return it }
|
||||
|
||||
findByNameInProject(filename, project)?.let { return it }
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
private fun buildFileInfoMessage(editor: Editor, project: Project, fullPath: Boolean): String {
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
<idea-plugin>
|
||||
<dependencies>
|
||||
<module name="com.intellij.modules.rider"/>
|
||||
<plugin id="com.intellij.modules.rider"/>
|
||||
</dependencies>
|
||||
<projectListeners>
|
||||
<listener class="com.maddyhome.idea.vim.listener.RiderActionListener"
|
||||
|
||||
@@ -26,11 +26,11 @@ dependencies {
|
||||
testImplementation("org.junit.jupiter:junit-jupiter:6.0.3")
|
||||
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
|
||||
|
||||
implementation("io.ktor:ktor-client-core:3.4.1")
|
||||
implementation("io.ktor:ktor-client-cio:3.4.1")
|
||||
implementation("io.ktor:ktor-client-content-negotiation:3.4.1")
|
||||
implementation("io.ktor:ktor-serialization-kotlinx-json:3.4.1")
|
||||
implementation("io.ktor:ktor-client-auth:3.4.1")
|
||||
implementation("io.ktor:ktor-client-core:3.4.2")
|
||||
implementation("io.ktor:ktor-client-cio:3.4.2")
|
||||
implementation("io.ktor:ktor-client-content-negotiation:3.4.2")
|
||||
implementation("io.ktor:ktor-serialization-kotlinx-json:3.4.2")
|
||||
implementation("io.ktor:ktor-client-auth:3.4.2")
|
||||
implementation("org.eclipse.jgit:org.eclipse.jgit:6.6.0.202305301015-r")
|
||||
|
||||
// This is needed for jgit to connect to ssh
|
||||
|
||||
@@ -22,6 +22,7 @@ import com.intellij.openapi.util.Disposer;
|
||||
import com.maddyhome.idea.vim.api.*;
|
||||
import com.maddyhome.idea.vim.config.VimState;
|
||||
import com.maddyhome.idea.vim.config.migration.ApplicationConfigurationMigrator;
|
||||
import com.maddyhome.idea.vim.group.KeyGroup;
|
||||
import com.maddyhome.idea.vim.group.VimNotifications;
|
||||
import com.maddyhome.idea.vim.group.VimWindowGroup;
|
||||
import com.maddyhome.idea.vim.history.VimHistory;
|
||||
@@ -130,12 +131,12 @@ public class VimPlugin implements PersistentStateComponent<Element>, Disposable
|
||||
return VimInjectorKt.getInjector().getHistoryGroup();
|
||||
}
|
||||
|
||||
public static @NotNull VimKeyGroup getKey() {
|
||||
return VimInjectorKt.getInjector().getKeyGroup();
|
||||
public static @NotNull KeyGroup getKey() {
|
||||
return ((KeyGroup)VimInjectorKt.getInjector().getKeyGroup());
|
||||
}
|
||||
|
||||
public static @Nullable VimKeyGroup getKeyIfCreated() {
|
||||
return ApplicationManager.getApplication().getServiceIfCreated(VimKeyGroup.class);
|
||||
public static @Nullable KeyGroup getKeyIfCreated() {
|
||||
return ApplicationManager.getApplication().getServiceIfCreated(KeyGroup.class);
|
||||
}
|
||||
|
||||
public static @NotNull VimWindowGroup getWindow() {
|
||||
@@ -337,7 +338,7 @@ public class VimPlugin implements PersistentStateComponent<Element>, Disposable
|
||||
}
|
||||
}
|
||||
if (element.getChild("shortcut-conflicts") != null) {
|
||||
((VimKeyGroupBase)getKey()).loadShortcutConflictsData(element);
|
||||
getKey().loadShortcutConflictsData(element);
|
||||
}
|
||||
if (element.getChild("editor") != null) {
|
||||
getEditor().loadEditorStateData(element);
|
||||
|
||||
@@ -11,6 +11,7 @@ import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.diagnostic.logger
|
||||
import com.intellij.openapi.extensions.ExtensionPointListener
|
||||
import com.intellij.openapi.extensions.PluginDescriptor
|
||||
import com.intellij.vim.api.VimInitApi
|
||||
import com.maddyhome.idea.vim.api.VimExtensionRegistrator
|
||||
import com.maddyhome.idea.vim.api.injector
|
||||
import com.maddyhome.idea.vim.api.setToggleOption
|
||||
@@ -20,7 +21,6 @@ import com.maddyhome.idea.vim.key.MappingOwner.Plugin.Companion.remove
|
||||
import com.maddyhome.idea.vim.options.OptionAccessScope
|
||||
import com.maddyhome.idea.vim.options.OptionDeclaredScope
|
||||
import com.maddyhome.idea.vim.options.ToggleOption
|
||||
import com.intellij.vim.api.VimInitApi
|
||||
import com.maddyhome.idea.vim.statistic.ExtensionTracking
|
||||
import com.maddyhome.idea.vim.thinapi.VimApiImpl
|
||||
|
||||
@@ -106,9 +106,13 @@ class VimExtensionRegistrar : VimExtensionRegistrator {
|
||||
override fun enableDelayedExtensions() {
|
||||
delayedExtensionEnabling.forEach {
|
||||
val name = it.name ?: it.instance.name
|
||||
val initApi = createVimApi(name)
|
||||
it.instance.init(initApi)
|
||||
logger.info("IdeaVim extension '$name' initialized")
|
||||
try {
|
||||
val initApi = createVimApi(name)
|
||||
it.instance.init(initApi)
|
||||
logger.info("IdeaVim extension '$name' initialized")
|
||||
} catch (e: Throwable) {
|
||||
logger.error("Failed to initialize IdeaVim extension '$name'", e)
|
||||
}
|
||||
}
|
||||
delayedExtensionEnabling.clear()
|
||||
}
|
||||
|
||||
@@ -241,13 +241,17 @@ internal class VimEscHandler(nextHandler: EditorActionHandler) : VimKeyHandler(n
|
||||
|
||||
/**
|
||||
* Rider (and CLion Nova) uses a separate handler for esc to close the completion. IdeaOnlyEscapeHandlerAction is especially
|
||||
* designer to get all the esc presses, and if there is a completion close it and do not pass the execution further.
|
||||
* designed to get all the esc presses, and if there is a completion close it and do not pass the execution further.
|
||||
* This doesn't work the same as in IJ.
|
||||
* In IdeaVim, we'd like to exit insert mode on closing completion. This is a requirement as the change of this
|
||||
* behaviour causes a lot of complaining from users. Since the rider handler gets execution control, we don't
|
||||
* receive an event and don't exit the insert mode.
|
||||
* To fix it, this special handler exists only for rider and stands before the rider's handler. We don't execute the
|
||||
* handler from rider because the autocompletion is closed automatically anyway.
|
||||
*
|
||||
* NOTE: This handler only works when octopus is enabled (non-Rider IDEs). For Rider, where octopus is disabled
|
||||
* (VIM-3815) and Escape is consumed by the popup manager before the EditorEscape chain fires, the fix is in
|
||||
* [com.maddyhome.idea.vim.listener.IdeaSpecifics.LookupTopicListener] via a LookupListener.
|
||||
*/
|
||||
internal class VimEscForRiderHandler(nextHandler: EditorActionHandler) : VimKeyHandler(nextHandler) {
|
||||
override val key: String = "<Esc>"
|
||||
|
||||
@@ -50,6 +50,8 @@ import com.maddyhome.idea.vim.group.visual.IdeaSelectionControl
|
||||
import com.maddyhome.idea.vim.helper.exitSelectMode
|
||||
import com.maddyhome.idea.vim.helper.exitVisualMode
|
||||
import com.maddyhome.idea.vim.helper.isIdeaVimDisabledHere
|
||||
import com.maddyhome.idea.vim.ide.isClionNova
|
||||
import com.maddyhome.idea.vim.ide.isRider
|
||||
import com.maddyhome.idea.vim.newapi.globalIjOptions
|
||||
import com.maddyhome.idea.vim.newapi.initInjector
|
||||
import com.maddyhome.idea.vim.newapi.vim
|
||||
@@ -350,6 +352,16 @@ internal object IdeaSpecifics {
|
||||
if (newLookup.editor.isIdeaVimDisabledHere) return
|
||||
|
||||
(VimPlugin.getKey() as VimKeyGroupBase).registerShortcutsForLookup(newLookup)
|
||||
|
||||
// In Rider/CLion Nova, octopus is disabled (VIM-3815) and Escape is consumed by the popup manager
|
||||
// (due to LookupSummaryInfo popup) before the action system runs, so IdeaVim never sees it.
|
||||
// Listen for explicit lookup cancellation (Escape) to exit insert mode.
|
||||
// Note: we check isRider/isClionNova specifically, not !isOctopusEnabled(), because
|
||||
// JetBrains Client (split mode) also has octopus disabled but doesn't need this workaround,
|
||||
// and isCanceledExplicitly can be true for non-Escape keys (e.g. space) in that environment.
|
||||
if (isRider() || isClionNova()) {
|
||||
newLookup.addLookupListener(RiderEscLookupListener(newLookup.editor))
|
||||
}
|
||||
}
|
||||
|
||||
// Lookup closed
|
||||
@@ -361,6 +373,20 @@ internal object IdeaSpecifics {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* In Rider/CLion Nova, octopus is disabled (VIM-3815) and Escape is consumed by the popup manager
|
||||
* (due to LookupSummaryInfo parameter info popup) before the action system runs, so IdeaVim never sees it.
|
||||
* This listener exits insert mode when the lookup is explicitly cancelled (Escape).
|
||||
*/
|
||||
private class RiderEscLookupListener(private val editor: Editor) : com.intellij.codeInsight.lookup.LookupListener {
|
||||
override fun lookupCanceled(event: com.intellij.codeInsight.lookup.LookupEvent) {
|
||||
if (event.isCanceledExplicitly && editor.vim.mode is Mode.INSERT) {
|
||||
editor.vim.exitInsertMode(injector.executionContextManager.getEditorExecutionContext(editor.vim))
|
||||
KeyHandler.getInstance().reset(editor.vim)
|
||||
}
|
||||
}
|
||||
}
|
||||
//endregion
|
||||
|
||||
//region Hide Vim search highlights when showing IntelliJ search results
|
||||
|
||||
@@ -12,6 +12,7 @@ import com.intellij.openapi.editor.Caret
|
||||
import com.intellij.openapi.editor.LogicalPosition
|
||||
import com.intellij.openapi.editor.VisualPosition
|
||||
import com.maddyhome.idea.vim.api.BufferPosition
|
||||
import com.maddyhome.idea.vim.api.ImmutableVimCaret
|
||||
import com.maddyhome.idea.vim.api.LocalMarkStorage
|
||||
import com.maddyhome.idea.vim.api.SelectionInfo
|
||||
import com.maddyhome.idea.vim.api.VimCaret
|
||||
@@ -198,3 +199,12 @@ class IjVimCaret(val caret: Caret) : VimCaretBase() {
|
||||
|
||||
override fun hashCode(): Int = this.caret.hashCode()
|
||||
}
|
||||
|
||||
val Caret.vim: VimCaret
|
||||
get() = VimEditorFactory.getInstance().createVimCaret(this)
|
||||
|
||||
val VimCaret.ij: Caret
|
||||
get() = VimEditorFactory.getInstance().extractCaret(this)
|
||||
|
||||
val ImmutableVimCaret.ij: Caret
|
||||
get() = VimEditorFactory.getInstance().extractCaret(this)
|
||||
|
||||
@@ -671,3 +671,12 @@ class IjVimEditor(editor: Editor) : MutableLinearEditor, VimEditorBase() {
|
||||
}
|
||||
}
|
||||
|
||||
val Editor.vim: VimEditor
|
||||
get() = VimEditorFactory.getInstance().createVimEditor(this)
|
||||
|
||||
val VimEditor.ij: Editor
|
||||
get() = VimEditorFactory.getInstance().extractEditor(this)
|
||||
|
||||
val com.intellij.openapi.util.TextRange.vim: TextRange
|
||||
get() = TextRange(this.startOffset, this.endOffset)
|
||||
|
||||
|
||||
@@ -14,7 +14,6 @@ import com.intellij.openapi.editor.Editor
|
||||
import com.maddyhome.idea.vim.api.ImmutableVimCaret
|
||||
import com.maddyhome.idea.vim.api.VimCaret
|
||||
import com.maddyhome.idea.vim.api.VimEditor
|
||||
import com.maddyhome.idea.vim.common.TextRange
|
||||
|
||||
interface VimEditorFactory {
|
||||
fun createVimEditor(editor: Editor): VimEditor
|
||||
@@ -27,21 +26,3 @@ interface VimEditorFactory {
|
||||
fun getInstance(): VimEditorFactory = service()
|
||||
}
|
||||
}
|
||||
|
||||
val Editor.vim: VimEditor
|
||||
get() = VimEditorFactory.getInstance().createVimEditor(this)
|
||||
|
||||
val VimEditor.ij: Editor
|
||||
get() = VimEditorFactory.getInstance().extractEditor(this)
|
||||
|
||||
val Caret.vim: VimCaret
|
||||
get() = VimEditorFactory.getInstance().createVimCaret(this)
|
||||
|
||||
val VimCaret.ij: Caret
|
||||
get() = VimEditorFactory.getInstance().extractCaret(this)
|
||||
|
||||
val ImmutableVimCaret.ij: Caret
|
||||
get() = VimEditorFactory.getInstance().extractCaret(this)
|
||||
|
||||
val com.intellij.openapi.util.TextRange.vim: TextRange
|
||||
get() = TextRange(this.startOffset, this.endOffset)
|
||||
|
||||
@@ -194,7 +194,7 @@ class ExTextField internal constructor(private val myParentPanel: ExEntryPanel)
|
||||
// handler adds all non-control characters to the text field. We want to add all characters, so if we have an
|
||||
// actual character, just add it. Anything else, we'll pass to the super class like before (even though it's unclear
|
||||
// what it will do with the keystroke)
|
||||
if (stroke.keyChar != KeyEvent.CHAR_UNDEFINED) {
|
||||
if (stroke.keyChar != KeyEvent.CHAR_UNDEFINED && !isKeyCharEnterOrEscape(stroke.keyChar)) {
|
||||
replaceSelection(stroke.keyChar.toString())
|
||||
} else {
|
||||
val event = KeyEvent(
|
||||
|
||||
17
src/main/resources/IdeaVIM.ideavim-frontend-split.xml
Normal file
17
src/main/resources/IdeaVIM.ideavim-frontend-split.xml
Normal file
@@ -0,0 +1,17 @@
|
||||
<!--
|
||||
~ Copyright 2003-2026 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.
|
||||
-->
|
||||
|
||||
<!-- Split-mode (Remote Dev) specific registrations.
|
||||
This module only loads when intellij.platform.frontend.split is available,
|
||||
which provides access to intellij.rd.client and its extension points. -->
|
||||
<idea-plugin package="com.maddyhome.idea.vim">
|
||||
<dependencies>
|
||||
<module name="intellij.platform.frontend.split"/>
|
||||
<module name="IdeaVIM.ideavim-frontend"/>
|
||||
</dependencies>
|
||||
</idea-plugin>
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2003-2023 The IdeaVim authors
|
||||
* Copyright 2003-2026 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
|
||||
@@ -10,9 +10,12 @@ package org.jetbrains.plugins.ideavim.action.motion.search
|
||||
|
||||
import com.maddyhome.idea.vim.state.mode.Mode
|
||||
import com.maddyhome.idea.vim.state.mode.SelectionType
|
||||
import com.maddyhome.idea.vim.ui.ex.ExEntryPanel
|
||||
import org.jetbrains.plugins.ideavim.VimTestCase
|
||||
import org.junit.jupiter.api.Disabled
|
||||
import org.junit.jupiter.api.Test
|
||||
import kotlin.test.assertFalse
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
class SearchEntryFwdActionTest : VimTestCase() {
|
||||
@Test
|
||||
@@ -110,6 +113,23 @@ class SearchEntryFwdActionTest : VimTestCase() {
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `test escape after search not found closes panel without inserting escape char`() {
|
||||
configureByText("lorem ipsum dolor sit amet")
|
||||
typeText("/notfound")
|
||||
|
||||
val panel = ExEntryPanel.getOrCreatePanelInstance()
|
||||
assertTrue(panel.isActive)
|
||||
|
||||
typeText("<Esc>")
|
||||
|
||||
assertFalse(panel.isActive)
|
||||
assertMode(Mode.NORMAL())
|
||||
// The panel text should not contain ^[ (escape character written as text)
|
||||
assertFalse(panel.text.contains("\u001B"), "Panel text should not contain escape character")
|
||||
assertFalse(panel.text.contains("^["), "Panel text should not contain ^[ literal")
|
||||
}
|
||||
|
||||
@Disabled("Ctrl-o doesn't work yet in select mode")
|
||||
@Test
|
||||
fun `search in one time from select mode`() {
|
||||
|
||||
@@ -22,11 +22,11 @@ class JumpNavigationSplitTest : IdeaVimStarterTestBase() {
|
||||
openFile(longFile("Jump1"))
|
||||
|
||||
typeVim("G")
|
||||
pause(300)
|
||||
pause(500)
|
||||
assertCaretAfter(40, "G should go to end of file")
|
||||
|
||||
ctrlO()
|
||||
pause(300)
|
||||
pause(500)
|
||||
assertCaretBefore(10, "Ctrl-O should jump back to start")
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ class JumpNavigationSplitTest : IdeaVimStarterTestBase() {
|
||||
openFile(longFile("Jump2"))
|
||||
|
||||
typeVim("gg")
|
||||
pause(300)
|
||||
pause(500)
|
||||
|
||||
typeVim("/Line 30\n")
|
||||
pause()
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2003-2023 The IdeaVim authors
|
||||
* Copyright 2003-2026 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
|
||||
@@ -13,14 +13,22 @@ 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.helper.isCommandLineActionChar
|
||||
import com.maddyhome.idea.vim.state.KeyHandlerState
|
||||
import javax.swing.KeyStroke
|
||||
|
||||
@CommandOrMotion(keys = ["<C-K>"], modes = [Mode.INSERT, Mode.CMD_LINE])
|
||||
/**
|
||||
* Insert mode: insert a digraph character via `<C-K>`
|
||||
*
|
||||
* The converted digraph character is re-injected through the key handler so that it is processed as typed input in
|
||||
* Insert mode (handled by the change group).
|
||||
*/
|
||||
@CommandOrMotion(keys = ["<C-K>"], modes = [Mode.INSERT])
|
||||
class InsertCompletedDigraphAction : VimActionHandler.SingleExecution() {
|
||||
override val type: Command.Type = Command.Type.INSERT
|
||||
|
||||
@@ -29,22 +37,6 @@ class InsertCompletedDigraphAction : VimActionHandler.SingleExecution() {
|
||||
// We're waiting for it to complete and give us a CHARACTER
|
||||
override val argumentType: Argument.Type = Argument.Type.DIGRAPH
|
||||
|
||||
/**
|
||||
* Perform additional initialisation when starting to wait for an argument
|
||||
*
|
||||
* IdeaVim has two ways of handling digraphs/literals. Actions such as `r` or `f` can accept a digraph, which really
|
||||
* means it accepts a character, but the user can use `<C-K>`/`<C-V>` to type a digraph or literal and convert it into
|
||||
* a character. Unfortunately, there is no mode that can be used to register an "insert digraph/literal" action for
|
||||
* these keys while replace or find is active. So the key handler hard codes these keys and will check for them when
|
||||
* an action expects a digraph (and like Vim, these keys cannot be mapped). Once the state machine has matched a
|
||||
* character, the expected argument is reset to [Argument.Type.CHARACTER] and the character is passed through the key
|
||||
* handler again, potentially mapped, and then attached as an argument to the current command, which is now complete
|
||||
* and executed.
|
||||
*
|
||||
* In Insert and Command-line mode, the `<C-K>` and `<C-V>` keys are actions that will wait for a character argument,
|
||||
* and then insert it. Commands are only executed once complete, so we use [onStartWaitingForArgument] to start the
|
||||
* digraph state machine. This also gives us a repeatable command and captures the keys for `'showcmd'`.
|
||||
*/
|
||||
override fun onStartWaitingForArgument(editor: VimEditor, context: ExecutionContext, keyState: KeyHandlerState) {
|
||||
val result = keyState.digraphSequence.startDigraphSequence()
|
||||
KeyHandler.getInstance().setPromptCharacterEx(result.promptCharacter)
|
||||
@@ -56,7 +48,6 @@ class InsertCompletedDigraphAction : VimActionHandler.SingleExecution() {
|
||||
cmd: Command,
|
||||
operatorArguments: OperatorArguments,
|
||||
): Boolean {
|
||||
// The converted digraph character has been captured as an argument, push it back through key handler
|
||||
val argument = cmd.argument as? Argument.Character ?: return false
|
||||
val keyStroke = KeyStroke.getKeyStroke(argument.character)
|
||||
val keyHandler = KeyHandler.getInstance()
|
||||
@@ -64,3 +55,37 @@ class InsertCompletedDigraphAction : VimActionHandler.SingleExecution() {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Command-line mode: insert a digraph character via `<C-K>`
|
||||
*
|
||||
* Control characters like Escape or Enter are inserted directly into the command line to avoid being matched as
|
||||
* commands. Other characters use [VimCommandLine.handleKey] so that overwrite mode is handled correctly.
|
||||
*/
|
||||
@CommandOrMotion(keys = ["<C-K>"], modes = [Mode.CMD_LINE])
|
||||
class CmdLineCompletedDigraphAction : VimActionHandler.SingleExecution() {
|
||||
override val type: Command.Type = Command.Type.INSERT
|
||||
override val argumentType: Argument.Type = Argument.Type.DIGRAPH
|
||||
|
||||
override fun onStartWaitingForArgument(editor: VimEditor, context: ExecutionContext, keyState: KeyHandlerState) {
|
||||
val result = keyState.digraphSequence.startDigraphSequence()
|
||||
KeyHandler.getInstance().setPromptCharacterEx(result.promptCharacter)
|
||||
}
|
||||
|
||||
override fun execute(
|
||||
editor: VimEditor,
|
||||
context: ExecutionContext,
|
||||
cmd: Command,
|
||||
operatorArguments: OperatorArguments,
|
||||
): Boolean {
|
||||
val argument = cmd.argument as? Argument.Character ?: return false
|
||||
val commandLine = injector.commandLine.getActiveCommandLine() ?: return false
|
||||
val ch = argument.character
|
||||
if (ch.isCommandLineActionChar()) {
|
||||
commandLine.insertText(commandLine.caret.offset, ch.toString())
|
||||
} else {
|
||||
commandLine.handleKey(KeyStroke.getKeyStroke(ch))
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2003-2023 The IdeaVim authors
|
||||
* Copyright 2003-2026 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
|
||||
@@ -13,14 +13,22 @@ 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.helper.isCommandLineActionChar
|
||||
import com.maddyhome.idea.vim.state.KeyHandlerState
|
||||
import javax.swing.KeyStroke
|
||||
|
||||
@CommandOrMotion(keys = ["<C-V>", "<C-Q>"], modes = [Mode.INSERT, Mode.CMD_LINE])
|
||||
/**
|
||||
* Insert mode: insert a literal character via `<C-V>` / `<C-Q>`
|
||||
*
|
||||
* The converted literal character is re-injected through the key handler so that it is processed as typed input in
|
||||
* Insert mode (handled by the change group).
|
||||
*/
|
||||
@CommandOrMotion(keys = ["<C-V>", "<C-Q>"], modes = [Mode.INSERT])
|
||||
class InsertCompletedLiteralAction : VimActionHandler.SingleExecution() {
|
||||
override val type: Command.Type = Command.Type.INSERT
|
||||
|
||||
@@ -29,22 +37,6 @@ class InsertCompletedLiteralAction : VimActionHandler.SingleExecution() {
|
||||
// We're waiting for it to complete and give us a CHARACTER
|
||||
override val argumentType: Argument.Type = Argument.Type.DIGRAPH
|
||||
|
||||
/**
|
||||
* Perform additional initialisation when starting to wait for an argument
|
||||
*
|
||||
* IdeaVim has two ways of handling digraphs/literals. Actions such as `r` or `f` can accept a digraph, which really
|
||||
* means it accepts a character, but the user can use `<C-K>`/`<C-V>` to type a digraph or literal and convert it into
|
||||
* a character. Unfortunately, there is no mode that can be used to register an "insert digraph/literal" action for
|
||||
* these keys while replace or find is active. So the key handler hard codes these keys and will check for them when
|
||||
* an action expects a digraph (and like Vim, these keys cannot be mapped). Once the state machine has matched a
|
||||
* character, the expected argument is reset to [Argument.Type.CHARACTER] and the character is passed through the key
|
||||
* handler again, potentially mapped, and then attached as an argument to the current command, which is now complete
|
||||
* and executed.
|
||||
*
|
||||
* In Insert and Command-line mode, the `<C-K>` and `<C-V>` keys are actions that will wait for a character argument,
|
||||
* and then insert it. Commands are only executed once complete, so we use [onStartWaitingForArgument] to start the
|
||||
* digraph state machine. This also gives us a repeatable command and captures the keys for `'showcmd'`.
|
||||
*/
|
||||
override fun onStartWaitingForArgument(editor: VimEditor, context: ExecutionContext, keyState: KeyHandlerState) {
|
||||
val result = keyState.digraphSequence.startLiteralSequence()
|
||||
KeyHandler.getInstance().setPromptCharacterEx(result.promptCharacter)
|
||||
@@ -56,7 +48,6 @@ class InsertCompletedLiteralAction : VimActionHandler.SingleExecution() {
|
||||
cmd: Command,
|
||||
operatorArguments: OperatorArguments,
|
||||
): Boolean {
|
||||
// The converted literal character has been captured as an argument, push it back through key handler
|
||||
val argument = cmd.argument as? Argument.Character ?: return false
|
||||
val keyStroke = KeyStroke.getKeyStroke(argument.character)
|
||||
val keyHandler = KeyHandler.getInstance()
|
||||
@@ -64,3 +55,39 @@ class InsertCompletedLiteralAction : VimActionHandler.SingleExecution() {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Command-line mode: insert a literal character via `<C-V>` / `<C-Q>`
|
||||
*
|
||||
* Control characters like Escape or Enter are inserted directly into the command line to avoid being matched as
|
||||
* commands (e.g., LeaveCommandLineAction). Other characters use [VimCommandLine.handleKey] so that overwrite mode
|
||||
* is handled correctly.
|
||||
*/
|
||||
@CommandOrMotion(keys = ["<C-V>", "<C-Q>"], modes = [Mode.CMD_LINE])
|
||||
class CmdLineCompletedLiteralAction : VimActionHandler.SingleExecution() {
|
||||
override val type: Command.Type = Command.Type.INSERT
|
||||
override val argumentType: Argument.Type = Argument.Type.DIGRAPH
|
||||
|
||||
override fun onStartWaitingForArgument(editor: VimEditor, context: ExecutionContext, keyState: KeyHandlerState) {
|
||||
val result = keyState.digraphSequence.startLiteralSequence()
|
||||
KeyHandler.getInstance().setPromptCharacterEx(result.promptCharacter)
|
||||
}
|
||||
|
||||
override fun execute(
|
||||
editor: VimEditor,
|
||||
context: ExecutionContext,
|
||||
cmd: Command,
|
||||
operatorArguments: OperatorArguments,
|
||||
): Boolean {
|
||||
val argument = cmd.argument as? Argument.Character ?: return false
|
||||
val commandLine = injector.commandLine.getActiveCommandLine() ?: return false
|
||||
val ch = argument.character
|
||||
if (ch.isCommandLineActionChar()) {
|
||||
// Insert directly to avoid these being matched as commands by the key handler
|
||||
commandLine.insertText(commandLine.caret.offset, ch.toString())
|
||||
} else {
|
||||
commandLine.handleKey(KeyStroke.getKeyStroke(ch))
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -160,7 +160,11 @@ abstract class VimSearchHelperBase : VimSearchHelper {
|
||||
return TextRange(start, end)
|
||||
}
|
||||
|
||||
override fun findWordAtOrFollowingCursor(editor: VimEditor, caret: ImmutableVimCaret, isBigWord: Boolean): TextRange? {
|
||||
override fun findWordAtOrFollowingCursor(
|
||||
editor: VimEditor,
|
||||
caret: ImmutableVimCaret,
|
||||
isBigWord: Boolean,
|
||||
): TextRange? {
|
||||
val offset = caret.offset
|
||||
return findWordAtOrFollowingCursor(editor, offset, isBigWord)
|
||||
}
|
||||
@@ -168,6 +172,7 @@ abstract class VimSearchHelperBase : VimSearchHelper {
|
||||
override fun findFilenameAtOrFollowingCursor(editor: VimEditor, caret: ImmutableVimCaret): TextRange? {
|
||||
return findFilenameAtOrFollowingCursor(editor, caret.offset)
|
||||
}
|
||||
|
||||
override fun findFilenameAtOrFollowingCursor(editor: VimEditor, offset: Int): TextRange? {
|
||||
val text = editor.text()
|
||||
if (text.isEmpty()) return null
|
||||
@@ -300,6 +305,9 @@ abstract class VimSearchHelperBase : VimSearchHelper {
|
||||
}
|
||||
|
||||
if (result is VimMatchResult.Failure) {
|
||||
if (!showMessages) {
|
||||
return null
|
||||
}
|
||||
if (wrap) {
|
||||
injector.messages.showErrorMessage(editor, injector.messages.message("E486", pattern))
|
||||
} else if (dir === Direction.FORWARDS) {
|
||||
@@ -307,7 +315,6 @@ abstract class VimSearchHelperBase : VimSearchHelper {
|
||||
} else {
|
||||
injector.messages.showErrorMessage(editor, injector.messages.message("E384", pattern))
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
// When trying to find the end position for a match, we're allowed to match the current position. But if we do that
|
||||
@@ -334,6 +341,10 @@ abstract class VimSearchHelperBase : VimSearchHelper {
|
||||
}
|
||||
}
|
||||
|
||||
if (result is VimMatchResult.Failure) {
|
||||
return null
|
||||
}
|
||||
|
||||
return (result as VimMatchResult.Success).range
|
||||
}
|
||||
|
||||
@@ -1768,7 +1779,8 @@ abstract class VimSearchHelperBase : VimSearchHelper {
|
||||
|
||||
if (isOuter && shouldEndOnWhitespace && start > 0
|
||||
&& !isWhitespace(editor, chars[end], isBig)
|
||||
&& !isWhitespace(editor, chars[start], isBig)) {
|
||||
&& !isWhitespace(editor, chars[start], isBig)
|
||||
) {
|
||||
|
||||
// Outer word objects normally include following whitespace. But if there's no following whitespace to include,
|
||||
// we should extend the range to include preceding whitespace. However, Vim doesn't select whitespace at the
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2003-2023 The IdeaVim authors
|
||||
* Copyright 2003-2026 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
|
||||
@@ -18,3 +18,13 @@ fun KeyStroke.isCloseKeyStroke(): Boolean {
|
||||
keyCode == KeyEvent.VK_C && modifiers and InputEvent.CTRL_DOWN_MASK != 0 ||
|
||||
keyCode == '['.code && modifiers and InputEvent.CTRL_DOWN_MASK != 0
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this character would be matched as a command-line action (close or execute) rather than text input
|
||||
* when re-injected through the key handler in CMD_LINE mode.
|
||||
*
|
||||
* Escape closes the command line, Enter/CR executes it.
|
||||
*/
|
||||
fun Char.isCommandLineActionChar(): Boolean {
|
||||
return this == '\u001B' || this == '\n' || this == '\r'
|
||||
}
|
||||
|
||||
@@ -83,7 +83,7 @@ sealed class Command(
|
||||
if (Flag.SAVE_SELECTION !in argFlags.flags) {
|
||||
// Editor.inBlockSelection is not available, because we're not in Visual mode anymore. Check if the primary caret
|
||||
// currently has a selection and if (when we still in Visual) it was a block selection.
|
||||
injector.application.runReadAction {
|
||||
injector.application.runWriteAction {
|
||||
if (editor.primaryCaret().hasSelection() && editor.primaryCaret().lastSelectionInfo.selectionType.isBlock) {
|
||||
editor.removeSecondaryCarets()
|
||||
}
|
||||
|
||||
@@ -299,10 +299,15 @@
|
||||
"class": "com.maddyhome.idea.vim.action.motion.updown.MotionDownAction",
|
||||
"modes": "NXO"
|
||||
},
|
||||
{
|
||||
"keys": "<C-K>",
|
||||
"class": "com.maddyhome.idea.vim.action.change.insert.CmdLineCompletedDigraphAction",
|
||||
"modes": "C"
|
||||
},
|
||||
{
|
||||
"keys": "<C-K>",
|
||||
"class": "com.maddyhome.idea.vim.action.change.insert.InsertCompletedDigraphAction",
|
||||
"modes": "IC"
|
||||
"modes": "I"
|
||||
},
|
||||
{
|
||||
"keys": "<C-Left>",
|
||||
@@ -409,10 +414,15 @@
|
||||
"class": "com.maddyhome.idea.vim.action.window.tabs.PreviousTabAction",
|
||||
"modes": "NXO"
|
||||
},
|
||||
{
|
||||
"keys": "<C-Q>",
|
||||
"class": "com.maddyhome.idea.vim.action.change.insert.CmdLineCompletedLiteralAction",
|
||||
"modes": "C"
|
||||
},
|
||||
{
|
||||
"keys": "<C-Q>",
|
||||
"class": "com.maddyhome.idea.vim.action.change.insert.InsertCompletedLiteralAction",
|
||||
"modes": "IC"
|
||||
"modes": "I"
|
||||
},
|
||||
{
|
||||
"keys": "<C-R>",
|
||||
@@ -559,10 +569,15 @@
|
||||
"class": "com.maddyhome.idea.vim.action.motion.scroll.CtrlUpAction",
|
||||
"modes": "N"
|
||||
},
|
||||
{
|
||||
"keys": "<C-V>",
|
||||
"class": "com.maddyhome.idea.vim.action.change.insert.CmdLineCompletedLiteralAction",
|
||||
"modes": "C"
|
||||
},
|
||||
{
|
||||
"keys": "<C-V>",
|
||||
"class": "com.maddyhome.idea.vim.action.change.insert.InsertCompletedLiteralAction",
|
||||
"modes": "IC"
|
||||
"modes": "I"
|
||||
},
|
||||
{
|
||||
"keys": "<C-W>",
|
||||
|
||||
Reference in New Issue
Block a user