日拱一卒,麻省理工YYDS,一节课让我学会用vim

语言: CN / TW / HK

大家好,我是梁唐。

今天我们继续聊聊麻省理工的missing smester,消失的学期,讲解那些不会在课上提及的工具和技术。

这一节课主要讲的是vim编辑器的一些使用技巧,老实讲vim我也经常使用,但也没有专门花时间来好好学习一下它的语法,只是简单了解一些基本的用法。这一节课上完之后感觉受益匪浅,就像是老师说的一样,这节课最大的目的其实不是传授多少vim的使用诀窍,而是让大家get到vim的设计理念,并且感受到使用它的魅力。

非常建议大家去听一下这节课,B站有中文字幕的精校版,不用担心英语不好听不懂的问题。老实讲这个老师的语速还是挺快的,感觉像开了1.5倍速……

B站课程链接

和之前的课程一样,这节课也有非常详细的笔记。

笔记链接

那么就让我们话不多说,日拱一卒,开始今天的学习吧。

Editors (Vim)

编写英文文本和写代码是完全不同的行为,编程的时候,你会花时间在文件当中切换,阅读代码,搜索一些内容,并且参考一些内容进行编辑。所以为了编写代码开发一些工具或功能是非常有必要的(比如微软开发了vscode)。

作为程序员,我们大部分的时间都花在了编码上。所以花一些时间去掌握一些编辑工具和编辑技巧是非常有帮助的。你应该这样学习一门新的编辑器:

  • 从教程开始(在这门课上我们会提供一些资源)
  • 在你所有写代码的环境中坚持使用(即使刚开始的时候可能会降低编码速度)
  • 一边执行一边查阅和学习:当你感觉存在更好的方式时,很有可能的确有

如果你遵守上述的方法,完全坚持使用新的编辑器来编写所有的代码。那么你的学习过程可能是这样的:刚开始的一两个小时,你会学习最基础的功能,比如打开、编辑、保存和退出,检查缓存。当你花费了20个小时之后,你将会和使用你之前的编辑器一样快。在之后,好处就体现出来了:你将会拥有充足的知识以及肌肉记忆,新的编辑器将会大大节约你的时间。

现代的文本编辑器都非常好用且强大,所以学习永不止步,当你学得越多,你会变得越快。

学习哪个编辑器?

程序员往往对于他们使用的文本编辑器有着很强的执念。

当下哪一个编辑器最流行?你可以参考一下Stack Overflow的调查(当然这会存在一些偏差,毕竟Stack Overflow的用户不能代表所有程序员)。

vscode是最欢迎的编辑器,而vim是命令行编辑器当中最受欢迎的。

Vim

这门课所有的教程都是基于vim编辑器的。vim拥有非常漫长的历史:它源自于Vi编辑器(1976),并且它至今仍然被持续更新。Vim背后的原理非常机智,因此,很多工具都支持Vim模式。比如140万用户在vscode上安装了Vim仿真。即使你最终会选择其他的文本编辑器,Vim也同样值得学习。

显然在一节50分钟的课上是不可能讲完所有Vim的功能的,所以我们将会聚焦在vim背后的运行哲学上。仅仅教授你们基础,展示你们一些强大、先进的功能,然后给你们资料让你们自己掌握它。

Vim的设计哲学

在编程的时候,你在阅读和编辑上花费的时间是最多的,而不是编写。正因此,Vim是一个模式化的编辑器:它针对插入文本和控制文本拥有不同的模式。Vim是可编程的(支持Vimscript以及其他语言,比如Python),并且Vim的界面本身就是一门编程语言:按键就是命令,并且这些命令是可组合的。Vim拒绝使用鼠标,因为这样太慢了,甚至Vim拒绝使用小键盘,因为这需要你的手移动太长的距离。

最终的结果就是,这门编辑器可以使得你的手速跟上你的思考速度。

模式化编辑

vim的设计理念是大佬的程序员的时间被花在了阅读,导航和做小的修正上,而不是大段的编码上。因此,vim拥有多种操作模式:

  • Normal:在文件中移动光标以及做修改
  • Insert:插入文本
  • Replace: 替换文本
  • Visual(plain,line,block):选择文本块
  • Command-line:运行命令

同样的按键在不同的模式下可能拥有不同的含义,比如x在insert模式下是插入字符x,而在normal模式下,它将会删除光标之后的一个字符,在visual模式下,它会删除选中的内容。

在默认设置中,vim会在左下角展示当前模式,默认模式是normal模式。你大部分时间将花在normal和insert模式中。

你可以通过按下键从其他模式回到normal模式。normal模式中按下 i 进入inset模式,按下 R 进入replace模式, v 进入visual模式, V 进入visual line模式, 进入visual block模式(Ctrl-V,有时候写成^V),按下 : 进入command-line模式。

在vim当中你将会经常用到案件,所以你可以考虑将它映射到Caps Lock来方便按键。Mac电脑可以在键盘-修饰键当中设置:

基础

输入文本

从Normal模式按下i进入insert模式。此时vim会像其他编辑器一样,直到你按下 回到normal 模式。

记住这一点之后,你就已经具备了使用vim的基本知识了。

Buffers, tabs, and windows

Vim维护一系列打开的文件,被称为buffer。一个vim的会话将会包含多个tab,每一个拥有一系列窗口(分体式窗格),每一个窗口展示一个buffer。

和其他你熟悉的程序不同,窗口和buffer不是一对一的。比如在网页浏览器当中,一个窗口只会有一个buffer。窗口仅仅是用来呈现的,一个buffer可以在多个窗口中展示,甚至是一个tab中的多个窗口。有时候这会很有帮助,比如说当你需要参考同一个文件中的其他部分来编码时。

打开vim时,默认只会开启一个tab,并且只包含一个窗口。

命令行

按下: 可以进入命令行模式,你的光标将会跳转到屏幕最下方的命令行当中。这个模式拥有需多功能,比如打开、保存以及关闭文件,还有退出Vim。

  • :q 退出(关闭窗口)
  • :w 保存
  • :wq 保存和退出
  • :e {name of file} 打开文件
  • :ls 展示打开的buffer
  • :help {topic} 打开帮助

  • :help :w 开启:w 命令的帮助

  • :help w 开启w按键的帮助

Vim的界面就是编程语言

Vim最重要的理念就是vim的界面本身就是一门编程语言。按键就是命令,并且命令之间可以组合。这就让我们可以非常便捷地移动以及编辑,尤其是当命令成为我们肌肉记忆之后。

移动

你通常在Normal模式中花费时间最多的可能是移动光标,移动命令就是用来移动光标的。移动命令英文称为movements,在vim中也被称为名词(nouns),因为它们指的是大块的文本。

  • 基础移动:hjkl(左下上右)
  • w (下一个单词),b(单词开头),e(单词结尾)
  • 0(行开头),^(该行第一个非空位置),$(行尾)
  • H (屏幕最上方),M(屏幕中间),L(屏幕底部)
  • 翻页:Ctrl-u(向上翻页),Ctrl-d(向下翻页)
  • gg(文件开头),G(文件结尾)

  • {数字}<回车>(命令行模式)或{数字}G 跳转到行号

  • %,括号跳转到与之配对的另一个括号处
  • f{字符}, t{字符}, F{字符}, T{字符}。光标跳转到字符位置,f向后查找,F向前查找,t向后查找,移动到指定字符前,T向前查找,移动到指定字符后
  • 搜索:/{regex},n向后找下一个匹配,N找向前一个匹配

选择

选择模式:

  • visual:v
  • visual line: V
  • visual block: Ctrl-v

可以用来移动光标选择文本

编辑

所有你之前需要通过鼠标完成的功能你现在都可以通过键盘使用一系列移动命令以及组合来完成。从现在开始,Vim看起来像是一个编程语言了。Vim的编辑命令被称为verbs(动词),因为动词作用在名词上。

  • i 进入insert 模式

    • 对于修改和删除文本,我们会使用一些其他命令,而不是删除键
  • o / O 插入新的一行,o 插入在下方, O插入在上方

  • d{motion} 根据motion指令进行删除

  • 比如dw 删除一个单词, d$删除直到行尾的所有内容,d0删除该行开头的内容

  • c{motion} 根据motion执行修改

  • 比如cw 修改单词

  • 和d{motion}类似,只不过会进入编辑模式

  • x 删除一个字符(等价于dl)

  • s 替代一个字符(等价于xi)
  • visual 模式 + 操作

  • 选择文本,d删除,c修改

  • u 撤销, redo

  • y 拷贝
  • p 粘贴
  • 除此之外还有很多,比如 ~翻转字母大小写

Counts

你可以使用一个整数将名词和动词操作连接起来,实现重复执行若干次某个命令的效果

  • 3w 向前移动3个单词
  • 5j 向下移动5行
  • 7dw 删除7个单词

Modifiers

你可以使用修改器来修改名词的含义,比如i,意味着里面(inside),a意味着 around。

  • ci( 修改 () 括号里的内容
  • ci[ 修改 [] 括号里的内容
  • da' 删除引号里的字符串,包括引号

Demo

这是一个有bug的fizz buzz程序。

我们需要修正以下问题:

  • main函数没有被调用
  • range从1开始而非从0开始
  • 对于15的倍数,在同行输出fizz和buzz
  • 对于5的倍数输出buzz
  • 不应该使用固定的参数10,而应该使用系统参数

这个部分建议大家去看一下视频当中老师的演示去实际体验一下,看看使用了vim之后,我们修改代码会变得有多么方便,光看说明可能体会不到。

自定义 Vim

vim通过~/.vimrc文件来进行配置和自定义,有许多基础的设置你需要开启。

我们提供了一个详细说明的配置文件,你可以使用它作为开始。我们推荐你使用它,因为它修复了vim当中的一些古怪的设置。你可以访问原始文档进行下载,并将下载内容保存在你的~/.vimrc下。

vim的自定义非常丰富,因此非常值得花时间进行探索。你可以在GitHub上看到很多激动人心的配置,除此之外还有很多的博客,不要仅仅复制粘贴其他人的配置文件,阅读一下,弄懂它,选择那些你需要的。

Vim拓展

vim也有非常丰富的拓展插件,和一些过时的建议中说的不同,你并不需要为vim设置插件管理器(因为vim8.0)。相反,你可以使用内置的包管理系统。只需要创建一个目录~/.vim/pack/vendor/start/,然后将插件放在那里,比如通过git。

下面是一些我们非常喜欢的插件:

我们尽量不列举太多的插件,你可以登录Vim Awesome网站查看关于Vim的一些非常使用的插件。那里有成千上万的vim插件,你可以搜索topic:best Vim plugins

进阶 Vim

接下来展示一些vim的强大特性,由于篇幅太多,所以不可能全部讲完,只能介绍一部分。

搜索和替换

:s (subsitute) 命令

  • %s/foo/bar/g

  • 在文件中将foo全局替换成bar

  • %s/[.]((.))/\1/g

  • 将所有Markdown中的链接替换成纯URL

多窗口

  • :sp / :vsp 分隔窗口
  • 一个buffer可以出现在多个窗口中

  • q{character}开始录制一个宏到寄存器{character}中
  • q 停止录制
  • @{character} 执行刚刚录制的宏
  • 当出现错误时宏执行会停止
  • {number}@{character} 会将宏重复执行{number}次
  • 宏可以递归执行

  • 首先,清楚寄存器当中的宏 q{character}q

  • 记录宏,在宏中递归调用@{character} (不会生效,因为录制还没有完成)

  • 样例:将xml转成json

  • key是name和email的对象数组

  • 使用Python程序吗?
  • 使用 sed / 正则表达式吗?

    • g/people/d
    • %s//{/g
    • %s/(.*)<\/name>/"name":"\1",/g
    • ...
  • vim 命令和宏

  • Gdd, ggdd删除头尾两行
  • 创建宏处理单个元素(寄存器e)

    • 跳转去往 所在行
    • qe^r"f>s": "<ESC>f<C"<ESC>q
  • 处理person的宏

  • 处理person,并且去往下一个person的宏

  • 执行宏,直到文件末尾

  • 手动删除最后的逗号,并且加上[] 分隔符

我照着老师给的命令尝试了一下,真的很快就全部都改好了,比sublime的批量修改还要快。

img

唯一的缺点就是命令看起来不是很直观,需要花一点时间理解。

资源

  • vimtutor是一个vim教程, 只要安装了vim就有,直接使用命令vimtutor即可打开
  • Vim Adventures 是一个学习vim的游戏
  • Vim Tips Wiki
  • Vim Advent Calendar 拥有一系列vim的tip
  • Vim Golf是一个代码高尔夫,使用vim ui比谁完成修改使用的命令更少
  • Vi/Vim Stack Exchange
  • Vim Screencasts
  • Practical Vim(书籍)

Exercises

  • 完成vimtutor,注意:它在80x24的终端窗口看起来最舒服
  • 下载我们的vimrc (https://missing.csail.mit.edu/2020/files/vimrc),并且将它保存在你的~/.vimrc中。将我们的注释都读一遍,观察一下配置前后vim窗口的变化
  • 安装和配置插件:ctrlp.vim

  • 创建路径:mkdir -p ~/.vim/pack/vendor/start

  • 下载插件:cd ~/.vim/pack/vendor/start; git clone https://github.com/ctrlpvim/ctrlp.vim
  • 阅读插件的文档,尝试使用CtrlP去寻找项目路径中的文件,使用命令:CtrlP
  • 在你的~/.vimrc中配置你的CtrlP,使得你可以通过快捷键Ctrl-P打开

  • 为了练习Vim,在你的机器上重新做一下课程中的Demo(Python代码片段)

  • 在接下来的一个月使用vim作为你的文本编辑器。无论它刚开始的时候用起来有多么不顺畅,或者当你觉得有更好的方法时,尝试着去谷歌一下。
  • 继续自定义你的~/.vimrc,并且安装更多的插件
  • (进阶)将XML转化成json (https://missing.csail.mit.edu/2020/files/example-data.xml),尝试着使用vim的宏亲自做一下。如果你被难住了,可以参考一下上面关于宏的内容

这一次课程没什么实际的问题,大部分内容都是让我们配置vim并且亲自尝试使用vim。其实关于vim也的确很难出一些实战性的问题,更多的还是要我们亲自去使用它去感受它的魅力。

至少对我而言,这节课充分让我认识到了vim的强大功能。我已经根据老师的意思,在我的vscode中安装了vim插件,不出意外的话,在以后的编码当中,我都会使用vim作为我的编辑器风格。

如果你也有志于提升你的编码风格和速度,不妨也尝试一下吧。