精通 Vim——入门

150 阅读27分钟

欢迎来到《精通 Vim》。本书将教你如何熟练使用 Vim、其插件,以及它的思想继承者!
本章将为使用 Vim 打下基础。每一件工具都蕴含特定的使用哲学,Vim 也不例外。与当今大多数人习惯的方式相比,Vim 引入了另一种处理文本的方式。本章将着重指出这些差异,并建立一套健康的编辑习惯,让你以更“Vim 式”的心态接近 Vim,并确保用对工具。为使示例具体,我们将在整章中用 Vim 编写一个小型 Python 应用。

本章将涵盖以下主题:

  • 不同主版本 Vim 之间的差异
  • 有模式无模式界面,以及为什么 Vim 与其他编辑器不同
  • 安装与更新 Vim
  • gVim —— Vim 的图形界面
  • 为 Python 开发配置 Vim,并编辑你的配置
  • 常见文件操作——打开、修改、保存与关闭文件
  • 移动光标——用方向键与光标移动键、按单词、按段落等进行导航
  • 对文件进行简单编辑,并将编辑命令与移动命令组合使用
  • 持久化撤销历史(persistent undo)
  • 查阅 Vim 内置手册

技术要求

本章会编写一个基础的 Python 应用。你无需预先下载代码,我们会从零创建文件。若你在学习过程中迷路或需要更多参考,可以查看 GitHub 上的最终代码:
github.com/PacktPublis…

整本书我们都会主要用 Vim 编写 Python 代码,默认读者对该语言有所了解,示例均基于 Python 3 语法。

使用 Python 2 代码
如果你必须“活在过去”,可以把 Python 3 的示例改成 Python 2:把 print('Woof!') 改成 print 'Woof!' 即可在 Python 2 中运行。

我们还会创建并修改 Vim 的配置文件 .vimrc。该文件的成品版本也可从上面的 GitHub 链接获得。

简短的历史课

让我们回到时间的起点:20 世纪中叶。那时还没有个人电脑与终端,只有电传打字机。电传打字机是一种可通过通信线路发送和接收消息的机械打字机。下面是 Teletype ASR-33(1963)的照片——一种曾作为计算机接口与输入设备的高级打字机:

image.png

图 1.1 —— Teletype Corporation ASR-33 电传打字机(图片作者 Arnold Reinhold,维基百科,CC BY-SA 3.0)

在电传打字机上,你只能逐行处理文本,所以当时使用的是行编辑器,如 Ken Thompson 开发的 ed,以及其后继者——Bill Joy 的 ex。行编辑器和今天的 Vim 一样,都是有模式的(稍后详述),但受限于前述 I/O 条件,只能一次处理一行文本。是的,真的只能一行。

随着技术进步,电传打字机被带屏幕的终端取代,文本编辑能力大为增强。Vim 的直接前身 vi 诞生于 1976 年。与前辈不同,vi(由 ex 的作者 Bill Joy 开发)引入了许多“生活质量”特性,甚至允许你一次编辑多行文本——这在当时可是奢侈!

你知道吗?
在许多现代系统上,vi 命令其实是指向 vim-tiny(功能受限版 Vim)的符号链接,而非最初的 vi 实现!

vi 激发了许多克隆实现,其中包括 STEVIE(ST Editor for VI Enthusiasts)。后来 Vim 的代码正是以 STEVIE 的源码为基础展开的。Vim 的第一个版本由 Bram Moolenaar1991 年发布。至此,你已经追上进度了!

虽然你不太可能遇到一台“停留在上世纪 90 年代末”的 Vim 设备,但了解不同 Vim 版本的变化仍然有益。下面是(大幅简化的)各主版本亮点,直至本书第二版写作时。自 1991 年以来,Vim 一直在持续演进!

  • 1.0(1991) :Bram Moolenaar 为 Amiga 计算机发布 “Vi Imitation”。
  • 2.0(1993) :以如今的名字 Vi Improved 发布!
  • 3.0(1994) :支持多窗口
  • 4.0(1996) :加入图形界面支持。
  • 5.0–5.8(1998–2001) :加入语法高亮脚本选择模式
  • 6.0–6.4(2001–2005) :加入插件折叠支持。
  • 7.0–7.4(2006–2013) :新增拼写检查代码补全标签页分支历史持久化撤销等。
  • 8.0–8.2(2016–2019)优化异步 I/O内置终端弹出窗口
  • 9.0(2022) :引入新脚本语言 Vim9script

如同 vi 一样,Vim 也有众多“亲戚”,其中不乏非常成功的实现。本书第 9 章会介绍其中一个更受欢迎的替代实现。

试试 :help
若想详阅各版本差异,可打开 :help(你会在本章末学会如何使用)并搜索 “Versions”。例如试试 :help version9 查看 Vim 9 的新增内容!

开始一次对话(关于“有模式”界面)

如果你曾编辑过文本,你很可能对无模式(modeless)界面更熟悉。那是现代主流编辑器的默认选择,也是许多人学习编辑文本时的起点。如果你还记得智能手机出现之前的时代,许多座机与早期手机也基本是无模式的。

“无模式”指:每个界面元素只有单一功能。每次按键要么显示一个字符,要么执行固定动作。每个按键(或组合键)总是做同一件事:应用始终在同一个模式下运作。

然而,这并非唯一方式。

欢迎来到有模式(modal)界面:每个触发动作会根据上下文执行不同功能。我们今天最常见的有模式界面例子是智能手机——在不同 App 或不同菜单下,点按屏幕的效果各不相同。

image.png

图 1.2 —— 智能手机采用有模式界面,而传统电话(大多)是无模式

文本编辑器也类似。Vim 是有模式编辑器:一次按键的作用会随所处模式而变。比如在插入模式(输入文本的模式)下,按 o 会在屏幕上输入字母 o;但一旦切换到其他模式,o 的功能就变为在光标下方新增一行

与 Vim 协作就像与你的编辑器“对话”。你让 Vim 删除接下来的三个单词:按下 d3w(delete 3 words);你让 Vim 修改引号内的文本:按下 ci"(change inside ")。

人们常说 Vim 比其他编辑器“更快”,但这未必是 Vim 的核心要点。Vim 的价值在于:让你在处理文本时保持流畅。你无需为抓鼠标而打断节奏;你不必为移动到某处连续敲同一个键 17 次;也不必为精准选中文段而用鼠标一点点挪动

无模式编辑器中,工作流程充满打断;在有模式编辑器中,一切更具“流”感:你用一致的“语言”向编辑器发出动作指令。在 Vim 里,编辑变得更加有意识、更可组合、更高效

安装(Installation)

Vim 可用于所有主流平台,并且在 LinuxmacOS 上预装(不过你可能希望升级到较新的版本)。根据操作系统与个人偏好,你有多种安装方式可选。下面这张“粗略小图”展示了一些常见方案:

image.png

图 1.3 – 不同操作系统上的 Vim 安装选项

请在下列小节找到你的系统,快速浏览并完成安装。

为什么有这么多截图?
你会发现接下来的安装说明包含了不少细节和截图。虽然 Vim 在多数平台都容易获得,但装到最新版本并不总像想象中那样直接。如果你发现自己安装了不合适的版本,随时可以回到本章按步骤重新来一遍。

在 Linux 与类 Unix 系统上安装

大多数 Linux 机器都自带 Vim,这当然是好消息!不过它可能比较陈旧,而新版本经常包含新功能与性能优化(参见本章前面的“简史”部分)。要从最新补丁构建一份“新鲜”的 Vim,请在命令行执行:

$ git clone https://github.com/vim/vim.git
$ cd vim/src
$ ./configure --prefix=/usr/local --with-features=huge
$ make
$ sudo make install

继续阅读下一节以了解编译选项的更多信息。

缺少依赖
如果安装过程中遇到问题,可能是依赖未安装。对基于 Debian 的发行版,可先执行:

$ sudo apt-get install make build-essential \
libncurses5-dev libncursesw5-dev --fix-missing

以上步骤可确保你获得 Vim 的最新大/小版本补丁。如果你不追求“最前沿”,也可以直接使用发行版的包管理器更新 Vim。不同发行版的命令略有差异,常见示例如下:

发行版/系统安装最新 Vim 的命令
Debian 系(Debian、Ubuntu、Mint)sudo apt-get update``sudo apt-get install vim-gtk
CentOS(及 Fedora 22 之前)sudo yum check-update``sudo yum install vim-enhanced
Fedora 22+sudo dnf check-update``sudo dnf install vim-enhanced
Archsudo pacman -Syu``sudo pacman -S gvim
FreeBSDsudo pkg update``sudo pkg install vim

注意包名
不同仓库中 Vim 的包名不同。比如 Debian 系中的 vim-gtk,CentOS 中的 vim-enhanced,通常意味着启用了更多功能(如 GUI 支持)。
另请注意:包管理器的仓库版本可能滞后数月甚至数年。

安装完成后,启动编辑器:

$ vim

Vim 与 vi
Vi 是 Vim 的前身(Vim 即 Vi Improved)。在一些发行版上,vi 命令指向精简版 Vim(vim-tiny) ;在另一些发行版上,它只是指向功能完整 Vim 的符号链接。

编译选项(Compilation options)

从源码编译通常是获取最新 Vim 的最佳方式。若你不惧“动手”,下面是 configure 常用选项。基本流程:

$ git clone https://github.com/vim/vim.git
$ cd vim/src
$ ./configure <options>
$ make
$ sudo make install
  • 安装位置:使用 --prefix 控制

    • --prefix=/usr/local:系统范围的合理默认
    • --prefix=$HOME/.local:仅对当前用户可用
  • 功能集:启用不同规模的功能(tinysmallnormalbighuge

    • --with-features=huge:包含几乎所有功能(含实验性)
    • --with-features=normal:合理功能集(本书大多基于此)
    • --with-features=tiny:精简到只含基础功能(无语法高亮/插件)
  • 语言支持:通过 --enable-<language>interp 控制(用于 Vim 内部与语言交互,如插件/脚本;与“能否编辑该语言文件”无关)

    • --enable-luainterp=yes 启用 Lua
    • --enable-perlinterp=yes 启用 Perl
    • --enable-python3interp=yes 启用 Python 3
    • --enable-rubyinterp=yes 启用 Ruby
  • X11 剪贴板:要与 Linux 的系统剪贴板集成,可加 --with-x。同时你可能需要 X 开发库(如使用 apt:sudo apt install libx11-dev libxtst-dev)。

在 macOS 上安装

macOS 自带 Vim,但版本可能较旧。这里介绍两种安装较新版本的方式:

  1. 通过 Homebrew(macOS 的包管理器)安装;
  2. 下载 MacVim.dmg 镜像安装(图形体验更熟悉)。

本书会经常使用命令行,推荐 Homebrew 路线;但如果你更偏好图形安装,也可选择 .dmg

使用 Homebrew

Homebrew 是第三方包管理器,安装与升级都很方便。安装说明见 brew.sh。在撰写本书时,安装命令为:

$ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

执行后按提示多次回车继续。

如果你没有安装 Xcode
若未安装 Xcode(在 Mac 上进行开发常需要它的一些组件),系统会弹出安装提示。我们不会直接使用 Xcode,按默认设置安装即可。

稍等片刻即可看到 Installation successful! 的提示。接着用 Homebrew 安装 Vim:

$ brew install vim

Homebrew 会自动安装依赖,无需手动处理。

如果你之前装过 Vim,运行上述命令可能提示已安装。要升级到最新版本,请执行:

$ brew upgrade vim

现在可以愉快地打开 Vim 了:

$ vim

image.png

图 1.4 – 通过 Homebrew 安装的 macOS 上的 Vim

接下来介绍使用 .dmg 镜像的方法。

下载 .dmg 镜像

  1. 访问 github.com/macvim-dev/…,下载 MacVim.dmg
  2. 打开 MacVim.dmg,将 Vim 图标拖到 Applications 目录(如下图)。

image.png

图 1.5 – MacVim 安装界面:拖拽到 Applications 文件夹

根据你的安全设置,首次在“应用程序”中打开 MacVim 可能出现下图所示的提示:

image.png

图 1.6 – 默认的“未识别开发者”提示

此时在“应用程序”中找到 MacVim,右键其图标,选择 Open,将出现下图提示:

image.png

图 1.7 – 通过右键 Open 后的“未识别开发者”提示

点击 Open 后,即可正常启动 MacVim。试试看吧:

image.png

图 1.8 – macOS 上的 MacVim

在 Windows 上安装(Setting up on Windows)

在 Windows 上使用 Vim 主要有两条路径:

  • 安装 Cygwin,获得更接近 Unix 的命令行体验;
  • 安装 gVim(Vim 的图形版,亦可在 Windows 的 cmd.exe 下使用)。

建议两者都装上,然后选择你更顺手的方式:gVim 在 Windows 上更“本地化”(而且更易安装);如果你习惯 Unix shell,Cygwin 可能更合胃口。

通过 Cygwin 获得类 Unix 体验

Cygwin 是 Windows 上的类 Unix 环境与命令行接口,旨在把强大的 Unix shell 与配套工具带到 Windows 机器上。

Windows Subsystem for Linux(WSL)
WSL 是 Windows 10+ 的一项特性,可在 Windows 内直接运行 Linux 环境。尽管我个人没有深度使用 WSL,但它广受好评:快速、易用、稳定,是在 Windows 上使用 Linux 命令行与工具的可靠方式,并在持续改进中,可能比 Cygwin 更佳。详见:learn.microsoft.com/windows/wsl

安装 Cygwin

前往 cygwin.com/install.htm…,根据系统选择下载 setup-x86_64.exe(64 位)或 setup-x86.exe(32 位)。

如何确认系统位数?
若不确定系统是 32 位还是 64 位,打开“控制面板 → 系统和安全 → 系统”,查看“系统类型”(如:64-bit Operating System, x64-based processor)。

运行安装程序,你会看到如下 Cygwin 安装界面:

image.png

图 1.9 – Windows 上的 Cygwin 安装向导

连续点击 Next > ,使用默认设置:

  • Download source:Install from Internet
  • Root directory:C:\cygwin64(或推荐默认值)
  • Install for:All Users
  • Local package directory:C:\Downloads(或推荐默认值)
  • Internet connection:Use System Proxy Settings
  • Download site:http://cygwin.mirror.constant.com(或任一可用镜像)

随后进入 Select Packages 界面。这里选择 vimgvimvim-doc 包。最简单方式是在搜索框输入 vim,展开 All | Editors 类别,点击所需包旁的箭头图标,如下图所示:

image.png

图 1.10 – Cygwin 包选择界面(New 一列中已选中 gvim、vim、vim-doc)

截图显示的版本为 8.2.4372-2(本章写作时,2023 年 7 月,Cygwin 中可用的最新版本)。当时 Vim 的最新上游版本是 9.0,引入了 Vim9script(版本差异可参见前文“简史”部分)。

用 Cygwin 编译 Vim
若你想要 Vim 的最新版本,建议在 Cygwin 内从官方 Git 仓库编译安装。完成 Cygwin 安装后,可参照本章前面的“在 Linux 上安装”部分;同时在 Cygwin 中安装 gitmake 等工具。

可能需要的附加工具
建议在 Net 类别下安装 curl,在 Devel 类别下安装 git(第 3 章会用到)。在 Utils 类别安装 dos2unix 也很有帮助——它可把 Windows 风格的行尾转换为 Linux 风格(偶尔会用到)。

再点两次 Next > 开始安装。安装耗时较长,此时不妨先来杯咖啡预祝成功!

安装结束后可能出现一些 post-install 脚本错误提示,一般可以忽略(除非与 Vim 相关——这时请善用搜索引擎,按错误信息查找解决方案)。

继续点击 Next > ,保持默认:

  • Create icon on Desktop
  • Add icon to Start Menu

恭喜——已在 Cygwin 环境中安装好 Vim!

在 Cygwin 中追加安装包
如需日后安装其他包,重新运行安装程序并勾选需要的包即可。

使用 Cygwin

打开 Cygwin(根据系统不同,程序名可能为 Cygwin64 TerminalCygwin Terminal):

image.png

图 1.11 – Cygwin64 Terminal 应用图标

打开后,你会看到熟悉的 Linux 风格提示符:

image.png

图 1.12 – Cygwin 命令行(示例用户 ruslan,主机 RUSLAN-DESKTOP)

Cygwin 支持本书将使用的全部 Unix 命令。本书也会在需要时说明,在 Cygwin 下是否要调整命令。

输入 vim 并回车启动 Vim,如下图所示(注意状态行中的 Modified by <cygwin@cygwin.com>):

image.png

图 1.13 – 通过 Cygwin 安装的 Vim

选择 Cygwin,就意味着你将获得 Linux 风格的 shell 体验——因此本书中与 Linux 相关的说明同样适用。

请同时留意 Windows 与 Linux 的换行符差异。若遇到 Vim 抱怨文件中有无法识别的 ^M 字符,可对该文件运行 dos2unix 转换行尾后再试。

图形版 Vim:gVim

关于图形版 Vim 的更多讨论,见本章后面的“Vanilla Vim vs gVim”小节。

与 Windows 一贯的风格一致,这条路径更“可视化”。在浏览器访问:
github.com/vim/vim-win32-installer,下载可执行安装包。本章写作时(2023 年 7 月)最新 gVim 版本为 9.0

也可以使用 winget
若你熟悉 winget,可直接运行:
winget install -e --id vim.vim
(若想尝鲜夜构版本,改为 vim.vim.nightly

双击安装程序并按屏幕提示进行:

image.png

图 1.14 – gVim 9.0 安装欢迎界面

一路 NextI AgreeInstallation Options 页面。大多数默认选项即可,不过建议勾选Create .bat files for command line use。勾选后可在 Windows 命令提示符中使用 vim 命令。本书部分示例会使用命令行,因此启用该选项更方便跟练。

如下图所示:

image.png

图 1.15 – gVim 安装选项(已勾选 Create .bat files)

点击 Next > ,继续以下设置:

  • Select the type of install:Typical(勾选 .bat 后可能自动变为 Custom,无妨)
  • Do not remap keys for Windows behavior
  • Right button has a popup menu, left button starts visual mode
  • Destination Folder:C:\Program Files (x86)\Vim(或推荐默认值)

最后点击 InstallClose。是否查看 README 随意。

桌面上会出现几个新图标,其中最重要的是 gVim 9.0

image.png

图 1.16 – gVim 9.0 应用图标

启动它,你就可以继续下一步了。Happy Vimming!

在 ChromeOS 上安装

ChromeOS 越来越流行(尤其在教育与部分企业场景)。Chromebook 价格低、易用、对硬件要求也低。我本人曾用 Chromebook 作为日常工作设备多年——选择 ChromeOS 并不意味着要与 Vim 说再见。

要在 ChromeOS 上运行 Vim,需要在其旁边安装一个 Linux 环境。这并不复杂、无需双系统,且与 ChromeOS 集成良好。

ChromeOS 的 Linux 支持
部分老旧 ChromeOS 设备不支持 Linux 环境。可在“设置”应用中搜索 Linux 检查是否支持;若无结果,则无法在该设备上使用 Vim。

首先在 ChromeOS 中开启 Linux:打开“设置 → 高级 → 开发者 → Linux 开发环境 → 开启”:

image.png

图 1.17 – 在 Chromebook 上开启 Linux 开发环境的提示

Next 继续。默认设置即可,如下图:

image.png

图 1.18 – Linux 开发环境设置(采用推荐设置即可)

点击 Install,几分钟内即可完成。

新安装的 Debian Linux 环境可通过 Terminal 应用访问。默认环境名为 penguin,在 Terminal 中选择它:

image.png

图 1.19 – ChromeOS 上名为 penguin 的 Linux 环境

你将看到熟悉的 Linux 命令行提示符:

image.png

图 1.20 – ChromeOS 内的 Linux 终端(示例中通过 sudo apt install cowsay 安装了 cowsay)

与多数 Linux 机器一样,这里通常也已预装 Vim。

编译获取最新 Vim
如需最新版本,建议按“在 Linux 上安装”部分从官方 Git 仓库编译 Vim(并不难)。

现在可在终端启动 Vim:

$ vim

界面如下:

image.png

图 1.21 – ChromeOS 终端中的 Vim 欢迎界面

在 Linux 中访问 ChromeOS 文件
由于 ChromeOS 与 Linux 的集成,你可以在 ChromeOS 文件应用中访问 Linux 的 Home 目录(在终端用 cd ~ 即可进入该目录):

image.png

图 1.22 – 可从 ChromeOS 的“文件”应用访问 Linux 文件

此外,也可在 ChromeOS 中右键某个文件,选择 Share with Linux 将其共享给 Linux,在 Linux 中可通过 /mnt/chromeos 访问。

验证与排错(Verifying and troubleshooting the installation)

不论在哪个平台安装 Vim,最好确认所需功能已启用。命令行执行:

$ vim --version

你会看到一长串功能列表,前缀为 +(已启用)或 -(未启用):

image.png

图 1.23 – vim --version 的输出示例

上图可见,该 Vim 编译时启用了 Python 2+python),而 Python 3 为禁用(-python3)。要修正,可 重新编译 使其带 +python3(需要先装依赖),或找到发行版里已经编译好 +python3 的包。

Vim 的语言集成功能
注意 +python3 等选项表示 Vim 与该语言的集成(插件/脚本可调用该语言)。你仍然可以编辑任何文件(包括 Python 3),但 Vim、插件与脚本将无法在内部运行 Python 3。

使用 :help
查看 Vim 可启用的全部功能列表:在 Vim 内输入 :help feature-list

例如在 Linux 上重新编译并启用 Python 3 支持:

$ git clone https://github.com/vim/vim.git
$ cd vim/src
$ ./configure --prefix=/usr/local \
    --with-features=huge \
    --enable-python3interp
$ make
$ sudo make install

指定功能集
我们传入了 --with-features=huge 以启用尽可能多的特性。但注意该选项不包含语言绑定,因此还需显式开启 --enable-python3interp

总体来说,如果你的 Vim 行为与其他安装(包括本书描述)不一致,可能是缺少某些功能
不同系统与需求下的处理略有不同。快速搜索类似关键词通常能找到答案:
“Installing Vim with + on ”。

安装流程到此结束。接下来,让我们更仔细地看看我们都装了些什么。

原生 Vim 与 gVim(Vanilla Vim versus gVim)

按照前面的说明,你已经安装了两种风味的 Vim:命令行版 VimgVim。在 Windows 上,gVim 的界面如下:

image.png

图 1.24 – Windows 下的 gVim 界面

gVim 为 Vim 提供了图形用户界面(GUI),拥有更好的鼠标支持和更多的上下文菜单。与许多终端模拟器相比,它还能显示更广的配色范围,并提供一些你对现代 GUI 所期望的易用性功能。

你可以在 Windows 上直接运行 gVim 9.0 的可执行文件来启动 gVim;在 Linux 与 macOS 上,则可以通过以下命令启动:

$ gvim

Windows 用户可能会更偏爱 gVim。

本书的重点在于提升文本编辑效率,因此我们不会花太多篇幅去介绍 gVim 中多级菜单的导航(这些通常比较直观,但会打断编辑的“流”)。

因此,我们将把重心放在非图形版本的 Vim 上;不过,适用于 Vim 的内容同样适用于 gVim。两者共享配置,你可以随时来回切换。总体上,gVim 对新手稍微友好一些,但就本书而言,你选择哪一个并不重要。

两个都试试吧!

.vimrc 配置 Vim(Configuring Vim with your .vimrc)

Vim 会从 .vimrc 文件读取配置。Vim 开箱即用,但开启一些选项能让写代码更轻松。

查看隐藏文件
在类 Unix 系统中,以点号(.)开头的文件是隐藏的。要显示它们,可在命令行执行 ls -a

LinuxmacOS 上,.vimrc 位于你的用户目录(完整路径为 /home/<username>/.vimrc)。也可用以下命令查看你的用户目录路径:

$ echo $HOME

早期版本的 Windows 资源管理器不允许运行以点开头的文件名,因此在 Windows 上该文件名为 _vimrc。它通常位于 C:\Users<username>_vimrc。你也可以在 Windows 命令提示符中运行:

$ echo %USERPROFILE%

定位 .vimrc
如果遇到问题,打开 Vim,输入 :echo $MYVIMRC 并回车。它会显示 Vim 当前从哪里读取 .vimrc

根据你的操作系统找到正确位置,把准备好的配置文件放进去。你可以从 GitHub 下载本章使用的 .vimrc
github.com/PacktPublis…
本章使用的 .vimrc 内容如下:

syntax on " Enable syntax highlighting.
filetype plugin indent on " Enable file type based options.
set nocompatible " Don't run in backwards compatible mode.
set autoindent " Respect indentation when starting new line.
set expandtab " Expand tabs to spaces. Essential in Python.
set tabstop=4 " Number of spaces tab is counted for.
set shiftwidth=4 " Number of spaces to use for autoindent.
set backspace=2 " Fix backspace behavior on most terminals.
colorscheme murphy " Change a colorscheme.

这些你日后可能想调整
如果你打算把 Vim 作为多种文件类型的主力编辑器,建议把某些选项仅应用于 Python。可为相关设置加上 autocmd filetype python 前缀,使其只在 Python 文件中生效:

autocmd filetype python set expandtab
autocmd filetype python set tabstop=4
autocmd filetype python set shiftwidth=4

以双引号(")开头的行是注释,Vim 会忽略。上述设置开启了一些合理的默认值,如语法高亮和一致的缩进;它们也修复了“裸 Vim”安装中常见的一个痛点——不同环境下 Backspace 键行为不一致。

试用配置项
编辑 Vim 配置时,可以先试再写入 .vimrc。方法是在普通模式下输入冒号加命令,例如 :set autoindent(回车执行)。如果想查看某个设置的当前值,在命令末尾加问号:例如 :set tabstop? 会显示当前的 tabstop 值。

我把 colorscheme 也改了,以便截图在纸面上更易读;当然你不必更改(除非你也在写一本关于 Vim 的书——那就另当别论了)。

缤纷的颜色世界
Vim 9 自带许多配色主题,而且列表在每次发布时都会增长。可以输入 :colorscheme <name> 并回车来试用某个主题;输入 :colorscheme 后按 Tab 键多次可以在可用主题名之间循环。关于配置 Vim 与配色(包括使用网上找到的主题),可参见第 7 章。

你已经完成了 Vim 的配置——现在,是时候开始真正学会如何使用它了!

常用操作(或者:如何退出 Vim)

本节我们将专注于不依赖鼠标或菜单与 Vim 交互。先来张多年前的梗图:

image.png

图 1.25 – 对典型 Vim 用户的精准刻画(来源:twitter.com/iamdevloper…

编程本就是一项需要高度专注的工作。到处翻找右键菜单并不有趣,把手一直放在键盘的主键区可以避免在键盘与鼠标之间频繁切换。

接下来我们会学习如何打开(更重要的是关闭)Vim、保存文件以及进行基础编辑。

打开文件(Opening files)

先启动你偏好的命令行(Linux/macOS 用 Terminal,Windows 用 Cygwin 等)。我们来写个非常简单的 Python 小程序——开个平方根计算器的头。运行:

$ vim spam.py

图形界面 YES!
如果你使用 gVim,也可以通过菜单 File → Open 打开文件。某些时候,图形界面确实更顺手!

这会打开名为 spam.py 的文件。若文件已存在,你会看到其内容;若不存在,则是空白屏幕,如下:

image.png

图 1.26 – 打开新文件时底部出现 [New File] 的提示

底部状态栏文件名旁的 [New File] 表示该文件尚不存在。太好了——你已经用 Vim 打开了第一个文件!

如果 Vim 已经打开,也可以在 Vim 里输入并回车:

:e spam.py

这就是你执行的第一个 Vim 命令!输入冒号(:)会进入命令行模式,在底部输入一行文本作为命令,按 Enter 执行,从而完成复杂操作,甚至可调用系统命令行。:e:edit 的缩写。

Vim 帮助里经常把 Enter 键称作 <CR>,即 carriage return(回车)。

修改文本(Changing text)

Vim 默认处于普通模式(normal mode) ,每个按键都对应一条命令。按下 i 进入插入模式(insert mode) 。此时状态栏会显示 -- INSERT --,在 gVim 中光标也会由块状变成竖线,如下:

image.png

图 1.27 – 底部左侧出现 -- INSERT -- 表示插入模式

插入模式的行为与常见的“非模式化”编辑器相同。通常我们只在需要输入文本时短暂停留在插入模式。

模式、模式、还是模式
你已经遇到了三种模式:命令行模式普通模式插入模式。本书第 3 章会介绍更多模式及其含义。

现在输入这段小代码(本章都会围绕它来示例移动与编辑):

image.png

图 1.28 – 一个向《巨蟒剧团》“Spam”梗致敬的简单 Python 3 程序

Esc 返回普通模式。你会看到状态栏中的 -- INSERT -- 消失了,Vim 又准备好接收你的命令了。

这段代码并不“优雅”
它不是 Python 最佳实践,只是用来演示 Vim 能力。

保存与退出(Saving and closing files)

先保存文件,输入:

:w

别忘了执行命令!
命令末尾要按 Enter 才会执行。:w:write 的缩写。

关于命名
:w 后可跟文件名,将当前缓冲写到另一文件:例如 :w spam_2.py。若想保存并切换到新文件名,可用 :saveas spam_2.py

现在退出 Vim,检查文件是否已创建。:q:quit 的缩写。也可把写入与退出合并::wq

:q

若文件有改动而你不想保存,需使用强制退出:

:q!

命令可长可短
很多命令有长短两种写法:如 :e/:edit:w/:write:q/:quit。在 Vim 手册中,可选部分常用中括号表示,如 :w[rite]:e[dit]

回到系统命令行,查看当前目录并运行脚本:

$ ls
$ python3 spam.py

image.png

图 1.29 – ls -apython3 spam.py 的输出示例

命令小贴士
在类 Unix 系统中,ls 列出当前目录内容(-a 会显示隐藏文件)。python3 spam.py 用 Python 3 解释器执行脚本。

关于交换文件(A word about swap files)

默认情况下,Vim 会为你正在编辑的文件创建交换文件(swap file)来跟踪改动,以便 Vim/SSH 会话/机器崩溃时恢复内容。如果你没有正常退出 Vim,或者同时在多个 Vim 实例中编辑同一文件,再次打开时会看到类似界面:

image.png

图 1.30 – 打开文件时出现的 swap 文件提示

此时按 r恢复交换文件中的内容,按 d删除交换文件并放弃其中的改动。若你选择恢复,为了避免下次再出现该提示,可以重新打开文件、执行 :e,并在提示时按 d 删除交换文件(注意:如果该文件正被另一个 Vim 实例打开,Vim 不会允许删除其 swap)。

默认情况下,Vim 会在与原文件相同的目录下创建类似 <filename>.swp.<filename>.swp 的文件。如果你不想让这些文件“散落一地”,可以把它们统一放到一个目录里,在 .vimrc 中添加:

set directory=$HOME/.vim/swap//

注意末尾的双斜杠;没有它此设置可能无法正确工作!

给 Windows 用户
在 Windows 上可使用(注意最后两个反斜杠的方向):

set directory=%USERDATA%.vim\swap//

你也可以彻底禁用 swap 文件:

set noswapfile

你可能会说:“我大部分时间都在浏览代码而不是从上到下写!”别担心——这正是 Vim 有别于常规编辑器的地方。下一节我们就来学习,如何在你刚写的内容里高效地移动

在文本中移动:与编辑器“对话”

和多数传统编辑器相比,Vim 让你更高效地在内容间穿梭。先从基础开始。

你可以用方向键,或用 h、j、k、l 在文本中逐字符移动。这是最精细但效率最低的移动方式:

按键备用按键动作
h左方向键光标左移
j下方向键光标下移
k上方向键光标上移
l右方向键光标右移

image.png

图 1.31 – h、j、k、l 方向键的示意

Vim 的前身 vi 诞生在古早的 ADM-3A 终端上,它没有方向键,因此用 h、j、k、l 充当方向键。

image.png

图 1.32 – ADM-3A 终端

试着用用它们!习惯用 h、j、k、l 的一个好处是你的双手始终停留在键盘主键区,减少手部移动、保持“心流”。而且,很多应用也把 h、j、k、l 当作方向键——能响应它们的工具超乎你想象。

你也许会不停按方向键到达目标位置,但有更好的办法:给命令加数字前缀,表示重复次数。比如按下 5j 会向下移动 5 行,14l 会向右移动 14 个字符。本书里的大多数命令都支持这种用法。

逐字符数很难(也没人愿意数),所以可以按“词”移动:用 w 跳到下一个词的开头,用 e 跳到当前/下一个词的结尾,向后则用 b 回到上一个词的开头

把这些字母大写还能改变“词”的定义:把空白以外的连续字符都当作一个 WORD。这样你就能按需区分不同的移动粒度。

Vim 有两种“词”对象:小写的 word 与大写的 WORD

  • word:由字母、数字、下划线组成的序列;
  • WORD:由非空白字符组成、以空白分隔的序列(细节更复杂,见 :help iskeyword)。

假设我们取示例代码中的某一行进行说明:

注意:光标位于 ingredient 的第一个字符上。

此时按 w 会把光标移到下一个逗号,而 W 会跳到 with_spam 的开头。大写的 W/E/B 会把以空格分隔的任意连续字符看作一个整体。对应关系如下:

按键动作
w向前移动到下一个 word 的开头
e向前移动到当前/下一个 word 的结尾
W向前移动到下一个 WORD 的开头
E向前移动到当前/下一个 WORD 的结尾
b向后移动到上一个 word 的开头
B向后移动到上一个 WORD 的开头

下面的截图(未附)展示了这些命令从初始光标位置结果光标位置的更多例子:

按键初始位置结果位置
w
e
b
W
E
B

把这些“按词移动”与前面的方向移动组合起来,你就能用更少按键到达目标。

另外,按段落移动也很有用。被至少两个换行分隔的内容被视为不同段落;在代码中,每个代码块通常就是一个段落(如下示意):

image.png

图 1.33 – 这里可以看到三个段落

常量 INGREDIENTS、函数 prepare_menu_itemmain 是三个独立段落。用 } 向前(下)移动一个段落, { 向后(上)移动一个段落:

命令动作
{向后移动一个段落
}向前移动一个段落

别忘了也可以给它们加数字前缀,比如 3} 一次跨过三个段落。

image.png

图 1.34 – Vim 基本移动按键的可视化

移动的方法还有很多,但以上是最重要的基础。第 2 章我们会继续介绍更复杂的导航技巧。

在插入模式下做简单编辑(Making simple edits in insert mode)

在 Vim 中,除非你是在“写作”,否则通常希望尽量少待在插入模式里;多数文本操作其实都是“编辑”。下面就聚焦于编辑。

你已经会用 i 进入插入模式。进入插入模式还有更多方式。很多时候你想把一段文本替换成另一段,这就用到 c(change)命令。change 是复合命令:它会删掉一段文本并立刻进入插入模式,而它必须**跟随一个“移动/对象”**来告诉 Vim 改哪一段——可以和你之前学过的任何移动命令组合。示例:

命令之前之后
Cw
c3e
Cb
c4l
cW

word 与 WORD 的区别
记住:非字母数字(含标点)也会被当作“词”。例如 prepare_menu_item(ingredient, has_spam) 会被视为 6 个 word(但只算 1 个 WORD):prepare_menu_item(ingredient,(逗号)、has_spam)

特例
有个小历史遗留:cw 的行为等同于 ce(来自 Vim 的前身 Vi)。

随着你学到更复杂的移动命令,把它们和 c 组合能获得又快又顺的编辑体验。本书后面也会介绍一些插件,能进一步强化 c:比如修改括号内文本在不同引号之间切换等。

就像一句话的结构
这些命令基本都遵循 <命令> <数字> <移动或文本对象> 的结构。数字既可放在命令也可放在命令

比如下面这一行:

prepare_menu_item(ingredient, with_spam=has_spam)

想把 ingredient 改成 'egg'

prepare_menu_item('egg', with_spam=has_spam)

可以这样一气呵成:

当前行内容操作
光标在行首
2w,把光标前移到 ingredient 的开头
cw,删掉 ingredient 并进入插入模式
输入 'egg'
Esc 回到普通模式

有时我们只是想剪掉一段而不填新内容,就用 d(delete)。它和 c 很像,只是对 w / e 的行为更“标准”。例如:

命令之前之后
dw
d3e
db
d5l
dW

另外还有两个顺手的整行快捷键:

命令作用
cc清空整行并进入插入模式,保留当前缩进(写代码时很实用)。
dd删除整行

示例代码片段(图 1.35):

image.png

  • dd 会把一行彻底删除,光标跳到下一行(图 1.36)。

image.png

  • cc 会清空当前行并以正确缩进入插入模式(图 1.37)。

image.png

可视模式(Visual mode)
如果一时间想不好该用哪种移动命令,可以先用 v 进入可视模式进行选区,再用常见移动调选区,选好后执行 c(改)或 d(删)即可。

持久化撤销与重复(Persistent undo and repeat)

像其它编辑器一样,Vim 会记录你的每一步操作:按 u 撤销上一步,按 Ctrl+r 重做。

撤销树(Undo tree)
Vim 的撤销历史是树形而非线性的,如何在树上穿梭见第 4 章。

Vim 还能把撤销历史持久化到磁盘,方便你隔几天也能撤回/回忆当时的改动。

在你的 .vimrc 里开启:

set undofile

不过这会在各处生成很多 undo 文件。可以指定一个目录集中存放:

" 为所有文件启用持久化撤销
set undofile
let my_undo_dir = expand('$HOME/.vim/undodir')
if !isdirectory(my_undo_dir))
  call mkdir(my_undo_dir, "p")
endif
set undodir=my_undo_dir

Windows 用户
把路径改成 $USERPROFILE\vimfiles\undodir(而且你编辑的是 _vimrc 而不是 .vimrc)。

这样就能在不同会话之间撤销/重做了。

:help 阅读 Vim 手册

Vim 最好的自学工具就是 :help(图 1.38)。

image.png 这是随 Vim 一起安装的海量教程与参考。用 PageUp/PageDown 浏览(加分项:试试 Ctrl+b / Ctrl+f)。

:help help-summary
有空读一下 help-summary 页面,短小精悍,讲了如何高效浏览帮助。我在本节也穿插了其中一些技巧。

当你卡住或想深挖某个命令时,用 :help(可缩写为 :h)搜索。例如查我们学过的普通模式命令 cc

:h cc

(图 1.39)可以看到命令的行为,以及与设置(如 autoindent)的关系。

image.png

查找“选项”
在 Vim 帮助里,选项名总是用单引号包裹,例如想查 .vimrc 里的 set autoindent,执行:

:help 'autoindent'

:help 是在一组帮助文件里跳转。你会看到某些词被高亮,那是标签(tags) ,可以直接 :help 该标签 跳过去。可惜并非所有标签名都直观。比如想学如何搜索字符串,如果你直接:

:h search

会跳到表达式 search() 的说明(图 1.40),并不是我们要的。

image.png 此时敲:

:h search

(先别回车)然后按 Ctrl+d,Vim 会列出所有包含 search 的帮助标签,其中就有我们想要的 search-commands。把命令补全为:

:h search-commands

这就来到搜索命令的正确条目(图 1.41)。

image.png

在帮助里穿梭
在帮助页里,很多关键字外面会带有 [ { | 等符号或被高亮。把光标放在关键字上,按 Ctrl+]跳转到定义,按 Ctrl+o返回。试试看!

搜索
在帮助页(或任何文件)里,你可以用 /关键字 向前搜索、用 ?关键字 向后搜索。更多高级搜索技巧见第 2 章。

最后别忘了还有命令行工具 vimtutor。本书覆盖了它的大部分内容,但 vimtutor 里有很多练习,非常适合把 Vim 操作变成肌肉记忆。

有疑问或想更深入理解 Vim 行为时,随时用 :help

总结

最初的 Vi 是在带宽和速度受限的远程终端上使用而开发的。这些限制促使 Vi 形成了一套高效且有章法的编辑流程——这也正是今天 Vim(Vi Improved) 的核心。

本章中,你了解了 Vim 的一些(希望有趣的)历史轶事以及各大版本之间的差异。

你学会了如何在所有主流平台上安装与升级 Vim 及其图形版本 gVim(方法多到可能超出你的实际需要)。

你学会了通过调整 .vimrc 配置 Vim——随着你不断按需定制编辑器,这将是你经常会回去修改的地方。

你掌握了在 Vim 中处理文件、在文本中移动以及进行修改的基础。Vim 的文本对象(字母、单词、段落)与复合命令(如 d2w——删除 2 个单词)让精确的文本操作成为可能。

如果本章只能带走一件事,那就是 :help。Vim 内置的帮助系统内容极其详尽——只要你知道要找什么,它几乎能回答你所有的问题。

下一章我们将继续挖掘 Vim 的潜力:学习如何更高效地在文件间导航,并进一步提升编辑文本的能力。