8  編輯器之道:Neovim

Neovim 是 Vim 的現代化分支,提供更好的擴展性和更活躍的開發社群。

8.1 為什麼選擇 Neovim?

  • Lua 設定:比 VimL 更直覺
  • 內建 LSP:原生語言伺服器支援
  • 非同步插件:不會卡住編輯器
  • 活躍社群:豐富的現代插件

8.2 安裝

背景(問題發現):傳統的 Vim 雖然強大,但在擴展性和現代化功能上有所限制。Neovim 作為 Vim 的現代化分支,提供了更好的插件架構、內建 LSP 支援,以及用 Lua 設定的能力。

方法:使用 Homebrew 套件管理器來安裝 Neovim,這是 macOS 上最簡單且可靠的安裝方式。Homebrew 會自動處理依賴關係和版本更新。

結果(程式碼)

brew install neovim

討論/延伸: - 安裝後可用 nvim --version 確認版本(建議 0.9.0 以上) - Linux 用戶可用 sudo apt install neovim 或從原始碼編譯 - Windows 用戶可用 Scoop 或 Chocolatey 安裝 - 首次啟動會比較慢,因為需要編譯語法檔案

8.3 基礎框架:NvChad

背景(問題發現):從零開始設定 Neovim 需要花費大量時間選擇插件、配置 LSP、設計主題和快捷鍵。初學者容易在設定階段就放棄,而經驗豐富的用戶也希望有個良好的起點。

方法NvChad 是一個預配置的 Neovim 框架,提供了: - 精美的 UI 主題和狀態欄 - 合理的預設快捷鍵映射 - 插件管理器(lazy.nvim)預配置 - LSP、自動補全、語法高亮等現代功能開箱即用 - 清晰的目錄結構,方便擴展

結果(程式碼)

git clone https://github.com/NvChad/NvChad ~/.config/nvim --depth 1
nvim

討論/延伸: - --depth 1 只克隆最新版本,節省空間和時間 - 首次啟動 nvim 會自動安裝所有插件(需要網路連線) - 安裝完成後會看到歡迎畫面,按 <Space>th 可切換主題 - 其他類似框架:LazyVimAstroNvim(各有特色,可依喜好選擇) - 建議先使用預設設定一段時間,了解後再自訂

8.4 目錄結構

~/.config/nvim/
├── init.lua           # 入口點
├── lua/
│   ├── options.lua    # 編輯器選項
│   ├── mappings.lua   # 快捷鍵設定
│   ├── plugins/       # 插件設定
│   └── configs/       # 插件配置
└── lazy-lock.json     # 插件版本鎖定

8.5 基本選項

背景(問題發現):Neovim 的預設設定雖然功能完整,但不一定符合現代編輯習慣。例如預設沒有相對行號(對 Vim 動作很重要)、沒有自動換行、沒有拼寫檢查等。每個開發者都需要根據自己的工作流程調整這些基本選項。

方法:在 lua/options.lua 中使用 vim.opt API 來設定編輯器選項。這個 API 比傳統的 set 命令更符合 Lua 語法,支援表格、布林值等原生型別。核心概念是讓編輯器更符合現代開發習慣: - 相對行號配合 Vim 動作(如 5j 跳 5 行) - 智慧換行保持文字可讀性 - 一致的縮排和空格使用 - 保持游標周圍的上下文可見 - 英文拼寫檢查避免錯字

結果(程式碼)

-- lua/options.lua
local opt = vim.opt

opt.relativenumber = true  -- 相對行號
opt.wrap = true            -- 自動換行
opt.linebreak = true       -- 在單詞邊界換行
opt.expandtab = true       -- Tab 轉空格
opt.shiftwidth = 2         -- 縮排寬度
opt.tabstop = 2            -- Tab 寬度
opt.scrolloff = 10         -- 保持游標上下可見行數
opt.spell = true           -- 拼寫檢查
opt.spelllang = { "en_us" }

討論/延伸: - relativenumber 搭配 number 可同時顯示絕對和相對行號 - shiftwidthtabstop 設為 2 適合 JavaScript/TypeScript,Python 可能需要 4 - scrolloff = 10 讓游標始終在螢幕中央,避免頻繁捲動 - 可用 opt.spelllang = { "en_us", "cjk" } 加入中文支援避免誤報 - 其他常用選項:opt.clipboard = "unnamedplus"(系統剪貼簿整合)、opt.ignorecase = true(搜尋時忽略大小寫)

8.6 插件管理:lazy.nvim

背景(問題發現):傳統的插件管理器(如 vim-plugpacker.nvim)在啟動時會載入所有插件,導致 Neovim 啟動速度變慢。當插件數量增加到 20-30 個時,啟動時間可能超過 1 秒,影響工作效率。而且插件的依賴關係和版本管理也較為複雜。

方法lazy.nvim 採用「延遲載入」(lazy loading)策略,只在真正需要時才載入插件。核心概念: - 事件觸發載入event = "BufReadPost" 表示在讀取檔案後才載入 - 命令觸發載入cmd = "CommandName" 表示在執行特定命令時才載入 - 檔案類型載入ft = "python" 表示只在 Python 檔案中載入 - 模組化設定:每個插件獨立一個檔案,便於管理和版本控制

結果(程式碼)

-- lua/plugins/example.lua
return {
  "username/plugin-name",
  event = "BufReadPost",  -- 延遲載入
  config = function()
    require("plugin-name").setup({})
  end,
}

討論/延伸: - 常用的延遲載入事件:VeryLazy(最低優先級)、BufReadPre(讀取前)、InsertEnter(進入插入模式) - lazy = false 可強制在啟動時載入(適用於 UI 插件如主題、狀態欄) - dependencies = { "other-plugin" } 可聲明插件依賴關係 - 用 :Lazy 命令可查看所有插件狀態、更新、清理未使用的插件 - 用 :Lazy profile 可分析啟動時間,找出瓶頸 - lazy.nvim 會自動生成 lazy-lock.json 鎖定版本,確保團隊環境一致

8.7 必備插件

插件 功能
telescope.nvim 模糊搜尋
nvim-treesitter 語法高亮
nvim-lspconfig LSP 設定
nvim-cmp 自動補全
gitsigns.nvim Git 整合

8.8 推薦插件清單

以下是依據實際使用經驗整理的插件推薦,按功能分類:

8.8.1 導航與搜尋

插件 功能 說明
telescope.nvim 模糊搜尋 Neovim 生態系的核心,幾乎所有東西都能搜
flash.nvim 快速跳轉 用標籤快速跳到畫面任何位置
harpoon 檔案書籤 標記常用檔案,一鍵切換
oil.nvim 檔案管理 用 buffer 編輯檔案系統,超直覺

8.8.2 UI 美化與體驗

插件 功能 說明
noice.nvim 訊息 UI 取代內建的命令列和通知,更現代化
dressing.nvim 輸入框美化 vim.ui.selectvim.ui.input 更好看
fidget.nvim LSP 進度 右下角顯示 LSP 載入狀態
barbecue.nvim 麵包屑導航 頂部顯示目前位置(類似 VS Code)

8.8.3 程式碼編輯

插件 功能 說明
LuaSnip 程式碼片段 強大的 snippet 引擎,支援動態內容
nvim-surround 括號操作 快速增刪改括號、引號等
Comment.nvim 註解 gc 快速註解程式碼
treesj 拆分合併 一鍵拆分/合併程式碼區塊
dial.nvim 增減強化 Ctrl+a/x 支援日期、布林值等

8.8.4 LSP 增強

插件 功能 說明
lspsaga.nvim LSP UI 更漂亮的 hover、rename、code action
trouble.nvim 診斷清單 集中顯示所有錯誤和警告
aerial.nvim 大綱視圖 顯示程式碼結構,快速跳轉

8.8.5 Git 整合

插件 功能 說明
gitsigns.nvim Git 狀態 行號旁顯示增刪改,支援 blame
neogit Git 客戶端 類似 Magit 的完整 Git 介面
gitgraph.nvim Git 圖形 視覺化分支歷史

8.8.6 AI 輔助

插件 功能 說明
avante.nvim AI 編輯 類似 Cursor 的 AI 編輯體驗
codecompanion.nvim AI 對話 支援多種 LLM 的程式碼助手
codeium.nvim AI 補全 免費的 AI 程式碼補全

8.8.7 Markdown 與寫作

插件 功能 說明
render-markdown.nvim Markdown 渲染 在編輯器內即時渲染 Markdown
markdown-preview.nvim 預覽 瀏覽器即時預覽
zen-mode.nvim 專注模式 隱藏干擾,專心寫作
pangu.vim 中英排版 自動在中英文間加空格

8.8.8 實用工具

插件 功能 說明
todo-comments.nvim TODO 高亮 高亮 TODO、FIXME 等註解
yanky.nvim 複製歷史 記錄複製歷史,可回溯貼上
better-escape.nvim 快速離開 jk 離開插入模式,無延遲
bigfile.nvim 大檔優化 開啟大檔時自動停用耗資源功能
Note不需要全部安裝

以上是經過篩選的推薦清單,請根據自己的需求選擇。寧可少裝幾個,也不要讓 Neovim 變得臃腫。建議從核心插件開始,遇到需求再逐步添加。

8.9 打造個人 Wiki:Markdown 編輯的魔法

如果你像我一樣用 Markdown 來管理筆記、知識庫或個人 Wiki,以下是一些讓編輯體驗更順暢的設定技巧。

8.9.3 mkdnflow:Wiki 導航的核心

mkdnflow.nvim 是讓 Neovim 變成 Wiki 編輯器的關鍵:

  • <CR>(Enter):在 wikilink 上按 Enter 就跳轉,檔案不存在會自動建立
  • <BS>(Backspace):返回上一個檔案,就像瀏覽器的上一頁
  • <Tab> / <S-Tab>:在連結間快速跳轉
  • ]] / [[:跳到下/上一個標題
require("mkdnflow").setup({
  links = {
    style = "wiki",  -- 使用 [[wikilink]] 風格
    transform_explicit = function(text)
      -- 自動把空格轉底線、轉小寫
      return text:gsub(" ", "_"):lower()
    end,
  },
  mappings = {
    MkdnEnter = { { "n", "v" }, "<CR>" },
    MkdnGoBack = { "n", "<BS>" },
    MkdnNextLink = { "n", "<Tab>" },
    MkdnPrevLink = { "n", "<S-Tab>" },
  },
})

8.9.4 草稿發佈提醒

寫部落格或技術文章時,常常會忘記把 draft: true 改成 false。這個自動命令會在儲存時提醒你:

vim.api.nvim_create_autocmd("BufWritePre", {
  pattern = "*.md",
  callback = function()
    local lines = vim.api.nvim_buf_get_lines(0, 0, -1, false)
    for i, line in ipairs(lines) do
      if line:match("draft: true") then
        local response = vim.fn.input("Ready to publish? (y/n): ")
        if response == "y" then
          lines[i] = line:gsub("draft: true", "draft: false")
          vim.api.nvim_buf_set_lines(0, 0, -1, false, lines)
        end
        break
      end
    end
  end,
})
Tip為什麼這樣設計?

這些看似瑣碎的自動化,累積起來會大幅提升筆記體驗:

  • 降低摩擦:建立新筆記零成本,不用手動填 frontmatter
  • 自動建立連結:知識網絡自然形成,不用刻意維護
  • 減少遺忘:草稿發佈提醒避免尷尬

當寫筆記變得像呼吸一樣自然,你就會更願意記錄想法。

8.10 LSP 設定

背景(問題發現):沒有 LSP(Language Server Protocol)的編輯器就像沒有智慧的文字編輯器,缺少: - 自動補全和智慧提示 - 跳轉到定義和參考 - 即時錯誤診斷 - 重構功能(重新命名、提取函數等) - 懸停文件顯示

每種程式語言都需要對應的 Language Server,而且需要正確設定才能發揮作用。

方法:使用 nvim-lspconfig 插件來配置各語言的 LSP Server。核心概念: 1. 安裝 Language Server:用 Mason:MasonInstall pyright)或系統套件管理器安裝 2. 設定 lspconfig:為每種語言呼叫對應的 setup() 函數 3. 特定語言配置:某些 Server 需要額外設定(如 Lua 需要識別 vim 全域變數)

結果(程式碼)

-- lua/configs/lspconfig.lua
local lspconfig = require "lspconfig"

-- Python
lspconfig.pyright.setup {}

-- TypeScript
lspconfig.ts_ls.setup {}

-- Lua
lspconfig.lua_ls.setup {
  settings = {
    Lua = {
      diagnostics = {
        globals = { "vim" },
      },
    },
  },
}

討論/延伸: - Mason 整合:建議用 :Mason UI 來安裝和管理 Language Servers,避免手動處理路徑 - 常用 Language Servers: - Python: pyright(快速)或 pylsp(功能多) - JavaScript/TypeScript: ts_ls(官方) - Go: gopls、Rust: rust_analyzer - HTML/CSS: html, cssls - Lua 特殊設定globals = { "vim" } 避免編輯 Neovim 配置時出現 vim 未定義警告 - 自訂能力:可在 setup() 中設定 on_attach(按鍵綁定)、capabilities(補全能力)等 - 除錯 LSP:用 :LspInfo 查看 LSP 狀態、:LspLog 查看日誌 - 效能優化:大型專案可用 root_dir 限制 LSP 範圍,避免掃描整個專案

8.11 常用快捷鍵

快捷鍵 功能
<Space>ff 搜尋檔案
<Space>fg 搜尋文字
gd 跳到定義
K 顯示文件
<Space>ca Code action
<Space>rn 重新命名

8.12 與 tmux 整合

背景(問題發現):開發時經常需要在多個視窗間切換,例如: - 編輯器(Neovim split) - 終端機(tmux pane) - 測試輸出 - 伺服器日誌

預設情況下,Vim split 用 Ctrl+w h/j/k/l 切換,而 tmux pane 用 Ctrl+b 加方向鍵,兩套不同的快捷鍵讓切換變得繁瑣且容易混淆。

方法:使用 vim-tmux-navigator 插件統一 Vim 和 tmux 的視窗切換邏輯。核心概念: 1. 統一快捷鍵:用 Ctrl+h/j/k/l 在所有視窗間切換(Vim 內部 split 和 tmux pane) 2. 智慧偵測:插件會自動判斷是否在邊界,決定是切換 Vim split 還是 tmux pane 3. 雙向整合:需要同時在 Neovim 和 tmux 配置中設定

結果(程式碼)

return {
  "christoomey/vim-tmux-navigator",
  lazy = false,
}

討論/延伸: - tmux 配置:需要在 ~/.tmux.conf 加入對應設定(參考插件文件) - lazy = false:此插件必須在啟動時載入,確保快捷鍵立即可用 - 注意事項:如果 tmux 設定了 prefix,需要確保不衝突 - 替代方案Navigator.nvim 提供類似功能,但支援更多終端複用器 - 除錯方法:如果切換不順,檢查 tmux 和 Neovim 是否都正確載入設定 - 延伸用途:搭配 tmux sessionizer(如 sesh)可實現專案間快速切換

8.13 實作練習

  1. 安裝 NeovimNvChad
  2. :Lazy 查看插件狀態
  3. <Space>ff 搜尋檔案
  4. 嘗試在 tmux pane 間切換
Tip學習曲線

Vim 的學習曲線陡峭,但值得投資。建議從 vimtutor 開始,每天練習 15 分鐘。

8.14 推薦 YouTube 教學頻道

如果你偏好透過影片學習,以下是幾個高品質的 Neovim 教學頻道:

頻道 特色 適合對象
typecraft 「Neovim for Newbs」系列,循序漸進 完全初學者
TJ DeVries Neovim 核心開發者,kickstart.nvim 作者 想深入理解原理者
ThePrimeagen 高能量、實戰導向,Vim 動作技巧 想提升效率者
Josean Martinez 完整設定教學,Mac 環境友善 想要完整配置者
devaslife 優美的影片風格,Web 開發導向 前端開發者
Note從 kickstart.nvim 開始

如果你不想用 NvChad 這類預設框架,可以考慮 kickstart.nvim。這是由 Neovim 核心開發者 TJ DeVries 維護的入門配置,只有一個 init.lua 檔案,註解詳盡,非常適合想要從頭理解 Neovim 配置的人。