Overview

本视频([00:00])是“Missing Semester”课程的第三讲,其核心论题是:对于程序员而言,文本编辑器是至关重要的工具,而 vim 是一款设计精良、功能强大且影响深远的模态编辑器 [03:06]。视频的结论是,尽管 vim 存在一定的学习曲线 [01:26],但其独特的“模态编辑”理念 [04:52] 和“将接口视为编程语言”的设计哲学 [19:32],使得程序员一旦熟练掌握,就能极大提升编辑效率,实现“以思考的速度编辑代码” [20:16]。视频强烈建议投入时间学习 vim,因为这种投资将在整个职业生涯中带来巨大的回报 [00:12, 48:03]。

按照主题来梳理

主题一:为什么选择 Vim?—— 程序员的编辑器哲学

本讲座首先探讨了为什么程序员需要专门的文本编辑器 [00:30]。与撰写普通文章(如使用 Microsoft Word)不同,编程涉及大量非线性的活动:阅读代码、在文件各处导航、以及进行小范围的精确修改 [00:37]。因此,为编程而设计的编辑器(如 vim, Emacs, VS Code 等)针对这些活动进行了优化。

讲座选择了 vim 作为教学工具,原因有三 [03:12]:

  1. 讲师的偏好与经验:所有讲师都长期使用 vim 作为主要编辑器,并对其效果非常满意 [03:17]。

  2. 核心思想的价值vim 背后蕴含着许多有趣且强大的设计思想 [03:23]。即使学习者未来不以 vim 为主,理解这些思想本身也极具价值。

  3. 广泛的影响力vim 的理念非常成功,以至于许多其他流行的工具都支持“vim 仿真模式” (vim emulation mode) [03:35]。例如,VS Code 中(当时)最流行的 vim 插件已有约 140 万次下载 [03:43]。这种模式还存在于 Shell、Python REPL、Jupyter Notebook 甚至浏览器中 [03:56]。

讲座强调了学习 vim 的心态 [01:02]:

  • 克服初期障碍:刚开始切换到 vim 这样的复杂工具时,效率可能会暂时下降 [01:26]。

  • 坚持投入:讲师估计,大约需要 20 小时的编程练习,学习者就能恢复到原来的编辑速度 [01:38]。

  • 终身学习vim 易于上手基础,但需要“一生去精通” (a lifetime to master) [01:49]。关键在于,当感觉操作效率低下时,要主动查找更好的方法(例如使用 Google 或寻求帮助)[02:01],因为这些工具是“程序员为程序员编写的” [02:05],你遇到的问题几乎总有现成的解决方案。

主题二:Vim 的基石 —— 模态编辑 (Modal Editing)

vim 最核心且最与众不同的理念是“模态编辑” [04:52]。这意味着编辑器有多种操作“模式” (mode),每种模式下,键盘按键的含义完全不同 [04:54]。这是基于“编程时会做不同类型事情”的观察(如阅读、小幅修改、大量输入)[05:00]。

视频中介绍了几个关键模式 [05:28, 07:23]:

  • Normal Mode (普通模式)

    • 这是 vim 启动时的默认模式 [05:28]。

    • 此模式下,你按下的键不会输入文本,而是被解释为“命令” [07:07],用于导航(如上下左右移动)、编辑(如删除、复制)等。

    • 讲师强调,这是你花费大部分时间的地方,是 vim 的“家” (home) [39:41]。

  • Insert Mode (插入模式)

    • 这个模式最接近我们熟悉的普通编辑器(如记事本)[07:01, 11:04]。

    • 在此模式下,按下的键会直接输入到文本缓冲区 [11:09]。

    • 如何进入:在 Normal Mode 按 i (insert) 键 [05:48, 11:14]。进入后,左下角会显示 -- INSERT -- [11:20]。

    • 如何退出:按 Esc 键返回 Normal Mode [05:56, 11:46]。

  • Command-line Mode (命令行模式)

    • 用于执行更复杂或偏向“文件级”的操作,如保存、退出、搜索替换、打开帮助等 [12:23]。

    • 如何进入:在 Normal Mode 按 : (冒号) 键 [08:12, 12:28]。光标会跳转到底部命令行。

    • 如何退出:按 Esc 键返回 Normal Mode [13:05]。

  • Visual Mode (可视化模式)

    • 用于“选择”文本块 [31:11]。

    • 如何进入

      • v:进入标准的 Visual Mode,用于选择字符流 [31:25]。

      • V (大写 V):进入 Visual Line Mode,用于整行选择 [32:12]。

      • Ctrl-v:进入 Visual Block Mode,用于选择矩形文本块 [32:18]。

  • Replace Mode (替换模式)

    • 如何进入:在 Normal Mode 按 R (大写 R) [07:52]。

    • 此模式下,输入会覆盖(替换)光标下的字符,而不是插入 [07:27]。

由于 Esc 键在模式切换中至关重要 [08:40],而它在现代键盘上位置偏僻,许多 vim 用户会重映射 (rebind) Caps Lock (大写锁定键) 来充当 Esc,因为它在主行 (home row) 上,更易于访问 [08:50]。

主题三:Vim 基础操作 —— 启动、保存与 Buffer 概念

掌握了模式切换后,你需要知道如何执行最基本的文件操作。这通常在命令行模式(按 :)下完成:

  • 启动 Vim:在 shell 中输入 vim 启动程序 [09:28],或输入 vim <filename> (如 vim editors.MD) 来打开特定文件 [10:07]。

  • 保存文件 (Write):输入 :w [14:19]。w 代表 write (写入)。

  • 退出 (Quit):输入 :q [13:15]。

  • 保存并退出:可以组合使用 :wq

  • 强制退出:如果文件已修改但不想保存,需使用 :q! (强制退出)。

  • 获取帮助 (Help):输入 :help [14:50]。可以查询特定命令,如 :help :w 查询 :w 命令的用法 [15:04],或 :help w 查询 w 键(在 Normal Mode 下)的用法 [15:25]。

讲座还澄清了 vim 中一个独特且重要的概念:Buffer (缓冲区)、Window (窗口) 和 Tab (标签页) 的关系 [17:09]。

  • Buffer (缓冲区):是内存中打开的“文件” [17:30]。

  • Window (窗口):是显示 Buffer 的“视口”。

  • Tab (标签页):是 Window 的集合 [17:41]。

与 VS Code 或 Sublime Text 不同,vim 中的 Buffer 和 Window 不是一一对应的 [17:46]。你可以在一个 Tab 页中打开多个 Window(例如通过“分屏” [17:58]),并且多个 Window 可以显示同一个 Buffer [18:02]。这非常有用,比如你可以同时查看一个文件的顶部(如 import 语句)和底部(你正在编辑的代码)[18:12]。

主题四:Vim 的核心 —— 将接口视为编程语言

这是本讲座最核心的理念 [19:32]:Vim 的 Normal Mode 本身就是一种编程语言 [19:46]。

你不是在“操作”编辑器,而是在“编程”编辑器。你通过组合不同的“命令”(按键)来构建复杂的编辑操作 [19:54]。一旦形成肌肉记忆,你就能以极高的效率编辑 [20:16]。

这种“语言”由几个基本构件组成:

构件一:Movement (移动/导航)

这是 vim 语言中的“名词”或“范围”,它们定义了操作的“对象”。

  • 基本移动

    • h (左), j (下), k (上), l (右) [20:42]。讲师建议使用这四个键(在主行上)替代方向键,以减少手部移动 [20:47]。
  • 词汇移动

    • w (word):移动到下一个的开头 [21:47]。

    • b (backward):移动到上一个的开头 [21:52]。

    • e (end):移动到当前的末尾 [21:59]。

  • 行内移动

    • 0 (零):移动到当前行的行首(第 0 列)[22:15]。

    • $ (美元符号):移动到当前行的行尾 [22:15]。

    • ^ (脱字符):移动到当前行第一个非空字符 [22:19]。

  • 行间移动(文件级)

    • gg:移动到文件的第一行 [23:20]。

    • G (大写 G):移动到文件的最后一行 [23:20]。

    • Ctrl-d (down):向下滚动半页 [22:58]。

    • Ctrl-u (up):向上滚动半页 [22:58]。

  • 查找移动

    • f{char}:(Find) 移动到当前行下一个出现的 {char} 字符上 [24:17]。例如 fo 会跳到下一个 ‘o’。

    • t{char}:(To) 移动到当前行下一个 {char} 字符的前一个位置 [24:48]。

    • F{char}T{char}:功能同上,但方向是反向查找 [24:41]。

  • 搜索移动

    • / {pattern}:(Search) 按下 / 后输入搜索词并回车,光标会跳转到第一个匹配项 [39:11]。

    • n (next):跳转到下一个匹配项 [40:02]。

构件二:Edit (编辑操作)

这是 vim 语言中的“动词” (Operators),它们定义了要“做什么”。

  • i (insert):在光标进入 Insert Mode [25:43]。

  • o (open):在光标下方打开一个新行,并进入 Insert Mode [26:09]。

  • O (大写 O):在光标上方打开一个新行,并进入 Insert Mode [26:29]。

  • x:删除光标下的单个字符 [28:44]。

  • r{char} (replace):替换光标下的单个字符为 {char} [28:56]。

  • u (undo):撤销上一步操作 [29:15]。

  • Ctrl-r (redo):重做(恢复)上一步的撤销 [29:30]。

  • . (点):重复上一次的编辑命令 [41:06]。这是一个极其强大的命令,用于自动化重复任务。

构件三:Operators (操作符) + Compositions (组合)

vim 强大的地方在于,许多“动词”(编辑操作)可以和“名词”(移动)组合起来,形成“动宾短语”。

  • d (delete):删除 [26:44]。它本身不做什么,它在等待一个“移动”命令来告诉它要删除_什么_。

    • dwd (删除) + w (一个词) = 删除一个词 [27:03]。

    • ded (删除) + e (到词尾) = 删除到词尾 [27:29]。

    • d$d (删除) + $ (到行尾) = 删除到行尾

    • dd:当动词重复两次时,通常作用于“整行” [28:25]。dd = 删除整行

  • c (change):修改 [27:39]。它类似 d,但执行后会自动进入 Insert Mode,方便你立即输入新内容 [27:48]。

    • cwc (修改) + w (一个词) = 修改一个词(删除该词并进入插入模式)[43:18]。

    • cec (修改) + e (到词尾) = 修改到词尾 [27:53]。

    • c$c (修改) + $ (到行尾) = 修改到行尾

    • cc修改整行(删除整行并进入插入模式)[28:30]。

  • y (yank):复制 [30:28]。yank (猛拉) 是 vim 中“复制”的术语 [30:36]。

    • ywy (复制) + w (一个词) = 复制一个词 [31:00]。

    • yy复制整行 [30:49]。

  • p (paste):粘贴 [30:36]。将在光标粘贴 yd 操作的内容(d 删除的内容也会被放入剪贴板)[30:49]。

构件四:Count (计数)

这是 vim 语言中的“数字”,用于指定动作的重复次数 [33:07]。

  • 4j4 (计数) + j (向下) = 向下移动 4 行 [33:32]。

  • 7dwd7w7 (计数) + dw (删除一个词) = 删除 7 个词 [34:02]。

  • 3e3 (计数) + e (到词尾) = 移动 3 个词的词尾 [33:53]。

构件五:Modifier (修饰符)

这是 vim 语言中的“介词”,它们与 a (around) 和 i (inside) 配合使用,用于操作“文本对象” (text objects),如括号、引号等 [34:59]。

  • i (inside):表示“内部” [35:06]。

  • a (around):表示“周围”(包含文本对象本身)[35:06]。

假设光标在 (hello world) 的中间:

  • di(d (删除) + i (内部) + ( (括号) = 删除括号内的内容 (即 “hello world”),保留括号 [36:38]。

  • da(d (删除) + a (周围) + ( (括号) = 删除括号及内部的所有内容 (即 “(hello world)”) [36:55]。

假设光标在 [link text] 的中间:

  • ci[c (修改) + i (内部) + [ (方括号) = 修改方括号内的内容 [36:02]。vim 会删除 “link text”,并让你进入 Insert Mode。

主题五:实战演示 —— 修复 FizzBuzz

讲座通过一个修复有问题的 FizzBuzz 程序的实例 [37:40],演示了上述“语言”的流畅组合。

  1. 问题main 函数未被调用。

    • 操作G (跳到文件末尾) -> o (在下方打开新行) -> (输入 main() 等) -> Esc (返回 Normal Mode) [38:24]。
  2. 问题:循环从 0 开始,应为 1 到 limit+1

    • 操作/range (搜索 “range”) -> Enter (跳转) -> ww (移动两个词到 limit) -> i (插入) -> (输入 1, ) -> Esc -> e (到 limit 词尾) -> a (在词后附加) -> (输入 +1) -> Esc [39:00]。
  3. 问题:打印 “fizz” 的地方应为 “fizzbuzz”。

    • 操作/fizz (搜索 “fizz”) -> Enter -> n (跳转到下一个) -> e (到 “fizz” 词尾) -> ci" (Change Inside Quotes,修改引号内的内容) -> (输入 fizzbuzz) -> Esc [40:02]。
  4. 问题:打印 fizzbuzz 时应在同一行。

    • 操作:(移动到 print("fizz") 行) -> $ (到行尾) -> i (插入) -> (输入 , end="") -> Esc [40:51]。

    • 亮点:(移动到下一行 print("buzz")) -> . (点命令) [41:06]。vim 自动重复了上一步的 i, end=""<Esc> 操作,极大地提高了效率。

  5. 问题limit 硬编码为 10,应改为命令行参数。

    • 操作gg (到文件顶部) -> O (在上方打开新行) -> (输入 import sys) -> Esc [41:36]。

    • 操作/10 (搜索 “10”) -> Enter -> ci( (Change Inside Parentheses,修改括号内的内容) -> (输入 int(sys.argv[1])) -> Esc [41:52]。

主题六:Vim 的定制化与扩展

vim 不仅接口是可编程的,它本身也是高度可配置的 [44:19]。

  • 配置文件 (.vimrc)

    • 这是一个位于用户主目录下的纯文本文件 (~/.vimrc) [44:38]。

    • 你可以在其中设置各种选项,如开启语法高亮 (syntax on)、显示行号 (set number) [45:05]、设置缩进等。

    • 讲座提供了推荐的基础配置链接 [44:55],并鼓励查看他人的 .vimrc 文件以获取灵感 [45:42]。

  • 插件 (Plugins)

    • vim 可以通过插件扩展功能 [45:48]。

    • 例如,实现模糊文件搜索 (fuzzy file finding) [45:53]、可视化撤销树 (undo history) [46:06]、文件浏览器 [46:14] 等。

框架 & 心智模型 (Framework & Mindset)

心智模型:克服“效率深谷” (The Productivity Dip) 的投资心态

视频建立了一个关于学习复杂工具(如 vim)的清晰心智模型,其核心是“短期投资换取长期回报” [00:17]。

  • 认识“效率深谷”

    • 当你从熟悉的工具(如 VS Code 搭配鼠标)切换到 vim 时,你的效率几乎必然会立即下降 [01:26]。这是因为 vim 的操作逻辑(模态编辑、纯键盘驱动)与你过去的肌肉记忆完全相悖。

    • 在这个阶段,你会感到沮丧,用 vim 完成简单任务的速度可能比原来慢得多。

  • 跨越“盈亏平衡点”

    • 讲师给出了一个具体的预估:坚持使用 vim 进行约 20 小时的实际编程 [01:38]。

    • 在这 20 小时内,你的目标不是“高效”,而是“熟悉”。你需要刻意练习,将 i/Esc 的切换、hjkl 的移动、d/c/y 的组合内化。

    • 达到这个“盈亏平衡点”后,你的 vim 编辑速度将追平你使用旧工具的速度 [01:43]。

  • 享受“复利效应”

    • 一旦越过 20 小时的门槛,真正的收益才刚开始 [01:43]。

    • 你对 vim “语言”的掌握会越来越熟练,你会发现自己组合命令的速度越来越快。你将开始体会到“以思考的速度编辑” [20:16],因为你的手不需要离开键盘主行,你思考“删除这个词” (dw) 和你执行它几乎是同步的。

    • 这种效率提升是持续的。你每学会一个新的技巧(如 . 重复、ci" 修改引号内内容),你的效率都会再次提升。

  • 采用“持续改进”的元认知

    • vim 的学习是“a lifetime to master”(需要一生去精通) [01:49]。

    • 关键的心态是:当你感觉自己正在用一种低效的方式做事时,停下来 [02:01]。

    • 问自己:“一定有更好的方法” (there is a better way) [02:05]。然后去搜索(Google、:help)。

    • 例如,你可能在重复按 xxxx 来删除 4 个字符,当你意识到这一点时,你应该停下,去查找,然后学会 4xdw。这个“发现并改进”的循环是 vim 学习的核心。

框架:Vim 的“命令语法”—— 一门微型编程语言

视频中最重要的框架,就是将 Normal Mode 的操作视为一种具有明确语法的“编程语言” [19:38, 25:06]。理解这个语法是精通 vim 的关键。

这个语言的基本“句子结构”可以被抽象为:

[Count] [Operator] [Modifier/Motion]

(计数) + (操作/动词) + (修饰符/移动/名词)

我们来拆解这个框架:

  • 1. [Motion] (移动/名词):最简单的句子

    • 一个单独的 Motion(移动)命令本身就是一个完整的句子,意思是“移动光标”。

    • j -> “向下移动一行。” [20:55]

    • w -> “移动到下一个词。” [21:47]

    • $ -> “移动到行尾。” [22:15]

  • 2. [Count] + [Motion] (计数 + 移动)

    • 这是给“名词”加上了数量,使其成为复数。

    • 4j -> “向下移动行。” [33:32]

    • 3w -> “向前移动个词。” [33:53]

  • 3. [Operator] + [Motion] (操作 + 移动):核心的“动宾结构”

    • 这是 vim 语言中最常见的句式。“Operator”(操作符/动词)指定_做什么_,“Motion”(移动/名词)指定_对谁做_。

    • 动词 d (delete):

      • dw -> “删除 (d) 一个词 (w)。” [27:03]

      • d$ -> “删除 (d) 到行尾 ($)。”

    • 动词 c (change):

      • ce -> “修改 © 到词尾 (e)。” [27:53]

      • c/foo -> “修改 © 到下一个 “foo” 出现的地方 (/)。”

    • 动词 y (yank):

      • yw -> “复制 (y) 一个词 (w)。” [31:00]
    • 动词 v (visual): (严格来说 v 是进入另一种模式,但其组合逻辑类似)

      • vw -> “选中 (v) 一个词 (w)。” [31:41]
  • 4. [Operator] + [Operator] (操作 + 操作):作用于“行”的特殊句式

    • 当一个操作符重复两次时,它通常(但不总是)表示“对当前整行执行操作” [28:25]。

    • dd -> “删除 (d) 整行 (d)。” [28:25]

    • cc -> “修改 © 整行 ©。” [28:30]

    • yy -> “复制 (y) 整行 (y)。” [30:49]

  • 5. [Count] + [Operator] + [Motion] (计数 + 操作 + 移动):完整的复杂句子

    • 这是将所有元素组合起来,形成精确而高效的命令。

    • 7dw -> “删除 (d) 接下来的七 (7) 个词 (w)。” [34:02]

    • 2cc -> “修改 © 当前行及下一行,共两 (2) 行 ©。”

  • 6. [Operator] + [Modifier] + [Text Object] (操作 + 修饰符 + 文本对象):更高级的“介词短语”

    • 这是此语言框架的精髓。[Modifier] (修饰符, 即 ia) 充当“介词”(如 “in” 或 “around”),而 [Text Object] (如 (, [, ") 充当“宾语”。

    • 动词 c (change):

      • ci( -> “修改 © 在…内部 (i) 的括号 (()。” [41:52]

      • ci" -> “修改 © 在…内部 (i) 的引号 (")。” [40:09]

    • 动词 d (delete):

      • da[ -> “删除 (d) 周围 (a) 的方括号 ([)。” (连同方括号一起删除) [36:55]

      • di{ -> “删除 (d) 在…内部 (i) 的花括号 ({)。”

通过这个“语言框架”来思考,vim 就不再是一堆孤立的快捷键,而是一个具有内在逻辑、可组合、可预测的强大系统。你的目标就是学会这个语言的“词汇”(各种 Motions 和 Operators)和“语法”(组合规则),最终实现“说出”命令(ci")来替代“手动选择并删除再按下插入”的繁琐操作。