mirror of
https://github.com/chylex/IntelliJ-IdeaVim.git
synced 2026-04-07 16:46:53 +02:00
Compare commits
29 Commits
customized
...
customized
| Author | SHA1 | Date | |
|---|---|---|---|
|
7b813899f0
|
|||
|
727dee5b85
|
|||
|
3e7ea8668c
|
|||
|
89f7c76180
|
|||
|
a7d0297e2d
|
|||
|
45da61debe
|
|||
|
ebc77454ab
|
|||
|
c9193cb6d4
|
|||
|
13246c0a80
|
|||
|
b0ff57a4f5
|
|||
|
f4e0684ca8
|
|||
|
3a3e7952b1
|
|||
|
1ff6066e33
|
|||
|
3a9abba410
|
|||
|
510f8f948e
|
|||
|
b623bf739c
|
|||
|
c99d97b3bc
|
|||
|
6b8eb8952f
|
|||
|
25d70ee975
|
|||
|
cbc9637d17
|
|||
|
0d893d9961
|
|||
|
4ac3a1eaaa
|
|||
|
86a6e9643f
|
|||
|
8b06078607
|
|||
|
924455907a
|
|||
|
40367859b8
|
|||
|
45f7934d71
|
|||
|
0880e5f935
|
|||
|
8af3788379
|
16
.idea/runConfigurations/Split_Frontend_Debugger.xml
generated
16
.idea/runConfigurations/Split_Frontend_Debugger.xml
generated
@@ -1,16 +0,0 @@
|
||||
<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
24
.idea/runConfigurations/Start_CLion_with_IdeaVim.xml
generated
@@ -1,24 +0,0 @@
|
||||
<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>
|
||||
@@ -1,25 +0,0 @@
|
||||
<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" folderName="Split Mode">
|
||||
<configuration default="false" name="Start IJ with IdeaVim (Split Mode)" type="GradleRunConfiguration" factoryName="Gradle">
|
||||
<log_file alias="idea.log" path="$PROJECT_DIR$/build/idea-sandbox/system/log/idea.log" />
|
||||
<ExternalSystemSettings>
|
||||
<option name="executionName" />
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
<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>
|
||||
@@ -1,24 +0,0 @@
|
||||
<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>
|
||||
@@ -1,25 +0,0 @@
|
||||
<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
24
.idea/runConfigurations/Start_Rider_with_IdeaVim.xml
generated
@@ -1,24 +0,0 @@
|
||||
<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>
|
||||
@@ -1,24 +0,0 @@
|
||||
<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>
|
||||
@@ -1,25 +0,0 @@
|
||||
<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,7 +6,6 @@
|
||||
* 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
|
||||
@@ -27,11 +26,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.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")
|
||||
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")
|
||||
|
||||
// This comes from the changelog plugin
|
||||
// classpath("org.jetbrains:markdown:0.3.1")
|
||||
@@ -113,7 +112,7 @@ dependencies {
|
||||
testFramework(TestFrameworkType.Platform)
|
||||
testFramework(TestFrameworkType.JUnit5)
|
||||
|
||||
compatiblePlugin("com.intellij.classic.ui")
|
||||
plugin("com.intellij.classic.ui", "261.22158.185")
|
||||
|
||||
pluginModule(runtimeOnly(project(":modules:ideavim-common")))
|
||||
pluginModule(runtimeOnly(project(":modules:ideavim-frontend")))
|
||||
@@ -226,30 +225,6 @@ 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 {
|
||||
@@ -272,55 +247,6 @@ 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.
|
||||
@@ -329,11 +255,6 @@ 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 {
|
||||
@@ -365,12 +286,6 @@ 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-55
|
||||
version=chylex-53
|
||||
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/2d6327017519d23b96af35865dc997fcb544fb40/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||
# https://github.com/gradle/gradle/blob/b631911858264c0b6e4d6603d677ff5218766cee/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,27 +165,25 @@ 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" }
|
||||
return LocalFileSystem.getInstance().refreshAndFindFileByNioFile(Path(dir, relativePath))
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
return found
|
||||
}
|
||||
|
||||
private fun buildFileInfoMessage(editor: Editor, project: Project, fullPath: Boolean): String {
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
<idea-plugin>
|
||||
<dependencies>
|
||||
<plugin id="com.intellij.modules.rider"/>
|
||||
<module name="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.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("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("org.eclipse.jgit:org.eclipse.jgit:6.6.0.202305301015-r")
|
||||
|
||||
// This is needed for jgit to connect to ssh
|
||||
|
||||
@@ -22,7 +22,6 @@ 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;
|
||||
@@ -131,12 +130,12 @@ public class VimPlugin implements PersistentStateComponent<Element>, Disposable
|
||||
return VimInjectorKt.getInjector().getHistoryGroup();
|
||||
}
|
||||
|
||||
public static @NotNull KeyGroup getKey() {
|
||||
return ((KeyGroup)VimInjectorKt.getInjector().getKeyGroup());
|
||||
public static @NotNull VimKeyGroup getKey() {
|
||||
return VimInjectorKt.getInjector().getKeyGroup();
|
||||
}
|
||||
|
||||
public static @Nullable KeyGroup getKeyIfCreated() {
|
||||
return ApplicationManager.getApplication().getServiceIfCreated(KeyGroup.class);
|
||||
public static @Nullable VimKeyGroup getKeyIfCreated() {
|
||||
return ApplicationManager.getApplication().getServiceIfCreated(VimKeyGroup.class);
|
||||
}
|
||||
|
||||
public static @NotNull VimWindowGroup getWindow() {
|
||||
@@ -338,7 +337,7 @@ public class VimPlugin implements PersistentStateComponent<Element>, Disposable
|
||||
}
|
||||
}
|
||||
if (element.getChild("shortcut-conflicts") != null) {
|
||||
getKey().loadShortcutConflictsData(element);
|
||||
((VimKeyGroupBase)getKey()).loadShortcutConflictsData(element);
|
||||
}
|
||||
if (element.getChild("editor") != null) {
|
||||
getEditor().loadEditorStateData(element);
|
||||
|
||||
@@ -11,7 +11,6 @@ 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
|
||||
@@ -21,6 +20,7 @@ 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,13 +106,9 @@ class VimExtensionRegistrar : VimExtensionRegistrator {
|
||||
override fun enableDelayedExtensions() {
|
||||
delayedExtensionEnabling.forEach {
|
||||
val name = it.name ?: it.instance.name
|
||||
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)
|
||||
}
|
||||
val initApi = createVimApi(name)
|
||||
it.instance.init(initApi)
|
||||
logger.info("IdeaVim extension '$name' initialized")
|
||||
}
|
||||
delayedExtensionEnabling.clear()
|
||||
}
|
||||
|
||||
@@ -241,17 +241,13 @@ internal class VimEscHandler(nextHandler: EditorActionHandler) : VimKeyHandler(n
|
||||
|
||||
/**
|
||||
* Rider (and CLion Nova) uses a separate handler for esc to close the completion. IdeaOnlyEscapeHandlerAction is especially
|
||||
* designed to get all the esc presses, and if there is a completion close it and do not pass the execution further.
|
||||
* designer 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>"
|
||||
|
||||
@@ -49,9 +49,8 @@ import com.maddyhome.idea.vim.group.NotificationService
|
||||
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.hasVisualSelection
|
||||
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
|
||||
@@ -334,6 +333,23 @@ internal object IdeaSpecifics {
|
||||
vimEditor.exitMode()
|
||||
vimEditor.mode = Mode.NORMAL()
|
||||
}
|
||||
} else {
|
||||
// IdeaSelectionControl will not be called if we're moving to a new variable with no change in selection.
|
||||
// And if we're moving to the end of the template, the change in selection will reset us to Normal because
|
||||
// IdeaSelectionControl will be called when the template is no longer active.
|
||||
if ((!editor.selectionModel.hasSelection() && !vimEditor.mode.hasVisualSelection) || newIndex == -1) {
|
||||
if (vimEditor.isIdeaRefactorModeSelect) {
|
||||
if (vimEditor.mode !is Mode.INSERT) {
|
||||
vimEditor.exitMode()
|
||||
injector.application.runReadAction {
|
||||
val context = injector.executionContextManager.getEditorExecutionContext(editor.vim)
|
||||
VimPlugin.getChange().insertBeforeCaret(editor.vim, context)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
vimEditor.mode = Mode.NORMAL()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -352,16 +368,6 @@ 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
|
||||
@@ -373,20 +379,6 @@ 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,7 +12,6 @@ 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
|
||||
@@ -199,12 +198,3 @@ 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,12 +671,3 @@ 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,6 +14,7 @@ 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
|
||||
@@ -26,3 +27,21 @@ 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 && !isKeyCharEnterOrEscape(stroke.keyChar)) {
|
||||
if (stroke.keyChar != KeyEvent.CHAR_UNDEFINED) {
|
||||
replaceSelection(stroke.keyChar.toString())
|
||||
} else {
|
||||
val event = KeyEvent(
|
||||
|
||||
@@ -20,5 +20,5 @@ import com.maddyhome.idea.vim.vimscript.model.functions.BuiltinFunctionHandler
|
||||
@VimscriptFunction(name = "pumvisible")
|
||||
internal class PopupMenuVisibleFunctionHandler : BuiltinFunctionHandler<VimInt>() {
|
||||
override fun doFunction(arguments: Arguments, editor: VimEditor, context: ExecutionContext, vimContext: VimLContext) =
|
||||
(CompletionService.getCompletionService().currentCompletion != null).asVimInt()
|
||||
(CompletionService.getCompletionService().currentCompletion == null).asVimInt()
|
||||
}
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
<!--
|
||||
~ 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-2026 The IdeaVim authors
|
||||
* Copyright 2003-2023 The IdeaVim authors
|
||||
*
|
||||
* Use of this source code is governed by an MIT-style
|
||||
* license that can be found in the LICENSE.txt file or at
|
||||
@@ -10,12 +10,9 @@ 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
|
||||
@@ -113,23 +110,6 @@ 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(500)
|
||||
pause(300)
|
||||
assertCaretAfter(40, "G should go to end of file")
|
||||
|
||||
ctrlO()
|
||||
pause(500)
|
||||
pause(300)
|
||||
assertCaretBefore(10, "Ctrl-O should jump back to start")
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ class JumpNavigationSplitTest : IdeaVimStarterTestBase() {
|
||||
openFile(longFile("Jump2"))
|
||||
|
||||
typeVim("gg")
|
||||
pause(500)
|
||||
pause(300)
|
||||
|
||||
typeVim("/Line 30\n")
|
||||
pause()
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2003-2026 The IdeaVim authors
|
||||
* Copyright 2003-2023 The IdeaVim authors
|
||||
*
|
||||
* Use of this source code is governed by an MIT-style
|
||||
* license that can be found in the LICENSE.txt file or at
|
||||
@@ -13,22 +13,14 @@ 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
|
||||
|
||||
/**
|
||||
* 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])
|
||||
@CommandOrMotion(keys = ["<C-K>"], modes = [Mode.INSERT, Mode.CMD_LINE])
|
||||
class InsertCompletedDigraphAction : VimActionHandler.SingleExecution() {
|
||||
override val type: Command.Type = Command.Type.INSERT
|
||||
|
||||
@@ -37,6 +29,22 @@ 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)
|
||||
@@ -48,6 +56,7 @@ 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()
|
||||
@@ -55,37 +64,3 @@ 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-2026 The IdeaVim authors
|
||||
* Copyright 2003-2023 The IdeaVim authors
|
||||
*
|
||||
* Use of this source code is governed by an MIT-style
|
||||
* license that can be found in the LICENSE.txt file or at
|
||||
@@ -13,22 +13,14 @@ 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
|
||||
|
||||
/**
|
||||
* 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])
|
||||
@CommandOrMotion(keys = ["<C-V>", "<C-Q>"], modes = [Mode.INSERT, Mode.CMD_LINE])
|
||||
class InsertCompletedLiteralAction : VimActionHandler.SingleExecution() {
|
||||
override val type: Command.Type = Command.Type.INSERT
|
||||
|
||||
@@ -37,6 +29,22 @@ 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)
|
||||
@@ -48,6 +56,7 @@ 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()
|
||||
@@ -55,39 +64,3 @@ 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,11 +160,7 @@ 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)
|
||||
}
|
||||
@@ -172,7 +168,6 @@ 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
|
||||
@@ -305,9 +300,6 @@ 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) {
|
||||
@@ -315,6 +307,7 @@ 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
|
||||
@@ -341,10 +334,6 @@ abstract class VimSearchHelperBase : VimSearchHelper {
|
||||
}
|
||||
}
|
||||
|
||||
if (result is VimMatchResult.Failure) {
|
||||
return null
|
||||
}
|
||||
|
||||
return (result as VimMatchResult.Success).range
|
||||
}
|
||||
|
||||
@@ -1779,8 +1768,7 @@ 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-2026 The IdeaVim authors
|
||||
* Copyright 2003-2023 The IdeaVim authors
|
||||
*
|
||||
* Use of this source code is governed by an MIT-style
|
||||
* license that can be found in the LICENSE.txt file or at
|
||||
@@ -18,13 +18,3 @@ 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.runWriteAction {
|
||||
injector.application.runReadAction {
|
||||
if (editor.primaryCaret().hasSelection() && editor.primaryCaret().lastSelectionInfo.selectionType.isBlock) {
|
||||
editor.removeSecondaryCarets()
|
||||
}
|
||||
|
||||
@@ -299,15 +299,10 @@
|
||||
"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": "I"
|
||||
"modes": "IC"
|
||||
},
|
||||
{
|
||||
"keys": "<C-Left>",
|
||||
@@ -414,15 +409,10 @@
|
||||
"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": "I"
|
||||
"modes": "IC"
|
||||
},
|
||||
{
|
||||
"keys": "<C-R>",
|
||||
@@ -569,15 +559,10 @@
|
||||
"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": "I"
|
||||
"modes": "IC"
|
||||
},
|
||||
{
|
||||
"keys": "<C-W>",
|
||||
|
||||
Reference in New Issue
Block a user