Vim 相关快捷键

背景 & 目标

个人使用 vim 已经很久了,但由于快捷键种类繁多,一直没有下决心好好学习整理一下,本篇文章会把这次学习的过程详细记录下来

目前在 IDE 和一些文档编辑器如 Obsidian 上都有对应的 vim 支持,因此完整学习后,对于文章的书写或者开发日常,泛用性比较好

本篇文章以 vscode 中 Learn Vim 插件作为参考资料,并整理核心内容为中文

基础移动

这四个键是 vim 中基础移动动作

  • h
  • j
  • k
  • l

使用 vim 动作快速移动

  • f(字符) 移动到本行下一个字符出现的地方
  • F(字符) 移动到本行上一个字符出现的地方

t 的移动和 f 基本一致,但是光标落的地方稍有不同

type t(   ==> v                       v
              const fireball = function(target){
type f(   ==> ^                        ^

当需要反复执行 f( 可以使用 ; 来重复上一个动作

type fdfdfd ==> v   v               v        v
                let damage = weapon.damage * d20();
                let damage = weapon.damage * d20();
type fd;;   ==> v   v               v        v

水平移动

  • 0 移动到行首
  • ^ 移动到行首非空字符
  • $ 移动到行尾
  • g_ 移动到尾的非空字符

垂直移动

  • } 移动到下一段
  • { 同上,但向上移动
  • CTRL-D 向下翻半页
  • CTRL-U 向上翻半页

搜索

  • /{内容} 向下搜索
  • ?{内容} 向上搜索

在输入 /? 后, 接自己想要搜索的内容, 如 /cucumber 接着按下 ENTER 键,进入搜索模式

  • n 跳转下一个匹配项
  • N 跳转上一个匹配项

这里的内容不一定是一段准确的字符串,同样支持正则表达式

数字+动作

在 vim 中,数字可以理解为重复次数,比如 2w 就相当于按了两次 w 键,可以和其他动作一起组合, 这里我们以 wf 为例

type wwww ==> v   v v   v   v
              word. are two words
              word. are two words
type 3w2w ==>       ^       ^

type f[;;  ==> vv    v
               [[1], [1, 2], [3]]
               [[1], [1, 2], [3]]
type 3f[  ==>        ^

其他核心动作

  • gg 跳转至文件第一个字符
  • {行}gg 跳转至指定行
  • G 跳转至文件最后一个字符
  • %({[]}) 直接来回跳转

使用 Vim 操作符进行神奇的编辑

使用 运算符/operators数量/counts动作/motions 结合使用,来定义应用于文本范围的操作:

   做什么 (删除, 修改...)
      /
     /      做多少次(缺省时相当于count 为 1)
    /         /
   v         v
{operator}{count}{motion}
                    ^
                   /
                  /
           在哪里执行这个动作

以删除为例,d2w 相当于执行 删除 2 次 w 的范围

  start here
  /
 /
v
DO NOT ENTER!
# 执行后
ENTER!

撤销/重做

在尝试删除之前,需要先知道如何 撤销/重做

  • u 撤销
  • CTRL-R 重做

d

  • d 删除字符
  • dd 删除一行
  • D 从光标删除到行尾
  • dt; 从光标删除到 ; 字符
  • d/hello 从光标删除直到 hello

c

  • c 替换并插入,相当于 d + i
  • cc 替换整行,相当于 dd + i
  • C 从光标替换到行尾 d + $ + a

在如下例子中,我们希望将 const courteousSalute 修改为 const politeSalute,整体相当于少敲了一个键

  start here
  /
 /
v
const courteousSalute

// d + i 时: wdtSipolite
// c     时: wctSpolite

. 操作

  • . 重复上一次改动

这里要理解什么是 改动

  • 使用 d{motion} 算改动
  • 使用 i{xxx} 算改动
  • 使用 c{xxx} 算改动

在如下例子中,我们希望将两个 courteous 替换为 polite

  start here
  /
 /
v
const courteousSalute = "I courteously salute you good person.";
// d + i   时: wdtSipolite<ESC>fcdwipolitely<ESPACE><ESC>
// c       时: wctSpolite<ESC>fccwpolitely<ESPACE><ESC>
// c + .   时: wcfspolite<ESC>fc

又或者使用搜索配合 c + .

/co<ENTER>cfspolite<ESC>n.
找到下一个 co 开头的位置, 然后修改至s字符,接着输入 polite,使用 n 进入查找的下一个,最后使用 . 重复执行一次

文本对象

在 Vim 中,我们可以使用如下组合

{操作}{a|i}{文本对象}

其中 a|i文本对象 的解释为

            |- `a` 是 around
            |- `i` 是 inner
           /
          /
         /
        {a|i}{文本对象}
                  /
                 /
                | w - 单词
                | s - 句子
                | p - 段落
                | " - 引号

以下面这个为例,执行后会删除双引号中所有内容,fR 指找到下一个 R 开头的位置,ci" 指替换双引号内部的所有内容

单单在这个粒子中,fR 可以省略,直接输入 ci" 效果也是一样的

   you are here!
  /
 /
v
const poem = "Roses are red";
// fRci"

其他操作

  • y yank,复制
  • p put,粘贴
  • g~ 字母大小写切换
    • gu 字母小写
    • 给U 字母大写
  • > 增加缩进
  • < 移除缩进
  • = 格式化代码
  • x 等于 dl 删除当前光标的字符
  • X 等于 dh 删除光标前的字符
  • s 等于 ch 或 dli,删除当前光标的字符并进入插入模式
  • r 替换当前字符
  • ~ 切换当前字符大小写

插入文字

目前为止,我们所有的介绍都在 Normal Mode 中,接下来会介绍 Insert Mode

  • i 在光标前插入
  • a 在光标后插入
  • I 在行首插入
  • A 在行尾插入

           you are here
               /
              /
             v
       const status = "I'm in awe"
      ^     ^ ^                   ^
      |     | |                   |
      I     i a                   A

  • o 在当前行的下方增加一行,并进入 Insert Mode
  • O 在当前行的上方增加一行,并进入 Insert Mode

           you are here
               /
              /
   O ->      v
       const status = "I'm in awe"
   o ->

选择文字

这个部分是 Visual Mode

  • v 逐字模式
  • V 逐行模式
  • CTRL-V 逐块模式

Visual Mode 下,我们提交操作符时,与 Normal Mode 的顺序是反过来的

进入 Visual Mode
    /
   /                      做那个操作
  /                         /
---------                  /
{v|V|C-V}{count}{motion}{operator}
         ---------------
           /
          /
   执行哪个动作

以下发内容为例,我们希望在 Visual Mode 中删除 It is,此时可以执行 vtbd,这段操作可以理解为,进入视觉模式,选择直到 b 字符的前方(此时 It is 已经被选中),最后执行删除

 start here
  /
 /
v
It is better to go forward without a goal

同样的如果我们希望删除多行,仅保留最后的 123,此时可以执行 Vjjd,可以理解为,进入逐行模式,选择三行后,执行删除操作

 start here
  /
 /
v
It is better to go forward without a goal
It is better to go forward without a goal
It is better to go forward without a goal
123

如果希望对多行进行追加,比如下方的例子,在行首追加 aaa 在行尾追加 bbb,此时可以执行 CTRL-V2jIaaa<Esc> 接着执行 CTRL-V2j$Abbb

这里指令变多了,稍微复杂些,第一段是进入逐块模式,向下选择两行,然后在行首插入 aaa, 接着 Esc 退出

第二段是,再次进入逐块模式,向下选择两行,跳转到行尾,接着在行尾插入 bbb

 start here
  /
 /
v
123
456666
789

结果
aaa123bbb
aaa456666bbb
aaa789bbb