编辑动词与语法:把句子说完整
学习目标
- 把「编辑语言」的语法公式刻进本能:
[count] 动词 [count] 名词 - 掌握三大主力动词的完整家族:d(删)、c(改)、y(复制)
- 掌握粘贴 p/P 的两种语义:行有行的粘法,字有字的粘法
- 会用小动词干小活:r 单字替换、s/S、大小写 ~/gU、缩进 >>/==、合并 J
- 理解计数前缀的自由:
2dw与d2w是同一句话的两种语序 - 毕业演出:用三句「编辑语言」完成一次真实的函数签名重构
1. 语法总纲:一句话的完整结构
第 0 章预告、第 1 章埋线、第 2 章备料(移动 = 名词)、第 4 章扩编(文本对象 = 名词)—— 现在把动词补齐,这门「编辑语言」就成句了。它的语法只有一条:
[数字] 动词 [数字] 名词
读几个例句找找感觉:3dw = 「删三个词」;c2w = 「改两个词」;d2i(……好吧这句是病句,但 2daw(删两个词)、y3w(复制三个词)都是地道表达。数字可以出现在动词前、名词前、或两边都出现 —— 效果是相乘的,位置随你喜欢:
这条公式真正的威力在于组合爆炸:十来个动词 × 几十个名词,自动生成上百条命令,而你需要「背」的只有每个词本身的含义。传统编辑器教你的每个快捷键都是一条孤立的知识;Vim 教你的是一套能自己造句的语法。这也是本教程把 ch04、ch05 称为「语法篇」的原因 —— 学完这两章,后面所有章节(可视化、查找、宏)不过是往这套语法里添几个新词。
把公式用顺,还有三条「说话纪律」值得贴在显示器边上:
- 说完整的句子。按了 d 却还没想好名词?宁可 Esc 取消重来,也别糊一个错的范围 —— 半截句子是最常见的误删来源;
- 先想名词,再配动词。动手前先自问「我要动的东西是什么」(词?括号?行?)—— 名词定了,动词往往只有一两个候选;反过来先按动词再找名词,说明还没想清就出手了;
- 数字是量词,不是口令。
3dw里的 3 和中文「删三个词」的「三个」是同一个词性 —— 它修饰后面的名词,不该被当成需要背的「快捷键编号」。
2. d 家族:射程菜单系统化
d 你已经用了一章半,现在把它系统化 —— d + 任何名词,一表全收:
| 句子 | 读法 | 备注 |
|---|---|---|
| dw / de | 删到下一词头 / 本词尾 | 从光标处起算 —— 注意与 daw 的区别 |
| d$ / D | 删到行尾 | D 是打包键,等价 d$ |
| dfx / dtx | 删到 x(含)/ 删到 x 前 | 第 2 章的 dt, 就是它 |
| dd | 删当前行 | 名词 = 当前行,与 yy 同构 |
| diw / daw | 删词(词本身 / 带空格) | 第 4 章词典,光标在词内即可 |
| di( / da{ | 清空括号 / 连壳删块 | 跨行也罩得住 |
一个此刻必须说清的设定:d 不是「删除」,是「剪切」。删掉的内容并没有蒸发,它躺在寄存器里,随时可以被 p 粘回来 —— 这既是福利(删了后悔有药),也是伏笔(第 9 章的「复制被删除顶掉」陷阱就从这来)。眼下你只需要知道:删掉的东西按 p 能再拿出来。
什么时候不该用 d?两个信号:①删完马上要打字 —— 换 c,一句话说完;②删的目的是「挪走」—— 直接规划成 d + p 的组合(下一节),别用 x 一个字符一个字符地抠。反过来,凡是「这段彻底不要了」,d + 大名词(dap、di{)是终点站,后面接 u 就是免费的回程票。
3. c 家族:删了就开工
c(change)和 d 只差一步:删完立刻进入插入模式。经验法则一句话:接下来要打字,就用 c;纯删除,才用 d。用 d 删完再按 i,等于把一句话拆成两句说。
看演示时盯住一个细节:cw 删词时不吃尾部空格(dw 才吃)。为什么?因为你删词是要接着打字的 —— 空格留下,新词直接顶上,排版天然正确。这是 Vim 里少见的「cw 特殊照顾」,也算语言的贴心之处(严格说 cw 从词中按起行为等同 ce:总是删到本词结尾)。
| 句子 | 读法 | 打包键 |
|---|---|---|
| cw / ciw | 改词(后者光标随处,第 4 章 ⭐) | — |
| c$ | 改到行尾 | C(大写打包) |
| cc | 清空整行重写 | S |
| ci( / ci" | 重写参数 / 重写字符串 | — |
| ct, | 改到逗号前 | — |
大写打包键家族可以串起来记:D = d$、C = c$、S = cc,再加上第 1 章的 A = $a、I = ^i —— 行尾、行首、整行,Shift 一下直达。它们不是为了省一个键,是为了让「打到行尾」变成一个单拍动作,节奏更顺。
从 d 换到 c,心理上要过的坎只有一个:你不再需要「删干净再进入插入」的两段式。传统编辑器的肌肉记忆是「选中 → 删除 → 打字」,三步各自为政;Vim 的 c 把后两步焊死成一步 —— 范围一旦圈定,光标已经就位、模式已经切换、就等你开口。练习时专门体会那个瞬间:ciw 按下去的下一毫秒,手不应该有任何停顿地开始打字。c 的节奏是一口气,断了就说明又回去想「删了多少」了。
4. y 家族:无痕的复制
y(yank,Vim 里「复制」的黑话)是三个主力动词里最安静的 —— 按下去屏幕上什么也不发生。这让新手很没安全感:「我复制了吗?」答案统一是:按对了就复制了,想看证据,第 9 章的 :reg 命令能打开寄存器查验。眼下先信任它:
y 的名词表和 d 完全同源 —— yw 复制词、y$ 复制到行尾、yy 复制整行、yiw 复制光标所在的词(第 4 章词典直接继承)、yi( 复制括号内全部。学动词不学搭配:动词认识名词库,搭配自动成立。
日常最高频的三连是:yiw(抓个词)→ 移动 → p(放下)。比如把一个变量名抄去别处、把参数列表复制到注释里当文档。黄金搭档 yiw + ciw + p 还能玩「用寄存器里的词替换当前词」,第 9 章展开。
复制要养成三个小习惯:①复制前先选好名词再按 —— y 无声,按错也不响铃,错了的复制会在粘贴时才爆雷;②复制行用 yy 而不是 y$ —— 前者是行形状(粘出来新起一行),后者是字符形状,粘贴行为完全不同;③大段复制宁可先 v 选中看一眼范围(第 7 章)再 y —— 复制是不可见的操作,可见的确认值得多花半秒。
5. p 与 P:行有行的粘法,字有字的粘法
p(paste)在光标后粘贴,P(大写)在光标前粘贴。但它粘贴的「形状」不由你决定,由寄存器里内容的形状决定:yy/dd 存的是「行」,粘出来就是新起一行;yw/dw/yiw 存的是「字符」,粘出来就插进当前行:
这个演示藏了两个日后天天用的「搬家技巧」:dd + p = 把当前行往下移一行(行序调整,比剪切板来回倒快得多);dw + P = 词序调整(把词搬到光标前)。本质都是「剪切 + 粘贴」= 移动 —— Vim 没有单独的「移动」命令,语言自己组合出来了。
| 按键 | 粘贴位置 | 行寄存器时 | 字符寄存器时 |
|---|---|---|---|
| p | 光标后 | 粘到下方成新行 | 插在光标字符之后 |
| P | 光标前 | 粘到上方成新行 | 插在光标字符之前 |
| 3p | 同上,×3 | 粘贴也吃计数:三份副本一次到位 | |
verison 的 i 和 s 换回来:光标放到 i 上,按 x(删掉 i)再 p(粘到后面)—— verison 变 version,两键修完一处笔误。同理 ddp 交换相邻两行、dwP 交换相邻词。「删 + 粘」的化学反应值得专门玩十分钟。
6. r 与 s:小改不打草稿
不是每次修改都值得「清范围 + 重打」。改一个字符,r(replace)连插入模式都不进:
r 后面跟一个字符,原地换掉光标处的字符,光标不动、模式不变、节奏不断。x1 变 x2、i 变 j,这类「只差一个字母」的场景它是绝对王者(还能 3r- 把三个字符换成 ---)。s(substitute)则是「删一个字符并顺势进入插入」,是 cl 的打包;S 上节已见过 = cc。选型口诀:换一个字符用 r,要接着打字用 s,成片修改回 c + 名词。
7. 大小写:~ 与 gU / gu
三个换挡动词:~ 翻转光标处一个字符(光标右移,可连按);gU 把名词变大写、gu 变小写 —— g 是前缀(第 2 章的 g_ 见过),后面接一个完整的动词-名词组合:
最值得练熟的是 gUiw:光标所在的词整个变大写 —— url 变 URL、api_key 风格的常量命名信手拈来(下划线不改,Snake Case 里逐段 gUiw + w 正好)。整行版是 gUU/guu。注意读法:gU 读「变大写」,它和 d 平级 —— 所以 gUiw 是标准的「动词 + i + 名词」句式,g 只是动词的姓氏。
8. 缩进与格式化:>> << ==
在 IDE 里写代码,缩进大多是被回车键自动带出来的;但改别人的代码、贴代码、删了外层块之后,缩进就乱了。三个动词专治:
>> 当前行右移一级、<< 左移一级(> 和 d 一样是等名词的动词 —— >i{ 缩进整个块、2>> 缩进两行,都是合法句);== 自动缩进当前行 —— 按语言规则摆正。在 IDE 里 = 背后调用的是编辑器/语言服务的格式化引擎,表现比纯 Vim 更聪明,放心用。想格式化整个文件,别想着 gg=G(虽然它确实行),直接用 IDE 的格式化快捷键更省心 —— 第 12 章会讲「Vim 管编辑、IDE 管工程」的分工哲学,这里是第一次预演。
9. J:把下一行拉上来
J(Join)把下一行合并到当前行尾,自动吃掉下一行的缩进、在连接处补一个空格;gJ 则原样拼接不补空格:
J 的高频场景:①别人代码里的无脑断行拼回去;②把两段字符串字面量拼成一个(配 J 还是 gJ 看引号里有没有空格);③写 markdown 时把软折行的段落并回一行。反向操作(一行拆两行)是 r+回车 —— 把某个字符原地换成换行,又见 r 的百变。
顺带交代一个家族惯例:J 不吃计数前缀?吃 —— 3J 把下面两行一起并上来。但在 IDE 里我更推荐单步 JJ 地按:合并是不可视的操作(你看不到下一行是什么就并了),一步一步按、每步看清再继续,比赌三行一次到位稳妥 —— 这是少数「宁慢勿快」的命令,快有 u 兜底,稳靠自己。
10. 毕业演出:三句话的重构
把本章所有零件组装起来,做一次真实的重构:函数 area(w, h) 参数名太吝啬,要改成 width, height,函数体同步更新。传统做法:选中、删、打、再选中、再删、再打…… 现在你说三句话:
数一下:第一句 ci((改内括号)重写签名;第二、三句 fw + ciw、fh + ciw(找旧名、改内词)同步函数体 —— 全程 15 个左右的按键,没有一次方向键、没有一次鼠标、没有一个多余字符。这就是「编辑即说话」的完成态:眼睛看到意图,嘴里是中文,手上是语法。
复盘这次重构用到的词法:名词两个(i(、iw,第 4 章),动词两个(c、隐含的 f 移动,第 2 章),连一个本章新词都没有 —— 但只有把「动词 + 名词」的公式内化成本能,这些零件才能在两秒内自动组装成句子。往后的章节会不断给你新词(v 选择的名词、/ 查找的名词、宏的自动化),而句子结构,永远只有这一条。
11. 每日训练计划(30 分钟 × 3 天)
| 天 | 时间盒 | 内容 | 通过标准 |
|---|---|---|---|
| 第 1 天 | 0–10 分钟 | 重放演示 1–3,读 §1–§3;靶场把 d/c 的名词各配 5 个 | cw 和 dw 的空格差异说得清 |
| 10–30 分钟 | 练习 1:三动词轮换 | 同一词上 diw/ciw/yiw 不假思索 | |
| 第 2 天 | 0–10 分钟 | 重放演示 4–6,读 §4–§6 | 能说出 p/P 行级字符级的判断规则 |
| 10–30 分钟 | 练习 2 + 练习 3 | dd+p 移行 10 次不卡壳 | |
| 第 3 天 | 0–10 分钟 | 重放演示 7–10,读 §7–§10,重点看毕业演出 | 能默写 capstone 的三句话 |
| 10–30 分钟 | 练习 4:盲测毕业考 | 12 题对 9 题,本章毕业 |
12. 如果本章只记住三件事
- 语法公式:
[数字] 动词 [数字] 名词—— 数字相乘、位置随便,动词 × 名词组合爆炸,你背的只有词,不是句子; - 要打字用 c,纯删用 d,搬运用 d+ p:剪切粘贴合起来就是「移动」,dd+p 移行、dw+P 移词、xp 修笔误;
- 小活用小工具:一个字符 r、大小写 gUiw、缩进 ==、并线 J —— 别动不动清一大片再重打。
下一章回到插入模式本身:进出的全部姿势、插入模式内的快捷键、替换模式 R —— 把「打字」这最后一公里也优化掉。
练习
练习 1:三动词轮换(10 分钟)
靶场任选 20 个标识符,每个上面连做三件事:diw → u;ciw 输入 foo → Esc → u;yiw → w → P → u。感受同一个名词在三个动词下的三种手感。通过线:手指不再在 d/c/y 之间犹豫。
练习 2:行搬运工(10 分钟)
找一段 15 行左右的代码,只用 dd + p(和 k/j 移动)把乱序的行排成你想要的顺序(比如把 import 全挪到顶部)。规则:全程禁用鼠标和 Cmd+X。体会「删行 = 剪切行」和「p 粘到下方」的组合 —— 十几分钟下来你对行级移动的恐惧会消失。
练习 3:大小写与缩进工坊(10 分钟)
①找 10 个全小写变量,逐个 gUiw 变大写,u 撤销;~ 连按翻转一个词。②把一段故意弄乱的缩进(你手动加空格)用 >>/<</== 修回整齐;再试试 >i{ 整块右移 —— 又一次「对象当名词」。
练习 4:盲测毕业考(10 分钟)
对着真实代码,12 个任务先说按键再验证:①删三个词 ②改两个词 ③删到行尾(两种按键)④清空整行重写(两种按键)⑤复制整行并粘到下面 ⑥把当前行下移一行 ⑦交换相邻两行 ⑧修一个笔误字母 ⑨变量名整个变大写 ⑩当前行自动缩进 ⑪合并下两行(补空格/不补各一次)⑫改某函数的参数列表。答案例:3dw/c2w/D 或 d$/cc 或 S/yyp/ddp/ddp/rp 或 xp/gUiw/==/J 与 gJ/ci(。12 对 9 毕业。
常见陷阱
VSCode / IDEA 差异
VSCode(VSCodeVim)
- 本章动词全家(d/c/y/p/r/s/~ / gU / >> / == / J)VSCodeVim 全部原生支持
- == 会调用语言服务的格式化(和 Shift+Alt+F 同源),格式化结果一致
- Cmd+c/v 与 y/p 默认各自为政:开了
vim.useSystemClipboard(第 1 章配置)后共用系统剪贴板,互不打架 - 整行移动有个原生对手 Alt+↑/↓ —— 和 ddp 二选一,顺手就行,但在纯 Vim 环境(远程/终端)只有后者永远在线
IntelliJ IDEA(IdeaVim)
- IdeaVim 同样全支持;.J 合并、gU 大小写这类冷门键也在线
- == 走 IDEA 的 Code Style 引擎;全文件格式化用 Cmd+Alt+L
- 重要分工:跨文件重命名千万别用 ciw,用 IDEA 的 Rename 重构(Shift+F6)—— 它改的是符号引用,不是文本。ciw 只管单文件内的字面改名
- IDEA 的 Cmd+D(Duplicate Line)与 yyp 等价,知道即可,继续用 Vim 侧保持手感统一
本章速记
| 按键 | 作用 | 按键 | 作用 |
|---|---|---|---|
N动词N名词 | 计数相乘,位置随便 | C / D / S | c$ / d$ / cc 打包键 |
| d / c / y | 删(=剪切)/ 改 / 复制 | rx / s | 换单字符 / 删一个顺势改 |
| p / P | 粘到后 / 前(形状随寄存器) | ~ / gUiw | 翻转一字符 / 词变大写 |
| yy + p | 复制行 + 粘下行 | >> / == | 缩进一级 / 自动缩进行 |
| dd + p | 当前行下移(搬家) | J / gJ | 并行(补/不补空格) |
一句话心法:数字 × 动词 × 名词 —— 想清楚要说什么,再动手;删即剪切,y 无痕,p 看形状。