Vim 精进

1. 高阶光标移动

vim 的绝大多数高效快捷操作是以光标所在位置为基础和出发点的,因此,光标位置驾驭能力,即在 vim 内快速移动光标,快速到达期望的位置,是 vim 所有高阶编辑操作的基本前提。

vim 点滴中,介绍了光标的基本移动方法,在此基础上,本文梳理更为高阶的光标移动方法。

1). 行内快速移动 — f 操作

f 操作,即字符查找命令,顾名思义,它是用来查找字符的,可以在一行内将光标快速定位期望的字符上,是 vim 中移动最快的方式之一。其具体使用形式为:

  • f + 期望查找的char

如果一行内有多个”期望查找的char”,使用 ;(分号),(逗号) 在各个 char 之间前后移动光标。

2). 全文快速移动 — 搜索操作

f 操作是在一行内进行光标快移,而搜索操作是光标在全文中快速移动的重要利器。搜索操作若执行成功,光标会自动移动到第一个匹配的字符串。

如果搜索范围内有多个”匹配项”,使用 n (分号)N (逗号) 在各个匹配项之间前后移动光标。

a). 重量级搜索 — / 操作

vim 提供全面的重量级搜索能力,可以针对任意字符串进行全文搜索,具体形式如下:

  • / + 期望查找的字符串

期望字符串可以直接以字符串形式给出,也可以用 regular expression 形式给出。尤其是利用 regular expression 时,可找出各类特色字符串。

b). 轻量级搜索 — * 操作

除重量级的任意字符串查找之外,vim 还提供轻量级的”检索快速通道”,可以直接查找光标位置的单词。操作简单直接,直接在光标所在单词上输入 * (星号),即可在全文内查找所有匹配光标所在位置单词的实例。

c). 搜索结果查看

为方便直观查看搜索匹配的结果情况,vim 也提供了相关的设置选项

set hls(earch) -- 开启搜索结果高亮
set nohls(earch) -- 关闭搜索结果高亮

高亮选项在 vim 默认情况下未开启,需要手动或设置 vimrc 开启。高亮开启后,一旦搜索匹配成功,高亮一直存在,实际应用中,使用 “/ + 文字不存在的字符串” 来取消高亮,更为便捷。

vim 还提供了 “实时预览式搜索” 的选项,即随着 / 查找域输入内容的变化,实时预览第一处匹配。具体设置选项为 incsearch

incsearch -- 实时预览搜索结果

3). “屏幕行”上的微移动 — g 操作

vim 的基本移动操作以 “逻辑行” 为单位,但 UI 实际展示中,由于显示区域限制,一个 “逻辑行” 有时会自动换行成由多个 “屏幕行” 组成,此时,如想在 “屏幕行” 之间移动,基本移动操作无能为力,利用 “g 操作 + 基本移动操作”,可以在显示的 “屏幕行” 之间及内部进行操作,实现了更细粒度上的 “微移动”。

几个典型 g 操作:

  • gj — 向下移动一个”屏幕行”
  • gk — 向上移动一个”屏幕行”
  • g0 — 移动行”屏幕行”行首
  • g$ — 移动行”屏幕行”行尾

g 操作动作更为“细腻”,实用性很强。

2. 文本对象

就像常见的大多数编辑器一样,vim 提供了基本的以位置为基础的文本编辑能力,某种角度而言,这是一种以 “点(光标所在位置)” 为基础的操作方式。与其他大多数编辑器不同的是,vim 还提供了更高阶的以 “块(区域)” 为基础的操作方式,vim 中的这种 “块(区域)” 即 — 文本对象(text-object)。

文本对象就是基于结构定义的文本区域。在 vim 中,文本对象可以作为一个基本的操作单元,vim 允许对这个区域从整体上进行各种操作。这种操作效率极高,是 vim 应用的 “杀手锏” 之一。

1) 文本对象的定义

vim 的文本对象两个字符组成:

pic

  • 第一个是 “前导边界定义符”,它定义了文本对象(文本区域)的边界,永远是字符 i 或 字符 a,字符 i 可理解为 “inside”,即内边界;字符 a 可理解为 “around”,即外边界。
  • 第二个是 “文本区域定义符”,它定义了每一个具体的文本对象。因文本对象是基于结构定义的文本区域,故文本区域的符号也是以英文文本中各个结构元素为基础定义的,具体使用的符号有:
    • w — 一个单词
    • s — 一个句子
    • p — 一个段落
    • () — 圆括号( )内文本区域
    • [] — 方括号[ ]内文本区域
    • {} — 大括号{ }内文本区域
    • \< 或 > — 尖括号\< >内文本区域
    • — 单引号内文本区域
    • — 双引号内文本区域
    • ` — 反引号内文本区域
    • t — 标签\<tag>\</tag>内文本区域

将前导符与区域符组合,即构成一个完整的文本对象。从区域符的定义不难看出,其可以分为两类,一个是对称区域,如 ( )、[ ]、{ }、t 等,一类是非对称个区域,如 w、p、s。针对两类不同的区域,i 和 a 组合后的效果不同:

  • 针对对称区域,容易理解,字符 i 定义了 “对称符号内部区域的文本”,字符 a 定义了 “对称符号内部区域 + 对称符号本身的文本”;
  • 针对非对称区域,字符 i 定义了保守的区域最小范围,即 w、p、s 本身,字符 a 则定义了扩展范围,包括 w、p、s 周边的空白区域。使用时,可以根据操作需求具体,选择保守区域或是扩展范围区域。
常用的典型文本对象有:
1) 非对称文本对象:
    aw, iw; 
    as, is;
    ap, ip;
2) 对称文本对象
    a( = a) = ab, i( = i) = ib; b代表block
    a{ = a} = aB, i{ = i} = iB; B代表BLOCK
    a[ = a], i[ = i];   
    a< = a>, i< = i>;
    a', i'; 
    a", i";
    a`, i`;
    at, it;     t代表tag

2) 文本对象的操作

文本对象定义了一个文本区域,使用时,采用的是 “以点选面” 的方式,即只要光标在文本对象内任意位置,输入文本对象组合符,即可选择相应的文本对象。

vim 对文本进行编辑时,采用的是 “操作方法 + 操作对象” 的模式,类似机器语言中的 “操作码 + 操作数” 的概念。选取特定的操作方法(如 d、c、y等),选取文本对象作为操作对象,可极大的提高编辑的效率。

文本对象的操作与前述 f 和搜索等快速操作在理念上有明显的不同,f 和搜索等快速操作更像是一种单向操作,而文本对象操作则是一种双向操作。

pic2

尤其是用 vim 编程时,文本对象操作对于标记语言、各类括号内元素的处理有着明显的优势!

3) 使用技巧

对称文本对象使用直观明了,非对称文本对象进行操作时,
* d 操作进行删除操作,与 a 前导符结合较多,如 daw,删除文本单元本身外,还要删除多余的空白区域(如空格);
* c 操作进行修改操作,则与 i 前导符结合较多,如 ciw,修改文本直接在文本单元处进行修改,其他空白区域还可继续使用

3. 寄存器体系

文本编辑任务中,数据交换的工作必不可少。交换的数据范畴广泛,既包括对代表信息的数据的存储与复用,典型如剪切、复制、黏贴等;也包括对代表操作的数据的存储与复用,如将当前操作步骤存储下来,在某个特定时间、特定位置进行回放等。无论哪种数据,交换想顺利完成,必须有共享存储资源存放交换的数据,软件通过某种手段访问共享存储资源完成数据的交换。像其他编辑软件一样,vim 也提供了数据交换区机制,不同的是,vim 不仅仅依靠单一的操作系统剪切板,vim 以寄存器的形式提供了几十组共享数据存储区,形成了一个功能丰富,完备的寄存器体系。

1) 寄存器使用基本形式

vim 提供了多种寄存器,每种寄存器有特定的编号(id),利用编号,可以找到并使用对应的寄存器。基本使用形式为:

  • “(双引号) + 寄存器编号

2) 寄存器种类

vim 寄存器众多,根据不同的用途可划分为不同种类,典型寄存器类型有:

  • 无名寄存器(”) — 默认使用的寄存器
    • 在操作中没有明确指定要使用的寄存器,则 vim 将缺省使用的寄存器
    • 与所有的数据交互操作都进行交互,无名寄存器内的数据很快被覆盖
    • 编号为双引号,引用形式为 ""
    • 实际使用中不需要特意指出该寄存器编号!
  • 复制专用寄存器(0)
    • 顾名思义,专门用于存储复制操作的内容,即仅当使用 y{motion} 命令时,该寄存器才会被赋值,其他操作均不会影响该寄存器
    • 默认情况下,执行一次 y 操作有两个备份,一份放在无名寄存器中,一份放在复制专用寄存器中
    • 编号为数字 0,引用形式为 "0
  • 字母寄存器(a-z,A-Z)
    • 字母寄存器为通用类型寄存器,可以结合任何操作,使用场景不受限制
    • 小写字母 a-z 寄存器是不记忆覆盖型寄存器;大写字母 A-Z 寄存器是有记忆追加型寄存器
    • 编号为 a-z,A-Z,引用形式为 "a - "z"A - "Z
  • 加号寄存器(+) — 系统剪切板
    • 加号寄存器与系统剪切板等效
    • vim 软件内部与外部数据交换的通道
    • 编号为加号 +,引用形式为 "+

3) 寄存器的使用

寄存器要结合具体的操作来使用,在使用时,只需在具体操作中给出指定的寄存器的编号,该操作即会与指定的寄存器交互,从中读写数据。如,

"ayiw -- 将当前单词复制到寄存器 a 中
"bdd -- 将当前行剪切至寄存器 b 中
"ap -- 将寄存器 a 中的内容粘贴出来
"+p -- 将剪切板的内容粘贴到 vim 内部

字符输入状态下的寄存器使用

在文字输入状态下,如插入模式或命令输入模式(:)下,寄存器使用方法比较特殊。在这些模式下,无法使用 " + 编号 的形式调用指定寄存器。使用组合键 <Ctrl + r> + 寄存器 将特定寄存器中的数据复制到输入符号的位置。

4) 寄存器内容查看

在命令行模式中,输入 Ex 指令:

  • reg + 寄存器编号 — 查看特定编号寄存器内容
  • reg — 查看所有寄存器内容

reference:

  1. :h text-objects
  2. Practical Vim
  3. https://coolshell.cn/articles/5426.html

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注