Neovim 配置与学习

Keywords: #技术 #Neovim
Table of Contents

Setup

安装 Neovim

Home - Neovim | Neovim/Neovim (github.com)

打开 Neovim 官网或者 GitHub 主页,根据指引下载对应操作系统的最新版。可以下载安装包进行安装,也可以使用命令行进行安装。

安装完成后,将 Neovim 添加进系统的环境变量中。

在命令行中输入 nvim ,出现欢迎界面说明 Neovim 安装成功。

image.png

配置 LazyVim

LazyVim 是一个 Neovim 的一键 Setup 方案,它内置了一些基础的插件,配置了人性化的快捷键。同时 LazyVim 也是一个 Neovim 的包管理器,可以快捷方便地管理 Neovim 的各种插件。

🚀 Getting Started | LazyVim | LazyVim(github.com)

打开 LazyVim 官网或者 GitHub 主页,进行 LazyVim 的安装。

在安装之前,LazyVim 还需要一些依赖配置,如 Neovim、Git、Nerd Font 字符字体、C 语言编译器以及一个支持真颜色的终端等。

image.png

安装好各种所需要的依赖环境,就可以进行 LazyVim 的安装

  • Linux 环境
# required
mv ~/.config/nvim{,.bak}

# optional but recommended
mv ~/.local/share/nvim{,.bak}
mv ~/.local/state/nvim{,.bak}
mv ~/.cache/nvim{,.bak}

# Clone the starter
git clone https://github.com/LazyVim/starter ~/.config/nvim

# Remove the `.git` folder, so you can add it to your own repo later
rm -rf ~/.config/nvim/.git

# Start Neovim!
nvim
  • Windows 环境

Windows 下 Neovim 的配置文件应该存放在 C:\Users\YOUR_USERNAME\AppData\Local\nvim 中,如果该目录下不存在 nvim 文件夹,新建一个 nvim 文件夹即可。

nvim 文件夹中执行克隆仓库命令:

git clone https://github.com/LazyVim/starter

将其中的 lua 文件夹和 init.lua 移到 nvim 根目录中,其余文件删除即可。目录结构为:

nvim
│  init.lua
└─lua
    ├─config
    │      autocmds.lua
    │      keymaps.lua
    │      lazy.lua
    │      options.lua
    └─plugins
            example.lua

重新打开 Neovim 会出现 LazyVim 的初始化界面,在初始化界面会自动下载一些基本插件,等待插件下载完成。如果因为网络问题导致插件下载失败,可以尝试重启 Neovim,或者按下字母 I 重新安装。完成后按 q 来到 LazyVim 的欢迎界面。如果出现图标乱码,请安装 Nerd 字体

image.png

输入 : 打开命令行,输入 LazyHealth 检查插件是否工作正常。使用 Ctrl + u / d 可以上下快速浏览。

image.png

可以看到有一些 ERROR 出现,比如 Grugfar ,这是因为没有安装 live grep ,后续会安装。

为了方便后续在 Windows 环境下使用 Neovim,可以在终端中新建一个 Neovim 配置,方便之后一键打开,也可以设置打开终端默认使用 Neovim。

image.png

Mode & Register

Neovim 的四大编辑模式与寄存器

Mode 模式

Neovim 共有四大模式:

  1. Normal Mode
  2. Insert Mode
  3. Visual Mode
  4. Ex Mode

image.png

其中 Normal Mode 是默认模式,光标为方块状显示在文本区,此时按下 i 等键进入 Insert Mode。在 Insert Mode 中光标为竖线,界面左下角会显示 Insert 字样。输入完文本后,按下 ESC 键可以返回 Normal Mode

接下来可以按下 v 键进入 Visual Mode,等同于在记事本中框选一段文本的模式,此时可针对选中的文本进行删除拷贝等操作,操作完成后会自动返回 Normal Mode

最后,按下 : 键就会进入 Ex Mode,光标会移动到左下角位置,此时可以输入批处理命令或者是保存退出查找替换等操作。

Normal Mode 提供的关键键和操作很多,我们不需要全部记住。其中最常用的功能包括文档的浏览跳转、复制粘贴、撤销重做等。


实际操作演示

进入命令行使用 nvim mode.md 创建 mode.md 文件,默认打开文件进入 Normal Mode 。

按下 i 键进入 Insert Mode,可以在文本区输入文本。除此之外,还有多种方式从 Normal Mode 进入 Insert Mode,如按下 o 键,在光标下方另起一行进入 Insert Mode,按下 O 键,在光标上方另起一行进入 Insert Mode,可通过 Open 单词首字母辅助记忆。

image.png

Insert Mode 操作

Insert Mode 中的常用快捷键

  • ←↓↑→方向键:控制光标移动
  • Ctrl + ↑←↓→方向键 :快速移动光标,即按单词移动
  • BS 退格键:删除字符
  • Ctrl + w :删除单词
  • Ctrl + u :删除光标前的所有当前行的字符

Normal Mode 操作

从 Normal Mode 到 Insert Mode 的主要快捷键

  • o:在光标下方另起一行进入 Insert Mode,open
  • O:在光标上方另起一行进入 Insert Mode,open
  • a:在光标处字母的右侧进入 Insert Mode,append
  • A:在光标处所在行行尾进入 Insert Mode,append
  • i:在光标处字母的左侧进入 Insert Mode
  • I:在光标处所在行行首进入 Insert Mode

Normal Mode 中的光标移动快捷键

  • h j k l:代替方向键实现光标的左下上右←↓↑→
  • w b:按下一个上一个单词词首快速移动光标,word before
  • e:按下一个单词词尾快速移动光标,end
  • 数字 + 以上三种操作:如向上移动 2 行按 2k,向右移动 5 个单词按 5w,向左移动 10 个字符按 10h
  • 0:“硬”行首,即光标跳转到行首第 1 列,无论第 1 列有无字符
  • ^:“软”行首,即光标跳转到行首首字符,不一定是第 1 列
  • $:光标跳转到行尾
  • f + 字符:对光标的所有字符进行查找,有多个字符可使用 , ; 进行前后光标快速跳转,find
  • F + 字符:对光标的所有字符进行查找,有多个字符可使用 , ; 进行前后光标快速跳转,find
  • t + 字符 / T + 字符:与 f 功能类似,找到指定字符的前一个字符,till

Normal Mode 中的复制粘贴快捷键

  • y + 快捷键:复制字符,根据操作符的不同,复制字符的范围不同,yank
  • Y:复制从光标处到所处行末尾的字符
  • yy:复制光标所处当前行的所有字符,可组合数字向下复制多行,如 6yy 向下复制 6 行字符
  • p:在光标所处行的下方新开一行粘贴复制的内容,可组合数字复制多次,如 100p 可粘贴 100 次
  • P:在光标所处行前粘贴复制的内容,可组合数字复制多次,如 100p 可粘贴 100 次

补充:Operator-pending Mode 操作符待处理模式。在 Normal Mode 下仅仅按下 y 键是不能进行字符的复制操作,此时只是进入了 Operator-pending Mode 中,想要完成复制操作,还需要按下其他有效按键,y + ? = combo

Operator-pending Mode 操作符待处理模式的常用 combo 包括以上介绍的 Insert Mode 中的所有快捷键组合,y + j/k/h/l/w/b/e/f/t/0/^/$/G/gg…… = combo

比如:

  • y + l:复制光标后的一个字符
  • y + k:复制光标当前行和上一行字符
  • y + w / y + e:复制光标所处位置到单词末尾的字符
  • y + aw / y + iw:复制光标所处位置的单词,iw 不会包含周边的空格,而 aw 会包含单词末尾的空格
  • y + 2w / y + 2e:复制光标所处位置到第 2 个单词末尾的字符
  • y + 2aw / 2y + aw:复制光标所处位置往后的 2 个单词,会包含末尾的空格
  • y + 3j / 4yy:复制包含光标所在行的下方 4 行字符
  • y + 10l:复制光标右侧的 10 个字符
  • y + t + ,:复制光标后方到第一个 , 字符前的所有字符,不包含 ,
  • y + f + ,:复制光标后方到第一个 , 字符前的所有字符,包含 ,
  • y + $ / Y:复制从光标处到所处行末尾的字符

总结来说,y + 光标移动快捷键 实现光标移动到哪就复制到哪。这种操作模式就是 operator + motion = action 操作符+动作指令=操作,这也是 vim 强大的地方。

Normal Mode 中的阅读浏览快捷键

  • G:跳转到文本末尾
  • gg:跳转到文本开头
  • 行号 + G:跳转到指定行号,可配合 数字 + 方向键hjkl 快速相对跳转
  • Ctrl + u:向上跳转半个屏幕,up,十分接近鼠标滚动效果
  • Ctrl + d:向下跳转半个屏幕,down,十分接近鼠标滚动效果
  • Ctrl + f:向上跳转整个屏幕,font
  • Ctrl + b:向下跳转整个屏幕,back

Normal Mode 中的文本编辑快捷键

  • d:删除字符 delete,与 y 复制相同,可以和多种光标移动快捷键组成 combo
    • d + aw / d + iw:删除光标所处位置的单词,iw 不会包含周边的空格,而 aw 会包含单词末尾的空格
    • 以上所有对于 y 的组合操作都可以用于 d
  • D:删除从光标处到所处行末尾的字符
  • dd:删除光标所处当前行的所有字符,可组合数字向下复制多行,如 6dd 向下删除 6 行字符
  • c:修改字符 change,与 d 删除类似,区别在于使用 c 键删除字符后会直接进入 Insert Mode,可少按一次 i
  • r:替换当前光标所在的字符, replace
  • R:进入替换模式,可以像 Insert Mode 一样编辑文本,但是会替换当前光标所在的字符,replace
  • >> / <<:向右缩进或向左缩进,可以在前面加上数字,指定缩进的距离,如 4>> 向右缩进 4 格
  • g + u / g + U:转成为小写或大写字符,与 y 复制相同,可以和多种光标移动快捷键组成 combo
    • g + u + aw / g + u + iw:将光标所处位置的单词全部变为小写字符
    • g + U + aw / g + U + iw:将光标所处位置的单词全部变为大写字符
    • 以上所有对于 y 的组合操作都可以用于 gu / gU
  • ~:切换大小写字符,不能组合 combo
  • x:删除光标所处的单个字符

Normal Mode 中的撤销重做快捷键

  • u:撤销之前的操作,undo
    • 撤销以每个文本操作为一个单元,比如 d + awp 等等
    • 从离开 Normal Mode 到重新进入 Normal Mode 之间的操作也作为一个撤销单元,比如在 Insert Mode 中进行文本编辑的操作
    • 因此,我们可以通过特定的操作来控制撤销的范围,比如在 Insert Mode 中需要换行输入文本,此时使用 Esc 退出 Insert Mode 再利用 o 键新起一行来代替换行操作,可以缩小撤销的范围
  • Ctrl + r:重做之前的撤销操作,redo

Visual Mode 操作

在 Normal Mode 中按下 v 键可以进入 Visual Mode。进入之后可以像在 Normal Mode 中一样移动光标或者像 Operator-pending Mode 输入动作指令,从而调整选择范围。调整好选取之后可以之间按下操作符进行文本操作,如Normal Mode 中的部分文本编辑快捷键

除此之外,在 Normal Mode 中还可以按下 V 键进入 V-LINE 模式,即面向行的 Visual Mode。按 Ctrl + v 进入 V-BLOCK 模式,即面向列块的 Visual Mode,确定好选区之后可以按下 i 键,批量给每一行批量添加文本。

Visual Mode 中的常用快捷键

  • v:从 Normal Mode 进入 Visual Mode
  • V:从 Normal Mode 进入面向行的 Visual Mode,V-LINE 模式
  • Ctrl + v:从 Normal Mode 进入面向列块的 Visual Mode,V-BLOCK 模式
  • o:切换选区的移动端,即选区开头和末尾切换
  • ←↓↑→ / hjkl:左下上右移动光标选择选区
  • 常用的文本编辑操作符
    • d:删除选区内容
    • c:删除选区内容并进入 Insert Mode
    • y:复制选区内容,操作完成后会返回 Normal Mode,此时按下 g + v 可以返回刚才的选区
    • p:粘贴并覆盖选区内容
  • ……

Ex Mode 操作

在 Normal Mode 中可以按下 : 进入 Ex Mode,然后可以输入命令并按 Enter 执行。

按下 :q 可以打开 Ex 命令历史,在命令历史中,可以像 Normal Mode 中编辑文本一样编辑 Ex 命令。将光标移动到想执行的命令上,按 Enter 可直接执行。

也可以按下 /? 进入 Ex Mode ,调出查找提示符,此时输入任何文本都会进行全文匹配,按下 Enter 开始跳转,按下 n 键跳转到下一个匹配项,按下 N 键跳转到上一个匹配项。

Ex Mode 中的常用命令

  • ::从 Normal Mode 进入 Ex Mode
  • :q:打开 Ex 命令历史
  • /?:从 Normal Mode 进入 Ex Mode 并调出查找提示符
  • q:退出指令,quit
  • q!:强制退出指令
  • w:保存指令,write
  • wq:保存并退出
  • Shell 命令,用 ! 开头,以下为 Linux 命令
    • !ls:列出当前目录
    • !pwd:列出当前路径
    • %!sort -r:排序操作
    • r!date:打印时间操作
    • r!date "+\%s":打印时间戳操作
  • ……

Register 寄存器

寄存器主要用于临时储存剪切和复制的文本,最常用的有:

  • 无名寄存器 Unnamed register,用 " 表示
  • 有名寄存器 Named register,用 a - z 表示
  • 复制寄存器 Yank register,用 0 表示
  • 表达式寄存器 Expression register,用 = 表示

寄存器的规则

调用寄存器前需要按下 "

无名寄存器:当我们使用 c 修改d 删除一段内容时,被取缔的内容会自动存放到无名寄存器中,按下 " 可查看,使用 p 进行粘贴时,会默认粘贴无名寄存器中最新的内容。

在使用 y 复制一段内容时,复制的内容不仅会存放到无名寄存器,也会存放在复制寄存器

有名寄存器a - z 一共 26 个,不会自动存储文本,如果想使用有名寄存器,可以在输入操作符之前加上双引号 "a - z 之一的有名寄存器代号,如 "a + yy 会复制当前行内容并存放到 a 寄存器中,同样按下 "a + p 会将 a 寄存器中的内容粘贴到文本中

复制寄存器:最常用的寄存器是复制寄存器:0,当我们进入 Visual Mode 进行多次粘贴时,会发现第二次粘贴的文本是第一次粘贴时被取缔的文本,原因是第一次粘贴时无名寄存器中存的是我们最初复制的内容,但粘贴完成后无名寄存器里的文本也会被覆盖的文本取缔,即 p 粘贴操作也会覆盖无名寄存器,内容为粘贴时被覆盖的文本。这时候我们需要使用 :0复制寄存器,才可以继续粘贴我们复制的文本。

表达式寄存器:进入 Ex Mode,用于简单表达式的计算,或者调用一些函数,如 strftime("%Y") 会将年份打印在光标处并进入 Insert Mode。

在 Insert Mode 下也可以使用寄存器,按下 Ctrl + r + 寄存器符号 即可,如 Ctrl + r + 0 可以粘贴 Normal Mode 下复制的文本,Ctrl + r + = 可唤起表达式寄存器。

练习题

习题一

# 克隆仓库
git clone https://github.com/zhangddjs/pde-tutorial.git
# 切换到习题目录
cd pde-tutorial/neovim/2modenregister/
# 打开练习说明
neovim practice_cn.md
# 使用垂直分屏
:vs
# 左右分屏切换
`Ctrl + h` `Ctrl + l`
# 打开text文件
:e text
1. r + i + n
2. diw + 5j + ve + p + 5k + p
3. dl + e + p
4. r7  /  v + l + c + 8
5. gu + iw
6. yiw + ve + p
7. d3j / 4dd
8. line('.') + G + p

讲解

  1. xp :使用 x 删除 n,再使用 p 把 n 粘贴到 i 后面
  2. dd + 光标移动 + p:使用 dd 删除第 5 行,4j 将光标移动到第 9 行,p 粘贴到第 9 行。再用同样操作将原来第 10 行删除并粘贴到第 5 行。
    1. 使用 V 进入面向行的 Visual Mode 直接进行替换。
    2. 进入 Ex Mode,使用 m10 可以将第 5 行移动到第 10 行,使用 m4 将原先第 10 行移动到第 5 行
  3. x + e + p:将开头的 6 删除,将光标移动到词尾并粘贴
    1. 使用 v + e + d + P,进入 Visual Mode 将 line 字符删除并粘贴到开头
    2. 使用 x 删除开头的 6,使用 A 从末尾进入 Insert Mode,按下 Ctrl + r + " 使用无名寄存器粘贴 6 到末尾
  4. 第 7 行使用 x:删除 - 号,也可以使用 14 + Ctrl + a,让末尾数字 -7 与 14 相加,得到 7;第 8 行也是类似操作 92 + Ctrl + x 让末尾数字与 92 相减
  5. guaw:转化单词变为小写
    1. 使用 V 进入 Visua Mode,按下 ~ 整行转化大小写
  6. ye + v + iq + "0 + p:复制 line,v 进入 Visual Mode 使用 iq 选择引号中的字符,使用 "0 + p 复制寄存器中的内容粘贴替换,使用 vib 选中括号内的字符,同样使用 "0 + p 复制寄存器中的内容粘贴替换,也可以使用 vi{vi< 来选择指定括号内的字符,使用复制寄存器粘贴
  7. V + 3j + d:使用 Visual Mode 选择 4 行并删除
    1. 4dd:在 11 行删除 4 行
    2. :11,14d:在 Ex Mode 中使用命令删除
  8. G + A + Ctrl + R + = + line('.'):跳转到最后一行从末尾进入 Insert Mode,使用表达式寄存器,使用 line('.') 获取当前行行号并粘贴

思考题

# 创建水平分屏
:split
# 编辑text2
e text2

讲解

按照直觉,我们应该进入 Visual Mode 进行批量编辑,但是无论是面向行还是面向列块的 Visual Mode 都不能满足题目要求。Ctrl + v 进入面向列块的模式,选中所有行按下 A 进入 Insert Mode,这时候的光标会按照最长那一行的末尾对齐排列,并不符合要求。

技巧,在 Ctrl + v 进入面向列块的 Visual Mode 中,可以按下 $ 指选择的每一行都截止到行尾,此时 A 进入 Insert Mode 输入的字符就会出现在每一行的结尾。

Philosophy

Neovim 的使用哲学:使修改可重复

Neovim 中的“瑞士军刀” :. 键的使用

在平时我们处理文本时经常会遇到一些重复性的工作,例如多次删除/添加相同字符,重复执行相同的操作等,在传统的文本编辑器中,这需要手动重复操作,没有很好的办法,然而在 Neovim 中则提供了一种高效的解决方案—— Dot . 键。

Dot . 键可以重复上一次的操作,成倍提升效率,也使操作更加流畅。

修改的定义

Dot 键的官方描述是重复上一次修改 Repeat last change,需要注意的是 Neovim 中定义的修改单位是什么。

正如在 Mode & Register 中提到的操作符待处理模式 Operator + Motion = Action 的公式,在 Normal Mode 下,大部分的文本编辑操作,如 daw yep 等都算作是一次修改,因此可以使用 Dot . 键进行重复。同样的,每次重复和修改操作都可以用 u 进行撤销。

然而,在 Insert Mode 下修改的定义有所不同,只有在进入 Insert Mode 开始到退出 Insert Mode 中的所有操作才算作是一次修改,并且在 Insert Mode 编辑文本的过程中移动了光标,修改的状态也会被重置,即只有最后一次光标移动之后的操作才算作一次修改

虽然以上的 Dot 键介绍很简单,在这只是开始。针对同一个文本操作,Neovim 可以通过多种不同的快捷键组合方式来实现,虽然这极具灵活性,但也要求我们在组合快捷键时掌握一些技巧,来充分实现修改的可重复,真正发挥 Dot 键的威力,这便是 Neovim 的使用哲学

可重复修改的技巧

  1. 技巧 1减少无关移动 Reduce Unnecessary Movements

回忆上一节的思考题,我们需要给不同长短的各行末尾添加 ok 字符。

一种可行的方法是使用 $ 到行尾,再按 a 插入 ok,然后使用 j$. 重复操作,但是这种方式仍显低效,因为每行都需要重复按 $

但是如果使用的是 A 而不是 $a,就可以将移动操作记录到 . 中,使用 . 就可以重复操作,接下来就可以使用 j. 让每行末尾都添加相同的字符。这是因为 A 同时移动光标并进入 Insert Mode,这并不会重置 Neovim 定义的一次修改操作。

下面是常用可重复快捷键的替换:

  • $a ---> A 行尾插入
  • ^i ---> I 行首插入
  • ko ---> O 向上新开一行插入
  • d$a / Da ---> C 删除光标后字符到行尾并插入
  • ……
  1. 技巧 2善用 ai Use a and i Wisely

当我们光标在一个单词末尾,想删除这个单词时,可以使用 dbx 或者 bdw,虽然这两种操作都起作用但是却无法使用 . 键重复,因为在 dbx 中实际上有两个修改行为,. 只记录了最后一个 x 的修改行为,按下 . 只能删除单个字符。同样 bdw 中,开头的 b 只是单纯移动了光标,不能算作是一个修改,因此 . 键只记录了 dw,故只能删除单词在光标之后的部分。

为了实现操作的完整可重复性,这里推荐使用 diw 或者 daw,这样不论光标在单词的哪个位置都可以删除整个单词,并且可以使用 . 键重复。

类似的操作还有:

  • diq:删除引号内的字符 delete inside quote
  • dab: 删除括号周围(包括 ()[]{} 括号)的字符 delete around block
  • ……
  1. 技巧 3只在必要时使用可视命令 Use Visual Mode Only When Necessary

我们在删除当前单词时,除了通过 diw / daw,还可以使用 vawd,但是这是使用 . 键在另一个单词上重复操作,效果往往不如预期,这是因为 . 在重复 Visual Mode 中的操作时会按照上次高亮文本的长度产生作用,因此对不同长度的单词只能删除固定长度的字符。

因此 . 键只有在处理面向行的 Visual Mode 时效果才更加

所以在一般情况下,能用操作符完成的命令,就避免使用可视模式下的命令,如:

  • vawd ---> daw:删除单词
  • viwc ---> ciw:删除单词并进入 Insert Mode
  • viqc ---> ciq:删除引号内的字符并进入 Insert Mode
  1. 技巧 4以退为进 Step Back to Move Forward

如果我们要给当前行的每个空格前后加上字母 a,进入插入模式后,在坐标插入 a 后避免不了要将光标移动到另一边,光标一旦移动,操作就变得不可重复。

这时可以借助“以退为进”的技巧,进入插入模式后,我们先删除空格,再输入 a a,这样就可以完成一个可重复的操作,接下来只需要 f .;.;.;…… 就可以完成后续空格周围添加 a 的操作。

  1. 技巧 5让移动可重复 Make Movements Repeatable

回顾前几个技巧可以发现,一个理想的 Dot 操作通常伴随着可重复的移动指令,比如 j.j.j.j. w.w.w.w. ;.;.;.;. 等。除此之外,还可以在单词上按下 * 进入单词匹配模式,按下 *n 在相同单词之间跳转,同样可以和 Dot 键组合成 *.*.*.*. 或者 n.n.n.n.

像以上这种,一次按键用于移动,另一次按键执行的编辑模式,也被称为“Dot 范式. pardigm

练习题

practice 1

  1. 方法一:使用 Ctrl + v 加上方向键选中日期,按下 3 Ctrl a
  2. 方法二:使用 Dot 键,在第一行的日期上执行 3 Ctrl a 后,按两次 j.

3 Ctrl a 是给当前数字加上 3;3 Ctrl x 是给当前数字减去 3

这样的操作在上一节中的练习题也有涉及

practice 2

  1. 方法一(错误):使用 Ctrl v jj $ 选中三行末尾,使用 Ctrl R = line('.') 条件表达式寄存器,但是这样三行的行号都是 7,因此不对
  2. 方法二(错误):在第一行使用 A Ctrl R = line('.') 插入行号后,通过 Dot 键 j.j. 但是依旧是都是 7,效果不理想
  3. 方法三:常规方法,只能一行行手动输入行号

practice 3

  1. 方法一:以退为进的技巧,使用 f + 搜索加号,a 进入插入模式删除加号,输入 空格+空格,利用 Dot 键 ;.;.;.

practice 4

  1. 方法一:光标在长单词上,使用 ciw 删除单词并进入 Insert Mode ,输入 ( 会自动补全右括号,调用无名寄存器并粘贴删除的单词 Ctrl R " ,接着进入 Normal Mode 中使用 Dot 键 *.*.*.n.n.n. 匹配相同的字符串并替换。

practice 5

  1. 方法一(错误):参考 practice 4 中的方法,使用 ciw 删除单词并进入插入模式,输入左右括号,再调用无名寄存器粘贴单词,最后使用 w 来到下一个单词按下 Dot 键 . 重复操作。这时会发现粘贴的依然是第一个单词,效果并不理想。
  2. 方法二:手动添加左右括号

结合 practice 2 和 5 的经验,我们发现 Dot 键并不会记录 Insert Mode 下的寄存器命令,只会记录其执行结果

practice 6

  1. 方法一(错误):与上一节中的练习类似。先复制单词 yiw,使用 viq 选中引号内的单词,使用 "0 p ,再使用 w 来下一个单词按下 Dot 键 . 效果并不理想。

这时候回想技巧三,只在必要时使用可视模式。这里 Dot 键之所以失效,其实也是使用了 Visual Mode。

  1. 方法二:类似于 practice 4。先复制单词 yiw,使用 ciw 删除引号内的单词并进入插入模式,按下 Ctrl R 0 粘贴复制寄存器中的字符,接着使用 wl 等光标移动快捷键(不能使用 Visual Mode 快捷键来选中)移动光标到下一个单词,使用 Dot 键 . 重复操作 Wl.Wl.Wl.Wl.

综上这些练习题,我们发现虽然 Dot 键十分强大,但是还是有一些局限的情况,正如 practice 2 和 5 以及最后一题的 Visual Mode 情况,我们依旧只能通过手动输入,而 Dot 键并不起作用。

然而,Neovim 还有一个更强大的操作可以用来解决这些常用的固定的而不能很好使用 Dot 键的操作,这就是宏 Macro

Plugins

虽然 LazyVim 已经集成了很多使用的插件,但是我们仍然需要掌握 Neovim 的插件配置与使用,来实现插件的灵活管理。

本章节通过文件管理插件的例子来讲解以下内容:

  1. leader 键的作用
  2. 配置目录的结构
  3. File Explorer 插件的使用
  4. 插件控制台
  5. 插件更新,回滚,安装,卸载
  6. 快捷键映射

配置目录

我们在命令行终端输入 nvim 进入 LazyVim 的欢迎界面,可以看到一些菜单项。

image.png

按下 c 键可以打开 Neovim 的配置文件列表页面。

image.png

打开入口文件 init.lua,此时就进入了配置文件目录。

我们需要借助文件树来查看和编辑目录下其他配置文件,可以按下 leader 键。leader 键在 Neovim 中是常用的功能键,可以调用文件树、Git、telescope 等多种插件提供的功能。

image.png

leader 键默认为空格键,按下后进入操作符待处理模式,然后再按 e 键打开文件树(NeoTree 插件)。

此时可以按 ? 问号键查看帮助,通过 j k 上下选择文件Enter 回车键查看目录或者打开文件,也可以按 s split 键分屏打开文件

NeoTree 左上角会显示当前的工作目录,Linux 中 ~/.config/nvim 和 Windows 中 ~\AppData\local\nvim 是 Neovim 的默认配置路径

在配置目录中,init.lua 是入口文件,Neovim 启动时会首先运行它,加载并初始化 lua 目录下的配置。

lua 目录包括两个子目录:config 用于存放通用配置,比如快捷键映射等;plugins 则专门存放插件相关的配置

image.png

配置插件

了解了基本的配置结构后,我们将开始实践。首先,我们要将 LazyVim 内置的 NeoTree 插件替换成 MiniFiles 插件

首先我们按 空格l leader lazy 打开 LazyVim 的插件控制台,在这里可以查看和管理已经安装的插件。

控制台顶部有按键提示,这些大写按键的操作都是针对所有插件的。如果只想单独操作某个指定插件,可以按对应的小写按键

image.png

我们 Ctrl d 往下浏览,可以看到许多等待更新的插件,将光标移动到 NeoTree 上 按下 U 键后,NeoTree 的状态就变成 updated 了

需要注意的是,每个插件的新版本都有可能存在 bug 或冲突,更新后严重的话会导致 Newvim 整个瘫痪,此时就需要回滚。

我们打开 lazy-lock. json 文件,将问题插件的 commit 哈希值改为更新前的,重启 Neovim 后,打开插件控制台,按 r restore 键,就可以将插件恢复到之前的版本。

我们浏览控制台后会发现 MiniFiles 插件并不在其中,因此需要手动安装。进入 MiniFiles 插件的仓库主页,来到 installation 部分,点开 With folke/lazy. nvim,可以看到两种安装方式,一种是安装 Mini 插件机,一种是单独安装 MiniFiles 插件,我们选择单独安装。

image.png

将 stable 版本的配置拷贝下来,回到 Neovim 配置目录,在 plugins 下创建 minifiles.lua 文件,粘贴刚才拷贝的配置,并参考 example 的格式,在开头加上 return,即 return { "echasnovski/mini.files", version = "*" }

image.png

然后根据仓库中 important 的要求:

Important: don't forget to call ` require('mini.files').setup() ` to enable its functionality

init.lua 文件中加上 require('mini.files').setup(),这样就完成了配置。

image.png

我们重新打开 Neovim,这时 LazyVim 就会识别到 MiniFiles 的配置,并自动开始安装。安装结束后,我们进入 Ex Mode,输入 :lua MiniFiles.open() 命令,调用 MiniFiles open 方法即可打开 MiniFiles 文件树,这时我们就可以像操作文本一样操作文件树了。

  • hjkl 选择文件或进入目录
  • o 键可以另起一行来创建文件或目录
  • 双击 y 键可以复制文件
  • p 键粘贴文件
  • ciw 修改文件名
  • 双击 d 键删除文件
  • q 键退出
  • ……

操作完成后,记得按 = 等于号将修改同步到磁盘,接下来我们可以卸载 NeoTree 插件了。

卸载插件

在 LazyVim 中卸载插件,只需移除该插件相关的配置文件即可。比如移除 minifiles.md 就可以卸载 MiniFiles 插件。

但由于 NeoTree 是 LazyVim 内置插件,没有相关配置可以移除,这就需要我们在 plugins 目录下,创建 disabled.lua 文件来管理禁用插件,将 NeoTree 插件设置为 enabled = false

return {
  { "nvim-neo-tree/neo-tree.nvim", enabled = false },
}

再重启 Neovim,这时 NeoTree 插件就被禁用了。按下 leader e 也不会唤起文件树,我们再按下 leader l 打开控制台,找到 NeoTree,按插件 clean x 已完成卸载,这时 leader e 键就空闲出来了。

image.png

快捷键映射

我们并不想每次唤起文件树时都进入 Ex Mode,输入一长串命令 :lua MiniFiles.open(),就可以考虑将唤醒命令绑定到 leader e 上。

我们打开 config 目录下的 keymaps.lua 文件,这个文件是专门用于管理快捷键映射的,可以从顶部注释中的链接里查看当前 LazyVim 的内置 keymap

image.png

我们看到每一条 keymap 配置都是一个 map 方法。该方法共有四个参数

  • 第一个参数为模式,首字母 N 代表 Normal ModeI 代表 Insert Mode
  • 第二个参数代表按键,普通按键用单个字符表示,特殊按键,比如 Ctrl h 则写作 <C-h>
  • 第三个参数代表按键触发的效果,可以是一串按键序列,也可以是一个表达式
  • 第四个参数则是一些附加选项,比如映射的描述信息

这里要绑定 leader e 键,可以加一个 map。

  1. 第一个参数填 N ,因为是在 Normal Mode 下触发
  2. 第二个参数填按键,也就是尖括号 <leader e>
  3. 第三个参数填按键序列,即 : lua MiniFiles.open() 代表进入 Ex Mode 并启动 MiniFiles;
  4. 第四个参数填描述信息
local map = vim.keymap.set
map("n", "<leader>e", ":lua MiniFiles.open()<cr>", { desc = "Trigger Mini Files" })

重启 Neovim,按 leader e 就可以唤起 MiniFiles 文件树了,自此 NeoTree 和 MiniFiles 的替换工作就完成了。

练习题