深色模式
Neovim 使用入门
概述
Neovim 是一个运行在终端里的编辑器,命令名通常是 nvim。它继承了 Vim 的模式编辑、组合命令和文本对象,同时提供 Lua 配置、内置终端、内置 LSP 客户端等能力,适合在服务器、远程开发环境和本地终端里长期使用。
刚开始使用时,不必马上安装一整套插件。先掌握模式切换、移动、编辑、搜索、分屏和基础配置,再逐步补齐文件树、模糊搜索、语法高亮、补全和 LSP,学习成本会低很多。
安装启动
macOS 可以用 Homebrew 安装:
sh
brew install neovimLinux 发行版通常也能直接通过包管理器安装:
sh
# Ubuntu / Debian
sudo apt install neovim
# Arch Linux
sudo pacman -S neovim发行版仓库里的 Neovim 版本可能偏旧。需要使用较新的 LSP 配置接口或插件生态时,优先确认 nvim --version 输出。
安装后查看版本:
sh
nvim --version常见启动方式如下:
sh
# 打开空编辑器
nvim
# 打开当前目录
nvim .
# 打开文件
nvim main.go
# 打开文件并跳到第 20 行
nvim +20 main.go进入 Neovim 后,可以先运行内置教程:
vim
:Tutor检查运行环境:
vim
:checkhealth退出编辑器:
vim
:q如果文件有未保存修改,普通 :q 会被拦住;确认丢弃修改时使用 :q!。
模式
Neovim 的操作围绕模式展开。模式不是装饰品,而是编辑效率的来源。
| 模式 | 入口 | 作用 |
|---|---|---|
| Normal | 默认模式,或按 <Esc> | 移动光标、执行编辑命令 |
| Insert | i、a、o、O | 像普通编辑器一样输入文本 |
| Visual | v、V、<C-v> | 选择字符、行或块 |
| Command-line | :、/、? | 执行命令、搜索文本 |
| Terminal | :terminal | 在 Neovim 内运行 shell |
几个常用入口:
| 按键 | 作用 |
|---|---|
i | 在光标前进入 Insert 模式 |
a | 在光标后进入 Insert 模式 |
o | 在当前行下方新建一行并进入 Insert 模式 |
O | 在当前行上方新建一行并进入 Insert 模式 |
<Esc> | 回到 Normal 模式 |
: | 输入命令,例如 :w、:q |
终端模式里,<Esc> 会传给终端程序,不一定能回到 Normal 模式。默认退出终端输入状态的按键是:
text
<C-\><C-n>后面可以通过配置把它改成更顺手的按键。
光标移动
Neovim 鼓励在 Normal 模式里移动,而不是长时间依赖方向键。
| 按键 | 作用 |
|---|---|
h / j / k / l | 左 / 下 / 上 / 右 |
w | 跳到下一个单词开头 |
b | 跳到上一个单词开头 |
e | 跳到当前或下一个单词结尾 |
0 | 跳到行首 |
^ | 跳到本行第一个非空字符 |
$ | 跳到行尾 |
gg | 跳到文件开头 |
G | 跳到文件结尾 |
20G | 跳到第 20 行 |
<C-d> | 向下滚动半屏 |
<C-u> | 向上滚动半屏 |
zz | 把当前行滚到屏幕中间 |
数字可以放在很多命令前面作为重复次数:
| 示例 | 作用 |
|---|---|
5j | 向下移动 5 行 |
3w | 向后移动 3 个单词 |
10G | 跳到第 10 行 |
2dd | 删除 2 行 |
f 和 t 适合在当前行内快速移动:
| 示例 | 作用 |
|---|---|
fa | 跳到本行下一个字符 a |
ta | 跳到本行下一个字符 a 前面 |
; | 重复上一次 f、t、F、T 查找 |
, | 反向重复上一次行内查找 |
编辑命令
Normal 模式里的编辑命令通常由“操作 + 范围”组成。先理解这个组合,比死背一堆快捷键更有效。
| 操作 | 含义 |
|---|---|
d | 删除 |
c | 修改,删除后进入 Insert 模式 |
y | 复制,也叫 yank |
> | 增加缩进 |
< | 减少缩进 |
= | 自动缩进 |
常见组合:
| 命令 | 作用 |
|---|---|
dd | 删除当前行 |
yy | 复制当前行 |
p | 粘贴到光标后或下一行 |
P | 粘贴到光标前或上一行 |
x | 删除当前字符 |
u | 撤销 |
<C-r> | 重做 |
ciw | 修改当前单词 |
diw | 删除当前单词 |
yiw | 复制当前单词 |
d$ | 删除到行尾 |
c$ | 修改到行尾 |
gg=G | 从文件开头到结尾自动缩进 |
这里的 iw 是文本对象,表示 inner word。类似的还有 i"、i'、i(、i{,适合处理引号和括号里的内容。
例如光标在下面字符串内部时:
txt
hello "neovim user"执行 ci" 会删除双引号里的内容并进入 Insert 模式,双引号本身保留。这个命令刚记住时有点怪,用熟以后会很难回到鼠标拖选。
剪贴板
Neovim 有自己的寄存器,默认复制不一定进入系统剪贴板。
| 命令 | 作用 |
|---|---|
yy | 复制当前行到默认寄存器 |
p | 从默认寄存器粘贴 |
"+y | 复制选中内容到系统剪贴板 |
"+p | 从系统剪贴板粘贴 |
想让默认复制粘贴直接使用系统剪贴板,可以在配置里加入:
lua
vim.opt.clipboard = 'unnamedplus'macOS 通常可以直接使用系统剪贴板。Linux 桌面环境可能需要安装 xclip、xsel 或 wl-clipboard,具体缺什么可以看 :checkhealth provider 的输出。
文件与缓冲区
Neovim 里需要区分三个概念:
- buffer:已经打开到内存里的文件内容。
- window:屏幕上的一个显示区域,可以显示某个 buffer。
- tab:一组 window 布局,不等于普通编辑器里的文件标签。
常用文件命令:
| 命令 | 作用 |
|---|---|
:e main.go | 打开文件 |
:w | 保存当前文件 |
:wq | 保存并退出 |
:q | 关闭当前窗口 |
:q! | 不保存并强制关闭当前窗口 |
:ls | 查看 buffer 列表 |
:bnext | 切到下一个 buffer |
:bprev | 切到上一个 buffer |
:bdelete | 删除当前 buffer |
:Ex | 打开内置文件浏览器 |
用 nvim . 打开目录时,通常会进入内置文件浏览器。它足够完成基础的打开文件、进入目录、返回上级目录;如果后续需要更强的项目导航,再考虑文件树或模糊搜索插件。
搜索替换
搜索命令很高频:
| 命令 | 作用 |
|---|---|
/keyword | 向下搜索 keyword |
?keyword | 向上搜索 keyword |
n | 跳到下一个匹配 |
N | 跳到上一个匹配 |
* | 搜索光标下的单词 |
# | 反向搜索光标下的单词 |
:noh | 取消当前搜索高亮 |
替换使用 :s 命令:
vim
" 替换当前行第一个 old
:s/old/new/
" 替换当前行所有 old
:s/old/new/g
" 替换全文所有 old
:%s/old/new/g
" 替换全文所有 old,并逐个确认
:%s/old/new/gc
" 只替换第 10 到 20 行
:10,20s/old/new/g/ 本身是分隔符,路径替换时可以换成其他分隔符,减少转义:
vim
:%s#/api/v1#/api/v2#g分屏标签
分屏用于同时查看多个位置,尤其适合一边看定义,一边改调用点。
| 命令 / 按键 | 作用 |
|---|---|
:split | 水平分屏 |
:vsplit | 垂直分屏 |
:sp main.go | 水平分屏打开文件 |
:vsp main.go | 垂直分屏打开文件 |
<C-w>h | 移动到左侧窗口 |
<C-w>j | 移动到下方窗口 |
<C-w>k | 移动到上方窗口 |
<C-w>l | 移动到右侧窗口 |
<C-w>= | 平均分配窗口大小 |
<C-w>q | 关闭当前窗口 |
标签页适合保存一组窗口布局:
| 命令 | 作用 |
|---|---|
:tabnew | 新建标签页 |
:tabnew main.go | 在新标签页打开文件 |
gt | 切到下一个标签页 |
gT | 切到上一个标签页 |
:tabclose | 关闭当前标签页 |
日常更建议优先使用 buffer 和分屏,把 tab 当成“布局分组”。把 tab 当成文件标签来用,后面很容易绕晕。
配置文件
现代 Neovim 配置通常使用 Lua,也可以继续使用 Vimscript。本文使用 Lua 示例。配置目录可以在 Neovim 内查看:
vim
:echo stdpath('config')常见位置如下:
| 系统 | 配置文件 |
|---|---|
| macOS / Linux | ~/.config/nvim/init.lua |
| Windows | %LOCALAPPDATA%\nvim\init.lua |
一个简洁的配置目录可以这样组织:
text
~/.config/nvim/
├── init.lua
├── lua/
│ ├── options.lua
│ ├── keymaps.lua
│ └── lsp.lua
└── after/init.lua 作为入口,负责加载其他文件:
lua
require('options')
require('keymaps')
require('lsp')修改配置后,可以重启 Neovim;也可以在配置文件里执行:
vim
:source %配置出错时先看报错文件和行号,再用 :messages 查看最近消息。Neovim 配置一旦长大,错误通常不是“大方向错了”,而是某个模块加载顺序不对或插件还没安装。
基础配置
下面是一份偏通用的 lua/options.lua:
lua
vim.g.mapleader = ' '
vim.opt.number = true
vim.opt.relativenumber = true
vim.opt.mouse = 'a'
vim.opt.termguicolors = true
vim.opt.signcolumn = 'yes'
vim.opt.ignorecase = true
vim.opt.smartcase = true
vim.opt.hlsearch = true
vim.opt.incsearch = true
vim.opt.expandtab = true
vim.opt.shiftwidth = 2
vim.opt.tabstop = 2
vim.opt.smartindent = true
vim.opt.splitright = true
vim.opt.splitbelow = true
vim.opt.undofile = true
vim.opt.clipboard = 'unnamedplus'常用按键可以放在 lua/keymaps.lua:
lua
local map = vim.keymap.set
map('n', '<leader>w', '<cmd>w<cr>', { desc = '保存文件' })
map('n', '<leader>q', '<cmd>q<cr>', { desc = '关闭窗口' })
map('n', '<leader>h', '<cmd>noh<cr>', { desc = '取消搜索高亮' })
map('n', '<leader>sv', '<cmd>vsplit<cr>', { desc = '垂直分屏' })
map('n', '<leader>ss', '<cmd>split<cr>', { desc = '水平分屏' })
map('t', '<Esc><Esc>', [[<C-\><C-n>]], { desc = '退出终端模式' })<leader> 是自定义前缀键。上面的配置把它设成空格,所以 <leader>w 就是先按空格,再按 w。
插件管理
Neovim 不强制绑定某个插件管理器。理解插件管理的本质就够了:把插件下载到运行时路径里,再按需要加载。
内置的 Vim packages 机制把插件分成两类:
pack/*/start/*:启动时自动加载。pack/*/opt/*:按需用:packadd加载。
例如安装一个启动时自动加载的插件,目录大致是:
text
~/.config/nvim/pack/plugins/start/example-plugin/现代配置里也经常使用第三方插件管理器,例如 lazy.nvim。它更适合管理大量插件、懒加载、锁定版本和更新插件。插件数量不宜一开始就堆满;先补高频能力,再处理“看起来很酷但实际很少按”的功能。
一个比较稳的补插件顺序是:
- 语法高亮和缩进:优先处理常用语言。
- 模糊搜索:用于找文件、找文本、找 buffer。
- Git 集成:查看变更、跳转 hunk、显示 blame。
- 补全:配合 LSP、路径、buffer 内容。
- 主题和状态栏:最后再调,不然容易先把时间花在配色上。
LSP
Neovim 内置 LSP 客户端,但语言服务器要单独安装。Go 代码需要 gopls,Python 常见的是 pyright,Lua 常见的是 lua-language-server。
下面的 vim.lsp.config 与 vim.lsp.enable 写法适合较新的 Neovim 版本。旧版本配置 LSP 时,通常会使用 nvim-lspconfig 提供的 require('lspconfig').gopls.setup({}) 写法。
示例:给 Go 配置 gopls。先安装语言服务器:
sh
brew install gopls然后在配置里加入:
lua
vim.lsp.config('gopls', {
cmd = { 'gopls' },
filetypes = { 'go' },
root_markers = { 'go.mod', '.git' },
})
vim.lsp.enable('gopls')常用 LSP 按键可以放在 LspAttach 事件里,只对已经连接 LSP 的 buffer 生效:
lua
vim.api.nvim_create_autocmd('LspAttach', {
callback = function(event)
local opts = { buffer = event.buf }
vim.keymap.set('n', 'gd', vim.lsp.buf.definition, opts)
vim.keymap.set('n', 'K', vim.lsp.buf.hover, opts)
vim.keymap.set('n', '<leader>rn', vim.lsp.buf.rename, opts)
vim.keymap.set('n', '<leader>ca', vim.lsp.buf.code_action, opts)
vim.keymap.set('n', '<leader>f', function()
vim.lsp.buf.format({ async = true })
end, opts)
end,
})检查 LSP 状态:
vim
:checkhealth vim.lsp当前 buffer 已连接语言服务器后,跳转定义、查看悬浮文档、重命名、格式化才会生效。LSP 没工作时,优先检查三件事:语言服务器是否在 PATH 里、当前文件类型是否匹配、项目根目录是否能被识别。
常用命令
这组命令适合放在脑子里的“工具箱”里:
| 命令 | 作用 |
|---|---|
:help keyword | 查看帮助,例如 :help lua-guide |
:Tutor | 打开内置教程 |
:checkhealth | 检查环境和插件状态 |
:messages | 查看最近消息和报错 |
:set number? | 查看某个选项当前值 |
:map | 查看按键映射 |
:verbose map <leader>w | 查看某个映射来自哪里 |
:edit $MYVIMRC | 打开当前配置入口文件 |
:source % | 重新加载当前文件 |
:terminal | 打开内置终端 |
帮助文档支持跳转:在帮助页里按 <C-]> 跳到光标下的标签,按 <C-o> 返回上一处。Neovim 的帮助文档信息密度很高,学会查 :help 后,很多问题不需要先去搜索引擎里碰碰运气。
使用习惯
Neovim 的效率主要来自几个习惯:
- 尽量在 Normal 模式思考编辑动作,而不是一直待在 Insert 模式。
- 多用文本对象,例如
ciw、ci"、di(、yi{。 - 多用搜索、跳转和命令范围,少用鼠标慢慢选。
- 配置从小文件开始拆分,出错时容易定位。
- 插件按需求添加,不要直接复制一份看不懂的大配置。
可以尝试 LazyVim、NvChad、AstroNvim 这类发行版,它们能很快给出接近 IDE 的体验。更长期的做法是保留一份自己能解释清楚的最小配置;哪天远程服务器只有一个干净的 nvim,也不至于突然失去编辑能力。
