截止到上一篇文章,我們配置了neovim的很多內(nèi)容了。具備了一些編輯器的常用功能了,而且可以勝任日常的文檔編輯工作了。但是想作為一個(gè)可靠的代碼編輯器還缺少重要的一環(huán),即代碼語(yǔ)法部分的支持。
在過去的vim配置中,我們基于 you-complete-me這個(gè)插件配置。但是對(duì)于不懂c語(yǔ)言甚至vim的小白來(lái)說(shuō)簡(jiǎn)直是災(zāi)難。各種兼容問題、報(bào)錯(cuò)頻出,而且效果也遠(yuǎn)不如 visual studio code等編輯器。也有可能是我那個(gè)時(shí)候比較菜,當(dāng)初針對(duì) python配置的補(bǔ)全效果很一般只能補(bǔ)全內(nèi)置函數(shù),自己定義的類和方法無(wú)法補(bǔ)全,而且跳轉(zhuǎn)時(shí)好時(shí)壞。后來(lái)我拋棄了vim很長(zhǎng)一段時(shí)間。好在微軟提供了lsp這個(gè)大殺器,讓vim、emacs這類編輯器的代碼編輯體驗(yàn)提升了很大一截。而且配置還相對(duì)簡(jiǎn)單。
lsp 簡(jiǎn)介
過去的編輯器包攬了諸如代碼高亮、語(yǔ)法分析、跳轉(zhuǎn)等功能,這樣就導(dǎo)致了所有編輯器都有自己專有的一套顯示、跳轉(zhuǎn)等方案。而第三方編輯器想要達(dá)到完全相同的效果幾乎是不可能的。但是微軟提出的 lsp(language server protocol
) 確改變了這一格局。
lsp最重要的就是將語(yǔ)法分析、跳轉(zhuǎn)、自動(dòng)補(bǔ)全功能這些語(yǔ)言的核心功能和最終呈現(xiàn)效果分開。即server端主要提供了語(yǔ)法分析、補(bǔ)全、跳轉(zhuǎn)的核心功能,而在客戶端要做的就是調(diào)用服務(wù)端提供的這些功能來(lái)展示以及通過快捷鍵或者其他用戶接口以便用戶使用。而且語(yǔ)言服務(wù)器是以進(jìn)程的方式單獨(dú)運(yùn)行,并不會(huì)影響客戶端的運(yùn)行。它們之間通過本地網(wǎng)絡(luò)的形式進(jìn)行信息交換
- 用戶在工具中打開一個(gè)的文件, 該工具通知語(yǔ)言服務(wù)器文檔打開 ('textDocument/didOpen') 。 從現(xiàn)在起,有關(guān)文檔內(nèi)容不再位于文件系統(tǒng)上,而是保存在編輯器開辟的一塊內(nèi)容中
- 用戶進(jìn)行編輯:該工具通知服務(wù)器文檔更改 ('textDocument/didChange') ,程序語(yǔ)義信息由語(yǔ)言服務(wù)器更新。 發(fā)生這種情況時(shí),語(yǔ)言服務(wù)器會(huì)分析此信息,并通知工具 ('textDocument/publishDiagnostics') 檢測(cè)到的錯(cuò)誤和警告,并且還可能返回一些可能的用于補(bǔ)全的內(nèi)容
- 用戶對(duì)編輯器中的符號(hào)執(zhí)行“轉(zhuǎn)到定義”:該工具發(fā)送具有兩個(gè)參數(shù)的“textDocument/definition”請(qǐng)求: (1) 文檔 URI, (2) 從服務(wù)器啟動(dòng) Go to Definition 請(qǐng)求的文本位置。 服務(wù)器使用文檔 URI 和符號(hào)定義在文檔中的位置進(jìn)行響應(yīng)。客戶端接到返回后,根據(jù)服務(wù)器標(biāo)記的位置進(jìn)行跳轉(zhuǎn)
- 用戶關(guān)閉文檔 (文件) :工具發(fā)送“textDocument/didClose”通知,通知語(yǔ)言服務(wù)器文檔現(xiàn)在不再處于內(nèi)存中,并且將當(dāng)前內(nèi)容保存到文件系統(tǒng)中。
treesitter 配置
我們簡(jiǎn)單介紹過 neovim-treesitter
這個(gè)插件,它可以用來(lái)做代碼高亮。它采用 lsp
協(xié)議實(shí)現(xiàn),比起單純使用正則表達(dá)式來(lái)說(shuō),它具有更好的渲染效果。那么我們體驗(yàn) lsp
效果的第一步就來(lái)配置它吧。
treesitter
想要工作,需要根據(jù)語(yǔ)言下載配套語(yǔ)言對(duì)應(yīng)的語(yǔ)法解析模塊,我們可以使用 :TSInstallInfo
來(lái)查看當(dāng)前我們安裝了哪些解析模塊。
我們發(fā)現(xiàn)并沒有安裝任何的模塊,基于當(dāng)前配置文件的工程,我們先來(lái)體驗(yàn)一下 lua
的效果。
我們使用 :TSInstall <language>
的命令可以下載指定語(yǔ)言的模塊。這里我們使用 :TSInstall lua
來(lái)下載lua模塊。后續(xù)我們可以使用 :TSUpdate lua
來(lái)更新該模塊。跟 packer
類似的 :TSUpdate
即可以用來(lái)下載也可以用來(lái)更新。也就是一條命令就搞定了
安裝完成之后我們可以使用 :TSBufToggle highlight
來(lái)使用 treesitter
進(jìn)行高亮
如果我們每次都需要手工調(diào)用命令來(lái)進(jìn)行高亮的話,就太不智能了。我們可以在配置文件中配置它自動(dòng)加載語(yǔ)法高亮。
require('nvim-treesitter.configs').setup({
-- 支持的語(yǔ)言
ensure_installed = {"html", "css", "vim", "lua", "javascript", "typescript", "c", "cpp", "python"},
-- 啟用代碼高亮
highlight = {
enable = true,
additional_vim_regex_highlighting = false
},
--啟用增量選擇
incremental_selection = {
enable = true,
keymaps = {
init_selection = '<CR>',
node_incremental = '<CR>',
node_decremental = '<BS>',
scope_incremental = '<TAB>'
}
},
-- 啟用基于 Treesitter 的代碼格式化(=)
indent = {
enable = true
},
})
-- 開啟代碼折疊
vim.wo.foldmethod = 'expr'
vim.wo.foldexpr = 'nvim_treesitter#foldexpr()'
-- 默認(rèn)不折疊
vim.wo.foldlevel = 99
我們來(lái)一條條的解釋這些配置
ensure_installed
表示需要支持哪些語(yǔ)言,如果里面設(shè)置了某些語(yǔ)言,那么在啟動(dòng)之后它會(huì)自動(dòng)調(diào)用 :TSUpdate
來(lái)下載和更新對(duì)應(yīng)語(yǔ)言的 server
部分。
等它下載完了對(duì)應(yīng)的語(yǔ)言模塊之后,我們發(fā)現(xiàn)它已經(jīng)很好的完成了代碼著色的功能。
增量選擇可以一次選擇一塊的代碼,依次擴(kuò)大或者縮小所選擇的語(yǔ)言塊,我們使用回車來(lái)開始和擴(kuò)大增量選擇,使用退格鍵來(lái)減少增量選擇代碼塊。各位小伙伴可以根據(jù)自己的習(xí)慣來(lái)定義快捷鍵
另外我們可以使用 =
來(lái)格式化代碼。為了方便我們定義自動(dòng)命令,每當(dāng)執(zhí)行 :w
寫入前前自動(dòng)格式化代碼
local auto_indent = vim.api.nvim_create_augroup("AUTO_INDENT", {clear = true})
vim.api.nvim_create_autocmd({"BufWritePost"}, {
pattern = "*",
group = auto_indent,
command = 'normal! gg=G``'
})
這里因?yàn)樘崆笆褂昧?gg改變了光標(biāo)位置,在格式化之后使用 `` 來(lái)回到上次跳轉(zhuǎn)之前的位置。
最后我們可以使用 zc
和 zo
來(lái)折疊和展開代碼。不過我自己很少用,需要查看文件中的符號(hào)例如函數(shù)、變量等我可以使用其他插件來(lái)解決,如果要成塊的跳轉(zhuǎn)代碼我比較喜歡使用 %
。
好了,到此為止我們先體驗(yàn)了一下基于 lsp
實(shí)現(xiàn)的 treesitter
的功能,后面將展開講述 lsp
對(duì)一些語(yǔ)言的支持,敬請(qǐng)期待