從9月份到國慶這段時(shí)間,因?yàn)榈昧伺畠海谑腔乩霞規(guī)兔α侠砑沂乱约芭惆槔掀藕团畠骸R粫r(shí)之間無暇顧及該系列教程的更新。等我回來的時(shí)候發(fā)現(xiàn)很多小伙伴私信我催更。在這里向支持本人這一拙劣教程的各位小伙伴表示真誠的感謝。言歸正傳,讓我們開始吧
之前我們根據(jù)lua語言配置了基于lsp的代碼高亮、自動(dòng)跳轉(zhuǎn)、自動(dòng)補(bǔ)全等等功能,那個(gè)時(shí)候我們安裝了很多插件,像 nvim-lspconfig、nvim-lsp-installernvim-cmp等等,每個(gè)插件都在干嘛,雖然我們配置好了 lua相關(guān)的內(nèi)容,但是可能仍然有小伙伴有疑問,碰到其他語言該如何配置,是不是要重新下載對(duì)應(yīng)的插件呢?為了解答這些問題,這篇文章我們將要來根據(jù) c++和 python的日常習(xí)慣來進(jìn)行配置,給大家演示一下在上述內(nèi)容都配置完成之后面對(duì)其他語言我們該如何進(jìn)行處理
安裝配置 c++ 相關(guān)的lsp服務(wù)
關(guān)于c++ 的服務(wù),我們根據(jù) nvim-lsp-installer
官方給出的表格中顯示它可以使用 ccls
和 clang
,這里我們以 ccls
作為示例進(jìn)行講解。
首先通過命令安裝 :LspInstall ccls
接著我們新建一個(gè) ftplugin/c.lua
和 ftplugin/cpp.lua
來配置 c/c++
。不過他們兩個(gè)采用相同的配置,我們暫時(shí)將一份配置復(fù)制兩遍
require("lsp/cpp")
他們的作用只有一個(gè),那就是加載 lsp/cpp
這個(gè)文件,我們將他們的配置放到一個(gè)文件中
然后我們再在 lua/lsp/cpp.lua
文件中加入以下內(nèi)容用于啟動(dòng) lsp服務(wù)端
local lspconfig = require('lspconfig')
lspconfig.ccls.setup {
init_options = {
cache = {
directory = ".ccls-cache";
};
}
}
我們進(jìn)入一個(gè) .c/.cpp
文件發(fā)現(xiàn)已經(jīng)加載了 ccls
了。如果沒有加載可以使用 :LspStart
命令手工加載或者使用 LspInfo
查看是否有問題
現(xiàn)在我們已經(jīng)可以看到lsp服務(wù)給出的提示了
修改之前的配置
我們在第22篇文章中給出了基于 lsp
的 lua
的配置,主要是使用 lsp
服務(wù)端的配置和對(duì)應(yīng)的跳轉(zhuǎn)之類的快捷鍵配置,我們將它放到了 lsp/lua.lua
目錄下了。但是一想想我們使用 c++
、Python
或者其他什么語言的時(shí)候,這些快捷鍵應(yīng)該是不會(huì)修改的,這個(gè)時(shí)候自然就想到了要重用快捷鍵了。所以來配置之前的第一件事就是想辦法重用這些快捷鍵。
這個(gè)時(shí)候我們想到的辦法就是將之前定義的快捷鍵封裝成函數(shù),然后在 on_attach
的回調(diào)函數(shù)中調(diào)用該函數(shù)。我們將那些快捷鍵定義放到 lua/keybindings.lua
中
local lsp_keybinds = {}
lsp_keybinds.set_keymap = function (bufnr)
-- 跳轉(zhuǎn)到聲明
vim.api.nvim_buf_set_keymap(bufnr, "n", "gd", "<cmd>lua vim.lsp.buf.declaration()<CR>", {silent = true, noremap = true})
-- 跳轉(zhuǎn)到定義
vim.api.nvim_buf_set_keymap(bufnr, "n", "gD", "<cmd>lua vim.lsp.buf.definition()<CR>", {silent = true, noremap = true})
-- 顯示注釋文檔
vim.api.nvim_buf_set_keymap(bufnr, "n", "gh", "<cmd>lua vim.lsp.buf.hover()<CR>", {silent = true, noremap = true})
-- 跳轉(zhuǎn)到實(shí)現(xiàn)
vim.api.nvim_buf_set_keymap(bufnr, "n", "gi", "<cmd>lua vim.lsp.buf.implementation()<CR>", {silent = true, noremap = true})
-- 跳轉(zhuǎn)到引用位置
vim.api.nvim_buf_set_keymap(bufnr, "n", "gr", "<cmd>lua vim.lsp.buf.references()<CR>", {silent = true, noremap = true})
-- 以浮窗形式顯示錯(cuò)誤
vim.api.nvim_buf_set_keymap(bufnr, "n", "go", "<cmd>lua vim.diagnostic.open_float()<CR>", {silent = true, noremap = true})
vim.api.nvim_buf_set_keymap(bufnr, "n", "gp", "<cmd>lua vim.diagnostic.goto_prev()<CR>", {silent = true, noremap = true})
vim.api.nvim_buf_set_keymap(bufnr, "n", "gn", "<cmd>lua vim.diagnostic.goto_next()<CR>", {silent = true, noremap = true})
end
return lsp_keybinds
我們將它打包到lsp_keybinds
模塊中作為 keybinds.lua
文件的導(dǎo)出模塊。然后在 lsp/lua.lua
文件的 on_attach
函數(shù)中調(diào)用這個(gè)函數(shù)完成快捷鍵的配置工作
local lsp_set_keymap = require("keybindings")
local on_attach = function(_, bufnr)
lsp_set_keymap.set_keymap(bufnr)
end
現(xiàn)在我們就完成了 c/c++
相關(guān)的配置
嘗試一下綁定的那些快捷鍵,發(fā)現(xiàn)它可以正常進(jìn)行跳轉(zhuǎn)
是不是很簡單了,我們沒有安裝任何的插件,只是安裝了 c++
lsp
的服務(wù)端。剩下的配置依然延續(xù)之前的就好了
python 相關(guān)配置
我們再來以 python
的配置作為例子來講lsp的配置。python
的服務(wù)端我們采用 pyright
。還有一個(gè)方法可以安裝 lsp
服務(wù)。我們可以在命令模式中輸入 :LspInstallInfo
查看當(dāng)前已安裝的 lsp
服務(wù)。下面會(huì)列出一堆的未安裝的 lsp
服務(wù)。這個(gè)時(shí)候我們可以將光標(biāo)移動(dòng)到某個(gè)服務(wù)上,按下 i
來安裝該服務(wù)。
這里我提前已經(jīng)安裝好了,所以它顯示在 Installed Server 中,沒有安裝它應(yīng)該顯示在下方的Available Server 列表中。
安裝完成之后我們還是按照慣例,在 ftplugin
目錄下建立一個(gè) python.lua
文件并且在該文件中加載 lua/lsp/python.lua
文件
我們在 lua/lsp/python.lua
文件中加入下面的代碼
local lsp_set_keymap = require("keybindings")
local util = require 'lspconfig/util'
require('lspconfig').pyright.setup{
on_attach = function(_, bufnr)
lsp_set_keymap.set_keymap(bufnr)
end,
cmd = { "pyright-langserver", "--stdio" },
filetypes = { "python" },
settings = {
python = {
analysis = {
autoSearchPaths = true,
diagnosticMode = "workspace",
useLibraryCodeForTypes = true,
typeCheckingMode = "off"
},
},
},
root_dir = function(fname)
local root_files = {
'pyproject.toml',
'setup.py',
'setup.cfg',
'requirements.txt',
'Pipfile',
'pyrightconfig.json',
}
return util.root_pattern(unpack(root_files))(fname) or util.find_git_ancestor(fname) or util.path.dirname(fname)
end,
}
前面的配置與 c++
的配置類似。主要設(shè)置快捷鍵,這里需要注意的是 root_dir
這里的配置,想要在對(duì)應(yīng)緩沖中啟動(dòng)相應(yīng)的 lsp
服務(wù),需要buffer
處在對(duì)應(yīng)語言的項(xiàng)目中,root_dir
規(guī)定在 buffer
所在目錄中存在這些文件或者目錄時(shí)將該目錄作為對(duì)應(yīng)項(xiàng)目文件
如果我們不加該配置,可能會(huì)導(dǎo)致lsp
服務(wù)啟動(dòng)失敗。如果失敗的話我們使用 :LspInfo
來查看失敗原因
這個(gè)根目錄設(shè)置是可以作用于它下面所有子目錄的。這里我根據(jù) python
中常用文件給出了一個(gè)列表,各位小伙伴可以根據(jù)自己的需求自行添加
另外需要注意的一個(gè)問題時(shí),pyright
依賴于 node
的 work_threads
模塊,該模塊從12版本以后才被支持,如果小伙伴的 node
版本低于該版本需要考慮升級(jí) node
根據(jù)這兩個(gè)例子,相信各位已經(jīng)熟悉了該如何配置不同語言的 lsp
服務(wù)了。這里面沒有什么深?yuàn)W的代碼,也沒有什么個(gè)性化到只有自己才會(huì)用的配置,希望能起到拋磚引玉的作用,后面再碰到什么其他語言小伙伴們應(yīng)該可以很容易的添加它的lsp服務(wù)了。