mirror of
https://github.com/chylex/IntelliJ-IdeaVim.git
synced 2024-11-25 16:42:55 +01:00
Compare commits
40 Commits
8a9d9af1bb
...
8e162bce95
Author | SHA1 | Date | |
---|---|---|---|
8e162bce95 | |||
2cdd62371e | |||
d461f61438 | |||
de7fe30a97 | |||
6d80c21344 | |||
a57a80442c | |||
866e6dc831 | |||
f11bb12f19 | |||
70ea1bd46f | |||
|
2845beaf8a | ||
|
1e58ead126 | ||
|
fafa7572d0 | ||
|
4ddeb72bfe | ||
|
28ba36dddb | ||
|
b6c501311c | ||
|
01d4ebe254 | ||
|
34dd332f0b | ||
|
596d0c7115 | ||
|
672601b028 | ||
|
e5045f28ab | ||
|
12ba067db3 | ||
|
5413606425 | ||
|
72ae18557b | ||
|
99bd119ed6 | ||
|
faebf66065 | ||
|
dc030d6895 | ||
|
7f626005a5 | ||
|
28d0741e14 | ||
|
c0e17a6c61 | ||
|
b5046b089e | ||
|
1075112bfa | ||
|
37fddacf8e | ||
|
2091a59897 | ||
|
d2a427b38f | ||
|
c069719c1c | ||
|
654a443d4b | ||
|
a6ec2d5ed7 | ||
|
02ac083175 | ||
|
561fce5d40 | ||
|
a88263874a |
1
.gitattributes
vendored
Normal file
1
.gitattributes
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
* text=auto eol=lf
|
31
.github/workflows/checkNewPlugins.yml
vendored
Normal file
31
.github/workflows/checkNewPlugins.yml
vendored
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
# This workflow will build a package using Gradle and then publish it to GitHub packages when a release is created
|
||||||
|
# For more information see: https://github.com/actions/setup-java/blob/main/docs/advanced-usage.md#Publishing-using-gradle
|
||||||
|
|
||||||
|
# This workflow syncs changes from the docs folder of IdeaVim to the IdeaVim.wiki repository
|
||||||
|
|
||||||
|
name: Check new plugin dependencies
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
schedule:
|
||||||
|
- cron: '0 5 * * *'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Fetch origin repo
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Set up JDK 17
|
||||||
|
uses: actions/setup-java@v2
|
||||||
|
with:
|
||||||
|
java-version: '17'
|
||||||
|
distribution: 'adopt'
|
||||||
|
server-id: github # Value of the distributionManagement/repository/id field of the pom.xml
|
||||||
|
settings-path: ${{ github.workspace }} # location for the settings.xml file
|
||||||
|
|
||||||
|
- name: Check new plugins
|
||||||
|
run: ./gradlew scripts:checkNewPluginDependencies
|
19
.github/workflows/mergePr.yml
vendored
19
.github/workflows/mergePr.yml
vendored
@ -5,7 +5,7 @@ name: Update Changelog On PR
|
|||||||
|
|
||||||
on:
|
on:
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
pull_request:
|
pull_request_target:
|
||||||
types: [ closed ]
|
types: [ closed ]
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
@ -30,13 +30,26 @@ jobs:
|
|||||||
id: update_authors
|
id: update_authors
|
||||||
run: ./gradlew updateMergedPr -PprId=${{ github.event.number }}
|
run: ./gradlew updateMergedPr -PprId=${{ github.event.number }}
|
||||||
env:
|
env:
|
||||||
GITHUB_OAUTH: ${{ secrets.MERGE_PR }}
|
GITHUB_OAUTH: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
# Reuse from update changelog
|
||||||
|
- uses: nrwl/last-successful-commit-action@v1
|
||||||
|
id: last_successful_commit
|
||||||
|
with:
|
||||||
|
branch: 'master'
|
||||||
|
workflow_id: 'updateChangelog.yml'
|
||||||
|
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: Update changelog
|
||||||
|
run: ./gradlew updateChangelog
|
||||||
|
env:
|
||||||
|
SUCCESS_COMMIT: ${{ steps.last_successful_commit.outputs.commit_hash }}
|
||||||
|
|
||||||
- name: Commit changes
|
- name: Commit changes
|
||||||
uses: stefanzweifel/git-auto-commit-action@v4
|
uses: stefanzweifel/git-auto-commit-action@v4
|
||||||
with:
|
with:
|
||||||
branch: master
|
branch: master
|
||||||
commit_message: Update changelog after merging PR
|
commit_message: Update changelog after merging PR
|
||||||
commit_user_name: Alex Plate
|
commit_user_name: Alex Plate
|
||||||
commit_user_email: aleksei.plate@jetbrains.com
|
commit_user_email: aleksei.plate@jetbrains.com
|
||||||
commit_author: Alex Plate <aleksei.plate@jetbrains.com>
|
commit_author: Alex Plate <aleksei.plate@jetbrains.com>
|
||||||
|
2
.github/workflows/updateChangelog.yml
vendored
2
.github/workflows/updateChangelog.yml
vendored
@ -11,6 +11,7 @@ on:
|
|||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
|
|
||||||
|
if: github.event.pull_request.merged != true
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
@ -45,3 +46,4 @@ jobs:
|
|||||||
commit_user_email: aleksei.plate@jetbrains.com
|
commit_user_email: aleksei.plate@jetbrains.com
|
||||||
commit_author: Alex Plate <aleksei.plate@jetbrains.com>
|
commit_author: Alex Plate <aleksei.plate@jetbrains.com>
|
||||||
file_pattern: CHANGES.md
|
file_pattern: CHANGES.md
|
||||||
|
skip_fetch: false
|
@ -25,6 +25,9 @@ usual beta standards.
|
|||||||
|
|
||||||
## To Be Released
|
## To Be Released
|
||||||
|
|
||||||
|
### Features:
|
||||||
|
* Add IdeaVim tutor. You can access it via the status bar icon.
|
||||||
|
|
||||||
### Fixes:
|
### Fixes:
|
||||||
* [VIM-2797](https://youtrack.jetbrains.com/issue/VIM-2797) Introduce variable to mute default argtextobj mappings
|
* [VIM-2797](https://youtrack.jetbrains.com/issue/VIM-2797) Introduce variable to mute default argtextobj mappings
|
||||||
* [VIM-758](https://youtrack.jetbrains.com/issue/VIM-758) Support d mappings
|
* [VIM-758](https://youtrack.jetbrains.com/issue/VIM-758) Support d mappings
|
||||||
@ -37,6 +40,9 @@ usual beta standards.
|
|||||||
* [553](https://github.com/JetBrains/ideavim/pull/553) by [Matt Ellis](https://github.com/citizenmatt): Rearrange and rename some code in engine
|
* [553](https://github.com/JetBrains/ideavim/pull/553) by [Matt Ellis](https://github.com/citizenmatt): Rearrange and rename some code in engine
|
||||||
* [560](https://github.com/JetBrains/ideavim/pull/560) by [Runinho](https://github.com/Runinho): Fix(VIM-2577) paste not working at end of notebook cell
|
* [560](https://github.com/JetBrains/ideavim/pull/560) by [Runinho](https://github.com/Runinho): Fix(VIM-2577) paste not working at end of notebook cell
|
||||||
* [571](https://github.com/JetBrains/ideavim/pull/571) by [Ada](https://github.com/adaext): Remove the redundant quotation mark at the end of "packadd matchit" command
|
* [571](https://github.com/JetBrains/ideavim/pull/571) by [Ada](https://github.com/adaext): Remove the redundant quotation mark at the end of "packadd matchit" command
|
||||||
|
* [561](https://github.com/JetBrains/ideavim/pull/561) by [Matt Ellis](https://github.com/citizenmatt): Fix incremental search not scrolling to current match
|
||||||
|
* [559](https://github.com/JetBrains/ideavim/pull/559) by [Runinho](https://github.com/Runinho): Fix(VIM-2760) notebookCommandMode detection
|
||||||
|
* [579](https://github.com/JetBrains/ideavim/pull/579) by [Martin Yzeiri](https://github.com/myzeiri): VIM-2799: Add Matchit support for cshtml files
|
||||||
|
|
||||||
## 2.0.0, 2022-11-01
|
## 2.0.0, 2022-11-01
|
||||||
|
|
||||||
|
@ -89,7 +89,7 @@ Here are some examples of supported vim features and commands:
|
|||||||
* Vim web help
|
* Vim web help
|
||||||
* `~/.ideavimrc` configuration file
|
* `~/.ideavimrc` configuration file
|
||||||
|
|
||||||
[IdeaVim plugins](https://github.com/JetBrains/ideavim/wiki/Emulated-plugins):
|
[IdeaVim plugins](https://github.com/JetBrains/ideavim/wiki/IdeaVim-Plugins):
|
||||||
|
|
||||||
* vim-easymotion
|
* vim-easymotion
|
||||||
* NERDTree
|
* NERDTree
|
||||||
@ -104,6 +104,7 @@ Here are some examples of supported vim features and commands:
|
|||||||
* vim-paragraph-motion
|
* vim-paragraph-motion
|
||||||
* vim-indent-object
|
* vim-indent-object
|
||||||
* match.it
|
* match.it
|
||||||
|
etc
|
||||||
|
|
||||||
See also:
|
See also:
|
||||||
|
|
||||||
@ -202,7 +203,7 @@ Put your settings to `$XDG_CONFIG_HOME/ideavim/ideavimrc` file.
|
|||||||
IdeaVim Plugins
|
IdeaVim Plugins
|
||||||
--------------------
|
--------------------
|
||||||
|
|
||||||
See [doc/emulated-plugins.md](https://github.com/JetBrains/ideavim/wiki/Emulated-plugins)
|
See [doc/emulated-plugins.md](https://github.com/JetBrains/ideavim/wiki/IdeaVim-Plugins)
|
||||||
|
|
||||||
Executing IDE Actions
|
Executing IDE Actions
|
||||||
---------------------
|
---------------------
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
IdeaVim project is licensed under MIT license except the following parts of it:
|
IdeaVim project is licensed under MIT license except the following parts of it:
|
||||||
|
|
||||||
File [RegExp.kt](src/main/java/com/maddyhome/idea/vim/regexp/RegExp.kt) is licensed under Vim License.
|
File [RegExp.kt](src/main/java/com/maddyhome/idea/vim/regexp/RegExp.kt) is licensed under Vim License.
|
||||||
|
File [Tutor.kt](src/main/java/com/maddyhome/idea/vim/ui/Tutor.kt) is licensed under Vim License.
|
||||||
|
|
||||||
```
|
```
|
||||||
VIM LICENSE
|
VIM LICENSE
|
||||||
|
@ -61,6 +61,7 @@ plugins {
|
|||||||
antlr
|
antlr
|
||||||
java
|
java
|
||||||
kotlin("jvm") version "1.7.20"
|
kotlin("jvm") version "1.7.20"
|
||||||
|
application
|
||||||
|
|
||||||
id("org.jetbrains.intellij") version "1.11.1-SNAPSHOT"
|
id("org.jetbrains.intellij") version "1.11.1-SNAPSHOT"
|
||||||
id("org.jetbrains.changelog") version "1.3.1"
|
id("org.jetbrains.changelog") version "1.3.1"
|
||||||
@ -808,7 +809,7 @@ fun updateMergedPr(number: Int) {
|
|||||||
if (pullRequest.user.login == "dependabot[bot]") return
|
if (pullRequest.user.login == "dependabot[bot]") return
|
||||||
|
|
||||||
val prNumber = pullRequest.number
|
val prNumber = pullRequest.number
|
||||||
val userName = pullRequest.user.name
|
val userName = pullRequest.user.name ?: pullRequest.user.login
|
||||||
val login = pullRequest.user.login
|
val login = pullRequest.user.login
|
||||||
val title = pullRequest.title
|
val title = pullRequest.title
|
||||||
val section =
|
val section =
|
||||||
|
@ -381,3 +381,18 @@ Original plugin: [matchit.vim](https://github.com/chrisbra/matchit).
|
|||||||
https://github.com/adelarsq/vim-matchit/blob/master/doc/matchit.txt
|
https://github.com/adelarsq/vim-matchit/blob/master/doc/matchit.txt
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary><h2>IdeaVim-Quickscope</h2></summary>
|
||||||
|
|
||||||
|
Original plugin: [quick-scope](https://github.com/unblevable/quick-scope).
|
||||||
|
|
||||||
|
### Setup:
|
||||||
|
- Install [IdeaVim-sneak](https://plugins.jetbrains.com/plugin/15348-ideavim-sneak) plugin.
|
||||||
|
- Add the following command to `~/.ideavimrc`: `set quickscope`
|
||||||
|
|
||||||
|
### Instructions
|
||||||
|
|
||||||
|
https://plugins.jetbrains.com/plugin/19417-ideavim-quickscope
|
||||||
|
|
||||||
|
</details>
|
||||||
|
@ -8,15 +8,14 @@
|
|||||||
|
|
||||||
# suppress inspection "UnusedProperty" for whole file
|
# suppress inspection "UnusedProperty" for whole file
|
||||||
|
|
||||||
ideaVersion=LATEST-EAP-SNAPSHOT
|
ideaVersion=2022.3
|
||||||
downloadIdeaSources=true
|
downloadIdeaSources=true
|
||||||
instrumentPluginCode=true
|
instrumentPluginCode=true
|
||||||
version=SNAPSHOT
|
version=chylex-15
|
||||||
javaVersion=17
|
javaVersion=17
|
||||||
remoteRobotVersion=0.11.15
|
remoteRobotVersion=0.11.15
|
||||||
antlrVersion=4.10.1
|
antlrVersion=4.10.1
|
||||||
|
|
||||||
|
|
||||||
# Please don't forget to update kotlin version in buildscript section
|
# Please don't forget to update kotlin version in buildscript section
|
||||||
kotlinVersion=1.7.20
|
kotlinVersion=1.7.20
|
||||||
publishToken=token
|
publishToken=token
|
||||||
|
51
scripts/build.gradle.kts
Normal file
51
scripts/build.gradle.kts
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2003-2022 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
plugins {
|
||||||
|
java
|
||||||
|
kotlin("jvm")
|
||||||
|
application
|
||||||
|
}
|
||||||
|
|
||||||
|
// group 'org.jetbrains.ideavim'
|
||||||
|
// version 'SNAPSHOT'
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
mavenCentral()
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
compileOnly("org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.7.20")
|
||||||
|
|
||||||
|
implementation("io.ktor:ktor-client-core:2.1.3")
|
||||||
|
implementation("io.ktor:ktor-client-cio:2.1.3")
|
||||||
|
implementation("io.ktor:ktor-client-content-negotiation:2.1.3")
|
||||||
|
implementation("io.ktor:ktor-serialization-kotlinx-json:2.1.3")
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks {
|
||||||
|
compileKotlin {
|
||||||
|
kotlinOptions {
|
||||||
|
freeCompilerArgs = listOf("-Xjvm-default=all-compatibility")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.register("generateIdeaVimConfigurations", JavaExec::class) {
|
||||||
|
group = "verification"
|
||||||
|
description = "This job tracks if there are any new plugins in marketplace we don't know about"
|
||||||
|
mainClass.set("scripts.MainKt")
|
||||||
|
classpath = sourceSets["main"].runtimeClasspath
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.register("checkNewPluginDependencies", JavaExec::class) {
|
||||||
|
group = "verification"
|
||||||
|
description = "This job tracks if there are any new plugins in marketplace we don't know about"
|
||||||
|
mainClass.set("scripts.CheckNewPluginDependenciesKt")
|
||||||
|
classpath = sourceSets["main"].runtimeClasspath
|
||||||
|
}
|
13
scripts/src/main/kotlin/scripts/Main.kt
Normal file
13
scripts/src/main/kotlin/scripts/Main.kt
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2003-2022 The IdeaVim authors
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by an MIT-style
|
||||||
|
* license that can be found in the LICENSE.txt file or at
|
||||||
|
* https://opensource.org/licenses/MIT.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package scripts
|
||||||
|
|
||||||
|
fun main() {
|
||||||
|
println("Hello")
|
||||||
|
}
|
@ -0,0 +1,54 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2003-2022 The IdeaVim authors
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by an MIT-style
|
||||||
|
* license that can be found in the LICENSE.txt file or at
|
||||||
|
* https://opensource.org/licenses/MIT.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package scripts
|
||||||
|
|
||||||
|
import io.ktor.client.*
|
||||||
|
import io.ktor.client.call.*
|
||||||
|
import io.ktor.client.engine.cio.*
|
||||||
|
import io.ktor.client.plugins.contentnegotiation.*
|
||||||
|
import io.ktor.client.request.*
|
||||||
|
import io.ktor.serialization.kotlinx.json.*
|
||||||
|
import kotlinx.coroutines.runBlocking
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Marketplace has a API to get all plugins that depend on our plugin.
|
||||||
|
* Here we have a list of dependent plugins at some moment and we check if something changed in that.
|
||||||
|
* If so, we need to update our list of plugins.
|
||||||
|
*
|
||||||
|
* This script makes no actions and aimed to notify the devs in case they need to update the list of IdeaVim plugins.
|
||||||
|
*/
|
||||||
|
|
||||||
|
val knownPlugins = listOf(
|
||||||
|
"IdeaVimExtension",
|
||||||
|
"github.zgqq.intellij-enhance",
|
||||||
|
"org.jetbrains.IdeaVim-EasyMotion",
|
||||||
|
"io.github.mishkun.ideavimsneak",
|
||||||
|
"eu.theblob42.idea.whichkey",
|
||||||
|
"com.github.copilot",
|
||||||
|
"com.github.dankinsoid.multicursor",
|
||||||
|
"com.joshestein.ideavim-quickscope",
|
||||||
|
)
|
||||||
|
|
||||||
|
fun main() {
|
||||||
|
val client = HttpClient(CIO) {
|
||||||
|
install(ContentNegotiation) {
|
||||||
|
json()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
runBlocking {
|
||||||
|
val res = client.get("https://plugins.jetbrains.com/api/plugins/") {
|
||||||
|
parameter("dependency", "IdeaVIM")
|
||||||
|
parameter("includeOptional", true)
|
||||||
|
}
|
||||||
|
val output = res.body<List<String>>()
|
||||||
|
println(output)
|
||||||
|
if (knownPlugins != output) error("Unknown plugins list: ${output}")
|
||||||
|
}
|
||||||
|
}
|
@ -10,4 +10,5 @@ pluginManagement {
|
|||||||
|
|
||||||
rootProject.name = 'IdeaVIM'
|
rootProject.name = 'IdeaVIM'
|
||||||
include 'vim-engine'
|
include 'vim-engine'
|
||||||
|
include 'scripts'
|
||||||
|
|
||||||
|
@ -92,6 +92,16 @@ public class EventFacade {
|
|||||||
EditorFactory.getInstance().addEditorFactoryListener(listener, parentDisposable);
|
EditorFactory.getInstance().addEditorFactoryListener(listener, parentDisposable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void addCaretListener(@NotNull Editor editor,
|
||||||
|
@NotNull CaretListener listener,
|
||||||
|
@NotNull Disposable disposable) {
|
||||||
|
editor.getCaretModel().addCaretListener(listener, disposable);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeCaretListener(@NotNull Editor editor, @NotNull CaretListener listener) {
|
||||||
|
editor.getCaretModel().removeCaretListener(listener);
|
||||||
|
}
|
||||||
|
|
||||||
public void addEditorMouseListener(@NotNull Editor editor,
|
public void addEditorMouseListener(@NotNull Editor editor,
|
||||||
@NotNull EditorMouseListener listener,
|
@NotNull EditorMouseListener listener,
|
||||||
@NotNull Disposable disposable) {
|
@NotNull Disposable disposable) {
|
||||||
|
@ -242,12 +242,7 @@ public class VimPlugin implements PersistentStateComponent<Element>, Disposable
|
|||||||
|
|
||||||
public static @NotNull String getVersion() {
|
public static @NotNull String getVersion() {
|
||||||
final IdeaPluginDescriptor plugin = PluginManagerCore.getPlugin(getPluginId());
|
final IdeaPluginDescriptor plugin = PluginManagerCore.getPlugin(getPluginId());
|
||||||
if (!ApplicationManager.getApplication().isInternal()) {
|
return plugin != null ? plugin.getVersion() : "SNAPSHOT";
|
||||||
return plugin != null ? plugin.getVersion() : "SNAPSHOT";
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return "INTERNAL" + (plugin != null ? " - " + plugin.getVersion() : "");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isEnabled() {
|
public static boolean isEnabled() {
|
||||||
|
@ -144,6 +144,10 @@ class VimShortcutKeyAction : AnAction(), DumbAware/*, LightEditCompatible*/ {
|
|||||||
|
|
||||||
if ((keyCode == KeyEvent.VK_TAB || keyCode == KeyEvent.VK_ENTER) && editor.appCodeTemplateCaptured()) return false
|
if ((keyCode == KeyEvent.VK_TAB || keyCode == KeyEvent.VK_ENTER) && editor.appCodeTemplateCaptured()) return false
|
||||||
|
|
||||||
|
if (keyCode == KeyEvent.VK_LEFT || keyCode == KeyEvent.VK_RIGHT) return false
|
||||||
|
if (keyCode == KeyEvent.VK_UP || keyCode == KeyEvent.VK_DOWN) return false
|
||||||
|
if (keyCode == KeyEvent.VK_HOME || keyCode == KeyEvent.VK_END) return false
|
||||||
|
|
||||||
if (editor.inInsertMode) {
|
if (editor.inInsertMode) {
|
||||||
if (keyCode == KeyEvent.VK_TAB) {
|
if (keyCode == KeyEvent.VK_TAB) {
|
||||||
// TODO: This stops VimEditorTab seeing <Tab> in insert mode and correctly scrolling the view
|
// TODO: This stops VimEditorTab seeing <Tab> in insert mode and correctly scrolling the view
|
||||||
|
@ -228,12 +228,13 @@ private object FileTypePatterns {
|
|||||||
} else if (fileTypeName == "CMakeLists.txt" || fileName == "CMakeLists") {
|
} else if (fileTypeName == "CMakeLists.txt" || fileName == "CMakeLists") {
|
||||||
this.cMakePatterns
|
this.cMakePatterns
|
||||||
} else {
|
} else {
|
||||||
return null
|
this.htmlPatterns
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private val htmlLikeFileTypes = setOf(
|
private val htmlLikeFileTypes = setOf(
|
||||||
"HTML", "XML", "XHTML", "JSP", "JavaScript", "JSX Harmony", "TypeScript", "TypeScript JSX", "Vue.js", "Handlebars/Mustache"
|
"HTML", "XML", "XHTML", "JSP", "JavaScript", "JSX Harmony", "TypeScript",
|
||||||
|
"TypeScript JSX", "Vue.js", "Handlebars/Mustache", "Razor"
|
||||||
)
|
)
|
||||||
|
|
||||||
private val htmlPatterns = createHtmlPatterns()
|
private val htmlPatterns = createHtmlPatterns()
|
||||||
|
@ -12,6 +12,7 @@ import com.intellij.openapi.editor.Editor
|
|||||||
import com.maddyhome.idea.vim.VimPlugin
|
import com.maddyhome.idea.vim.VimPlugin
|
||||||
import com.maddyhome.idea.vim.api.ExecutionContext
|
import com.maddyhome.idea.vim.api.ExecutionContext
|
||||||
import com.maddyhome.idea.vim.api.VimCaret
|
import com.maddyhome.idea.vim.api.VimCaret
|
||||||
|
import com.maddyhome.idea.vim.api.VimChangeGroup
|
||||||
import com.maddyhome.idea.vim.api.VimEditor
|
import com.maddyhome.idea.vim.api.VimEditor
|
||||||
import com.maddyhome.idea.vim.api.getLineEndOffset
|
import com.maddyhome.idea.vim.api.getLineEndOffset
|
||||||
import com.maddyhome.idea.vim.api.injector
|
import com.maddyhome.idea.vim.api.injector
|
||||||
@ -30,6 +31,7 @@ import com.maddyhome.idea.vim.extension.VimExtensionFacade.putKeyMappingIfMissin
|
|||||||
import com.maddyhome.idea.vim.extension.VimExtensionFacade.setOperatorFunction
|
import com.maddyhome.idea.vim.extension.VimExtensionFacade.setOperatorFunction
|
||||||
import com.maddyhome.idea.vim.extension.VimExtensionFacade.setRegisterForCaret
|
import com.maddyhome.idea.vim.extension.VimExtensionFacade.setRegisterForCaret
|
||||||
import com.maddyhome.idea.vim.helper.editorMode
|
import com.maddyhome.idea.vim.helper.editorMode
|
||||||
|
import com.maddyhome.idea.vim.helper.runWithEveryCaretAndRestore
|
||||||
import com.maddyhome.idea.vim.key.OperatorFunction
|
import com.maddyhome.idea.vim.key.OperatorFunction
|
||||||
import com.maddyhome.idea.vim.newapi.IjVimCaret
|
import com.maddyhome.idea.vim.newapi.IjVimCaret
|
||||||
import com.maddyhome.idea.vim.newapi.IjVimEditor
|
import com.maddyhome.idea.vim.newapi.IjVimEditor
|
||||||
@ -75,22 +77,20 @@ class VimSurroundExtension : VimExtension {
|
|||||||
override val isRepeatable = true
|
override val isRepeatable = true
|
||||||
|
|
||||||
override fun execute(editor: VimEditor, context: ExecutionContext) {
|
override fun execute(editor: VimEditor, context: ExecutionContext) {
|
||||||
setOperatorFunction(Operator())
|
setOperatorFunction(Operator(supportsMultipleCursors = false)) // TODO
|
||||||
executeNormalWithoutMapping(injector.parser.parseKeys("g@"), editor.ij)
|
executeNormalWithoutMapping(injector.parser.parseKeys("g@"), editor.ij)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class VSurroundHandler : ExtensionHandler {
|
private class VSurroundHandler : ExtensionHandler {
|
||||||
override fun execute(editor: VimEditor, context: ExecutionContext) {
|
override fun execute(editor: VimEditor, context: ExecutionContext) {
|
||||||
val selectionStart = editor.ij.caretModel.primaryCaret.selectionStart
|
|
||||||
// NB: Operator ignores SelectionType anyway
|
// NB: Operator ignores SelectionType anyway
|
||||||
if (!Operator().apply(editor, context, SelectionType.CHARACTER_WISE)) {
|
if (!Operator(supportsMultipleCursors = true).apply(editor, context, SelectionType.CHARACTER_WISE)) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
runWriteAction {
|
runWriteAction {
|
||||||
// Leave visual mode
|
// Leave visual mode
|
||||||
executeNormalWithoutMapping(injector.parser.parseKeys("<Esc>"), editor.ij)
|
executeNormalWithoutMapping(injector.parser.parseKeys("<Esc>"), editor.ij)
|
||||||
editor.ij.caretModel.moveToOffset(selectionStart)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -111,6 +111,10 @@ class VimSurroundExtension : VimExtension {
|
|||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun change(editor: VimEditor, context: ExecutionContext, charFrom: Char, newSurround: Pair<String, String>?) {
|
fun change(editor: VimEditor, context: ExecutionContext, charFrom: Char, newSurround: Pair<String, String>?) {
|
||||||
|
editor.ij.runWithEveryCaretAndRestore { changeAtCaret(editor, context, charFrom, newSurround) }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun changeAtCaret(editor: VimEditor, context: ExecutionContext, charFrom: Char, newSurround: Pair<String, String>?) {
|
||||||
// Save old register values for carets
|
// Save old register values for carets
|
||||||
val surroundings = editor.sortedCarets()
|
val surroundings = editor.sortedCarets()
|
||||||
.map {
|
.map {
|
||||||
@ -209,27 +213,45 @@ class VimSurroundExtension : VimExtension {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class Operator : OperatorFunction {
|
private class Operator(private val supportsMultipleCursors: Boolean) : OperatorFunction {
|
||||||
override fun apply(vimEditor: VimEditor, context: ExecutionContext, selectionType: SelectionType): Boolean {
|
override fun apply(vimEditor: VimEditor, context: ExecutionContext, selectionType: SelectionType): Boolean {
|
||||||
val editor = vimEditor.ij
|
val editor = vimEditor.ij
|
||||||
val c = getChar(editor)
|
val c = getChar(editor)
|
||||||
if (c.code == 0) return true
|
if (c.code == 0) return true
|
||||||
|
|
||||||
val pair = getOrInputPair(c, editor) ?: return false
|
val pair = getOrInputPair(c, editor) ?: return false
|
||||||
// XXX: Will it work with line-wise or block-wise selections?
|
|
||||||
val range = getSurroundRange(editor) ?: return false
|
|
||||||
runWriteAction {
|
runWriteAction {
|
||||||
val change = VimPlugin.getChange()
|
val change = VimPlugin.getChange()
|
||||||
val leftSurround = pair.first
|
if (supportsMultipleCursors) {
|
||||||
val primaryCaret = editor.caretModel.primaryCaret
|
editor.runWithEveryCaretAndRestore {
|
||||||
change.insertText(IjVimEditor(editor), IjVimCaret(primaryCaret), range.startOffset, leftSurround)
|
applyOnce(editor, change, pair)
|
||||||
change.insertText(IjVimEditor(editor), IjVimCaret(primaryCaret), range.endOffset + leftSurround.length, pair.second)
|
}
|
||||||
// Jump back to start
|
}
|
||||||
executeNormalWithoutMapping(injector.parser.parseKeys("`["), editor)
|
else {
|
||||||
|
applyOnce(editor, change, pair)
|
||||||
|
// Jump back to start
|
||||||
|
executeNormalWithoutMapping(injector.parser.parseKeys("`["), editor)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun applyOnce(editor: Editor, change: VimChangeGroup, pair: Pair<String, String>) {
|
||||||
|
// XXX: Will it work with line-wise or block-wise selections?
|
||||||
|
val range = getSurroundRange(editor)
|
||||||
|
if (range != null) {
|
||||||
|
val primaryCaret = editor.caretModel.primaryCaret
|
||||||
|
change.insertText(IjVimEditor(editor), IjVimCaret(primaryCaret), range.startOffset, pair.first)
|
||||||
|
change.insertText(
|
||||||
|
IjVimEditor(editor),
|
||||||
|
IjVimCaret(primaryCaret),
|
||||||
|
range.endOffset + pair.first.length,
|
||||||
|
pair.second
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun getSurroundRange(editor: Editor): TextRange? = when (editor.editorMode) {
|
private fun getSurroundRange(editor: Editor): TextRange? = when (editor.editorMode) {
|
||||||
VimStateMachine.Mode.COMMAND -> VimPlugin.getMark().getChangeMarks(editor.vim)
|
VimStateMachine.Mode.COMMAND -> VimPlugin.getMark().getChangeMarks(editor.vim)
|
||||||
VimStateMachine.Mode.VISUAL -> editor.caretModel.primaryCaret.run { TextRange(selectionStart, selectionEnd) }
|
VimStateMachine.Mode.VISUAL -> editor.caretModel.primaryCaret.run { TextRange(selectionStart, selectionEnd) }
|
||||||
|
@ -82,7 +82,7 @@ public class ProcessGroup extends VimProcessGroupBase {
|
|||||||
String initText = getRange(((IjVimEditor) editor).getEditor(), cmd);
|
String initText = getRange(((IjVimEditor) editor).getEditor(), cmd);
|
||||||
VimStateMachine.getInstance(editor).pushModes(VimStateMachine.Mode.CMD_LINE, VimStateMachine.SubMode.NONE);
|
VimStateMachine.getInstance(editor).pushModes(VimStateMachine.Mode.CMD_LINE, VimStateMachine.SubMode.NONE);
|
||||||
ExEntryPanel panel = ExEntryPanel.getInstance();
|
ExEntryPanel panel = ExEntryPanel.getInstance();
|
||||||
panel.activate(((IjVimEditor) editor).getEditor(), ((IjExecutionContext) context).getContext(), ":", initText, 1);
|
panel.activate(((IjVimEditor) editor).getEditor(), ((IjExecutionContext) context).getContext(), ":", initText, cmd.getCount());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -113,7 +113,7 @@ public class ProcessGroup extends VimProcessGroupBase {
|
|||||||
|
|
||||||
logger.debug("processing command");
|
logger.debug("processing command");
|
||||||
|
|
||||||
final String text = panel.getText();
|
String text = panel.getText();
|
||||||
|
|
||||||
if (!panel.getLabel().equals(":")) {
|
if (!panel.getLabel().equals(":")) {
|
||||||
// Search is handled via Argument.Type.EX_STRING. Although ProcessExEntryAction is registered as the handler for
|
// Search is handled via Argument.Type.EX_STRING. Although ProcessExEntryAction is registered as the handler for
|
||||||
@ -124,7 +124,15 @@ public class ProcessGroup extends VimProcessGroupBase {
|
|||||||
|
|
||||||
if (logger.isDebugEnabled()) logger.debug("swing=" + SwingUtilities.isEventDispatchThread());
|
if (logger.isDebugEnabled()) logger.debug("swing=" + SwingUtilities.isEventDispatchThread());
|
||||||
|
|
||||||
VimInjectorKt.getInjector().getVimscriptExecutor().execute(text, editor, context, skipHistory(editor), true, CommandLineVimLContext.INSTANCE);
|
int repeat = 1;
|
||||||
|
if (text.contains("raction ")) {
|
||||||
|
text = text.replace("raction ", "action ");
|
||||||
|
repeat = panel.getCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < repeat; i++) {
|
||||||
|
VimInjectorKt.getInjector().getVimscriptExecutor().execute(text, editor, context, skipHistory(editor), true, CommandLineVimLContext.INSTANCE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (ExException e) {
|
catch (ExException e) {
|
||||||
VimPlugin.showMessage(e.getMessage());
|
VimPlugin.showMessage(e.getMessage());
|
||||||
|
@ -17,6 +17,7 @@ import com.intellij.openapi.actionSystem.PlatformDataKeys
|
|||||||
import com.intellij.openapi.editor.Caret
|
import com.intellij.openapi.editor.Caret
|
||||||
import com.intellij.openapi.editor.RangeMarker
|
import com.intellij.openapi.editor.RangeMarker
|
||||||
import com.intellij.openapi.ide.CopyPasteManager
|
import com.intellij.openapi.ide.CopyPasteManager
|
||||||
|
import com.intellij.util.PlatformUtils
|
||||||
import com.maddyhome.idea.vim.VimPlugin
|
import com.maddyhome.idea.vim.VimPlugin
|
||||||
import com.maddyhome.idea.vim.api.ExecutionContext
|
import com.maddyhome.idea.vim.api.ExecutionContext
|
||||||
import com.maddyhome.idea.vim.api.VimCaret
|
import com.maddyhome.idea.vim.api.VimCaret
|
||||||
@ -146,6 +147,9 @@ class PutGroup : VimPutBase() {
|
|||||||
startOffset: Int,
|
startOffset: Int,
|
||||||
endOffset: Int,
|
endOffset: Int,
|
||||||
): Int {
|
): Int {
|
||||||
|
// Temp fix for VIM-2808. Should be removed after rider will fix it's issues
|
||||||
|
if (PlatformUtils.isRider()) return endOffset
|
||||||
|
|
||||||
val startLine = editor.offsetToBufferPosition(startOffset).line
|
val startLine = editor.offsetToBufferPosition(startOffset).line
|
||||||
val endLine = editor.offsetToBufferPosition(endOffset - 1).line
|
val endLine = editor.offsetToBufferPosition(endOffset - 1).line
|
||||||
val startLineOffset = (editor as IjVimEditor).editor.document.getLineStartOffset(startLine)
|
val startLineOffset = (editor as IjVimEditor).editor.document.getLineStartOffset(startLine)
|
||||||
|
@ -8,13 +8,17 @@
|
|||||||
|
|
||||||
package com.maddyhome.idea.vim.group.visual
|
package com.maddyhome.idea.vim.group.visual
|
||||||
|
|
||||||
|
import com.intellij.openapi.editor.Caret
|
||||||
import com.intellij.openapi.editor.Editor
|
import com.intellij.openapi.editor.Editor
|
||||||
import com.maddyhome.idea.vim.api.getLineEndForOffset
|
import com.maddyhome.idea.vim.api.getLineEndForOffset
|
||||||
import com.maddyhome.idea.vim.api.getLineStartForOffset
|
import com.maddyhome.idea.vim.api.getLineStartForOffset
|
||||||
import com.maddyhome.idea.vim.command.VimStateMachine
|
import com.maddyhome.idea.vim.command.VimStateMachine
|
||||||
|
import com.maddyhome.idea.vim.helper.inBlockSubMode
|
||||||
import com.maddyhome.idea.vim.helper.isEndAllowed
|
import com.maddyhome.idea.vim.helper.isEndAllowed
|
||||||
import com.maddyhome.idea.vim.helper.moveToInlayAwareOffset
|
import com.maddyhome.idea.vim.helper.moveToInlayAwareOffset
|
||||||
|
import com.maddyhome.idea.vim.helper.vimSelectionStart
|
||||||
import com.maddyhome.idea.vim.newapi.IjVimEditor
|
import com.maddyhome.idea.vim.newapi.IjVimEditor
|
||||||
|
import com.maddyhome.idea.vim.newapi.vim
|
||||||
|
|
||||||
fun moveCaretOneCharLeftFromSelectionEnd(editor: Editor, predictedMode: VimStateMachine.Mode) {
|
fun moveCaretOneCharLeftFromSelectionEnd(editor: Editor, predictedMode: VimStateMachine.Mode) {
|
||||||
if (predictedMode != VimStateMachine.Mode.VISUAL) {
|
if (predictedMode != VimStateMachine.Mode.VISUAL) {
|
||||||
@ -40,3 +44,10 @@ fun moveCaretOneCharLeftFromSelectionEnd(editor: Editor, predictedMode: VimState
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated("Use same method on VimCaret")
|
||||||
|
fun Caret.vimSetSelection(start: Int, end: Int = start, moveCaretToSelectionEnd: Boolean = false) {
|
||||||
|
vimSelectionStart = start
|
||||||
|
setVisualSelection(start, end, this.vim)
|
||||||
|
if (moveCaretToSelectionEnd && !editor.inBlockSubMode) moveToInlayAwareOffset(end)
|
||||||
|
}
|
||||||
|
@ -46,6 +46,12 @@ public class EditorHelper {
|
|||||||
return editor.getScrollingModel().getVisibleAreaOnScrollingFinished();
|
return editor.getScrollingModel().getVisibleAreaOnScrollingFinished();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//("Use extension function with the same name on VimEditor")
|
||||||
|
@Deprecated
|
||||||
|
public static boolean isLineEmpty(final @NotNull Editor editor, final int line, final boolean allowBlanks) {
|
||||||
|
return EngineEditorHelperKt.isLineEmpty(new IjVimEditor(editor), line, allowBlanks);
|
||||||
|
}
|
||||||
|
|
||||||
public static boolean scrollVertically(@NotNull Editor editor, int verticalOffset) {
|
public static boolean scrollVertically(@NotNull Editor editor, int verticalOffset) {
|
||||||
final ScrollingModel scrollingModel = editor.getScrollingModel();
|
final ScrollingModel scrollingModel = editor.getScrollingModel();
|
||||||
final Rectangle area = scrollingModel.getVisibleAreaOnScrollingFinished();
|
final Rectangle area = scrollingModel.getVisibleAreaOnScrollingFinished();
|
||||||
|
@ -12,6 +12,7 @@ package com.maddyhome.idea.vim.helper
|
|||||||
|
|
||||||
import com.intellij.codeWithMe.ClientId
|
import com.intellij.codeWithMe.ClientId
|
||||||
import com.intellij.openapi.editor.Caret
|
import com.intellij.openapi.editor.Caret
|
||||||
|
import com.intellij.openapi.editor.CaretState
|
||||||
import com.intellij.openapi.editor.Editor
|
import com.intellij.openapi.editor.Editor
|
||||||
import com.intellij.openapi.editor.ex.util.EditorUtil
|
import com.intellij.openapi.editor.ex.util.EditorUtil
|
||||||
import com.intellij.openapi.fileEditor.ex.FileEditorManagerEx
|
import com.intellij.openapi.fileEditor.ex.FileEditorManagerEx
|
||||||
@ -96,3 +97,41 @@ val Caret.vimLine: Int
|
|||||||
*/
|
*/
|
||||||
val Editor.vimLine: Int
|
val Editor.vimLine: Int
|
||||||
get() = this.caretModel.currentCaret.vimLine
|
get() = this.caretModel.currentCaret.vimLine
|
||||||
|
|
||||||
|
inline fun Editor.runWithEveryCaretAndRestore(action: () -> Unit) {
|
||||||
|
val caretModel = this.caretModel
|
||||||
|
val carets = if (this.inBlockSubMode) null else caretModel.allCarets
|
||||||
|
if (carets == null || carets.size == 1) {
|
||||||
|
action()
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
var initialDocumentSize = this.document.textLength
|
||||||
|
var documentSizeDifference = 0
|
||||||
|
|
||||||
|
val caretOffsets = carets.map { it.selectionStart to it.selectionEnd }
|
||||||
|
val restoredCarets = mutableListOf<CaretState>()
|
||||||
|
|
||||||
|
caretModel.removeSecondaryCarets()
|
||||||
|
|
||||||
|
for ((selectionStart, selectionEnd) in caretOffsets) {
|
||||||
|
if (selectionStart == selectionEnd) {
|
||||||
|
caretModel.primaryCaret.moveToOffset(selectionStart + documentSizeDifference)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
caretModel.primaryCaret.setSelection(
|
||||||
|
selectionStart + documentSizeDifference,
|
||||||
|
selectionEnd + documentSizeDifference
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
action()
|
||||||
|
restoredCarets.add(caretModel.caretsAndSelections.single())
|
||||||
|
|
||||||
|
val documentLength = this.document.textLength
|
||||||
|
documentSizeDifference += documentLength - initialDocumentSize
|
||||||
|
initialDocumentSize = documentLength
|
||||||
|
}
|
||||||
|
|
||||||
|
caretModel.caretsAndSelections = restoredCarets
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
package com.maddyhome.idea.vim.helper
|
package com.maddyhome.idea.vim.helper
|
||||||
|
|
||||||
|
import com.intellij.openapi.actionSystem.ex.ActionUtil
|
||||||
import com.intellij.openapi.editor.Editor
|
import com.intellij.openapi.editor.Editor
|
||||||
import com.intellij.openapi.editor.actionSystem.TypedAction
|
import com.intellij.openapi.editor.actionSystem.TypedAction
|
||||||
import com.intellij.openapi.editor.actionSystem.TypedActionHandler
|
import com.intellij.openapi.editor.actionSystem.TypedActionHandler
|
||||||
@ -49,7 +50,15 @@ class HandlerInjector {
|
|||||||
fun notebookCommandMode(editor: Editor?): Boolean {
|
fun notebookCommandMode(editor: Editor?): Boolean {
|
||||||
return if (editor != null) {
|
return if (editor != null) {
|
||||||
val inEditor = EditorHelper.getVirtualFile(editor)?.extension == "ipynb"
|
val inEditor = EditorHelper.getVirtualFile(editor)?.extension == "ipynb"
|
||||||
TypedAction.getInstance().rawHandler::class.java.simpleName.equals("JupyterCommandModeTypingBlocker") && inEditor
|
return if (TypedAction.getInstance().rawHandler::class.java.simpleName.equals("JupyterCommandModeTypingBlocker")) {
|
||||||
|
inEditor
|
||||||
|
} else {
|
||||||
|
// only true in command mode.
|
||||||
|
// Set by `org.jetbrains.plugins.notebooks.ui.editor.actions.command.mode.NotebookEditorModeListenerAdapter`
|
||||||
|
// appears to be null in non Notebook editors
|
||||||
|
val allow_plain_letter_shortcuts = editor.contentComponent.getClientProperty(ActionUtil.ALLOW_PlAIN_LETTER_SHORTCUTS)
|
||||||
|
inEditor && (allow_plain_letter_shortcuts != null && allow_plain_letter_shortcuts as Boolean)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
TypedAction.getInstance().rawHandler::class.java.simpleName.equals("JupyterCommandModeTypingBlocker")
|
TypedAction.getInstance().rawHandler::class.java.simpleName.equals("JupyterCommandModeTypingBlocker")
|
||||||
}
|
}
|
||||||
|
@ -15,9 +15,11 @@ import com.intellij.openapi.command.impl.UndoManagerImpl
|
|||||||
import com.intellij.openapi.command.undo.UndoManager
|
import com.intellij.openapi.command.undo.UndoManager
|
||||||
import com.intellij.openapi.components.Service
|
import com.intellij.openapi.components.Service
|
||||||
import com.intellij.openapi.fileEditor.impl.text.TextEditorProvider
|
import com.intellij.openapi.fileEditor.impl.text.TextEditorProvider
|
||||||
|
import com.maddyhome.idea.vim.VimPlugin
|
||||||
import com.maddyhome.idea.vim.api.ExecutionContext
|
import com.maddyhome.idea.vim.api.ExecutionContext
|
||||||
import com.maddyhome.idea.vim.api.VimEditor
|
import com.maddyhome.idea.vim.api.VimEditor
|
||||||
import com.maddyhome.idea.vim.api.injector
|
import com.maddyhome.idea.vim.api.injector
|
||||||
|
import com.maddyhome.idea.vim.command.VimStateMachine
|
||||||
import com.maddyhome.idea.vim.common.ChangesListener
|
import com.maddyhome.idea.vim.common.ChangesListener
|
||||||
import com.maddyhome.idea.vim.listener.SelectionVimListenerSuppressor
|
import com.maddyhome.idea.vim.listener.SelectionVimListenerSuppressor
|
||||||
import com.maddyhome.idea.vim.newapi.ij
|
import com.maddyhome.idea.vim.newapi.ij
|
||||||
@ -42,6 +44,7 @@ class UndoRedoHelper : UndoRedoBase() {
|
|||||||
if (undoManager.isUndoAvailable(fileEditor)) {
|
if (undoManager.isUndoAvailable(fileEditor)) {
|
||||||
if (injector.optionService.isSet(OptionScope.GLOBAL, IjVimOptionService.oldUndo)) {
|
if (injector.optionService.isSet(OptionScope.GLOBAL, IjVimOptionService.oldUndo)) {
|
||||||
SelectionVimListenerSuppressor.lock().use { undoManager.undo(fileEditor) }
|
SelectionVimListenerSuppressor.lock().use { undoManager.undo(fileEditor) }
|
||||||
|
restoreVisualMode(editor)
|
||||||
} else {
|
} else {
|
||||||
performUntilFileChanges(editor, { undoManager.isUndoAvailable(fileEditor) }, { undoManager.undo(fileEditor) })
|
performUntilFileChanges(editor, { undoManager.isUndoAvailable(fileEditor) }, { undoManager.undo(fileEditor) })
|
||||||
|
|
||||||
@ -71,6 +74,7 @@ class UndoRedoHelper : UndoRedoBase() {
|
|||||||
if (undoManager.isRedoAvailable(fileEditor)) {
|
if (undoManager.isRedoAvailable(fileEditor)) {
|
||||||
if (injector.optionService.isSet(OptionScope.GLOBAL, IjVimOptionService.oldUndo)) {
|
if (injector.optionService.isSet(OptionScope.GLOBAL, IjVimOptionService.oldUndo)) {
|
||||||
SelectionVimListenerSuppressor.lock().use { undoManager.redo(fileEditor) }
|
SelectionVimListenerSuppressor.lock().use { undoManager.redo(fileEditor) }
|
||||||
|
restoreVisualMode(editor)
|
||||||
} else {
|
} else {
|
||||||
performUntilFileChanges(editor, { undoManager.isRedoAvailable(fileEditor) }, { undoManager.redo(fileEditor) })
|
performUntilFileChanges(editor, { undoManager.isRedoAvailable(fileEditor) }, { undoManager.redo(fileEditor) })
|
||||||
CommandProcessor.getInstance().runUndoTransparentAction {
|
CommandProcessor.getInstance().runUndoTransparentAction {
|
||||||
@ -105,4 +109,21 @@ class UndoRedoHelper : UndoRedoBase() {
|
|||||||
private fun ifFilePathChanged(editor: VimEditor, oldPath: String?): Boolean {
|
private fun ifFilePathChanged(editor: VimEditor, oldPath: String?): Boolean {
|
||||||
return editor.getPath() != oldPath
|
return editor.getPath() != oldPath
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun restoreVisualMode(editor: VimEditor) {
|
||||||
|
if (!editor.mode.inVisualMode && editor.getSelectionModel().hasSelection()) {
|
||||||
|
val detectedMode = VimPlugin.getVisualMotion().autodetectVisualSubmode(editor)
|
||||||
|
|
||||||
|
// Visual block selection is restored into multiple carets, so multi-carets that form a block are always
|
||||||
|
// identified as visual block mode, leading to false positives.
|
||||||
|
// Since I use visual block mode much less often than multi-carets, this is a judgment call to never restore
|
||||||
|
// visual block mode.
|
||||||
|
val wantedMode = if (detectedMode == VimStateMachine.SubMode.VISUAL_BLOCK)
|
||||||
|
VimStateMachine.SubMode.VISUAL_CHARACTER
|
||||||
|
else
|
||||||
|
detectedMode
|
||||||
|
|
||||||
|
VimPlugin.getVisualMotion().enterVisualMode(editor, wantedMode)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,29 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2003-2022 The IdeaVim authors
|
|
||||||
*
|
|
||||||
* Use of this source code is governed by an MIT-style
|
|
||||||
* license that can be found in the LICENSE.txt file or at
|
|
||||||
* https://opensource.org/licenses/MIT.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.maddyhome.idea.vim.helper
|
|
||||||
|
|
||||||
import com.intellij.ide.plugins.StandalonePluginUpdateChecker
|
|
||||||
import com.intellij.openapi.components.Service
|
|
||||||
import com.intellij.openapi.components.service
|
|
||||||
import com.maddyhome.idea.vim.VimPlugin
|
|
||||||
import com.maddyhome.idea.vim.group.NotificationService
|
|
||||||
import com.maddyhome.idea.vim.icons.VimIcons
|
|
||||||
|
|
||||||
@Service(Service.Level.APP)
|
|
||||||
class VimStandalonePluginUpdateChecker : StandalonePluginUpdateChecker(
|
|
||||||
VimPlugin.getPluginId(),
|
|
||||||
updateTimestampProperty = PROPERTY_NAME,
|
|
||||||
NotificationService.IDEAVIM_STICKY_GROUP,
|
|
||||||
VimIcons.IDEAVIM,
|
|
||||||
) {
|
|
||||||
companion object {
|
|
||||||
private const val PROPERTY_NAME = "ideavim.statistics.timestamp"
|
|
||||||
val instance: VimStandalonePluginUpdateChecker = service()
|
|
||||||
}
|
|
||||||
}
|
|
@ -63,7 +63,9 @@ private var Caret._vimSelectionStart: Int? by userDataCaretToEditor()
|
|||||||
|
|
||||||
// Keep a track of the column that we intended to navigate to but were unable to. This might be because of inlays,
|
// Keep a track of the column that we intended to navigate to but were unable to. This might be because of inlays,
|
||||||
// virtual indent or moving from the end of a long line to the end of a short line. Keep a track of the position when
|
// virtual indent or moving from the end of a long line to the end of a short line. Keep a track of the position when
|
||||||
// the value is set, if it's not the same during get, we've been moved by IJ and so no longer valid
|
// the value is set, if it's not the same during get, we've been moved by IJ and so no longer valid. We also invalidate
|
||||||
|
// the cached value through a caret listener handler, to prevent issues with the caret being moved and returned before
|
||||||
|
// the cache is checked/invalidated
|
||||||
var Caret.vimLastColumn: Int
|
var Caret.vimLastColumn: Int
|
||||||
get() {
|
get() {
|
||||||
if (visualPosition != _vimLastColumnPos) {
|
if (visualPosition != _vimLastColumnPos) {
|
||||||
|
@ -52,7 +52,6 @@ import com.maddyhome.idea.vim.group.visual.VimVisualTimer
|
|||||||
import com.maddyhome.idea.vim.group.visual.moveCaretOneCharLeftFromSelectionEnd
|
import com.maddyhome.idea.vim.group.visual.moveCaretOneCharLeftFromSelectionEnd
|
||||||
import com.maddyhome.idea.vim.group.visual.vimSetSystemSelectionSilently
|
import com.maddyhome.idea.vim.group.visual.vimSetSystemSelectionSilently
|
||||||
import com.maddyhome.idea.vim.helper.GuicursorChangeListener
|
import com.maddyhome.idea.vim.helper.GuicursorChangeListener
|
||||||
import com.maddyhome.idea.vim.helper.VimStandalonePluginUpdateChecker
|
|
||||||
import com.maddyhome.idea.vim.helper.exitSelectMode
|
import com.maddyhome.idea.vim.helper.exitSelectMode
|
||||||
import com.maddyhome.idea.vim.helper.exitVisualMode
|
import com.maddyhome.idea.vim.helper.exitVisualMode
|
||||||
import com.maddyhome.idea.vim.helper.forceBarCursor
|
import com.maddyhome.idea.vim.helper.forceBarCursor
|
||||||
@ -62,6 +61,7 @@ import com.maddyhome.idea.vim.helper.isEndAllowed
|
|||||||
import com.maddyhome.idea.vim.helper.isIdeaVimDisabledHere
|
import com.maddyhome.idea.vim.helper.isIdeaVimDisabledHere
|
||||||
import com.maddyhome.idea.vim.helper.localEditors
|
import com.maddyhome.idea.vim.helper.localEditors
|
||||||
import com.maddyhome.idea.vim.helper.moveToInlayAwareOffset
|
import com.maddyhome.idea.vim.helper.moveToInlayAwareOffset
|
||||||
|
import com.maddyhome.idea.vim.helper.resetVimLastColumn
|
||||||
import com.maddyhome.idea.vim.helper.subMode
|
import com.maddyhome.idea.vim.helper.subMode
|
||||||
import com.maddyhome.idea.vim.helper.updateCaretsVisualAttributes
|
import com.maddyhome.idea.vim.helper.updateCaretsVisualAttributes
|
||||||
import com.maddyhome.idea.vim.helper.vimDisabled
|
import com.maddyhome.idea.vim.helper.vimDisabled
|
||||||
@ -157,6 +157,7 @@ object VimListenerManager {
|
|||||||
eventFacade.addEditorMouseMotionListener(editor, EditorMouseHandler, disposable)
|
eventFacade.addEditorMouseMotionListener(editor, EditorMouseHandler, disposable)
|
||||||
eventFacade.addEditorSelectionListener(editor, EditorSelectionHandler, disposable)
|
eventFacade.addEditorSelectionListener(editor, EditorSelectionHandler, disposable)
|
||||||
eventFacade.addComponentMouseListener(editor.contentComponent, ComponentMouseListener, disposable)
|
eventFacade.addComponentMouseListener(editor.contentComponent, ComponentMouseListener, disposable)
|
||||||
|
eventFacade.addCaretListener(editor, EditorCaretHandler, disposable)
|
||||||
|
|
||||||
VimPlugin.getEditor().editorCreated(editor)
|
VimPlugin.getEditor().editorCreated(editor)
|
||||||
|
|
||||||
@ -175,6 +176,7 @@ object VimListenerManager {
|
|||||||
eventFacade.removeEditorMouseMotionListener(editor, EditorMouseHandler)
|
eventFacade.removeEditorMouseMotionListener(editor, EditorMouseHandler)
|
||||||
eventFacade.removeEditorSelectionListener(editor, EditorSelectionHandler)
|
eventFacade.removeEditorSelectionListener(editor, EditorSelectionHandler)
|
||||||
eventFacade.removeComponentMouseListener(editor.contentComponent, ComponentMouseListener)
|
eventFacade.removeComponentMouseListener(editor.contentComponent, ComponentMouseListener)
|
||||||
|
eventFacade.removeCaretListener(editor, EditorCaretHandler)
|
||||||
|
|
||||||
VimPlugin.getEditorIfCreated()?.editorDeinit(editor, isReleased)
|
VimPlugin.getEditorIfCreated()?.editorDeinit(editor, isReleased)
|
||||||
|
|
||||||
@ -206,7 +208,6 @@ object VimListenerManager {
|
|||||||
private object VimEditorFactoryListener : EditorFactoryListener {
|
private object VimEditorFactoryListener : EditorFactoryListener {
|
||||||
override fun editorCreated(event: EditorFactoryEvent) {
|
override fun editorCreated(event: EditorFactoryEvent) {
|
||||||
add(event.editor)
|
add(event.editor)
|
||||||
VimStandalonePluginUpdateChecker.instance.pluginUsed()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun editorReleased(event: EditorFactoryEvent) {
|
override fun editorReleased(event: EditorFactoryEvent) {
|
||||||
@ -494,6 +495,12 @@ object VimListenerManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private object EditorCaretHandler : CaretListener {
|
||||||
|
override fun caretPositionChanged(event: CaretEvent) {
|
||||||
|
event.caret?.resetVimLastColumn()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
enum class SelectionSource {
|
enum class SelectionSource {
|
||||||
MOUSE,
|
MOUSE,
|
||||||
OTHER
|
OTHER
|
||||||
|
@ -11,12 +11,17 @@ package com.maddyhome.idea.vim.ui
|
|||||||
import com.intellij.icons.AllIcons
|
import com.intellij.icons.AllIcons
|
||||||
import com.intellij.ide.BrowserUtil
|
import com.intellij.ide.BrowserUtil
|
||||||
import com.intellij.ide.DataManager
|
import com.intellij.ide.DataManager
|
||||||
|
import com.intellij.ide.projectView.ProjectView
|
||||||
|
import com.intellij.ide.scratch.ScratchRootType
|
||||||
|
import com.intellij.ide.util.PsiNavigationSupport
|
||||||
import com.intellij.openapi.actionSystem.ActionManager
|
import com.intellij.openapi.actionSystem.ActionManager
|
||||||
import com.intellij.openapi.actionSystem.ActionPlaces
|
import com.intellij.openapi.actionSystem.ActionPlaces
|
||||||
import com.intellij.openapi.actionSystem.ActionUpdateThread
|
import com.intellij.openapi.actionSystem.ActionUpdateThread
|
||||||
import com.intellij.openapi.actionSystem.AnActionEvent
|
import com.intellij.openapi.actionSystem.AnActionEvent
|
||||||
import com.intellij.openapi.actionSystem.DataContext
|
import com.intellij.openapi.actionSystem.DataContext
|
||||||
import com.intellij.openapi.actionSystem.DefaultActionGroup
|
import com.intellij.openapi.actionSystem.DefaultActionGroup
|
||||||
|
import com.intellij.openapi.application.impl.LaterInvocator
|
||||||
|
import com.intellij.openapi.fileTypes.PlainTextLanguage
|
||||||
import com.intellij.openapi.options.ShowSettingsUtil
|
import com.intellij.openapi.options.ShowSettingsUtil
|
||||||
import com.intellij.openapi.project.DumbAwareAction
|
import com.intellij.openapi.project.DumbAwareAction
|
||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
@ -30,6 +35,7 @@ import com.intellij.openapi.wm.StatusBarWidget
|
|||||||
import com.intellij.openapi.wm.StatusBarWidgetFactory
|
import com.intellij.openapi.wm.StatusBarWidgetFactory
|
||||||
import com.intellij.openapi.wm.WindowManager
|
import com.intellij.openapi.wm.WindowManager
|
||||||
import com.intellij.openapi.wm.impl.status.widget.StatusBarWidgetsManager
|
import com.intellij.openapi.wm.impl.status.widget.StatusBarWidgetsManager
|
||||||
|
import com.intellij.psi.PsiManager
|
||||||
import com.intellij.ui.awt.RelativePoint
|
import com.intellij.ui.awt.RelativePoint
|
||||||
import com.intellij.util.Consumer
|
import com.intellij.util.Consumer
|
||||||
import com.intellij.util.ui.LafIconLookup
|
import com.intellij.util.ui.LafIconLookup
|
||||||
@ -193,6 +199,10 @@ private object VimActionsPopup {
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
actionGroup.addSeparator("Learn")
|
||||||
|
|
||||||
|
actionGroup.add(TutorAction())
|
||||||
|
|
||||||
actionGroup.addSeparator(MessageHelper.message("action.contacts.help.text"))
|
actionGroup.addSeparator(MessageHelper.message("action.contacts.help.text"))
|
||||||
actionGroup.add(
|
actionGroup.add(
|
||||||
HelpLink(
|
HelpLink(
|
||||||
@ -220,6 +230,22 @@ private object VimActionsPopup {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class TutorAction() : DumbAwareAction("Tutor") {
|
||||||
|
override fun actionPerformed(e: AnActionEvent) {
|
||||||
|
val project = e.project ?: return
|
||||||
|
val file = ScratchRootType.getInstance()
|
||||||
|
.createScratchFile(project, "Tutor.txt", PlainTextLanguage.INSTANCE, tutor) ?: return
|
||||||
|
|
||||||
|
PsiNavigationSupport.getInstance()
|
||||||
|
.createNavigatable(project, file, 0)
|
||||||
|
.navigate(!LaterInvocator.isInModalContextForProject(project))
|
||||||
|
|
||||||
|
PsiManager.getInstance(project).findFile(file)?.let {
|
||||||
|
ProjectView.getInstance(project).selectPsiElement(it, false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private class HelpLink(
|
private class HelpLink(
|
||||||
@NlsActions.ActionText name: String,
|
@NlsActions.ActionText name: String,
|
||||||
val link: String,
|
val link: String,
|
||||||
|
927
src/main/java/com/maddyhome/idea/vim/ui/Tutor.kt
Normal file
927
src/main/java/com/maddyhome/idea/vim/ui/Tutor.kt
Normal file
@ -0,0 +1,927 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2003-2022 The IdeaVim authors
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by an MIT-style
|
||||||
|
* license that can be found in the LICENSE.txt file or at
|
||||||
|
* https://opensource.org/licenses/MIT.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.maddyhome.idea.vim.ui
|
||||||
|
|
||||||
|
internal val tutor = """
|
||||||
|
===============================================================================
|
||||||
|
= Welcome to the IdeaVim Tutor =
|
||||||
|
===============================================================================
|
||||||
|
|
||||||
|
Based on the original VIM Tutor:
|
||||||
|
https://github.com/vim/vim/blob/master/runtime/tutor/tutor
|
||||||
|
|
||||||
|
Vim is a very powerful editor that has many commands, too many to
|
||||||
|
explain in a tutor such as this. This tutor is designed to describe
|
||||||
|
enough of the commands that you will be able to easily use Vim as
|
||||||
|
an all-purpose editor.
|
||||||
|
|
||||||
|
IdeaVim is a Vim engine for JetBrains IDEs, such as IntelliJ IDEA, PyCharm,
|
||||||
|
and more. It allows you to use Vim-style editing inside of a full-fledged IDE.
|
||||||
|
|
||||||
|
This tutorial doesn't cover a few things that are explained in Vim tutor,
|
||||||
|
but aren’t relevant to IdeaVim (for example, how to exit Vim). If you’re
|
||||||
|
still interested in them, see the last section.
|
||||||
|
|
||||||
|
The approximate time required to complete the tutor is 30 minutes,
|
||||||
|
depending upon how much time is spent with experimentation.
|
||||||
|
|
||||||
|
It is important to remember that this tutor is set up to teach by
|
||||||
|
use. That means that you need to execute the commands to learn them
|
||||||
|
properly. If you only read the text, you will forget the commands!
|
||||||
|
|
||||||
|
Now, make sure that your Caps-Lock key is NOT depressed and press
|
||||||
|
the j key enough times to move the cursor so that lesson 1.1
|
||||||
|
completely fills the screen.
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
Lesson 1.1: MOVING THE CURSOR
|
||||||
|
|
||||||
|
|
||||||
|
** To move the cursor, press the h,j,k,l keys as indicated. **
|
||||||
|
^
|
||||||
|
k Hint: The h key is at the left and moves left.
|
||||||
|
< h l > The l key is at the right and moves right.
|
||||||
|
j The j key looks like a down arrow.
|
||||||
|
v
|
||||||
|
1. Move the cursor around the screen until you are comfortable.
|
||||||
|
|
||||||
|
2. Hold down the down key (j) until it repeats.
|
||||||
|
Now you know how to move to the next lesson.
|
||||||
|
|
||||||
|
3. Using the down key, move to lesson 1.2.
|
||||||
|
|
||||||
|
NOTE: If you are ever unsure about something you typed, press <ESC> to place
|
||||||
|
you in Normal mode. Then retype the command you wanted.
|
||||||
|
|
||||||
|
NOTE: The cursor keys should also work. But using hjkl you will be able to
|
||||||
|
move around much faster, once you get used to it. Really!
|
||||||
|
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
Lesson 1.2: TEXT EDITING - DELETION
|
||||||
|
|
||||||
|
|
||||||
|
** Press x to delete the character under the cursor. **
|
||||||
|
|
||||||
|
1. Move the cursor to the line below marked --->.
|
||||||
|
|
||||||
|
2. To fix the errors, move the cursor until it is on top of the
|
||||||
|
character to be deleted.
|
||||||
|
|
||||||
|
3. Press the x key to delete the unwanted character.
|
||||||
|
|
||||||
|
4. Repeat steps 2 through 4 until the sentence is correct.
|
||||||
|
|
||||||
|
---> The ccow jumpedd ovverr thhe mooon.
|
||||||
|
|
||||||
|
5. Now that the line is correct, go on to lesson 1.4.
|
||||||
|
|
||||||
|
NOTE: As you go through this tutor, do not try to memorize, learn by usage.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
Lesson 1.3: TEXT EDITING - INSERTION
|
||||||
|
|
||||||
|
|
||||||
|
** Press i to insert text. **
|
||||||
|
|
||||||
|
1. Move the cursor to the first line below marked --->.
|
||||||
|
|
||||||
|
2. To make the first line the same as the second, move the cursor on top
|
||||||
|
of the character BEFORE which the text is to be inserted.
|
||||||
|
|
||||||
|
3. Press i and type in the necessary additions.
|
||||||
|
|
||||||
|
4. As each error is fixed press <ESC> to return to Normal mode.
|
||||||
|
Repeat steps 2 through 4 to correct the sentence.
|
||||||
|
|
||||||
|
---> There is text misng this .
|
||||||
|
---> There is some text missing from this line.
|
||||||
|
|
||||||
|
5. When you are comfortable inserting text move to lesson 1.5.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
Lesson 1.4: TEXT EDITING - APPENDING
|
||||||
|
|
||||||
|
|
||||||
|
** Press A to append text. **
|
||||||
|
|
||||||
|
1. Move the cursor to the first line below marked --->.
|
||||||
|
It does not matter on what character the cursor is in that line.
|
||||||
|
|
||||||
|
2. Press A and type in the necessary additions.
|
||||||
|
|
||||||
|
3. As the text has been appended press <ESC> to return to Normal mode.
|
||||||
|
|
||||||
|
4. Move the cursor to the second line marked ---> and repeat
|
||||||
|
steps 2 and 3 to correct this sentence.
|
||||||
|
|
||||||
|
---> There is some text missing from th
|
||||||
|
There is some text missing from this line.
|
||||||
|
---> There is also some text miss
|
||||||
|
There is also some text missing here.
|
||||||
|
|
||||||
|
5. When you are comfortable appending text move to lesson 1.6.
|
||||||
|
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Lesson 1 SUMMARY
|
||||||
|
|
||||||
|
|
||||||
|
1. The cursor is moved using either the arrow keys or the hjkl keys.
|
||||||
|
h (left) j (down) k (up) l (right)
|
||||||
|
|
||||||
|
2. To delete the character at the cursor type: x
|
||||||
|
|
||||||
|
3. To insert or append text type:
|
||||||
|
i type inserted text <ESC> insert before the cursor
|
||||||
|
A type appended text <ESC> append after the line
|
||||||
|
|
||||||
|
NOTE: Pressing <ESC> will place you in Normal mode or will cancel
|
||||||
|
an unwanted and partially completed command.
|
||||||
|
|
||||||
|
Now continue with lesson 2.
|
||||||
|
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
Lesson 2.1: DELETION COMMANDS
|
||||||
|
|
||||||
|
|
||||||
|
** Type dw to delete a word. **
|
||||||
|
|
||||||
|
1. Press <ESC> to make sure you are in Normal mode.
|
||||||
|
|
||||||
|
2. Move the cursor to the line below marked --->.
|
||||||
|
|
||||||
|
3. Move the cursor to the beginning of a word that needs to be deleted.
|
||||||
|
|
||||||
|
4. Type dw to make the word disappear.
|
||||||
|
|
||||||
|
NOTE: The letter d will appear in the status bar as you type it.
|
||||||
|
Vim is waiting for you to type w . If you see another character
|
||||||
|
than d you typed something wrong; press <ESC> and start over.
|
||||||
|
|
||||||
|
---> There are a some words fun that don't belong paper in this sentence.
|
||||||
|
|
||||||
|
5. Repeat steps 3 and 4 until the sentence is correct and go to lesson 2.2.
|
||||||
|
|
||||||
|
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
Lesson 2.2: MORE DELETION COMMANDS
|
||||||
|
|
||||||
|
|
||||||
|
** Type d${'$'} to delete to the end of the line. **
|
||||||
|
|
||||||
|
1. Press <ESC> to make sure you are in Normal mode.
|
||||||
|
|
||||||
|
2. Move the cursor to the line below marked --->.
|
||||||
|
|
||||||
|
3. Move the cursor to the end of the correct line (AFTER the first . ).
|
||||||
|
|
||||||
|
4. Type d${'$'} to delete to the end of the line.
|
||||||
|
|
||||||
|
---> Somebody typed the end of this line twice. end of this line twice.
|
||||||
|
|
||||||
|
|
||||||
|
5. Move on to lesson 2.3 to understand what is happening.
|
||||||
|
|
||||||
|
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
Lesson 2.3: ON OPERATORS AND MOTIONS
|
||||||
|
|
||||||
|
|
||||||
|
Many commands that change text are made from an operator and a motion.
|
||||||
|
The format for a delete command with the d delete operator is as follows:
|
||||||
|
|
||||||
|
d motion
|
||||||
|
|
||||||
|
Where:
|
||||||
|
d - is the delete operator.
|
||||||
|
motion - is what the operator will operate on (listed below).
|
||||||
|
|
||||||
|
A short list of motions:
|
||||||
|
w - until the start of the next word, EXCLUDING its first character.
|
||||||
|
e - to the end of the current word, INCLUDING the last character.
|
||||||
|
${'$'} - to the end of the line, INCLUDING the last character.
|
||||||
|
|
||||||
|
Thus typing de will delete from the cursor to the end of the word.
|
||||||
|
|
||||||
|
NOTE: Pressing just the motion while in Normal mode without an operator will
|
||||||
|
move the cursor as specified.
|
||||||
|
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
Lesson 2.4: USING A COUNT FOR A MOTION
|
||||||
|
|
||||||
|
|
||||||
|
** Typing a number before a motion repeats it that many times. **
|
||||||
|
|
||||||
|
1. Move the cursor to the start of the line below marked --->.
|
||||||
|
|
||||||
|
2. Type 2w to move the cursor two words forward.
|
||||||
|
|
||||||
|
3. Type 3e to move the cursor to the end of the third word forward.
|
||||||
|
|
||||||
|
4. Type 0 (zero) to move to the start of the line.
|
||||||
|
|
||||||
|
5. Repeat steps 2 and 3 with different numbers.
|
||||||
|
|
||||||
|
---> This is just a line with words you can move around in.
|
||||||
|
|
||||||
|
6. Move on to lesson 2.5.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
Lesson 2.5: USING A COUNT TO DELETE MORE
|
||||||
|
|
||||||
|
|
||||||
|
** Typing a number with an operator repeats it that many times. **
|
||||||
|
|
||||||
|
In the combination of the delete operator and a motion mentioned above you
|
||||||
|
insert a count before the motion to delete more:
|
||||||
|
d number motion
|
||||||
|
|
||||||
|
1. Move the cursor to the first UPPER CASE word in the line marked --->.
|
||||||
|
|
||||||
|
2. Type d2w to delete the two UPPER CASE words.
|
||||||
|
|
||||||
|
3. Repeat steps 1 and 2 with a different count to delete the consecutive
|
||||||
|
UPPER CASE words with one command.
|
||||||
|
|
||||||
|
---> this ABC DE line FGHI JK LMN OP of words is Q RS TUV cleaned up.
|
||||||
|
|
||||||
|
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
Lesson 2.6: OPERATING ON LINES
|
||||||
|
|
||||||
|
|
||||||
|
** Type dd to delete a whole line. **
|
||||||
|
|
||||||
|
Due to the frequency of whole line deletion, the designers of Vi decided
|
||||||
|
it would be easier to simply type two d's to delete a line.
|
||||||
|
|
||||||
|
1. Move the cursor to the second line in the phrase below.
|
||||||
|
2. Type dd to delete the line.
|
||||||
|
3. Now move to the fourth line.
|
||||||
|
4. Type 2dd to delete two lines.
|
||||||
|
|
||||||
|
---> 1) Roses are red,
|
||||||
|
---> 2) Mud is fun,
|
||||||
|
---> 3) Violets are blue,
|
||||||
|
---> 4) I have a car,
|
||||||
|
---> 5) Clocks tell time,
|
||||||
|
---> 6) Sugar is sweet
|
||||||
|
---> 7) And so are you.
|
||||||
|
|
||||||
|
Doubling to operate on a line also works for operators mentioned below.
|
||||||
|
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
Lesson 2.7: THE UNDO COMMAND
|
||||||
|
|
||||||
|
|
||||||
|
** Press u to undo the last commands. **
|
||||||
|
|
||||||
|
1. Move the cursor to the line below marked ---> and place it on the
|
||||||
|
first error.
|
||||||
|
2. Type x to delete the first unwanted character.
|
||||||
|
3. Now type u to undo the last command executed.
|
||||||
|
4. This time fix all the errors on the line using the x command.
|
||||||
|
6. Now type u a few times to undo the preceding commands.
|
||||||
|
7. Now type CTRL-R (keeping CTRL key pressed while hitting R) a few times
|
||||||
|
to redo the commands.
|
||||||
|
|
||||||
|
---> Fiix the errors oon thhis line and reeplace them witth undo.
|
||||||
|
|
||||||
|
8. These are very useful commands. Now move on to the lesson 2 Summary.
|
||||||
|
|
||||||
|
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
Lesson 2 SUMMARY
|
||||||
|
|
||||||
|
1. To delete from the cursor up to the next word type: dw
|
||||||
|
2. To delete from the cursor up to the end of the word type: de
|
||||||
|
3. To delete from the cursor to the end of a line type: d${'$'}
|
||||||
|
4. To delete a whole line type: dd
|
||||||
|
|
||||||
|
5. To repeat a motion prepend it with a number: 2w
|
||||||
|
6. The format for a change command is:
|
||||||
|
operator [number] motion
|
||||||
|
where:
|
||||||
|
operator - is what to do, such as d for delete
|
||||||
|
[number] - is an optional count to repeat the motion
|
||||||
|
motion - moves over the text to operate on, such as w (word),
|
||||||
|
e (end of word), ${'$'} (end of the line), etc.
|
||||||
|
|
||||||
|
7. To move to the start of the line use a zero: 0
|
||||||
|
|
||||||
|
8. To undo previous actions, type: u (lowercase u)
|
||||||
|
To undo the undo's, type: CTRL-R
|
||||||
|
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
Lesson 3.1: THE PUT COMMAND
|
||||||
|
|
||||||
|
|
||||||
|
** Type p to put previously deleted text after the cursor. **
|
||||||
|
|
||||||
|
1. Move the cursor to the first line below marked --->.
|
||||||
|
|
||||||
|
2. Type dd to delete the line and store it in a Vim register.
|
||||||
|
|
||||||
|
3. Move the cursor to the c) line, ABOVE where the deleted line should go.
|
||||||
|
|
||||||
|
4. Type p to put the line below the cursor.
|
||||||
|
|
||||||
|
5. Repeat steps 2 through 4 to put all the lines in correct order.
|
||||||
|
|
||||||
|
---> d) Can you learn too?
|
||||||
|
---> b) Violets are blue,
|
||||||
|
---> c) Intelligence is learned,
|
||||||
|
---> a) Roses are red,
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
Lesson 3.2: THE REPLACE COMMAND
|
||||||
|
|
||||||
|
|
||||||
|
** Type rx to replace the character at the cursor with x . **
|
||||||
|
|
||||||
|
1. Move the cursor to the first line below marked --->.
|
||||||
|
|
||||||
|
2. Move the cursor so that it is on top of the first error.
|
||||||
|
|
||||||
|
3. Type r and then the character which should be there.
|
||||||
|
|
||||||
|
4. Repeat steps 2 and 3 until the first line is equal to the second one.
|
||||||
|
|
||||||
|
---> Whan this lime was tuoed in, someone presswd some wrojg keys!
|
||||||
|
---> When this line was typed in, someone pressed some wrong keys!
|
||||||
|
|
||||||
|
5. Now move on to lesson 3.3.
|
||||||
|
|
||||||
|
NOTE: Remember that you should be learning by doing, not memorization.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
Lesson 3.3: THE CHANGE OPERATOR
|
||||||
|
|
||||||
|
|
||||||
|
** To change until the end of a word, type ce . **
|
||||||
|
|
||||||
|
1. Move the cursor to the first line below marked --->.
|
||||||
|
|
||||||
|
2. Place the cursor on the u in lubw.
|
||||||
|
|
||||||
|
3. Type ce and the correct word (in this case, type ine ).
|
||||||
|
|
||||||
|
4. Press <ESC> and move to the next character that needs to be changed.
|
||||||
|
|
||||||
|
5. Repeat steps 3 and 4 until the first sentence is the same as the second.
|
||||||
|
|
||||||
|
---> This lubw has a few wptfd that mrrf changing usf the change operator.
|
||||||
|
---> This line has a few words that need changing using the change operator.
|
||||||
|
|
||||||
|
Notice that ce deletes the word and places you in Insert mode.
|
||||||
|
cc does the same for the whole line.
|
||||||
|
|
||||||
|
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
Lesson 3.4: MORE CHANGES USING c
|
||||||
|
|
||||||
|
|
||||||
|
** The change operator is used with the same motions as delete. **
|
||||||
|
|
||||||
|
1. The change operator works in the same way as delete. The format is:
|
||||||
|
|
||||||
|
c [number] motion
|
||||||
|
|
||||||
|
2. The motions are the same, such as w (word) and ${'$'} (end of line).
|
||||||
|
|
||||||
|
3. Move the cursor to the first line below marked --->.
|
||||||
|
|
||||||
|
4. Move the cursor to the first error.
|
||||||
|
|
||||||
|
5. Type c${'$'} and type the rest of the line like the second and press <ESC>.
|
||||||
|
|
||||||
|
---> The end of this line needs some help to make it like the second.
|
||||||
|
---> The end of this line needs to be corrected using the c${'$'} command.
|
||||||
|
|
||||||
|
NOTE: You can use the Backspace key to correct mistakes while typing.
|
||||||
|
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
Lesson 3 SUMMARY
|
||||||
|
|
||||||
|
|
||||||
|
1. To put back text that has just been deleted, type p . This puts the
|
||||||
|
deleted text AFTER the cursor (if a line was deleted it will go on the
|
||||||
|
line below the cursor).
|
||||||
|
|
||||||
|
2. To replace the character under the cursor, type r and then the
|
||||||
|
character you want to have there.
|
||||||
|
|
||||||
|
3. The change operator allows you to change from the cursor to where the
|
||||||
|
motion takes you. eg. Type ce to change from the cursor to the end of
|
||||||
|
the word, c${'$'} to change to the end of a line.
|
||||||
|
|
||||||
|
4. The format for change is:
|
||||||
|
|
||||||
|
c [number] motion
|
||||||
|
|
||||||
|
Now go on to the next lesson.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
Lesson 4.1: CURSOR LOCATION AND FILE STATUS
|
||||||
|
|
||||||
|
** Type G to move to a line in the file. **
|
||||||
|
|
||||||
|
NOTE: Read this entire lesson before executing any of the steps!!
|
||||||
|
|
||||||
|
1. Remember the line number for Step 3.
|
||||||
|
|
||||||
|
2. Press G to move you to the bottom of the file.
|
||||||
|
Type gg to move you to the start of the file.
|
||||||
|
|
||||||
|
3. Type the number of the line you were on and then G . This will
|
||||||
|
return you to the line you were on before pressing G.
|
||||||
|
|
||||||
|
4. If you feel confident to do this, execute steps 1 through 3.
|
||||||
|
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
Lesson 4.2: THE SEARCH COMMAND
|
||||||
|
|
||||||
|
|
||||||
|
** Type / followed by a phrase to search for the phrase. **
|
||||||
|
|
||||||
|
1. In Normal mode type the / character. Notice that it and the cursor
|
||||||
|
appear at the bottom of the screen as with the : command.
|
||||||
|
|
||||||
|
2. Now type 'errroor' <ENTER>. This is the word you want to search for.
|
||||||
|
|
||||||
|
3. To search for the same phrase again, simply type n .
|
||||||
|
To search for the same phrase in the opposite direction, type N .
|
||||||
|
|
||||||
|
4. To search for a phrase in the backward direction, use ? instead of / .
|
||||||
|
|
||||||
|
---> "errroor" is not the way to spell error; errroor is an error.
|
||||||
|
NOTE: When the search reaches the end of the file it will continue at the
|
||||||
|
start, unless the 'wrapscan' option has been reset.
|
||||||
|
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
Lesson 4.3: MATCHING PARENTHESES SEARCH
|
||||||
|
|
||||||
|
|
||||||
|
** Type % to find a matching ),], or } . **
|
||||||
|
|
||||||
|
1. Place the cursor on any (, [, or { in the line below marked --->.
|
||||||
|
|
||||||
|
2. Now type the % character.
|
||||||
|
|
||||||
|
3. The cursor will move to the matching parenthesis or bracket.
|
||||||
|
|
||||||
|
4. Type % to move the cursor to the other matching bracket.
|
||||||
|
|
||||||
|
5. Move the cursor to another (,),[,],{ or } and see what % does.
|
||||||
|
|
||||||
|
---> This ( is a test line with ('s, ['s ] and {'s } in it. ))
|
||||||
|
|
||||||
|
|
||||||
|
NOTE: This is very useful in debugging a program with unmatched parentheses!
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
Lesson 4.4: THE SUBSTITUTE COMMAND
|
||||||
|
|
||||||
|
|
||||||
|
** Type :s/old/new/g to substitute 'new' for 'old'. **
|
||||||
|
|
||||||
|
1. Move the cursor to the line below marked --->.
|
||||||
|
|
||||||
|
2. Type :s/thee/the <ENTER> . Note that this command only changes the
|
||||||
|
first occurrence of "thee" in the line.
|
||||||
|
|
||||||
|
3. Now type :s/thee/the/g . Adding the g flag means to substitute
|
||||||
|
globally in the line, change all occurrences of "thee" in the line.
|
||||||
|
|
||||||
|
---> thee best time to see thee flowers is in thee spring.
|
||||||
|
|
||||||
|
4. To change every occurrence of a character string between two lines,
|
||||||
|
type :#,#s/old/new/g where #,# are the line numbers of the range
|
||||||
|
of lines where the substitution is to be done.
|
||||||
|
Type :%s/old/new/g to change every occurrence in the whole file.
|
||||||
|
Type :%s/old/new/gc to find every occurrence in the whole file,
|
||||||
|
with a prompt whether to substitute or not.
|
||||||
|
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
Lesson 4 SUMMARY
|
||||||
|
|
||||||
|
|
||||||
|
1. G moves to the end of the file.
|
||||||
|
number G moves to that line number.
|
||||||
|
gg moves to the first line.
|
||||||
|
|
||||||
|
2. Typing / followed by a phrase searches FORWARD for the phrase.
|
||||||
|
Typing ? followed by a phrase searches BACKWARD for the phrase.
|
||||||
|
After a search type n to find the next occurrence in the same direction
|
||||||
|
or N to search in the opposite direction.
|
||||||
|
|
||||||
|
3. Typing % while the cursor is on a (,),[,],{, or } goes to its match.
|
||||||
|
|
||||||
|
4. To substitute new for the first old in a line type :s/old/new
|
||||||
|
To substitute new for all 'old's on a line type :s/old/new/g
|
||||||
|
To substitute phrases between two line #'s type :#,#s/old/new/g
|
||||||
|
To substitute all occurrences in the file type :%s/old/new/g
|
||||||
|
To ask for confirmation each time add 'c' :%s/old/new/gc
|
||||||
|
|
||||||
|
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
Lesson 5.1: THE OPEN COMMAND
|
||||||
|
|
||||||
|
|
||||||
|
** Type o to open a line below the cursor and place you in Insert mode. **
|
||||||
|
|
||||||
|
1. Move the cursor to the first line below marked --->.
|
||||||
|
|
||||||
|
2. Type the lowercase letter o to open up a line BELOW the cursor and place
|
||||||
|
you in Insert mode.
|
||||||
|
|
||||||
|
3. Now type some text and press <ESC> to exit Insert mode.
|
||||||
|
|
||||||
|
---> After typing o the cursor is placed on the open line in Insert mode.
|
||||||
|
|
||||||
|
4. To open up a line ABOVE the cursor, simply type a capital O , rather
|
||||||
|
than a lowercase o. Try this on the line below.
|
||||||
|
|
||||||
|
---> Open up a line above this by typing O while the cursor is on this line.
|
||||||
|
|
||||||
|
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
Lesson 5.2: THE APPEND COMMAND
|
||||||
|
|
||||||
|
|
||||||
|
** Type a to insert text AFTER the cursor. **
|
||||||
|
|
||||||
|
1. Move the cursor to the start of the first line below marked --->.
|
||||||
|
|
||||||
|
2. Press e until the cursor is on the end of li .
|
||||||
|
|
||||||
|
3. Type an a (lowercase) to append text AFTER the cursor.
|
||||||
|
|
||||||
|
4. Complete the word like the line below it. Press <ESC> to exit Insert
|
||||||
|
mode.
|
||||||
|
|
||||||
|
5. Use e to move to the next incomplete word and repeat steps 3 and 4.
|
||||||
|
|
||||||
|
---> This li will allow you to pract appendi text to a line.
|
||||||
|
---> This line will allow you to practice appending text to a line.
|
||||||
|
|
||||||
|
NOTE: a, i and A all go to the same Insert mode, the only difference is where
|
||||||
|
the characters are inserted.
|
||||||
|
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
Lesson 5.3: ANOTHER WAY TO REPLACE
|
||||||
|
|
||||||
|
|
||||||
|
** Type a capital R to replace more than one character. **
|
||||||
|
|
||||||
|
1. Move the cursor to the first line below marked --->. Move the cursor to
|
||||||
|
the beginning of the first xxx .
|
||||||
|
|
||||||
|
2. Now press R and type the number below it in the second line, so that it
|
||||||
|
replaces the xxx .
|
||||||
|
|
||||||
|
3. Press <ESC> to leave Replace mode. Notice that the rest of the line
|
||||||
|
remains unmodified.
|
||||||
|
|
||||||
|
4. Repeat the steps to replace the remaining xxx.
|
||||||
|
|
||||||
|
---> Adding 123 to xxx gives you xxx.
|
||||||
|
---> Adding 123 to 456 gives you 579.
|
||||||
|
|
||||||
|
NOTE: Replace mode is like Insert mode, but every typed character deletes an
|
||||||
|
existing character.
|
||||||
|
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
Lesson 5.4: COPY AND PASTE TEXT
|
||||||
|
|
||||||
|
|
||||||
|
** Use the y operator to copy text and p to paste it **
|
||||||
|
|
||||||
|
1. Move to the line below marked ---> and place the cursor after "a)".
|
||||||
|
|
||||||
|
2. Start Visual mode with v and move the cursor to just before "first".
|
||||||
|
|
||||||
|
3. Type y to yank (copy) the highlighted text.
|
||||||
|
|
||||||
|
4. Move the cursor to the end of the next line: j${'$'}
|
||||||
|
|
||||||
|
5. Type p to put (paste) the text. Then type: a second <ESC> .
|
||||||
|
|
||||||
|
6. Use Visual mode to select " item.", yank it with y , move to the end of
|
||||||
|
the next line with j${'$'} and put the text there with p .
|
||||||
|
|
||||||
|
---> a) this is the first item.
|
||||||
|
b)
|
||||||
|
|
||||||
|
NOTE: You can also use y as an operator: yw yanks one word,
|
||||||
|
yy yanks the whole line, then p puts that line.
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
Lesson 5.5: SET OPTION
|
||||||
|
|
||||||
|
|
||||||
|
** Set an option so a search or substitute ignores case **
|
||||||
|
|
||||||
|
1. Search for 'ignore' by entering: /ignore <ENTER>
|
||||||
|
Repeat several times by pressing n .
|
||||||
|
|
||||||
|
2. Set the 'ic' (Ignore case) option by entering: :set ic
|
||||||
|
|
||||||
|
3. Now search for 'ignore' again by pressing n
|
||||||
|
Notice that Ignore and IGNORE are now also found.
|
||||||
|
|
||||||
|
4. Set the 'hlsearch' and 'incsearch' options: :set hls is
|
||||||
|
|
||||||
|
5. Now type the search command again and see what happens: /ignore <ENTER>
|
||||||
|
|
||||||
|
6. To disable ignoring case enter: :set noic
|
||||||
|
|
||||||
|
NOTE: To remove the highlighting of matches enter: :nohlsearch
|
||||||
|
NOTE: If you want to ignore case for just one search command, use \c
|
||||||
|
in the phrase: /ignore\c <ENTER>
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
Lesson 5 SUMMARY
|
||||||
|
|
||||||
|
1. Type o to open a line BELOW the cursor and start Insert mode.
|
||||||
|
Type O to open a line ABOVE the cursor.
|
||||||
|
|
||||||
|
2. Type a to insert text AFTER the cursor.
|
||||||
|
Type A to insert text after the end of the line.
|
||||||
|
|
||||||
|
3. The e command moves to the end of a word.
|
||||||
|
|
||||||
|
4. The y operator yanks (copies) text, p puts (pastes) it.
|
||||||
|
|
||||||
|
5. Typing a capital R enters Replace mode until <ESC> is pressed.
|
||||||
|
|
||||||
|
6. Typing ":set xxx" sets the option "xxx". Some options are:
|
||||||
|
'ic' 'ignorecase' ignore upper/lower case when searching
|
||||||
|
'is' 'incsearch' show partial matches for a search phrase
|
||||||
|
'hls' 'hlsearch' highlight all matching phrases
|
||||||
|
You can either use the long or the short option name.
|
||||||
|
|
||||||
|
7. Prepend "no" to switch an option off: :set noic
|
||||||
|
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Lesson 6.1: CREATE A STARTUP SCRIPT
|
||||||
|
|
||||||
|
|
||||||
|
** Enable IdeaVim features **
|
||||||
|
|
||||||
|
IdeaVim and Vim have many more features than Vi, but most of them are disabled
|
||||||
|
by default. To start using more features, first create an "ideavimrc" file.
|
||||||
|
For Vim it’s a "vimrc" file.
|
||||||
|
|
||||||
|
To do so, click the IdeaVim status bar icon
|
||||||
|
(the green V letter) and click "Create ~/.ideavimrc". This will create a
|
||||||
|
".ideavimrc" file in your home directory.
|
||||||
|
|
||||||
|
Add the following lines to the file:
|
||||||
|
|
||||||
|
Plug 'machakann/vim-highlightedyank'
|
||||||
|
set incsearch
|
||||||
|
|
||||||
|
Click on the reload icon in the upper-right corner of the editor.
|
||||||
|
|
||||||
|
With these commands, you've enable the "highlightedyank" plugin and incremental
|
||||||
|
search. The "highlightedyank" plugin highlights the text that was yanked.
|
||||||
|
The incremental search feature shows search matches as you type the query.
|
||||||
|
|
||||||
|
You can find more plugins by clicking “Status bar icon | Plugins…”.
|
||||||
|
|
||||||
|
You can add all of your preferred settings to this "ideavimrc" file.
|
||||||
|
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
Lesson 6 SUMMARY
|
||||||
|
|
||||||
|
|
||||||
|
1. Create an ideavimrc startup script to keep your preferred settings.
|
||||||
|
|
||||||
|
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
This concludes the IdeaVim Tutor. It was intended to give a brief overview of
|
||||||
|
the IdeaVim plugin, just enough to allow you to use the editor fairly easily.
|
||||||
|
It is far from complete as IdeaVim and Vim have many many more commands.
|
||||||
|
|
||||||
|
For further reading and studying, this book is recommended:
|
||||||
|
Vim - Vi Improved - by Steve Oualline
|
||||||
|
Publisher: New Riders
|
||||||
|
The first book completely dedicated to Vim. Especially useful for beginners.
|
||||||
|
There are many examples and pictures.
|
||||||
|
See https://iccf-holland.org/click5.html
|
||||||
|
|
||||||
|
This book is older and more about Vi than Vim, but also recommended:
|
||||||
|
Learning the Vi Editor - by Linda Lamb
|
||||||
|
Publisher: O'Reilly & Associates Inc.
|
||||||
|
It is a good book to get to know almost anything you want to do with Vi.
|
||||||
|
The sixth edition also includes information on Vim.
|
||||||
|
|
||||||
|
This tutorial was written by Michael C. Pierce and Robert K. Ware,
|
||||||
|
Colorado School of Mines using ideas supplied by Charles Smith,
|
||||||
|
Colorado State University. E-mail: bware@mines.colorado.edu.
|
||||||
|
|
||||||
|
To learn more about IdeaVim, visit the official GitHub repository:
|
||||||
|
https://github.com/JetBrains/ideavim
|
||||||
|
|
||||||
|
Modified for Vim by Bram Moolenaar.
|
||||||
|
|
||||||
|
Modified for IdeaVim by Alex Plate.
|
||||||
|
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
We removed the Vim Tutor sections that are related to the Vim editor,
|
||||||
|
but not really applicable to the IdeaVim plugin.
|
||||||
|
We recommend running these steps in an actual Vim editor.
|
||||||
|
|
||||||
|
Lesson 1.2: EXITING VIM
|
||||||
|
|
||||||
|
!! NOTE: Before executing any of the steps below, read this entire lesson!!
|
||||||
|
|
||||||
|
1. Press the <ESC> key (to make sure you are in Normal mode).
|
||||||
|
|
||||||
|
2. Type: :q! <ENTER>.
|
||||||
|
This exits the editor, DISCARDING any changes you have made.
|
||||||
|
|
||||||
|
3. Get back here by executing the command that got you into this tutor. That
|
||||||
|
might be: vimtutor <ENTER>
|
||||||
|
|
||||||
|
4. If you have these steps memorized and are confident, execute steps
|
||||||
|
1 through 3 to exit and re-enter the editor.
|
||||||
|
|
||||||
|
NOTE: :q! <ENTER> discards any changes you made. In a few lessons you
|
||||||
|
will learn how to save the changes to a file.
|
||||||
|
|
||||||
|
|
||||||
|
Lesson 1.6: EDITING A FILE
|
||||||
|
|
||||||
|
** Use :wq to save a file and exit. **
|
||||||
|
|
||||||
|
!! NOTE: Before executing any of the steps below, read this entire lesson!!
|
||||||
|
|
||||||
|
1. If you have access to another terminal, do the following there.
|
||||||
|
Otherwise, exit this tutor as you did in lesson 1.2: :q!
|
||||||
|
|
||||||
|
2. At the shell prompt type this command: vim file.txt <ENTER>
|
||||||
|
'vim' is the command to start the Vim editor, 'file.txt' is the name of
|
||||||
|
the file you wish to edit. Use the name of a file that you can change.
|
||||||
|
|
||||||
|
3. Insert and delete text as you learned in the previous lessons.
|
||||||
|
|
||||||
|
4. Save the file with changes and exit Vim with: :wq <ENTER>
|
||||||
|
|
||||||
|
5. If you have quit vimtutor in step 1 restart the vimtutor and move down to
|
||||||
|
the following summary.
|
||||||
|
|
||||||
|
6. After reading the above steps and understanding them: do it.
|
||||||
|
|
||||||
|
Lesson 5.1: HOW TO EXECUTE AN EXTERNAL COMMAND
|
||||||
|
|
||||||
|
|
||||||
|
** Type :! followed by an external command to execute that command. **
|
||||||
|
|
||||||
|
1. Type the familiar command : to set the cursor at the bottom of the
|
||||||
|
screen. This allows you to enter a command-line command.
|
||||||
|
|
||||||
|
2. Now type the ! (exclamation point) character. This allows you to
|
||||||
|
execute any external shell command.
|
||||||
|
|
||||||
|
3. As an example type ls following the ! and then hit <ENTER>. This
|
||||||
|
will show you a listing of your directory, just as if you were at the
|
||||||
|
shell prompt. Or use :!dir if ls doesn't work.
|
||||||
|
|
||||||
|
NOTE: It is possible to execute any external command this way, also with
|
||||||
|
arguments.
|
||||||
|
|
||||||
|
NOTE: All : commands must be finished by hitting <ENTER>
|
||||||
|
From here on we will not always mention it.
|
||||||
|
|
||||||
|
Lesson 5.2: MORE ON WRITING FILES
|
||||||
|
|
||||||
|
|
||||||
|
** To save the changes made to the text, type :w FILENAME **
|
||||||
|
|
||||||
|
1. Type :!dir or :!ls to get a listing of your directory.
|
||||||
|
You already know you must hit <ENTER> after this.
|
||||||
|
|
||||||
|
2. Choose a filename that does not exist yet, such as TEST.
|
||||||
|
|
||||||
|
3. Now type: :w TEST (where TEST is the filename you chose.)
|
||||||
|
|
||||||
|
4. This saves the whole file (the Vim Tutor) under the name TEST.
|
||||||
|
To verify this, type :!dir or :!ls again to see your directory.
|
||||||
|
|
||||||
|
NOTE: If you were to exit Vim and start it again with vim TEST , the file
|
||||||
|
would be an exact copy of the tutor when you saved it.
|
||||||
|
|
||||||
|
5. Now remove the file by typing (Windows): :!del TEST
|
||||||
|
or (Unix): :!rm TEST
|
||||||
|
|
||||||
|
Lesson 5.3: SELECTING TEXT TO WRITE
|
||||||
|
|
||||||
|
|
||||||
|
** To save part of the file, type v motion :w FILENAME **
|
||||||
|
|
||||||
|
1. Move the cursor to this line.
|
||||||
|
|
||||||
|
2. Press v and move the cursor to the fifth item below. Notice that the
|
||||||
|
text is highlighted.
|
||||||
|
|
||||||
|
3. Press the : character. At the bottom of the screen :'<,'> will appear.
|
||||||
|
|
||||||
|
4. Type w TEST , where TEST is a filename that does not exist yet. Verify
|
||||||
|
that you see :'<,'>w TEST before you press <ENTER>.
|
||||||
|
|
||||||
|
5. Vim will write the selected lines to the file TEST. Use :!dir or :!ls
|
||||||
|
to see it. Do not remove it yet! We will use it in the next lesson.
|
||||||
|
|
||||||
|
NOTE: Pressing v starts Visual selection. You can move the cursor around
|
||||||
|
to make the selection bigger or smaller. Then you can use an operator
|
||||||
|
to do something with the text. For example, d deletes the text.
|
||||||
|
|
||||||
|
Lesson 5.4: RETRIEVING AND MERGING FILES
|
||||||
|
|
||||||
|
|
||||||
|
** To insert the contents of a file, type :r FILENAME **
|
||||||
|
|
||||||
|
1. Place the cursor just above this line.
|
||||||
|
|
||||||
|
NOTE: After executing Step 2 you will see text from lesson 5.3. Then move
|
||||||
|
DOWN to see this lesson again.
|
||||||
|
|
||||||
|
2. Now retrieve your TEST file using the command :r TEST where TEST is
|
||||||
|
the name of the file you used.
|
||||||
|
The file you retrieve is placed below the cursor line.
|
||||||
|
|
||||||
|
3. To verify that a file was retrieved, cursor back and notice that there
|
||||||
|
are now two copies of lesson 5.3, the original and the file version.
|
||||||
|
|
||||||
|
NOTE: You can also read the output of an external command. For example,
|
||||||
|
:r !ls reads the output of the ls command and puts it below the
|
||||||
|
cursor.
|
||||||
|
|
||||||
|
Lesson 7.1: GETTING HELP
|
||||||
|
|
||||||
|
|
||||||
|
** Use the on-line help system **
|
||||||
|
|
||||||
|
Vim has a comprehensive on-line help system. To get started, try one of
|
||||||
|
these three:
|
||||||
|
- press the <HELP> key (if you have one)
|
||||||
|
- press the <F1> key (if you have one)
|
||||||
|
- type :help <ENTER>
|
||||||
|
|
||||||
|
Read the text in the help window to find out how the help works.
|
||||||
|
Type CTRL-W CTRL-W to jump from one window to another.
|
||||||
|
Type :q <ENTER> to close the help window.
|
||||||
|
|
||||||
|
You can find help on just about any subject, by giving an argument to the
|
||||||
|
":help" command. Try these (don't forget pressing <ENTER>):
|
||||||
|
|
||||||
|
:help w
|
||||||
|
:help c_CTRL-D
|
||||||
|
:help insert-index
|
||||||
|
:help user-manual
|
||||||
|
|
||||||
|
Lesson 7.3: COMPLETION
|
||||||
|
|
||||||
|
|
||||||
|
** Command line completion with CTRL-D and <TAB> **
|
||||||
|
|
||||||
|
1. Make sure Vim is not in compatible mode: :set nocp
|
||||||
|
|
||||||
|
2. Look what files exist in the directory: :!ls or :!dir
|
||||||
|
|
||||||
|
3. Type the start of a command: :e
|
||||||
|
|
||||||
|
4. Press CTRL-D and Vim will show a list of commands that start with "e".
|
||||||
|
|
||||||
|
5. Type d<TAB> and Vim will complete the command name to ":edit".
|
||||||
|
|
||||||
|
6. Now add a space and the start of an existing file name: :edit FIL
|
||||||
|
|
||||||
|
7. Press <TAB>. Vim will complete the name (if it is unique).
|
||||||
|
|
||||||
|
NOTE: Completion works for many commands. Just try pressing CTRL-D and
|
||||||
|
<TAB>. It is especially useful for :help .
|
||||||
|
""".trimIndent()
|
@ -293,7 +293,7 @@ public class ExEntryPanel extends JPanel {
|
|||||||
VimPlugin.getEditor().closeEditorSearchSession(editor);
|
VimPlugin.getEditor().closeEditorSearchSession(editor);
|
||||||
final int matchOffset = SearchHighlightsHelper.updateIncsearchHighlights(editor, pattern, forwards, caretOffset, searchRange);
|
final int matchOffset = SearchHighlightsHelper.updateIncsearchHighlights(editor, pattern, forwards, caretOffset, searchRange);
|
||||||
if (matchOffset != -1) {
|
if (matchOffset != -1) {
|
||||||
editor.getCaretModel().getPrimaryCaret().moveToOffset(matchOffset);
|
new IjVimCaret(editor.getCaretModel().getPrimaryCaret()).moveToOffset(matchOffset);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
resetCaretOffset(editor);
|
resetCaretOffset(editor);
|
||||||
|
@ -0,0 +1,48 @@
|
|||||||
|
/*
|
||||||
|
* IdeaVim - Vim emulator for IDEs based on the IntelliJ platform
|
||||||
|
* Copyright (C) 2003-2021 The IdeaVim authors
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.maddyhome.idea.vim.vimscript.model.functions.handlers
|
||||||
|
|
||||||
|
import com.intellij.refactoring.rename.inplace.InplaceRefactoring
|
||||||
|
import com.maddyhome.idea.vim.api.ExecutionContext
|
||||||
|
import com.maddyhome.idea.vim.api.VimEditor
|
||||||
|
import com.maddyhome.idea.vim.newapi.ij
|
||||||
|
import com.maddyhome.idea.vim.vimscript.model.VimLContext
|
||||||
|
import com.maddyhome.idea.vim.vimscript.model.datatypes.VimDataType
|
||||||
|
import com.maddyhome.idea.vim.vimscript.model.datatypes.VimInt
|
||||||
|
import com.maddyhome.idea.vim.vimscript.model.expressions.Expression
|
||||||
|
import com.maddyhome.idea.vim.vimscript.model.functions.FunctionHandler
|
||||||
|
|
||||||
|
object RenamingFunctionHandler : FunctionHandler() {
|
||||||
|
|
||||||
|
override val name = "renaming"
|
||||||
|
override val minimumNumberOfArguments = 0
|
||||||
|
override val maximumNumberOfArguments = 0
|
||||||
|
|
||||||
|
override fun doFunction(
|
||||||
|
argumentValues: List<Expression>,
|
||||||
|
editor: VimEditor,
|
||||||
|
context: ExecutionContext,
|
||||||
|
vimContext: VimLContext,
|
||||||
|
): VimDataType {
|
||||||
|
return if (InplaceRefactoring.getActiveInplaceRenamer(editor.ij) == null)
|
||||||
|
VimInt.ZERO
|
||||||
|
else
|
||||||
|
VimInt.ONE
|
||||||
|
}
|
||||||
|
}
|
@ -226,12 +226,12 @@
|
|||||||
|
|
||||||
<!-- Change -->
|
<!-- Change -->
|
||||||
<vimAction implementation="com.maddyhome.idea.vim.action.change.change.ChangeCaseLowerMotionAction" mappingModes="N" keys="gu"/>
|
<vimAction implementation="com.maddyhome.idea.vim.action.change.change.ChangeCaseLowerMotionAction" mappingModes="N" keys="gu"/>
|
||||||
<vimAction implementation="com.maddyhome.idea.vim.action.change.change.ChangeCaseLowerVisualAction" mappingModes="X" keys="u"/>
|
<!-- <vimAction implementation="com.maddyhome.idea.vim.action.change.change.ChangeCaseLowerVisualAction" mappingModes="X" keys="u"/>-->
|
||||||
<vimAction implementation="com.maddyhome.idea.vim.action.change.change.ChangeCaseToggleCharacterAction" mappingModes="N" keys="~"/>
|
<vimAction implementation="com.maddyhome.idea.vim.action.change.change.ChangeCaseToggleCharacterAction" mappingModes="N" keys="~"/>
|
||||||
<vimAction implementation="com.maddyhome.idea.vim.action.change.change.ChangeCaseToggleMotionAction" mappingModes="N" keys="g~"/>
|
<vimAction implementation="com.maddyhome.idea.vim.action.change.change.ChangeCaseToggleMotionAction" mappingModes="N" keys="g~"/>
|
||||||
<vimAction implementation="com.maddyhome.idea.vim.action.change.change.ChangeCaseToggleVisualAction" mappingModes="X" keys="~"/>
|
<vimAction implementation="com.maddyhome.idea.vim.action.change.change.ChangeCaseToggleVisualAction" mappingModes="X" keys="~"/>
|
||||||
<vimAction implementation="com.maddyhome.idea.vim.action.change.change.ChangeCaseUpperMotionAction" mappingModes="N" keys="gU"/>
|
<vimAction implementation="com.maddyhome.idea.vim.action.change.change.ChangeCaseUpperMotionAction" mappingModes="N" keys="gU"/>
|
||||||
<vimAction implementation="com.maddyhome.idea.vim.action.change.change.ChangeCaseUpperVisualAction" mappingModes="X" keys="U"/>
|
<!-- <vimAction implementation="com.maddyhome.idea.vim.action.change.change.ChangeCaseUpperVisualAction" mappingModes="X" keys="U"/>-->
|
||||||
<vimAction implementation="com.maddyhome.idea.vim.action.change.change.ChangeCharacterAction" mappingModes="N" keys="r"/>
|
<vimAction implementation="com.maddyhome.idea.vim.action.change.change.ChangeCharacterAction" mappingModes="N" keys="r"/>
|
||||||
<vimAction implementation="com.maddyhome.idea.vim.action.change.change.ChangeCharactersAction" mappingModes="N" keys="s"/>
|
<vimAction implementation="com.maddyhome.idea.vim.action.change.change.ChangeCharactersAction" mappingModes="N" keys="s"/>
|
||||||
<vimAction implementation="com.maddyhome.idea.vim.action.change.change.ChangeEndOfLineAction" mappingModes="N" keys="C"/>
|
<vimAction implementation="com.maddyhome.idea.vim.action.change.change.ChangeEndOfLineAction" mappingModes="N" keys="C"/>
|
||||||
@ -329,8 +329,8 @@
|
|||||||
<vimAction implementation="com.maddyhome.idea.vim.action.change.RepeatChangeAction" mappingModes="N" keys="."/>
|
<vimAction implementation="com.maddyhome.idea.vim.action.change.RepeatChangeAction" mappingModes="N" keys="."/>
|
||||||
<vimAction implementation="com.maddyhome.idea.vim.action.ExEntryAction" mappingModes="NXO" keys=":"/>
|
<vimAction implementation="com.maddyhome.idea.vim.action.ExEntryAction" mappingModes="NXO" keys=":"/>
|
||||||
<vimAction implementation="com.maddyhome.idea.vim.action.ResetModeAction" mappingModes="ALL" keys="«C-\»«C-N»"/>
|
<vimAction implementation="com.maddyhome.idea.vim.action.ResetModeAction" mappingModes="ALL" keys="«C-\»«C-N»"/>
|
||||||
<vimAction implementation="com.maddyhome.idea.vim.action.change.RedoAction" mappingModes="N" keys="«C-R»"/>
|
<vimAction implementation="com.maddyhome.idea.vim.action.change.RedoAction" mappingModes="NX" keys="U,«C-R»"/>
|
||||||
<vimAction implementation="com.maddyhome.idea.vim.action.change.UndoAction" mappingModes="N"/>
|
<vimAction implementation="com.maddyhome.idea.vim.action.change.UndoAction" mappingModes="NX"/>
|
||||||
|
|
||||||
<!-- Keys -->
|
<!-- Keys -->
|
||||||
<vimAction implementation="com.maddyhome.idea.vim.action.change.OperatorAction" mappingModes="N" keys="g@"/>
|
<vimAction implementation="com.maddyhome.idea.vim.action.change.OperatorAction" mappingModes="N" keys="g@"/>
|
||||||
|
@ -22,5 +22,6 @@
|
|||||||
<vimLibraryFunction implementation="com.maddyhome.idea.vim.vimscript.model.functions.handlers.TolowerFunctionHandler" name="tolower"/>
|
<vimLibraryFunction implementation="com.maddyhome.idea.vim.vimscript.model.functions.handlers.TolowerFunctionHandler" name="tolower"/>
|
||||||
<vimLibraryFunction implementation="com.maddyhome.idea.vim.vimscript.model.functions.handlers.ToupperFunctionHandler" name="toupper"/>
|
<vimLibraryFunction implementation="com.maddyhome.idea.vim.vimscript.model.functions.handlers.ToupperFunctionHandler" name="toupper"/>
|
||||||
<vimLibraryFunction implementation="com.maddyhome.idea.vim.vimscript.model.functions.handlers.JoinFunctionHandler" name="join"/>
|
<vimLibraryFunction implementation="com.maddyhome.idea.vim.vimscript.model.functions.handlers.JoinFunctionHandler" name="join"/>
|
||||||
|
<vimLibraryFunction implementation="com.maddyhome.idea.vim.vimscript.model.functions.handlers.RenamingFunctionHandler" name="renaming"/>
|
||||||
</extensions>
|
</extensions>
|
||||||
</idea-plugin>
|
</idea-plugin>
|
@ -1,39 +1,35 @@
|
|||||||
<!--
|
<idea-plugin xmlns:xi="http://www.w3.org/2001/XInclude">
|
||||||
~ Copyright 2003-2022 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.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<idea-plugin url="https://plugins.jetbrains.com/plugin/164" xmlns:xi="http://www.w3.org/2001/XInclude">
|
|
||||||
<name>IdeaVim</name>
|
<name>IdeaVim</name>
|
||||||
<id>IdeaVIM</id>
|
<id>IdeaVIM</id>
|
||||||
<change-notes><![CDATA[
|
<change-notes><![CDATA[
|
||||||
<h3>Changes:</h3>
|
|
||||||
<ul>
|
|
||||||
<li>IdeaVim changes license from GPL-2.0 or later to MIT. <a href="https://youtrack.jetbrains.com/issue/VIM-2782">VIM-2782</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
<h3>Fixes:</h3>
|
<h3>Fixes:</h3>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="https://youtrack.jetbrains.com/issue/VIM-1758">VIM-1758</a> Commentary plugin in rider</li>
|
<li><a href="https://youtrack.jetbrains.com/issue/VIM-2797">VIM-2797</a> Introduce variable to mute default argtextobj
|
||||||
<li><a href="https://youtrack.jetbrains.com/issue/VIM-1903">VIM-1903</a> Autoindent now works in rider</li>
|
mappings
|
||||||
<li><a href="https://youtrack.jetbrains.com/issue/VIM-2744">VIM-2744</a> Fix undo from ex line</li>
|
|
||||||
<li><a href="https://youtrack.jetbrains.com/issue/VIM-2749">VIM-2749</a> Fix :tabn and :tabN commands</li>
|
|
||||||
<li><a href="https://youtrack.jetbrains.com/issue/VIM-2718">VIM-2718</a> Fixed case where the primary caret was
|
|
||||||
changed
|
|
||||||
</li>
|
</li>
|
||||||
<li><a href="https://youtrack.jetbrains.com/issue/VIM-2766">VIM-2766</a> Move NERDTree update to background thread
|
<li><a href="https://youtrack.jetbrains.com/issue/VIM-758">VIM-758</a> Support d mappings</li>
|
||||||
|
<li><a href="https://youtrack.jetbrains.com/issue/VIM-2577">VIM-2577</a> Fix paste at the end of notebook cell</li>
|
||||||
|
<li><a href="https://youtrack.jetbrains.com/issue/VIM-2813">VIM-2813</a> Migrate update checker to
|
||||||
|
VimStandalonePluginUpdateChecker
|
||||||
</li>
|
</li>
|
||||||
<li><a href="https://youtrack.jetbrains.com/issue/VIM-2768">VIM-2768</a> Refactor listeners</li>
|
|
||||||
<li><a href="https://youtrack.jetbrains.com/issue/VIM-2776">VIM-2776</a> Use filename index for file search</li>
|
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<h3>Merged PRs:</h3>
|
<h3>Merged PRs:</h3>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="https://github.com/JetBrains/ideavim/pull/550">550</a> by <a href="https://github.com/citizenmatt">Matt
|
<li><a href="https://github.com/JetBrains/ideavim/pull/558">558</a> by <a href="https://github.com/citizenmatt">Matt
|
||||||
Ellis</a>: Fix(VIM-2778) Remove override of editor scroll setting
|
Ellis</a>: Fix incorrect normalising for trailing inlay
|
||||||
|
</li>
|
||||||
|
<li><a href="https://github.com/JetBrains/ideavim/pull/554">554</a> by <a href="https://github.com/citizenmatt">Matt
|
||||||
|
Ellis</a>: Refactor "last column" calculations
|
||||||
|
</li>
|
||||||
|
<li><a href="https://github.com/JetBrains/ideavim/pull/553">553</a> by <a href="https://github.com/citizenmatt">Matt
|
||||||
|
Ellis</a>: Rearrange and rename some code in engine
|
||||||
|
</li>
|
||||||
|
<li><a href="https://github.com/JetBrains/ideavim/pull/560">560</a> by <a
|
||||||
|
href="https://github.com/Runinho">Runinho</a>: Fix(VIM-2577) paste not working at end of notebook cell
|
||||||
|
</li>
|
||||||
|
<li><a href="https://github.com/JetBrains/ideavim/pull/571">571</a> by <a href="https://github.com/adaext">Ada</a>:
|
||||||
|
Remove the redundant quotation mark at the end of "packadd matchit" command
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
]]>
|
]]>
|
||||||
@ -50,7 +46,7 @@
|
|||||||
<li><a href="https://youtrack.jetbrains.com/issues/VIM">Issue tracker</a>: feature requests and bug reports</li>
|
<li><a href="https://youtrack.jetbrains.com/issues/VIM">Issue tracker</a>: feature requests and bug reports</li>
|
||||||
</ul>
|
</ul>
|
||||||
]]></description>
|
]]></description>
|
||||||
<version>SNAPSHOT</version>
|
<version>chylex</version>
|
||||||
<vendor>JetBrains</vendor>
|
<vendor>JetBrains</vendor>
|
||||||
|
|
||||||
<!-- Please search for "[VERSION UPDATE]" in project in case you update the since-build version -->
|
<!-- Please search for "[VERSION UPDATE]" in project in case you update the since-build version -->
|
||||||
|
@ -80,6 +80,28 @@ class MotionLastColumnActionTest : VimTestCase() {
|
|||||||
doTest(keys, before, after, VimStateMachine.Mode.VISUAL, VimStateMachine.SubMode.VISUAL_BLOCK)
|
doTest(keys, before, after, VimStateMachine.Mode.VISUAL, VimStateMachine.SubMode.VISUAL_BLOCK)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun `test dollar motion resets intended location after motion`() {
|
||||||
|
doTest(
|
||||||
|
"\$hlj",
|
||||||
|
"""
|
||||||
|
A Discovery
|
||||||
|
|
||||||
|
I ${c}found it in a legendary land
|
||||||
|
all rocks and lavender and tufted grass,[ additional symbols]
|
||||||
|
where it was settled on some sodden sand
|
||||||
|
hard by the torrent of a mountain pass.
|
||||||
|
""".trimIndent(),
|
||||||
|
"""
|
||||||
|
A Discovery
|
||||||
|
|
||||||
|
I found it in a legendary land
|
||||||
|
all rocks and lavender and tu${c}fted grass,[ additional symbols]
|
||||||
|
where it was settled on some sodden sand
|
||||||
|
hard by the torrent of a mountain pass.
|
||||||
|
""".trimIndent()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
@VimBehaviorDiffers(
|
@VimBehaviorDiffers(
|
||||||
originalVimAfter = """
|
originalVimAfter = """
|
||||||
A Discovery
|
A Discovery
|
||||||
|
@ -213,7 +213,7 @@ class KeyHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* See the description for [com.maddyhome.idea.vim.action.DuplicableOperatorAction]
|
* See the description for [com.maddyhome.idea.vim.command.DuplicableOperatorAction]
|
||||||
*/
|
*/
|
||||||
private fun mapOpCommand(
|
private fun mapOpCommand(
|
||||||
key: KeyStroke,
|
key: KeyStroke,
|
||||||
|
@ -176,7 +176,8 @@ abstract class VimChangeGroupBase : VimChangeGroup {
|
|||||||
val startOffsets = updatedRange.startOffsets
|
val startOffsets = updatedRange.startOffsets
|
||||||
val endOffsets = updatedRange.endOffsets
|
val endOffsets = updatedRange.endOffsets
|
||||||
for (i in updatedRange.size() - 1 downTo 0) {
|
for (i in updatedRange.size() - 1 downTo 0) {
|
||||||
editor.deleteString(TextRange(startOffsets[i], endOffsets[i]))
|
val (newRange, _) = editor.search(startOffsets[i].offset to endOffsets[i].offset, editor, LineDeleteShift.NL_ON_END) ?: continue
|
||||||
|
editor.deleteString(TextRange(newRange.first.point, newRange.second.point))
|
||||||
}
|
}
|
||||||
if (type != null) {
|
if (type != null) {
|
||||||
val start = updatedRange.startOffset
|
val start = updatedRange.startOffset
|
||||||
|
@ -0,0 +1,22 @@
|
|||||||
|
package com.maddyhome.idea.vim.option
|
||||||
|
|
||||||
|
import com.maddyhome.idea.vim.api.injector
|
||||||
|
import com.maddyhome.idea.vim.options.OptionConstants
|
||||||
|
import com.maddyhome.idea.vim.options.OptionScope
|
||||||
|
|
||||||
|
|
||||||
|
@Deprecated("Please use StrictMode from com.maddyhome.idea.vim.options.helpers", replaceWith = ReplaceWith("com.maddyhome.idea.vim.options.helpers.StrictMode"))
|
||||||
|
object StrictMode {
|
||||||
|
@JvmName("assertTrue")
|
||||||
|
fun assert(condition: Boolean, message: String) {
|
||||||
|
if (!condition) {
|
||||||
|
fail(message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun fail(message: String) {
|
||||||
|
if (injector.optionService.isSet(OptionScope.GLOBAL, OptionConstants.ideastrictmodeName)) {
|
||||||
|
error(message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user