Neovim 設定文件結構與基礎功能設定
前言
Neovim 同時支援使用 VimScript 和 Lua 語言來撰寫設定文件,前者源自於它的老祖 Vim,而後者則是一種極爲輕量的 Scripting language,同時亦是 Neovim 有別於 Vim 最大的特點之一:它更加易學、具有更好的工具支持與易擴展性、以及更高的執行效能,這都是你應該選擇使用 Lua 而非 VimScript 原因,唯一導致你必須使用 VimScript 的理由大概只有,當你想與 Vim 共用你的這份設定文件的時候。
有鑑於我已經不太使用 Vim 了,且我也更加喜歡 Lua 的設定模式,故本系列文都將使用 Lua 來撰寫設定文件,如果你是從 Vim 轉過來的 VimScript 使用者,放心,Lua 比 VimScript 簡單多了,順着設定文件讀下去,想必就能學會個七、八成了吧。
在本章裡,我將介紹 Neovim 的設定文件結構,分享與說明我的基礎功能設定,以及安裝部分依賴程式以啟用特定功能,如果想直接看我的設定和設定項說明,也可以直接跳到 基礎設定說明 一段閱讀。
而如果想直接複製我的設定文件,可以到這裡(我的 github)來複製完整版的內容。
建立設定文件與引用
設定文件在哪裡?
遇事不決,先問 help page,讓我們輸入:h config
,來看看有沒有什麼有用的資訊:
有了,在 Unix 環境下,Config file 的位置應該在 ~/.config/nvim/init.lua
,而這也就是 Neovim 每次在起動時,讀取設定文件的入口處。
註:如果你在電腦中找不到文件,甚至相關的資料夾,請直接創建一個就可以了。
接著,讓我們來試寫第一段 Lua 程式,看看 Neovim 會不會正常運行它吧,編輯 init.lua
:
1 | print("Hello!") |
重新啓動 Neovim,你應該就可以看到文字訊息被打印出來了。
另外,如果你因爲輸入了什麼而錯過任何系統訊息,想重看完整內容的話,可以在開啟 Neovim 後,輸入:message
來查看所有的歷史訊息,或是輸入:{count} mes
來查看最近的 {count} 筆訊息,例如:1 mes
。
建立文件結構
以下將是我們接下來會採用的文件結構:
init.lua
:作為設定文件的入口,負責引用其他的設定文件。lua/
:當我們在 Lua 中引用其他文件時,Lua 會優先引用./lua/?.lua
中的文件,如果不存在,才會去使用./?.lua
中的文件。例如:當我們在
init.lua
中引用test.lua
時,Lua 會優先使用./lua/test.lua
,如果不存在,才會去使用./test.lua
。我的建議是,為了避免將來管理混亂,還是乖乖地把所有設定檔放在
lua/
裡頭會比較好。imp/
:這層資料夾將作為命名空間,用意是避免當 Lua 在引用其他外掛的設定時,出現意外的文件名稱衝突,你可以將這個資料夾以任何你喜歡的方式命名,例如:user/
、launch/
、或是和我一樣以 id 的前三碼命名。options.lua
:這將會是我們的第一個設定文件,用來對 Neovim 的基礎功能進行設定,詳細內容將在後續介紹。
引用設定文件
最後,讓我們來引用我們的第一個設定文件吧,編輯init.lua
:
1 | require("imp/options") |
require("{filename}")
:此函式將會引用./lua/{filename}.lua
。
接著做為測試,讓我們編輯options.lua
:
1 | print("Hi, I'm options") |
重啓 Neovim,此時我們就可以看到option.lua
的內容被成功引用了:
基礎設定說明
Lua API
Neovim 提供了一套完整的 Lua library,其所提供的 API 讓我們的設定文件可以輕鬆使用 Lua 語言來與 Neovim 進行交互。這些 API 大多都以vim.
做爲前綴,例如:
API | 用途 | 例子 | 對應的 VimScript |
---|---|---|---|
vim.opt |
用於設置和訪問全局選項 | vim.opt.number = true |
set number |
vim.g |
用於設置和訪問全局變量 | vim.g.my_var = 'hello' |
let g:my_var = 'hello' |
vim.cmd |
用於執行 Vim 命令(Ex 命令) | vim.cmd("new") |
:new |
所以,我們可以如此編輯 options.lua
:
vim.opt.number = true |
儲存後重新起動 Neovim,你就會發現左側的行號被開啓了。Neovim就是透過這樣的方式,在每次啟動時引用設定文件,並根據其中的設定來變更編輯器的行為。
設定選項的魔法 —— :options
如果每次測試設定選項都必須要一項一項的查找,並反覆開關 Neovim 來測試效果的話,那也太麻煩了,所幸,Neovim 提供了即時改變選項的魔法:options
:
這裡提供了所有設定的分類目錄,以及各選項的簡述與選項內容,我們同樣可以使用/
進行關鍵字搜尋,或將遊標移動到有興趣的目錄上,並按下<Enter>
來查看目錄內容。
接著,我們可以將遊標移動到設定的選項上,然後按下<Enter>
,或甚至直接修改字串內容,就可以發現選項被套用了。
這個設定不會被記錄,所以你可以隨意嘗試各種不同的設定,再將你喜歡的一條條記錄到設定檔中,我相當推薦各位有空的時候可以來這裡摸索一下,有時或許會發現一些神奇又實用的功能。
options.lua
完整說明
以下我將對我的設定項目進行分類介紹,完整的設定檔可以到這裡(我的 github)查看,你可以直接複製再根據需求進行微調;而由於項目有點多,且有部分我已經標上註解了,所以我這裡只會對一些我認為比較重要的,以及比較容易有疑慮的選項進行說明。
basic
0 | -- basic -- |
clipboard
:
剪貼簿應該是每個剛入坑 Neovim 的人都會遇到的問題之一,你會發現你在 Neovim 外複製的東西無法直接使用指令p
來貼上,同樣地,我們在 Neovim 中使用y
複製的東西,也無法貼到 Neovim 外的其他地方,這是因爲 Neovim 預設的剪貼簿和系統是不同的,所以我們需要對其進行設定。
另外,我們還需要在系統中額外安裝剪貼簿工具,才能讓它正常作用,我這裡使用的是 Xclip:安裝完成後,複製貼上的功能應該就可以正常使用了。sudo apt-get install xclip
virtualedit
:
在預設情況,當我們使用 V-Block 模式時,我們是無法將遊標移動到行尾之後的部分的,即便圈選的其他行在這之後仍有內容:
而當我們將其設為block
之後,Neovim 就可以將這樣的行尾視為空白一起圈選起來了。
另外,它還提供了其他模式,不過我沒有使用過,所以這裡就不做贅述了。iskeyword:append("-")
:
當我們使用w
等指令進行單字間的跳躍時,Neovim 會把一些被特殊符號(例如:’-‘)所隔開的字視為兩個獨立的單字,我們可以透過這條設定,來將被這些符號分割的文字視為一個完整的單字。
backup
10 | -- backup -- |
swapfile
:
當不正常關閉 Neovim 時,它會爲當下正在開啓的檔案建立備份,並在下一次開啓時詢問要不要復原備份,由於我有動不動就存檔的習慣,以及它有時不知道爲什麼會到處出現,讓我覺得很煩,所以我習慣將它關閉。undofile
:
如果你希望可以在關閉文件後,在下一次開啓時還可以保留上次的操作記錄,來讓你使用指令u
和C-r
來還原上/下一步,那麼你可以選擇將這個選項開啓。
line number and line column
14 | -- line number and line column -- |
relativenumber
:
相對行號在進行跳轉和多行操作時很有用,我相當推薦將它開啓。而下圖則是官方提供的number(nu)
和relativenumber(rnu)
開關時的顯示對照圖:
tab and indentation
20 | -- tab and indentation -- |
tabstop
:指的是當文件中有 tab 字符時,會將其顯示成幾個空格的寬度,以及當在 insert mode 按下<Tab>
時,會將連續多少的空格轉換成 tab 字符。softtabstop
:當在 insert mode 按下<Tab>
時,會插入多少個空格。shiftwidth
:當使用>>
或<<
進行縮排,以及新增一行時自動縮排所移動的空格數。註:這可能有點複雜,舉個例子,當設定為
tabstop=8
,softtabstop=4
,shiftwidth=2
時,在 insert mode 中按第一次<Tab>
會插入4個空格,再按一次則會將8個空格轉為1個 tab 字符,按第三次則會變成1個 tab 字符加上4個空格,以此類推。
而當我使用>>
或<<
,或是新增一行符合自動縮排的條件時,則整行會移動2個空格。smarttab
:當開啓時,當在行首進入 insert mode 插入<Tab>
時,會根據shiftwidth
的設定來插入空格,否則會插入根據softtabstop
來插入,我覺得這相當混淆人,所以我選擇把它關閉。expandtab
:將所有 tab 字符都擴展成空格,如果設為true
,則上述的轉換規則就不適用了,所有的 tab 都會變成相應數量的空格。
wrap and scrolloff
29 | -- wrap and scrolloff -- |
wrap
:當你的文字長度超出視窗邊框時,是否換行顯示。scrolloff
:當視窗 上/下 捲動時,顯示在遊標 上/下 的行數,如果你希望畫面捲動時,遊標始終在正中央的位置,可以選擇把它設成 999 之類的極大數字。sidescrolloff
:和 scrolloff 相同,不過是左右方向的。
search
34 | -- search -- |
smartcase
:當搜尋的 pattern 中有大寫時,搜尋會變成 case sensitive,否則 ignore case,另外如果將它設為 true,它會覆蓋掉 ignorecase 選項的設定。
splitting windows
40 | -- splitting windows -- |
當分割視窗時,Neovim 預設分割新視窗是開在左上的,這太反人類了,所以你可以透過第一二條設定來把它改成開在右下。
而 equalalways
的作用則是當分割出新視窗時,要不要自動調整平分所有視窗的長寬,如果設為 false,則它只會將最右或最下側的視窗平分而已
equalalways = true
equalalways = false
appearance
45 | -- appearance -- |
showtabline
:設為 0 時永不顯示,1 時只有當存在兩個 tab 以上時才會顯示,2 則永遠顯示。cursorline
:開啓會將遊標所在行的行數加上醒目提示,如果想將所在列也標亮,可以調整cursorcolumn
選項。pumheight
:顯示彈出式菜單的最大行數。(之後使用 cmp 功能時才會有比較明顯的體現。)
auto-commenting
52 | vim.cmd("autocmd bufenter * set formatoptions-=cro") -- disable auto-commenting new lines |
如果你希望在註解行上用例如o
或O
等指令新增空白行時,會自動加上註解標籤的話,可以把這行刪掉,而我不喜歡它,所以我這裡把它關掉了。
依賴環境安裝與設定
還記得我們之前提過的:checkhealth
嗎,如果你現在打開它,應該會發現在 provider 一區裡,經過我們剛才對剪貼簿的處理,Clipboard 已經顯示為 OK 了:
接下來,由於我經常使用到 Python3 的開發環境,加上之後安裝的許多外掛也可能依賴於 Python3 provider,所以我這裡會將它安裝和設定起來。
安裝 python3
Ubuntu 22.04 中應該已經自帶 python3.10,如果沒有的話,可以透過以下的指令下載。
sudo apt-get install software-properties-common -y |
安裝 pip
pip 是 Python 的軟體包管理工具,是使用 Python 必須安裝的工具之一。
sudo apt-get install python3-pip -y |
安裝 pynvim
pynvim 就是 Neovim 之所以依賴於 Python3 的原因了,他是 Neovim 在 python 中的外掛。
python3 -m pip install --user --upgrade pynvim |
通常到這裏就結束了,不過如果你的系統中存在多個版本的 Python 的話,建議到 options.lua
中加入類似下面這條設定,來指定 Neovim 取用的 Python 路徑:
54 | vim.g.python3_host_prog = "/bin/pythin3" |
至此,再看:checkhealth provider
的話,應該就可以看到 Python3 一區也都變 OK 了,而至於其他 provider,由於目前還沒用到,加上我其實也對它們不是很了解,所以我沒有多做處理了。
後記
至此,就是本章的所有內容了,Neovim 終於至少看起來像個人,但離稱手還是有相當大的差距,而在下一章裡,我將會介紹如何設定快捷鍵(Keymaps)。
與這章的後半段類似,我會分享並說明我的 keymaps 設定,裡頭有許多我覺得實用甚至堪稱魔法的神奇設定,將在下一章誠心推薦給各位。
上一篇: 救救我啊我救我 —— help 與 checkhealth
下一篇: Neovim 快捷鍵設定