假如你是位木匠师傅,最烦的莫过于干两分钟活就要弯腰捡一次工具。普通编辑器就是这样——你正敲着代码,手一挪去点鼠标找位置,回来又得重新摆好姿势。Vim 是另一座工坊:它把“看料、雕刻、端详、吩咐”分成四种模式,双手始终停在同一把键盘上,像师傅巡视工作台、拿起刻刀、掂量木料、对学徒下令一样,各干各的,互不打扰。Neovim 则是这座工坊的现代化翻修:墙和柜子用新的脚本语言重新定制,还从外面请来一位“图纸顾问”,你每画一笔,它就在旁边提醒你哪条线对不齐、哪个尺寸标错了。这篇文章就是一次工坊参观:先认识四种模式,再学巡视与雕刻的招式,接着布置多张工作台,然后改写匠规手册,最后添置定制工具、请进现代顾问。走完这一趟,无论你在电脑前还是服务器里,都能下笔如有神。

岗位关联

学完这一篇,你能读懂任何人的 vimrc / init.lua,并亲手搭起一套高效终端编辑工作流——这是 AI 工程师在远程服务器与本地开发之间无缝切换的基本功。

目录
  1. 可视化演示
  2. 模式化编辑
  3. 高效移动
  4. 编辑魔法
  5. 缓冲窗口
  6. 定制配置
  7. 插件生态
  8. 现代 Neovim
  9. AI 应用场景
  10. Python 演示
  11. 常见误区
  12. 面试题

可视化演示

\u5c55\u793aPrim\u7b97\u6cd5\u4ece\u8d77\u59cb\u9876\u70b9\u51fa\u53d1\uff0c\u6bcf\u6b65\u4ece\u5df2\u9009\u9876\u70b9\u96c6\u5408\u5230\u672a\u9009\u9876\u70b9\u7684\u8fb9\u4e2d\u9009\u62e9\u6743\u503c\u6700\u5c0f\u7684\u8fb9\u52a0\u5165\u751f\u6210\u6811\uff0c\u76f4\u5230\u6240\u6709\u9876\u70b9\u8fde\u901a\u3002

本节配有交互动效(进入视口后自动加载,约 3KB)。

Prim\u7b97\u6cd5\u6784\u5efaMST \u5df2\u8fde\u901a\u9876\u70b9 \u5f53\u524d\u9009\u4e2d\u7684\u8fb9 W=16 \u8d2a\u5fc3\u9009\u62e9\u6700\u5c0f\u6743\u8fb9

模式化编辑

工匠干活从不“边走路边刻字”:他先绕工作台一圈看清每块料的位置,再俯身下刀;刻到一半,会直起身重新打量。Vim 的模态设计正是如此。普通编辑器永远处于“打字”状态,键盘就是文字流;而 Vim 把键盘变成一个遥控器——不同模式下,同一个键有不同的含义。

Vim 打开文件后默认处于普通模式(Normal),此时每个字母都是命令:j 下移一行、x 删一个字符。按 i 进入插入模式(Insert),这才是真正的“打字模式”;按 Esc 或 Ctrl-[ 返回普通模式。按 v 进入可视模式(Visual),移动光标即可选中文本;按 : 进入命令行模式,执行 :w 保存、:q 退出等指令。

新手最常见的困境是“一进插入模式就出不来了”——因为他们的编辑流程是“打字、打字、还是打字”。Vim 高手的节奏完全相反:大部分时间在普通模式里“指挥”,小部分时间才输入。模式的切换可以用一条状态流转表示:

NORMAL→ i / a / o INSERT→ Esc NORMAL\displaystyle \text{NORMAL} \xrightarrow{\ i\ /\ a\ /\ o\ } \text{INSERT} \xrightarrow{\ \mathrm{Esc}\ } \text{NORMAL}

1. NORMAL(普通/指挥模式):Vim 启动后的默认状态,每个按键都是命令而非文本。

NORMAL: j=下移, x=删除, u=撤销\text{NORMAL}:\ j=\text{下移},\ x=\text{删除},\ u=\text{撤销}

2. i / a / o(三个入口):i 在光标前插入,a 在光标后追加,o 在下方新开一行并进入插入。

i=insert(前), a=append(后), o=open(新行)\text{i}=\text{insert(前)},\ \text{a}=\text{append(后)},\ \text{o}=\text{open(新行)}

3. INSERT(插入/雕刻模式):这是唯一“敲什么显示什么”的模式,与普通编辑器一致。

INSERT: 直接输入字符\text{INSERT}:\ \text{直接输入字符}

4. Esc(返回指挥台):按 Esc 或 Ctrl-[ 回到普通模式,重新获得全部命令能力。

Esc⇒NORMAL\mathrm{Esc} \Rightarrow \text{NORMAL}

所以在 Vim 里,“雕刻是例外,巡视是常态”。高手不会一直猫着腰打字,而是时不时直起身来打量全局、发号施令——这正是“模式化”让人变快的原因:每一次模式切换,都是一次“我接下来要做什么”的明确表态。

高效移动

师傅在工坊里走位很有讲究:小碎步挪到台边,迈一大步跨过料堆,抬头远眺看清整间屋子。Vim 的移动命令就是三种步幅。小碎步是 h/j/k/l——左、下、上、右;中步是 w/b/e——按“词”为单位前后跳;远眺是 gg(文首)、G(文末)、0(行首)与 $(行尾)。

为什么移动这么重要?因为在普通模式下“去哪儿”永远先于“做什么”。你删之前得先站到目标旁边(d + motion),改之前也得先定位。除了方向与词跳,f + 字符 能在当前行内直接跳到下一个指定字符,/ 关键字 则全文搜索,n / N 在搜索结果之间来回切。

Vim 的移动还支持“数字前缀”,表示重复多少次。比如 3w 是向前跳三个词,5j 是向下五行。这给了“距离”一个量化表达:

3 w⇒3×motion(w)⇒向前跳过 3 个词\displaystyle 3\,w \quad\Rightarrow\quad 3 \times \text{motion}(w) \quad\Rightarrow\quad \text{向前跳过 3 个词}

1. count(步数):数字写在 motion 前面,表示重复次数。

count: 3,5,10∈N\text{count}:\ 3, 5, 10 \in \mathbb{N}

2. motion w(词步幅):w 跳到下一个词首,b 回上一个词首,e 跳到词尾。

motion: w(词首), b(回词首), e(词尾)\text{motion}:\ w(\text{词首}),\ b(\text{回词首}),\ e(\text{词尾})

3. 组合(步数 × 步幅):3w 等价于连续按三次 w,一步到位表达“跨三个词”。

3 w≡w→w→w3\,w \equiv w \to w \to w

把移动练成肌肉记忆后,你会慢慢发现一个真相:编辑的本质就是“先到位,再动手”。就像师傅不站到料前绝不落刀一样——定位快,整间工坊的效率就上来了。

编辑魔法

师傅的手法说来也简单:削去多余的(delete)、取走样件(yank)、贴上木皮(put)、改出精形(change)。Vim 把这一切提炼成一条通用语法:动词 + 步数 + 步幅。动词决定“做什么”,步幅决定“做多远”。

最常用的动词是 d(删除)、y(复制)、c(修改)。它们可以和上一节的任意 motion 组合:d2w 删掉两个词,y3j 向下复制三行,ci" 修改一对引号内的内容,dd 删除整行,p 在光标后粘贴。命令 . 可以重复上一次完整编辑,u 撤销、Ctrl-r 重做。

用公式拆解一个经典组合:

d 2 w=d⏟operator 删除+2⏟count 步数+w⏟motion 词\displaystyle d\,2\,w = \underbrace{d}_{\text{operator 删除}} + \underbrace{2}_{\text{count 步数}} + \underbrace{w}_{\text{motion 词}}

1. operator(动词):d 删除、y 复制、c 修改,决定对文本做什么。

operator: d=delete, y=yank, c=change\text{operator}:\ d=\text{delete},\ y=\text{yank},\ c=\text{change}

2. count(步数):数字让操作作用于多份距离。

count: 2⇒两份步骤\text{count}:\ 2 \Rightarrow \text{两份步骤}

3. motion(步幅):w 词、j 行、} 段,划定作用的范围。

motion: w(词), j(行), }(段落)\text{motion}:\ w(\text{词}),\ j(\text{行}),\ \}(\text{段落})

4. 组合效果:同一套语法可衍生出无数命令。

d2w=删两词; c2w=改两词; y2w=抄两词d2w = \text{删两词};\ c2w = \text{改两词};\ y2w = \text{抄两词}

一旦脑子习惯“动词 + 距离”,你会发现以前的编辑就像用筷子一颗颗夹豆子,而 Vim 是一句“把这盘豆子倒进碗里”就搞定。. 键则是工坊里的“复读机”学徒:你示范一次,它就照做一次,重复劳动从此消失。

缓冲窗口

工坊里从来不止一张工作台:有的台面正雕到一半,有的只是翻出来看一眼。Vim 的 buffer(缓冲区)就是每张台面上摆着的“料”,window(窗口)是你看向某块料的那扇玻璃,而 tab(标签页)则是把好几张工作台分成的不同区域。

用 :e 文件名 可以打开新料上桌;:bn / :bp 在台面之间来回切换;:vsp(竖直)与 :sp(水平)把当前视野一分为二,配合 Ctrl-w 加方向键在窗口间跳转;:tabnew 新建标签页,把不同任务的工作台分组收纳。默认开启 set hidden 后,Vim 允许你“先藏起没雕完的料、换一块新的”,不必被迫先保存。

缓冲、窗口、标签页是三层的空间关系:

:vsp⇒ buffer A buffer B (左右并排);:bn/:bp⇒切换 buffer\displaystyle :vsp \Rightarrow \frac{\ \text{buffer A}\ }{\text{buffer B}}~(\text{左右并排}) \quad;\quad :bn / :bp \Rightarrow \text{切换 buffer}

1. buffer(料):打开过的文件及其修改记录,是内容本身。

buffer=文件内容+undo 历史\text{buffer} = \text{文件内容} + \text{undo 历史}

2. window(窗户):buffer 的一个可视“视角”,同一个 buffer 可被多个 window 同时看。

window→buffer (一对多)\text{window} \to \text{buffer}~(\text{一对多})

3. :vsp(开窗):屏幕纵向分为左右两个 window。

:vsp⇒vertical split:vsp \Rightarrow \text{vertical split}

4. :bn / :bp(换料):跳转到下一个 / 上一个 buffer。

:bn=buffer next; :bp=buffer previous:bn = \text{buffer next};\ :bp = \text{buffer previous}

记住“料、视角、布局”三层关系,你就不会在开着十几个文件的 Vim 里迷路——因为每块料都有编号,每扇窗都看得清清楚楚,每张工作台都摆得井井有条。这也正是终端多任务编辑不乱的底气。

定制配置

每个师傅都有自己的规矩册:锤子挂左墙、刻刀放右屉、卯榫余量留半寸。Vim 的规矩册叫 vimrc(Neovim 中是 init.lua),它在你每次开工时自动加载,把所有偏好布置妥当。

最常用的配置分两类:开关类与键位类。set number 显示行号;set relativenumber 显示相对行号(配合 d/y 数行距超方便);set tabstop=4 让 Tab 显示成 4 格;set expandtab 把 Tab 转成空格。键位类用 map 系列命令,例如 :nnoremap <Leader>s :w<Enter>,意思是“在普通模式按下 Leader+s 就保存”。Leader 键默认是反斜杠 \,大家通常改成空格:

:nnoremap⟨Leader⟩s:w⟨Enter⟩;let mapleader=’ ’\displaystyle :nnoremap \quad \langle \text{Leader} \rangle s \quad :w \langle \text{Enter} \rangle \quad;\quad \text{let mapleader} = \text{' '}

1. :nnoremap(非递归映射):n 普通模式 + nore 非递归,保证映射不会循环套用自身。

nnoremap: normal mode, non-recursive\text{nnoremap}:\ \text{normal mode, non-recursive}

2. \<Leader\>s(触发键):Leader 是用户自定义前缀键,配合 s 组成组合键。

⟨Leader⟩+s⇒触发动作\langle \text{Leader} \rangle + s \Rightarrow \text{触发动作}

3. :w\<Enter\>(目标动作):执行“保存当前文件”命令。

:w⟨Enter⟩⇒save file:w \langle \text{Enter} \rangle \Rightarrow \text{save file}

4. set mapleader(更换前缀):把默认的 \ 换成更顺手的空格键。

mapleader=’ ’⇒空格成为 Leader\text{mapleader} = \text{' '} \Rightarrow \text{空格成为 Leader}

配置的哲学是“小步迭代,只加自己用得上的规矩”。直接抄一份大神的整本规矩册,就像把别人家的墙柜照搬进自己工坊——看着气派,用起来处处别扭。今天加一行,明天改一行,规矩册才真正属于你。

插件生态

工坊开久了,师傅会向外订购专用工具:开榫机、边角刨、定角尺。Vim 的插件就是这些“专用工具”——某个痛点别人已经打磨好了,你拿来即用。而插件管理器(vim-plug、lazy.nvim)就是那张“订购单”:写下要什么,它负责进货、上架、更新。

以 Neovim 最流行的 lazy.nvim 为例:你用一个 Lua 表(table)声明插件来源和加载条件。比如想用 Treesitter 获得精准语法高亮、用 nvim-lspconfig 接入语言服务器,可以写成:

{ ’nvim-lspconfig’⏟插件来源,config=function()⏟加载后配置,lazy=true⏟用到才加载 }\displaystyle \{ \ \underbrace{\text{'nvim-lspconfig'}}_{\text{插件来源}},\quad \underbrace{\text{config} = \text{function}()}_{\text{加载后配置}},\quad \underbrace{\text{lazy} = \text{true}}_{\text{用到才加载}} \ \}

1. 插件来源(进货地址):一般是 GitHub 的 作者/仓库名,如 neovim/nvim-lspconfig。

来源=’author/repo’\text{来源} = \text{'author/repo'}

2. config(上架布置):插件加载后执行的自定义函数,通常在里面做键位映射与默认设置。

config=function()⋯end\text{config} = \text{function()} \cdots \text{end}

3. lazy = true(按需上架):懒加载,只有打开对应文件类型时才加载,减少启动开销。

lazy=true⇒延迟加载\text{lazy} = \text{true} \Rightarrow \text{延迟加载}

插件是把双刃剑:装得越多,工坊越挤,启动越慢。有经验的做法是“够用就好、按需加载”——每件工具都要说得清用途,说不清的,就先别进货。

现代 Neovim

Neovim 是 Vim 的现代化翻修版:地基还是那套模态模型,但墙、柜、照明都换了新材料。最亮眼的两件事——配置语言从 Vimscript 换成 Lua,以及内置了 LSP 客户端。LSP 就像工坊里请来的一位“活图纸顾问”:你每画一笔,它在旁边看着,尺寸标错立刻指出来,你想找某张图纸的出处,它一秒翻给你。

Lua 配置的核心是 vim.opt 和 vim.api。vim.opt.number = true 相当于老式 set number;vim.api.nvim_create_autocmd 可以注册自动命令,比如“保存前自动格式化”。LSP 客户端则通过语言服务器提供四项核心能力:补全(输入时给候选项)、诊断(错误与警告的红波浪线)、跳转定义(gd)、悬停签名(看函数参数)。

一条经典的 Lua 自动命令:

vim.api.nvim_create_autocmd({’BufWritePre’}, {callback=function() fmt() end})\displaystyle \text{vim.api.nvim\_create\_autocmd}( \{ \text{'BufWritePre'} \},\ \{ \text{callback} = \text{function() fmt() end} \} )

1. vim.api(Lua 工具箱入口):Neovim 暴露给 Lua 的官方 API 命名空间,nvim_create_autocmd 是其中一个函数。

vim.api⇒Neovim 的 Lua API\text{vim.api} \Rightarrow \text{Neovim 的 Lua API}

2. BufWritePre(保存前事件):事件名,表示“文件将写入磁盘之前”。

BufWritePre=before write buffer\text{BufWritePre} = \text{before write buffer}

3. callback(回调):事件触发后执行的 Lua 函数,这里调用 fmt() 格式化。

callback=function()→fmt()\text{callback} = \text{function()} \to \text{fmt()}

4. 整体意义(规矩化):把“保存即整洁”固化成自动化行为,不用每次手动记得。

写盘前格式化⇒代码永远整洁\text{写盘前格式化} \Rightarrow \text{代码永远整洁}

所以 Neovim 不是“另一个编辑器”,而是“Vim 的哲学 + 现代工程能力”。它把你练熟的肌肉记忆原封不动地保存下来,又给你 Lua 和 LSP 这对新翅膀。对 AI 工程师来说,无论你在本地 IDE 还是在容器里改代码,都能用同一套手艺,始终保持一段行云流水的节奏。

AI 应用场景

场景 1:服务器容器里改训练代码

阶段:模型训练与调试(Dev/Deploy 侧)

解决的问题:SSH 进去的机器没有图形界面,改配置、修训练脚本只能用终端。用 nano 逐行挪、用 sed 又得现查正则,效率极低。Vim/Neovim 在纯终端里就给到近乎 IDE 的体验:LSP 让 gd 直接跳转函数定义,:vsp 边看配置边改代码,:bn 在脚本与配置文件间快速切换。

具体案例:你在容器里调试 PyTorch 训练脚本,发现 train.py 里 batch_size 写死 32,同时要确认 config.yaml 的并行参数。nvim train.py 进入后,/batch_size 定位,ci" 把 32 改成 64;Ctrl-w h 切到左窗口查看 config,:wq 保存退出——全程没碰一次鼠标。

场景 2:大型开源代码库阅读与重构

阶段:代码理解与重构

解决的问题:在大模型代码库(如 transformers、vLLM)里找某个算子的定义和调用链,鼠标滚轮翻几万行太痛苦。Vim 的移动语法 + LSP 定位是阅读神器:/关键字 搜索、gd 跳定义、Ctrl-o 回跳,配合 % 配平括号,长文件阅读如鱼得水。

具体案例:想搞懂 Qwen2Attention 的前向过程::vsp 一屏开源码一屏开注释,/forward 定位函数,gd 跳到 scaled_dot_product_attention,% 在大括号间对照作用域——半小时就梳理完一条调用链。

场景 3:把 Vim 肌肉记忆带进日常 IDE

阶段:日常编码与迭代

解决的问题:很多 AI 工程师主力是 VSCode,但鼠标和键盘来回切换打断“心流”。VSCode 的 Vim 插件、JetBrains 的 IdeaVim 把 Vim 的模态和操作符语法搬进 IDE,让补全、重构、跳转都不再需要摸鼠标。

具体案例:在 VSCode 里写推理服务,想统一改一个字符串参数:ci" 直接改引号内容,改完按 . 重复到下一处,再 gd 跳到函数定义确认类型——手指不离键盘,思路不断。

Python 演示

python81 行
# -*- coding: utf-8 -*-"""MiniVim: 用几十行 Python 模拟 Vim 的"动词 + 距离"编辑语法"""  class MiniVim:    def __init__(self, text):        self.text = list(text)      # 把字符串拆成字符列表, 方便插入与删除        self.cursor = 0             # 光标所在列表下标        self.count = 1              # 数字前缀, 记录"几步"     def skip_words(self, pos, count):        # 从 pos 出发, 跳过 count 个词, 返回停下的下标        for _ in range(count):            while pos < len(self.text) and self.text[pos] == " ":                pos += 1            while pos < len(self.text) and self.text[pos] != " ":                pos += 1        return pos     def delete(self, motion, count):        if motion == "d":                       # dd: 删除整行(单行文本即全部)            del self.text[:]        elif motion == "$":                     # d$: 从光标删到行尾            del self.text[self.cursor:]        elif motion == "w":                     # dw / d2w: 删 1..N 个词            end = self.skip_words(self.cursor, count)            del self.text[self.cursor:end]        elif motion == "l":                     # dl: 删 1..N 个字符            for _ in range(count):                if self.cursor < len(self.text):                    del self.text[self.cursor]     def move(self, k):        if k == "h":            self.cursor = max(0, self.cursor - self.count)        elif k == "l":            self.cursor = min(len(self.text), self.cursor + self.count)        elif k == "w":            self.cursor = self.skip_words(self.cursor, self.count)        elif k == "$":            self.cursor = len(self.text)        self.count = 1     def run(self, keys):        i = 0        while i < len(keys):            k = keys[i]            if k.isdigit():                     # 数字前缀: 先记下"几步"                self.count = int(k)            elif k in "hlw$":                   # 移动命令: 小碎步与跨步                self.move(k)            elif k in "dc":                     # 操作符: d 删除, c 改(此处同删除)                j = i + 1                while j < len(keys) and keys[j].isdigit():                    self.count = int(keys[j])                    j += 1                motion = keys[j] if j < len(keys) else "l"                self.delete(motion, self.count)                self.count = 1                i = j                           # 跳过已被消费的 motion            i += 1        return "".join(self.text)  def demo():    cases = [        ("hello world python", "dw"),    # 删一个词        ("hello world python", "d2w"),   # 删两个词        ("hello  vim world", "2w"),      # 跳到第二个词后面        ("hello world python", "$5h"),   # 先到行尾再左移 5 格        ("hello world python", "dd"),    # 删整行        ("hello world python", "d$"),    # 从行首删到行尾    ]    for text, keys in cases:        v = MiniVim(text)        v.run(keys)        print("%-18r + %-4s => text=%-18r cursor=%d" % (text, keys, "".join(v.text), v.cursor))  if __name__ == "__main__":    demo()
目的:用 Python 实现一个微型 Vim 状态机,演示“动词 + 步数 + 步幅”如何组合出强大的编辑命令。
  1. self.text = list(text)把字符串拆成字符列表,方便在任意位置插入/删除。
  2. skip_words(pos, count)模拟 Vim 的 w:跳过空格、再跳过一串非空格,重复 count 次。
  3. delete(motion, count)按动词 d 分派:w 删词、l 删字符、d 删整行、$ 删到行尾。
  4. elif k in "hlw$"移动命令分派,h/l/w/$ 分别对应左移/右移/词跳/行尾。
  5. if k.isdigit(): self.count = int(k)数字前缀先缓存为“步数”,这是 Vim 语法的关键。
  6. motion = keys[j] if j < len(keys) else "l"操作符后紧跟的字符就是步幅(motion)。
  7. i = j跳过已被操作符消费的 motion 键,避免一个键被处理两遍。
  8. cases = [...]一组观摩用例:d2w 会真实演示“删掉两个词”的组合效果。

常见误区

误区“我平时用 VSCode / PyCharm,界面好看补全又强,学 Vim 纯属浪费时间。”

正解真正的战场在 SSH 进去的服务器和容器——那里没有图形界面,只有终端。Neovim 通过 LSP 提供了和 IDE 平起平坐的补全、跳转、诊断,而且理念还被 VSCode 的 Vim 插件吸收。Vim 不是要取代 IDE,而是给你一套“在任何环境都通用的编辑手艺”。

为何常见:大多数人只在本地图形界面里写代码,没经历过“只能 SSH 改文件”的部署现场,所以觉得 Vim 无用。

误区“我可以用上下左右键移动,hjkl 背起来又绕,没必要。”

正解方向键在键盘右下角,右手每次都要离开字母区;而 hjkl 就在字母区中心,配合数字前缀(如 3w、5j),你能用“距离”而非“次数”思考。手不离键盘,才是模态编辑的威力所在。

为何常见:hjkl 初看很反直觉(j 为什么是向下?),因为历史原因它继承自 vi 的物理键盘布局;一旦过了适应期,效率提升立竿见影。

误区“网上有现成的'最强 Vim 配置',clone 下来一放,我就拥有大神同款效率了。”

正解配置是高度个人化的“工坊规矩”:你不知道每行的作用、没有养成相应按键习惯、冲突报错时无从下手。正确姿势是从最小配置开始:只加自己理解的设置,按需装插件,让规矩册随你的工作流长出来。

为何常见:人们总想走捷径复制成功,但编辑器的效率本质是“人 + 配置”的长期磨合,配置只是其中一半。

误区“我配好了 nvim-lspconfig,怎么打开文件还是没有补全和跳转?”

正解LSP 是“客户端-服务器”架构:Neovim 只是客户端,你还得为每种语言安装对应的 language server(如 Python 的 pyright / py-lsp、TypeScript 的 tsserver),并在配置里设置启动命令。顾问来了工坊,还得先给他一张名片(语言服务器路径),他才知道怎么干活。

为何常见:不熟悉“客户端/服务器”分工,以为插件 = 功能实体,忽略了语言服务器是独立安装的外部程序。

面试题

Q1. Vim 打开文件后默认处于哪种模式?

单选题 · easy

  • A.插入模式
  • B.普通模式← 正确答案
  • C.可视模式
  • D.命令行模式

答案:B。Vim 的默认态是普通模式(Normal),此时键盘按键是命令而非文本;按 i 才进入插入模式,按 v 进可视模式,按 : 进命令行模式。这就像师傅进工坊先“巡视”,而不是直接动手刻。

Q2. 普通模式下,在光标前进入插入模式的命令是?

单选题 · easy

  • A.a 光标后追加
  • B.o 下方新开行
  • C.i 光标前插入← 正确答案
  • D.p 粘贴内容

答案:C。i = insert(光标前插入),a = append(光标后追加),o = open new line(向下新开一行并进入插入)。只有 C 满足“光标前进入插入”。

Q3. 普通模式下 w 键的作用是?

单选题 · easy

  • A.跳到单词词尾
  • B.跳到下一个词首← 正确答案
  • C.删除光标下单词
  • D.向下移动一行

答案:B。w 是 motion,跳到下一个词首;e 跳词尾;b 回上一个词首。容易混淆的是 e 与 w:w 到词首,e 到词尾。

Q4. 命令 d2w 的含义是?

单选题 · mid

  • A.删除两个字符
  • B.删除两个词← 正确答案
  • C.复制两个词
  • D.向下走两行

答案:B。d2w = 动词 d(delete)+ 步数 2 + motion w(word),即“删除两个词”。这是 Vim “动词+距离”语法最典型的例子。

Q5. 在普通模式下按哪个键可以重复上一次完整的编辑操作?

单选题 · mid

  • A.按 u 撤销上一步
  • B.按。重复上次编辑← 正确答案
  • C.按 p 粘贴内容
  • D.按 r 替换字符

答案:B。. 复读机上一次编辑动作(比如 d2w),u 撤销,p 粘贴,r 替换单个字符。重复操作是 Vim 高效的秘密武器之一。

Q6. 哪个快捷键用于重做(Redo)?

单选题 · mid

  • A.按 u 撤销上一步
  • B.按。重复上次编辑
  • C.按 Ctrl-r 重做← 正确答案
  • D.按 Ctrl-p 上翻历史

答案:C。u 撤销,Ctrl-r 重做(redo)。B 的 . 是“重复上次编辑”,D 的 Ctrl-p 是命令行的上一条历史。注意区分撤销与重做的对称关系。

Q7. 执行 :vsp 后屏幕会发生什么?

单选题 · mid

  • A.左右并排分屏← 正确答案
  • B.上下并排分屏
  • C.关闭当前窗口
  • D.切换到下一缓冲

答案:A。:vsp 是 vertical split,即纵向分割、左右并排两个窗口;:sp 才是水平分割(上下排列)。分屏后可用 Ctrl-w 加方向键在窗口间跳转。

Q8. 下列哪些属于 Vim 的编辑操作符(operator)?

多选题 · mid

  • A.d 删除← 正确答案
  • B.y 复制← 正确答案
  • C.w 词跳转
  • D.c 修改← 正确答案

答案:ABD。操作符是“动词”:d(delete)、y(yank)、c(change)。w 是 motion(词跳转),不是操作符。记住“动词 + 步数 + 步幅”的语法,就知道 w 属于步幅位。

Q9. 关于 LSP(语言服务器协议),下列说法正确的有?

多选题 · hard

  • A.支持 gd 跳转到定义← 正确答案
  • B.只负责代码补全
  • C.能显示错误诊断← 正确答案
  • D.需要安装语言服务器← 正确答案

答案:ACD。LSP 提供补全、跳转定义(gd)、诊断、悬停签名等多种能力,不止补全;它的架构是“客户端 + 语言服务器”,Neovim 是客户端,还要为每种语言安装对应 server(如 pyright)。

Q10. 下列哪些是 Neovim 相比传统 Vim 的现代化特性?

多选题 · hard

  • A.内置 Lua 运行时← 正确答案
  • B.内置 LSP 客户端← 正确答案
  • C.自带图形界面
  • D.异步插件加载← 正确答案

答案:ABD。Neovim 用 Lua 作配置语言、内置 LSP 客户端、支持异步机制(插件如 lazy.nvim 可并行/懒加载);但 Neovim 本身仍是终端程序,GUI 由外部客户端(如 neovide)提供,不属于内置特性。