天天看點

從零開始配置vim(21)——lsp簡介與treesitter 配置

作者:一葉障目0001

截止到上一篇文章,我們配置了neovim的很多内容了。具備了一些編輯器的常用功能了,而且可以勝任日常的文檔編輯工作了。但是想作為一個可靠的代碼編輯器還缺少重要的一環,即代碼文法部分的支援。

在過去的vim配置中,我們基于 you-complete-me這個插件配置。但是對于不懂c語言甚至vim的小白來說簡直是災難。各種相容問題、報錯頻出,而且效果也遠不如 visual studio code等編輯器。也有可能是我那個時候比較菜,當初針對 python配置的補全效果很一般隻能補全内置函數,自己定義的類和方法無法補全,而且跳轉時好時壞。後來我抛棄了vim很長一段時間。好在微軟提供了lsp這個大殺器,讓vim、emacs這類編輯器的代碼編輯體驗提升了很大一截。而且配置還相對簡單。

lsp 簡介

過去的編輯器包攬了諸如代碼高亮、文法分析、跳轉等功能,這樣就導緻了所有編輯器都有自己專有的一套顯示、跳轉等方案。而第三方編輯器想要達到完全相同的效果幾乎是不可能的。但是微軟提出的 lsp(language server protocol) 确改變了這一格局。

lsp最重要的就是将文法分析、跳轉、自動補全功能這些語言的核心功能和最終呈現效果分開。即server端主要提供了文法分析、補全、跳轉的核心功能,而在用戶端要做的就是調用服務端提供的這些功能來展示以及通過快捷鍵或者其他使用者接口以便使用者使用。而且語言伺服器是以程序的方式單獨運作,并不會影響用戶端的運作。它們之間通過本地網絡的形式進行資訊交換

從零開始配置vim(21)——lsp簡介與treesitter 配置
  • 使用者在工具中打開一個的檔案, 該工具通知語言伺服器文檔打開 (‘textDocument/didOpen’) 。 從現在起,有關文檔内容不再位于檔案系統上,而是儲存在編輯器開辟的一塊内容中
  • 使用者進行編輯:該工具通知伺服器文檔更改 (‘textDocument/didChange’) ,程式語義資訊由語言伺服器更新。 發生這種情況時,語言伺服器會分析此資訊,并通知工具 (‘textDocument/publishDiagnostics’) 檢測到的錯誤和警告,并且還可能傳回一些可能的用于補全的内容
  • 使用者對編輯器中的符号執行“轉到定義”:該工具發送具有兩個參數的“textDocument/definition”請求: (1) 文檔 URI, (2) 從伺服器啟動 Go to Definition 請求的文本位置。 伺服器使用文檔 URI 和符号定義在文檔中的位置進行響應。用戶端接到傳回後,根據伺服器标記的位置進行跳轉
  • 使用者關閉文檔 (檔案) :工具發送“textDocument/didClose”通知,通知語言伺服器文檔現在不再處于記憶體中,并且将目前内容儲存到檔案系統中。

treesitter 配置

我們簡單介紹過 neovim-treesitter 這個插件,它可以用來做代碼高亮。它采用 lsp 協定實作,比起單純使用正規表達式來說,它具有更好的渲染效果。那麼我們體驗 lsp 效果的第一步就來配置它吧。

treesitter 想要工作,需要根據語言下載下傳配套語言對應的文法解析子產品,我們可以使用 :TSInstallInfo 來檢視目前我們安裝了哪些解析子產品。

我們發現并沒有安裝任何的子產品,基于目前配置檔案的工程,我們先來體驗一下 lua 的效果。

我們使用 :TSInstall <language>的指令可以下載下傳指定語言的子產品。這裡我們使用 :TSInstall lua 來下載下傳lua子產品。後續我們可以使用 :TSUpdate lua 來更新該子產品。跟 packer 類似的 :TSUpdate 即可以用來下載下傳也可以用來更新。也就是一條指令就搞定了

安裝完成之後我們可以使用 :TSBufToggle highlight 來使用 treesitter 進行高亮

從零開始配置vim(21)——lsp簡介與treesitter 配置

如果我們每次都需要手工調用指令來進行高亮的話,就太不智能了。我們可以在配置檔案中配置它自動加載文法高亮。

require('nvim-treesitter.configs').setup({                                               
    -- 支援的語言
    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()'
-- 預設不折疊
vim.wo.foldlevel = 99
           

我們來一條條地解釋這些配置

ensure_installed 表示需要支援哪些語言,如果裡面設定了某些語言,那麼在啟動之後它會自動調用 :TSUpdate 來下載下傳和更新對應語言的 server 部分。

等它下載下傳完了對應的語言子產品之後,我們發現它已經很好地完成了代碼着色的功能。

增量選擇可以一次選擇一塊的代碼,依次擴大或者縮小所選擇的語言塊,我們使用回車來開始和擴大增量選擇,使用倒退鍵來減少增量選擇代碼塊。各位小夥伴可以根據自己的習慣來定義快捷鍵

從零開始配置vim(21)——lsp簡介與treesitter 配置

另外我們可以使用 = 來格式化代碼。為了友善我們定義自動指令,每當執行 :w 寫入前前自動格式化代碼

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``'
})
           

這裡因為提前使用了 gg改變了光标位置,在格式化之後使用 `` 來回到上次跳轉之前的位置。

從零開始配置vim(21)——lsp簡介與treesitter 配置

最後我們可以使用 zc 和 zo 來折疊和展開代碼。不過我自己很少用,需要檢視檔案中的符号例如函數、變量等我可以使用其他插件來解決,如果要成塊的跳轉代碼我比較喜歡使用 %。

從零開始配置vim(21)——lsp簡介與treesitter 配置

好了,到此為止我們先體驗了一下基于 lsp 實作的 treesitter 的功能,後面将展開講述 lsp 對一些語言的支援,敬請期待

繼續閱讀