Neovim 完整參考指南
Neovim 完整參考指南
Neovim(nvim)是以 Vim 操作模型為基礎、可用 Lua 擴充的文字編輯器。本指南採「先學原生、再按需要加外掛」的方式:移動、編輯、buffer、window、quickfix、terminal 與基本 Lua 設定都不依賴外掛;LSP、補全、檔案瀏覽器等則是可選的開發環境強化。
快捷鍵中的
<leader>預設是\;許多設定會改成空白鍵。<CR>是 Enter、<Esc>是 Escape、<C-x>是 Ctrl+x。
1. 安裝與第一步
安裝
macOS:
brew install neovim
Ubuntu / Debian:
sudo apt update
sudo apt install neovim
Fedora:
sudo dnf install neovim
確認版本並開啟檔案:
nvim --version
nvim README.md
新版本通常能取得較完整的 Lua 與 LSP 體驗;若發行版套件過舊,請依 Neovim 官方安裝說明 安裝官方釋出的版本。
說明系統與離開
Neovim 的說明是內建文件,不必上網:
:help
:help :w
:help motion.txt
:Tutor
常用命令:
| 命令 | 功能 |
|---|---|
:w |
儲存目前檔案 |
:q |
關閉目前 window;未儲存時會拒絕 |
:wq / :x |
儲存後離開 |
:q! |
放棄目前未儲存變更並離開 |
:qa |
關閉全部 window |
:checkhealth |
檢查剪貼簿、provider、外掛等環境 |
2. 模式、計數與命令列
最常用的是 Normal、Insert、Visual 與 Command-line 模式。Normal mode 是組合指令的起點;若不確定身在何處,按 <Esc> 回到 Normal mode。
| 模式 | 進入方式 | 用途 |
|---|---|---|
| Normal | <Esc> |
移動、操作文字、執行快捷鍵 |
| Insert | i、a、o |
輸入文字 |
| Visual | v、V、<C-v> |
選取字元、行或區塊 |
| Command-line | : |
執行 Ex 命令,例如 :w |
常見進入 Insert mode 的差別:i 在游標前插入、a 在後插入、I 到行首插入、A 到行尾插入、o 在下方新開一行、O 在上方新開一行。u 復原,<C-r> 重做。
多數指令可加次數,例如 3w 前進三個單字、5dd 刪除五行、2>> 縮排兩行。冒號命令也可帶範圍:
:10,20d " 刪除第 10 到 20 行
:%s/old/new/g " 全檔替換
3. 移動、文字物件與操作符
基本移動
| 按鍵 | 移動 |
|---|---|
h j k l |
左、下、上、右 |
w / b / e |
下一個單字開頭/上一個單字開頭/目前或下一個單字結尾 |
0 / ^ / $ |
行首/第一個非空白字元/行尾 |
gg / G |
檔案開頭/結尾 |
{ / } |
上一段/下一段 |
f{字元} / t{字元} |
行內找字元/停在該字元前;; 重複、, 反向 |
% |
跳到成對括號、標籤或區塊的另一端 |
<C-u> / <C-d> |
向上/向下捲半頁 |
/pattern<CR> 向下搜尋、?pattern<CR> 向上搜尋,接著用 n / N 前往下一個/上一個結果。* 可搜尋游標下的完整單字;# 反向搜尋。
Operator + motion:真正的編輯語法
操作符(operator)後面接移動(motion),形成可組合指令。常見操作符為:d 刪除、c 修改後進入 Insert、y 複製、> / < 縮排/減少縮排、= 重新縮排。重複操作符通常代表整行,如 dd、yy、cc。
dw 刪到下一個單字開頭
ciw 修改游標所在單字(change inner word)
dap 刪除一個段落(delete a paragraph)
y$ 複製至行尾
>G 將目前行到檔尾縮排
文字物件(text object)讓操作以語意範圍為單位:iw 是單字內部、aw 包含周邊空白;i( / a( 是括號內/連同括號;同理可用 i[、i{、i"、i'、it(HTML/XML tag)。
ci" 只改雙引號內文字
da( 刪除一組括號及其內容
vi{ 視覺選取大括號內容
取代、貼上與大小寫
x 刪除一個字元,r{字元} 取代一個字元,R 進入覆寫模式。p 貼在游標後(或行下),P 貼在前(或行上);~ 切換游標下字元大小寫。Visual mode 下選取後按 > / < 縮排,按 = 依檔案縮排規則格式化選取區。
4. 搜尋、取代、register 與 macro
搜尋與取代
取代命令的格式是 :[range]s/搜尋/替換/[flags]:
:s/foo/bar/ " 目前行第一個 foo
:%s/foo/bar/g " 全檔所有 foo
:%s/foo/bar/gc " 每次替換前確認
:'<,'>s/foo/bar/g " Visual 選取範圍(選取後按 :)
常用 flag:g 每行全部匹配、c 確認、i 忽略大小寫。若內容有 /,可換分隔字元::%s#src/app#src/web#g。可用 :set ignorecase smartcase,使全小寫查詢不分大小寫、含大寫的查詢精確比對。
Register(暫存器)
" 開頭可指定 register:"ayy 複製目前行到 a、"ap 貼上 a。未命名 register " 會保存最近一次刪除或複製;"0 保存最近一次 yank;"_ 是黑洞 register,避免不想要的刪除覆蓋剪貼簿。
"_dd 刪除一行,但不污染預設 register
"0p 貼上最近複製的內容
:reg 檢視所有 register
系統剪貼簿通常用 "+y 與 "+p。也可以在設定中使用 vim.opt.clipboard = "unnamedplus";需先透過 :checkhealth 確認系統剪貼簿 provider 可用。
Macro(巨集)
q{register} 開始錄製,執行完按 q 停止;@{register} 執行,@@ 重複最近的 macro。例如逐行補上逗號:按 qaA,<Esc>jq 錄到 a,再以 @a 或 10@a 執行。
若 macro 的動作改變行數或游標位置,先對兩三行測試,再用 :{range}normal @a 批次執行:
:10,20normal @a
5. 多檔案工作:buffer、window 與 tabpage
三者不是同義詞:buffer 是已開啟檔案或文字內容;window 是螢幕中觀看某個 buffer 的視窗;tabpage 是一組 window 的版面。原生 tabpage 不是一般編輯器的一檔一分頁,專案中常以 buffer + split 為主。
Buffer
:e src/main.lua " 開啟或切換檔案
:ls " 列出 buffer
:b 3 " 切到編號 3 的 buffer
:b filename " 依名稱切換
:bn / :bp " 下一個/上一個 buffer
:bd " 關閉目前 buffer
:bdelete! " 放棄未儲存變更並關閉 buffer
Window(split)
:split README.md " 水平切割並開檔
:vsplit src/main.lua " 垂直切割並開檔
<C-w>h/j/k/l " 往左/下/上/右切換 window
<C-w>w " 在 window 間循環
<C-w>q " 關閉目前 window
<C-w>o " 只保留目前 window
<C-w>= " 平均分配大小
<C-w>_ / <C-w>| " 最大化高度/寬度
Tabpage
:tabnew README.md " 新 tabpage 並開檔
:tabnext / :tabprev " 下一個/上一個 tabpage
gt / gT " Normal mode 下一個/上一個 tabpage
:tabclose " 關閉目前 tabpage
6. Quickfix、location list 與 terminal
Quickfix:跨檔案結果清單
quickfix list 常由編譯器、測試命令、grep 或 LSP 產生。它是全域清單;location list 則是特定 window 的相似清單。
:make " 使用 'makeprg' 執行,錯誤寫入 quickfix
:copen " 開啟 quickfix window
:cnext / :cprev " 前往下一個/上一個項目
:cfirst / :clast " 第一個/最後一個項目
:cclose " 關閉 quickfix window
:grep TODO **/*.lua " 將 grep 結果放入 quickfix(依環境設定)
若用外部搜尋工具,較可靠的方式是先設定 grepprg,或直接使用 :vimgrep /TODO/gj **/*.lua 建立 quickfix。gj 會保留每個檔案的多筆匹配。location list 以 :lopen、:lnext、:lprev 操作。
內建 terminal
Neovim 原生有 terminal buffer:
:terminal
:split | terminal
:vsplit | terminal
在 terminal mode 按 <C-\\><C-n> 回到 Normal mode,再以 <C-w>h/j/k/l 切換視窗;i 回到 terminal 輸入。終端程序結束後,關閉其 buffer::bd。把長時間 server、log 與 editor 分開管理時,可搭配 tmux 常用指南。
7. Lua 設定:最小可用 init.lua
Neovim 讀取 ~/.config/nvim/init.lua(Windows 通常是 %LOCALAPPDATA%\\nvim\\init.lua)。先建立目錄與檔案:
mkdir -p ~/.config/nvim
nvim ~/.config/nvim/init.lua
以下僅使用 Neovim 原生 API,不需 plugin:
-- ~/.config/nvim/init.lua
vim.g.mapleader = " "
vim.g.maplocalleader = " "
vim.opt.number = true
vim.opt.relativenumber = true
vim.opt.expandtab = true
vim.opt.shiftwidth = 2
vim.opt.tabstop = 2
vim.opt.smartindent = true
vim.opt.ignorecase = true
vim.opt.smartcase = true
vim.opt.splitright = true
vim.opt.splitbelow = true
vim.opt.clipboard = "unnamedplus"
vim.opt.undofile = true
vim.keymap.set("n", "<leader>w", "<cmd>write<CR>", { desc = "Save file" })
vim.keymap.set("n", "<leader>q", "<cmd>quit<CR>", { desc = "Quit window" })
vim.keymap.set("n", "<Esc>", "<cmd>nohlsearch<CR>", { desc = "Clear search highlight" })
local group = vim.api.nvim_create_augroup("user_config", { clear = true })
vim.api.nvim_create_autocmd("TextYankPost", {
group = group,
callback = function()
vim.highlight.on_yank()
end,
})
設定修改後可重啟 Neovim,或在目前 session 執行:
:source $MYVIMRC
:messages
vim.opt 用於選項、vim.g 用於全域變數、vim.keymap.set 建立映射,vim.api.nvim_create_autocmd 建立自動命令。設定變大時,可把 Lua 模組放到 ~/.config/nvim/lua/,再用 require("模組名稱") 載入。
8. 外掛與發行版:可選,不是前提
lazy.nvim:外掛管理器
lazy.nvim 是外掛管理器,不是 Neovim 必需元件。下例會在第一次啟動時安裝 lazy.nvim,並只宣告一個可選外掛;請以官方 README 的最新 bootstrap 程式碼為準。
-- 放在 init.lua 的原生設定之後
local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim"
if not vim.uv.fs_stat(lazypath) then
vim.fn.system({
"git", "clone", "--filter=blob:none",
"https://github.com/folke/lazy.nvim.git", "--branch=stable", lazypath,
})
end
vim.opt.rtp:prepend(lazypath)
require("lazy").setup({
{ "nvim-lua/plenary.nvim", lazy = true },
})
首次啟動後以 :Lazy 查看、安裝、更新與檢查外掛。若尚未有 Git,先安裝 Git;失敗時先看 :messages 與 :checkhealth lazy。
LazyVim 是什麼?
LazyVim 是以 lazy.nvim 為基礎的 Neovim 發行版(預先整合設定與外掛),不是 lazy.nvim 的同義詞,也不是使用 Neovim 的必要條件。它適合希望快速擁有預設 keymap、LSP 與 UI 的使用者;想理解每項行為或保有極簡設定時,從自己的 init.lua 開始通常更合適。不要把 LazyVim 的快捷鍵誤認為 Neovim 原生快捷鍵。
開發常用外掛建議(全部可選)
| 類別 | 常用外掛 | 用途與原生界線 |
|---|---|---|
| LSP | neovim/nvim-lspconfig、mason-org/mason.nvim |
lspconfig 協助設定語言伺服器;Mason 協助安裝工具。Neovim 原生提供 LSP client,但不會替你安裝 server。 |
| 補全 | hrsh7th/nvim-cmp 或 saghen/blink.cmp |
插入模式候選選單與 snippet 整合;不是原生自動補全體驗。 |
| 格式化 | stevearc/conform.nvim |
統一呼叫 formatter;也可直接用原生 vim.lsp.buf.format()。 |
| Lint | mfussenegger/nvim-lint |
在儲存或事件時呼叫外部 linter;原生只負責呈現 diagnostics。 |
| 語法樹 | nvim-treesitter/nvim-treesitter |
更精細的 highlight、indent、text object;不是所有語言都需啟用。 |
| 搜尋/挑選 | nvim-telescope/telescope.nvim、ibhagwan/fzf-lua |
模糊找檔、buffer、grep、Git 資訊;原生則有 :find、:buffers、quickfix。 |
| Git | lewis6991/gitsigns.nvim、tpope/vim-fugitive |
行內變更標記與 Git 操作;Git 本身仍在終端執行。 |
| Debug | mfussenegger/nvim-dap、rcarriga/nvim-dap-ui |
Debug Adapter Protocol client 與介面;仍需安裝語言對應 debug adapter。 |
外掛能提升整合,但也會增加更新、相容性與啟動時間成本。一次只加一組功能,啟動後執行 :checkhealth 並讀該外掛 README;需要快速定位檔案與文字時,外部 fzf 常用指令指南 和 rg 常用指令指南 仍然很可靠。
9. LSP、診斷與格式化的原生操作
LSP(Language Server Protocol)讓語言伺服器提供跳轉、引用、重新命名、診斷與格式化。Neovim 原生具備 client API;但「哪個 server、如何啟動、server 本身如何安裝」需要自行設定或借助前述可選工具。
以下是 Neovim 0.11+ 的原生附加範例。它假設已在系統 $PATH 安裝 lua-language-server;Neovim 不會代為下載這個外部程式。放入 init.lua 後,開啟 Lua 檔案時會依檔案類型啟用 lua_ls:
vim.lsp.config("lua_ls", {
cmd = { "lua-language-server" },
filetypes = { "lua" },
root_markers = { ".luarc.json", ".luarc.jsonc", ".git" },
settings = {
Lua = {
diagnostics = { globals = { "vim" } },
},
},
})
vim.lsp.enable("lua_ls")
若使用的是 Neovim 0.10 或更舊版本,沒有此 vim.lsp.config/vim.lsp.enable 工作流;可升級 Neovim,或改用可選的 neovim/nvim-lspconfig 依其文件設定 server。
server 已附加到目前 buffer 後,常用原生命令/API 如下:
vim.keymap.set("n", "gd", vim.lsp.buf.definition, { desc = "Go to definition" })
vim.keymap.set("n", "gr", vim.lsp.buf.references, { desc = "References" })
vim.keymap.set("n", "K", vim.lsp.buf.hover, { desc = "Hover documentation" })
vim.keymap.set("n", "<leader>rn", vim.lsp.buf.rename, { desc = "Rename symbol" })
vim.keymap.set({ "n", "v" }, "<leader>f", function()
vim.lsp.buf.format({ async = true })
end, { desc = "Format buffer" })
vim.keymap.set("n", "[d", vim.diagnostic.goto_prev, { desc = "Previous diagnostic" })
vim.keymap.set("n", "]d", vim.diagnostic.goto_next, { desc = "Next diagnostic" })
K、gd、gr 等在此段是「你自行設定的 mapping」;Neovim 原生提供的是對應 Lua 函式,預設按鍵配置仍可能因版本或你的設定而不同。以 :checkhealth vim.lsp 與 :lua vim.print(vim.lsp.get_clients({ bufnr = 0 })) 確認目前 buffer 的原生 LSP 狀態,:lua vim.diagnostic.open_float() 顯示游標位置診斷。若安裝了 nvim-lspconfig,其提供的 :LspInfo 也可作為額外診斷工具。
格式化與 lint 是不同事:formatter 重排程式碼,linter 回報潛在問題。優先採用專案既有的 formatter、linter、CI 規則,避免以編輯器設定覆蓋團隊標準。
10. 日常工作流程
原生優先的專案巡覽流程
- 從專案根目錄開啟:
nvim .或nvim path/to/file。 - 用
:e開檔、:ls瀏覽既有 buffer;以:vsplit對照兩個檔案。 - 用
/、*、:vimgrep尋找符號或待辦,並用:copen在 quickfix 逐筆處理。 - 用
ciw、dap、Visual mode 等語意操作修改;以:w儲存並用u/<C-r>安全回退。 - 用
:terminal執行測試、formatter 或 Git;錯誤可由:make或 quickfix 導回來源。 - 在終端以
git status、git diff、git commit完成版本控制;指令參考 Git 常用指令指南。
使用 rg 建立 quickfix
若專案已安裝 ripgrep,可由 shell 產生可讀的清單:
rg --vimgrep "TODO" . > /tmp/nvim-todo.txt
再在 Neovim 載入:
:cfile /tmp/nvim-todo.txt
:copen
或在 Neovim 設定 grepprg 後以 :grep 直接搜尋。這保留 rg 的忽略規則及速度,並讓 quickfix 成為跨檔案待辦清單。
11. 疑難排解
| 情況 | 先做什麼 |
|---|---|
修改 init.lua 後沒生效 |
重新啟動,或 :source $MYVIMRC;接著看 :messages 是否有 Lua 錯誤。 |
| 外掛安裝/更新失敗 | 確認 git --version、網路與寫入權限;執行 :Lazy、:checkhealth lazy、:messages。 |
| LSP 沒有附加 | 檢查檔案 type(:set filetype?)、server 是否已安裝、專案 root 是否正確,再用 :checkhealth vim.lsp 與 :lua vim.print(vim.lsp.get_clients({ bufnr = 0 }));有安裝 nvim-lspconfig 時也可用其 :LspInfo。 |
| 格式化無作用 | 分辨是否已設定 formatter 或 LSP formatting;先在終端直接執行專案的 formatter,確認工具本身可用。 |
| 系統剪貼簿無作用 | 跑 :checkhealth;Linux 常需 xclip、xsel、wl-clipboard 等 provider,遠端 SSH/tmux 也會影響剪貼簿橋接。 |
<Esc>、jk 等鍵行為奇怪 |
檢查 :verbose map <Esc>,它會顯示最後定義 mapping 的位置。 |
| 啟動變慢或衝突 | 先以 nvim --clean 排除使用者設定;再逐一停用最近新增的外掛,避免一次更新所有設定。 |
| Swap 檔警告 | 確認沒有另一個 Neovim 正在編輯同一檔案;若確定沒有且不需復原,依提示刪除 swap,否則先用復原選項。 |
診斷設定問題時,先比較 nvim --clean 與一般 nvim 的結果:前者正常通常代表問題在設定或外掛,而非 Neovim 本體。
12. 快速參考
模式與檔案
| 動作 | 快捷鍵/命令 |
|---|---|
| 回到 Normal mode | <Esc> |
| 插入/附加 | i / a |
| 新增上下行 | o / O |
| 視覺選取 | v / V / <C-v> |
| 儲存/離開 | :w / :q / :wq |
| 開檔/列 buffer | :e file / :ls |
| 下一個/上一個 buffer | :bn / :bp |
| 關閉 buffer | :bd |
移動與編輯
| 動作 | 快捷鍵 |
|---|---|
| 單字移動 | w / b / e |
| 行首/行尾 | 0 / ^ / $ |
| 檔案開頭/結尾 | gg / G |
| 搜尋與下一筆 | /text<CR>、n / N |
| 刪除/複製一行 | dd / yy |
| 修改單字/引號內文字 | ciw / ci" |
| 貼上前/後 | P / p |
| 復原/重做 | u / <C-r> |
| 替換全檔(確認) | :%s/old/new/gc |
視窗、清單與終端
| 動作 | 快捷鍵/命令 |
|---|---|
| 水平/垂直切割 | :split / :vsplit |
| 切換 window | <C-w>h/j/k/l |
| 新 tabpage | :tabnew |
| 開啟/下一筆 quickfix | :copen / :cnext |
| 開啟 terminal | :terminal |
| terminal 回 Normal mode | <C-\\><C-n> |
延伸閱讀
- tmux 常用指南 — 將 Neovim、測試與長時間程序組成可持續的終端工作環境。
- ripgrep rg 使用教學 — 以
rg快速搜尋專案並導入 quickfix。 - fzf 常用指令指南 — 用模糊搜尋挑選檔案、分支與命令歷史。
- Git 常用指令指南 — 從 Neovim terminal 執行日常 Git 工作。
- Neovim 使用手冊 — 原生功能與
:help的完整線上版本。 - Neovim Lua 指南 — Lua 設定與 API 基礎。
- lazy.nvim 文件 — 外掛規格、安裝與管理方式。