Vim-LSP 筆記

其實我們每天都在用它,只是我們自己不知道。

什麼是 LSP?

一個協議(Protocal),把程式編輯器分為 Sever 跟 Client 兩個部分:

lsp

就跟網頁開發中的前後端一樣,後端才是那個真正幫你檢查語法或格式是否正確的人,而前端則是負責幫處理你眼前畫面的那個人。

Neovim 內建就有包含 client 端的部分,可以讓你用一些 LSP 相關的 API 來顯示語法錯誤、高亮醒目等等的功能。

至於 server 的部分則需要自己安裝,以前端來說的話會用 npm install -g typescript-language-server 來處理。不過多虧有人寫了 nvim-lsp-installer ,所以可以省下自己安裝的功夫。

推薦網站

實際配置

1. 安裝必要套件

1
2
use "neovim/nvim-lspconfig"
use "williamboman/nvim-lsp-installer"

2. 用 lsp-installer 安裝想要的 language server

1
:LspInstallInfo

3. 寫配置檔(setup)

這邊先說個概念,理論上每一個語言都會有不同的 setup,所以如果你想把檔案結構拆的比較細的話,就會有蠻多檔案的。因此這邊為了方便理解先全部寫成在一個檔案裡:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
-- lua/user/setup
-- 引入套件
local lsp_installer = require "nvim-lsp-installer"
local lsp_config = require "lspconfig"

-- 這個看起來是用來設定 installer 本身的 config,但其實是必要的一行,不可以拿掉。
require("nvim-lsp-installer").setup({
automatic_installation = true, -- 自動安裝(需重新重啟 neovim)
ui = {
icons = {
server_installed = "✓",
server_pending = "➜",
server_uninstalled = "✗"
}
}
})

-- 一定要有這一行 setup 你的 language server 才會啟動
lsp_config.sumneko_lua.setup{}

附註:其實 lspconfig 主要的用途就是讓你可以用比較簡單的方式來處理 code 而已,他本身是沒有任何 language server client 的功能的,詳細可以參考官方的 wiki

最後看到有出現語法檢查的效果就成功了。

關於 lsp_installer.on_server_ready()

在一些舊的設定中你可能會看到這樣的寫法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
local status_ok, lsp_installer = pcall(require, "nvim-lsp-installer")
if not status_ok then
return
end

-- Register a handler that will be called for all installed servers.
-- Alternatively, you may also register handlers on specific server instances instead (see example below).
lsp_installer.on_server_ready(function(server)
local opts = {
on_attach = require("user.lsp.handlers").on_attach,
capabilities = require("user.lsp.handlers").capabilities,
}

if server.name == "jsonls" then
local jsonls_opts = require("user.lsp.settings.jsonls")
opts = vim.tbl_deep_extend("force", jsonls_opts, opts)
end

if server.name == "sumneko_lua" then
local sumneko_opts = require("user.lsp.settings.sumneko_lua")
opts = vim.tbl_deep_extend("force", sumneko_opts, opts)
end

if server.name == "pyright" then
local pyright_opts = require("user.lsp.settings.pyright")
opts = vim.tbl_deep_extend("force", pyright_opts, opts)
end

-- This setup() function is exactly the same as lspconfig's setup function.
-- Refer to https://github.com/neovim/nvim-lspconfig/blob/master/doc/server_configurations.md
server:setup(opts)
end)

官方現在已經不建議這樣寫了,可以到這個 issue 中參考詳細內容。

現在建議的寫法:

1
2
3
4
5
6
7
-- 當作這行不存在(除非你想設置其他 config)
require("nvim-lsp-installer").setup {}
local lspconfig = require("lspconfig")

lspconfig.sumneko_lua.setup {}
lspconfig.tsserver.setup {}
-- ... and so on

查看 LSP 連結狀態

當你想寫一些配置的時候你可能會需要知道 client(一個 table)相關的資訊,這時候可以用 :lua print(vim.inspect(vim.lsp.buf_get_clients())) 來查看(這個很有用)。

我的 LSP config 快捷鍵配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
local function lsp_keymaps(bufnr)
local opts = { noremap = true, silent = true, buffer = bufnr }
-- popup diagnostic
vim.keymap.set('n', 'gl', vim.diagnostic.open_float, opts)
-- 跳到下一個 diagnostic
vim.keymap.set('n', '[d', vim.diagnostic.goto_prev, opts)
-- 跳到前一個 diagnostic
vim.keymap.set('n', ']d', vim.diagnostic.goto_next, opts)
-- 顯示 diagnostic 列表
vim.keymap.set('n', '<space>q', vim.diagnostic.setloclist, opts)
vim.keymap.set('n', 'gD', vim.lsp.buf.declaration, opts)
vim.keymap.set('n', 'gd', vim.lsp.buf.definition, opts)
vim.keymap.set('n', 'gr', vim.lsp.buf.references, opts)
vim.keymap.set('n', 'gi', vim.lsp.buf.implementation, opts)
-- 到那個 type 定義的地方
vim.keymap.set('n', 'gt', vim.lsp.buf.type_definition, opts)
vim.keymap.set('n', 'D', vim.lsp.buf.hover, opts)
vim.keymap.set('n', '<C-s>', vim.lsp.buf.signature_help, opts)
vim.keymap.set('n', '<F2>', vim.lsp.buf.rename, opts)
-- 對這個 diagnostic 做事情(例如:disable line)
vim.keymap.set('n', '<leader>ca', vim.lsp.buf.code_action, opts)
end
Neovim-配置筆記 Vim 筆記
Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×