共计 7550 个字符,预计需要花费 19 分钟才能阅读完成。
如何在 neovim 中设置 lsp
在本教程中,我们将学习如何设置 lsp 以进行自动完成并了解每个包的作用。
我们还将设置自动格式化。
Neovim 支持 lsp,这意味着它充当 lsp 的客户端。
Neovim 有内置的 lsp 支持。但 neovim 对于如何使用它没有任何意见。Neovim 把这个留给了用户。
了解这一切是什么
当您在 neovim 中打开文件时,lsp 客户端将附加到缓冲区。
附加的客户端依赖于 lsp 中的文件类型和配置。
然后客户端将开始与安装在您计算机上的语言服务器对话。
lsp 通过代码完成、错误诊断和更多功能进行响应。
让我们启动 neovim 并将 lsp 客户端附加到缓冲区
我们将尝试启动 lsp 客户端并将客户端附加到缓冲区。
初始化 lua
vim.lsp.start_client({
name = 'my-server-name',
cmd = {'lua-language-server'},
root_dir = vim.fs.dirname(vim.fs.find({'pyproject.toml', 'setup.py'}, {upward = true})[1]),
})
参数:
-
name 是用户指定的服务器名称,必须是唯一的
-
cmd 在您的计算机上启动语言服务器
-
root_dir 检查模式
-
upward = true 就是从上往下开始寻找
将 setup.py (或 root_dir 中提到的任何类型的文件)放在 init.lua 旁边,然后 lsp 客户端将识别该模式并附加到缓冲区(在本例中为 init.lua)。
运行 :lua =vim.lsp.get_active_clients() 会给你一个 lua 表。
如果表为空,则 lsp 不会附加并且运行 :lua =vim.lsp.get_active_clients() 将给出空表 {}。
如果一切顺利的话你可以看到这一点。
lsp 已连接并与语言服务器通信。
您可以看到警告弹出 init.lua。
或者您可以打开任何 lua 文件,只需放置 setup.py 或 pyproject.toml,lsp 将附加到缓冲区。
您还可以仅输入代码即可完成代码
键入 vim. 将光标放在 后面。并在插入模式下按
如果一切正常,您将看到一个弹出窗口打开。
像这样:
neovim/nvim-lspconfig
这是 neovim 的官方插件,其中包含服务器配置和更多功能,可帮助您设置 lsp 客户端并启动特定语言服务器。
删除所有以前的代码。
安装 lspconfig,我在这里使用 lazy.vim,你可以使用你最喜欢的包管理器
初始化 lua
local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim"
if not vim.loop.fs_stat(lazypath) then
vim.fn.system({
"git",
"clone",
"--filter=blob:none",
"https://github.com/folke/lazy.nvim.git",
"--branch=stable", -- latest stable release
lazypath,
})
end
vim.opt.rtp:prepend(lazypath)
require("lazy").setup({
-- All of the packages goes here
"neovim/nvim-lspconfig"
}
})
现在导入 lspconfig
初始化 lua
{...}
-- Setup language servers.
local lspconfig = require('lspconfig')
现在 lspconfig 直接给出所有可用 lsps 的默认设置的配置。查看适用于您的编程语言的配置 (https://github.com/neovim/nvim-lspconfig/blob/master/doc/server_configurations.md)。
初始化 lua
local lspconfig = require('lspconfig')
-- Python
lspconfig.pyright.setup {}
-- Typescript , Javascript
lspconfig.tsserver.setup {}
-- Lua
lspconfig.lua_ls.setup {}
现在您可以为每个 lsp 设置提供自定义选项。请参阅您的编程语言的配置 (https://github.com/neovim/nvim-lspconfig/blob/master/doc/server_configurations.md)。
初始化 lua
lspconfig.rust_analyzer.setup {
-- Server-specific settings. See `:help lspconfig-setup`
settings = {['rust-analyzer'] = {},},
}
现在我们想要在 lsp 客户端附加到缓冲区时设置一些键盘映射。
这里创建了一个 autocmd
-- Use LspAttach autocommand to only map the following keys
-- after the language server attaches to the current buffer
vim.api.nvim_create_autocmd('LspAttach', {group = vim.api.nvim_create_augroup('UserLspConfig', {}),
callback = function(ev)
-- Enable completion triggered by
vim.bo[ev.buf].omnifunc = 'v:lua.vim.lsp.omnifunc'
-- Buffer local mappings.
-- See `:help vim.lsp.*` for documentation on any of the below functions
local opts = {buffer = ev.buf}
vim.keymap.set('n', 'gD', vim.lsp.buf.declaration, opts)
vim.keymap.set('n', 'gd', vim.lsp.buf.definition, opts)
vim.keymap.set('n', 'K', vim.lsp.buf.hover, opts)
vim.keymap.set('n', 'gi', vim.lsp.buf.implementation, opts)
vim.keymap.set('n', '', vim.lsp.buf.signature_help, opts)
vim.keymap.set('n', 'wa', vim.lsp.buf.add_workspace_folder, opts)
vim.keymap.set('n', 'wr', vim.lsp.buf.remove_workspace_folder, opts)
vim.keymap.set('n', 'wl', function()
print(vim.inspect(vim.lsp.buf.list_workspace_folders()))
end, opts)
vim.keymap.set('n', 'D', vim.lsp.buf.type_definition, opts)
vim.keymap.set('n', 'rn', vim.lsp.buf.rename, opts)
vim.keymap.set({'n', 'v'}, 'ca', vim.lsp.buf.code_action, opts)
vim.keymap.set('n', 'gr', vim.lsp.buf.references, opts)
vim.keymap.set('n', 'f', function()
vim.lsp.buf.format {async = true}
end, opts)
end,
})
这里定义了一些有用的键盘映射,例如
这里定义了一些有用的键盘映射,例如 gdfor going to defination。
再次,如果我们按下,
我们希望自动触发完成弹出窗口,类似于 IDE。
所以我们必须使用另一个名为 nvim_cmp 的包 (https://github.com/hrsh7th/nvim-cmp)
删除自动命令
hrsh7th/nvim-cmp
安装 nvim_cmp 和一些源。
require("lazy").setup({
'hrsh7th/nvim-cmp', -- Autocompletion plugin,
'hrsh7th/cmp-nvim-lsp', -- LSP source for nvim-cmp,
'saadparwaiz1/cmp_luasnip', -- Snippets source for nvim-cmp
'L3MON4D3/LuaSnip', -- Snippets plugin
"neovim/nvim-lspconfig",
}
})
这里的
这里的来源是什么意思
-
Nvim_cmp 从许多来源获取完成信息,例如
-
cmp-nvim-lsp 从语言服务器获取数据
-
luasnip 从片段中获取数据并展开 nvim_cmp 的片段
-
buffersNeovim 中从缓冲区获取数据
在这里,我们使用 cmp 的功能扩展 lsp 的功能,以利用 cmp 的功能。
并创建了一个 lua 表,其中包含我想要设置的所有 lsp 服务器。
local capabilities = require("cmp_nvim_lsp").default_capabilities()
local luasnip = require 'luasnip'
local servers = {
"lua_ls"
"tsserver"
}
for _, lsp in ipairs(servers) do
lspconfig[lsp].setup {
-- on_attach = my_custom_on_attach,
capabilities = capabilities,
}
end
设置 Nvim-cmp
导入 Nvim-cmp
local cmp = require 'cmp'
cmp.setup {}
片段
Nvim-cmp 不“知道”如何扩展片段,这就是我们需要 luasnip 的原因。
这个回调函数从片段中获取数据,这里 cmp 需要扩展它。
所以我们使用 luasnip 来扩展代码片段。
cmp.setup {
snippet = {expand = function(args)
luasnip.lsp_expand(args.body)
end,
},}
来源
Nvim-cmp 需要来源向我们展示建议
来源包括来自语言服务器、缓冲区等的响应。
cmp.setup {
snippet = {expand = function(args)
luasnip.lsp_expand(args.body)
end,
},
sources = {{ name = 'nvim_lsp'},
{name = "buffer"},
},}
为 Nvim-cmp 定义键盘映射
cmp.setup {
snippet = {expand = function(args)
luasnip.lsp_expand(args.body)
end,
},
sources = {{ name = 'nvim_lsp'},
{name = "buffer"},
},
mapping = cmp.mapping.preset.insert({[''] = cmp.mapping.scroll_docs(-4), -- Up
[''] = cmp.mapping.scroll_docs(4), -- Down
[''] = cmp.mapping.select_next_item(),
[''] = cmp.mapping.select_prev_item(),
[''] = cmp.mapping.complete(),
[''] = cmp.mapping.confirm {
behavior = cmp.ConfirmBehavior.Replace,
select = true,
},
}),}
最后,我们在打字时得到了自动完成功能。
保存时格式化
现在我们有了自动完成功能。我们应该设置一种方法来格式化我们的代码。
使用 lsp 格式化缓冲区的一种方法是调用 vim.lsp.buf.format()
像这样调用 :lua vim.lsp.buf.format() 应该格式化缓冲区。
为此,我们必须定义一个自动命令,它将 vim.lsp.buf.format() 在保存缓冲区之前运行。
async 选项告诉如何格式化,如果 true 则格式是 非阻塞的 (当 vim 理想时,将会发生缓冲区的格式化)。
我这样做是 async = false 因为无论如何我想在保存缓冲区之前格式化缓冲区。
vim.api.nvim_create_autocmd('BufWritePre', {callback = function()
vim.lsp.buf.format {async = false,}
end,
})
这将在保存任何缓冲区时运行,这是我们不希望的,因为如果 lsp_client 未附加到缓冲区,那么它将抛出错误。
因此,只有当 lsp 附加到缓冲区时,我们才必须定义上述自动命令。
我们必须创建另一个自动命令,该命令仅在连接 lsp 时运行。
vim.api.nvim_create_autocmd('LspAttach', {group = vim.api.nvim_create_augroup('lsp-attach-format', { clear = true}),
-- This is where we attach the autoformatting for reasonable clients
callback = function(args)
local client_id = args.data.client_id
local client = vim.lsp.get_client_by_id(client_id)
local bufnr = args.buf
if not client.server_capabilities.documentFormattingProvider then
return
end
vim.api.nvim_create_autocmd('BufWritePre', {group = get_augroup(client),
buffer = bufnr,
callback = function()
if not format_is_enabled then
return
end
vim.lsp.buf.format {
async = false,
filter = function(c)
return c.id == client.id
end,
}
end,
})
end,})
lsp.buf.format 中的过滤器接收客户端并且必须返回布尔值。false 将停止请求格式化缓冲区。
例如:
这不会格式化附加了 tsserver 的缓冲区。
-- Never request typescript-language-server for formattingvim.lsp.buf.format {filter = function(client) return client.name ~= "tsserver" end}
就是这样。
详细配置示例:https://github.com/rishavmngo/dot-files
参考:
nvim-lua/kickstart.nvim(https://github.com/nvim-lua/kickstart.nvim)
lsp 的 Neovim 文档(https://neovim.io/doc/user/lsp.html)
文章来源地址 https://www.toymoban.com/diary/apps/342.html 文章来源:https://www.toymoban.com/diary/apps/342.html
到此这篇关于如何在 neovim 中设置 lsp 的文章就介绍到这了, 更多相关内容可以在右上角搜索或继续浏览下面的相关文章,希望大家以后多多支持 TOY 模板网!