006 《Vim: 权威指南》


作者Lou Xiao, gemini创建时间2025-04-11 14:14:33更新时间2025-04-11 14:14:33

🌟🌟🌟本文案由Gemini 2.0 Flash Thinking Experimental 01-21创作,用来辅助学习知识。🌟🌟🌟

书籍大纲

▮▮▮▮ 1. chapter 1: Vim 之旅:起航
▮▮▮▮▮▮▮ 1.1 Vim 的起源与演变:从 vi 到 Vim
▮▮▮▮▮▮▮ 1.2 Vim 的设计哲学:模式、效率与可扩展性
▮▮▮▮▮▮▮ 1.3 安装与配置 Vim:跨平台指南
▮▮▮▮▮▮▮ 1.4 首次启动 Vim:界面导览与基本操作
▮▮▮▮▮▮▮▮▮▮▮ 1.4.1 Vim 的用户界面:窗口、缓冲区与标签页
▮▮▮▮▮▮▮▮▮▮▮ 1.4.2 Vim 的模式:Normal, Insert, Visual, Command 等
▮▮▮▮▮▮▮▮▮▮▮ 1.4.3 最基本的移动:hjkl 键的奥秘
▮▮▮▮ 2. chapter 2: 基础操作:文本编辑的基石
▮▮▮▮▮▮▮ 2.1 进入与退出 Insert 模式:开始文本输入
▮▮▮▮▮▮▮ 2.2 文本插入、删除与替换:字符、单词与行
▮▮▮▮▮▮▮ 2.3 撤销、重做与重复操作:. 命令的威力
▮▮▮▮▮▮▮ 2.4 保存与打开文件:文件操作基础
▮▮▮▮ 3. chapter 3: 高效移动:指尖上的舞蹈
▮▮▮▮▮▮▮ 3.1 单词级移动:w, b, e, ge
▮▮▮▮▮▮▮ 3.2 行内快速跳转:0, $, ^, f, F, t, T
▮▮▮▮▮▮▮ 3.3 段落与句子移动:{, }, ), (
▮▮▮▮▮▮▮ 3.4 屏幕滚动与跳转:Ctrl+u, Ctrl+d, Ctrl+b, Ctrl+f, H, M, L
▮▮▮▮▮▮▮ 3.5 标记与跳转:m, `
▮▮▮▮ 4. chapter 4: 文本操作进阶:精准编辑的艺术
▮▮▮▮▮▮▮ 4.1 Visual 模式详解:字符、行与块选择
▮▮▮▮▮▮▮ 4.2 剪切、复制与粘贴:寄存器的概念
▮▮▮▮▮▮▮ 4.3 文本对象:iw, aw, is, as, ip, ap
▮▮▮▮▮▮▮ 4.4 操作符与动作的组合:d, c, y 与各种动作的灵活运用
▮▮▮▮▮▮▮ 4.5 大小写转换、缩进与对齐
▮▮▮▮ 5. chapter 5: 搜索与替换:信息定位与批量修改
▮▮▮▮▮▮▮ 5.1 基本搜索:/? 命令
▮▮▮▮▮▮▮ 5.2 高级搜索选项:忽略大小写、高亮显示等
▮▮▮▮▮▮▮ 5.3 正则表达式基础:元字符与模式匹配
▮▮▮▮▮▮▮ 5.4 替换命令 :s:基本替换与全局替换
▮▮▮▮▮▮▮ 5.5 正则表达式在替换中的应用:捕获组与反向引用
▮▮▮▮ 6. chapter 6: 多文件操作:项目级编辑利器
▮▮▮▮▮▮▮ 6.1 缓冲区管理::buffers, :ls, :bnext, :bprev, :bdelete
▮▮▮▮▮▮▮ 6.2 窗口分割与管理::split, :vsplit, Ctrl+w 系列命令
▮▮▮▮▮▮▮ 6.3 标签页管理::tabnew, :tabnext, :tabprev, :tabclose
▮▮▮▮▮▮▮ 6.4 文件浏览器与目录树::Explore, 插件推荐
▮▮▮▮ 7. chapter 7: 宏与自动化:效率倍增的秘诀
▮▮▮▮▮▮▮ 7.1 宏的录制与播放:q 命令
▮▮▮▮▮▮▮ 7.2 宏的编辑与重复执行:@, @@, 数字前缀
▮▮▮▮▮▮▮ 7.3 宏的进阶应用:递归宏与条件宏
▮▮▮▮ 8. chapter 8: Vim 配置:打造个性化编辑器
▮▮▮▮▮▮▮ 8.1 .vimrc 文件:Vim 配置的入口
▮▮▮▮▮▮▮ 8.2 常用配置选项详解:行号、缩进、搜索、界面等
▮▮▮▮▮▮▮ 8.3 配色方案与字体设置:美化 Vim 界面
▮▮▮▮▮▮▮ 8.4 键盘映射:自定义快捷键 :map, :noremap
▮▮▮▮▮▮▮ 8.5 自动命令:根据事件触发命令 :autocmd
▮▮▮▮ 9. chapter 9: Vim 插件:扩展无限可能
▮▮▮▮▮▮▮ 9.1 插件管理工具:Vundle, Pathogen, vim-plug 等
▮▮▮▮▮▮▮ 9.2 常用插件分类与推荐:代码补全、语法检查、文件管理、主题美化等
▮▮▮▮▮▮▮ 9.3 插件配置与使用技巧
▮▮▮▮▮▮▮ 9.4 自定义插件:Vimscript 基础入门
▮▮▮▮ 10. chapter 10: Vimscript 编程:深度定制 Vim
▮▮▮▮▮▮▮ 10.1 Vimscript 语法基础:变量、函数、控制结构
▮▮▮▮▮▮▮ 10.2 Vimscript 常用函数库:字符串、列表、字典操作
▮▮▮▮▮▮▮ 10.3 编写简单的 Vimscript 函数与命令
▮▮▮▮▮▮▮ 10.4 开发实用的 Vim 插件:案例分析
▮▮▮▮ 11. chapter 11: 高级技巧与最佳实践
▮▮▮▮▮▮▮ 11.1 利用 Vim 进行代码重构
▮▮▮▮▮▮▮ 11.2 使用 Vim 进行版本控制集成 (Git 等)
▮▮▮▮▮▮▮ 11.3 远程编辑与协作::netrw, TRAMP
▮▮▮▮▮▮▮ 11.4 Vim 与终端的融合:tmux, screen
▮▮▮▮▮▮▮ 11.5 性能优化与问题排查
▮▮▮▮ 12. chapter 12: Vim 的知识框架与架构深度解析
▮▮▮▮▮▮▮ 12.1 Vim 的核心概念模型:缓冲区、窗口、标签页的内在联系
▮▮▮▮▮▮▮ 12.2 Vim 的事件循环与模式切换机制
▮▮▮▮▮▮▮ 12.3 Vim 的可扩展性架构:插件与 Vimscript 的工作原理
▮▮▮▮ 13. chapter 13: 实战案例:Vim 在不同场景下的应用
▮▮▮▮▮▮▮ 13.1 Vim 在代码开发中的应用:各种编程语言的配置与技巧
▮▮▮▮▮▮▮ 13.2 Vim 在文本写作中的应用:Markdown, LaTeX 支持
▮▮▮▮▮▮▮ 13.3 Vim 在系统管理中的应用:配置文件编辑、日志分析
▮▮▮▮ 14. chapter 14: Vim 社区与资源
▮▮▮▮▮▮▮ 14.1 Vim 社区文化与学习资源:网站、论坛、邮件列表
▮▮▮▮▮▮▮ 14.2 Vim 常用命令速查表
▮▮▮▮▮▮▮ 14.3 Vim 学习进阶路线图


1. chapter 1: Vim 之旅:起航

1.1 Vim 的起源与演变:从 vi 到 Vim

Vim,全称 Vi IMproved,正如其名,是经典文本编辑器 vi 的增强版。要理解 Vim 的精髓,我们必须先回顾 vi 的历史,以及 Vim 如何在其基础上发展壮大。

vi 的故事始于 20 世纪 70 年代,那时计算机世界还处于早期阶段。Bill Joy,这位 Sun Microsystems 的联合创始人,在加州大学伯克利分校开发了 vivi 的诞生并非偶然,它是 ed 编辑器的可视化版本。ed 是一款行编辑器,用户需要通过命令来操作文本行,效率相对较低,尤其是在图形终端尚未普及的时代。vi 的出现,将文本编辑带入了全新的交互模式,用户可以直接在屏幕上看到文本内容,并使用键盘进行编辑,极大地提升了效率。

vi 的设计灵感来源于 ex 编辑器,ex 也是 Bill Joy 的作品,它扩展了 ed 的功能。vi 实际上是 ex 的可视化模式(Visual mode)。因此,在 Vim 中,我们仍然可以使用许多以冒号 : 开头的命令,这些命令实际上来源于 ex

vi 迅速成为 Unix 系统上的标准编辑器,并随着 Unix 的普及而广泛传播。它的简洁、高效和强大的文本处理能力,赢得了无数程序员和系统管理员的喜爱。然而,vi 并非完美无缺,它在功能上存在一些局限性,例如不支持多级撤销、窗口分割等现代编辑器的常见功能。

进入 20 世纪 90 年代,计算机技术飞速发展,用户对文本编辑器的需求也日益增长。Bram Moolenaar,一位荷兰程序员,为了解决 vi 的一些缺陷,并增加更多现代化的功能,开始开发 Vim。Vim 最初被称为 Vi IMitation,意在尽可能地模仿 vi 的行为,同时加入新的特性。随着时间的推移,Vim 的功能越来越强大,最终更名为 Vi IMproved,寓意着它超越了 vi,成为了更优秀的文本编辑器。

Vim 在保留 vi 核心设计理念的基础上,进行了大量的改进和扩展:

增强的功能:Vim 增加了语法高亮、多级撤销、窗口分割、标签页、拼写检查、自动补全、脚本编程等众多功能,极大地提升了编辑效率和用户体验。
跨平台支持vi 主要运行在 Unix 系统上,而 Vim 被移植到了几乎所有主流操作系统,包括 Windows、macOS、Linux 等,实现了跨平台的一致体验。
可扩展性:Vim 拥有强大的插件系统和 Vimscript 脚本语言,用户可以通过安装插件或编写脚本来定制 Vim,满足各种个性化需求。
活跃的社区:Vim 拥有一个庞大而活跃的社区,用户可以从中获取丰富的学习资源、插件和支持,共同推动 Vim 的发展。

Vim 并非是对 vi 的简单复制,而是在继承其精华的基础上,进行了革命性的创新。它不仅是一款文本编辑器,更是一种文化,一种哲学,代表着高效、专注和极致的文本编辑体验。时至今日,Vim 仍然是程序员和文本工作者的首选工具之一,它的生命力经久不衰,持续影响着文本编辑领域的发展。

1.2 Vim 的设计哲学:模式、效率与可扩展性

Vim 之所以能够从众多文本编辑器中脱颖而出,并受到无数用户的推崇,很大程度上归功于其独特的设计哲学。理解 Vim 的设计哲学,是掌握 Vim 精髓的关键。Vim 的核心设计理念可以概括为三个关键词:模式(Modes)效率(Efficiency)可扩展性(Extensibility)

模式(Modes) 是 Vim 最显著的特点,也是初学者学习 Vim 时最大的障碍。与大多数编辑器不同,Vim 不是一个“所见即所得”(WYSIWYG)的编辑器。它将编辑器的状态划分为不同的模式,每个模式下,键盘按键的含义都不同。Vim 最常用的模式包括:

Normal 模式(普通模式):这是 Vim 的默认模式,也是 Vim 的灵魂所在。在 Normal 模式下,键盘按键主要用于执行各种编辑命令,例如移动光标、删除文本、复制粘贴等。Normal 模式是 Vim 高效编辑的核心,熟练掌握 Normal 模式下的各种命令,可以极大地提升编辑效率。
Insert 模式(插入模式):在 Insert 模式下,Vim 的行为类似于普通的文本编辑器,键盘按键用于输入文本。从 Normal 模式切换到 Insert 模式,通常使用 i, a, o 等命令。
Visual 模式(可视模式):Visual 模式用于文本选择。类似于其他编辑器的选择文本功能,但在 Vim 中,Visual 模式更加强大和灵活,可以进行字符、行、块等多种方式的选择。从 Normal 模式切换到 Visual 模式,通常使用 v, V, Ctrl+v 等命令。
Command-line 模式(命令行模式):Command-line 模式用于执行更复杂的命令,例如保存文件、搜索替换、设置选项等。从 Normal 模式切换到 Command-line 模式,按下 : 键即可。

模式化的设计,使得 Vim 可以用有限的键盘按键,实现丰富的编辑功能。初学者可能会觉得模式切换比较繁琐,但一旦习惯了这种模式化的操作方式,就会发现它带来的效率提升是巨大的。模式切换本身也是一种肌肉记忆的训练,熟练之后,模式切换会变得非常自然流畅,几乎感觉不到模式的存在,只专注于编辑任务本身。

效率(Efficiency) 是 Vim 设计的另一个核心目标。Vim 的所有设计,都旨在提升用户的编辑效率。这种效率体现在多个方面:

键盘操作为主:Vim 强调键盘操作,尽可能减少对鼠标的依赖。所有的编辑操作,几乎都可以通过键盘命令完成,避免了鼠标在键盘和屏幕之间的频繁切换,提高了操作的连贯性和效率。
组合命令:Vim 的命令具有很强的组合性。通过将操作符(operator)和动作(motion)组合起来,可以实现各种复杂的编辑操作。例如,dw 删除一个单词,ciw 修改一个单词,dap 删除一个段落。这种组合命令的方式,使得 Vim 的命令系统非常简洁而强大。
重复操作:Vim 提供了强大的重复操作机制,例如 . 命令可以重复上次的编辑操作,宏(macro)可以录制和回放一系列操作。这些重复操作机制,可以极大地减少重复性劳动,提升编辑效率。
快速移动:Vim 提供了丰富的移动命令,例如单词级移动、行内跳转、段落移动、屏幕滚动等。熟练掌握这些移动命令,可以快速定位到文本的任何位置,提高编辑效率。

可扩展性(Extensibility) 是 Vim 保持活力的重要因素。Vim 具有高度的可扩展性,用户可以通过插件和 Vimscript 脚本来定制 Vim,满足各种个性化需求。

插件系统:Vim 拥有丰富的插件生态系统,涵盖了代码补全、语法检查、文件管理、主题美化等各个方面。通过安装插件,可以极大地扩展 Vim 的功能,使其适应不同的工作场景。
Vimscript 脚本:Vimscript 是一种专门为 Vim 设计的脚本语言,用户可以使用 Vimscript 编写自定义的函数、命令和插件,深度定制 Vim 的行为。Vimscript 的存在,使得 Vim 不仅仅是一个编辑器,更是一个可编程的编辑平台。

模式、效率和可扩展性,这三个核心设计理念相互支撑,共同构成了 Vim 独特的魅力。理解这些设计理念,可以帮助我们更好地学习和使用 Vim,发挥 Vim 的最大潜力。

1.3 安装与配置 Vim:跨平台指南

Vim 是一款跨平台的文本编辑器,几乎可以在所有主流操作系统上运行。本节将介绍在不同操作系统上安装和配置 Vim 的方法,帮助读者快速搭建 Vim 编辑环境。

1. Linux 系统

大多数 Linux 发行版都默认预装了 Vim 或 vi 的简化版本。可以通过终端命令检查是否已安装 Vim:

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 vim --version

如果显示 Vim 的版本信息,则说明已安装。如果没有安装,可以使用包管理器进行安装。

Debian/Ubuntu

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 sudo apt update
2 sudo apt install vim

Fedora/CentOS/RHEL

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 sudo dnf install vim

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 sudo yum install vim

Arch Linux

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 sudo pacman -S vim

安装完成后,再次运行 vim --version 确认安装成功。

2. macOS 系统

macOS 系统通常预装了 vi,但不是完整功能的 Vim。建议安装完整版的 Vim。

Homebrew (推荐):如果你的 macOS 系统安装了 Homebrew 包管理器(https://brew.sh/),可以使用以下命令安装 Vim:

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 brew install vim

MacPorts:如果使用 MacPorts 包管理器(https://www.macports.org/),可以使用以下命令安装 Vim:

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 sudo port install vim

直接下载:也可以从 Vim 官网(https://www.vim.org/)下载 macOS 版本的 Vim 安装包进行安装。

安装完成后,在终端中输入 vim 即可启动 Vim。

3. Windows 系统

Windows 系统默认没有安装 Vim。需要手动下载安装。

Vim 官网下载:访问 Vim 官网下载页面(https://www.vim.org/download.php#pc),选择 gvim_版本号_setup.exe 下载安装程序。gvim 是带有图形界面的 Vim 版本,更适合 Windows 用户。
Chocolatey:如果你的 Windows 系统安装了 Chocolatey 包管理器(https://chocolatey.org/),可以使用以下命令安装 Vim:

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 choco install vim

安装完成后,可以在开始菜单中找到 gVim 图标,点击即可启动图形界面的 Vim。也可以在命令行中使用 vim 命令启动命令行界面的 Vim。

4. Vim 配置

Vim 的配置文件是 .vimrc 文件,位于用户的主目录(home directory)下。Vim 启动时会自动读取 .vimrc 文件中的配置信息。如果 .vimrc 文件不存在,可以手动创建。

创建 .vimrc 文件

Linux/macOS:在终端中输入以下命令创建 .vimrc 文件:

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 touch ~/.vimrc

Windows:在资源管理器中,进入用户主目录(通常是 C:\Users\YourUserName),创建一个名为 _vimrc 的文件。注意文件名以 _ 开头,而不是 .。或者,也可以创建 .vimrc 文件,Vim for Windows 也支持 .vimrc 文件。

编辑 .vimrc 文件:使用任何文本编辑器(包括 Vim 本身)打开 .vimrc 文件,即可编辑 Vim 的配置。例如,可以添加以下配置项:

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 " 设置行号
2 set number
3
4 " 启用语法高亮
5 syntax on
6
7 " 设置缩进为 4 个空格
8 set tabstop=4
9 set softtabstop=4
10 set shiftwidth=4
11 set expandtab

保存 .vimrc 文件后,重新启动 Vim,配置即可生效。关于 .vimrc 文件的详细配置,将在本书的后续章节深入讲解。

通过以上步骤,即可在不同操作系统上完成 Vim 的安装和基本配置。接下来,我们将进入 Vim 的世界,开始探索 Vim 的基本操作。

1.4 首次启动 Vim:界面导览与基本操作

首次启动 Vim,你可能会看到一个简洁甚至有些简陋的界面,与现代图形界面编辑器截然不同。不要被表象所迷惑,Vim 的强大之处,蕴藏在这个看似简单的界面之下。本节将引导你熟悉 Vim 的用户界面,并介绍一些最基本的操作,帮助你迈出 Vim 之旅的第一步。

1.4.1 Vim 的用户界面:窗口、缓冲区与标签页

Vim 的用户界面,主要由三个核心概念组成:窗口(Window)缓冲区(Buffer)标签页(Tab Page)。理解这三个概念之间的关系,对于高效使用 Vim 至关重要。

缓冲区(Buffer):缓冲区是 Vim 中最基本的文件载体。当我们打开一个文件时,Vim 会将文件内容加载到内存中的一个缓冲区。一个缓冲区对应一个文件,但一个文件可以被加载到多个缓冲区。缓冲区是 Vim 编辑操作的核心,所有的编辑操作都是在缓冲区中进行的。可以使用 :buffers:ls 命令查看当前打开的缓冲区列表。

窗口(Window):窗口是缓冲区的可视化展示。一个窗口显示一个缓冲区的内容。Vim 允许在一个 Vim 实例中打开多个窗口,每个窗口可以显示不同的缓冲区,或者同一个缓冲区的不同部分。窗口之间是相互独立的,可以在不同的窗口中编辑不同的文件,或者同时查看同一个文件的不同部分。可以使用 :split:vsplit 命令创建新的窗口,使用 Ctrl+w 系列命令管理窗口。

标签页(Tab Page):标签页是窗口的容器。一个标签页可以包含多个窗口。标签页类似于现代浏览器中的标签页,用于组织和管理多个窗口。可以使用 :tabnew 命令创建新的标签页,使用 :tabnext:tabprev 命令切换标签页,使用 :tabclose 命令关闭标签页。

缓冲区、窗口和标签页之间的关系可以用一个比喻来理解:

缓冲区 就像是内存中的文件副本,是实际存储文件内容的地方。
窗口 就像是显示器上的一个视图,用于展示缓冲区的内容。
标签页 就像是工作区,用于组织和管理多个窗口。

一个 Vim 实例可以包含多个标签页,每个标签页可以包含多个窗口,每个窗口可以显示一个缓冲区。这种多层次的结构,使得 Vim 可以高效地管理多个文件和复杂的编辑任务。

Vim 界面元素:

编辑区域:占据 Vim 窗口的大部分区域,用于显示和编辑文本内容。
命令行区域:位于 Vim 窗口底部,用于输入和显示命令行命令。按下 : 键即可进入命令行模式。
状态行:位于 Vim 窗口底部,命令行区域上方,显示当前文件的信息,例如文件名、文件类型、光标位置、当前模式等。
行号列(可选):位于编辑区域左侧,显示文本的行号。可以通过 set number 命令启用行号显示。

1.4.2 Vim 的模式:Normal, Insert, Visual, Command 等

Vim 最核心的概念之一就是 模式(Modes)。Vim 将编辑器的状态划分为不同的模式,每个模式下,键盘按键的含义都不同。理解和熟练掌握 Vim 的模式,是高效使用 Vim 的关键。

Vim 主要有以下几种模式:

Normal 模式(普通模式):Vim 启动后的默认模式。Normal 模式是 Vim 的核心模式,主要用于执行各种编辑命令,例如移动光标、删除文本、复制粘贴等。在 Normal 模式下,键盘按键不是用于输入字符,而是用于执行命令。例如,h, j, k, l 用于移动光标,d 用于删除,y 用于复制,p 用于粘贴。

Insert 模式(插入模式):Insert 模式用于输入文本。在 Insert 模式下,键盘按键的行为类似于普通的文本编辑器,输入的字符会直接插入到文本中。从 Normal 模式切换到 Insert 模式,可以使用以下命令:

i (insert):在光标当前位置之前插入文本。
a (append):在光标当前位置之后插入文本。
o (open line below):在光标所在行的下方插入新行并进入 Insert 模式。
O (open line above):在光标所在行的上方插入新行并进入 Insert 模式。
I (Insert at beginning of line):在光标所在行的行首进入 Insert 模式。
A (Append at end of line):在光标所在行的行尾进入 Insert 模式。

从 Insert 模式返回 Normal 模式,按下 <Esc> 键或 <Ctrl+[> 组合键。

Visual 模式(可视模式):Visual 模式用于文本选择。类似于其他编辑器的选择文本功能,但在 Vim 中,Visual 模式更加强大和灵活。从 Normal 模式切换到 Visual 模式,可以使用以下命令:

v (visual character):按字符选择文本。
V (visual line):按行选择文本。
Ctrl+v (visual block):按块(矩形区域)选择文本。

在 Visual 模式下,可以使用移动命令(例如 h, j, k, l, w, b 等)来扩展或缩小选择区域。选择文本后,可以执行各种操作,例如删除 (d)、复制 (y)、替换 (c) 等。从 Visual 模式返回 Normal 模式,按下 <Esc> 键。

Command-line 模式(命令行模式):Command-line 模式用于执行更复杂的命令,例如保存文件、搜索替换、设置选项等。从 Normal 模式切换到 Command-line 模式,按下 : 键。此时,光标会移动到 Vim 窗口底部的命令行区域,可以输入命令并按 <Enter> 键执行。常用的命令行命令包括:

:w (write):保存文件。
:q (quit):退出 Vim。
:wq (write and quit):保存文件并退出 Vim。
:e 文件名 (edit):打开指定文件。
:help 命令 (help):查看指定命令的帮助信息。

从 Command-line 模式返回 Normal 模式,按下 <Esc> 键。

除了以上四种常用模式,Vim 还有其他模式,例如 Replace 模式Select 模式 等,将在后续章节中逐步介绍。

1.4.3 最基本的移动:hjkl 键的奥秘

在 Vim 中,移动光标是编辑操作的基础。与大多数编辑器使用方向键移动光标不同,Vim 默认使用 h, j, k, l 四个键来移动光标。这四个键位于键盘的 Home 行,使得手指无需离开 Home 行即可完成光标移动,提高了效率。

h:向左移动光标一个字符 (left)。
j:向下移动光标一行 (down)。
k:向上移动光标一行 (up)。
l:向右移动光标一个字符 (right)。

初学者可能会觉得使用 hjkl 键移动光标不太习惯,但一旦适应了这种方式,就会发现它的优势:

高效性hjkl 键位于 Home 行,手指无需移动即可完成光标移动,减少了手指的移动距离,提高了操作效率。
人体工学hjkl 键的布局符合人体工学,长时间使用不易疲劳。
Vim 文化hjkl 键是 Vim 的标志性特色之一,体现了 Vim 的设计哲学。

除了 hjkl 键,Vim 还提供了其他移动命令,例如单词级移动、行内跳转、段落移动等,将在后续章节中详细介绍。但 hjkl 键是最基本、最常用的移动命令,是 Vim 用户必须掌握的基础技能。

练习:

  1. 启动 Vim。
  2. 进入 Normal 模式(如果不是默认模式)。
  3. 使用 hjkl 键在屏幕上随意移动光标,感受 hjkl 键的移动方式。
  4. 尝试组合使用 hjkl 键,例如连续按 jjjj 向下移动多行,连续按 llll 向右移动多列。
  5. 熟悉 hjkl 键的位置,尽量做到盲打,无需低头看键盘。

通过反复练习,你会逐渐习惯使用 hjkl 键移动光标,并体会到它带来的便捷和高效。hjkl 键是 Vim 之旅的起点,掌握了 hjkl 键,你就迈出了成为 Vim 高手的坚实一步。

ENDOF_CHAPTER_

2. chapter 2: 基础操作:文本编辑的基石

2.1 进入与退出 Insert 模式:开始文本输入

Vim 的核心设计理念之一是模式(modes)。理解和熟练运用不同的模式是掌握 Vim 的关键。在 Vim 中,我们主要与以下几种模式打交道,而 Normal 模式(Normal mode)Insert 模式(Insert mode) 是最基础且最重要的两种。

Normal 模式,也常被称为普通模式命令模式,是 Vim 启动后的默认模式。在这个模式下,键盘上的按键主要被解释为命令,用于移动光标、复制粘贴、删除文本、以及执行各种编辑操作。Normal 模式是 Vim 高效编辑的精髓所在,大部分时间我们都应该处于 Normal 模式,思考和规划我们的编辑操作。

Insert 模式,即插入模式,顾名思义,是用来输入文本的模式。当我们想要像在其他编辑器中一样直接输入文字时,就需要切换到 Insert 模式。

进入 Insert 模式 的方法有很多,不同的命令会从不同的位置进入 Insert 模式,并可能产生不同的初始行为:

i (insert):在光标当前位置之前进入 Insert 模式。这是最常用的进入 Insert 模式的命令。
a (append):在光标当前位置之后进入 Insert 模式。
o (open line below):在当前行之下新建一行并进入 Insert 模式,光标位于新行的行首。
O (open line above):在当前行之上新建一行并进入 Insert 模式,光标位于新行的行首。
I (Insert at beginning of line):移动光标到当前行行首并进入 Insert 模式。
A (Append at end of line):移动光标到当前行行尾并进入 Insert 模式。

这些命令都是在 Normal 模式下使用的。例如,在 Normal 模式下按下 i 键,Vim 就会切换到 Insert 模式,并且你可以在屏幕的左下角看到 -- INSERT -- 的提示,表明你当前处于 Insert 模式。

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 -- INSERT --

退出 Insert 模式 的方法相对简单,最常用的方法是按下 <Esc> (Escape 键)。按下 <Esc> 键后,Vim 会立即返回到 Normal 模式,-- INSERT -- 的提示也会消失。 另一个退出 Insert 模式的方法是使用 Ctrl + c 组合键,效果与 <Esc> 键类似,也是返回到 Normal 模式。

理解和熟练掌握 Normal 模式和 Insert 模式之间的切换是学习 Vim 的第一步。在实际使用中,你会频繁地在这两种模式之间切换,Normal 模式用于快速定位和操作,Insert 模式用于文本输入。这种模式化的设计,正是 Vim 高效编辑的基石。

2.2 文本插入、删除与替换:字符、单词与行

在 Insert 模式下,文本的输入方式与常见的文本编辑器并无二致。你可以像平常一样输入字符、空格、换行等。本节重点介绍在 Normal 模式下,如何高效地进行文本的插入、删除和替换操作。

文本插入,实际上我们在上一节已经介绍过了进入 Insert 模式的各种命令 i, a, o, I, A, O。它们不仅是进入 Insert 模式的命令,也隐含了文本插入的动作。再次回顾一下它们的区别:

i (insert):在光标前插入。
a (append):在光标后追加。
o (open line below):在当前行下方打开新行并插入。
O (open line above):在当前行上方打开新行并插入。
I (Insert at beginning of line):在行首插入。
A (Append at end of line):在行尾追加。

文本删除,在 Vim 中有多种删除命令,可以按字符、单词、行等不同单位进行删除。

x (delete character):删除光标所在位置的字符。相当于其他编辑器中的 Delete 键。
X (delete character before cursor):删除光标之前位置的字符。相当于其他编辑器中的 Backspace 键。
d{motion} (delete with motion):这是一个非常强大的删除命令,它结合了 删除操作符 d (delete)移动命令 {motion} (motion){motion} 可以是任何 Vim 的移动命令,例如 w (单词),e (单词末尾),b (单词开头),$ (行尾),^ (行首),gg (文件开头),G (文件结尾) 等。
▮▮▮▮⚝ 例如,dw 删除从光标位置到单词末尾的字符(包括光标所在字符到单词末尾)。
▮▮▮▮⚝ d$ 删除从光标位置到行尾的字符。
▮▮▮▮⚝ dgg 删除从光标位置到文件开头的字符。
dd (delete line):删除当前行。相当于 d_ (删除到行尾) 或 d0 (删除到行首) 的组合效果,但更简洁常用。可以使用数字前缀来删除多行,例如 3dd 删除从当前行开始的 3 行。

文本替换,Vim 也提供了多种替换命令,可以替换字符、单词、行等。

r{char} (replace character):将光标所在位置的字符替换为 {char}。例如,ra 将光标下的字符替换为 a。替换后自动返回 Normal 模式。
R (replace mode):进入 Replace 模式,类似于 Insert 模式,但输入的字符会替换光标所在位置的字符,而不是插入。按下 <Esc> 键退出 Replace 模式。
c{motion} (change with motion):类似于 d{motion},但删除文本后会立即进入 Insert 模式,等待输入新的文本进行替换。cchange 操作符
▮▮▮▮⚝ 例如,cw 替换从光标位置到单词末尾的字符,并进入 Insert 模式。
▮▮▮▮⚝ c$ 替换从光标位置到行尾的字符,并进入 Insert 模式。
▮▮▮▮⚝ cc 替换整行,并进入 Insert 模式。相当于 S 命令 (Change line)。可以使用数字前缀,例如 2cc 替换当前行和下一行,并进入 Insert 模式。
s (substitute character):删除光标所在位置的字符,并进入 Insert 模式,等待输入新的字符进行替换。相当于 cl (change letter)。
S (substitute line):删除整行,并进入 Insert 模式,等待输入新的行进行替换。相当于 cc (change current line)。

操作符 (operator) 与动作 (motion) 的组合 是 Vim 编辑的核心概念之一。d (delete), c (change), y (yank, 复制) 等都是操作符,它们本身并不执行任何操作,而是等待一个动作命令 {motion} 来指定操作的范围。这种组合方式极大地扩展了 Vim 命令的灵活性和效率。例如,d 操作符可以与 w, e, b, $, ^, gg, G, {, }, ), ( 等各种动作命令组合,实现对单词、行、段落、句子、甚至整个文件的删除操作。c 操作符和 y 操作符也是如此。

理解并熟练运用操作符与动作的组合,是掌握 Vim 高效编辑的关键一步。

2.3 撤销、重做与重复操作:. 命令的威力

在文本编辑过程中,撤销 (undo) 和重做 (redo) 是非常常用的功能,Vim 提供了简单而强大的撤销和重做机制。

撤销 (Undo)

u (undo):撤销最近一次的修改。可以连续按 u 键来撤销之前的多次修改,回到更早的版本。Vim 默认会记录编辑历史,允许你撤销多次操作。

重做 (Redo)

Ctrl + r (redo):重做被撤销的操作。在执行撤销操作 u 之后,可以使用 Ctrl + r 来重做刚才被撤销的修改。可以连续按 Ctrl + r 来重做多次撤销的操作。

重复操作 (.)

. (repeat last change):重复上一次的修改操作。这可能是 Vim 中最强大的命令之一。. 命令可以重复任何非移动类的编辑操作,例如插入文本、删除、替换、修改等。

. 命令的威力在于它可以将一系列复杂的操作记录下来,并通过一个简单的 . 键重复执行。例如:

假设你想要将一个文件中所有出现的 "apple" 替换为 "orange"。你可以这样做:

① 在 Normal 模式下,使用 /apple 搜索到第一个 "apple"。
② 使用 cworange<Esc> 命令将 "apple" 替换为 "orange" 并返回 Normal 模式。
③ 使用 n 命令跳转到下一个 "apple"。
按下 .,Vim 会自动重复上一次的替换操作 cworange<Esc>,将当前的 "apple" 也替换为 "orange"。
⑤ 继续使用 n 命令和 . 命令,可以快速替换所有 "apple"。

在这个例子中,我们只需要输入一次完整的替换命令 cworange<Esc>,之后只需要按 n. 键就可以高效地完成批量替换。. 命令极大地提高了重复性编辑任务的效率。

Vim 的撤销和重做机制非常强大,它不仅仅是简单的单步撤销和重做,而是可以回溯到编辑历史中的任何一个状态。并且,. 命令的重复操作功能,更是将 Vim 的效率提升到了一个新的高度。熟练运用 u, Ctrl + r, 和 . 命令,可以让你在 Vim 中更加自信和高效地进行文本编辑。

2.4 保存与打开文件:文件操作基础

在 Vim 中进行文本编辑,最终目的是将修改保存到文件中,或者打开已有的文件进行编辑。本节介绍 Vim 中最基本的文件操作命令。

保存文件

:w (write):保存当前文件。如果当前文件是新创建的,:w 命令会要求你输入文件名。如果文件已经存在,:w 命令会将当前缓冲区的内容写入到文件中,覆盖原有内容。
:w {filename} (write to file):将当前缓冲区的内容保存到指定的文件 {filename}。如果指定的文件不存在,则会创建新文件;如果文件已存在,则会覆盖原有文件。这相当于另存为 (Save As) 功能。
:wq (write and quit):保存当前文件并退出 Vim。这是最常用的保存并退出的命令。
:x (write and exit):保存当前文件并退出 Vim。与 :wq 类似,但 :x 命令只有在文件内容被修改时才会执行保存操作,如果文件内容没有修改,则直接退出,不会写入文件,效率更高。
:sav[eas] {filename} (save as):另存为。将当前缓冲区的内容保存到指定的文件 {filename},并切换到新文件进行编辑。原文件仍然保持打开状态。
:w! (write force):强制保存。在某些情况下,Vim 可能因为文件只读或者其他原因拒绝保存文件。:w! 命令会强制写入文件,即使文件是只读的。需要谨慎使用 :w!,因为它可能会覆盖文件的原有权限或导致数据丢失。

打开文件

:e {filename} (edit):打开指定的文件 {filename} 进行编辑。如果当前缓冲区有未保存的修改,Vim 会给出警告,可以使用 :e! 命令强制放弃当前修改并打开新文件。
:o {filename} (open):与 :e {filename} 命令功能相同,都是打开指定文件进行编辑。:o:edit 的简写形式。
:find {filename} (find file):查找并打开文件:find 命令会在 Vim 的 path 选项指定的目录列表中查找文件 {filename}。可以使用文件名的一部分进行模糊查找,Vim 会列出匹配的文件供你选择。这对于在大型项目中快速查找文件非常有用。
④ 在 Vim 启动时,可以直接在命令行参数中指定要打开的文件名,例如 vim filename.txt

文件路径

:w, :e, :o, :find 等文件操作命令中,可以使用相对路径绝对路径来指定文件名。

相对路径:相对于当前工作目录的路径。例如,file.txt 表示当前目录下的 file.txt 文件,subdir/file.txt 表示当前目录下的 subdir 子目录中的 file.txt 文件,../file.txt 表示上级目录下的 file.txt 文件。
绝对路径:从根目录开始的完整路径。例如,/home/user/documents/file.txt (Linux/macOS) 或 C:\Users\User\Documents\file.txt (Windows)。

文件操作基础

Vim 的文件操作是基于缓冲区 (buffer) 的概念。当你打开一个文件时,Vim 会将文件内容加载到内存中的一个缓冲区中。你在 Vim 中进行的所有编辑操作都是在缓冲区中进行的,而不是直接修改磁盘上的文件。当你执行 :w 命令保存文件时,Vim 才会将缓冲区的内容写入到磁盘文件中。

理解缓冲区的概念有助于更好地理解 Vim 的文件管理机制,我们将在后续章节中更深入地探讨缓冲区、窗口和标签页的管理。

掌握本节介绍的保存和打开文件的基本命令,是使用 Vim 进行文本编辑的基础。在实际使用中,你会频繁地使用这些命令来管理你的文件。

ENDOF_CHAPTER_

3. chapter 3: 高效移动:指尖上的舞蹈

3.1 单词级移动:w, b, e, ge

在 Vim 的世界里,高效移动是提升编辑效率的关键。本节我们将深入探讨单词级移动命令,它们是快速浏览和编辑文本的基础。掌握这些命令,你的手指将在文本中翩翩起舞,效率倍增。

w下一个单词词首(word forward)。将光标移动到下一个单词的词首。Vim 将单词(word)定义为字母、数字和下划线的组合,或者由非空白字符组成的序列,由空格、制表符或行尾分隔。

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 This is a sample sentence.
2 ^ 光标初始位置

▮▮▮▮按下 w 后:

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 This is a sample sentence.
2 ^ 光标移动到 "is" 的词首

▮▮▮▮再次按下 w

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 This is a sample sentence.
2 ^ 光标移动到 "a" 的词首

▮▮▮▮以此类推。w 命令非常适合逐词向前浏览文本。

b上一个单词词首(word backward)。将光标移动到上一个单词的词首。与 w 命令方向相反。

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 This is a sample sentence.
2 ^ 光标初始位置

▮▮▮▮按下 b 后:

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 This is a sample sentence.
2 ^ 光标移动到 "sentence" 的词首

▮▮▮▮再次按下 b

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 This is a sample sentence.
2 ^ 光标移动到 "sample" 的词首

▮▮▮▮b 命令用于快速回顾之前的单词,方便修改或检查。

e单词词尾(word end)。将光标移动到当前单词或下一个单词的词尾。

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 This is a sample sentence.
2 ^ 光标初始位置

▮▮▮▮按下 e 后:

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 This is a sample sentence.
2 ^ 光标移动到 "This" 的词尾 "s"

▮▮▮▮再次按下 e

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 This is a sample sentence.
2 ^ 光标移动到 "is" 的词尾 "s"

▮▮▮▮e 命令在需要操作单词末尾时非常有用,例如删除到单词末尾可以使用 de

ge上一个单词词尾(word end backward)。将光标移动到上一个单词的词尾。是 e 命令的反向操作。

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 This is a sample sentence.
2 ^ 光标初始位置

▮▮▮▮按下 ge 后:

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 This is a sample sentence.
2 ^ 光标移动到 "sentence" 的词尾 "e"

▮▮▮▮再次按下 ge

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 This is a sample sentence.
2 ^ 光标移动到 "sample" 的词尾 "e"

▮▮▮▮ge 命令可以方便地定位到前一个单词的末尾。

计数(Count): 这些单词移动命令都可以接受数字前缀,表示重复执行的次数。例如,3w 将光标向前移动三个单词的词首,2b 将光标向后移动两个单词的词首。

大写版本(Uppercase versions): W, B, E, gE 命令与小写版本类似,但它们将 WORD (大单词) 视为由空格分隔的字符序列。这意味着它们会跳过标点符号和特殊字符,将它们视为单词分隔符。在处理代码或包含特殊字符的文本时,大写版本可能更方便。

实战技巧:

⚝ 结合操作符:单词移动命令通常与 Vim 的操作符(operators)结合使用,例如 d (删除, delete), c (修改, change), y (复制, yank)。例如,dw 删除从当前光标位置到下一个单词词首的内容,cw 修改从当前光标位置到下一个单词词首的内容。
⚝ 快速浏览代码:在代码文件中,wb 可以帮助你快速浏览变量名、函数名等。
⚝ 编辑文本段落:结合计数和操作符,可以快速删除或修改一段文字。

掌握单词级移动命令是 Vim 效率提升的第一步,熟练运用它们,你会发现文本编辑变得流畅而高效。

3.2 行内快速跳转:0, $, ^, f, F, t, T

行内移动是日常编辑中最频繁的操作之一。Vim 提供了丰富的行内跳转命令,让你的光标在行内自由穿梭,精准定位。

0 (数字零):行首(beginning of line)。将光标移动到当前行的绝对行首,即行的第一个字符,包括缩进的空格或制表符。

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 This is a line with indentation.
2 ^ 光标可能在行中的任意位置

▮▮▮▮按下 0 后:

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 This is a line with indentation.
2 ^ 光标移动到行首

▮▮▮▮0 命令非常适合快速回到行首进行操作,例如在行首插入或删除内容。

^行首非空白字符(first non-blank character of line)。将光标移动到当前行第一个非空白字符的位置。如果行首有缩进,则光标会移动到第一个实际文本字符。

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 This is a line with indentation.
2 ^ 光标可能在行中的任意位置

▮▮▮▮按下 ^ 后:

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 This is a line with indentation.
2 ^ 光标移动到第一个非空白字符 "T"

▮▮▮▮^ 命令在编辑代码或格式化文本时非常有用,可以快速定位到代码或文本的起始位置。

$行尾(end of line)。将光标移动到当前行的行尾

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 This is a line of text.
2 ^ 光标可能在行中的任意位置

▮▮▮▮按下 $ 后:

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 This is a line of text.
2 ^ 光标移动到行尾

▮▮▮▮$ 命令常用于在行尾追加内容,或者删除到行尾等操作。

f{char}查找字符向前(find character forward)。在当前行向右查找字符 {char},并将光标移动到该字符处。例如,fa 会在当前行向右查找第一个字符 a 并移动光标到那里。

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 This is a sample sentence.
2 ^ 光标初始位置

▮▮▮▮按下 fs 后:

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 This is a sample sentence.
2 ^ 光标移动到第一个 "s"

▮▮▮▮f 命令可以快速定位到行内特定字符,非常方便。

F{char}查找字符向后(find character backward)。在当前行向左查找字符 {char},并将光标移动到该字符处。与 f 命令方向相反。例如,Fa 会在当前行向左查找第一个字符 a 并移动光标到那里。

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 This is a sample sentence.
2 ^ 光标初始位置

▮▮▮▮按下 Fs 后:

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 This is a sample sentence.
2 ^ 光标移动到第一个 "s" (从右向左)

▮▮▮▮F 命令用于向后查找字符,与 f 命令互补。

t{char}到字符前(till character forward)。在当前行向右查找字符 {char},并将光标移动到该字符之前的位置。例如,ta 会在当前行向右查找第一个字符 a 并移动光标到 a 之前的位置。

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 This is a sample sentence.
2 ^ 光标初始位置

▮▮▮▮按下 ts 后:

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 This is a sample sentence.
2 ^ 光标移动到第一个 "s" 之前的位置

▮▮▮▮t 命令与 f 命令类似,但光标停留在目标字符之前,方便进行插入或替换操作。

T{char}到字符前向后(till character backward)。在当前行向左查找字符 {char},并将光标移动到该字符之后的位置。与 t 命令方向相反。例如,Ta 会在当前行向左查找第一个字符 a 并移动光标到 a 之后的位置。

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 This is a sample sentence.
2 ^ 光标初始位置

▮▮▮▮按下 Ts 后:

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 This is a sample sentence.
2 ^ 光标移动到第一个 "s" (从右向左) 之后的位置

▮▮▮▮T 命令用于向后查找字符,并将光标停留在目标字符之后。

分号 ; 和逗号 ,: f, F, t, T 命令执行后,可以使用 ; 命令重复上一次的查找操作,方向相同。使用 , 命令重复上一次的查找操作,方向相反。这对于在行内多次查找相同字符非常方便。

计数(Count): f, F, t, T 命令也可以接受数字前缀,表示跳过多少个匹配的字符。例如,2fa 会跳过第一个 a,移动到第二个 a

实战技巧:

⚝ 快速定位:f, F, t, T 命令是行内快速定位的利器,可以替代多次按 hl 键。
⚝ 精准操作:结合操作符和 t 命令,可以精确地操作到某个字符之前的位置,例如 ct" 修改到下一个双引号之前的内容。
⚝ 代码导航:在代码中,可以使用 fF 快速跳转到变量名、函数名中的特定字符。

熟练掌握这些行内移动命令,你的光标将如同行云流水,在文本行间自由穿梭,编辑效率将得到质的飞跃。

3.3 段落与句子移动:{, }, ), (

除了单词和行,文本通常还以段落和句子为单位组织。Vim 提供了段落和句子级别的移动命令,让你能够更宏观地浏览和编辑文本结构。

{上一个段落起始(previous paragraph start)。将光标移动到当前段落的起始位置,如果光标已经在段落起始位置,则移动到上一个段落的起始位置。Vim 将段落(paragraph)定义为由空行分隔的文本块。

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 This is the first paragraph.
2 It has multiple lines.
3
4 This is the second paragraph.
5 Another line in the second paragraph.
6 ^ 光标可能在第二个段落的任意位置

▮▮▮▮按下 { 后:

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 This is the first paragraph.
2 It has multiple lines.
3
4 This is the second paragraph.
5 Another line in the second paragraph.
6 ^ 光标移动到第二个段落的起始空行之后的第一行

▮▮▮▮再次按下 { 后:

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 This is the first paragraph.
2 It has multiple lines.
3
4 This is the second paragraph.
5 Another line in the second paragraph.
6 ^ 光标移动到第一个段落的起始空行之后的第一行

▮▮▮▮{ 命令用于快速定位到当前或上一个段落的开头,方便进行段落级别的操作。

}下一个段落起始(next paragraph start)。将光标移动到下一个段落的起始位置。如果光标已经在段落末尾,则移动到下一个段落的起始位置

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 This is the first paragraph.
2 It has multiple lines.
3 ^ 光标可能在第一个段落的任意位置
4
5 This is the second paragraph.
6 Another line in the second paragraph.

▮▮▮▮按下 } 后:

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 This is the first paragraph.
2 It has multiple lines.
3 ^ 光标移动到第二个段落的起始空行之后的第一行
4
5 This is the second paragraph.
6 Another line in the second paragraph.

▮▮▮▮} 命令用于快速定位到下一个段落的开头。

(上一个句子起始(previous sentence start)。将光标移动到当前句子的起始位置,如果光标已经在句子起始位置,则移动到上一个句子的起始位置。Vim 将句子(sentence)定义为以句号 ., 问号 ?, 或感叹号 ! 结尾,后跟空格或换行符的文本。

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 This is the first sentence. This is the second sentence.
2 ^ 光标可能在第二个句子的任意位置

▮▮▮▮按下 ( 后:

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 This is the first sentence. This is the second sentence.
2 ^ 光标移动到第二个句子的起始位置 "This"

▮▮▮▮再次按下 ( 后:

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 This is the first sentence. This is the second sentence.
2 ^ 光标移动到第一个句子的起始位置 "This"

▮▮▮▮( 命令用于快速定位到当前或上一个句子的开头。

)下一个句子起始(next sentence start)。将光标移动到下一个句子的起始位置。如果光标已经在句子末尾,则移动到下一个句子的起始位置

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 This is the first sentence. This is the second sentence.
2 ^ 光标可能在第一个句子的任意位置

▮▮▮▮按下 ) 后:

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 This is the first sentence. This is the second sentence.
2 ^ 光标移动到第二个句子的起始位置 "This"

▮▮▮▮ 命令用于快速定位到下一个句子的开头。

计数(Count): {, }, (, ) 命令同样可以接受数字前缀,表示移动的段落或句子数量。例如,2} 将光标向下移动两个段落的起始位置。

实战技巧:

⚝ 文本结构化编辑:段落和句子移动命令非常适合处理结构化的文本,例如 Markdown 文档、代码注释等。
⚝ 快速浏览长文档:在阅读长文档时,可以使用 }) 命令快速浏览段落和句子,把握文章结构。
⚝ 结合操作符:与操作符结合,可以快速删除、复制或修改整个段落或句子,例如 d} 删除到段落末尾,y) 复制到句子末尾。

掌握段落和句子移动命令,你将能够以更宏观的视角编辑文本,处理大段文字将变得更加轻松高效。

3.4 屏幕滚动与跳转:Ctrl+u, Ctrl+d, Ctrl+b, Ctrl+f, H, M, L

当处理超出屏幕范围的文本时,屏幕滚动和跳转命令就显得尤为重要。Vim 提供了多种屏幕滚动和跳转方式,让你在文档中自由纵览。

Ctrl+u向上滚动半屏(scroll up half screen)。将屏幕向上滚动半屏,显示文档的上方内容。u 代表 "up"。

▮▮▮▮当需要查看屏幕上方的内容时,Ctrl+u 是一个快速而平滑的滚动方式。

Ctrl+d向下滚动半屏(scroll down half screen)。将屏幕向下滚动半屏,显示文档的下方内容。d 代表 "down"。

▮▮▮▮Ctrl+d 用于查看屏幕下方的内容,与 Ctrl+u 方向相反。

Ctrl+b向上滚动整屏(scroll up full screen)。将屏幕向上滚动整屏,显示文档的上一页内容。b 代表 "backward"。

▮▮▮▮Ctrl+b 可以快速翻页到上一页,适合快速浏览文档。

Ctrl+f向下滚动整屏(scroll down full screen)。将屏幕向下滚动整屏,显示文档的下一页内容。f 代表 "forward"。

▮▮▮▮Ctrl+f 用于快速翻页到下一页,与 Ctrl+b 方向相反。

H屏幕顶部(top of screen)。将光标移动到当前屏幕的顶部H 代表 "High"。

▮▮▮▮H 命令可以快速将光标定位到当前屏幕可见区域的顶部,方便从屏幕顶部开始阅读或编辑。

M屏幕中间(middle of screen)。将光标移动到当前屏幕的中间行M 代表 "Middle"。

▮▮▮▮M 命令将光标置于屏幕中央,提供一个居中的视角,适合阅读长篇文章。

L屏幕底部(bottom of screen)。将光标移动到当前屏幕的底部L 代表 "Low"。

▮▮▮▮L 命令可以将光标快速定位到屏幕底部,方便查看屏幕末尾的内容。

计数(Count): Ctrl+uCtrl+d 命令可以接受数字前缀,表示滚动的行数。例如,5Ctrl+d 将向下滚动 5 行。Ctrl+bCtrl+f 的计数表示滚动多少屏,但通常不常用。

实战技巧:

⚝ 阅读长文档:Ctrl+u, Ctrl+d, Ctrl+b, Ctrl+f 命令是阅读长文档的利器,可以快速浏览和翻页。
⚝ 代码审查:在代码审查时,可以使用屏幕滚动命令快速浏览代码文件。
⚝ 结合 H, M, LH, M, L 命令可以快速调整视角,结合屏幕滚动命令,可以更灵活地浏览文档。

熟练运用屏幕滚动和跳转命令,你将能够轻松驾驭长篇文档,在文本海洋中自由翱翔。

3.5 标记与跳转:m, `

在编辑过程中,我们经常需要在文档的不同位置之间来回跳转。Vim 的标记(mark)功能允许你在文档中设置书签,并在需要时快速跳回标记位置,极大地提升了编辑效率。

m{a-zA-Z}设置标记(set mark)。使用 m 命令后跟一个字母(azAZ),可以在当前光标位置设置一个局部标记(小写字母 a-z,只在当前缓冲区有效)或全局标记(大写字母 A-Z,跨缓冲区和文件有效)。例如,ma 在当前位置设置一个名为 a 的局部标记,mA 设置一个名为 A 的全局标记。

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 This is a line where we set a mark.
2 ^ 光标初始位置

▮▮▮▮按下 ma 后,就在当前位置设置了一个名为 a 的局部标记。

`{mark}`:**跳转到标记行首(jump to mark line start)**。使用反引号 `` 后跟一个标记名a-zA-Z),可以将光标跳转到**标记所在行的行首**。例如,``a跳转到标记a所在行的行首,``A跳转到标记A` 所在行的行首。

▮▮▮▮假设之前在某行设置了标记 a

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 ... (其他行) ...
2 This is a line where we set a mark. <-- 标记 'a' 设置在此行
3 ... (其他行) ...
4
5 Now we are at a different location.
6 ^ 当前光标位置

▮▮▮▮按下 `a` 后:

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 ... (其他行) ...
2 This is a line where we set a mark. <-- 光标跳转到标记 'a' 所在行的行首
3 ... (其他行) ...

' {mark}跳转到标记位置(jump to mark position)。使用单引号 ' 后跟一个标记名 {mark}a-zA-Z),可以将光标跳转到标记设置时的精确位置(行和列)。例如,'a 跳转到标记 a 设置时的精确位置,'A 跳转到标记 A 设置时的精确位置。

▮▮▮▮假设之前在某个位置设置了标记 a

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 ... (其他行) ...
2 This is a line where we set a mark.
3 ^ 标记 'a' 设置在此位置
4 ... (其他行) ...
5
6 Now we are at a different location.
7 ^ 当前光标位置

▮▮▮▮按下 'a 后:

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 ... (其他行) ...
2 This is a line where we set a mark.
3 ^ 光标跳转到标记 'a' 设置时的精确位置
4 ... (其他行) ...

跳转到上次编辑位置(jump to last edit position)。连续按两次反引号 ``,可以将光标跳转到上次编辑的位置。这对于在编辑过程中快速返回到之前修改的地方非常有用。

'.跳转到上次修改位置(jump to last modification position)。单引号加句点 '. 可以将光标跳转到上次修改的起始位置

'"跳转到上次退出位置(jump to last buffer exit position)。单引号加双引号 '" 可以将光标跳转到上次退出当前缓冲区时的位置

'^跳转到上次插入位置(jump to last insert position)。单引号加 ^ 可以将光标跳转到上次进入插入模式的位置

'[跳转到上次操作起始位置(jump to last operation start position)。单引号加 [ 可以将光标跳转到上次操作的起始位置,例如删除、修改等操作。

']跳转到上次操作结束位置(jump to last operation end position)。单引号加 ] 可以将光标跳转到上次操作的结束位置

标记类型:

局部标记 (a-z): 只在当前缓冲区内有效,关闭缓冲区后标记失效。适用于在单个文件中快速跳转。
全局标记 (A-Z): 跨缓冲区和文件有效,即使关闭文件后标记仍然存在。适用于在项目文件中进行标记和跳转。
自动标记: Vim 自动维护一些特殊标记,例如 ` (上次编辑位置), '. (上次修改位置) 等,方便进行历史位置跳转。

实战技巧:

⚝ 代码导航:在代码文件中,可以使用局部标记 a-z 在函数、类、变量定义等位置设置标记,方便快速跳转。
⚝ 文档校对:在校对文档时,可以使用全局标记 A-Z 在需要重点关注的位置设置标记,方便在不同文件之间跳转检查。
⚝ 快速返回编辑点:使用 ` 可以快速返回到上次编辑的位置,提高修改效率。 ⚝ 结合操作符:标记可以与操作符结合使用,例如d'a删除从当前位置到标记a` 所在行的内容。

掌握标记与跳转功能,你将在文档中拥有瞬间移动的能力,编辑效率将得到质的飞跃,真正体验到指尖上的舞蹈。

ENDOF_CHAPTER_

4. chapter 4: 文本操作进阶:精准编辑的艺术

4.1 Visual 模式详解:字符、行与块选择

Visual 模式(Visual Mode)是 Vim 中一个非常强大的模式,它允许你可视化地选择文本区域,然后对选中的文本执行各种操作,例如删除、复制、替换等。Visual 模式是精准编辑的核心,它让你从传统的字符级操作提升到区域级操作,极大地提高了文本处理的效率和灵活性。

Vim 提供了三种类型的 Visual 模式,以满足不同粒度的文本选择需求:

4.1.1 字符选择模式(Character-wise Visual Mode)

字符选择模式是最基础的 Visual 模式,它以字符为单位进行文本选择。

进入字符选择模式:

在 Normal 模式下,按下 v 键即可进入字符选择模式。此时,光标所在位置是选区的起始点。

选择文本:

进入字符选择模式后,你可以使用各种移动命令(例如 hjklwbft 等)来扩展或缩小选区。选中的文本会高亮显示。

退出字符选择模式:

按下 <Esc> 键或 v 键可以退出字符选择模式,返回到 Normal 模式。

示例:

假设你有一行文本:This is a line of text.,光标位于 T 处。

① 按下 v 键,进入字符选择模式。
② 按下 w 键,选中 This
③ 继续按下 w 键,选中 This is
④ 按下 e 键,选中 This is a
⑤ 按下 Esc 键,退出字符选择模式。

4.1.2 行选择模式(Line-wise Visual Mode)

行选择模式以行为单位进行文本选择,选中从光标所在行开始到目标行的所有完整行。

进入行选择模式:

在 Normal 模式下,按下 V 键(大写 V)即可进入行选择模式。此时,光标所在行被选中。

选择文本:

进入行选择模式后,可以使用上下移动命令(例如 jk}, { 等)来扩展或缩小选区。选中的行会高亮显示。

退出行选择模式:

按下 <Esc> 键或 V 键可以退出行选择模式,返回到 Normal 模式。

示例:

假设你有以下文本:

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 Line 1
2 Line 2
3 Line 3
4 Line 4

光标位于 Line 1L 处。

① 按下 V 键,进入行选择模式,Line 1 被选中。
② 按下 j 键,选中 Line 1Line 2 两行。
③ 继续按下 j 键,选中 Line 1Line 2Line 3 三行。
④ 按下 Esc 键,退出行选择模式。

4.1.3 块选择模式(Block-wise Visual Mode)

块选择模式允许你选择一个矩形区域的文本块,这在处理列数据或表格时非常有用。

进入块选择模式:

在 Normal 模式下,按下 <Ctrl + v> 组合键即可进入块选择模式。此时,光标所在位置是块选区的左上角。

选择文本:

进入块选择模式后,可以使用各种移动命令来扩展或缩小矩形选区。选中的文本块会高亮显示。

退出块选择模式:

按下 <Esc> 键或 <Ctrl + v> 组合键可以退出块选择模式,返回到 Normal 模式。

示例:

假设你有以下文本:

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 Column1 Column2 Column3
2 Data1 Data2 Data3
3 Data4 Data5 Data6

光标位于 Column1C 处。

① 按下 <Ctrl + v> 组合键,进入块选择模式。
② 按下 j 键,向下扩展一行。
③ 继续按下 j 键,向下扩展到第三行。
④ 按下 l 键,向右扩展一列。
⑤ 继续按下 l 键,向右扩展到第二列。
⑥ 按下 Esc 键,退出块选择模式,此时 "Col"、"Dat"、"Dat" 组成的矩形块被选中。

Visual 模式的通用操作:

在任何 Visual 模式下,选中文本后,你可以执行以下常用操作:

d (delete): 删除选中的文本。
y (yank): 复制选中的文本到寄存器。
c (change): 删除选中的文本并进入 Insert 模式,用于替换选中文本。
> (indent): 增加选中文本的缩进。
< (unindent): 减少选中文本的缩进。
= (equal): 自动缩进选中文本。
~ (swap case): 切换选中文本的大小写。
u (lowercase): 将选中文本转换为小写。
U (uppercase): 将选中文本转换为大写。
: (command-line): 进入命令行模式,可以对选中文本执行更复杂的操作,例如替换、过滤等。在命令行中,'<,'> 会自动填充,表示选区范围。

Visual 模式是 Vim 精准编辑的核心工具,熟练掌握 Visual 模式及其各种操作,可以极大地提高文本编辑效率。

4.2 剪切、复制与粘贴:寄存器的概念

在 Vim 中,剪切、复制和粘贴操作与传统的编辑器有所不同,其核心概念是寄存器(Registers)。寄存器是 Vim 用来存储文本片段的容器,可以理解为剪贴板。Vim 提供了多种寄存器,使得文本操作更加灵活和强大。

寄存器的类型:

Vim 的寄存器可以分为以下几类:

无名寄存器(Unnamed Register):" 表示,是默认寄存器。当我们使用 d (delete)、c (change)、y (yank) 等命令时,被删除或复制的文本默认会存放到无名寄存器中。
具名寄存器(Named Registers):azAZ 表示,共有 26 个具名寄存器。可以使用 " + 寄存器名来指定使用哪个具名寄存器。例如,"ayiw 表示复制光标所在单词到寄存器 a
▮▮▮▮⚝ 小写具名寄存器 (az): 覆盖式写入。每次使用小写具名寄存器进行删除、复制操作时,会将寄存器原有的内容完全替换为新的内容。
▮▮▮▮⚝ 大写具名寄存器 (AZ): 追加式写入。使用大写具名寄存器时,会将新的内容追加到寄存器原有内容的末尾。例如,如果寄存器 a 中已经有内容,使用 "Ayw 会将当前单词追加到寄存器 a 的内容之后。
数字寄存器(Numbered Registers):09 表示。
▮▮▮▮⚝ 寄存器 0 复制专用寄存器(Yank register)。只有 y (yank) 命令会使用寄存器 0,用于存储最近一次复制的内容。
▮▮▮▮⚝ 寄存器 19 删除寄存器(Delete registers)。寄存器 1 存储最近一次删除的内容,寄存器 2 存储倒数第二次删除的内容,以此类推,寄存器 9 存储较早的删除内容。当删除的内容超过一行时,会发生寄存器轮换,1 -> 2 -> ... -> 9 -> 消失。
只读寄存器(Read-only Registers):
▮▮▮▮⚝ . 寄存器(Dot register): 存储上次插入模式中插入的文本。
▮▮▮▮⚝ % 寄存器(Percent register): 存储当前文件名。
▮▮▮▮⚝ # 寄存器(Alternate file register): 存储上次编辑的文件名。
▮▮▮▮⚝ : 寄存器(Command register): 存储上次执行的命令行命令。
▮▮▮▮⚝ / 寄存器(Search register): 存储上次搜索的模式。
表达式寄存器(Expression Register):= 表示。允许执行 Vimscript 表达式,并将表达式的结果作为文本插入。

剪切(Delete):d 命令

d 命令用于删除文本,并将删除的文本存放到寄存器中(默认是无名寄存器 ",如果删除内容超过一行,还会存放到数字寄存器 1)。

删除到行尾: d$
删除一个单词: dw
删除一个段落: d}
删除当前行: dd
删除选中文本(Visual 模式): 在 Visual 模式下选中文本后,按下 d 键。

复制(Yank):y 命令

y 命令用于复制文本,并将复制的文本存放到寄存器中(默认是无名寄存器 " 和复制专用寄存器 0)。

复制到行尾: y$
复制一个单词: yw
复制一个段落: y}
复制当前行: yyY
复制选中文本(Visual 模式): 在 Visual 模式下选中文本后,按下 y 键。

粘贴(Paste):pP 命令

pP 命令用于粘贴寄存器中的文本。

p (小写 p): 在光标之后粘贴。如果寄存器内容是整行文本,则粘贴到光标所在行的下一行;如果寄存器内容是非整行文本,则粘贴到光标之后
P (大写 P): 在光标之前粘贴。如果寄存器内容是整行文本,则粘贴到光标所在行的上一行;如果寄存器内容是非整行文本,则粘贴到光标之前

指定寄存器:

dypP 命令之前,可以使用 " + 寄存器名来指定要使用的寄存器。

复制到寄存器 a "ayw (复制一个单词到寄存器 a)
删除到寄存器 b "bdd (删除当前行到寄存器 b)
从寄存器 a 粘贴: "ap (在光标之后粘贴寄存器 a 的内容)
从寄存器 b 粘贴到行前: "bP (在光标之前粘贴寄存器 b 的内容)

清空寄存器:

可以通过删除操作并将内容放入黑洞寄存器 _ 来清空寄存器,例如 "_dd 清空无名寄存器中当前行的内容(实际上是删除当前行,并将删除内容放入黑洞寄存器,从而达到清空无名寄存器的效果)。黑洞寄存器 _ 用于丢弃内容,放入黑洞寄存器的内容不会被保存,相当于“垃圾桶”。

理解和熟练运用寄存器是 Vim 高级文本操作的基础,它可以让你更精细地控制剪切、复制和粘贴行为,实现更复杂的编辑任务。

4.3 文本对象:iw, aw, is, as, ip, ap

文本对象(Text Objects)是 Vim 中一个非常强大的概念,它允许你以语义化的单位(例如单词、句子、段落、代码块等)来选取文本,而无需精确地移动光标。文本对象与操作符结合使用,可以实现高效、精准的文本编辑。

文本对象通常由两个字符组成:

第一个字符: i (inner) 或 a (around)。
▮▮▮▮⚝ i (inner):表示“内部的”,选取文本对象内部的内容,不包含周围的空格或分隔符。
▮▮▮▮⚝ a (around):表示“周围的”,选取文本对象及其周围的内容,包含周围的空格或分隔符。
第二个字符: 表示文本对象的类型,例如 w (word)、s (sentence)、p (paragraph)、" (double quotes)、' (single quotes)、) (parentheses)、] (brackets)、} (braces)、> (angle brackets)、t (tag) 等。

常用的文本对象:

iw (inner word): 光标所在单词的内部。
aw (a word): 光标所在单词及其周围的空格。
is (inner sentence): 光标所在句子的内部。
as (a sentence): 光标所在句子及其周围的空格。
ip (inner paragraph): 光标所在段落的内部。
ap (a paragraph): 光标所在段落及其周围的空行。
i" (inner double quotes): 双引号内部的文本。
a" (a double quotes): 双引号及其内部的文本。
i' (inner single quotes): 单引号内部的文本。
a' (a single quotes): 单引号及其内部的文本。
i(i) (inner parentheses): 圆括号内部的文本。
a(a) (a parentheses): 圆括号及其内部的文本。
i[i] (inner brackets): 方括号内部的文本。
a[a] (a brackets): 方括号及其内部的文本。
i{i} (inner braces): 花括号内部的文本。
a{a} (a braces): 花括号及其内部的文本。
i<i> (inner angle brackets): 尖括号内部的文本。
a<a> (a angle brackets): 尖括号及其内部的文本。
it (inner tag): XML/HTML 标签内部的内容。
at (a tag): XML/HTML 标签及其内部的内容。

文本对象与操作符的结合使用:

文本对象通常与操作符(例如 dcy>< 等)结合使用,构成命令,对文本对象进行操作。

语法: [操作符][文本对象]

diw (delete inner word): 删除光标所在单词的内部。
daw (delete a word): 删除光标所在单词及其周围的空格。
cis (change inner sentence): 删除光标所在句子的内部并进入 Insert 模式。
yas (yank a sentence): 复制光标所在句子及其周围的空格。
cip (change inner paragraph): 删除光标所在段落的内部并进入 Insert 模式。
yap (yank a paragraph): 复制光标所在段落及其周围的空行。
viw (visual inner word): 在字符选择模式下选中光标所在单词的内部。
vaw (visual a word): 在字符选择模式下选中光标所在单词及其周围的空格。
Vap (visual a paragraph): 在行选择模式下选中光标所在段落及其周围的空行。
ci" (change inner double quotes): 删除双引号内部的文本并进入 Insert 模式。
dat (delete a tag): 删除 XML/HTML 标签及其内部的内容。
yit (yank inner tag): 复制 XML/HTML 标签内部的内容。
>ip (indent inner paragraph): 增加光标所在段落内部的缩进。
<ap (unindent a paragraph): 减少光标所在段落及其周围空行的缩进。

示例:

假设你有以下文本: This is (a word) in parentheses.,光标位于 w 处。

diw 删除 "word",文本变为 This is (a ) in parentheses.
daw 删除 "(a word) ",文本变为 This is in parentheses.
ci( 删除 "a word" 并进入 Insert 模式,可以输入新的内容替换圆括号内的文本。
yap 如果这行文本是一个段落,则复制整行文本及其周围的空行。

文本对象是 Vim 高效编辑的关键特性之一,它使得文本操作更加符合语义,减少了手动移动光标和精确选择文本的繁琐操作,极大地提高了编辑效率和准确性。熟练掌握文本对象,可以让你在 Vim 中如鱼得水,体验到精准编辑的艺术。

4.4 操作符与动作的组合:d, c, y 与各种动作的灵活运用

Vim 的核心设计理念之一是操作符(Operators)动作(Motions) 的组合。操作符定义了要执行的操作(例如删除、修改、复制),而动作定义了操作的范围(例如单词、行、段落、直到某个字符等)。通过灵活组合操作符和动作,可以实现各种精准的文本编辑操作。

常用的操作符:

d (delete): 删除操作符。删除指定范围的文本,并将删除的文本存放到寄存器中。
c (change): 修改操作符。删除指定范围的文本,并进入 Insert 模式,用于替换删除的文本。
y (yank): 复制操作符。复制指定范围的文本,并将复制的文本存放到寄存器中。
> (indent): 增加缩进操作符。增加指定范围文本的缩进。
< (unindent): 减少缩进操作符。减少指定范围文本的缩进。
= (equal): 自动缩进操作符。自动缩进指定范围的文本。
~ (swapcase): 切换大小写操作符。切换指定范围文本的大小写。
gu (lowercase): 转换为小写操作符。将指定范围文本转换为小写。
gU (uppercase): 转换为大写操作符。将指定范围文本转换为大写。
! (filter): 过滤操作符。将指定范围文本通过外部命令过滤。

常用的动作:

动作可以是各种移动命令、文本对象、搜索命令等,用于定义操作符的作用范围。

移动命令:
▮▮▮▮⚝ 字符级移动: h, j, k, l
▮▮▮▮⚝ 单词级移动: w, b, e, ge
▮▮▮▮⚝ 行内移动: 0, $, ^, f{char}, F{char}, t{char}, T{char}
▮▮▮▮⚝ 行间移动: }, {, ), (
▮▮▮▮⚝ 屏幕滚动: Ctrl+u, Ctrl+d, Ctrl+b, Ctrl+f, H, M, L
▮▮▮▮⚝ 标记跳转: `m{char}
文本对象: iw, aw, is, as, ip, ap, i", a", i', a', i(, a(, i[, a[, i{, a{, i<, a<, it, at 等。
搜索命令: /pattern, ?pattern, n, N

操作符与动作的组合语法:

[操作符][动作]

示例:

dw (delete word): 删除从光标位置到单词末尾的文本。操作符是 d (delete),动作是 w (word,移动到下一个单词的词首)。
ciw (change inner word): 修改光标所在单词的内部。操作符是 c (change),动作是 iw (inner word,文本对象)。
yj (yank down): 复制当前行和下一行。操作符是 y (yank),动作是 j (down,向下移动一行)。
d$ (delete to end of line): 删除从光标位置到行尾的文本。操作符是 d (delete),动作是 $ (to end of line,移动到行尾)。
c0 (change to beginning of line): 修改从光标位置到行首的文本。操作符是 c (change),动作是 0 (to beginning of line,移动到行首)。
yG (yank to end of file): 复制从当前行到文件末尾的所有文本。操作符是 y (yank),动作是 G (to end of file,移动到文件末尾)。
d/pattern (delete until pattern): 删除从光标位置到下一个匹配 pattern 的文本。操作符是 d (delete),动作是 /pattern (search forward for pattern,向前搜索 pattern)。
>} (indent paragraph): 增加当前段落的缩进。操作符是 > (indent),动作是 } (paragraph,移动到下一个段落的段首)。
gUaw (uppercase a word): 将光标所在单词及其周围的空格转换为大写。操作符是 gU (uppercase),动作是 aw (a word,文本对象)。
!Gsort (filter to end of file through sort): 将从当前行到文件末尾的所有文本通过 sort 命令进行排序。操作符是 ! (filter),动作是 G (to end of file),外部命令是 sort

重复操作符:

有些操作符可以重复使用,表示对当前行或选区进行操作。

dd 删除当前行(相当于 d_,删除到行尾并包含换行符)。
cc 修改当前行(相当于 c_,删除当前行并进入 Insert 模式)。
yyY 复制当前行(相当于 y_,复制到行尾并包含换行符)。
>> 增加当前行的缩进。
<< 减少当前行的缩进。
== 自动缩进当前行。

操作符与动作的组合是 Vim 编辑的核心思想,它赋予了 Vim 极高的灵活性和效率。通过掌握各种操作符和动作,并灵活组合使用,可以实现各种复杂的文本编辑任务,真正体验到 Vim 精准编辑的艺术。

4.5 大小写转换、缩进与对齐

Vim 提供了丰富的命令来处理文本的大小写转换、缩进和对齐,这些命令可以帮助你快速格式化文本,提高代码和文档的可读性。

大小写转换:

~ (swapcase): 切换光标所在字符的大小写。如果光标位于大写字母,则转换为小写;如果位于小写字母,则转换为大写。
▮▮▮▮⚝ 范围操作: 可以与动作结合使用,例如 ~w 切换从光标位置到单词末尾的文本的大小写,~} 切换到段落末尾的文本的大小写,在 Visual 模式下选中文本后按 ~ 切换选中文本的大小写。
gu{motion} (lowercase): 将指定范围的文本转换为小写。gu 后面跟一个动作,例如 guw 将光标所在单词转换为小写,gu} 将当前段落转换为小写,在 Visual 模式下选中文本后按 gu 将选中文本转换为小写。
gU{motion} (uppercase): 将指定范围的文本转换为大写。gU 后面跟一个动作,例如 gUw 将光标所在单词转换为大写,gU} 将当前段落转换为大写,在 Visual 模式下选中文本后按 gU 将选中文本转换为大写。

缩进:

> (indent): 增加缩进。默认增加一个 shiftwidth 宽度的缩进(通常是 4 或 8 个空格,可以在 .vimrc 文件中设置 shiftwidth 选项)。
▮▮▮▮⚝ 范围操作: 可以与动作结合使用,例如 >w 增加从光标位置到单词末尾的文本的缩进, >} 增加当前段落的缩进,在 Visual 模式下选中多行文本后按 > 增加选中文本的缩进。
▮▮▮▮⚝ 重复操作符 >> 增加当前行的缩进。
< (unindent): 减少缩进。默认减少一个 shiftwidth 宽度的缩进。
▮▮▮▮⚝ 范围操作: 可以与动作结合使用,例如 <w 减少从光标位置到单词末尾的文本的缩进, <} 减少当前段落的缩进,在 Visual 模式下选中多行文本后按 < 减少选中文本的缩进。
▮▮▮▮⚝ 重复操作符 << 减少当前行的缩进。
= (equal): 自动缩进。根据文件类型和缩进规则,自动调整指定范围文本的缩进。
▮▮▮▮⚝ 范围操作: 可以与动作结合使用,例如 =w 自动缩进从光标位置到单词末尾的文本, =} 自动缩进当前段落,在 Visual 模式下选中多行文本后按 = 自动缩进选中文本。
▮▮▮▮⚝ 重复操作符 == 自动缩进当前行。
▮▮▮▮⚝ 全文件自动缩进: gg=G (先 gg 跳转到文件首行,然后 = 自动缩进,再 G 跳转到文件末尾,从而实现全文件自动缩进)。

对齐:

Vim 提供了 :left:right:center 命令来进行文本对齐,这些命令通常在 Visual 模式下选中多行文本后使用。

:left [indent] 左对齐选中文本。[indent] 是可选参数,表示左侧缩进的空格数,默认为 0。
▮▮▮▮⚝ 操作步骤:
① 在 Visual 模式下选中要对齐的文本行。
② 按下 : 键进入命令行模式,输入 left[range]left [indent],例如 :left 5 表示左对齐并缩进 5 个空格。
③ 按下 <Enter> 键执行命令。
:right [width] 右对齐选中文本。[width] 是可选参数,表示对齐的总宽度,默认为当前窗口宽度。
▮▮▮▮⚝ 操作步骤:
① 在 Visual 模式下选中要对齐的文本行。
② 按下 : 键进入命令行模式,输入 right[range]right [width],例如 :right 80 表示右对齐到 80 字符宽度。
③ 按下 <Enter> 键执行命令。
:center [width] 居中对齐选中文本。[width] 是可选参数,表示对齐的总宽度,默认为当前窗口宽度。
▮▮▮▮⚝ 操作步骤:
① 在 Visual 模式下选中要对齐的文本行。
② 按下 : 键进入命令行模式,输入 center[range]center [width],例如 :center 80 表示居中对齐到 80 字符宽度。
③ 按下 <Enter> 键执行命令。

示例:

假设你有以下文本:

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 line1
2 line2
3 line3

选中所有行,按下 > 增加所有行的缩进,变为:

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 line1
2 line2
3 line3

选中所有行,按下 < 减少所有行的缩进,变为:

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 line1
2 line2
3 line3

选中所有行,按下 = 自动缩进所有行(假设文件类型为文本文件,没有特定的缩进规则),可能变为:

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 line1
2 line2
3 line3

选中所有行,在命令行输入 :left 5 左对齐并缩进 5 个空格,变为:

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 line1
2 line2
3 line3

选中所有行,在命令行输入 :right 30 右对齐到 30 字符宽度(假设窗口宽度足够),变为:

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 line1
2 line2
3 line3

选中所有行,在命令行输入 :center 30 居中对齐到 30 字符宽度,变为:

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 line1
2 line2
3 line3

熟练掌握大小写转换、缩进和对齐命令,可以让你快速整理和格式化文本,提高文本的可读性和美观性,尤其在编写代码和文档时,这些命令非常实用。

ENDOF_CHAPTER_

5. chapter 5: 搜索与替换:信息定位与批量修改

5.1 基本搜索:/? 命令

在 Vim 中,搜索功能是快速定位文本内容的核心技能。无论是查找特定的单词、短语,还是定位到代码中的某个变量名,高效的搜索都能极大地提升编辑效率。Vim 提供了两种基本的搜索命令:/?,分别用于正向搜索反向搜索

5.1.1 正向搜索 / 命令

/ 命令允许你从当前光标位置向文件末尾进行搜索。使用方法非常简单:

  1. 在 Normal 模式下,按下 / 键。此时,Vim 会在屏幕底部显示一个 / 提示符,等待你输入要搜索的模式(pattern)。
  2. 输入你要搜索的文本,例如 example
  3. 按下 Enter 键,Vim 将会开始从当前光标位置向下搜索 example

如果找到了匹配项,Vim 会将光标移动到第一个匹配项的起始位置,并高亮显示匹配的文本。如果没有找到匹配项,Vim 会在屏幕底部显示 Pattern not found: example 的提示信息,并且光标位置不会改变。

示例

假设你的文本内容如下:

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 This is an example line.
2 Another line with example word.
3 And one more example here.
  1. 将光标移动到第一行的开头。
  2. 输入 /example 并按下 Enter
  3. Vim 会将光标移动到第一行中 example 的起始位置,并高亮显示 example

移动到下一个/上一个匹配项

⚝ 要移动到下一个匹配项,只需按下 n 键(next)。
⚝ 要移动到上一个匹配项,按下 N 键(previous,Shift + n)。

5.1.2 反向搜索 ? 命令

? 命令与 / 命令类似,但它是从当前光标位置向文件开头进行搜索。使用方法如下:

  1. 在 Normal 模式下,按下 ? 键。屏幕底部会显示 ? 提示符。
  2. 输入你要搜索的文本,例如 line
  3. 按下 Enter 键,Vim 将会从当前光标位置向上搜索 line

与正向搜索类似,找到匹配项后,Vim 会将光标移动到匹配项的起始位置并高亮显示。未找到匹配项时,会显示相应的提示信息。

示例

继续使用上面的文本内容:

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 This is an example line.
2 Another line with example word.
3 And one more example here.
  1. 将光标移动到第三行的末尾。
  2. 输入 ?line 并按下 Enter
  3. Vim 会将光标移动到第二行中 line 的起始位置,并高亮显示 line

移动到下一个/上一个匹配项(反向搜索)

⚝ 在反向搜索中,n 键仍然是移动到“下一个”匹配项,但这里的“下一个”指的是向上一个匹配项(因为是反向搜索)。
N 键则移动到“上一个”匹配项,即向下上一个匹配项。

为了避免混淆,可以记住 n 总是沿着搜索方向移动到下一个匹配项,而 N 则反方向移动。

5.1.3 搜索历史与重复搜索

Vim 会记录你的搜索历史,方便你重复使用之前的搜索模式。

⚝ 在 /? 提示符下,直接按下 Enter 键,Vim 会重复上一次的搜索。
⚝ 在 /? 提示符下,按下 键或 键,可以浏览搜索历史,选择之前的搜索模式。

示例

  1. 执行一次搜索,例如 /example
  2. 按下 n 几次,移动到不同的匹配项。
  3. 再次按下 / 键,然后直接按下 Enter。Vim 会再次执行 /example 搜索,并移动到下一个匹配项。

5.2 高级搜索选项:忽略大小写、高亮显示等

Vim 提供了丰富的搜索选项,可以让你更精确地控制搜索行为。这些选项通常通过在搜索模式中添加标志(flags)来实现,或者通过设置 Vim 的选项(options)来全局控制。

5.2.1 忽略大小写搜索 \c\C

默认情况下,Vim 的搜索是区分大小写的。如果你想进行忽略大小写的搜索,可以使用 \c 标志。将 \c 放在搜索模式的末尾,即可使搜索忽略大小写。

示例

搜索 example,忽略大小写:

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 /example\c

这样,Example, EXAMPLE, example 等都会被匹配到。

如果你想强制进行区分大小写的搜索,即使 Vim 的 ignorecase 选项被设置了,可以使用 \C 标志。

示例

强制区分大小写搜索 Example

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 /Example\C

只有完全匹配 Example 的文本才会被找到。

5.2.2 高亮显示搜索结果 hlsearch

hlsearch 是一个 Vim 选项,用于控制是否高亮显示所有搜索匹配项。默认情况下,hlsearch 是关闭的。

启用高亮显示:在 Command-line 模式下输入 :set hlsearch:set hls (简写)。
关闭高亮显示:在 Command-line 模式下输入 :set nohlsearch:set nohls
临时清除高亮显示:在 Normal 模式下输入 :nohlsearch:noh。这只会清除当前的高亮显示,下次搜索后又会重新高亮。

启用 hlsearch 后,每次搜索都会高亮显示所有匹配项,直到你执行新的搜索或手动清除高亮显示。

5.2.3 增量搜索 incsearch

incsearch 选项开启后,Vim 会在你输入搜索模式的过程中实时显示匹配结果。这意味着你不需要按下 Enter 键,Vim 就会在你输入每个字符时动态地更新搜索结果。

启用增量搜索:set incsearch:set is
关闭增量搜索:set noincsearch:set nois

增量搜索对于复杂的搜索模式非常有用,可以让你在输入的同时看到匹配效果,及时调整搜索模式。

5.2.4 智能大小写 smartcase

smartcase 选项与 ignorecase 选项配合使用,可以实现更智能的大小写处理。当 smartcase 启用时:

⚝ 如果搜索模式中包含大写字母,则搜索会区分大小写,除非 ignorecase 也被显式关闭。
⚝ 如果搜索模式中只包含小写字母,则搜索会忽略大小写(前提是 ignorecase 选项已启用)。

启用智能大小写:set smartcase:set scs
关闭智能大小写:set nosmartcase:set noscs

示例

假设 ignorecasesmartcase 都已启用:

⚝ 搜索 /example:会忽略大小写,匹配 example, Example, EXAMPLE 等。
⚝ 搜索 /Example:会区分大小写,只匹配 Example

5.2.5 环绕搜索 wrapscan

wrapscan 选项控制搜索是否在文件末尾或开头环绕。默认情况下,wrapscan 是启用的。

启用环绕搜索:set wrapscan:set ws。当搜索到达文件末尾(正向搜索)或文件开头(反向搜索)时,会继续从另一端开始搜索。
关闭环绕搜索:set nowrapscan:set nows。当搜索到达文件末尾或开头时,会停止搜索。

关闭 wrapscan 后,如果搜索到达文件边界仍未找到匹配项,Vim 会停止搜索并提示 search hit BOTTOM, continuing at TOP (环绕搜索启用时) 或 search hit BOTTOM without wrapping (环绕搜索关闭时)。

5.3 正则表达式基础:元字符与模式匹配

Vim 的搜索功能强大之处在于它支持正则表达式(Regular Expression, Regex)。正则表达式是一种强大的文本模式匹配工具,可以用来描述复杂的搜索模式。掌握正则表达式是提升 Vim 搜索效率的关键。

5.3.1 什么是正则表达式

正则表达式是由普通字符(例如字母、数字)和特殊字符(称为元字符)组成的字符串,用来描述一组字符串的模式。通过使用正则表达式,你可以进行模糊搜索、模式匹配、数据验证等操作。

5.3.2 常用元字符及其含义

元字符含义示例
.匹配任意单个字符(除了换行符,除非使用 \_.a.b 可以匹配 acb, adb, aeb
*匹配前一个字符零次或多次ab*c 可以匹配 ac, abc, abbc, abbbc
+匹配前一个字符一次或多次ab+c 可以匹配 abc, abbc, abbbc 等,但不匹配 ac
?匹配前一个字符零次或一次ab?c 可以匹配 ac, abc,但不匹配 abbc
[]字符集,匹配方括号中的任意一个字符[aeiou] 可以匹配任意一个元音字母
[^]排除字符集,匹配不在方括号中的任意一个字符[^0-9] 可以匹配任意一个非数字字符
^在字符集 [] 中表示排除,在模式开头表示匹配行首^[a-z] 匹配以小写字母开头的行
$匹配行尾[0-9]$ 匹配以数字结尾的行
\转义字符,用于取消元字符的特殊含义,使其变为普通字符\. 匹配句点 . 本身
\|或,匹配 \| 两边的任意一个模式a\|b 匹配 ab
()分组,将模式的一部分组合成一个单元,可以与 *, +, ? 等量词结合使用,也用于捕获组(ab)+ 匹配 ab, abab, ababab

字符集简写

为了方便使用,正则表达式提供了一些预定义的字符集简写:

简写含义等价于
\d匹配任意数字[0-9]
\D匹配任意非数字字符[^0-9]
\w匹配任意单词字符(字母、数字、下划线)[a-zA-Z0-9_]
\W匹配任意非单词字符[^a-zA-Z0-9_]
\s匹配任意空白字符(空格、制表符、换行符等)[ \t\r\n\f\v]
\S匹配任意非空白字符[^ \t\r\n\f\v]

位置锚定

除了 ^$,正则表达式还提供了一些位置锚定元字符:

元字符含义示例
\<匹配单词开头\<word 匹配以 word 开头的单词
\>匹配单词结尾word\> 匹配以 word 结尾的单词
\b匹配单词边界(\<\> 的组合,但更通用)\bword\b 匹配独立的单词 word

5.3.3 正则表达式示例

匹配以数字开头的行^[0-9]^\d
匹配包含单词 "Vim" 的行(忽略大小写)/\<Vim\>\c/\bVim\b\c
匹配邮箱地址\w\+@\w\+\.\w\+ (简化版,实际邮箱地址的正则表达式会更复杂)
匹配 HTML 标签<[^>]\+>

5.4 替换命令 :s:基本替换与全局替换

Vim 的替换命令 :s (substitute) 是基于搜索命令的,它允许你找到匹配某个模式的文本,并将其替换为指定的文本。:s 命令的基本语法如下:

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 :[range]s/pattern/replacement/[flags]

[range]:指定替换的范围。如果不指定,默认只在当前行进行替换。
s:替换命令的标志。
/pattern/:要搜索的正则表达式模式。
/replacement/:替换文本。
[flags]:替换标志,用于控制替换行为。

5.4.1 基本替换:替换当前行第一个匹配项

在最简单的形式下,:s 命令只替换当前行第一个匹配到的 pattern

示例

假设当前行内容为:This is a test line, test test.

  1. 将当前行中的第一个 test 替换为 example
1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 :s/test/example/

▮▮▮▮执行后,当前行变为:This is a example line, test test.

5.4.2 全局替换:替换当前行所有匹配项

要替换当前行中所有匹配到的 pattern,需要在 :s 命令后添加 g 标志(global)。

示例

继续使用上面的例子:This is a example line, test test.

  1. 将当前行中所有test 替换为 example
1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 :s/test/example/g

▮▮▮▮执行后,当前行变为:This is a example line, example example.

5.4.3 范围替换:多行替换

:s 命令可以通过指定范围来对多行进行替换。常用的范围包括:

当前行到文件末尾.,$$
当前行到指定行号.,{行号}
指定行号范围{起始行号},{结束行号}
所有行% (相当于 1,$)

示例

假设文件内容如下:

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 line one test
2 line two test
3 line three test
  1. 将第 2 行到第 3 行的所有 test 替换为 example
1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 :2,3s/test/example/g

▮▮▮▮执行后,文件变为:

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 line one test
2 line two example
3 line three example
  1. 整个文件中的所有 test 替换为 example
1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 :%s/test/example/g

▮▮▮▮执行后,文件变为:

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 line one example
2 line two example
3 line three example

5.4.4 替换标志 (flags)

除了 g 标志,:s 命令还支持其他一些有用的标志:

i:忽略大小写 (ignore case)。等同于搜索模式中的 \c 标志。
I:区分大小写 (case sensitive)。等同于搜索模式中的 \C 标志。
c:确认 (confirm)。在每次替换前都会询问是否替换。
n:计数 (number)。不执行替换,只统计匹配到的数量。
&:重复上次替换命令的标志和范围。

示例

  1. 替换时忽略大小写:
1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 :s/Test/example/gi
  1. 替换前进行确认:
1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 :%s/test/example/gc

▮▮▮▮Vim 会在每个匹配项处暂停,并询问你是否替换,你可以输入 y (yes), n (no), a (all), q (quit), l (last), ^E (scroll up), ^Y (scroll down)。

  1. 统计文件中 test 出现的次数,但不进行替换:
1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 :%s/test/example/gn

▮▮▮▮Vim 会显示匹配到的数量,例如 3 matches on 3 lines

5.4.5 分隔符的选择

:s 命令中,默认的分隔符是 /。但如果你的 patternreplacement 中包含 / 字符,就需要使用转义字符 \ 来转义 /,或者选择其他分隔符。常用的分隔符包括 +, -, =, @, % 等。

示例

假设你要将路径 /usr/local/bin 替换为 /usr/bin

  1. 使用 / 分隔符,需要转义 /
1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 :s/\/usr\/local\/bin/\/usr\/bin/g
  1. 使用 + 分隔符,无需转义 /
1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 :s+/usr/local/bin+/usr/bin+g

使用其他分隔符可以提高命令的可读性,尤其是在处理路径或 URL 等包含 / 的文本时。

5.5 正则表达式在替换中的应用:捕获组与反向引用

正则表达式在替换命令中同样非常强大,尤其是在结合捕获组(capture groups)反向引用(backreferences)时,可以实现更复杂的文本转换和格式化。

5.5.1 捕获组 ()

在正则表达式中,使用 () 可以将模式的一部分捕获为一个组。捕获组可以用于:

  1. 分组:将模式的一部分组合成一个单元,方便应用量词或其他操作。
  2. 反向引用:在替换文本中引用捕获组匹配到的内容。

示例

正则表达式 (ab)+c 中,(ab) 就是一个捕获组,它匹配 ab, abab, ababab 等。

5.5.2 反向引用 \1, \2, ...

在替换文本中,可以使用 \1, \2, \3 等来引用前面模式中第 1, 2, 3, ... 个捕获组匹配到的文本。\1 引用第一个捕获组,\2 引用第二个捕获组,以此类推。

示例

假设文件内容如下:

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 apple banana
2 orange grape
  1. 将每行中的两个单词互换位置:
1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 :%s/\(\w\+\) \(\w\+\)/\2 \1/g

▮▮▮▮⚝ \(\w\+\):第一个捕获组,匹配一个或多个单词字符,并捕获到第一个组。
▮▮▮▮⚝ :匹配空格。
▮▮▮▮⚝ \(\w\+\):第二个捕获组,匹配一个或多个单词字符,并捕获到第二个组。
▮▮▮▮⚝ \2 \1:替换文本,\2 引用第二个捕获组的内容,\1 引用第一个捕获组的内容,中间用空格分隔。

▮▮▮▮执行后,文件变为:

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 banana apple
2 grape orange

5.5.3 更复杂的替换示例

  1. 将 Markdown 标题 # Title 转换为 HTML 标题 <h1>Title</h1>
1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 :%s/^# \(.\+\)$/

\1/g

▮▮▮▮⚝ ^# \(.\+\)$:匹配以 # 开头,后跟一个空格,然后是任意字符(. 匹配任意字符,\+ 匹配一次或多次),直到行尾 $ 的行。\(.\+\) 捕获标题内容到第一个组。
▮▮▮▮⚝ <h1>\1<\/h1>:替换文本,使用 \1 引用捕获组的内容,并添加 HTML 标签。

  1. 将日期格式 YYYY-MM-DD 转换为 MM/DD/YYYY
1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 :%s/\(\d\{4}\)-\(\d\{2}\)-\(\d\{2}\)/\2\/\3\/\1/g

▮▮▮▮⚝ \(\d\{4}\)-\(\d\{2}\)-\(\d\{2}\):匹配 YYYY-MM-DD 格式的日期。\d\{4} 匹配 4 位数字(年),\d\{2} 匹配 2 位数字(月和日)。使用 () 分别捕获年、月、日到三个组。
▮▮▮▮⚝ \2\/\3\/\1:替换文本,按照 MM/DD/YYYY 的顺序引用捕获组,并用 / 分隔。

通过灵活运用正则表达式、捕获组和反向引用,你可以在 Vim 中实现非常强大的搜索和替换功能,进行复杂的文本处理和批量修改。掌握这些技巧将极大地提升你的文本编辑效率。

ENDOF_CHAPTER_

6. chapter 6: 多文件操作:项目级编辑利器

在软件开发、文本处理或者系统管理等多种场景下,我们经常需要同时处理多个文件。Vim 作为高效的文本编辑器,自然提供了强大的多文件操作能力,使得用户能够在一个 Vim 实例中轻松管理和编辑多个文件,极大地提升工作效率。本章将深入探讨 Vim 的多文件操作机制,包括缓冲区管理、窗口分割、标签页管理以及文件浏览器等,助你掌握项目级编辑的利器。

6.1 缓冲区管理::buffers, :ls, :bnext, :bprev, :bdelete

缓冲区(Buffer)是 Vim 中最核心的概念之一。当你打开一个文件时,Vim 并不会直接操作磁盘上的文件,而是将文件内容加载到内存中的缓冲区中。所有的编辑操作都是在缓冲区中进行的。理解缓冲区是掌握 Vim 多文件操作的基础。

6.1.1 什么是缓冲区?

简单来说,缓冲区就是 Vim 用来存放文件内容的内存区域。每个打开的文件都对应一个缓冲区。即使你在 Vim 中打开了多个文件,它们也都是以缓冲区的形式存在于内存中。

独立性:每个缓冲区都是独立的,拥有自己的文件内容、光标位置、撤销历史等。
内存驻留:缓冲区存在于内存中,这意味着在缓冲区中的操作速度非常快。
持久化:缓冲区的内容可以保存到磁盘文件中,实现文件的持久化存储。

6.1.2 查看缓冲区列表::buffers:ls

要查看当前 Vim 实例中所有打开的缓冲区,可以使用 :buffers 命令,或者其简写形式 :ls。这两个命令会列出当前所有的缓冲区,并显示每个缓冲区的状态信息。

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 :buffers

或者

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 :ls

执行上述命令后,Vim 会显示类似如下的缓冲区列表:

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 1 #h "chapter6.txt" line 1
2 2 %a "chapter5.txt" line 1
3 3 "chapter4.txt" line 0

列表中的每一行代表一个缓冲区,各列信息的含义如下:

缓冲区编号(Buffer Number):每行最前面的数字 1, 2, 3 等是缓冲区的唯一编号。你可以使用这些编号来快速切换到对应的缓冲区。
缓冲区标志(Flags):紧随编号之后的 #, %, a, h 等字符是缓冲区标志,表示缓冲区的状态。常见的标志有:
▮▮▮▮ⓒ #:表示备用缓冲区(alternate buffer)。通常是上一个被编辑的缓冲区。
▮▮▮▮ⓓ %:表示当前活动缓冲区(current buffer)。当前正在编辑的缓冲区。
▮▮▮▮ⓔ a:表示已加载缓冲区(loaded buffer)。缓冲区内容已加载到内存。
▮▮▮▮ⓕ h:表示隐藏缓冲区(hidden buffer)。缓冲区在后台,没有显示在窗口中。
▮▮▮▮ⓖ +:表示已修改缓冲区(modified buffer)。缓冲区内容自上次保存后被修改过。
▮▮▮▮ⓗ -:表示未修改缓冲区(unmodified buffer)。缓冲区内容自上次保存后未被修改过。
▮▮▮▮ⓘ =:表示只读缓冲区(readonly buffer)。缓冲区是只读的,不能修改。
▮▮▮▮ⓙ ?:表示不存在的缓冲区(nonexistent buffer)。缓冲区对应的文件不存在。
文件名(Filename):双引号括起来的部分是缓冲区对应的文件名。如果缓冲区没有关联文件(例如,使用 :enew 创建的新缓冲区),则此处为空。
行号(Line Number)line 1, line 0 等表示光标当前所在的行号。

6.1.3 切换缓冲区::bnext, :bprev, :buffer <编号/文件名>

在多个缓冲区之间切换是多文件操作的核心。Vim 提供了多种命令来快速切换缓冲区:

:bnext:bn:切换到下一个缓冲区(按照缓冲区列表的顺序)。如果当前是最后一个缓冲区,则切换到第一个缓冲区,形成循环。
:bprev:bp:切换到上一个缓冲区(按照缓冲区列表的顺序)。如果当前是第一个缓冲区,则切换到最后一个缓冲区,形成循环。
:buffer <编号>:b <编号>:切换到指定编号的缓冲区。例如,:buffer 2:b 2 切换到编号为 2 的缓冲区。
:buffer <文件名>:b <文件名>:切换到指定文件名的缓冲区。可以使用文件名的一部分进行匹配。例如,:b chap 可以切换到文件名以 "chap" 开头的缓冲区。如果存在多个匹配项,Vim 会列出所有匹配项供你选择。

示例

假设我们有三个缓冲区,编号分别为 1, 2, 3。当前活动缓冲区是 2。

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 :bn " 切换到下一个缓冲区,即缓冲区 3
2 :bp " 切换到上一个缓冲区,即缓冲区 2 (从缓冲区 3 切换回来)
3 :b 1 " 切换到缓冲区 1
4 :b chapter5.txt " 切换到文件名为 chapter5.txt 的缓冲区

6.1.4 关闭缓冲区::bdelete:bd

当你完成对某个缓冲区的编辑,或者想要清理不再需要的缓冲区时,可以使用 :bdelete 命令来删除缓冲区。

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 :bdelete <编号/文件名>

或者

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 :bd <编号/文件名>

与切换缓冲区类似,你可以使用缓冲区编号或文件名来指定要删除的缓冲区。

注意事项

未保存的修改:如果缓冲区的内容自上次保存后被修改过(即缓冲区标志中有 +),:bdelete 命令会阻止你删除缓冲区,并提示你先保存或放弃修改。
强制删除:如果你确定要删除缓冲区,并且放弃未保存的修改,可以使用 :bdelete!:bd! 命令进行强制删除。
最后一个窗口:如果被删除的缓冲区是当前窗口显示的唯一缓冲区,Vim 会关闭该窗口。如果还有其他窗口显示该缓冲区,则只会关闭当前窗口对该缓冲区的显示。

最佳实践

⚝ 养成定期查看和清理缓冲区的习惯,避免打开过多的缓冲区导致内存占用过高。
⚝ 使用缓冲区编号或文件名快速切换到需要的缓冲区,提高编辑效率。
⚝ 在删除缓冲区之前,务必确认是否已保存所有修改,避免数据丢失。

6.2 窗口分割与管理::split, :vsplit, Ctrl+w 系列命令

窗口(Window)是 Vim 中显示缓冲区内容的视图。一个 Vim 窗口可以显示一个缓冲区,也可以分割成多个窗口,同时显示多个缓冲区的内容。窗口分割是 Vim 多文件操作的强大功能之一,它允许你并排查看和编辑多个文件,或者在同一个文件中查看不同的部分。

6.2.1 窗口的基本概念

视图:窗口是缓冲区的视图,它负责将缓冲区的内容显示在屏幕上。
独立性:每个窗口都有自己的光标位置、滚动位置等,但它们共享同一个缓冲区。
分割:一个窗口可以被分割成多个子窗口,每个子窗口可以显示不同的缓冲区,或者同一个缓冲区的不同部分。

6.2.2 水平分割窗口::split:sp

:split 命令(简写 :sp)用于水平分割当前窗口,创建一个新的窗口显示当前缓冲区。

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 :split

或者

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 :sp

执行上述命令后,当前窗口会被水平分割成上下两个窗口,两个窗口显示的是同一个缓冲区的内容。

你也可以在 :split 命令后指定要打开的文件名,在新窗口中打开并显示该文件对应的缓冲区。

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 :split chapter7.txt

6.2.3 垂直分割窗口::vsplit:vs

:vsplit 命令(简写 :vs)用于垂直分割当前窗口,创建一个新的窗口显示当前缓冲区。

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 :vsplit

或者

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 :vs

执行上述命令后,当前窗口会被垂直分割成左右两个窗口,两个窗口显示的是同一个缓冲区的内容。

同样,你也可以在 :vsplit 命令后指定要打开的文件名,在新窗口中打开并显示该文件对应的缓冲区。

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 :vsplit chapter8.txt

6.2.4 窗口切换:Ctrl+w 系列命令

Vim 提供了丰富的 Ctrl+w 系列命令来管理和切换窗口。以下是一些常用的命令:

Ctrl+w wCtrl+w Ctrl+w:切换到下一个窗口(按照窗口分割的顺序)。如果当前是最后一个窗口,则切换到第一个窗口,形成循环。
Ctrl+w h:切换到左侧窗口(left)。
Ctrl+w j:切换到下方窗口(down)。
Ctrl+w k:切换到上方窗口(up)。
Ctrl+w l:切换到右侧窗口(right)。

这些命令的方向键 h, j, k, l 分别对应 Vim 的方向键,记忆起来非常方便。

6.2.5 窗口大小调整:Ctrl+w 系列命令

Ctrl+w 系列命令还可以用来调整窗口的大小:

Ctrl+w +:增加当前窗口的高度(水平分割窗口)。
Ctrl+w -:减小当前窗口的高度(水平分割窗口)。
Ctrl+w _:最大化当前窗口的高度(水平分割窗口)。
Ctrl+w |:最大化当前窗口的宽度(垂直分割窗口)。
Ctrl+w =:使所有窗口的高度和宽度相等。

6.2.6 关闭窗口::close:clo, :quit:q, Ctrl+w c, Ctrl+w q

关闭窗口也有多种方式:

:close:clo:关闭当前窗口。如果当前窗口是最后一个窗口,Vim 会退出。
:quit:q:关闭当前窗口。如果当前窗口是最后一个窗口,Vim 会退出。与 :close 类似,但 :quit 在某些情况下可能会有不同的行为,例如在帮助窗口中。
Ctrl+w c:关闭当前窗口,与 :close 效果相同。
Ctrl+w q:关闭当前窗口,与 :quit 效果相同。

注意事项

未保存的修改:如果窗口显示的缓冲区内容自上次保存后被修改过,关闭窗口的命令会阻止你关闭窗口,并提示你先保存或放弃修改。
强制关闭:可以使用 :close!:clo!, :quit!:q!, Ctrl+w !c, Ctrl+w !q 命令进行强制关闭,放弃未保存的修改。
最后一个窗口:如果关闭的是最后一个窗口,Vim 会退出。

最佳实践

⚝ 根据需要灵活使用水平分割和垂直分割,组织你的工作区。
⚝ 熟练掌握 Ctrl+w 系列命令,快速切换和调整窗口大小。
⚝ 使用窗口分割同时查看和编辑多个相关文件,提高代码编写和文档处理效率。
⚝ 在关闭窗口之前,务必确认是否已保存所有修改,避免数据丢失。

6.3 标签页管理::tabnew, :tabnext, :tabprev, :tabclose

标签页(Tab Page)是 Vim 中组织窗口的更高层次结构。一个标签页可以包含多个窗口,每个窗口可以显示不同的缓冲区。标签页允许你在不同的工作区之间快速切换,非常适合处理大型项目或者需要在不同任务之间切换的场景。

6.3.1 标签页的基本概念

工作区:标签页可以看作是一个独立的工作区,每个标签页可以包含一组窗口布局。
组织:标签页用于组织窗口,使得你可以将不同的任务或项目放在不同的标签页中,避免窗口混乱。
切换:可以在不同的标签页之间快速切换,就像浏览器中的标签页一样。

6.3.2 创建新标签页::tabnew:tabn

:tabnew 命令(简写 :tabn)用于创建一个新的标签页。

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 :tabnew

或者

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 :tabn

执行上述命令后,Vim 会创建一个新的标签页,并在新标签页中打开一个空的缓冲区。

你也可以在 :tabnew 命令后指定要打开的文件名,在新标签页中打开并显示该文件对应的缓冲区。

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 :tabnew chapter9.txt

6.3.3 切换标签页::tabnext:tabn, :tabprev:tabp, :tabfirst, :tablast, :tabm

Vim 提供了多种命令来切换标签页:

:tabnext:tabn:切换到下一个标签页(按照标签页创建的顺序)。如果当前是最后一个标签页,则切换到第一个标签页,形成循环。
:tabprev:tabp:切换到上一个标签页(按照标签页创建的顺序)。如果当前是第一个标签页,则切换到最后一个标签页,形成循环。
:tabfirst:tabfir:切换到第一个标签页。
:tablast:tabl:切换到最后一个标签页。
:tabm <位置>:移动当前标签页到指定位置。位置可以是:
▮▮▮▮ⓕ 0:移动到第一个位置。
▮▮▮▮ⓖ $:移动到最后一个位置。
▮▮▮▮ⓗ -1:向前移动一个位置。
▮▮▮▮ⓘ +1:向后移动一个位置。
▮▮▮▮ⓙ 数字 n:移动到第 n 个位置(从 0 开始计数)。

示例

假设我们有三个标签页,当前活动标签页是第二个标签页。

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 :tabn " 切换到下一个标签页,即第三个标签页
2 :tabp " 切换到上一个标签页,即第二个标签页 (从第三个标签页切换回来)
3 :tabfirst " 切换到第一个标签页
4 :tablast " 切换到最后一个标签页
5 :tabm 0 " 将当前标签页移动到第一个位置
6 :tabm $ " 将当前标签页移动到最后一个位置
7 :tabm -1 " 将当前标签页向前移动一个位置
8 :tabm +1 " 将当前标签页向后移动一个位置
9 :tabm 2 " 将当前标签页移动到第三个位置 (假设存在)

6.3.4 关闭标签页::tabclose:tabc, :tabonly, :tabdo

关闭标签页的命令:

:tabclose:tabc:关闭当前标签页。如果当前标签页是最后一个标签页,Vim 会退出。
:tabonly:tabo:关闭所有其他标签页,只保留当前标签页。
:tabdo <命令>:在所有标签页中执行指定的命令。例如,:tabdo :w 保存所有标签页中的修改。

注意事项

未保存的修改:如果标签页中的任何窗口显示的缓冲区内容自上次保存后被修改过,关闭标签页的命令会阻止你关闭标签页,并提示你先保存或放弃修改。
强制关闭:可以使用 :tabclose!:tabc! 命令进行强制关闭,放弃未保存的修改。
最后一个标签页:如果关闭的是最后一个标签页,Vim 会退出。

最佳实践

⚝ 使用标签页来组织不同的项目或任务,保持工作区的清晰和有序。
⚝ 熟练掌握标签页切换命令,快速在不同的工作区之间切换。
⚝ 使用 :tabdo 命令批量操作所有标签页,例如批量保存、批量查找替换等。
⚝ 在关闭标签页之前,务必确认是否已保存所有修改,避免数据丢失。

6.4 文件浏览器与目录树::Explore, 插件推荐

Vim 自带了一个简单的文件浏览器 :Explore,可以用来浏览文件系统。此外,还有许多强大的插件可以提供更完善的文件浏览器和目录树功能,例如 NERDTree, vim-vinegar, coc-explorer 等。

6.4.1 Vim 内置文件浏览器::Explore

:Explore 命令可以打开 Vim 的内置文件浏览器。

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 :Explore

执行上述命令后,Vim 会在一个新的窗口中打开文件浏览器,显示当前目录的文件和目录列表。

文件浏览器操作

方向键 j, k:上下移动光标选择文件或目录。
Enter
▮▮▮▮ⓐ 如果选择的是文件,则在当前窗口打开该文件。
▮▮▮▮ⓑ 如果选择的是目录,则进入该目录,显示该目录下的文件和目录列表。
-:返回上一级目录。
%:在新窗口中水平分割打开选中的文件。
^:在新窗口中垂直分割打开选中的文件。
t:在新标签页中打开选中的文件。
i:切换文件浏览器窗口的显示模式(详细列表、简洁列表、树状列表等)。
r:重命名选中的文件或目录。
d:删除选中的文件或目录。
c:创建新的目录。
a:创建新的文件。
q:关闭文件浏览器窗口。

:Explore 命令还有一些变体,可以打开不同模式的文件浏览器:

:Explore .:在文件浏览器中打开当前目录。
:Sexplore:水平分割窗口,并在新窗口中打开文件浏览器。
:Vexplore:垂直分割窗口,并在新窗口中打开文件浏览器。
:Texplore:在新标签页中打开文件浏览器。

6.4.2 文件浏览器插件推荐

虽然 Vim 内置的文件浏览器 :Explore 已经足够基本的文件浏览需求,但对于更复杂的文件管理和项目导航,使用专门的文件浏览器插件会更加高效和便捷。以下是一些常用的 Vim 文件浏览器插件推荐:

NERDTree

功能强大:NERDTree 是最流行的 Vim 文件浏览器插件之一,提供树状目录结构、文件预览、文件操作(创建、删除、重命名、移动等)、书签等丰富功能。
高度可定制:NERDTree 提供了丰富的配置选项,可以自定义外观、快捷键、文件过滤等。
插件地址https://github.com/preservim/nerdtree

vim-vinegar

简洁高效:vim-vinegar 是一款轻量级的文件浏览器插件,遵循 Vim 的哲学,提供简洁高效的文件浏览体验。
与 Vim 风格一致:vim-vinegar 的操作方式与 Vim 的其他操作风格一致,学习成本低。
插件地址https://github.com/junegunn/vim-vinegar

coc-explorer

现代界面:coc-explorer 是 coc.nvim 插件生态系统的一部分,提供现代化的文件浏览器界面,支持异步加载、文件图标、Git 状态显示等。
集成 coc.nvim:coc-explorer 与 coc.nvim 插件生态系统深度集成,可以与其他 coc 插件协同工作,例如代码补全、语法检查等。
插件地址https://github.com/weirongbing/coc-explorer

插件选择建议

初学者:如果只是需要基本的文件浏览功能,可以使用 Vim 内置的 :Explore 命令。
需要强大功能:如果需要更强大的文件管理功能,例如树状目录结构、文件操作、书签等,可以选择 NERDTree。
追求简洁高效:如果追求简洁高效的文件浏览体验,并且喜欢 Vim 的风格,可以选择 vim-vinegar。
使用 coc.nvim:如果已经在使用 coc.nvim 插件生态系统,并且喜欢现代化的界面,可以选择 coc-explorer。

插件安装

安装 Vim 插件通常需要使用插件管理器,例如 Vundle, Pathogen, vim-plug 等。插件管理器的使用方法请参考相关文档。

最佳实践

⚝ 根据自己的需求选择合适的文件浏览器工具,提高文件管理和项目导航效率。
⚝ 熟练掌握文件浏览器的操作快捷键,快速浏览和操作文件。
⚝ 结合文件浏览器和窗口分割、标签页管理等功能,构建高效的项目级编辑环境。

本章介绍了 Vim 的多文件操作功能,包括缓冲区管理、窗口分割、标签页管理以及文件浏览器。掌握这些功能,你将能够在一个 Vim 实例中高效地处理多个文件,提升项目级编辑的效率。在实际使用中,可以根据自己的工作习惯和项目需求,灵活组合和运用这些功能,打造个性化的高效编辑环境。

ENDOF_CHAPTER_

7. chapter 7: 宏与自动化:效率倍增的秘诀

7.1 宏的录制与播放:q 命令

宏(Macro)是 Vim 中一项极其强大的自动化工具,它允许你录制一系列的键盘操作,并在之后重复播放这些操作。想象一下,你需要对多行文本进行相同的复杂编辑,例如,在每一行的开头添加特定的前缀,或者修改每一行中特定位置的文本。如果没有宏,你可能需要一遍又一遍地重复相同的操作,这不仅效率低下,而且容易出错。而宏的出现,正是为了解决这类重复性任务,让你能够一键完成复杂的批量编辑,真正实现效率的倍增。

Vim 的宏功能核心在于 q 命令,它就像一个录音机上的“录制”按钮。要开始录制宏,你需要按下 q 键,紧接着指定一个寄存器(register)来存储你录制的操作序列。寄存器可以理解为一个临时的存储位置,Vim 使用字母 az 以及数字 09 等作为寄存器的名称。例如,如果你想将宏录制到寄存器 a 中,你需要输入 qa

一旦你输入了 qa,Vim 的底部状态栏会显示 “recording @a”,表示宏录制已经开始。这时,你所做的任何 Normal 模式下的操作都会被记录下来,包括移动光标、文本编辑、命令执行等等。当你完成需要录制的操作序列后,再次按下 q 键,宏录制就会停止。此时,你刚才的操作序列就被完整地保存在了寄存器 a 中。

录制宏的完整流程可以用以下步骤概括:

① 按下 q 键,启动宏录制。
② 指定一个寄存器(例如 az)来存储宏,例如输入 qa 表示使用寄存器 a
③ 执行你想要录制的一系列 Vim 命令和操作。
④ 再次按下 q 键,停止宏录制。

录制完成后,如何播放宏呢? 这就需要用到 @ 命令。@ 命令后跟寄存器的名称,就可以播放该寄存器中存储的宏。例如,要播放刚才录制到寄存器 a 中的宏,你只需要输入 @a。Vim 就会自动执行你之前录制的所有操作,就像有一个小助手在帮你重复劳动一样。

让我们通过一个简单的例子来演示宏的录制与播放。假设我们有如下几行文本,我们想要在每一行的开头添加 * 符号,将其转换为 Markdown 的无序列表:

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 apple
2 banana
3 orange
4 grape

使用宏可以非常快速地完成这个任务:

① 将光标移动到第一行 apple 的开头。
② 输入 qa 开始录制宏到寄存器 a
③ 输入 I* <Esc>。 这组命令的含义是:
▮▮▮▮ⓓ I:进入行首插入模式(Insert mode at the beginning of the line)。
▮▮▮▮ⓔ *:输入 * 符号(注意星号后有一个空格)。
▮▮▮▮ⓕ <Esc>:回到 Normal 模式。
⑦ 输入 j,将光标移动到下一行。
⑧ 输入 q,停止宏录制。

现在,寄存器 a 中就存储了 “在行首插入 * 并移动到下一行” 这一系列操作。要将这个宏应用到剩下的行,只需要将光标移动到第二行 banana 的开头,然后输入 @a。你会看到第二行也变成了 * banana。接着,你可以继续输入 @a,将宏应用到第三行、第四行,直到所有行都处理完毕。

为了更高效地重复执行宏,我们可以使用数字前缀。例如,如果你想将宏 @a 重复执行 3 次,可以输入 3@a。在这个例子中,我们有 4 行文本需要处理,第一行已经手动添加了 *,剩下的 3 行可以使用 3@a 一次性完成。

宏的录制和播放是 Vim 自动化操作的基础,掌握 q@ 命令,你就能轻松应对各种重复性的文本编辑任务,大幅提升你的工作效率。

7.2 宏的编辑与重复执行:@, @@, 数字前缀

上一节我们学习了宏的录制和播放,掌握了 q@ 命令的基本用法。本节我们将深入探讨宏的重复执行和编辑技巧,让你更加灵活地运用宏来提升效率。

重复执行宏:@@ 命令

在实际使用中,我们经常需要重复执行刚刚执行过的宏。Vim 提供了 @@ 命令,用于快速重复上次执行的宏,而无需再次输入寄存器名称。例如,如果你刚刚执行了 @a,想要再次执行相同的宏,只需要输入 @@ 即可。这在需要连续多次应用同一个宏的场景下非常方便,可以减少重复输入,提高操作效率。

继续上一节的例子,在为第一行添加 * 后,我们使用了 @a 命令为第二行添加了前缀。此时,如果光标已经移动到了第三行,我们只需要输入 @@,就可以为第三行添加 * 前缀,而无需再次输入 @a。 连续输入 @@,就可以快速处理后续的行。

数字前缀:批量执行宏

除了 @@ 命令,我们还可以使用数字前缀(numeric prefix)来批量执行宏。在 @ 命令之前输入一个数字,表示将宏重复执行指定的次数。例如,3@a 表示将寄存器 a 中的宏执行 3 次。

在之前的 Markdown 列表例子中,我们手动处理了第一行,剩下的三行可以使用 3@a 一次性完成。 假设光标位于第二行 banana 的行首,输入 3@a 后,Vim 会自动将宏 @a 执行三次,依次处理 bananaorangegrape 这三行,最终将它们都转换为 Markdown 列表项。

数字前缀与 @@ 命令也可以结合使用。例如,5@@ 表示将上次执行的宏重复执行 5 次。

宏的编辑

有时候,我们录制的宏可能并不完美,或者在使用的过程中发现需要对宏进行微调。Vim 允许我们编辑宏,虽然不能像编辑文本文件那样直接修改宏的内容,但我们可以通过一种巧妙的方式来间接编辑宏。

宏本质上是存储在寄存器中的一段文本,这段文本就是我们录制的操作序列。我们可以像粘贴寄存器内容一样,将宏的内容粘贴到 Vim 的缓冲区中进行编辑,然后再将编辑后的内容重新存回寄存器,从而达到编辑宏的目的。

具体步骤如下:

粘贴宏内容: 使用 "{register}p 命令将指定寄存器中的宏内容粘贴到当前光标位置。例如,要编辑寄存器 a 中的宏,可以输入 "ap。 这会将寄存器 a 中的宏操作序列以文本形式粘贴出来。

编辑宏内容: 粘贴出来的宏内容实际上是一系列 Vim 命令的文本表示。你可以像编辑普通文本一样,对这些命令进行修改、删除或添加。 例如,你可能会看到类似 i* <Esc>j 这样的文本,这对应于我们在之前例子中录制的宏。你可以根据需要修改这些命令。

重新存回寄存器: 编辑完成后,将光标移动到编辑后的宏文本的第一行,然后使用 "{register}y{motion} 命令将编辑后的文本覆盖原寄存器中的宏。 一个常用的方法是使用 "_dd"{register}Y 命令。
▮▮▮▮ⓑ "_dd": 删除当前行,并放入黑洞寄存器 _,即不影响任何普通寄存器。
▮▮▮▮ⓒ "{register}Y: 将当前行复制到指定的寄存器。 Y 相当于 yy,复制当前行。

例如,要将编辑后的宏文本重新存回寄存器 a,可以使用 "_ddaY (假设光标在编辑后的宏文本的第一行)。

宏编辑示例

假设我们录制的宏 @b 的内容是在行尾添加一个逗号 ,。 但是,我们现在希望修改宏,使其在行尾添加的是分号 ;。 我们可以这样编辑宏 @b

① 输入 "bp 将寄存器 b 中的宏内容粘贴出来。 假设粘贴出来的内容是 A,<Esc>
② 将光标移动到逗号 , 的位置,将其修改为分号 ;。 修改后的内容变为 A;<Esc>
③ 将光标移动到 A;<Esc> 这一行的行首。
④ 输入 "_dd"bY 将修改后的宏重新存回寄存器 b

现在,寄存器 b 中的宏就变成了在行尾添加分号 ;。 再次执行 @b,就会在行尾添加分号而不是逗号了。

通过这种粘贴、编辑、重新存回的方式,我们可以灵活地修改宏的内容,使其适应不断变化的需求。 宏的编辑功能为我们提供了更大的灵活性,即使录制初期考虑不周,后期仍然可以轻松调整和完善宏,确保其能够准确高效地完成任务。

7.3 宏的进阶应用:递归宏与条件宏

掌握了宏的录制、播放、重复执行和编辑等基本技巧后,我们已经能够利用宏解决很多重复性任务了。 本节我们将介绍宏的两种进阶应用:递归宏(recursive macro)条件宏(conditional macro),进一步挖掘宏的潜力,让你的 Vim 技能更上一层楼。

递归宏

递归宏是指在宏的定义中调用宏自身。 这种宏在处理结构化的文本数据时非常有用,例如,处理嵌套列表、XML 或 JSON 数据等。 递归宏的核心思想是将一个复杂的问题分解为更小的、自相似的子问题,并通过宏的自我调用来逐层解决。

要创建递归宏,关键在于在录制宏的过程中,调用正在录制的宏所在的寄存器。 听起来可能有些抽象,我们通过一个例子来具体说明。

假设我们有如下 Markdown 列表,其中包含嵌套列表,我们想要删除所有列表项前的 * 符号,只保留纯文本内容:

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 * Item 1
2 * Item 2
3 * Subitem 2.1
4 * Subitem 2.2
5 * Item 3

我们可以创建一个递归宏来处理这个问题。 宏的思路是:删除当前行行首的 *,然后移动到下一行,并判断下一行是否仍然是列表项(即行首是否以 * 开头)。 如果是,则递归调用宏自身继续处理;如果不是,则停止递归。

录制递归宏的步骤如下(假设使用寄存器 c):

① 将光标移动到第一行 * Item 1 的行首。
② 输入 qc 开始录制宏到寄存器 c
③ 输入 ^2x 删除行首的 *^ 移动到行首第一个非空白字符,2x 删除两个字符)。
④ 输入 j 移动到下一行。
关键步骤: 输入 :if getline('.') =~ '^\* ' <CR> @c <CR> endif <CR>。 这段命令是 Vimscript 的条件判断语句,它的含义是:
▮▮▮▮ⓕ :if getline('.') =~ '^\* ' <CR>: 判断当前行. 表示当前行)是否匹配正则表达式 ^\*getline('.') 获取当前行的内容, =~ 表示匹配操作符, ^\* 表示以 * 开头的正则表达式。 <CR> 表示回车,执行命令。
▮▮▮▮ⓖ @c <CR>: 如果条件成立(当前行以 * 开头),则递归调用宏 @c
▮▮▮▮ⓗ endif <CR>: 结束条件判断语句。
⑨ 输入 q 停止宏录制。

现在,寄存器 c 中就存储了一个递归宏。 将光标移动到第一行 * Item 1,然后输入 @c。 Vim 会执行宏 @c,删除第一行的 *,移动到第二行,判断第二行是否以 * 开头,如果是,则再次调用 @c 处理第二行,以此类推,直到遇到非列表项的行或者文件末尾,递归才会停止。

在这个例子中,宏 @c 会依次处理所有以 * 开头的行,删除行首的 *,最终将 Markdown 列表转换为纯文本:

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 Item 1
2 Item 2
3 Subitem 2.1
4 Subitem 2.2
5 Item 3

条件宏

严格来说,Vim 宏本身并不直接支持条件判断。 上面递归宏的例子中,我们实际上是借助 Vimscript 的条件判断语句 :if 来实现条件执行的效果。 因此,我们所说的“条件宏”,更准确地说是在宏中嵌入条件判断逻辑

除了使用 :if 语句,我们还可以利用 Vim 的其他特性来间接实现条件宏的效果。 例如,可以使用 v 模式(Visual 模式)结合条件判断,或者利用查找命令 /? 的返回值来控制宏的流程。

虽然 Vim 宏的条件判断能力相对有限,但通过巧妙地结合 Vimscript 和 Vim 的各种命令,我们仍然可以构建出功能强大的条件宏,应对更复杂的自动化场景。

总结

递归宏和条件宏是宏的进阶应用,它们 позволят 你处理更复杂、结构化的文本数据,实现更加智能化的自动化操作。 掌握递归宏,可以让你轻松处理嵌套结构的数据; 灵活运用条件判断,则可以使宏具备一定的“智能”,根据不同的情况执行不同的操作。 虽然条件宏的实现方式可能需要一些技巧,但掌握这些技巧将极大地扩展你的 Vim 自动化能力,让你在文本编辑的道路上更进一步。

ENDOF_CHAPTER_

8. chapter 8: Vim 配置:打造个性化编辑器

8.1 .vimrc 文件:Vim 配置的入口

Vim 的强大之处不仅在于其高效的编辑模式和丰富的命令,还在于其高度的可配置性。用户可以通过配置文件来自定义 Vim 的行为,使其更符合个人的使用习惯和工作流程。而 .vimrc 文件,正是 Vim 配置的入口,是打造个性化 Vim 编辑器的基石。

.vimrc 文件是一个纯文本文件,Vim 启动时会自动读取该文件中的配置命令,从而应用各种自定义设置。可以将其视为 Vim 的“大脑”,所有的个性化指令都存储在这里。

.vimrc 文件的位置

.vimrc 文件的位置取决于操作系统:

Unix-like 系统 (Linux, macOS 等)
⚝ 通常位于用户主目录 ~ 下,文件名为 .vimrc
⚝ 有些系统也可能支持在 ~/.vim/vimrc~/.config/nvim/init.vim (对于 Neovim) 位置。Vim 会按照一定的顺序查找这些文件,找到第一个存在的就加载。
Windows 系统
⚝ 通常位于用户主目录,文件名为 _vimrc
⚝ 用户主目录的确定方式可能因 Windows 版本而异,通常是 C:\Users\<YourUsername>%USERPROFILE% 环境变量指向的目录。
⚝ 也可以在 Vim 的安装目录下查找 _vimrcvimrc 文件,全局配置可能位于此处。

创建和编辑 .vimrc 文件

如果你的主目录下还没有 .vimrc 文件,你需要手动创建它。可以使用 Vim 本身来创建和编辑:

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 vim ~/.vimrc # Unix-like 系统
2 vim ~/_vimrc # Windows 系统

或者,你也可以使用任何文本编辑器来创建和编辑 .vimrc 文件。

.vimrc 文件的基本结构

.vimrc 文件主要由一系列 Vim 命令组成,每行一个命令。Vim 命令不区分大小写,但为了代码的可读性,通常建议使用小写。

.vimrc 文件中可以包含以下类型的配置:

设置选项 (Options)
⚝ 用于改变 Vim 的各种行为和特性,例如显示行号、设置缩进、启用语法高亮等。
⚝ 设置选项的命令通常以 set 开头,例如 set number (显示行号), set tabstop=4 (设置 Tab 宽度为 4 个空格)。
键位映射 (Mappings)
⚝ 用于自定义快捷键,将某个键或组合键映射到 Vim 命令或操作序列。
⚝ 映射命令以 map 系列命令开头,例如 map <F5> :w<CR> (将 F5 键映射为保存文件命令)。
自动命令 (Autocommands)
⚝ 用于在特定事件发生时自动执行某些命令,例如在打开特定类型文件时设置特定的选项。
⚝ 自动命令以 autocmd 开头。
插件配置 (Plugin Configurations)
⚝ 当你安装了 Vim 插件后,插件的配置通常也会放在 .vimrc 文件中。
注释 (Comments)
⚝ 使用双引号 " 开头的行表示注释,Vim 会忽略注释行。注释用于提高 .vimrc 文件的可读性,方便理解配置的作用。

一个简单的 .vimrc 示例

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 " 这是一个 .vimrc 示例文件
2
3 " 设置行号
4 set number
5
6 " 启用相对行号
7 set relativenumber
8
9 " 设置 Tab 宽度为 4 个空格
10 set tabstop=4
11 set shiftwidth=4
12 set expandtab " 将 Tab 转换为空格
13
14 " 启用语法高亮
15 syntax on
16
17 " 设置配色方案 (例如:solarized)
18 colorscheme solarized
19
20 " 启用鼠标支持
21 set mouse=a
22
23 " 搜索时忽略大小写
24 set ignorecase
25 set smartcase " 智能大小写:当搜索模式包含大写字母时,区分大小写;否则忽略大小写
26
27 " 显示命令历史记录的行数
28 set history=1000
29
30 " 启用自动补全
31 set wildmenu
32 set wildmode=longest:list,full
33
34 " 一些常用的键位映射
35 " 使用 jk 快速退出 Insert 模式
36 inoremap jk <Esc>
37
38 " 保存文件并退出
39 nnoremap <leader>wq :wq<CR>

.vimrc 的加载过程

Vim 启动时,会按照以下顺序查找并加载配置文件:

系统级配置文件
⚝ 通常位于 Vim 安装目录下的 _vimrcvimrc (Windows) 或 /etc/vimrc/etc/vim/vimrc (Unix-like)。
⚝ 系统级配置对所有用户生效,通常由系统管理员配置。
用户级配置文件
⚝ 即我们讨论的 .vimrc 文件,位于用户主目录下。
⚝ 用户级配置只对当前用户生效,用户可以根据自己的喜好进行自定义。
当前目录的 .vimrc (或 _vimrc)
⚝ Vim 也会查找当前工作目录下的 .vimrc_vimrc 文件。
⚝ 目录级配置只对当前目录及其子目录下的文件生效,可以用于项目特定的配置。

Vim 会依次加载这些配置文件,后面的配置会覆盖前面的配置。因此,用户级配置会覆盖系统级配置,目录级配置会覆盖用户级配置。

小结

.vimrc 文件是 Vim 配置的核心,通过编辑 .vimrc 文件,你可以定制 Vim 的各种功能和外观,使其成为真正属于你自己的编辑器。从简单的选项设置到复杂的键位映射和自动命令,.vimrc 提供了无限的可能性,让你不断优化你的 Vim 使用体验。掌握 .vimrc 的配置方法,是深入 Vim 世界,提升编辑效率的关键一步。

8.2 常用配置选项详解:行号、缩进、搜索、界面等

Vim 提供了大量的配置选项 (options),用于控制编辑器的各种行为。通过 setset no 命令,可以启用和禁用布尔类型的选项,或者使用 set option=value 来设置选项的值。本节将详细介绍一些常用的配置选项,涵盖行号、缩进、搜索、界面等方面,帮助你快速上手 Vim 配置。

1. 行号 (Line Numbers)

行号可以帮助你快速定位代码行,尤其是在调试和代码审查时非常有用。

number (或 nu): 显示绝对行号。

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 set number

启用后,Vim 会在每行前面显示绝对行号。

relativenumber (或 rnu): 显示相对行号。

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 set relativenumber

启用后,当前行显示为 0,上方行依次为 1, 2, 3...,下方行也依次为 1, 2, 3...。相对行号在配合移动命令时非常方便,例如 5j 可以快速向下移动 5 行。

同时启用绝对行号和相对行号: 可以同时启用 numberrelativenumber,绝对行号显示在左侧,相对行号显示在右侧。

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 set number relativenumber

2. 缩进 (Indentation)

缩进对于代码的可读性至关重要,Vim 提供了丰富的缩进选项来满足不同编程语言的缩进需求。

tabstop (或 ts): 设置 Tab 键的宽度,即一个 Tab 字符显示占用的空格数。

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 set tabstop=4 " 设置 Tab 宽度为 4 个空格

通常设置为 2 或 4。

shiftwidth (或 sw): 设置缩进和反缩进操作 (例如 >><< 命令) 的宽度。

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 set shiftwidth=4 " 设置缩进宽度为 4 个空格

通常与 tabstop 设置为相同的值。

expandtab (或 et): 将 Tab 键转换为空格。

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 set expandtab " 启用:按下 Tab 键时插入空格
2 set noexpandtab " 禁用:按下 Tab 键时插入 Tab 字符

在现代编程中,通常推荐使用空格缩进,启用 expandtab 可以避免 Tab 和空格混用导致的问题。

autoindent (或 ai): 自动缩进。

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 set autoindent " 启用:新行自动与上一行对齐缩进

在 Insert 模式下,按下回车键后,新行会自动与上一行保持相同的缩进级别。

smartindent (或 si): 智能缩进。

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 set smartindent " 启用:在 autoindent 的基础上,根据语法进行更智能的缩进

smartindentautoindent 更智能,例如在 C 语言中,在输入 { 后,下一行会自动增加缩进。

cindent: C 风格缩进。

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 set cindent " 启用:更严格的 C 语言风格缩进

cindent 提供了更符合 C 语言规范的缩进方式,适用于 C, C++, Java 等语言。

3. 搜索 (Search)

搜索功能是文本编辑器的核心功能之一,Vim 提供了强大的搜索选项。

incsearch: 增量搜索 (Incremental Search)。

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 set incsearch " 启用:输入搜索内容时,实时显示匹配结果

启用后,在输入搜索命令 /? 后,每输入一个字符,Vim 都会立即开始搜索并高亮显示匹配项。

hlsearch: 高亮显示搜索结果 (Highlight Search)。

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 set hlsearch " 启用:高亮显示所有匹配的搜索结果
2 set nohlsearch " 禁用:取消高亮显示搜索结果

启用后,搜索到的所有匹配项都会被高亮显示。可以使用 :nohlsearch 命令临时取消高亮显示。

ignorecase (或 ic): 搜索时忽略大小写。

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 set ignorecase " 启用:搜索时忽略大小写
2 set noignorecase " 禁用:搜索时区分大小写

smartcase: 智能大小写搜索。

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 set smartcase " 启用:当搜索模式包含大写字母时,区分大小写;否则忽略大小写

smartcase 通常与 ignorecase 一起使用,提供更智能的搜索体验。

4. 界面 (Interface)

Vim 的界面可以根据个人喜好进行定制,提升使用舒适度。

cursorline: 高亮显示当前行。

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 set cursorline " 启用:高亮显示光标所在的行

可以更清晰地看到当前编辑的行。

cursorcolumn: 高亮显示当前列。

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 set cursorcolumn " 启用:高亮显示光标所在的列

可以更清晰地看到当前编辑的列,对于对齐代码很有帮助。

wildmenu: 启用命令行的增强补全菜单。

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 set wildmenu " 启用:在命令行模式下,按下 Tab 键时显示补全菜单

启用后,在输入命令时,按下 Tab 键可以显示可用的补全选项,例如文件名、命令名、选项名等。

wildmode: 设置命令行补全模式。

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 set wildmode=longest:list,full " 设置补全模式

常用的 wildmode 值:
longest: 补全到最长公共前缀。
list: 显示所有匹配项列表。
full: 循环显示所有匹配项。

mouse: 启用鼠标支持。

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 set mouse=a " 启用:在所有模式下启用鼠标支持
2 set mouse=n " 只在 Normal 模式下启用鼠标支持
3 set mouse=v " 只在 Visual 模式下启用鼠标支持
4 set mouse=i " 只在 Insert 模式下启用鼠标支持
5 set mouse=c " 只在 Command-line 模式下启用鼠标支持
6 set mouse=r " 只在 Replace 模式下启用鼠标支持
7 set mouse=h " 在帮助窗口中启用鼠标支持
8 set mouse= "" 禁用鼠标支持

启用鼠标支持后,可以使用鼠标进行光标移动、窗口切换、菜单操作等。

clipboard: 设置剪贴板行为。

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 set clipboard=unnamedplus " 使用系统剪贴板 (需要 Vim 编译时支持 +clipboard 或 +xterm_clipboard 特性)
2 set clipboard=unnamed " 使用 * 寄存器作为剪贴板 (X11 系统)

unnamedplus 通常用于 GUI Vim,可以与系统剪贴板无缝集成。unnamed 通常用于终端 Vim 在 X11 系统中使用 * 寄存器作为剪贴板。

5. 编码 (Encoding)

编码设置对于正确显示和处理各种字符集非常重要。

encoding: Vim 内部使用的字符编码。

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 set encoding=utf-8 " 设置 Vim 内部编码为 UTF-8

通常设置为 utf-8,支持全球大部分字符集。

fileencoding: 文件编码。

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 set fileencoding=utf-8 " 设置新文件的默认编码为 UTF-8

fileencoding 是 Vim 读取和写入文件时使用的编码。通常也设置为 utf-8

fileencodings: 自动检测文件编码的列表。

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 set fileencodings=utf-8,gbk,latin1 " 设置自动检测编码的顺序

Vim 会按照列表中的顺序尝试检测文件编码。

6. 其他常用选项

swapfile: 启用交换文件 (Swap File)。

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 set swapfile " 启用:在编辑文件时创建交换文件,用于崩溃恢复
2 set noswapfile " 禁用:不创建交换文件

通常建议启用 swapfile,以防止意外情况导致数据丢失。

backup: 启用备份文件 (Backup File)。

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 set backup " 启用:在保存文件时创建备份文件
2 set nobackup " 禁用:不创建备份文件

启用 backup 可以保留文件的旧版本,以防误操作。

undofile: 启用持久化撤销 (Persistent Undo)。

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 set undofile " 启用:将撤销历史记录保存到文件,下次打开文件时可以继续撤销
2 set noundofile " 禁用:不保存撤销历史记录

启用 undofile 可以实现跨会话的撤销操作。

history: 设置命令历史记录和搜索历史记录的最大行数。

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 set history=1000 " 设置历史记录最大行数为 1000

增加历史记录行数可以方便地查找和重复使用之前的命令和搜索。

总结

以上只是一些常用的 Vim 配置选项,Vim 提供了数百个选项来定制编辑器的各个方面。你可以根据自己的需求,查阅 Vim 的帮助文档 :help options,探索更多的配置选项,打造最适合你的 Vim 编辑器。记住,配置是一个持续优化的过程,随着你对 Vim 的深入了解,你可以不断调整和完善你的 .vimrc 文件。

8.3 配色方案与字体设置:美化 Vim 界面

Vim 的外观也是个性化配置的重要组成部分。一个舒适美观的界面可以提升你的编辑体验,让你更专注于代码和文本。本节将介绍如何设置 Vim 的配色方案 (colorscheme) 和字体 (font),美化你的 Vim 界面。

1. 配色方案 (Colorscheme)

配色方案定义了 Vim 中各种元素 (例如:关键字、注释、字符串、背景等) 的颜色。Vim 自带了一些配色方案,同时也支持用户安装和使用第三方配色方案。

查看当前配色方案: 使用 :colorscheme 命令,不加任何参数,可以查看当前正在使用的配色方案名称。

切换配色方案: 使用 :colorscheme <name> 命令,可以将 Vim 的配色方案切换为 <name>。例如:

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 :colorscheme desert
2 :colorscheme evening
3 :colorscheme industry
4 :colorscheme koehler
5 :colorscheme morning
6 :colorscheme murphy
7 :colorscheme pablo
8 :colorscheme ron
9 :colorscheme shine
10 :colorscheme slate
11 :colorscheme delek
12 :colorscheme elflord
13 :colorscheme zellner

你可以尝试不同的配色方案,找到你喜欢的风格。

预览配色方案: 可以使用 Tab 键补全配色方案名称,方便预览。在输入 :colorscheme <部分名称> 后,按下 Tab 键,Vim 会列出匹配的配色方案,你可以继续按 Tab 键循环切换,实时预览效果。

设置默认配色方案: 将 :colorscheme <name> 命令添加到 .vimrc 文件中,可以设置 Vim 启动时默认使用的配色方案。例如,在 .vimrc 中添加 colorscheme solarized,可以将默认配色方案设置为 solarized

配色方案文件位置: Vim 的配色方案文件通常位于以下目录:
系统级: Vim 安装目录下的 colors 目录,例如 /usr/share/vim/vim<version>/colors (Unix-like) 或 C:\Program Files\Vim\vim<version>\colors (Windows)。
用户级: 用户主目录下的 .vim/colors 目录 (Unix-like) 或 vimfiles\colors 目录 (Windows)。

Vim 会在这些目录下查找配色方案文件 (.vim 文件)。

第三方配色方案: 有很多优秀的第三方 Vim 配色方案,你可以在网上搜索 "vim colorscheme" 找到它们。常见的配色方案网站包括:
vimcolors.com: http://vimcolors.com/
vim-color-schemes: https://github.com/flazz/vim-color-schemes

安装第三方配色方案通常需要将 .vim 文件下载到用户级的 colors 目录下。然后就可以在 Vim 中使用 :colorscheme <配色方案名称> 命令切换到该配色方案。

2. 字体设置 (Font)

字体设置主要针对 GUI Vim (例如 gvim, MacVim, Vim for Windows)。终端 Vim 的字体通常由终端程序本身设置。

设置字体: 使用 :set guifont=<字体名称>:<字体大小> 命令可以设置 GUI Vim 的字体。例如:

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 :set guifont=Monospace:h12 " 设置字体为 Monospace,字号为 12
2 :set guifont=Consolas:h14 " 设置字体为 Consolas,字号为 14

字体名称和字号的格式可能因操作系统和 Vim 版本而异。

字体选择: 选择合适的字体对于提高代码可读性非常重要。通常推荐使用等宽字体 (monospace font),例如:
Consolas: Windows 系统常用的等宽字体,清晰易读。
Menlo: macOS 系统默认的等宽字体,美观现代。
Source Code Pro: Adobe 开发的开源等宽字体,专为代码阅读设计。
Fira Code: Mozilla 开发的开源等宽字体,支持连字 (ligatures),可以更清晰地显示代码符号。
JetBrains Mono: JetBrains 开发的等宽字体,专为开发者设计,具有优秀的易读性。

字体大小: 字体大小的选择也需要根据个人喜好和屏幕分辨率进行调整。通常 12-14pt 的字号比较适合长时间阅读代码。

设置默认字体: 将 :set guifont=<字体名称>:<字体大小> 命令添加到 .vimrc 文件中,可以设置 GUI Vim 启动时默认使用的字体。

3. 美化界面的其他技巧

除了配色方案和字体,还可以通过其他方式美化 Vim 界面:

透明效果: 一些 GUI Vim 版本支持窗口透明效果,可以使 Vim 窗口背景透明,与桌面背景融合。可以通过设置 guifontbg 选项来实现透明效果,具体方法因 Vim 版本和操作系统而异。

状态栏 (Statusline) 定制: Vim 的状态栏显示当前文件的信息、光标位置、文件类型等。可以使用 :set statusline 选项定制状态栏的内容和样式,或者使用第三方插件 (例如 vim-airline, powerline) 来美化状态栏。

标签栏 (Tabline) 定制: Vim 的标签栏显示当前打开的标签页。可以使用 :set tabline 选项定制标签栏的内容和样式,或者使用第三方插件 (例如 vim-airline, powerline) 来美化标签栏。

行号栏 (Sign Column) 定制: 行号栏位于行号的左侧,用于显示 Git Gutter, Syntastic 等插件的标记。可以通过设置 signcolumn 选项来控制行号栏的行为。

光标样式 (Cursor Shape) 定制: 可以使用 :set guicursor 选项定制不同模式下的光标样式,例如在 Normal 模式下使用块状光标,在 Insert 模式下使用竖线光标。

总结

通过选择合适的配色方案和字体,并结合其他界面美化技巧,你可以打造一个赏心悦目的 Vim 编辑器,提升你的编码乐趣和效率。美化界面是一个个性化的过程,你可以不断尝试和调整,找到最符合你审美的 Vim 外观。

8.4 键盘映射:自定义快捷键 :map, :noremap

键盘映射 (key mapping) 是 Vim 最强大的功能之一。通过键盘映射,你可以将一个键或组合键绑定到 Vim 命令或操作序列,从而自定义快捷键,提高操作效率。Vim 提供了多种 map 命令,用于在不同模式下创建键盘映射。

1. map 系列命令

Vim 提供了多种 map 命令,用于在不同模式下创建键盘映射:

:map {lhs} {rhs}: 通用映射,在 Normal 模式、Visual 模式、Operator-pending 模式下都有效。
:noremap {lhs} {rhs}: 非递归映射,与 :map 类似,但不允许映射链的递归展开。推荐使用 :noremap,避免意外的递归映射导致的问题。
:nmap {lhs} {rhs}: Normal 模式映射,只在 Normal 模式下有效。
:nnoremap {lhs} {rhs}: Normal 模式非递归映射。
:vmap {lhs} {rhs}: Visual 模式映射,只在 Visual 模式和 Select 模式下有效。
:vnoremap {lhs} {rhs}: Visual 模式非递归映射。
:imap {lhs} {rhs}: Insert 模式映射,只在 Insert 模式下有效。
:inoremap {lhs} {rhs}: Insert 模式非递归映射。
:cmap {lhs} {rhs}: Command-line 模式映射,只在 Command-line 模式下有效。
:cnoremap {lhs} {rhs}: Command-line 模式非递归映射。
:omap {lhs} {rhs}: Operator-pending 模式映射,只在 Operator-pending 模式下有效。
:onoremap {lhs} {rhs}: Operator-pending 模式非递归映射。
:lmap {lhs} {rhs}: Language-mode 映射,用于输入法相关的映射。
:lnoremap {lhs} {rhs}: Language-mode 非递归映射。

{lhs} (Left-hand side): 表示被映射的键或组合键,即快捷键。
{rhs} (Right-hand side): 表示映射的目标,即要执行的 Vim 命令或操作序列。

2. 键的表示方法

map 命令中,可以使用特殊的符号来表示各种键:

普通字符: 例如 a, b, c, 1, 2, 3 等,直接使用字符本身表示。
控制键: 使用 <C-键> 表示 Ctrl 键组合,例如 <C-a> 表示 Ctrl+a, <C-S-a> 表示 Ctrl+Shift+a。
Shift 键: 使用 <S-键> 表示 Shift 键组合,例如 <S-a> 表示 Shift+a (大写字母 A)。
Alt 键 (Meta 键): 使用 <A-键><M-键> 表示 Alt 键组合,例如 <A-a> 表示 Alt+a。
功能键: 使用 <F1>, <F2>, ..., <F12> 表示功能键 F1, F2, ..., F12。
特殊键:
<CR>: 回车键 (Enter)。
<Esc>: Esc 键。
<Tab>: Tab 键。
<Space>: 空格键。
<BS>: 退格键 (Backspace)。
<Del>: Delete 键。
<Insert>: Insert 键。
<Home>: Home 键。
<End>: End 键。
<PageUp>: Page Up 键。
<PageDown>: Page Down 键。
<Up>, <Down>, <Left>, <Right>: 方向键。
<Leader>: Leader 键,默认是反斜杠 \,可以自定义。

3. Leader 键

Leader 键是一个特殊的键,通常用于作为自定义快捷键的前缀。默认的 Leader 键是反斜杠 \,但通常建议将其修改为逗号 , 或空格 <Space>,因为反斜杠不太方便按到。

设置 Leader 键:

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 let mapleader = "," " 将 Leader 键设置为逗号
2 let mapleader = "<Space>" " 将 Leader 键设置为空格

使用 Leader 键的映射示例:

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 nnoremap <leader>w :w<CR> " 将 <leader>w (例如 ,w 或 <Space>w) 映射为保存文件
2 nnoremap <leader>q :q<CR> " 将 <leader>q 映射为退出 Vim

4. 常用映射示例

快速保存文件:

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 nnoremap <F5> :w<CR> " 将 F5 键映射为保存文件

快速退出 Vim:

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 nnoremap <F8> :q<CR> " 将 F8 键映射为退出 Vim
2 nnoremap <leader>qq :qa!<CR> " 将 <leader>qq 映射为强制退出所有窗口

窗口操作:

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 nnoremap <C-w>h <C-w>h " 切换到左侧窗口
2 nnoremap <C-w>j <C-w>j " 切换到下方窗口
3 nnoremap <C-w>k <C-w>k " 切换到上方窗口
4 nnoremap <C-w>l <C-w>l " 切换到右侧窗口
5 nnoremap <leader>sv :vsplit<CR> " 垂直分割窗口
6 nnoremap <leader>sh :split<CR> " 水平分割窗口
7 nnoremap <leader>se :tabnew<CR> " 新建标签页

编辑操作:

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 inoremap jk <Esc> " 在 Insert 模式下,使用 jk 快速退出到 Normal 模式
2 nnoremap <leader>y "+y " 复制到系统剪贴板
3 nnoremap <leader>p "+p " 从系统剪贴板粘贴
4 vnoremap <leader>y "+y " Visual 模式下复制到系统剪贴板
5 vnoremap <leader>p "+p " Visual 模式下从系统剪贴板粘贴
6 nnoremap <leader>x "_d " 剪切但不复制到剪贴板 (删除到黑洞寄存器)

插件命令映射: 很多插件会提供自定义命令,你可以将其映射到快捷键,方便使用。例如,如果你使用了 NERDTree 插件 (文件管理器),可以将其映射到 <F3> 键:

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 nnoremap <F3> :NERDTreeToggle<CR>

5. 查看和取消映射

查看映射: 使用 :map 命令,不加任何参数,可以列出所有已定义的映射。可以使用 :map {lhs} 查看特定键的映射。例如 :map <F5>
取消映射:
:unmap {lhs}: 取消通用映射。
:unmap! {lhs}: 取消 Insert 模式和 Command-line 模式映射。
:nunmap {lhs}: 取消 Normal 模式映射。
:vunmap {lhs}: 取消 Visual 模式映射。
:iunmap {lhs}: 取消 Insert 模式映射。
:cunmap {lhs}: 取消 Command-line 模式映射。
:ounmap {lhs}: 取消 Operator-pending 模式映射。

6. 映射的最佳实践

使用 :noremap: 优先使用 :noremap 系列命令,避免递归映射带来的问题。
选择合适的模式: 根据映射的目的,选择合适的模式映射命令 (例如 :nmap, :imap, :vmap),避免在不必要的模式下触发映射。
使用 Leader 键: 将自定义映射放在 Leader 键下,避免与 Vim 默认快捷键冲突,并方便管理和记忆。
保持一致性: 在定义映射时,尽量保持风格一致,例如使用统一的前缀或后缀,方便记忆和维护。
注释说明: 在 .vimrc 文件中,为每个映射添加注释,说明其作用,方便日后维护和修改。

总结

键盘映射是 Vim 个性化配置的核心,通过自定义快捷键,你可以极大地提高 Vim 的操作效率,使其更符合你的使用习惯。合理地使用 map 命令,结合 Leader 键和各种键的表示方法,你可以打造一套高效、个性化的 Vim 快捷键系统,让你的 Vim 体验更上一层楼。

8.5 自动命令:根据事件触发命令 :autocmd

自动命令 (autocommand) 是 Vim 的高级特性,它允许你在特定事件发生时自动执行预定义的命令。通过自动命令,你可以实现很多自动化操作,例如根据文件类型设置不同的选项、在保存文件时自动格式化代码、在打开新文件时设置默认模板等。

1. :autocmd 命令语法

:autocmd 命令的基本语法如下:

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 :autocmd [事件] [模式] [命令]

[事件] (Event): 指定触发自动命令的事件类型。Vim 提供了丰富的事件类型,例如文件操作事件、缓冲区事件、窗口事件、Vim 启动和退出事件等。
[模式] (Pattern): 指定自动命令生效的文件名模式。可以使用通配符 *, ?, [] 等匹配文件名。留空表示对所有文件生效。
[命令] (Command): 指定在事件发生时要执行的 Vim 命令。可以是一个或多个 Vim 命令,多个命令之间用 | 分隔。

2. 常用事件类型 (Events)

Vim 提供了大量的事件类型,以下是一些常用的事件类型:

文件操作事件:
BufNewFile: 创建新缓冲区,在新文件被创建但还未读取内容时触发。
BufReadPre: 读取文件内容之前触发。
BufReadPost: 读取文件内容之后触发。
BufWritePre: 写入文件内容之前触发 (保存文件之前)。
BufWritePost: 写入文件内容之后触发 (保存文件之后)。
BufDelete: 缓冲区被删除时触发。
FileChangedShell: 文件在 Vim 外部被修改时触发。

缓冲区事件:
BufEnter: 进入缓冲区时触发 (例如切换到某个缓冲区)。
BufLeave: 离开缓冲区时触发 (例如切换到其他缓冲区)。
BufWinEnter: 缓冲区关联到窗口时触发。
BufWinLeave: 缓冲区从窗口解除关联时触发。

窗口事件:
WinEnter: 进入窗口时触发 (例如切换到某个窗口)。
WinLeave: 离开窗口时触发 (例如切换到其他窗口)。
WinNew: 创建新窗口时触发。
WinClosed: 窗口关闭时触发。

Vim 启动和退出事件:
VimEnter: Vim 启动完成时触发。
VimLeavePre: Vim 即将退出时触发。
VimLeave: Vim 退出时触发。

其他事件:
FileType: 检测到文件类型时触发。
Syntax: 语法高亮被加载时触发。
CursorHold: 光标在当前位置停留一段时间后触发 (用于自动保存等)。
TextChanged: 文本内容发生改变时触发。

3. 文件名模式 (Pattern)

文件名模式用于限制自动命令生效的文件范围。可以使用以下通配符:

*: 匹配任意字符序列 (除了目录分隔符)。
?: 匹配任意单个字符 (除了目录分隔符)。
[]: 匹配方括号内的任意字符,例如 [abc] 匹配 a, b, c 中的任意一个字符,[0-9] 匹配数字 0-9。
\: 转义字符,用于转义通配符本身,例如 \* 匹配字面意义的 * 字符。

文件名模式示例:

*.txt: 匹配所有 .txt 文件。
*.py: 匹配所有 .py 文件。
*.html,*.htm: 匹配所有 .html.htm 文件,多个模式用逗号分隔。
*.log: 匹配所有 .log 文件。
README*: 匹配所有以 README 开头的文件。
?ile: 匹配所有以任意字符开头,后面跟着 ile 的文件,例如 file, mile, piles 等。

4. 常用自动命令示例

根据文件类型设置选项: 根据文件类型设置不同的缩进、语法高亮等选项。

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 autocmd FileType python setlocal tabstop=4 shiftwidth=4 expandtab
2 autocmd FileType javascript,typescript setlocal tabstop=2 shiftwidth=2 expandtab
3 autocmd FileType c,cpp setlocal tabstop=4 shiftwidth=4 noexpandtab
4 autocmd FileType markdown setlocal wrap linebreak textwidth=80

setlocal 命令用于设置缓冲区局部选项,只对当前缓冲区生效。

保存文件时自动去除行尾空格:

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 autocmd BufWritePre * :%s/\s\+$//e

在保存所有文件 (* 模式) 之前 (BufWritePre 事件),执行 :s/\s\+$//e 命令,去除所有行尾的空格。

保存文件时自动格式化代码 (需要安装代码格式化工具,例如 autopep8, prettier 等):

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 " Python 代码自动格式化 (使用 autopep8)
2 autocmd BufWritePre *.py :call Autopep8()
3
4 " JavaScript/TypeScript 代码自动格式化 (使用 prettier)
5 autocmd BufWritePre *.js,*.jsx,*.ts,*.tsx :silent !prettier --write %

!command 用于执行外部命令,% 表示当前文件名。

打开新文件时设置默认模板: 例如,为 Python 文件设置 shebang 和编码声明。

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 autocmd BufNewFile *.py 0r ~/.vim/templates/python_template.py

在创建新的 .py 文件 (*.py 模式) 时 (BufNewFile 事件),在文件开头 (0r) 读取 ~/.vim/templates/python_template.py 文件的内容,作为文件模板。

自动加载语法高亮和启用文件类型检测: 通常在 .vimrc 文件开头添加以下两行,启用语法高亮和文件类型检测。

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 syntax on
2 filetype plugin indent on

但也可以使用自动命令,在 Vim 启动时执行:

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 autocmd VimEnter * syntax on | filetype plugin indent on

5. 自动命令组 (Autocmd Groups)

.vimrc 文件中定义了大量的自动命令时,为了方便管理和维护,可以使用自动命令组 (autocmd groups) 将相关的自动命令组织在一起。

定义自动命令组:

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 augroup myGroup
2 autocmd! " 清除 myGroup 组中已有的自动命令
3 autocmd BufWritePre *.txt :echo "Saving text file..."
4 autocmd BufReadPost *.txt :echo "Text file loaded."
5 augroup END

augroup myGroup 开始定义名为 myGroup 的自动命令组,augroup END 结束定义。autocmd! 用于清除组中已有的自动命令,避免重复定义。

6. 查看和删除自动命令

查看自动命令: 使用 :autocmd 命令,不加任何参数,可以列出所有已定义的自动命令。可以使用 :autocmd [事件] 查看特定事件的自动命令,例如 :autocmd BufWritePre
删除自动命令:
:autocmd!: 清除所有自动命令。
:autocmd! [事件]: 清除特定事件的所有自动命令。
:autocmd! augroup [组名]: 清除特定自动命令组中的所有自动命令。

7. 自动命令的最佳实践

使用自动命令组: 使用自动命令组组织相关的自动命令,方便管理和维护。
使用 autocmd!: 在自动命令组中使用 autocmd! 清除已有的自动命令,避免重复定义。
限制文件模式: 尽可能使用文件模式限制自动命令生效的文件范围,避免不必要的触发。
注意性能: 避免在自动命令中执行耗时的操作,影响 Vim 的性能。
注释说明: 在 .vimrc 文件中,为每个自动命令添加注释,说明其作用,方便日后维护和修改。

总结

自动命令是 Vim 高级配置的重要组成部分,通过自动命令,你可以根据各种事件自动执行 Vim 命令,实现高度自动化的编辑流程。合理地使用自动命令,可以极大地提高你的 Vim 使用效率,让 Vim 更加智能和个性化。掌握自动命令的配置方法,是深入 Vim 世界,成为 Vim 高手的必经之路。

ENDOF_CHAPTER_

9. chapter 9: Vim 插件:扩展无限可能

9.1 插件管理工具:Vundle, Pathogen, vim-plug 等

Vim 的强大之处不仅在于其核心功能,还在于其高度的可扩展性。插件(Plugins)是 Vim 生态系统中不可或缺的一部分,它们能够极大地扩展 Vim 的功能,使其适应各种不同的工作流程和需求。为了更方便地安装、管理和更新这些插件,涌现出了各种各样的插件管理工具(Plugin Manager)。本节将介绍几种流行的 Vim 插件管理工具,帮助读者快速上手插件管理。

Pathogen: Pathogen 是最早一批流行的 Vim 插件管理器之一,它的主要思想是将每个插件都放在单独的目录中,然后通过简单的配置,Pathogen 就能将这些插件添加到 Vim 的运行时路径(runtimepath)中。

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 " .vimrc 配置示例 (Pathogen)
2 execute pathogen#infect()
3 syntax on
4 filetype plugin indent on

使用 Pathogen 安装插件通常需要手动将插件仓库克隆到 ~/.vim/bundle 目录下(或者其他你配置的目录)。

Vundle (Vim bundle): Vundle 是另一个非常流行的插件管理器,它简化了插件的安装、更新和移除过程。Vundle 使用 Bundle 命令在 .vimrc 文件中声明需要安装的插件,然后通过 :BundleInstall 命令自动下载并安装这些插件。

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 " .vimrc 配置示例 (Vundle)
2 set nocompatible " be iMproved, required
3 filetype off " required
4
5 set rtp+=~/.vim/bundle/Vundle.vim
6 call vundle#begin()
7 " alternatively, pass a path where Vundle should install plugins
8 "call vundle#begin('~/some/path/here')
9
10 " 让 Vundle 管理插件版本,必须放在 vundle#begin() 和 vundle#end() 之间
11 Bundle 'VundleVim/Vundle.vim'
12 Bundle 'tpope/vim-fugitive' " Git 插件示例
13 Bundle 'Lokaltog/vim-easymotion' " 快速移动插件示例
14 Bundle 'scrooloose/nerdtree' " 文件树插件示例
15
16 " 所有插件配置结束后,调用 vundle#end()
17 call vundle#end() " required
18 filetype plugin indent on " required to ensure filetype-specific plugins are loaded
19 " To ignore plugin indent changes, instead use:
20 "filetype plugin on
21 "
22 " Brief help
23 " :BundleList - list configured bundles
24 " :BundleInstall - install (or update) bundles
25 " :BundleSearch foo - search for bundles on vim-scripts.org
26 " :BundleClean - remove unused bundles
27 " etc. - see :help vundle

Vundle 的优势在于其声明式的插件管理方式和便捷的命令操作,使得插件管理变得更加直观和高效。

vim-plug: vim-plug 是一个现代、快速且简洁的插件管理器。它支持并行安装、按需加载插件、分支/标签/提交版本管理、插件更新回滚等功能。vim-plug 的配置也非常简单,并且拥有出色的性能。

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 " .vimrc 配置示例 (vim-plug)
2 call plug#begin('~/.vim/plugged')
3 " 插件列表
4 Plug 'junegunn/vim-plug' " vim-plug 自身
5 Plug 'tpope/vim-fugitive'
6 Plug 'airblade/vim-gitgutter'
7 Plug 'neoclide/coc.nvim', {'branch': 'release'} " 代码补全引擎示例 (需要 Node.js)
8 Plug 'vim-airline/vim-airline' " 状态栏美化插件示例
9 Plug 'preservim/nerdtree'
10
11 call plug#end()
12 " 初始化插件系统 (可选,如果插件有初始化代码)
13 filetype plugin indent on
14 syntax on

vim-plug 以其速度和丰富的功能集,成为了许多 Vim 用户的首选插件管理器。

其他插件管理器: 除了上述几种,还有其他的插件管理器,例如 dein.vim, minpac 等,它们各有特点,读者可以根据自己的需求和偏好选择合适的工具。

选择插件管理器的关键在于找到一个适合自己工作流程和习惯的工具。对于初学者来说,Vundle 或 vim-plug 都是不错的选择,它们易于上手且功能强大。而 Pathogen 则更适合喜欢手动管理插件的用户。

9.2 常用插件分类与推荐:代码补全、语法检查、文件管理、主题美化等

Vim 插件生态系统非常繁荣,插件种类繁多,可以满足各种不同的需求。本节将对常用插件进行分类,并推荐一些优秀的插件,帮助读者快速找到适合自己的插件。

代码补全 (Code Completion): 代码补全插件可以极大地提高编码效率,它们能够根据上下文提示代码,减少输入错误。

YouCompleteMe (YCM): YCM 是一个强大而全面的代码补全引擎,支持多种编程语言,提供快速、准确的代码补全、语义分析、代码跳转等功能。YCM 的安装和配置相对复杂,但其强大的功能使其成为许多开发者的首选。
coc.nvim (Conquer of Completion): coc.nvim 是另一个流行的代码补全引擎,它基于 Language Server Protocol (LSP) 协议,支持多种语言,配置相对简单,性能优秀,并且拥有丰富的扩展插件。coc.nvim 需要 Node.js 环境。
nvim-cmp (Completion Menu Plugin for Neovim): nvim-cmp 是专为 Neovim 设计的补全框架,它轻量级、高度可定制,可以与其他 LSP 客户端和补全源集成,提供流畅的补全体验。

语法检查 (Syntax Checking) 与代码 Linting: 语法检查和代码 Linting 插件可以帮助开发者及时发现代码中的语法错误和潜在问题,提高代码质量。

ALE (Asynchronous Lint Engine): ALE 是一个异步 Lint 引擎,支持多种语言的语法检查和 Lint 工具,例如 ESLint, JSHint, Flake8, pylint 等。ALE 能够实时检查代码,并在编辑器中显示错误和警告信息。
Syntastic: Syntastic 是另一个流行的语法检查插件,它支持多种语言,可以集成各种语法检查工具。Syntastic 的配置相对简单,易于上手。

文件管理 (File Management): 文件管理插件可以帮助用户更方便地浏览文件系统、打开文件、创建文件等。

NERDTree: NERDTree 是一个经典的文件树插件,它在 Vim 窗口的侧边栏显示文件树,用户可以通过键盘快捷键或鼠标操作浏览文件和目录。
vim-vinegar: vim-vinegar 是一个简洁的文件管理器,它以 Vim 的方式操作文件系统,例如使用 . 打开当前目录,- 返回上级目录等。vim-vinegar 轻量级且高效,与 Vim 的操作方式高度一致。
ranger.vim: ranger.vim 将 ranger 文件管理器集成到 Vim 中,用户可以在 Vim 中使用 ranger 的强大文件管理功能。ranger 是一个基于终端的文件管理器,以其高效和强大的功能而闻名。

主题美化 (Theme & Beautification): 主题美化插件可以改变 Vim 的外观,使其更符合用户的审美偏好,提高编码的愉悦感。

vim-airline: vim-airline 是一个流行的状态栏美化插件,它在 Vim 窗口的底部显示美观且信息丰富的状态栏,可以显示当前文件类型、Git 分支、编码格式等信息。
lightline.vim: lightline.vim 是另一个状态栏美化插件,它比 vim-airline 更轻量级,性能更好,并且同样可以高度定制。
onedark.vim, gruvbox, ayu-vim 等: 这些是流行的 Vim 配色方案,它们提供了各种不同的颜色主题,用户可以根据自己的喜好选择。可以通过插件管理器安装这些配色方案,并在 .vimrc 文件中设置 colorscheme 选项来启用。

代码片段 (Code Snippets): 代码片段插件可以帮助用户快速插入常用的代码模板,提高编码效率。

UltiSnips: UltiSnips 是一个强大的代码片段引擎,它支持多种触发方式、变量替换、脚本扩展等功能。UltiSnips 需要配合代码片段集合插件一起使用,例如 honza/vim-snippets。
vim-snippets: vim-snippets 是一个流行的代码片段集合,包含了多种编程语言的常用代码片段,可以与 UltiSnips 或其他代码片段插件配合使用。

Git 集成 (Git Integration): Git 集成插件可以将 Git 功能集成到 Vim 中,方便用户在 Vim 中进行版本控制操作。

vim-fugitive: vim-fugitive 是一个强大的 Git 插件,它提供了 Git 命令的 Vim 封装,例如 :Git status, :Git add, :Git commit, :Git diff 等。vim-fugitive 使得在 Vim 中进行 Git 操作变得非常方便。
vim-gitgutter: vim-gitgutter 在 Vim 窗口的左侧显示 Git diff 信息,可以实时显示代码的修改、添加和删除,方便用户查看代码变更。

其他实用插件: 除了上述分类,还有许多其他实用的插件,例如:

vim-easymotion: 快速移动插件,可以通过少量按键快速跳转到屏幕上的任意位置。
surround.vim: 快速修改包围字符的插件,例如将 " 修改为 ',或者将 () 修改为 [] 等。
tabularize.vim: 文本对齐插件,可以将文本按照指定的字符或模式进行对齐。
commentary.vim: 快速注释/取消注释代码的插件,支持多种语言。

选择插件时,建议根据自己的实际需求进行选择,不必追求插件数量,而应注重插件的实用性和质量。可以参考插件的 GitHub 仓库的 star 数、issue 活跃度、更新频率等指标来评估插件的质量。

9.3 插件配置与使用技巧

安装插件后,通常需要进行一些配置才能使其更好地工作。插件的配置方式各有不同,但通常可以通过以下几种方式进行配置:

.vimrc 文件配置: 大部分插件都允许在 .vimrc 文件中进行配置。插件通常会提供一些全局变量或 Vim 命令,用户可以在 .vimrc 文件中设置这些变量或命令来定制插件的行为。例如,配置 NERDTree 插件的快捷键:

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 " .vimrc 配置示例 (NERDTree 快捷键)
2 nnoremap <leader>n :NERDTreeToggle<CR>

上述配置将 <leader>n 映射为 NERDTree 的切换命令 :NERDTreeToggle,用户可以通过按下 <leader>n 快捷键来打开或关闭 NERDTree。 <leader> 默认是反斜杠 \,通常建议将其重新映射为逗号 , 或空格 <Space> 等更方便按下的键。

插件自身的配置文件: 有些插件拥有独立的配置文件,例如 coc.nvim 的配置文件是 coc-settings.json,YCM 的配置文件是 .ycm_extra_conf.py 等。这些配置文件通常采用 JSON 或 Python 等格式,用户需要按照插件的文档说明编辑这些配置文件。

Vim 命令配置: 有些插件提供 Vim 命令来进行配置,例如 :PluginNameSetting option=value。用户可以在 Vim 中直接输入这些命令来配置插件,也可以将这些命令添加到 .vimrc 文件中。

插件使用技巧:

阅读插件文档: 每个插件通常都会提供详细的文档,包括插件的功能介绍、安装方法、配置选项、使用方法等。阅读插件文档是了解和使用插件的最佳途径。可以通过 :help plugin-name 命令在 Vim 中查看插件的帮助文档,或者访问插件的 GitHub 仓库查看 README 文件。
学习常用快捷键: 许多插件都定义了快捷键来执行常用操作。学习并熟练使用这些快捷键可以极大地提高插件的使用效率。可以在插件的文档中找到快捷键列表,或者通过 :help plugin-name-commands:help plugin-name-mappings 命令查看快捷键和命令的帮助信息。
按需加载插件: 对于一些大型插件,可以考虑按需加载,即只在需要使用插件时才加载它,以提高 Vim 的启动速度。一些插件管理器,例如 vim-plug,支持按需加载插件的功能。
定期更新插件: 插件开发者会不断更新插件,修复 bug,增加新功能。定期更新插件可以确保使用最新的功能和修复的 bug。可以使用插件管理器的更新命令,例如 :BundleUpdate (Vundle), :PlugUpdate (vim-plug) 等来更新插件。
关注插件社区: 关注插件的 GitHub 仓库、论坛、邮件列表等社区,可以及时了解插件的最新动态、学习使用技巧、与其他用户交流经验。

9.4 自定义插件:Vimscript 基础入门

Vimscript (Vim script) 是 Vim 的内置脚本语言,它允许用户编写自定义的 Vim 功能,包括自定义命令、函数、插件等。学习 Vimscript 可以帮助用户更深入地定制 Vim,使其完全符合自己的需求。本节将对 Vimscript 进行基础入门介绍,引导读者开始编写自己的 Vim 插件。

Vimscript 基础语法:

变量: Vimscript 支持多种变量类型,包括字符串、数字、列表、字典等。变量使用 let 关键字声明,例如:

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 let name = "Vim"
2 let count = 10
3 let mylist = [1, 2, 3]
4 let mydict = {'key': 'value'}

函数: Vimscript 使用 function 关键字定义函数,使用 endfunction 结束函数定义。函数可以接受参数,并使用 return 语句返回值。

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 function! MyFunction(arg1, arg2)
2 let result = a:arg1 + a:arg2 " 使用 a: 前缀访问函数参数
3 return result
4 endfunction
5
6 " 调用函数
7 let sum = MyFunction(3, 5)
8 echo sum " 输出 8

注意函数名通常以大写字母开头,并使用驼峰命名法。 ! 符号表示如果函数已存在则覆盖。 a: 前缀用于访问函数参数。

命令: Vimscript 可以定义自定义命令,使用 command 关键字定义命令。

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 command! HelloWorld echo "Hello, World!"
2
3 " 调用自定义命令
4 :HelloWorld

command! 定义了一个名为 HelloWorld 的自定义命令,执行该命令会输出 "Hello, World!"。

控制结构: Vimscript 支持常用的控制结构,例如 if-else, for, while 等。

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 " if-else 语句
2 if count > 10
3 echo "Count is greater than 10"
4 else
5 echo "Count is not greater than 10"
6 endif
7
8 " for 循环
9 for item in mylist
10 echo item
11 endfor
12
13 " while 循环
14 let i = 0
15 while i < 5
16 echo i
17 let i = i + 1
18 endwhile

编写简单的 Vimscript 函数与命令:

下面是一个简单的 Vimscript 函数示例,用于在当前行添加注释:

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 function! AddComment()
2 " 获取当前行内容
3 let current_line = getline('.')
4 " 判断文件类型,根据文件类型选择注释符号
5 if &filetype == 'python'
6 let comment_symbol = '#'
7 elseif &filetype == 'javascript'
8 let comment_symbol = '//'
9 else
10 let comment_symbol = '//' " 默认使用 // 注释符号
11 endif
12 " 在行首添加注释符号
13 call setline('.', comment_symbol . ' ' . current_line)
14 endfunction
15
16 " 定义一个命令来调用该函数
17 command! AddCommentLine call AddComment()
18
19 " 可以将命令映射到快捷键,例如 <leader>cc
20 nnoremap <leader>cc :AddCommentLine<CR>

将上述代码添加到 .vimrc 文件中,就可以使用 :AddCommentLine 命令或 <leader>cc 快捷键在当前行添加注释。

开发实用的 Vim 插件:案例分析:

一个简单的插件示例:自动在 Markdown 文件中插入日期和时间戳。

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 " 插件名称:InsertTimestamp.vim
2
3 function! InsertTimestamp()
4 " 获取当前日期和时间
5 let timestamp = strftime("%Y-%m-%d %H:%M:%S")
6 " 插入到当前位置
7 call append('.', "Timestamp: " . timestamp)
8 endfunction
9
10 " 定义一个命令
11 command! InsertTs call InsertTimestamp()
12
13 " 可以映射到快捷键,例如 ts
14 nnoremap ts :InsertTs
15
16 " 添加插件描述信息 (可选)
17 let s:plugin_description = "Insert current timestamp in Markdown files."

将上述代码保存为 ~/.vim/plugin/InsertTimestamp.vim 文件(如果使用 Pathogen)或 ~/.vim/plugged/InsertTimestamp/plugin/InsertTimestamp.vim 文件(如果使用 vim-plug),然后在 Vim 中打开 Markdown 文件,就可以使用 :InsertTs 命令或 <leader>ts 快捷键插入当前日期和时间戳。

这只是 Vimscript 编程的冰山一角。通过学习 Vimscript,可以实现更复杂、更强大的 Vim 功能定制,例如自定义代码片段、自动化工作流程、集成外部工具等。深入学习 Vimscript 可以参考 Vim 的帮助文档 :help vimscript-intro 和相关教程。

ENDOF_CHAPTER_

10. chapter 10: Vimscript 编程:深度定制 Vim

10.1 Vimscript 语法基础:变量、函数、控制结构

Vim之所以强大且灵活,很大程度上归功于其内置的脚本语言 Vimscript(也常被称为 Vim 脚本 或 VimL)。Vimscript 允许用户深度定制 Vim 编辑器,从简单的快捷键映射到复杂的功能扩展,几乎所有你能想到的定制化需求都可以通过 Vimscript 来实现。本节将带你入门 Vimscript 的语法基础,为你后续深入学习和应用打下坚实的基础。

10.1.1 Vimscript 的基本元素

Vimscript 是一种动态类型的脚本语言,其语法风格受到 ex 编辑器Vi 编辑器 的影响,同时也借鉴了一些其他编程语言的特性。理解其基本元素是学习 Vimscript 的第一步。

注释(Comments)

在 Vimscript 中,使用双引号 " 开始单行注释。任何在双引号之后到行尾的内容都会被 Vimscript 解释器忽略。

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 " 这是一个单行注释
2 let message = "Hello, Vimscript!" " 这也是注释,在代码的末尾

变量(Variables)

Vimscript 支持多种类型的变量,包括:

字符串(String): 文本数据,用双引号或单引号括起来。双引号字符串支持转义字符和变量内插,单引号字符串则完全按照字面意义解释。

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 let double_quoted_string = "This is a string with \nnewline and variable: ${variable}"
2 let single_quoted_string = 'This is a literal string, no \nnewline or ${variable} expansion'

数字(Number): 整数或浮点数。Vimscript 会根据上下文自动处理数字类型。

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 let integer_number = 123
2 let float_number = 3.14159

列表(List): 有序的元素集合,元素可以是不同的类型,用方括号 [] 定义。

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 let my_list = [1, "apple", 3.14, [2, 3]]

字典(Dictionary): 键值对的集合,键必须是字符串,值可以是任意类型,用花括号 {} 定义。

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 let my_dict = {'name': 'Vim', 'version': 9.0, 'features': ['powerful', 'extensible']}

函数引用(Funcref): 指向函数的引用,可以将函数赋值给变量,并在之后调用。

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 function! SayHello(name)
2 echo "Hello, " . a:name
3 endfunction
4 let hello_func = function('SayHello')
5 call hello_func('User')

变量在使用前需要先声明,可以使用 let 关键字进行声明和赋值。变量名区分大小写。

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 let myVariable = 10
2 let MyVariable = 20 " myVariable 和 MyVariable 是不同的变量

运算符(Operators)

Vimscript 支持常见的运算符,包括:

算术运算符(Arithmetic Operators): +, -, *, /, % (取模), ^ (幂)

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 let sum = 10 + 5
2 let difference = 20 - 8
3 let product = 6 * 7
4 let quotient = 15 / 4
5 let remainder = 16 % 5
6 let power = 2 ^ 3

比较运算符(Comparison Operators): == (等于), != (不等于), >, <, >=, <=

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 if 10 == 10
2 echo "Equal"
3 endif
4 if "apple" != "banana"
5 echo "Not equal"
6 endif

逻辑运算符(Logical Operators): && (逻辑与), || (逻辑或), ! (逻辑非)

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 if (10 > 5) && ("apple" == "apple")
2 echo "Both conditions are true"
3 endif
4 if (10 < 5) || ("apple" == "banana")
5 echo "At least one condition is true"
6 endif
7 if !(10 < 5)
8 echo "Condition is false, but negated to true"
9 endif

字符串运算符(String Operators): . (字符串连接)

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 let greeting = "Hello, " . "Vimscript!"
2 echo greeting

函数(Functions)

Vimscript 提供了大量的内置函数,用于执行各种操作,例如字符串处理、文件操作、窗口管理等。同时,用户也可以自定义函数来扩展 Vimscript 的功能。

内置函数(Built-in Functions): Vimscript 提供了丰富的内置函数,可以通过 :help functions 命令查看完整的函数列表和详细说明。例如:

▮▮▮▮⚝ strlen(string): 返回字符串的长度。
▮▮▮▮⚝ getline(lnum): 获取指定行的文本。
▮▮▮▮⚝ setline(lnum, text): 设置指定行的文本。
▮▮▮▮⚝ echo message: 在命令行区域显示消息。

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 let message_length = strlen("Hello")
2 echo message_length
3 let current_line = getline('.') " 获取当前行
4 call setline(1, "First line changed") " 修改第一行

用户自定义函数(User-defined Functions): 可以使用 functionendfunction 关键字定义自己的函数。函数名必须以大写字母开头。

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 function! MyFunctionName(arg1, arg2)
2 " 函数体
3 let result = a:arg1 + a:arg2
4 return result
5 endfunction
6
7 let sum_result = MyFunctionName(5, 3)
8 echo sum_result

▮▮▮▮在函数内部,使用 a: 前缀访问函数参数。return 关键字用于返回值。! 符号在 function! 中表示如果函数已存在则强制重新定义。

控制结构(Control Structures)

Vimscript 提供了控制程序流程的结构,包括条件语句和循环语句。

条件语句(Conditional Statements): if, elseif, else, endif 用于条件判断。

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 if condition1
2 " 如果 condition1 为真,则执行这里的代码
3 elseif condition2
4 " 如果 condition1 为假,且 condition2 为真,则执行这里的代码
5 else
6 " 如果 condition1 和 condition2 都为假,则执行这里的代码
7 endif
1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 let number = 10
2 if number > 10
3 echo "Number is greater than 10"
4 elseif number == 10
5 echo "Number is equal to 10"
6 else
7 echo "Number is less than 10"
8 endif

循环语句(Loop Statements): forwhile 用于循环执行代码块。

▮▮▮▮⚝ for 循环: 用于遍历列表或数字范围。

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 for item in my_list
2 echo item
3 endfor
4
5 for i in range(1, 5) " 遍历数字 1 到 5
6 echo i
7 endfor

▮▮▮▮⚝ while 循环: 只要条件为真就一直执行循环体。

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 let count = 0
2 while count < 5
3 echo "Count is: " . count
4 let count = count + 1
5 endwhile

10.1.2 Vimscript 的执行环境

Vimscript 代码可以在多种上下文中执行:

.vimrc 配置文件: Vim 启动时会自动执行 .vimrc 文件中的 Vimscript 代码,用于配置 Vim 的各种选项和行为。
命令行模式: 在 Vim 的命令行模式下(通过 : 进入),可以直接输入和执行 Vimscript 命令。
插件文件: Vim 插件通常由 Vimscript 文件组成,当插件被加载时,其中的 Vimscript 代码会被执行。
函数和命令: 用户自定义的函数和命令也是用 Vimscript 编写的,可以在需要时调用执行。

理解 Vimscript 的基本语法元素和执行环境是编写 Vim 脚本的基础。掌握这些知识后,你就可以开始编写简单的 Vimscript 代码,逐步深入 Vim 的定制化世界。

10.2 Vimscript 常用函数库:字符串、列表、字典操作

Vimscript 提供了丰富的内置函数库,使得处理各种数据类型变得非常方便。本节将重点介绍在 Vimscript 中常用的字符串、列表和字典操作函数,这些函数是编写高效 Vim 脚本的基石。

10.2.1 字符串操作函数

字符串在 Vimscript 中是常用的数据类型,Vimscript 提供了大量的函数来处理字符串,例如获取长度、截取子串、分割合并、查找替换等。

字符串长度

strlen({string}):返回字符串 {string} 的长度(字符数)。

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 let my_string = "Hello, Vimscript!"
2 let length = strlen(my_string)
3 echo length " 输出: 16

子字符串操作

substring({string}, {start} [, {end}]):返回字符串 {string} 从索引 {start} 开始到索引 {end} (不包含) 的子字符串。如果省略 {end},则返回从 {start} 到字符串末尾的子字符串。索引从 0 开始。

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 let my_string = "Hello, Vimscript!"
2 let sub_string1 = substring(my_string, 0, 5) " "Hello"
3 let sub_string2 = substring(my_string, 7) " "Vimscript!"
4 echo sub_string1
5 echo sub_string2

字符串分割与合并

split({string} [, {pattern} [, {keepempty}]]):将字符串 {string} 根据正则表达式 {pattern} 分割成列表。如果省略 {pattern},则默认使用空白字符分割。{keepempty} 参数为 "1" 时,保留空字符串元素。

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 let my_string = "apple,banana,orange"
2 let my_list = split(my_string, ',') " ["apple", "banana", "orange"]
3 echo my_list
4
5 let path_string = "/usr/local/bin:/usr/bin:/bin"
6 let path_list = split(path_string, ':', 1) " ["/usr/local/bin", "/usr/bin", "/bin"],保留空字符串(这里没有空字符串,但如果分隔符连续出现,则会保留空字符串)
7 echo path_list

join({list} [, {sep}]):将列表 {list} 中的元素连接成一个字符串,元素之间用字符串 {sep} 分隔。如果省略 {sep},则默认不使用分隔符。

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 let my_list = ["apple", "banana", "orange"]
2 let my_string = join(my_list, ', ') " "apple, banana, orange"
3 echo my_string
4
5 let words = ["Hello", "Vimscript"]
6 let sentence = join(words) " "HelloVimscript"
7 echo sentence

字符串查找与替换

match({string}, {pattern} [, {start} [, {count}]]):在字符串 {string} 中查找正则表达式 {pattern} 的匹配项,返回第一个匹配项的起始索引。如果没有找到匹配项,则返回 -1。{start} 参数指定查找的起始位置,{count} 参数限制查找的匹配数量。

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 let my_string = "This is a test string."
2 let index = match(my_string, 'test') " 返回 10 ( "test" 的起始索引)
3 echo index
4
5 let index_not_found = match(my_string, 'example') " 返回 -1 (未找到)
6 echo index_not_found

substitute({string}, {pattern}, {replacement}, {flags}):在字符串 {string} 中查找正则表达式 {pattern} 的匹配项,并用 {replacement} 替换。{flags} 参数控制替换行为,例如 'g' 表示全局替换,'i' 表示忽略大小写等。

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 let my_string = "apple banana apple"
2 let new_string = substitute(my_string, 'apple', 'orange', 'g') " "orange banana orange" (全局替换)
3 echo new_string
4
5 let case_string = "Vim is VIM"
6 let lower_string = substitute(case_string, 'VIM', 'vim', 'gi') " "vim is vim" (全局替换,忽略大小写)
7 echo lower_string

10.2.2 列表操作函数

列表是 Vimscript 中用于存储有序数据集合的重要数据类型。Vimscript 提供了丰富的函数来操作列表,包括获取长度、添加删除元素、切片排序等。

列表长度

len({list}):返回列表 {list} 的长度(元素个数)。

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 let my_list = [1, 2, 3, 4, 5]
2 let list_length = len(my_list)
3 echo list_length " 输出: 5

添加元素

add({list}, {item}):将元素 {item} 添加到列表 {list} 的末尾,并返回修改后的列表。

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 let my_list = [1, 2, 3]
2 call add(my_list, 4) " my_list 变为 [1, 2, 3, 4]
3 echo my_list

insert({list}, {item} [, {index}]):将元素 {item} 插入到列表 {list} 的指定索引 {index} 位置。如果省略 {index},则默认插入到列表的开头(索引 0)。

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 let my_list = [1, 2, 3]
2 call insert(my_list, 0, 0) " my_list 变为 [0, 1, 2, 3]
3 echo my_list
4 call insert(my_list, 2, 1.5) " my_list 变为 [0, 1, 1.5, 2, 3]
5 echo my_list

删除元素

remove({list}, {index}):移除列表 {list} 中索引为 {index} 的元素,并返回被移除的元素。

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 let my_list = [1, 2, 3]
2 let removed_item = remove(my_list, 1) " my_list 变为 [1, 3],removed_item 为 2
3 echo my_list
4 echo removed_item

filter({list}, {expression}):根据表达式 {expression} 过滤列表 {list} 中的元素,只保留表达式为真的元素。表达式可以使用 v:val 引用当前元素,v:idx 引用当前索引。

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 let my_list = [1, 2, 3, 4, 5, 6]
2 call filter(my_list, 'v:val % 2 == 0') " my_list 变为 [2, 4, 6] (只保留偶数)
3 echo my_list

列表切片

slice({list}, {start} [, {end}]):返回列表 {list} 从索引 {start} 开始到索引 {end} (不包含) 的子列表。如果省略 {end},则返回从 {start} 到列表末尾的子列表。

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 let my_list = [1, 2, 3, 4, 5]
2 let sub_list1 = slice(my_list, 1, 4) " [2, 3, 4]
3 let sub_list2 = slice(my_list, 2) " [3, 4, 5]
4 echo sub_list1
5 echo sub_list2

列表排序

sort({list} [, {func}]):对列表 {list} 进行排序。如果省略 {func},则默认进行升序排序。如果提供函数 {func},则使用该函数进行自定义排序。

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 let my_list = [3, 1, 4, 1, 5, 9, 2, 6]
2 call sort(my_list) " my_list 变为 [1, 1, 2, 3, 4, 5, 6, 9] (升序排序)
3 echo my_list
4
5 function! ReverseSort(i1, i2)
6 return a:i2 - a:i1 " 降序排序的比较函数
7 endfunction
8 let my_list2 = [3, 1, 4, 1, 5, 9, 2, 6]
9 call sort(my_list2, 'ReverseSort') " my_list2 变为 [9, 6, 5, 4, 3, 2, 1, 1] (降序排序)
10 echo my_list2

列表映射

map({list}, {expression}):对列表 {list} 中的每个元素应用表达式 {expression},并将结果组成新的列表返回。表达式可以使用 v:val 引用当前元素,v:idx 引用当前索引。

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 let my_list = [1, 2, 3, 4]
2 let squared_list = map(my_list, 'v:val * v:val') " [1, 4, 9, 16] (计算每个元素的平方)
3 echo squared_list
4
5 let string_list = ['apple', 'banana', 'orange']
6 let upper_list = map(string_list, 'toupper(v:val)') " ['APPLE', 'BANANA', 'ORANGE'] (将每个字符串转换为大写)
7 echo upper_list

10.2.3 字典操作函数

字典是 Vimscript 中用于存储键值对集合的数据类型。Vimscript 提供了丰富的函数来操作字典,包括获取键、值、判断键是否存在等。

获取键和值

keys({dictionary}):返回字典 {dictionary} 中所有键的列表。

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 let my_dict = {'name': 'Vim', 'version': 9.0, 'editor': v:true}
2 let key_list = keys(my_dict) " ['editor', 'name', 'version'] (键的列表,顺序可能不固定)
3 echo key_list

values({dictionary}):返回字典 {dictionary} 中所有值的列表。

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 let my_dict = {'name': 'Vim', 'version': 9.0, 'editor': v:true}
2 let value_list = values(my_dict) " [v:true, 'Vim', 9.0] (值的列表,顺序与键列表对应)
3 echo value_list

items({dictionary}):返回字典 {dictionary} 中所有键值对的列表,每个元素是一个包含键和值的列表 [key, value]

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 let my_dict = {'name': 'Vim', 'version': 9.0}
2 let item_list = items(my_dict) " [['name', 'Vim'], ['version', 9.0]]
3 echo item_list

判断键是否存在

has_key({dictionary}, {key}):判断字典 {dictionary} 中是否存在键 {key}。存在返回 1,不存在返回 0。

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 let my_dict = {'name': 'Vim', 'version': 9.0}
2 let has_name = has_key(my_dict, 'name') " 返回 1 (存在键 'name')
3 let has_author = has_key(my_dict, 'author') " 返回 0 (不存在键 'author')
4 echo has_name
5 echo has_author

获取值

get({dictionary}, {key} [, {default}]):获取字典 {dictionary} 中键 {key} 对应的值。如果键不存在,则返回 {default}。如果省略 {default} 且键不存在,则返回空字符串。

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 let my_dict = {'name': 'Vim', 'version': 9.0}
2 let name_value = get(my_dict, 'name') " 返回 'Vim'
3 let author_value = get(my_dict, 'author', 'Unknown') " 返回 'Unknown' (键 'author' 不存在,返回默认值)
4 let missing_value = get(my_dict, 'missing_key') " 返回 '' (键 'missing_key' 不存在,返回空字符串)
5 echo name_value
6 echo author_value
7 echo missing_value

更新和添加键值对

⚝ 可以使用 let 命令直接更新或添加字典的键值对。如果键已存在,则更新值;如果键不存在,则添加新的键值对。

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 let my_dict = {'name': 'Vim', 'version': 9.0}
2 let my_dict.version = 9.1 " 更新键 'version' 的值
3 let my_dict.author = 'Bram Moolenaar' " 添加新的键值对 'author': 'Bram Moolenaar'
4 echo my_dict

掌握这些常用的字符串、列表和字典操作函数,可以让你在 Vimscript 编程中更加高效地处理各种数据,实现更复杂的功能。通过灵活运用这些函数,可以编写出强大的 Vim 插件和定制化配置,提升你的 Vim 使用体验。

10.3 编写简单的 Vimscript 函数与命令

Vimscript 的强大之处在于可以自定义函数和命令,从而扩展 Vim 的功能,使其更符合个人使用习惯和工作流程。本节将介绍如何编写简单的 Vimscript 函数和命令,让你能够开始定制自己的 Vim 编辑器。

10.3.1 自定义函数

在 Vimscript 中,可以使用 functionendfunction 关键字来定义函数。函数名必须以大写字母开头。

函数定义

函数的基本语法结构如下:

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 function! FunctionName(argument1, argument2, ...)
2 " 函数体代码
3 " ...
4 return result " 可选的返回值
5 endfunction

function!: 声明函数开始。! 符号表示强制重新定义,如果函数已存在,则会覆盖之前的定义。
FunctionName: 函数名,必须以大写字母开头。
(argument1, argument2, ...): 函数的参数列表,参数名在函数内部通过 a:argument1, a:argument2 等方式访问。
" 函数体代码 ...": 函数的具体执行代码。
return result: 可选的返回值,使用 return 关键字返回结果。
endfunction: 声明函数结束。

函数调用

使用 call 命令调用函数,并将返回值(如果有)赋值给变量。

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 let result_variable = call FunctionName(argument_value1, argument_value2, ...)

如果函数没有返回值,或者你不需要返回值,也可以直接使用 call 命令调用函数。

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 call FunctionName(argument_value1, argument_value2, ...)

示例:简单的加法函数

下面是一个简单的 Vimscript 函数示例,用于计算两个数字的和:

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 function! Add(num1, num2)
2 let sum = a:num1 + a:num2
3 return sum
4 endfunction
5
6 let result = call Add(10, 5)
7 echo result " 输出: 15

在这个例子中,Add 函数接收两个参数 num1num2,计算它们的和,并通过 return 关键字返回结果。然后,使用 call Add(10, 5) 调用函数,并将返回值赋值给 result 变量,最后使用 echo 命令输出结果。

示例:显示当前日期和时间的函数

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 function! ShowDateTime()
2 let current_datetime = strftime("%Y-%m-%d %H:%M:%S") " 获取当前日期时间字符串
3 echo "Current date and time: " . current_datetime
4 endfunction
5
6 call ShowDateTime() " 调用函数显示日期时间

这个函数 ShowDateTime 使用 strftime() 函数获取当前日期和时间,并使用 echo 命令在命令行区域显示。

10.3.2 自定义命令

除了自定义函数,Vimscript 还允许用户自定义命令,这些命令可以在 Vim 的命令行模式下直接调用,就像内置命令一样。

命令定义

使用 command 关键字定义命令。基本语法结构如下:

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 command! -nargs={count} -range={range} CommandName :

command!: 声明自定义命令开始。! 符号表示强制重新定义,如果命令已存在,则会覆盖之前的定义。
-nargs={count}: 指定命令可以接受的参数数量。
▮▮▮▮⚝ 0: 不接受参数。
▮▮▮▮⚝ 1: 接受一个参数。
▮▮▮▮⚝ +: 接受一个或多个参数。
▮▮▮▮⚝ *: 接受零个或多个参数。
▮▮▮▮⚝ ?: 接受零个或一个参数。
-range={range}: 指定命令是否接受行范围。
▮▮▮▮⚝ %: 整个文件范围。
▮▮▮▮⚝ .: 当前行范围。
▮▮▮▮⚝ line: 接受行号范围。
▮▮▮▮⚝ (不指定):不接受行范围。
CommandName: 自定义命令的名称,必须以大写字母开头。
:<Vimscript 命令>: 命令执行的 Vimscript 代码。可以使用 | 分隔多个命令。

命令调用

在 Vim 的命令行模式下(输入 : 进入),直接输入自定义命令的名称并加上参数(如果需要)即可调用。

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 :CommandName argument1 argument2 ...

示例:简单的问候命令

下面是一个简单的自定义命令示例,用于显示问候消息:

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 command! -nargs=1 Hello :echo "Hello, !"

这个命令 Hello 使用 -nargs=1 指定接受一个参数,参数通过 <args> 引用。当在命令行输入 :Hello User 时,会执行 echo "Hello, User!",在命令行区域显示 "Hello, User!"。

示例:在当前行插入日期命令

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 command! InsertDate :call InsertCurrentDate()
2
3 function! InsertCurrentDate()
4 let current_date = strftime("%Y-%m-%d")
5 call append('.', current_date) " 在当前行之后插入日期
6 endfunction

这个例子定义了一个命令 InsertDate,当在命令行输入 :InsertDate 时,会调用 InsertCurrentDate 函数。InsertCurrentDate 函数获取当前日期,并使用 append('.') 在当前行之后插入日期。

示例:切换行号显示命令

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 command! ToggleLineNumber :call ToggleLineNumberFunc()
2
3 function! ToggleLineNumberFunc()
4 if (&number == 1)
5 set nonumber
6 echo "Line numbers disabled"
7 else
8 set number
9 echo "Line numbers enabled"
10 endif
11 endfunction

这个例子定义了一个命令 ToggleLineNumber,用于切换行号的显示状态。ToggleLineNumberFunc 函数检查当前是否显示行号 (&number == 1),如果是则关闭行号 (set nonumber),否则打开行号 (set number),并使用 echo 命令显示当前状态。

通过自定义函数和命令,你可以将常用的操作封装起来,简化操作步骤,提高工作效率。例如,你可以自定义命令来快速插入代码片段、格式化代码、执行外部脚本等。掌握自定义函数和命令的技巧,是 Vimscript 编程进阶的关键一步。

10.4 开发实用的 Vim 插件:案例分析

Vim 插件是扩展 Vim 功能的强大方式。通过编写 Vim 插件,你可以添加新的功能、改进现有功能、定制编辑器的行为,使其更符合你的需求。本节将通过一个案例分析,演示如何开发一个简单的但实用的 Vim 插件,帮助你入门 Vim 插件开发。

10.4.1 插件需求:自动添加文件头注释

假设我们需要开发一个 Vim 插件,实现以下功能:

功能描述: 当创建新的代码文件时,自动在文件头部添加预定义的文件头注释,包括文件名、作者、创建日期等信息。
适用场景: 适用于各种编程项目,帮助开发者规范代码文件,提高代码可维护性。
可配置性: 允许用户自定义作者名和注释模板。

10.4.2 插件文件结构

Vim 插件通常放在以下目录中:

~/.vim/plugin/: 全局插件,对所有用户生效。
~/.vim/ftplugin/: 文件类型插件,只对特定文件类型生效。
~/.vim/autoload/: 自动加载插件,提高 Vim 启动速度。
~/.vim/doc/: 插件文档。

对于这个简单的文件头注释插件,我们可以在 ~/.vim/plugin/ 目录下创建一个 Vimscript 文件,例如 auto_header.vim

10.4.3 插件代码实现

auto_header.vim 文件中,编写 Vimscript 代码实现插件功能。

定义插件变量和配置

首先,定义一些插件变量,用于存储作者名和注释模板,并允许用户自定义配置。

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 " 插件变量
2 let g:auto_header_author = get(g:, 'auto_header_author', 'Your Name') " 默认作者名
3 let g:auto_header_template = get(g:, 'auto_header_template', [
4 \'/**',
5 \' * @file %filename%',
6 \' * @author %author%',
7 \' * @date %date%',
8 \' * @brief File header comment generated by auto_header.vim',
9 \' */'
10 \]) " 默认注释模板

g:auto_header_author: 存储作者名,默认值为 'Your Name'。用户可以在 .vimrc 文件中设置 let g:auto_header_author = 'Your Custom Name' 来自定义作者名。
g:auto_header_template: 存储注释模板,是一个字符串列表,每一行代表注释的一行。模板中使用 %filename%, %author%, %date% 等占位符,将在运行时被替换。

定义添加文件头注释的函数

编写一个函数 s:InsertHeader(),用于生成并插入文件头注释。

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 function! s:InsertHeader()
2 " 获取文件名、作者、日期
3 let filename = expand('%:t') " 获取文件名 (不包含路径)
4 let author = g:auto_header_author
5 let date = strftime("%Y-%m-%d")
6
7 " 替换模板中的占位符
8 let header_lines = deepcopy(g:auto_header_template) " 复制模板,避免修改全局变量
9 call map(header_lines, {index, line -> substitute(line, '%filename%', filename, 'g')})
10 call map(header_lines, {index, line -> substitute(line, '%author%', author, 'g')})
11 call map(header_lines, {index, line -> substitute(line, '%date%', date, 'g')})
12
13 " 插入文件头注释
14 call insert(header_lines, '') " 在文件开头插入注释行
15 endfunction

s:InsertHeader(): 函数名以 s: 开头,表示是脚本局部函数,只在当前脚本文件中可见。
expand('%:t'): 获取当前文件名(不包含路径)。
g:auto_header_author: 获取全局作者名配置。
strftime("%Y-%m-%d"): 获取当前日期。
deepcopy(g:auto_header_template): 深拷贝注释模板,避免直接修改全局变量。
map() 函数和 substitute() 函数: 遍历模板行,替换占位符 %filename%, %author%, %date% 为实际值。
insert(header_lines, ''): 在文件开头插入注释行列表。

设置自动命令

使用 autocmd 命令,在创建新文件时自动调用 s:InsertHeader() 函数。

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 " 自动命令:创建新文件时自动添加文件头注释
2 autocmd BufNewFile * call s:InsertHeader()

autocmd BufNewFile *: 定义一个自动命令,在 BufNewFile 事件(创建新文件)发生时触发,* 表示对所有文件类型生效。
call s:InsertHeader(): 触发时调用的函数。

10.4.4 插件使用和测试

  1. 保存插件文件: 将以上代码保存到 ~/.vim/plugin/auto_header.vim 文件中。
  2. 创建新文件: 在 Vim 中使用 :new test.c:e new_file.py 等命令创建新的代码文件。
  3. 查看效果: 新创建的文件会自动在头部添加预定义的文件头注释,包含文件名、作者、创建日期等信息。
  4. 自定义配置: 在 .vimrc 文件中添加配置,例如:
1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 let g:auto_header_author = 'John Doe'
2 let g:auto_header_template = [
3 \'/*----------------------------------------------------------------',
4 \' * File: %filename%',
5 \' * Author: %author%',
6 \' * Date: %date%',
7 \' * Purpose: This file is generated by auto_header.vim plugin.',
8 \' *----------------------------------------------------------------*/'
9 \]

▮▮▮▮重新启动 Vim 或执行 :source ~/.vimrc 使配置生效。

10.4.5 插件改进方向

这个简单的文件头注释插件只是一个入门示例。可以进一步改进和扩展功能,例如:

文件类型判断: 根据文件类型(例如 C/C++, Python, JavaScript)使用不同的注释风格和模板。可以使用 expand('%:e') 获取文件扩展名,并根据扩展名选择不同的模板。
自定义模板: 允许用户为不同的文件类型自定义不同的注释模板。可以使用字典来存储不同文件类型的模板,并根据文件类型选择模板。
更丰富的占位符: 添加更多占位符,例如项目名、版本号、版权信息等。
交互式配置: 提供交互式命令,允许用户在创建文件时动态输入作者名、项目名等信息。

通过这个案例分析,你了解了 Vim 插件开发的基本流程和方法。从定义插件需求、设计文件结构、编写插件代码,到测试和改进插件,每一步都是 Vim 插件开发的重要组成部分。掌握 Vim 插件开发技能,可以让你深度定制 Vim 编辑器,打造更高效、更个性化的开发环境。

ENDOF_CHAPTER_

11. chapter 11: 高级技巧与最佳实践

11.1 利用 Vim 进行代码重构(Code Refactoring with Vim)

代码重构(Code Refactoring)是在不改变软件外部行为的前提下,改善代码内部结构的过程。Vim 提供了强大的文本编辑能力,结合一些技巧和插件,可以高效地进行代码重构。虽然 Vim 本身不像 IDE 那样提供自动化的重构工具,但通过灵活的命令组合和脚本扩展,我们可以实现许多常见的重构操作。

重命名变量与函数(Renaming Variables and Functions)

重命名是代码重构中最常见的操作之一。在 Vim 中,我们可以利用强大的搜索和替换功能 :s 以及正则表达式来实现精确的重命名。

基本替换命令: 使用 :s/oldName/newName/g 可以将当前文件中所有 oldName 替换为 newName。但这种方法可能会误伤,例如替换了注释或字符串中的 oldName

精确替换: 为了更精确地重命名,可以使用更严格的正则表达式,并结合 Vim 的单词边界 \<\>。例如,要重命名一个名为 variableName 的变量,可以使用 :s/\<variableName\>/newName/g\< 匹配单词开头,\> 匹配单词结尾,确保只替换完整的单词。

Visual 模式与替换: 在 Visual 模式下选中要重命名的变量,然后使用 :'<,'>s/oldName/newName/g 可以只在选定区域内进行替换,这在局部重命名时非常有用。

配合 * 命令: 将光标移动到要重命名的变量上,按下 * 命令可以快速搜索当前单词。然后可以使用 :%s/\<C-r>w\>/newName/g 进行替换。 <C-r>w 在替换命令中会粘贴当前光标下的单词,避免手动输入错误。

提取函数(Extract Function)

将一段代码块提取成一个独立的函数,可以提高代码的模块化和可读性。Vim 可以通过 Visual 模式、宏(Macro)和 :function 命令来辅助完成这个过程。

Visual 模式与宏:
▮▮▮▮1. 使用 Visual 模式选中要提取的代码块。
▮▮▮▮2. 使用 y 命令复制选中的代码块。
▮▮▮▮3. 在合适的位置(例如,文件顶部或底部)使用 oO 命令插入新行,并进入 Insert 模式。
▮▮▮▮4. 使用 p 命令粘贴复制的代码块。
▮▮▮▮5. 手动添加函数定义、参数和返回值等。
▮▮▮▮6. 返回到代码块原来的位置,将原来的代码块替换为对新函数的调用。

▮▮▮▮为了更高效地完成这个过程,可以使用宏来自动化一些步骤。例如,录制一个宏,包含复制选定代码块、跳转到函数定义位置、粘贴代码、添加函数框架、返回调用位置等操作。

:function 命令与脚本: 对于更复杂的提取函数操作,可以编写 Vimscript 函数来自动化。例如,可以编写一个函数,接受函数名、参数列表等信息,自动生成函数定义,并将选定的代码块移动到函数体内,然后在原位置生成函数调用。

内联函数(Inline Function)

内联函数是将函数调用处替换为函数体本身。在 Vim 中,可以通过搜索函数调用,然后手动或使用宏将函数体复制粘贴到调用处,并替换参数。

搜索与替换: 使用 /functionName( 搜索函数调用处。然后使用 yi( 复制函数参数。跳转到函数定义处,使用 yy 复制函数体(不包括函数定义行)。返回函数调用处,使用 ci( 删除函数调用和参数,然后使用 p 粘贴函数体。最后,手动替换函数体中的形参为实参。

宏自动化: 可以录制宏来自动化内联函数的过程,但由于函数体和参数的复杂性,宏可能更适用于简单的内联操作。

移动语句块(Move Statement Block)

移动语句块,例如将一段代码移动到循环外部或条件判断的不同分支,可以使用 Visual 模式和移动命令。

Visual 模式与移动命令:
▮▮▮▮1. 使用 Visual 模式选中要移动的代码块。
▮▮▮▮2. 使用 d 命令剪切选中的代码块。
▮▮▮▮3. 将光标移动到目标位置。
▮▮▮▮4. 使用 pP 命令粘贴代码块。

▮▮▮▮结合文本对象(Text Object)可以更快速地选中代码块。例如,vib 可以选中花括号 {} 包围的代码块,vap 可以选中段落。

代码格式化与对齐(Code Formatting and Alignment)

保持代码格式一致性是重构的重要部分。Vim 提供了强大的代码格式化和对齐功能。

= 命令: 在 Normal 模式下,= 命令可以自动缩进代码。可以使用 gg=G 对整个文件进行格式化,或者在 Visual 模式下选中代码块后使用 = 对选定区域进行格式化。

:indent 命令: :indent 命令可以调整代码的缩进级别。例如,:> > 可以将当前行向右缩进两级,:< < 可以向左缩进两级。在 Visual 模式下,可以使用 >< 对选定区域进行缩进调整。

:retab 命令: :retab 命令可以将文件中的 Tab 字符转换为空格,或将空格转换为 Tab 字符,保持缩进风格一致。

插件: 可以使用代码格式化插件,例如 alevim-prettierNeoformat 等,实现更强大的代码格式化功能,支持多种编程语言和格式化风格。

使用插件辅助重构(Refactoring Plugins)

虽然 Vim 本身不提供内置的重构工具,但有一些插件可以增强 Vim 的重构能力。

vim-refactor: vim-refactor 插件提供了一些基本的重构操作,例如重命名变量、提取函数等,可以通过快捷键或命令调用。

语言服务器协议(Language Server Protocol, LSP)客户端插件: 例如 coc.nvimvim-lspnvim-lspconfig 等,可以集成 LSP 服务器,为多种编程语言提供代码补全、语法检查、跳转到定义、查找引用、重构等功能。LSP 客户端插件通常需要配合相应的语言服务器一起使用。例如,对于 Python,可以使用 pylsppyright 语言服务器。

通过结合 Vim 的基本操作、宏、脚本和插件,我们可以构建一套高效的代码重构工作流,提升代码质量和开发效率。

11.2 使用 Vim 进行版本控制集成 (Git 等)(Version Control Integration with Vim (Git etc.))

版本控制(Version Control)是软件开发中不可或缺的一部分。Vim 可以很好地与版本控制系统集成,特别是与 Git 的集成非常成熟。通过插件和配置,可以在 Vim 中方便地进行版本控制操作,提高开发效率。

命令行 Git 集成(Command-line Git Integration)

Vim 本身就是一个强大的文本编辑器,可以很好地与命令行工具配合使用。最基本的方式是在 Vim 中直接调用 Git 命令。

:! 命令: 使用 :! 命令可以在 Vim 中执行外部命令。例如,:!git status 可以查看 Git 状态,:!git add . 可以添加所有修改到暂存区,:!git commit -m "commit message" 可以提交更改。

:shell 命令: 使用 :shell 命令可以打开一个终端 Shell,在 Shell 中可以执行 Git 命令。输入 exitCtrl+d 可以返回 Vim。

快捷键映射: 可以将常用的 Git 命令映射到快捷键,提高操作效率。例如,在 .vimrc 文件中添加以下配置:

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 nnoremap <leader>gs :!git status<CR>
2 nnoremap <leader>ga :!git add .<CR>
3 nnoremap <leader>gc :!git commit -m "<++>"<Left><Left><Left>
4 nnoremap <leader>gp :!git push<CR>
5 nnoremap <leader>gl :!git log --oneline --graph --decorate --all<CR>

▮▮▮▮上述配置将 <leader>gs 映射到 git status<leader>ga 映射到 git add .<leader>gc 映射到 git commit 并预留提交信息位置,<leader>gp 映射到 git push<leader>gl 映射到 git log<leader> 默认是反斜杠 \,可以自定义。

Git 插件(Git Plugins)

为了更方便地在 Vim 中进行 Git 操作,可以使用专门的 Git 插件。这些插件通常提供更友好的界面和更丰富的功能。

vim-fugitive: vim-fugitive 是最流行的 Vim Git 插件之一,提供了强大的 Git 集成功能。

▮▮▮▮⚝ :Git 命令: vim-fugitive 提供了 :Git 命令,可以在 Vim 中执行几乎所有的 Git 命令。例如,:Git status:Git add:Git commit:Git push 等。
▮▮▮▮⚝ :Gdiff 命令: :Gdiff 命令可以打开一个垂直分割窗口,显示当前文件与暂存区或上次提交版本的差异。可以使用 Vim 的 diff 功能查看和修改差异。
▮▮▮▮⚝ :Gblame 命令: :Gblame 命令可以显示每一行代码的最后修改作者和提交信息,方便代码追溯。
▮▮▮▮⚝ :Gcommit 命令: :Gcommit 命令可以打开一个窗口用于编写提交信息。
▮▮▮▮⚝ :Gpush:Gpull:Gfetch 等命令: 提供了常用的远程仓库操作命令。
▮▮▮▮⚝ 快捷键映射: vim-fugitive 也提供了一些默认的快捷键映射,例如 ]c[c 用于在差异块之间跳转,<leader>gg 打开 :Git 命令窗口等。

vim-gitgutter: vim-gitgutter 插件在 Vim 的行号栏显示 Git 差异标记,实时显示文件的修改、添加和删除行,非常直观。

▮▮▮▮⚝ 差异标记: 在行号栏左侧显示 + (添加)、- (删除)、~ (修改) 等标记,指示代码行的 Git 状态。
▮▮▮▮⚝ :GitGutterFold 命令: 可以折叠未修改的代码块,只显示修改过的代码,方便代码审查。
▮▮▮▮⚝ :GitGutterLineHighlightsToggle 命令: 可以切换是否高亮显示修改过的代码行。
▮▮▮▮⚝ 快捷键映射: vim-gitgutter 也提供了一些快捷键映射,例如 ]c[c 用于在差异块之间跳转。

diffview.nvim: diffview.nvim 是一个 Neovim 插件,提供更强大的 Git diff 查看功能,支持 split 窗口和 tab 页面显示 diff,以及 staged/unstaged changes 的区分。

其他 Git 插件: 还有一些其他的 Vim Git 插件,例如 nerdgitgitv 等,可以根据个人喜好选择使用。

Git 工作流集成(Git Workflow Integration)

结合 Git 插件和 Vim 的其他功能,可以构建高效的 Git 工作流。

代码审查(Code Review): 使用 :Gdiffdiffview.nvim 查看代码差异,使用 :Gblame 追溯代码修改历史,结合代码跳转和搜索功能,可以方便地进行代码审查。

分支管理(Branch Management): 使用 :Git branch 查看分支列表,:Git checkout branchName 切换分支,:Git merge branchName 合并分支,:Git rebase branchName rebase 分支。可以使用插件或自定义脚本来简化分支管理操作。

解决冲突(Conflict Resolution): 当 Git 冲突发生时,Vim 的 diff 功能可以帮助查看和解决冲突。可以使用 :diffsplit 命令手动比较和合并文件,也可以使用一些插件来辅助冲突解决。

通过合理选择和配置 Git 插件,并结合 Vim 的强大编辑能力,可以构建一套高效、便捷的 Git 版本控制工作流,提升开发效率和代码质量。

11.3 远程编辑与协作::netrw, TRAMP(Remote Editing and Collaboration: :netrw, TRAMP)

远程编辑(Remote Editing)是指在本地 Vim 编辑器中编辑远程服务器上的文件。Vim 提供了多种远程编辑方式,方便开发者在本地编辑远程代码,进行服务器配置管理等操作。

:netrw: :netrw 是 Vim 内置的文件管理器插件,也支持简单的远程文件编辑功能。

SCP 协议: :netrw 支持使用 SCP(Secure Copy Protocol)协议连接远程服务器。可以使用以下命令打开远程目录:

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 :e scp://user@host:/path/to/directory

▮▮▮▮或打开远程文件:

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 :e scp://user@host:/path/to/file

▮▮▮▮输入命令后,Vim 会提示输入远程服务器的密码。连接成功后,:netrw 会显示远程目录的文件列表,可以像浏览本地文件一样浏览和编辑远程文件。

局限性: :netrw 的远程编辑功能相对简单,性能可能不如专门的远程编辑工具,且不支持复杂的远程操作,例如端口转发、密钥认证等。

TRAMP(Transparent Remote Access, Multiple Protocols): TRAMP 是 Emacs 的一个扩展,也被移植到了 Vim 上。TRAMP 提供了更强大、更灵活的远程文件编辑功能,支持多种协议和认证方式。

多种协议支持: TRAMP 支持多种远程协议,包括 SSH、SCP、FTP、SFTP、plink、telnet 等。最常用的是 SSH 协议。

SSH 协议: 使用 TRAMP 通过 SSH 协议连接远程服务器的语法如下:

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 :e /ssh:user@host:/path/to/file

▮▮▮▮或

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 :e /ssh://user@host:/path/to/file

▮▮▮▮TRAMP 会自动处理 SSH 连接、认证和文件传输。如果配置了 SSH 密钥认证,可以免密码登录。

密钥认证: TRAMP 支持 SSH 密钥认证,可以提高安全性并避免频繁输入密码。需要配置 SSH 客户端使用密钥认证,并在 Vim 中使用 TRAMP 连接。

sudo 权限: TRAMP 支持使用 sudo 权限编辑远程文件。例如,要以 root 权限编辑远程文件,可以使用:

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 :e /sudo::ssh:user@host:/path/to/file

▮▮▮▮TRAMP 会先通过 SSH 连接到远程服务器,然后使用 sudo 命令获取 root 权限编辑文件。

目录浏览: TRAMP 也支持远程目录浏览。可以使用 :e /ssh:user@host:/path/to/directory 打开远程目录,使用 :Explore 命令在分割窗口中浏览远程目录。

性能优化: TRAMP 提供了多种性能优化选项,例如缓存远程文件、使用压缩传输等,可以提高远程编辑的响应速度。

远程协作(Remote Collaboration)

Vim 本身不直接提供实时的多人协作编辑功能,但可以通过一些工具和插件实现远程协作。

tmux 或 screen 会话共享: 可以使用 tmuxscreen 等终端复用工具创建会话,然后将会话共享给其他用户。多个用户可以同时连接到同一个 tmuxscreen 会话,共享同一个 Vim 实例,实现实时协作编辑。

▮▮▮▮⚝ tmux: 使用 tmux new-session -s session_name 创建一个新的 tmux 会话,使用 tmux attach-session -t session_name 连接到已存在的会话。可以使用 tmux list-sessions 查看会话列表。
▮▮▮▮⚝ screen: 使用 screen -S session_name 创建一个新的 screen 会话,使用 screen -r session_name 连接到已存在的会话。可以使用 screen -ls 查看会话列表。

▮▮▮▮通过会话共享,多个用户可以实时看到对方的编辑操作,实现简单的协作编辑。但这种方式的协作粒度较粗,容易发生冲突,且没有版本控制和权限管理。

插件: 有一些 Vim 插件尝试提供更高级的协作编辑功能,例如 vim-collaborationFloobits 等。这些插件通常基于云服务,提供实时的多人同步编辑、版本控制、聊天等功能。但这些插件的成熟度和稳定性可能不如专业的协作编辑工具。

结合版本控制系统: 对于代码协作,更推荐使用版本控制系统(如 Git)进行协作。每个开发者在本地编辑代码,然后通过 Git 提交和合并代码,实现协作开发。Vim 可以很好地与 Git 集成,提供高效的代码协作工作流。

通过 :netrw 或 TRAMP,可以方便地进行远程文件编辑和服务器管理。结合 tmuxscreen 会话共享,可以实现简单的远程协作。对于代码协作,更推荐使用 Git 等版本控制系统。

11.4 Vim 与终端的融合:tmux, screen(Vim and Terminal Integration: tmux, screen)

Vim 是一个基于终端的文本编辑器,与终端环境有着天然的融合性。结合终端复用工具 tmuxscreen,可以进一步提升 Vim 的使用效率和灵活性,构建更强大的开发环境。

tmux(Terminal Multiplexer): tmux 是一个强大的终端复用工具,可以在一个终端窗口中创建和管理多个会话、窗口和窗格(Pane)。

会话(Session): tmux 的最顶层概念是会话。一个会话可以包含多个窗口。会话是持久化的,即使终端窗口关闭,会话仍然在后台运行。可以随时重新连接到会话。

窗口(Window): 一个会话可以包含多个窗口。每个窗口相当于一个独立的终端屏幕。可以在窗口之间切换。

窗格(Pane): 一个窗口可以分割成多个窗格。每个窗格显示一个终端。可以在窗格之间切换和调整大小。

基本操作:

▮▮▮▮⚝ 启动 tmux: 在终端中输入 tmux 命令启动 tmux。
▮▮▮▮⚝ 创建新会话: tmux new-session -s session_name 创建一个名为 session_name 的新会话。
▮▮▮▮⚝ 连接到会话: tmux attach-session -t session_name 连接到名为 session_name 的会话。
▮▮▮▮⚝ 列出会话: tmux list-sessionstmux ls 列出当前所有会话。
▮▮▮▮⚝ 分离会话: 在 tmux 会话中按下 Ctrl+b d (默认快捷键前缀是 Ctrl+b,后面简称 C-b) 分离当前会话,会话会在后台继续运行。
▮▮▮▮⚝ 关闭会话: 在 tmux 会话中输入 exit 或按下 C-b :kill-session 关闭当前会话。
▮▮▮▮⚝ 窗口操作:
▮▮▮▮▮▮▮▮⚝ C-b c: 创建新窗口。
▮▮▮▮▮▮▮▮⚝ C-b n: 切换到下一个窗口。
▮▮▮▮▮▮▮▮⚝ C-b p: 切换到上一个窗口。
▮▮▮▮▮▮▮▮⚝ C-b &: 关闭当前窗口。
▮▮▮▮▮▮▮▮⚝ C-b ,: 重命名当前窗口。
▮▮▮▮▮▮▮▮⚝ C-b w: 显示窗口列表,并可选择窗口切换。
▮▮▮▮⚝ 窗格操作:
▮▮▮▮▮▮▮▮⚝ C-b %: 垂直分割当前窗格。
▮▮▮▮▮▮▮▮⚝ C-b ": 水平分割当前窗格。
▮▮▮▮▮▮▮▮⚝ C-b o: 切换到下一个窗格。
▮▮▮▮▮▮▮▮⚝ C-b <方向键>: 切换到指定方向的窗格。
▮▮▮▮▮▮▮▮⚝ C-b <空格>: 切换窗格布局。
▮▮▮▮▮▮▮▮⚝ C-b z: 最大化/恢复当前窗格。
▮▮▮▮▮▮▮▮⚝ C-b x: 关闭当前窗格。

tmux 与 Vim 结合: 在 tmux 窗口或窗格中运行 Vim,可以充分利用 tmux 的会话管理和窗口分割功能。

▮▮▮▮⚝ 多窗口布局: 可以使用 tmux 创建多个窗口,分别运行 Vim、Shell、Git 等工具,方便在不同任务之间切换。
▮▮▮▮⚝ 窗格分割: 可以使用 tmux 将一个窗口分割成多个窗格,例如一个窗格运行 Vim 编辑代码,另一个窗格运行 Shell 编译和运行程序,提高工作效率。
▮▮▮▮⚝ 会话持久化: tmux 会话的持久化特性可以保证工作环境的连续性。即使终端断开连接或电脑重启,tmux 会话仍然在后台运行,下次连接时可以恢复到上次的工作状态。

screen(GNU Screen): screen 是另一个终端复用工具,功能类似于 tmux,但历史更悠久。

会话、窗口: screen 也支持会话和窗口的概念,与 tmux 类似。

基本操作:

▮▮▮▮⚝ 启动 screen: 在终端中输入 screen 命令启动 screen。
▮▮▮▮⚝ 创建新会话: screen -S session_name 创建一个名为 session_name 的新会话。
▮▮▮▮⚝ 连接到会话: screen -r session_name 连接到名为 session_name 的会话。
▮▮▮▮⚝ 列出会话: screen -ls 列出当前所有会话。
▮▮▮▮⚝ 分离会话: 在 screen 会话中按下 Ctrl+a d (默认快捷键前缀是 Ctrl+a,后面简称 C-a) 分离当前会话。
▮▮▮▮⚝ 关闭会话: 在 screen 会话中输入 exit 或按下 C-a k 关闭当前窗口,当所有窗口关闭后,会话也会关闭。
▮▮▮▮⚝ 窗口操作:
▮▮▮▮▮▮▮▮⚝ C-a c: 创建新窗口。
▮▮▮▮▮▮▮▮⚝ C-a n: 切换到下一个窗口。
▮▮▮▮▮▮▮▮⚝ C-a p: 切换到上一个窗口。
▮▮▮▮▮▮▮▮⚝ C-a " (双引号): 显示窗口列表,并可选择窗口切换。
▮▮▮▮▮▮▮▮⚝ C-a X: 关闭当前窗口。
▮▮▮▮▮▮▮▮⚝ C-a A: 重命名当前窗口。
▮▮▮▮⚝ 区域(Region): screen 使用区域(Region)来分割窗口,类似于 tmux 的窗格。
▮▮▮▮▮▮▮▮⚝ C-a S: 水平分割当前区域。
▮▮▮▮▮▮▮▮⚝ C-a |: 垂直分割当前区域。
▮▮▮▮▮▮▮▮⚝ C-a <Tab>: 切换到下一个区域。
▮▮▮▮▮▮▮▮⚝ C-a Q: 关闭所有区域,只保留当前区域。

screen 与 Vim 结合: screen 也可以与 Vim 很好地结合使用,提供多窗口布局、会话持久化等功能,与 tmux 的使用方式类似。

选择 tmux 还是 screen: tmuxscreen 都是优秀的终端复用工具,选择哪个取决于个人偏好。

tmux 的优点:

▮▮▮▮⚝ 更现代: tmux 是较新的工具,设计更现代化,功能更丰富,配置更灵活。
▮▮▮▮⚝ 窗格分割: tmux 的窗格分割功能更强大,可以更精细地控制窗口布局。
▮▮▮▮⚝ 客户端-服务器架构: tmux 采用客户端-服务器架构,可以支持多个客户端连接到同一个服务器会话,方便多人协作。
▮▮▮▮⚝ 活跃的社区: tmux 社区活跃,文档完善,插件丰富。

screen 的优点:

▮▮▮▮⚝ 更成熟: screen 历史悠久,经过长时间的考验,稳定性更高。
▮▮▮▮⚝ 更普及: screen 在各种 Unix-like 系统上更普及,预装率更高。
▮▮▮▮⚝ 资源占用更少: 在某些情况下,screen 的资源占用可能比 tmux 更少。

▮▮▮▮对于 Vim 用户来说,tmux 通常是更推荐的选择,因为它功能更强大,配置更灵活,社区更活跃。但 screen 仍然是一个可靠的选择,尤其是在需要兼容旧系统或资源受限的环境中。

通过将 Vim 与 tmuxscreen 结合使用,可以构建一个高效、灵活、持久化的终端开发环境,显著提升开发效率。

11.5 性能优化与问题排查(Performance Optimization and Troubleshooting)

Vim 以其高效和轻量级著称,但在某些情况下,例如处理大型文件、使用大量插件或配置不当,可能会出现性能问题。了解 Vim 的性能优化技巧和问题排查方法,可以确保 Vim 始终保持最佳状态。

性能优化技巧(Performance Optimization Techniques)

避免不必要的插件: 插件是 Vim 扩展功能的强大方式,但过多的插件会降低 Vim 的启动速度和运行效率。只安装必要的插件,定期清理不常用的插件。

优化 .vimrc 配置: .vimrc 文件中的配置项会影响 Vim 的性能。

▮▮▮▮⚝ 延迟加载插件: 使用插件管理器(如 vim-plug)的延迟加载功能,只在需要时加载插件,可以显著提高 Vim 的启动速度。
▮▮▮▮⚝ 避免复杂的正则表达式: 正则表达式虽然强大,但复杂的正则表达式会消耗大量 CPU 资源。尽量使用简单的正则表达式,或使用更高效的字符串操作代替。
▮▮▮▮⚝ 禁用不必要的功能: 例如,如果不需要语法高亮,可以禁用 :syntax off。如果不需要自动缩进,可以禁用 :filetype indent off
▮▮▮▮⚝ 使用快速的配色方案: 一些配色方案可能比较复杂,会影响 Vim 的渲染速度。选择简洁、高效的配色方案。

使用 Swap 文件和备份文件: Vim 的 Swap 文件和备份文件功能可以防止数据丢失,但也会带来一定的性能开销。

▮▮▮▮⚝ 调整 Swap 文件和备份文件的位置: 将 Swap 文件和备份文件存储在快速存储介质(如 SSD)上,可以提高性能。
▮▮▮▮⚝ 禁用 Swap 文件和备份文件: 如果对数据安全性要求不高,可以禁用 Swap 文件和备份文件,提高性能。但不推荐这样做,除非非常了解风险。

使用异步操作: 对于耗时的操作,例如代码检查、格式化等,可以使用异步插件或功能,避免阻塞 Vim 的主线程,提高用户体验。例如,使用 ale 插件进行异步代码检查。

升级 Vim 版本: 新版本的 Vim 通常会进行性能优化,升级到最新版本可以获得性能提升。

硬件升级: 如果 Vim 性能问题严重,且优化效果不明显,可以考虑升级硬件,例如更换更快的 CPU、更大的内存、更快的存储介质。

问题排查方法(Troubleshooting Methods)

启动时卡顿: 如果 Vim 启动时卡顿,可能是插件加载过多或 .vimrc 配置有问题。

▮▮▮▮⚝ 使用 --startuptime 参数: 使用 vim --startuptime vim_startup.log 启动 Vim,并将启动时间信息记录到 vim_startup.log 文件中。分析 vim_startup.log 文件,可以找到启动耗时较长的插件或配置项。
▮▮▮▮⚝ 逐步禁用插件和配置: 注释掉 .vimrc 文件中的部分插件和配置项,逐步排查导致卡顿的原因。
▮▮▮▮⚝ 使用最小化配置启动: 使用 vim -u NONE -N 命令以最小化配置启动 Vim,排除配置文件的影响。

编辑大型文件卡顿: 如果编辑大型文件时卡顿,可能是 Vim 的性能瓶颈或文件类型识别有问题。

▮▮▮▮⚝ 禁用语法高亮: 对于大型文件,禁用语法高亮 :syntax off 可以提高编辑速度。
▮▮▮▮⚝ 禁用自动缩进: 禁用自动缩进 :filetype indent off 也可以提高性能。
▮▮▮▮⚝ 使用 set nowrap: 禁用自动换行 set nowrap 可以减少屏幕重绘次数,提高性能。
▮▮▮▮⚝ 检查文件类型: 确保 Vim 正确识别文件类型。如果文件类型识别错误,可能会导致不必要的语法高亮和缩进计算。可以使用 :set filetype? 查看当前文件类型。
▮▮▮▮⚝ 使用 LargeFile 插件: LargeFile 插件可以针对大型文件进行优化,例如禁用语法高亮、自动缩进等。

插件冲突: 如果安装了多个插件,可能会出现插件冲突,导致 Vim 功能异常或崩溃。

▮▮▮▮⚝ 逐步禁用插件: 禁用部分插件,逐步排查冲突的插件。
▮▮▮▮⚝ 查看插件文档: 仔细阅读插件文档,了解插件的兼容性和冲突情况。
▮▮▮▮⚝ 更新插件: 更新插件到最新版本,有时可以解决插件冲突问题。

Vimscript 错误: 如果编写了 Vimscript 脚本或插件,可能会出现 Vimscript 错误,导致 Vim 功能异常或崩溃。

▮▮▮▮⚝ 查看错误信息: Vim 通常会在命令行或消息区域显示 Vimscript 错误信息。仔细阅读错误信息,定位错误代码。
▮▮▮▮⚝ 使用 :scriptnames 命令: :scriptnames 命令可以列出所有已加载的 Vimscript 文件。检查是否有加载错误的脚本文件。
▮▮▮▮⚝ 使用 :debug 命令: :debug 命令可以启动 Vimscript 调试器,逐步执行 Vimscript 代码,查找错误。

内存泄漏: 在极少数情况下,Vim 可能会出现内存泄漏,导致内存占用不断增加,最终导致崩溃。

▮▮▮▮⚝ 监控内存占用: 使用系统监控工具(如 tophtop)监控 Vim 的内存占用。如果发现内存占用持续增加,可能是内存泄漏。
▮▮▮▮⚝ 重启 Vim: 重启 Vim 可以释放内存,暂时解决内存泄漏问题。
▮▮▮▮⚝ 报告 Bug: 如果确认是 Vim 本身的内存泄漏问题,可以向 Vim 官方报告 Bug。

通过掌握性能优化技巧和问题排查方法,可以确保 Vim 始终保持高效、稳定运行,为开发者提供最佳的编辑体验。

ENDOF_CHAPTER_

12. chapter 12: Vim 的知识框架与架构深度解析

12.1 Vim 的核心概念模型:缓冲区、窗口、标签页的内在联系

Vim 的强大和灵活性,很大程度上源于其精心设计的核心概念模型。理解缓冲区(Buffer)、窗口(Window)和标签页(Tab Page)之间的关系,是深入掌握 Vim 架构的关键。这三者构成了 Vim 编辑器的基本组织单元,协同工作,为用户提供了高效、多维度的文本编辑体验。

首先,我们来逐一认识这三个核心概念:

缓冲区(Buffer)

缓冲区是 Vim 中最基本的工作单元,它代表了内存中的文本数据。可以将其视为一个文件在内存中的映像

独立性:缓冲区独立于窗口和标签页存在。即使没有窗口显示某个缓冲区,该缓冲区仍然存在于内存中,保存着文件的内容。
持久性:缓冲区的内容会一直保留,直到显式地关闭(:bwipeout 或 Vim 退出),或者被新的内容替换。
文件关联:缓冲区通常与磁盘上的文件相关联,但并非必须如此。例如,可以使用 :enew 命令创建一个无名缓冲区,用于临时编辑一些文本片段,而无需保存到文件。
唯一性:每个缓冲区都有一个唯一的编号,可以使用 :buffers:ls 命令查看当前打开的所有缓冲区及其编号。

窗口(Window)

窗口是 Vim 用户界面的可视区域,用于显示缓冲区的内容。可以将窗口看作是观察缓冲区的“视口”。

显示缓冲区:一个窗口只能显示一个缓冲区的内容,但多个窗口可以同时显示同一个缓冲区。这使得可以同时查看和编辑文件的不同部分。
布局灵活:Vim 允许用户在一个 Vim 实例中创建多个窗口,并灵活地分割和调整窗口的大小和布局。可以使用 :split:vsplit 命令水平或垂直分割窗口。
独立视图设置:每个窗口可以有自己独立的视图设置,例如光标位置、滚动位置、折叠状态等。即使多个窗口显示同一个缓冲区,它们也可以有不同的视图状态。
窗口命令:Vim 提供了丰富的窗口管理命令,例如 Ctrl+w w(切换窗口)、Ctrl+w c(关闭窗口)、Ctrl+w =(平均分配窗口大小)等。

标签页(Tab Page)

标签页是 Vim 中组织窗口的容器。可以将标签页视为一组窗口的集合,类似于现代浏览器中的标签页。

组织窗口:一个标签页可以包含多个窗口,每个窗口显示不同的缓冲区或同一个缓冲区的不同部分。
工作区隔离:标签页提供了一种工作区隔离的机制。可以使用不同的标签页来组织不同的工作任务或项目,避免窗口混乱。
标签页命令:Vim 提供了标签页管理命令,例如 :tabnew(新建标签页)、:tabnext(切换到下一个标签页)、:tabclose(关闭当前标签页)等。
标签页与会话:标签页可以与 Vim 的会话(Session)功能结合使用,保存和恢复整个工作区布局,包括标签页、窗口和缓冲区。

内在联系与工作流程

缓冲区、窗口和标签页并非孤立存在,而是紧密联系、协同工作的。它们之间的关系可以用以下方式概括:

  1. 缓冲区是数据中心:缓冲区存储着文本数据,是编辑操作的核心。所有的编辑操作都是在缓冲区上进行的。
  2. 窗口是展示平台:窗口负责将缓冲区的内容呈现给用户。用户通过窗口查看和编辑缓冲区的内容。
  3. 标签页是组织框架:标签页用于组织和管理窗口,提供工作区隔离和布局管理。

工作流程示例

假设用户打开一个文件 example.txt

  1. Vim 会创建一个缓冲区,将 example.txt 的内容加载到缓冲区中。
  2. Vim 会创建一个窗口,并将该窗口与刚刚创建的缓冲区关联起来,从而在窗口中显示 example.txt 的内容。
  3. 默认情况下,这个窗口会位于一个默认的标签页中。

如果用户执行 :split 命令分割窗口:

  1. Vim 会创建一个新的窗口
  2. 新窗口默认会显示当前窗口所显示的缓冲区,即 example.txt 的缓冲区。
  3. 现在,两个窗口都显示同一个缓冲区,用户可以同时查看和编辑 example.txt 的不同部分。

如果用户执行 :tabnew 命令新建标签页:

  1. Vim 会创建一个新的标签页
  2. 新标签页默认是空的,不包含任何窗口。
  3. 用户可以在新标签页中打开新的文件,创建新的窗口,开始新的工作任务。

形象比喻

为了更形象地理解这三者之间的关系,可以将其比喻为:

缓冲区:好比是书本的内容,存储着实际的文本信息。
窗口:好比是书本的页面,展示书本内容的一部分。可以同时打开书本的多个页面来阅读不同的章节。
标签页:好比是书本的章节或者不同的书本,用于组织和区分不同的阅读内容。

总结

理解 Vim 的缓冲区、窗口和标签页模型,是掌握 Vim 高效编辑技巧的基础。它们共同构建了一个强大而灵活的文本编辑环境,允许用户以多维度、多视角的方式处理文本数据。通过熟练运用这三个核心概念,可以更有效地组织工作区,提高编辑效率,并充分发挥 Vim 的潜力。

12.2 Vim 的事件循环与模式切换机制

Vim 的核心架构基于事件循环(Event Loop)模式切换(Mode Switching)机制。这两个机制共同决定了 Vim 的交互方式和操作逻辑,也是 Vim 高效和灵活的关键所在。

事件循环(Event Loop)

事件循环是现代图形用户界面(GUI)应用程序和许多文本编辑器(包括 Vim)的核心架构模式。它负责监听和处理用户输入(例如键盘按键、鼠标操作)以及系统事件,并根据事件类型执行相应的操作。

在 Vim 中,事件循环的工作流程大致如下:

  1. 等待事件:Vim 进入事件循环后,首先会等待事件的发生。事件可以来自用户的键盘输入、鼠标操作,也可以是系统信号等。
  2. 事件捕获:当事件发生时,事件循环会捕获该事件。例如,用户按下键盘上的 h 键,事件循环会捕获到 “按下 h 键” 这个事件。
  3. 事件处理:事件循环根据捕获到的事件类型,查找相应的事件处理函数命令。例如,在 Normal 模式下按下 h 键,Vim 会执行向左移动光标的命令。
  4. 执行操作:事件处理函数或命令被执行,Vim 的状态发生改变,例如光标移动、文本修改、窗口切换等。
  5. 界面更新:Vim 根据状态的改变,更新用户界面,例如重新绘制窗口内容、更新光标位置等。
  6. 循环:完成界面更新后,事件循环再次回到等待事件的状态,重复上述步骤,不断监听和处理新的事件。

事件类型

Vim 事件循环处理的事件类型主要包括:

键盘事件:用户按键、释放按键等。这是 Vim 最主要的事件来源。
鼠标事件:鼠标点击、移动、滚动等。在 GUI 版本的 Vim 中支持鼠标操作。
定时器事件:Vim 可以设置定时器,定时触发事件,用于实现某些自动化功能。
信号事件:操作系统发送给 Vim 进程的信号,例如窗口大小改变信号、退出信号等。
自动命令事件:Vim 内部定义的事件,例如文件打开事件、缓冲区修改事件等,用于触发自动命令(autocmd)。

模式切换(Mode Switching)机制

Vim 最显著的特点之一就是其模式编辑的概念。Vim 并非像其他编辑器那样只有一个编辑模式,而是拥有多种不同的模式,每种模式下键盘按键的含义都不同。这种模式切换机制是 Vim 高效编辑的核心。

Vim 主要有以下几种模式:

Normal 模式(普通模式):Vim 启动后默认进入 Normal 模式。该模式下主要用于执行各种命令,例如移动光标、删除文本、复制粘贴、搜索替换等。Normal 模式是 Vim 的核心模式,也是效率最高的模式。
Insert 模式(插入模式):用于输入文本。在 Normal 模式下按下 i, a, o 等键可以进入 Insert 模式。在 Insert 模式下,键盘按键的行为与普通文本编辑器类似,直接输入字符。按下 Esc 键可以返回 Normal 模式。
Visual 模式(可视模式):用于选择文本块。在 Normal 模式下按下 v, V, Ctrl+v 等键可以进入 Visual 模式。Visual 模式下可以使用移动命令来选择字符、行或块,然后对选中文本进行操作,例如删除、复制、替换等。
Command-line 模式(命令行模式):用于执行更复杂的命令,例如文件操作、设置选项、调用外部命令等。在 Normal 模式下按下 : 键可以进入 Command-line 模式。命令输入完成后,按下 Enter 键执行命令。
Replace 模式(替换模式):用于替换文本。在 Normal 模式下按下 R 键可以进入 Replace 模式。在 Replace 模式下,输入的字符会替换光标位置的字符。按下 Esc 键可以返回 Normal 模式。
Select 模式(选择模式):类似于 Visual 模式,但更接近于图形界面的文本选择行为。通常较少使用,可以通过设置选项启用。
Ex 模式(Ex 模式):一种面向行的编辑模式,类似于 Unix 的 ex 编辑器。可以通过命令 :Ex 进入。

模式切换流程

模式切换是 Vim 操作的核心。用户通过在不同模式之间切换,组合使用各种命令,完成复杂的编辑任务。

Normal 模式是中心:Normal 模式是 Vim 的核心模式,也是各种操作的起点。大部分操作都是从 Normal 模式开始,并最终返回 Normal 模式。
模式切换命令:Vim 提供了丰富的命令用于模式切换。例如,从 Normal 模式进入 Insert 模式的命令有 i, a, o, I, A, O 等;进入 Visual 模式的命令有 v, V, Ctrl+v 等;进入 Command-line 模式的命令是 :
返回 Normal 模式:几乎所有其他模式都可以通过按下 Esc 键返回 Normal 模式。Esc 键是 Vim 中最重要的按键之一,用于快速回到命令模式。

模式切换与事件循环的协同

事件循环和模式切换机制紧密结合,共同驱动 Vim 的运行。

事件驱动模式切换:用户输入的按键事件会触发模式切换。例如,在 Normal 模式下按下 i 键,事件循环会检测到 i 键事件,并执行模式切换操作,将 Vim 从 Normal 模式切换到 Insert 模式。
模式决定事件处理:当前 Vim 处于哪种模式,决定了事件循环如何处理后续的按键事件。例如,在 Normal 模式下按下 h 键是向左移动光标,而在 Insert 模式下按下 h 键则是输入字符 h

总结

Vim 的事件循环和模式切换机制是其架构的基石。事件循环保证了 Vim 能够及时响应用户输入和系统事件,模式切换机制则赋予了 Vim 强大的命令集和高效的编辑能力。理解这两个机制的工作原理,有助于深入理解 Vim 的设计思想,并更好地利用 Vim 进行文本编辑。

12.3 Vim 的可扩展性架构:插件与 Vimscript 的工作原理

Vim 的强大之处不仅在于其核心功能,还在于其高度的可扩展性。Vim 允许用户通过插件(Plugins)Vimscript 脚本来扩展其功能,定制其行为,使其能够适应各种不同的编辑需求和工作流程。

可扩展性架构

Vim 的可扩展性架构主要体现在以下几个方面:

插件机制:Vim 提供了完善的插件机制,允许用户安装和管理第三方插件,以扩展 Vim 的功能。插件可以实现代码补全、语法检查、文件管理、主题美化等各种功能。
Vimscript 脚本:Vim 内置了强大的脚本语言 Vimscript(也称为 Vim 脚本或 VimL)。用户可以使用 Vimscript 编写脚本,自定义 Vim 的行为,例如定义新的命令、映射快捷键、编写插件等。
外部命令调用:Vim 允许用户在 Vim 中调用外部命令,并将外部命令的输出结果导入到 Vim 中,或者将 Vim 的内容传递给外部命令处理。这使得 Vim 可以与其他工具和系统命令集成。
API 接口:Vim 提供了一系列 API 接口,允许插件和 Vimscript 脚本访问 Vim 的内部数据和功能,例如缓冲区、窗口、选项、命令等。

插件(Plugins)

插件是 Vim 扩展功能的主要方式。Vim 社区拥有庞大而活跃的插件生态系统,提供了各种各样的插件,涵盖了几乎所有可能的编辑需求。

插件类型:Vim 插件可以分为多种类型,例如:
▮▮▮▮⚝ 功能增强插件:例如代码补全插件(如 coc.nvim, YouCompleteMe)、语法检查插件(如 ale, syntastic)、文件管理器插件(如 nerdtree, vim-vinegar)。
▮▮▮▮⚝ 界面美化插件:例如配色方案插件、状态栏插件、图标插件等。
▮▮▮▮⚝ 语言支持插件:针对特定编程语言或文件类型的插件,提供语法高亮、代码片段、代码格式化等功能。
▮▮▮▮⚝ 实用工具插件:例如 Git 集成插件(如 vim-fugitive)、Markdown 预览插件、TODO 管理插件等。
插件管理:为了方便插件的安装、更新和管理,出现了许多插件管理器,例如:
▮▮▮▮⚝ Vundle
▮▮▮▮⚝ Pathogen
▮▮▮▮⚝ vim-plug
▮▮▮▮⚝ dein.vim
▮▮▮▮⚝ packer.nvim
▮▮▮▮插件管理器可以自动下载、安装和更新插件,并管理插件的加载顺序和配置。
插件配置:大多数插件都提供配置选项,允许用户根据自己的需求定制插件的行为。插件配置通常在 .vimrc 文件中进行。

Vimscript 脚本(Vimscript)

Vimscript 是 Vim 内置的脚本语言,是 Vim 可扩展性的核心。Vimscript 是一种动态类型的、解释型的脚本语言,语法风格受到 Python 和 Perl 的影响,但也具有自身的特点。

Vimscript 的作用:Vimscript 可以用于:
▮▮▮▮⚝ 自定义 Vim 配置.vimrc 文件本身就是一个 Vimscript 文件,用于配置 Vim 的各种选项、映射快捷键、设置自动命令等。
▮▮▮▮⚝ 编写插件:Vim 插件通常使用 Vimscript 编写,可以实现各种复杂的功能扩展。
▮▮▮▮⚝ 自动化任务:可以使用 Vimscript 编写脚本,自动化执行一系列 Vim 命令,例如批量文件处理、文本转换等。
▮▮▮▮⚝ 扩展 Vim 命令:可以使用 Vimscript 定义新的 Vim 命令,扩展 Vim 的命令集。
Vimscript 的工作原理
▮▮▮▮1. 解释执行:Vimscript 代码在运行时被 Vim 解释器逐行解释执行。
▮▮▮▮2. 访问 Vim API:Vimscript 可以通过内置的函数和变量,访问 Vim 的内部 API,操作缓冲区、窗口、选项、命令等。
▮▮▮▮3. 事件驱动:Vimscript 可以响应 Vim 的各种事件,例如按键事件、文件打开事件、缓冲区修改事件等,实现事件驱动的编程。
▮▮▮▮4. 与 Vim 命令集成:Vimscript 可以与 Vim 的命令系统无缝集成,可以定义新的命令,也可以在 Vim 命令中调用 Vimscript 函数。
Vimscript 基础:Vimscript 的基础语法包括:
▮▮▮▮⚝ 变量:使用 let 关键字声明变量,支持字符串、数字、列表、字典等数据类型。
▮▮▮▮⚝ 函数:使用 function 关键字定义函数,可以接受参数和返回值。
▮▮▮▮⚝ 控制结构:支持 if-else, for, while 等控制结构。
▮▮▮▮⚝ 命令:Vimscript 可以执行 Vim 的各种命令,例如 :echo, :set, :map 等。
▮▮▮▮⚝ 字符串操作:提供丰富的字符串操作函数,例如字符串拼接、查找、替换等。
▮▮▮▮⚝ 列表和字典操作:支持列表和字典数据结构,并提供相应的操作函数。

插件与 Vimscript 的关系

插件通常是使用 Vimscript 编写的,或者至少部分使用 Vimscript。插件利用 Vimscript 提供的 API 和语言特性,扩展 Vim 的功能。

插件是 Vimscript 的应用:插件是 Vimscript 在实际应用中的体现。通过编写 Vimscript 代码,可以将各种功能封装成插件,方便用户安装和使用。
Vimscript 是插件的基础:Vimscript 是编写 Vim 插件的基础语言。理解 Vimscript 的语法和 API,是开发 Vim 插件的前提。

总结

Vim 的可扩展性架构是其强大功能的重要组成部分。插件和 Vimscript 脚本为用户提供了无限的定制空间,使得 Vim 可以适应各种不同的编辑需求和工作流程。通过利用插件和 Vimscript,用户可以将 Vim 打造成一个高度个性化、功能强大的编辑器,极大地提高编辑效率和工作体验。深入学习 Vimscript 编程,是成为 Vim 高手的必经之路。

ENDOF_CHAPTER_

13. chapter 13: 实战案例:Vim 在不同场景下的应用

13.1 Vim 在代码开发中的应用:各种编程语言的配置与技巧

Vim 作为一款强大的文本编辑器,在代码开发领域拥有广泛的应用。其高效的编辑模式、丰富的插件生态以及高度的可定制性,使得 Vim 成为众多程序员的首选工具。本节将深入探讨 Vim 在不同编程语言开发中的应用,并介绍相应的配置与技巧,帮助读者充分发挥 Vim 在代码开发中的潜力。

通用代码开发技巧

语法高亮(Syntax Highlighting):语法高亮是代码编辑器的基本功能,能够显著提高代码的可读性。Vim 内置了对众多编程语言的语法高亮支持,只需确保文件类型检测开启(filetype on)即可自动启用。对于一些较新的或较为小众的语言,可能需要安装额外的语法文件。

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 " 开启文件类型检测
2 filetype on
3 " 开启语法高亮
4 syntax on

代码补全(Code Completion):代码补全功能可以大幅提升编码效率,减少输入错误。Vim 本身提供了一些基本的补全功能,例如基于字典的补全、基于标签的补全等。但对于现代编程语言,通常需要借助插件来实现更智能、更全面的代码补全。常用的代码补全插件包括:
▮▮▮▮⚝ coc.nvim (Conquer of Completion):基于 Language Server Protocol (LSP) 的强大补全引擎,支持多种编程语言,提供智能补全、代码诊断、跳转到定义等功能。配置相对复杂,但功能强大。
▮▮▮▮⚝ nvim-cmp (nvim-completion):Neovim 的原生补全框架,可以与多种补全源配合使用,例如 LSP、nvim-lspconfigultisnips 等。配置灵活,性能优秀。
▮▮▮▮⚝ YouCompleteMe (YCM):老牌的自动补全插件,支持多种编程语言,补全速度快,但安装配置相对繁琐。

代码导航(Code Navigation):在大型代码库中,快速跳转到函数定义、变量声明等位置至关重要。Vim 提供了多种代码导航方式:
▮▮▮▮⚝ 标签跳转(Tags):使用 ctagsuniversal-ctags 生成标签文件,然后可以使用 :tag 命令跳转到标签,Ctrl+] 跳转到光标下单词的标签,Ctrl+t 返回。

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 # 使用 universal-ctags 生成 tags 文件
2 ctags -R .

▮▮▮▮⚝ LSP 跳转:配合 LSP 插件(如 coc.nvimnvim-lspconfig),可以使用 gd (跳转到定义), gi (跳转到实现), gr (跳转到引用) 等命令进行代码导航。
▮▮▮▮⚝ Ctrl+oCtrl+i:在跳转后,可以使用 Ctrl+o 返回到跳转前的位置,Ctrl+i 前进。

代码格式化(Code Formatting):保持代码风格一致性有助于提高代码可读性和团队协作效率。Vim 可以通过外部格式化工具或插件来实现代码格式化:
▮▮▮▮⚝ 外部格式化工具:例如 clang-format (C/C++/Objective-C), black (Python), prettier (JavaScript/TypeScript/CSS) 等。可以使用 Vim 的 :!command 执行外部命令,或者配置自动命令在保存文件时自动格式化。

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 " 使用 clang-format 格式化 C/C++ 代码
2 autocmd BufWritePre *.c,*.cpp,*.h :!clang-format -i %

▮▮▮▮⚝ 格式化插件:例如 vim-autoformat,可以集成多种格式化工具,并提供统一的格式化命令 :Autoformat

代码片段(Code Snippets):代码片段可以快速插入常用的代码模板,提高编码速度。常用的代码片段插件包括:
▮▮▮▮⚝ ultisnips:功能强大的代码片段引擎,支持多种触发方式和动态占位符。
▮▮▮▮⚝ neosnippet.vim:另一个流行的代码片段插件,配置简单,易于使用。

针对不同编程语言的配置与技巧

Python 🐍

▮▮▮▮⚝ 配置示例

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 " Python 相关配置
2 filetype plugin indent on
3 syntax on
4 set tabstop=4 " Tab 宽度为 4 个空格
5 set softtabstop=4 " 软 Tab 宽度为 4 个空格
6 set shiftwidth=4 " 缩进宽度为 4 个空格
7 set expandtab " 将 Tab 转换为空格
8 set autoindent " 自动缩进
9 set smartindent " 智能缩进
10 set number " 显示行号
11 set cursorline " 高亮当前行
12
13 " 代码检查插件 (例如:flake8, pylint)
14 " 可以使用 ale 插件集成代码检查
15 let g:ale_linters = {'python': ['flake8', 'pylint']}
16 let g:ale_fixers = {'python': ['black', 'isort']} " 代码格式化工具
17 let g:ale_python_flake8_options = '--max-line-length=120'
18
19 " 代码补全 (例如:coc.nvim)
20 " 需要安装 coc-python 扩展

▮▮▮▮⚝ 技巧
▮▮▮▮ⓐ 使用 :pyfile:python 命令执行 Python 代码。
▮▮▮▮ⓑ 利用 pydochelp() 查看 Python 文档。
▮▮▮▮ⓒ 结合 virtualenvvenv 管理 Python 虚拟环境,确保项目依赖隔离。

JavaScript / TypeScript 📜

▮▮▮▮⚝ 配置示例

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 " JavaScript / TypeScript 相关配置
2 filetype plugin indent on
3 syntax on
4 set tabstop=2
5 set softtabstop=2
6 set shiftwidth=2
7 set expandtab
8 set autoindent
9 set smartindent
10 set number
11 set cursorline
12
13 " 代码检查 (例如:eslint) 和格式化 (例如:prettier)
14 " 使用 ale 插件集成
15 let g:ale_linters = {'javascript': ['eslint'], 'typescript': ['eslint']}
16 let g:ale_fixers = {'javascript': ['prettier'], 'typescript': ['prettier']}
17 let g:ale_javascript_eslint_options = '--max-len 120'
18
19 " 代码补全 (例如:coc.nvim)
20 " 需要安装 coc-tsserver 扩展

▮▮▮▮⚝ 技巧
▮▮▮▮ⓐ 使用 :!node %:!deno run % 运行 JavaScript/TypeScript 代码(需要 Node.js 或 Deno 环境)。
▮▮▮▮ⓑ 利用 jsdoctypedoc 生成文档注释。
▮▮▮▮ⓒ 结合 npmyarn 管理项目依赖。

C / C++ 🛠️

▮▮▮▮⚝ 配置示例

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 " C / C++ 相关配置
2 filetype plugin indent on
3 syntax on
4 set tabstop=4
5 set softtabstop=4
6 set shiftwidth=4
7 set expandtab
8 set autoindent
9 set smartindent
10 set number
11 set cursorline
12
13 " 代码检查 (例如:clang-tidy) 和格式化 (例如:clang-format)
14 " 使用 ale 插件集成
15 let g:ale_linters = {'c': ['clang-tidy'], 'cpp': ['clang-tidy']}
16 let g:ale_fixers = {'c': ['clang-format'], 'cpp': ['clang-format']}
17
18 " 代码补全 (例如:coc.nvim 或 YCM)
19 " coc.nvim 需要安装 coc-clangd 扩展
20 " YCM 需要编译安装,配置较为复杂

▮▮▮▮⚝ 技巧
▮▮▮▮ⓐ 使用 :make 命令编译代码,并配置 makeprg 选项指定编译器和编译参数。

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 " 例如,使用 gcc 编译 C 代码
2 set makeprg=gcc\ % -o\ %<

▮▮▮▮ⓑ 利用 gdblldb 进行代码调试,可以使用 Vim 插件如 vimspectornvim-dap 集成调试器。
▮▮▮▮ⓒ 使用 ctags 或 LSP 进行代码导航。

其他语言:对于其他编程语言,例如 Java, Go, Rust, Ruby 等,Vim 同样提供了良好的支持。可以通过安装相应的语法文件、代码补全插件、代码检查插件等来定制 Vim 环境,以满足不同语言的开发需求。

总结

Vim 在代码开发中具有强大的功能和灵活性。通过合理的配置和插件选择,可以将其打造成高效、舒适的 IDE 替代品。关键在于理解 Vim 的核心理念,熟练掌握基本操作,并根据自身需求不断探索和定制。

13.2 Vim 在文本写作中的应用:Markdown, LaTeX 支持

Vim 不仅是代码编辑利器,同样也是优秀的文本编辑器,尤其在 Markdown 和 LaTeX 等标记语言的写作中,Vim 的高效编辑模式和可扩展性使其成为许多写作者的理想选择。本节将介绍 Vim 在 Markdown 和 LaTeX 写作中的应用技巧和配置。

Markdown 写作 📝

Markdown 语法支持:Vim 默认对 Markdown 语法提供基本的支持,包括标题、列表、链接、代码块等。可以通过安装插件来增强 Markdown 的语法高亮和功能。
▮▮▮▮⚝ vim-markdown:流行的 Markdown 语法高亮和增强插件,提供更好的语法高亮、列表和标题的自动格式化、表格编辑等功能。

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 " 使用 vim-plug 插件管理器安装
2 Plug 'plasticboy/vim-markdown'

实时预览:Markdown 的优势在于其简洁的语法和易于转换为 HTML 等格式。在 Vim 中可以实现 Markdown 文件的实时预览,方便写作时查看效果。
▮▮▮▮⚝ instant-markdown-d:一个 Node.js 写的 Markdown 预览服务器,可以与 Vim 插件配合使用,实现浏览器实时预览。
▮▮▮▮⚝ markdown-preview.nvim:Neovim 的 Markdown 预览插件,支持多种预览方式,包括浏览器预览和 Neovim 内置预览。

快捷键与宏:利用 Vim 的快捷键和宏功能,可以快速插入 Markdown 语法元素,提高写作效率。
▮▮▮▮⚝ 自定义快捷键:例如,可以映射快捷键来快速插入标题、列表、代码块等。

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 " 映射 <leader>h1 到 # 标题
2 nnoremap <leader>h1 i# <Esc>
3 " 映射 <leader>ul 到无序列表
4 nnoremap <leader>ul i- <Space><Esc>

▮▮▮▮⚝ 宏录制:可以使用宏来批量处理 Markdown 文本,例如批量添加或删除列表前缀、批量修改标题级别等。

拼写检查:Vim 内置了拼写检查功能,可以帮助检查 Markdown 文档中的拼写错误。

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 " 开启拼写检查,语言设置为英文
2 set spell spelllang=en_us
3 " 使用 ]s 和 [s 跳转到下一个和上一个拼写错误
4 " 使用 zg 添加单词到好词列表,zG 添加到全局好词列表
5 " 使用 zw 添加单词到坏词列表,zW 添加到全局坏词列表

LaTeX 写作 📚

LaTeX 语法支持:Vim 对 LaTeX 语法提供基本的支持,可以通过安装插件来增强 LaTeX 的语法高亮和功能。
▮▮▮▮⚝ vimtex:功能强大的 LaTeX 插件,提供语法高亮、代码补全、编译、错误检查、文档预览等功能,是 LaTeX 写作的必备插件。

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 " 使用 vim-plug 插件管理器安装
2 Plug 'lervag/vimtex'

编译与预览:LaTeX 文档需要编译成 PDF 或其他格式才能查看效果。vimtex 插件集成了 LaTeX 编译功能,可以方便地在 Vim 中编译和预览文档。
▮▮▮▮⚝ 编译命令:VimtexCompile 命令可以编译 LaTeX 文档。
▮▮▮▮⚝ 预览命令:VimtexView 命令可以打开 PDF 预览器查看编译结果。
▮▮▮▮⚝ 自动编译vimtex 可以配置为在保存文件时自动编译,实现实时预览效果。

代码片段与模板:LaTeX 语法较为繁琐,使用代码片段和模板可以提高写作效率。
▮▮▮▮⚝ vimtex 代码片段vimtex 插件自带了丰富的 LaTeX 代码片段,可以通过触发词快速插入常用 LaTeX 命令和环境。
▮▮▮▮⚝ 自定义模板:可以自定义 LaTeX 文档模板,快速创建新的 LaTeX 文档。

参考文献管理:对于学术论文等需要管理参考文献的 LaTeX 文档,可以使用 Vim 插件或外部工具进行参考文献管理。
▮▮▮▮⚝ vimtex 参考文献支持vimtex 可以与 BibTeX 或 BibLaTeX 配合使用,方便管理参考文献。
▮▮▮▮⚝ 外部参考文献管理工具:例如 Zotero, Mendeley 等,可以导出 BibTeX 文件,然后 vimtex 可以读取这些文件进行参考文献管理。

数学公式支持:LaTeX 的强大之处在于其对数学公式的完美支持。Vim 可以很好地支持 LaTeX 数学公式的编辑和显示。
▮▮▮▮⚝ vimtex 数学公式预览vimtex 可以配置为在 Vim 中预览 LaTeX 数学公式,方便检查公式的正确性。

总结

Vim 在 Markdown 和 LaTeX 写作中同样表现出色。通过安装合适的插件和配置,可以将其打造成高效、舒适的文本写作环境。无论是撰写博客文章、技术文档,还是学术论文、书籍,Vim 都能提供强大的支持,帮助写作者专注于内容创作。

13.3 Vim 在系统管理中的应用:配置文件编辑、日志分析

Vim 作为命令行环境下的文本编辑器,在系统管理领域具有独特的优势。其轻量级、快速启动、强大的文本处理能力,使得 Vim 成为系统管理员进行配置文件编辑、日志分析等任务的得力助手。本节将探讨 Vim 在系统管理中的应用场景和实用技巧。

配置文件编辑 ⚙️

语法高亮:对于常见的配置文件格式,例如 nginx.conf, apache2.conf, systemd unit files, YAML, JSON 等,Vim 提供了语法高亮支持,可以提高配置文件的可读性,减少配置错误。确保 filetype onsyntax on 已启用。

自动补全:对于一些配置文件格式,可以通过插件或配置实现自动补全功能,例如 YAML 文件的补全可以使用 coc.nvim 配合 coc-yaml 扩展。

代码折叠:对于结构复杂的配置文件,可以使用代码折叠功能来隐藏不关心的部分,聚焦于当前编辑区域。Vim 提供了多种折叠方式,例如基于缩进的折叠 (set foldmethod=indent),基于语法的折叠 (set foldmethod=syntax) 等。可以使用 za 打开/关闭当前折叠,zR 打开所有折叠,zM 关闭所有折叠。

批量修改:在系统管理中,经常需要批量修改配置文件,例如批量替换 IP 地址、端口号等。Vim 的全局替换命令 :s 和宏功能可以高效地完成批量修改任务。
▮▮▮▮⚝ 全局替换:%s/old_string/new_string/g 命令可以将文件中所有 old_string 替换为 new_string。可以使用正则表达式进行更复杂的替换。
▮▮▮▮⚝ 宏录制:可以使用宏来录制一系列编辑操作,然后重复执行宏来批量修改文件。

权限管理:在编辑系统配置文件时,经常需要使用管理员权限。可以使用 :w !sudo tee % 命令以管理员权限保存文件。这个命令的原理是使用 tee 命令将 Vim 的输出重定向到文件,并使用 sudo 提升权限。

日志分析 📜

快速打开大文件:Vim 启动速度快,可以快速打开大型日志文件,而不会像一些图形编辑器那样卡顿。可以使用 vim large_log_file.log 命令快速打开日志文件。

搜索与过滤:Vim 提供了强大的搜索功能,可以快速定位日志文件中的关键信息。
▮▮▮▮⚝ 基本搜索/keyword 命令可以搜索包含 keyword 的行。
▮▮▮▮⚝ 高级搜索:可以使用正则表达式进行更复杂的搜索,例如搜索特定时间范围内的日志。
▮▮▮▮⚝ :grep 命令:grep keyword *.log 命令可以在多个日志文件中搜索 keyword,并将结果显示在 quickfix 窗口中。可以使用 :cnext:cprev 命令在搜索结果之间跳转。
▮▮▮▮⚝ :vimgrep 命令:vimgrep /keyword/j *.log 命令与 :grep 类似,但使用 Vim 的正则表达式引擎,功能更强大。

高亮显示:可以使用 Vim 的 :syntax 命令或插件来高亮显示日志文件中的关键信息,例如错误级别、时间戳、IP 地址等,提高日志分析效率。

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 " 高亮显示 ERROR 关键词
2 syntax keyword ErrorLevelError ERROR
3 highlight link ErrorLevelError Error

分屏与标签页:可以使用 Vim 的分屏和标签页功能同时查看多个日志文件或日志文件的不同部分,方便对比分析。
▮▮▮▮⚝ :split:vsplit:命令可以水平或垂直分割窗口。
▮▮▮▮⚝ :tabnew:命令可以创建新的标签页。

宏与自动化:可以使用 Vim 的宏功能来自动化日志分析任务,例如批量提取特定类型的日志信息、批量格式化日志文件等。

与命令行工具集成:Vim 可以很好地与命令行工具集成,例如 awk, sed, grep, cut 等。可以使用 :!command 命令在 Vim 中执行外部命令,并将命令的输出导入到 Vim 缓冲区中进行进一步处理。

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 " 使用 awk 提取日志文件中的特定列
2 :r !awk '{print $1, $3}' log_file.log

远程编辑 🌐

:netrw 插件:Vim 内置了 netrw 插件,可以方便地编辑远程服务器上的文件。可以使用 vim scp://user@host/path/to/filevim sftp://user@host/path/to/file 命令打开远程文件。

TRAMP 模式:TRAMP (Transparent Remote Access, Multiple Protocol) 是 Emacs 的远程编辑模式,但也可以在 Vim 中使用 TRAMP 模式通过 SSH 等协议编辑远程文件。需要安装 vim-tramp 插件。

tmux/screen 会话共享:可以使用 tmux 或 screen 等终端复用工具创建会话,然后在会话中运行 Vim,实现多人协作编辑远程文件。

总结

Vim 在系统管理中扮演着重要的角色。其高效的文本编辑能力、强大的搜索功能、与命令行工具的良好集成,以及远程编辑能力,使得 Vim 成为系统管理员处理配置文件、分析日志、管理服务器的理想工具。熟练掌握 Vim 的系统管理技巧,可以显著提高系统管理效率和工作质量。

ENDOF_CHAPTER_

14. chapter 14: Vim 社区与资源

14.1 Vim 社区文化与学习资源:网站、论坛、邮件列表

Vim 社区是一个充满活力、乐于助人且极其专注的群体,他们共同维护着这款强大的文本编辑器,并致力于帮助新用户快速上手,同时也为资深用户提供深入交流和技术精进的平台。Vim 社区文化的核心价值在于效率精简共享。用户们推崇使用 Vim 提高工作效率,追求操作的精简与优雅,并且乐于分享自己的配置、技巧和插件,共同构建一个繁荣的 Vim 生态系统。

以下是一些重要的 Vim 社区资源和学习平台,它们是您深入了解 Vim、解决问题以及与全球 Vim 用户交流的重要场所:

官方网站 (Official Website)https://www.vim.org/
⚝ Vim 的官方网站是获取权威信息的第一站。您可以在这里找到 Vim 的最新版本下载、完整的帮助文档(Help Files)、Vimscript 文档、FAQ(常见问题解答)、以及各种与 Vim 相关的资源链接。
⚝ 官方网站的帮助文档是学习 Vim 最全面、最准确的资料,虽然内容庞大,但结构清晰,可以通过 :help <topic> 命令在 Vim 中直接访问,是深入理解 Vim 功能和原理的必备参考。

Vim-scripts 仓库 (Vim Scripts Repository)https://vim-scripts.org/ (可能已归档,部分功能迁移至 GitHub 等平台)
⚝ 这是一个历史悠久的 Vim 脚本和插件仓库,虽然现在可能不如 GitHub 等平台活跃,但仍然可以找到许多经典的 Vim 脚本和资源。
⚝ 浏览这个仓库可以了解 Vim 插件生态的早期发展,以及一些解决特定问题的实用脚本。

GitHub 上的 Vim 资源 (Vim Resources on GitHub)https://github.com/search?q=vim
⚝ GitHub 是目前 Vim 插件和配置分享最活跃的平台。通过搜索 "vim" 关键词,您可以找到数以万计的 Vim 仓库,包括各种插件、配色方案、配置 Dotfiles 以及 Vim 相关工具。
⚝ 许多优秀的 Vim 插件都托管在 GitHub 上,例如 NERDTree, CtrlP, coc.nvim 等。通过关注 GitHub 上活跃的 Vim 开发者和仓库,可以及时了解 Vim 社区的最新动态和技术趋势。

Vim subreddit (Reddit 上的 Vim 子版块)https://www.reddit.com/r/vim/
⚝ Reddit 的 r/vim 子版块是一个非常活跃的 Vim 用户社区。在这里,您可以提问、分享技巧、展示配置、讨论 Vim 的最新发展,以及参与各种与 Vim 相关的话题。
⚝ r/vim 社区氛围友好,乐于助人,是解决 Vim 使用问题、获取灵感和与其他 Vim 用户交流的绝佳场所。

Stack Overflow (堆栈溢出)https://stackoverflow.com/questions/tagged/vim
⚝ Stack Overflow 是程序员解决技术问题的首选网站。在 Stack Overflow 上搜索或提问关于 Vim 的问题,通常可以快速找到高质量的解答。
⚝ Stack Overflow 上的 Vim 标签下汇集了大量常见问题和解决方案,是解决 Vim 使用中遇到的具体技术难题的有效途径。

Vim Awesomehttps://vimawesome.com/
⚝ Vim Awesome 是一个精选的 Vim 插件目录,它收集了大量高质量的 Vim 插件,并按照功能和流行度进行分类和排序。
⚝ 通过 Vim Awesome,您可以方便地发现和选择适合自己需求的 Vim 插件,提升 Vim 的功能和效率。

Learn Vimscript the Hard Wayhttp://learnvimscriptthehardway.stevelosh.com/
⚝ 这是一本免费的在线教程,专门 для beginners 学习 Vimscript 编程。通过系统地学习这本教程,您可以掌握 Vimscript 的基础知识,并开始编写自己的 Vim 插件和配置。
⚝ 对于希望深度定制 Vim 或开发插件的用户来说,学习 Vimscript 是必不可少的,而 Learn Vimscript the Hard Way 是一个非常好的入门资源。

书籍 (Books)
⚝ 《Practical Vim, 2nd Edition: Edit Text at the Speed of Thought》:Drew Neil 的《Practical Vim》是公认的 Vim 学习经典之作。它以实践为导向,通过大量的技巧和案例,帮助读者深入理解 Vim 的操作方式和设计哲学,从而真正提高 Vim 的使用效率。
⚝ 《Mastering Vim Quickly: From WTF to OMG in No Time》:Jared Forsyth 的《Mastering Vim Quickly》以其幽默风趣的风格和循序渐进的教学方式而受到欢迎。这本书适合想要快速入门 Vim 并掌握核心技能的初学者。
⚝ 《Vi Improved -- Vim》 (官方文档书籍):这本由 Bram Moolenaar (Vim 的创造者) 撰写的书籍,实际上是 Vim 官方帮助文档的印刷版。它内容全面、权威,是深入了解 Vim 各个方面细节的必备参考书。

在线课程 (Online Courses)
Vim Adventureshttps://vim-adventures.com/:Vim Adventures 是一个以游戏化的方式学习 Vim 基础操作的在线平台。通过玩游戏,您可以轻松掌握 Vim 的移动、编辑等基本命令,寓教于乐。
付费平台 (如 Udemy, Coursera, Pluralsight 等):在 Udemy, Coursera, Pluralsight 等在线教育平台上,也有许多高质量的 Vim 课程,涵盖从入门到进阶的各个层面。您可以根据自己的需求选择合适的课程进行学习。

邮件列表 (Mailing Lists)
vim_dev 邮件列表:这是 Vim 开发者的邮件列表,主要讨论 Vim 的开发、bug 修复、新功能讨论等技术性话题。如果您对 Vim 的底层实现和开发感兴趣,可以关注这个邮件列表。
vim 邮件列表:这是一个更广泛的 Vim 用户邮件列表,讨论各种与 Vim 使用相关的话题,包括技巧分享、问题求助、插件推荐等。

通过积极参与这些社区和利用这些资源,您可以不断提升 Vim 技能,解决遇到的问题,并与其他 Vim 爱好者建立联系,共同进步。Vim 社区的开放、共享和互助精神,是 Vim 持续发展和保持活力的重要动力。

14.2 Vim 常用命令速查表

Vim 的强大之处在于其丰富的命令集。熟练掌握常用命令是提高 Vim 使用效率的关键。以下是一个 Vim 常用命令速查表,按照功能类别进行组织,方便快速查找和记忆。

① 模式切换 (Mode Switching)

命令功能描述 (Description)
Esc进入 Normal 模式 (Enter Normal mode)
i在光标前进入 Insert 模式 (Insert before cursor)
a在光标后进入 Insert 模式 (Insert after cursor)
o在当前行下方插入新行并进入 Insert 模式 (Open new line below)
O在当前行上方插入新行并进入 Insert 模式 (Open new line above)
A在行尾进入 Insert 模式 (Append to line end)
I在行首进入 Insert 模式 (Insert at line start)
v进入 Visual 模式 (字符选择) (Enter Visual mode (character))
V进入 Visual Line 模式 (行选择) (Enter Visual Line mode)
Ctrl+v进入 Visual Block 模式 (块选择) (Enter Visual Block mode)
:进入 Command-line 模式 (Enter Command-line mode)
R进入 Replace 模式 (替换模式) (Enter Replace mode)

② 移动 (Motion)

字符级移动 (Character-wise Motion)

命令功能描述 (Description)
h左移一个字符 (Move left one character)
j下移一行 (Move down one line)
k上移一行 (Move up one line)
l右移一个字符 (Move right one character)

单词级移动 (Word-wise Motion)

命令功能描述 (Description)
w移动到下一个单词词首 (Next word start)
W移动到下一个字串词首 (Next WORD start)
e移动到当前单词词尾 (Word end)
E移动到当前字串词尾 (WORD end)
b移动到上一个单词词首 (Previous word start)
B移动到上一个字串词首 (Previous WORD start)
ge移动到上一个单词词尾 (Previous word end)
gE移动到上一个字串词尾 (Previous WORD end)

行内移动 (Line-wise Motion)

命令功能描述 (Description)
0移动到行首 (Beginning of line)
^移动到行首第一个非空白字符 (First non-blank character of line)
$移动到行尾 (End of line)
f{char}移动到下一个字符 {char} 出现的位置 (Find next {char})
F{char}移动到上一个字符 {char} 出现的位置 (Find previous {char})
t{char}移动到下一个字符 {char} 之前的位置 (Till next {char})
T{char}移动到上一个字符 {char} 之后的位置 (Till previous {char})
;重复上次 f, F, t, T 命令 (Repeat last find/till)
,反向重复上次 f, F, t, T 命令 (Repeat last find/till in reverse)

行间移动 (Line-wise Motion)

命令功能描述 (Description)
gg移动到文件首行 (First line of file)
G移动到文件末行 (Last line of file)
:nnG移动到第 n 行 (Go to line n)
H移动到屏幕顶行 (Top of screen)
M移动到屏幕中间行 (Middle of screen)
L移动到屏幕底行 (Bottom of screen)
Ctrl+u向上滚动半屏 (Scroll up half screen)
Ctrl+d向下滚动半屏 (Scroll down half screen)
Ctrl+b向上滚动一屏 (Scroll up one screen)
Ctrl+f向下滚动一屏 (Scroll down one screen)
{移动到上一个段落 (Previous paragraph)
}移动到下一个段落 (Next paragraph)
(移动到上一个句子 (Previous sentence)
)移动到下一个句子 (Next sentence)

标记与跳转 (Marks and Jumps)

命令功能描述 (Description)
m{char}设置标记 {char} (Set mark {char})
``跳转到标记 {char} 所在行首 (Jump to mark {char} line start)
'{char}跳转到标记 {char} 所在行首 (Jump to mark {char} line start)
跳转到上次编辑位置 (Jump to last edit position)
''跳转到上次编辑位置所在行首 (Jump to last edit position line start)
Ctrl+o跳转到上一个跳转位置 (Jump to older position in jump list)
Ctrl+i跳转到下一个跳转位置 (Jump to newer position in jump list)

③ 编辑 (Editing)

插入 (Insert)

命令功能描述 (Description)
i在光标前插入 (Insert before cursor)
a在光标后插入 (Append after cursor)
I在行首插入 (Insert at beginning of line)
A在行尾插入 (Append to end of line)
o在当前行下方插入新行 (Open line below)
O在当前行上方插入新行 (Open line above)

删除 (Delete)

命令功能描述 (Description)
x删除光标所在字符 (Delete character under cursor)
X删除光标前一个字符 (Delete character before cursor)
d{motion}删除 {motion} 范围内的文本 (Delete text object specified by {motion})
dd删除当前行 (Delete current line)
D删除光标到行尾的内容 (Delete to end of line)

修改 (Change)

命令功能描述 (Description)
r{char}替换光标所在字符为 {char} (Replace character under cursor with {char})
R进入 Replace 模式 (Enter Replace mode)
c{motion}修改 {motion} 范围内的文本 (Change text object specified by {motion})
cc修改当前行 (Change current line)
C修改光标到行尾的内容 (Change to end of line)
s替换光标所在字符 (Substitute character under cursor)
S替换当前行 (Substitute current line)

复制与粘贴 (Yank and Paste)

命令功能描述 (Description)
y{motion}复制 {motion} 范围内的文本 (Yank text object specified by {motion})
yy复制当前行 (Yank current line)
Y复制当前行 (Yank current line)
p在光标后粘贴 (Paste after cursor)
P在光标前粘贴 (Paste before cursor)

撤销与重做 (Undo and Redo)

命令功能描述 (Description)
u撤销 (Undo)
Ctrl+r重做 (Redo)
.重复上次修改 (Repeat last change)

大小写转换 (Case Conversion)

命令功能描述 (Description)
~切换光标所在字符大小写 (Toggle case of character under cursor)
gu{motion}{motion} 范围内的文本转换为小写 (Make text object specified by {motion} lowercase)
gU{motion}{motion} 范围内的文本转换为大写 (Make text object specified by {motion} uppercase)

缩进与对齐 (Indentation and Alignment)

命令功能描述 (Description)
>增加缩进 (Indent)
<减少缩进 (Unindent)
= {motion}自动缩进 {motion} 范围内的代码 (Auto-indent text object specified by {motion})
==自动缩进当前行 (Auto-indent current line)

④ 搜索与替换 (Search and Replace)

搜索 (Search)

命令功能描述 (Description)
/pattern向下搜索 pattern (Search forward for pattern)
?pattern向上搜索 pattern (Search backward for pattern)
n查找下一个匹配项 (Next match)
N查找上一个匹配项 (Previous match)
*向下搜索光标所在单词 (Search forward for word under cursor)
#向上搜索光标所在单词 (Search backward for word under cursor)

替换 (Replace)

命令功能描述 (Description)
:s/old/new替换当前行第一个 oldnew (Substitute first occurrence of old with new in current line)
:s/old/new/g替换当前行所有 oldnew (Substitute all occurrences of old with new in current line)
:%s/old/new/g替换整个文件所有 oldnew (Substitute all occurrences of old with new in entire file)
:%s/old/new/gc替换整个文件所有 oldnew,每次替换前询问 (Substitute all occurrences of old with new in entire file, with confirmation)

⑤ 文件操作 (File Operations)

命令功能描述 (Description)
:w保存文件 (Write file)
:w filename另存为 filename (Write file as filename)
:wq:x保存并退出 (Write and quit)
:q退出 (Quit)
:q!强制退出,不保存 (Quit without saving)
:e filename打开文件 filename (Edit file filename)
:tabnew filename在新标签页中打开文件 filename (Open file filename in new tab)
:split filename在新窗口中打开文件 filename (Open file filename in new split window)
:buffers:ls列出缓冲区 (List buffers)
:bnext:bn切换到下一个缓冲区 (Next buffer)
:bprev:bp切换到上一个缓冲区 (Previous buffer)
:bdelete:bd删除缓冲区 (Delete buffer)

⑥ 窗口与标签页 (Window and Tab Management)

窗口 (Windows)

命令功能描述 (Description)
:split:sp水平分割窗口 (Split window horizontally)
:vsplit:vs垂直分割窗口 (Split window vertically)
Ctrl+w s水平分割窗口 (Split window horizontally)
Ctrl+w v垂直分割窗口 (Split window vertically)
Ctrl+w w切换到下一个窗口 (Switch to next window)
Ctrl+w h/j/k/l切换到左/下/上/右窗口 (Switch to left/down/up/right window)
Ctrl+w c关闭当前窗口 (Close current window)
Ctrl+w o只保留当前窗口,关闭其他窗口 (Only keep current window, close others)
Ctrl+w =使所有窗口大小相等 (Make all windows equal size)
Ctrl+w _最大化当前窗口高度 (Maximize current window height)
Ctrl+w \|最大化当前窗口宽度 (Maximize current window width)

标签页 (Tabs)

命令功能描述 (Description)
:tabnew:tabnew filename新建标签页 (New tab)
:tabedit filename在新标签页中打开文件 (Edit file in new tab)
:tabnext:tabn切换到下一个标签页 (Next tab)
:tabprev:tabp切换到上一个标签页 (Previous tab)
:tabfirst:tabf切换到第一个标签页 (First tab)
:tablast:tabl切换到最后一个标签页 (Last tab)
:tabclose:tabc关闭当前标签页 (Close current tab)
:tabonly:tabo只保留当前标签页,关闭其他标签页 (Only keep current tab, close others)
:tabmove {N}将当前标签页移动到第 N 个位置 (Move current tab to position N)

⑦ 宏 (Macros)

命令功能描述 (Description)
q{char}开始录制宏到寄存器 {char} (Start recording macro to register {char})
q结束宏录制 (Stop recording macro)
@{char}执行寄存器 {char} 中的宏 (Execute macro in register {char})
@@重复执行上次执行的宏 (Repeat last executed macro)
{number}@ {char}执行寄存器 {char} 中的宏 {number} 次 (Execute macro in register {char} {number} times)

⑧ 其他常用命令 (Other Useful Commands)

命令功能描述 (Description)
:help {topic}打开帮助文档,查看 {topic} 的帮助 (Open help for {topic})
:!执行外部命令 (Execute external command)
:set option设置 Vim 选项 (Set Vim option)
:set nooption取消设置 Vim 选项 (Unset Vim option)
:set invoption反转 Vim 选项 (Invert Vim option)
:map {lhs} {rhs}创建键盘映射 (Map key sequence {lhs} to {rhs})
:noremap {lhs} {rhs}创建非递归键盘映射 (Non-recursive map key sequence {lhs} to {rhs})

这个速查表涵盖了 Vim 中最常用的命令,但 Vim 的命令远不止这些。随着您对 Vim 的深入学习和实践,您会发现更多强大的命令和技巧,不断提升您的编辑效率。建议您将这个速查表打印出来,放在手边,随时查阅,并逐步将这些命令融入到您的日常 Vim 使用中。

14.3 Vim 学习进阶路线图

Vim 的学习曲线相对陡峭,但一旦掌握,将会成为您提升文本编辑效率的强大工具。本节为不同阶段的 Vim 用户提供一个学习进阶路线图,帮助您系统地提升 Vim 技能。

① 初级阶段 (Beginner Level):Vim 新手入门

目标 (Goals)
▮▮▮▮⚝ 熟悉 Vim 的基本概念和模式 (Normal, Insert, Visual, Command-line)。
▮▮▮▮⚝ 掌握基本的移动命令 (hjkl, w, b, e, 0, $, gg, G)。
▮▮▮▮⚝ 掌握基本的编辑命令 (i, a, o, x, d, c, y, p, u, Ctrl+r, .)。
▮▮▮▮⚝ 能够进行基本的文件操作 (:w, :q, :e)。
▮▮▮▮⚝ 能够使用 :help 命令查找帮助文档。

学习资源 (Learning Resources)
▮▮▮▮⚝ vimtutor 命令 (Vim 自带的交互式教程)。
▮▮▮▮⚝ Vim Adventures (游戏化学习平台)。
▮▮▮▮⚝ 《Mastering Vim Quickly》 (入门书籍)。
▮▮▮▮⚝ 在线 Vim 基础教程 (如 OpenVim, Vimium 教程等)。

实践建议 (Practice Tips)
▮▮▮▮⚝ 坚持每天使用 Vim 进行文本编辑,即使是简单的任务也尽量用 Vim 完成。
▮▮▮▮⚝ 重点练习基本移动和编辑命令,形成肌肉记忆。
▮▮▮▮⚝ 遇到不明白的命令或操作,及时查阅 :help 文档。
▮▮▮▮⚝ 避免过度依赖鼠标,尽量使用键盘操作。

进阶标志 (Advancement Criteria)
▮▮▮▮⚝ 能够熟练使用基本移动和编辑命令进行文本输入和修改。
▮▮▮▮⚝ 能够独立完成简单的文件编辑任务。
▮▮▮▮⚝ 对 Vim 的基本操作感到舒适和自信。

② 中级阶段 (Intermediate Level):效率提升与技巧掌握

目标 (Goals)
▮▮▮▮⚝ 深入理解 Vim 的模式和操作符-动作 (operator-motion) 语法。
▮▮▮▮⚝ 掌握高效的移动技巧 (单词级、行内、段落、屏幕滚动、标记跳转)。
▮▮▮▮⚝ 熟练运用 Visual 模式进行文本选择和块操作。
▮▮▮▮⚝ 掌握寄存器 (registers) 的概念,灵活运用剪切、复制、粘贴。
▮▮▮▮⚝ 掌握基本的搜索和替换命令 (/, ?, :s)。
▮▮▮▮⚝ 了解 .vimrc 配置文件,进行简单的个性化配置。

学习资源 (Learning Resources)
▮▮▮▮⚝ 《Practical Vim》 (进阶书籍)。
▮▮▮▮⚝ Vim Awesome (插件发现平台)。
▮▮▮▮⚝ Vim subreddit (Reddit Vim 社区)。
▮▮▮▮⚝ Stack Overflow (Vim 相关问题解答)。
▮▮▮▮⚝ 高级 Vim 教程 (如 Derek Wyatt 的 VimCast 系列)。

实践建议 (Practice Tips)
▮▮▮▮⚝ 学习和练习各种高效的移动命令组合,提高移动效率。
▮▮▮▮⚝ 深入理解 Visual 模式的各种用法,熟练进行文本选择和操作。
▮▮▮▮⚝ 学习使用文本对象 (text objects) 和操作符-动作语法,提高编辑效率。
▮▮▮▮⚝ 开始配置 .vimrc 文件,根据个人习惯定制 Vim。
▮▮▮▮⚝ 尝试使用一些常用的 Vim 插件,如文件管理器、代码补全等。

进阶标志 (Advancement Criteria)
▮▮▮▮⚝ 能够高效地进行文本编辑,操作速度明显提升。
▮▮▮▮⚝ 能够熟练运用 Visual 模式和文本对象进行复杂编辑操作。
▮▮▮▮⚝ 能够根据个人需求进行简单的 Vim 配置和插件使用。
▮▮▮▮⚝ 对 Vim 的操作逻辑和设计哲学有更深入的理解。

③ 高级阶段 (Advanced Level):深度定制与插件开发

目标 (Goals)
▮▮▮▮⚝ 掌握正则表达式 (regular expressions) 在 Vim 中的应用,进行高级搜索和替换。
▮▮▮▮⚝ 熟练进行多文件操作 (缓冲区、窗口、标签页管理)。
▮▮▮▮⚝ 掌握宏 (macros) 的录制和使用,实现自动化操作。
▮▮▮▮⚝ 深入理解 Vimscript 编程,能够编写自定义函数、命令和插件。
▮▮▮▮⚝ 掌握高级 Vim 配置技巧,打造高度个性化的 Vim 环境。
▮▮▮▮⚝ 了解 Vim 的架构和扩展机制,能够解决复杂的 Vim 使用问题。

学习资源 (Learning Resources)
▮▮▮▮⚝ 《Learn Vimscript the Hard Way》 (Vimscript 教程)。
▮▮▮▮⚝ Vim 官方帮助文档 (深入学习)。
▮▮▮▮⚝ Vim-dev 邮件列表 (了解 Vim 开发动态)。
▮▮▮▮⚝ GitHub 上的 Vim 插件源码 (学习插件开发)。
▮▮▮▮⚝ VimConf 等 Vim 社区活动 (交流学习)。

实践建议 (Practice Tips)
▮▮▮▮⚝ 深入学习正则表达式,并将其应用于 Vim 的搜索和替换操作中。
▮▮▮▮⚝ 学习使用宏进行重复性任务的自动化处理。
▮▮▮▮⚝ 系统学习 Vimscript 编程,尝试编写简单的 Vim 插件。
▮▮▮▮⚝ 研究和学习优秀的 Vim 插件源码,借鉴插件开发经验。
▮▮▮▮⚝ 积极参与 Vim 社区,与其他 Vim 用户交流学习心得。

进阶标志 (Advancement Criteria)
▮▮▮▮⚝ 能够灵活运用正则表达式进行复杂的文本处理任务。
▮▮▮▮⚝ 能够使用宏和 Vimscript 自动化日常编辑工作。
▮▮▮▮⚝ 能够根据自身需求开发或定制 Vim 插件。
▮▮▮▮⚝ 对 Vim 的内部机制和扩展能力有深入的理解。
▮▮▮▮⚝ 成为 Vim 社区的积极贡献者,能够帮助他人解决 Vim 使用问题。

④ 专家阶段 (Expert Level):Vim 大师与持续精进

目标 (Goals)
▮▮▮▮⚝ 精通 Vim 的所有功能和技巧,达到“指尖流淌”的境界。
▮▮▮▮⚝ 能够根据不同场景和需求,灵活运用 Vim 解决各种文本编辑问题。
▮▮▮▮⚝ 深入理解 Vim 的设计哲学和最佳实践,形成自己的 Vim 工作流。
▮▮▮▮⚝ 持续关注 Vim 社区的最新发展,不断学习和精进 Vim 技能。
▮▮▮▮⚝ 成为 Vim 领域的专家,能够分享经验、著书立说、推动 Vim 社区发展。

学习资源 (Learning Resources)
▮▮▮▮⚝ Vim 源码 (深入理解 Vim 实现原理)。
▮▮▮▮⚝ 顶级 Vim 专家博客和分享 (学习大师经验)。
▮▮▮▮⚝ 参与 Vim 开发和社区维护 (贡献社区)。
▮▮▮▮⚝ 持续关注文本编辑技术和工具的发展趋势 (保持前沿)。

实践建议 (Practice Tips)
▮▮▮▮⚝ 将 Vim 应用于各种工作场景,不断挑战和拓展 Vim 的应用范围。
▮▮▮▮⚝ 深入研究 Vim 的高级特性和技巧,挖掘 Vim 的潜力。
▮▮▮▮⚝ 积极参与 Vim 社区的讨论和贡献,分享自己的 Vim 经验和技巧。
▮▮▮▮⚝ 持续学习和探索新的文本编辑技术和工具,保持技术敏感度和学习热情。

进阶标志 (Advancement Criteria)
▮▮▮▮⚝ 成为公认的 Vim 专家,在 Vim 社区具有影响力。
▮▮▮▮⚝ 能够熟练运用 Vim 解决各种复杂的文本编辑和代码处理问题。
▮▮▮▮⚝ 能够根据自身需求和技术发展趋势,持续优化和改进 Vim 工作流。
▮▮▮▮⚝ 能够为 Vim 社区做出重要贡献,推动 Vim 的发展和普及。

这个 Vim 学习进阶路线图并非一成不变,您可以根据自己的实际情况和学习进度进行调整。重要的是保持学习的热情和实践的毅力,相信您最终能够掌握 Vim 这款强大的文本编辑器,并将其应用于您的工作和生活中,大幅提升效率和创造力。

ENDOF_CHAPTER_