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 iao 輸入文字
Visual vV<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 複製、> / < 縮排/減少縮排、= 重新縮排。重複操作符通常代表整行,如 ddyycc

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,再以 @a10@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-lspconfigmason-org/mason.nvim lspconfig 協助設定語言伺服器;Mason 協助安裝工具。Neovim 原生提供 LSP client,但不會替你安裝 server。
補全 hrsh7th/nvim-cmpsaghen/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.nvimibhagwan/fzf-lua 模糊找檔、buffer、grep、Git 資訊;原生則有 :find:buffers、quickfix。
Git lewis6991/gitsigns.nvimtpope/vim-fugitive 行內變更標記與 Git 操作;Git 本身仍在終端執行。
Debug mfussenegger/nvim-daprcarriga/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.configvim.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" })

Kgdgr 等在此段是「你自行設定的 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. 日常工作流程

原生優先的專案巡覽流程

  1. 從專案根目錄開啟:nvim .nvim path/to/file
  2. :e 開檔、:ls 瀏覽既有 buffer;以 :vsplit 對照兩個檔案。
  3. /*:vimgrep 尋找符號或待辦,並用 :copen 在 quickfix 逐筆處理。
  4. ciwdap、Visual mode 等語意操作修改;以 :w 儲存並用 u / <C-r> 安全回退。
  5. :terminal 執行測試、formatter 或 Git;錯誤可由 :make 或 quickfix 導回來源。
  6. 在終端以 git statusgit diffgit 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 常需 xclipxselwl-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>

延伸閱讀