跳到主要内容

09 综合练习:把编辑意图翻译成 Vim 操作

这一章不新增 vocabulary。目标是从“看命令,想作用”转为“看编辑意图,选择 Action 和 Target”。 请在可丢弃副本中完成任务;每一题都可能有多种正确操作。

先用一个已学过的组合确认练习方式:

Before — Normal Mode

const state = "draft";
^

Keys

ciwstatus<Esc>

After — Normal Mode

const status = "draft";
^

先核对文本、光标和最终 Mode,再解释这次操作的 Action 与 Target。正式练习的每一题都从下面代码的全新副本开始,避免前一题的修改影响后一题。

function buildLabel(user: User, options: LabelOptions) {
const prefix = "user";
const displayName = user.profile.name;
const fallback = "anonymous";
const primaryStatus = "pending";
const fallbackStatus = "pending";

return `${prefix}: ${displayName || fallback} (${primaryStatus || fallbackStatus})`;
}

Level 1:直接应用

  1. 从函数名开头移动到 options
  2. 移动到 displayName 的结尾。
  3. return 行定位到第一个 :
  4. 搜索 fallback,再返回前一个匹配项。

Level 2:组合

  1. buildLabel 改成另一个函数名。
  2. 分别修改参数名 options 和类型 LabelOptions
  3. 删除函数参数列表中的全部内容,但保留圆括号。
  4. 删除 return 后到行尾的内容。
  5. Yank 整个 const fallback 行,并在函数体中另一个位置 Put 一份。
  6. 删除 profile 这个单词。

Level 3:表达意图

下面只描述目标,不给出命令:

  1. 修改 "anonymous" 中的内容,但保留双引号。
  2. 删除模板字符串 ${...} 内部的一个对象,但保留花括号。
  3. 把参数列表中的内容替换成一个新参数,同时保留圆括号。
  4. 将两处 "pending" 改成同一个新值:先完成第一处,再在下一处重放。
  5. 删除连续两个 word;先决定 Count 应放在哪里,再执行。

对照答案的方式

先写下你的意图:

Action:
Target:
Control:

再检查结果是否符合任务。参考思路可以是:

修改单词        → change + inner word
清空括号内容 → delete + inside parentheses
Yank 一整行 → yank + line target
重复同一修改 → move + .

不要把这组思路当作唯一按键答案。若你的操作保留了要求保留的文本、得到正确结果,并能解释选择的 Target, 它就是有效答案。

完成标准

完成后,你应能解释:

  • 为什么 di( 不必被当作独立快捷键;
  • cwdw 为什么不应简单视为完全对称;
  • 什么时候应该用 Count,什么时候应该用 .
  • 删除为何可能覆盖刚刚 Yank 的 unnamed Register;
  • 当一个操作范围不确定时,为什么可以先用 Motion 或 Search 定位,再执行编辑。

如果某项仍需要反复查表,回到对应章节做一个新的 Before / Keys / After 小练习。Vim 的熟练来自多次 可观察的正确重复,而不是一次背完所有命令。

评论