最近在看一个 MIT 发布的系列课程视频:The Missing Semeter Of Your Computer Science Education,课程涵盖了很多我们在平常开发中遇到过的、但是课程体系中很少涉及到的话题,并介绍了相关的基础知识和最佳实践。这一系列视频中,其中一节是关于 Vim 的,介绍了 Vim 背后的思想和一些基本操作。
虽然之前在捣鼓云服务器的时候用过 VIm 编辑过一些文件,但是那时候对命令行环境还比较陌生,有一些基本的操作还不够熟练,也就不愿意去深入学习 Vim,导致一直没有入门。平时也主要用 VS Code 这样的现代编辑器,所以也没有太强的动力去学习 Vim。
最近在一些项目中,开始越来越多地和终端、shell 脚本打交道,愈发感觉需要学习一些进阶的操作,来提高生产力。这一系列课程视频恰好为我打开了新世界的大门。另外,在写代码的时候,确实发现在键盘和鼠标之间来回切换相当费时间。
正好现在借着这一系列视频,开始重新学习 Vim 的操作。现在断断续续已经用了两个礼拜、四五个小时了,基本的操作逐渐熟悉,编辑速度直线上升。甚至发现即使是在现代编辑器中,很多操作使用 Vim 也会更快一些。于是连 VS Code、Chrome 浏览器什么的全都配置了 Vim,尽量避免使用鼠标或者触控板。
在进入正题之前,向大家推荐一下这一系列的课程。如果你想系统地了解一下命令行界面、Vim 等各种工具,想要提升自己的生产力,或者简单地想学一些“高端”操作,都可以去看一下这一系列视频,相信你不会后悔的。
接下来,我会简单介绍一下 Vim 及其背后的思想,并通过一些简单的使用场景,介绍 Vim 入门级别的一些命令。
Vim 认为,开发者大部分时间花在阅读代码、对代码进行小幅编辑上,而非花在编写大量代码上。于是,Vim 就有了各种模式:在 普通(NORMAL)
模式下阅读代码、跳转位置、快速编辑,在 编辑(INSERT)
模式下编写代码,在 可视(VISUAL)
模式下选择代码,等等。
Vim 是可编程的,可以通过 Vimscript
或者 Python
编写控制 Vim
的程序。甚至连 Vim
的界面本身也是一种“编程语言”——每一个按键对应一个命令,并且多个命令可以组合在一起。
Vim 帮助你脱离对鼠标的依赖。在键盘和鼠标中频繁切换太慢了。甚至,在键盘和方向键之间切换也很慢,所以它连方向键也不需要。
基于这些思想,Vim 能够跟上我们思考的速度,使用熟练以后,会大大提高我们的效率。
Vim
命令打开一个文件时,会默认进入普通模式。i
(insert) 进入编辑模式,在当前光标之前插入文本。(还有另外的命令可以进入编辑模式,在之后会详细列出)v
(visual) 进入可视模式ESC
回到普通模式
ESC
。因此,建议将大写锁定键绑定为 ESC
,来减少手的移动幅度。正如在基本思想中所说,开发者很大一部分时间是在阅读代码。而且阅读并非总是线性的,需要在同一文件的不同部分来回跳转切换,或者需要查看多个文件。因此,在阅读模式下快速移动光标到自己想要查看的位置尤为重要。
Vim 不需要方向键,而是由 hjkl
代替,分别对应左、下、上、右四个方向键。虽然其实用方向键也可以移动,但是为了能够尽量避免手的位移,还是习惯一下 hjkl
为好。在 Vim 的配置文件中,也可以设置禁用方向键,这个之后会给出相应的配置。
但是这仅仅只是实现了方向键。我们还是只能一点点的上下左右移动。于是,又有了很多别的操作,让我们更快地移动
行间移动:
w
向后移动一个词。b
向前移动一个词e
向后移动到当前词的末尾字符{number}w/b/e
移动规定词数,比如 3w
会向后移动三个词$
/ ^
光标移动至行尾/行首跨行移动:
{number}j/k
向下/向上移动相应行数,比如 5k
向上移动 5 行
{number}G
移动到该行H
移动到窗口顶端,M
移动至窗口中间,L
移动到窗口底部Ctrl-u
向上滚动半个窗口,Ctrl-d
向下滚动半个窗口gg
移至文件顶端,G
文件移至底端搜索:
f{character}
F{character}
,在当前行,向后/向前查找某一字符,光标移动到该字符
,
和 ;
跳至下一处或者上一处t{character}
, T{character}
,在当前行,向后/向前查找某一字符,光标移动到该字符之前
,
和 ;
跳至下一处或者上一处/{regex}
搜索文件,n
/ N
跳转到下一处/上一处在普通模式下,除了上面提到的用 i
进入编辑模式,还有其他的命令:
I
(shift + i
) 在当前行的第一个非空字符之前进入编辑模式a
(append) 在光标之后进入编辑模式A
在行尾进入编辑模式o
在当前行下新插入一行,光标移动至行首,进入编辑模式O
在当前行上面新插入一行,光标移动至行首,进入编辑模式这几个操作对应了几个不同的场景。在实际的开发过程中很常见。比如行尾少了冒号或者分号,比如需要新开一行,不需要先移动光标到行尾,而可以直接使用对应的指令在相应位置开始编写代码。
还有一些常见的命令,可以对应其他的编辑场景:
d{motion}
删除,比如 dw
是删除当前词,d$
删除光标至行尾的所有字符,d^
删除光标至行首的所有字符c{motion}
修改,cw
是修改当前词,效果是删除当前词,并进入编辑模式,等同于 dw + i
x
删除当前字符,相当于 dl
s
替换当前字符,相当于 xi
进入可视模式后,可以选中文本,再进行操作:
d
删除,c
修改y
复制(英文是 yank),d
也会复制,p
粘贴Vim 中也有对应的撤销、重做:
u
撤销 ctrl + r
重做在前面我们见过了 {number}k
这样的操作,可以通过计数来执行特定次数相同的操作。更多的例子有:3w
向后移动 3 个词,7dw
删除 7 个词
通过修饰,可以修改名词的意思,实现不同的编辑效果。比如,ci(
可以修改当前括号内的内容,它会删除当前括号内的内容,并进入编辑模式。da'
则会删除引号以及引号内部的内容。这里 i
的意思是 inside,a 则是 around
在普通模式下,使用 :
进入命令行,进行文件的读取、写入等操作:
:w
保存:q
退出。 :wq
保存 + 退出:q!
放弃修改的内容强行退出:e {file name}
打开某一文件:ls
显示打开的文件(缓冲):help {topic}
打开帮助界面
:help :w
打开 :w
命令的帮助:help w
打开 w
移动操作的帮助介绍了一些基本操作,可以通过一个例子来看看如何使用这些命令来编辑一个文件:
The Missing Semester 提供了一个例子,里面是一段有问题的 Python 程序:
def fizz_buzz(limit): for i in range(limit): if i % 3 == 0: print('fizz') if i % 5 == 0: print('fizz') if i % 3 and i % 5: print(i) def main(): fizz_buzz(10) 复制代码
该程序存在一些问题:
main
函数不会执行,需要在文件末尾添加一些语句range
中的内容main
函数中使用的是写死的参数,而非命令行参数或者是用户的输入下面的几个动图,显示了如何通过 Vim 来修改这个程序。按键操作显示在了动图中
添加 if __name__ == 'main':
语句,涉及到行数跳转:
修改其中一个 'fizz'
为 'buzz'
:
修改 range
范围:
添加命令行参数:
前面提到了一些需要配置的功能。在上面的动图中你也看到了相对行号显示、自动缩进等,这些在最开始打开 Vim 的时候并不是默认开启的,需要在 Vim 的配置文件中进行配置。
在 macOS 和 Linux 系统中,Vim 的配置文件位于 '~/' 目录下,文件名为 .vimrc
。Vim 在每次启动时都会默认读取该文件的配置。
这里是一个比较简单的配置文件,建议你阅读注释的描述,判断自己是否需要这一设置,再手动配置你的 '~/.vimrc` 文件,仅仅加入你需要的配置项。这样能够避免你在不清楚设置的具体内容是什么的情况下,盲目拷贝别人的配置,导致引入一些你不习惯的操作。
配置文件来自于 The Missing Semester,翻译了注释
" 双引号为注释标记. " 如果在 Vim 中打开这个文件,则会看到语法高亮 " Vim 是基于 Vi 开发的。设置 `nocompatible` 会取消默认的 Vi 兼容模式,并启用一些有用的 Vim 功能 " 这项配置在 ~/.vimrc 中其实没必要,因为如果用户有 `~/.vimrc` 文件,Vim 会自动使用非兼容模式。 " 写在这以防配置文件是通过其他方式引入的(比如文件另存为了 foo,并通过 `vim -u foo` 命令启动了 Vim set nocompatible " 打开语法高亮 syntax on " 禁用默认的开启提示文字 set shortmess+=I " 显示行号 set number " 启用相对行号。当前行所显示的数字是实际行号,上面和下面的行都会显示相对的行号,便于跳转 set relativenumber " 在窗口底部显示状态栏 set laststatus=2 " 如果搜索的关键词全部为小写,则搜索忽略大小写。如果关键词中含有大写字母,则搜索变为大小写敏感 set ignorecase set smartcase " 即时显示搜索结果,而非等待按回车之后再显示 set incsearch " 启用鼠标。虽然你应该尽量避免使用鼠标,但是某些情况下还是鼠标比较方便 set mouse+=a " 当使用方向键跳转行数时发出提示 " Do this in normal mode... nnoremap <Left> :echoe "Use h"<CR> nnoremap <Right> :echoe "Use l"<CR> nnoremap <Up> :echoe "Use k"<CR> nnoremap <Down> :echoe "Use j"<CR> " ...and in insert mode inoremap <Left> <ESC>:echoe "Use h"<CR> inoremap <Right> <ESC>:echoe "Use l"<CR> inoremap <Up> <ESC>:echoe "Use k"<CR> inoremap <Down> <ESC>:echoe "Use j"<CR> " 将缩进符显示为 4 个空格 set tabstop=4 " 当使用 '>' 缩进时, 使用 4 个空格 set shiftwidth=4 " 按 Tab 键时,插入 4 个空格 set expandtab " 设置自动缩进,根据文件类型缩进 set autoindent filetype plugin indent on 复制代码
本篇文章介绍了 Vim 的基本思想,入门 Vim 需要了解的基本操作,以及基本的配置项。这篇文章也是在 VS Code 中 启用了 Vim 插件之后编写的。
我自己也是刚用了没几个小时,虽然大部分操作已经比较熟悉,但是还是有些地方会卡住一小会。不过,用得越多,就能发现卡壳儿的地方越来越少,写代码的速度越来越快了。
Vim 是一个非常强大的编辑器,还有很多的功能、插件和配置没有探索到。后续当我用得再多一些,总结出一些高级用法之后,再来分享。
网上也有不少资源可以学习 Vim,比如 Vim Tutor
在命令行学习 Vim 操作。还有人建了一个网页,大家互相比拼谁能用最少的命令修改完一段文本。另外,当你觉得在编辑什么文件时,有些操作过于繁琐,那很有可能确实存在一个更好的方式,这时不妨上网查一下,看看前人有没有相应的解决方法。
入门 Vim 确实是一个循序渐进的过程,一开始很不习惯。但是当你逼着自己用一段时间以后,就会越用越顺手。当然,还是在业余时间偷偷练习吧,熟悉 Vim 操作之前,在搬砖修福报的时候还是保持效率更重要。。
missing.csail.mit.edu/2020/editor…
文章同步发布于博客:点击查看