Neovim 配置全面解析(下)
原文:Neovim 配置全面解析(下) - 知乎 (zhihu.com)
环境:Ubuntu 20.04
宿主机:windows (windows terminal)WSL 2
NVIM:v 0.10.0-dev
配置 Neovim 需要保证流畅的 github 环境(以便于快速拉取插件),可以使用代理或是配置 Github SSH key
本篇博客是学习掘金小册的学习笔记,有兴趣的朋友可以直接点击下文链接了解详情
小册链接: https://s.juejin.cn/ds/iFGpuLW6/
因为文章字数超出平台限制,所以教程分上下两章节
Neovim 配置全面解析(上) - 知乎 (zhihu.com)
Neovim 配置全面解析(下) - 知乎 (zhihu.com)
基于 LSP 代码补全及自定义代码段
相关插件:hrsh7th/nvim-cmp: A completion plugin for neovim coded in Lua. (github.com)
相关概念:
- 补全引擎
补全引擎就是为 Neovim 提供代码补全核心功能的插件,比如 nvim-cmp
- 补全源
补全源就是补全引擎需要的数据来源,最常见的来源是来自 Language Server 提供的数据,它会知道某个类有哪些属性和方法等。
- snippet 引擎
snippet 引擎就是自定义代码段的引擎,常见的有vsnip
、luasnip
等
添加插件
-- 补全引擎
use ("hrsh 7 th/nvim-cmp")
-- snippet 引擎
use ("hrsh 7 th/vim-vsnip")
-- 补全源
use ("hrsh 7 th/cmp-vsnip")
use ("hrsh 7 th/cmp-nvim-lsp") -- { name = nvim_lsp }
use ("hrsh 7 th/cmp-buffer") -- { name = 'buffer' },
use ("hrsh 7 th/cmp-path") -- { name = 'path' }
use ("hrsh 7 th/cmp-cmdline") -- { name = 'cmdline' }
-- 常见编程语言代码段
use ("rafamadriz/friendly-snippets")
注意:只有hrsh 7 th/nvim-cmp
是补全引擎插件本身,其他cmp-xxx
基本都是插件补全来源,也就是说当你输入一个变量的时候,可以从多个来源显示补全的内容。
像 hrsh 7 th/cmp-nvim-lsp 就是 Neovim 内置 LSP 提供的补全内容,hrsh 7 th/cmp-buffer 补全当前 buffer 的内容, hrsh 7 th/cmp-cmdline 是命令行的补全,hrsh 7 th/cmp-path 则是用来补全路径,如果配置了这个,当输入一个路径的时候会补全路径
创建lua/lsp/cmp. lua
local cmp = require ("cmp")
cmp.setup ({
-- 指定 snippet 引擎
snippet = {
expand = function (args)
-- For `vsnip` users.
vim. fn ["vsnip#anonymous"](args.body)
-- For `luasnip` users.
-- require ('luasnip'). lsp_expand (args. body)
-- For `ultisnips` users.
-- vim. fn ["UltiSnips#Anon"](args.body)
-- For `snippy` users.
-- require'snippy'. expand_snippet (args. body)
end,
},
-- 补全源
sources = cmp.config.sources ({
{ name = "nvim_lsp" },
-- For vsnip users.
{ name = "vsnip" },
-- For luasnip users.
-- { name = 'luasnip' },
--For ultisnips users.
-- { name = 'ultisnips' },
-- -- For snippy users.
-- { name = 'snippy' },
}, { { name = "buffer" }, { name = "path" } }),
-- 快捷键设置
mapping = require ("keybindings"). cmp (cmp),
})
-- / 查找模式使用 buffer 源
cmp.setup.cmdline ("/", {
mapping = cmp.mapping.preset.cmdline (),
sources = {
{ name = "buffer" },
},
})
-- : 命令行模式中使用 path 和 cmdline 源.
cmp.setup.cmdline (": ", {
mapping = cmp.mapping.preset.cmdline (),
sources = cmp.config.sources ({
{ name = "path" },
}, {
{ name = "cmdline" },
}),
})
lua/keybindings. lua
添加
-- nvim-cmp 自动补全
pluginKeys. cmp = function (cmp)
return {
-- 出现补全
["<A-.>"] = cmp.mapping (cmp.mapping.complete (), {"i", "c"}),
-- 取消补全
["<A-,>"] = cmp.mapping ({
i = cmp.mapping.abort (),
c = cmp.mapping.close ()
}),
-- 上一个
["<C-k>"] = cmp. mapping. select_prev_item (),
-- 下一个
["<C-j>"] = cmp. mapping. select_next_item (),
-- 确认
["<CR>"] = cmp.mapping.confirm ({
select = true,
behavior = cmp. ConfirmBehavior. Replace
}),
-- 如果窗口内容太多,可以滚动
["<C-u>"] = cmp.mapping (cmp. mapping. scroll_docs (-4), {"i", "c"}),
["<C-d>"] = cmp.mapping (cmp. mapping. scroll_docs (4), {"i", "c"}),
}
end
init. lua
require ("lsp. cmp") -- (新增)
LSP 功能增强
UI 插件,同时 lspage 还可以自定义快捷键,对于我自己而言我认为有些地方文字更加直观,如果有些朋友需要美化可自行查找
弹窗显示错误
当一行代码很长的时候,右侧的提示文字就会显示不全
之前配置过 gp 快捷键使用弹窗显示错误,可以有效解决
功能增强
相关插件:kkharji/lspsaga.nvim: The neovim language-server-client UI (github.com)
添加插件
use ("tami 5/lspsaga. nvim" )
创建lua/lsp/ui. lua
local lspsaga = require 'lspsaga'
lspsaga. setup { -- defaults ...
debug = false,
use_saga_diagnostic_sign = true,
-- diagnostic sign
error_sign = "",
warn_sign = "",
hint_sign = "",
infor_sign = "",
diagnostic_header_icon = " ",
-- code action title icon
code_action_icon = " ",
code_action_prompt = {
enable = true,
sign = true,
sign_priority = 40,
virtual_text = true,
},
finder_definition_icon = " ",
finder_reference_icon = " ",
max_preview_lines = 10,
finder_action_keys = {
-- open = "o",
open = "<CR>",
vsplit = "s",
split = "i",
-- quit = "q",
quit = "<ESC>",
scroll_down = "<C-f>",
scroll_up = "<C-b>",
},
code_action_keys = {
-- quit = "q",
quit = "<ESC>",
exec = "<CR>",
},
rename_action_keys = {
-- quit = "<C-c>",
quit = "<ESC>",
exec = "<CR>",
},
definition_preview_icon = " ",
border_style = "single",
rename_prompt_prefix = "➤",
rename_output_qflist = {
enable = false,
auto_open_qflist = false,
},
server_filetype_map = {},
diagnostic_prefix_format = "%d. ",
diagnostic_message_format = "%m %c",
highlight_prefix = false,
}
lua/keybindings. lua
中的 mapLSP 函数替换为
-- lsp 回调函数快捷键设置
pluginKeys. mapLSP = function (mapbuf)
-- rename
--[[
Lspsaga 替换 rn
mapbuf ("n", "<leader>rn", "<cmd>lua vim.lsp.buf.rename ()<CR>", opt)
--]]
mapbuf ("n", "<leader>rn", "<cmd>Lspsaga rename<CR>", opt)
-- code action
--[[
Lspsaga 替换 ca
mapbuf ("n", "<leader>ca", "<cmd>lua vim. lsp. buf. code_action ()<CR>", opt)
--]]
mapbuf ("n", "<leader>ca", "<cmd>Lspsaga code_action<CR>", opt)
-- go xx
--[[
mapbuf ('n', 'gd', '<cmd>Lspsaga preview_definition<CR>', opt)
--]]
mapbuf ("n", "gd", "<cmd>lua vim.lsp.buf.definition ()<CR>", opt)
--[[
Lspsaga 替换 gh
mapbuf ("n", "gh", "<cmd>lua vim.lsp.buf.hover ()<CR>", opt)
--]]
mapbuf ("n", "gh", "<cmd>Lspsaga hover_doc<cr>", opt)
--[[
Lspsaga 替换 gr
mapbuf ("n", "gr", "<cmd>lua vim.lsp.buf.references ()<CR>", opt)
--]]
mapbuf ("n", "gr", "<cmd>Lspsaga lsp_finder<CR>", opt)
--[[
Lspsaga 替换 gp, gj, gk
mapbuf ("n", "gp", "<cmd>lua vim. diagnostic. open_float ()<CR>", opt)
mapbuf ("n", "gj", "<cmd>lua vim. diagnostic. goto_next ()<CR>", opt)
mapbuf ("n", "gk", "<cmd>lua vim. diagnostic. goto_prev ()<CR>", opt)
--]]
-- diagnostic
mapbuf ("n", "gp", "<cmd>Lspsaga show_line_diagnostics<CR>", opt)
mapbuf ("n", "gj", "<cmd>Lspsaga diagnostic_jump_next<cr>", opt)
mapbuf ("n", "gk", "<cmd>Lspsaga diagnostic_jump_prev<cr>", opt)
mapbuf ("n", "<leader>f", "<cmd>lua vim.lsp.buf.format ({ bufnr = bufnr })<CR>", opt)
-- 未用
-- mapbuf ("n", "gD", "<cmd>lua vim.lsp.buf.declaration ()<CR>", opt)
-- mapbuf ("n", "gi", "<cmd>lua vim.lsp.buf.implementation ()<CR>", opt)
-- mapbuf ('n', '<leader>q', '<cmd>lua vim.diagnostic.setloclist ()<CR>', opt)
-- mapbuf ("n", "<C-k>", "<cmd>lua vim. lsp. buf. signature_help ()<CR>", opt)
-- mapbuf ('n', '<space>wa', '<cmd>lua vim. lsp. buf. add_workspace_folder ()<CR>', opt)
-- mapbuf ('n', '<space>wr', '<cmd>lua vim. lsp. buf. remove_workspace_folder ()<CR>', opt)
-- mapbuf ('n', '<space>wl', '<cmd>lua print (vim.inspect (vim. lsp. buf. list_workspace_folders ()))<CR>', opt)
-- mapbuf ('n', '<space>D', '<cmd>lua vim. lsp. buf. type_definition ()<CR>', opt)
end
init. lua
require ("lsp. ui")
代码格式化
之前lua/keybindings. lua
定义过格式化快捷键
mapbuf ("n", "<leader>f", "<cmd>lua vim.lsp.buf.format ({ bufnr = bufnr })<CR>", opt)
但是你会发现格式化不起作用,这是因为使用的 Lua Language Server 并没有实现格式化功能。
格式化方案有如下两种:
- 第一种是使用专门的格式化插件;
- 第二种是给 Language Server 注入格式化功能。
这里只讲解第二种
相关插件:jose-elias-alvarez/null-ls.nvim: Use Neovim as a language server to inject LSP diagnostics, code actions, and more via Lua. (github.com)
添加插件
-- 代码格式化
use ({ "jose-elias-alvarez/null-ls. nvim", requires = "nvim-lua/plenary. nvim" })
添加配置文件 lua/lsp/null-ls. lua
local status, null_ls = pcall (require, "null-ls")
if not status then
vim.notify ("没有找到 null-ls")
return
end
local formatting = null_ls. builtins. formatting
null_ls.setup ({
debug = false,
sources = {
-- Formatting ---------------------
-- brew install shfmt
formatting. shfmt,
-- StyLua
formatting. stylua,
-- frontend
formatting.prettier.with ({ -- 只比默认配置少了 markdown
filetypes = {
"javascript",
"javascriptreact",
"typescript",
"typescriptreact",
"vue",
"css",
"scss",
"less",
"html",
"json",
"yaml",
"graphql",
},
prefer_local = "node_modules/. bin",
}),
-- formatting. fixjson,
-- formatting.black.with ({ extra_args = { "--fast" } }),
},
-- 保存自动格式化
on_attach = function (client, bufnr)
if client. supports_method ("textDocument/formatting") then
vim. api. nvim_clear_autocmds ({ group = augroup, buffer = bufnr })
vim. api. nvim_create_autocmd ("BufWritePre", {
group = augroup,
buffer = bufnr,
callback = function ()
-- on 0.8, you should use vim.lsp.buf.format ({ bufnr = bufnr }) instead
vim.lsp.buf.format ({ bufnr = bufnr })
-- vim. lsp. buf. formatting_sync ()
end,
})
end
end,
})
init. lua
require ("lsp. null-ls")
安装之后可以运行:LspInfo
查看绑定的 Language Server
然后我们可以看到有两个 LSP 了,null-ls 作为通用 LSP,可以在任何 filetypes 中运行。
然后执行:NullLsInfo
查看源的激活情况
之后的话即可使用: lua vim.lsp.buf.format ()
命令或是直接使用快捷键<leader>f
进行格式化
但是我们会发现包如下错误,这是因为相应语言应该配置相应的 Code Formatter,显示报错就是缺少 Lua 语言的 StyLua,其它语言可以自行配置相应的 Formatter
下面展示如何配置 stylua
配置环境
stylua 需要配置 rust 环境,rust 官网:安装 Rust - Rust 程序设计语言 (rust-lang.org)
因为我是使用 WSL,因此直接执行如下命令即可
curl --proto '=https' --tlsv 1.2 -sSf https://sh.rustup.rs | sh
执行source "$HOME/. cargo/env"
执行rustc --version
看是否成功,失败则看是否添加~/. cargo/bin
路径到环境变量中
安装步骤
执行
cargo install stylua
输出stylua -V
看是否成功
出现问题
格式化之后里面的空格就都变成了"^I", 原本应该是“·”的
直接将basic. lua
文件中设置vim. o. listchars = "space:·, tab:··"
或是设置vim. o. list = false
前端开发必要配置
配置语法高亮
执行: TSInstall css scss json html vue javascript typescript
执行:TSInstallInfo
查看安装情况
配置 LSP
lua/lsp/setup. lua
mason_config.setup ({
ensure_installed = {"lua_ls", "html", "cssls"}
})
...
local servers = {
lua_ls = require ("lsp. config. lua"),
-- 新增
html = require ("lsp. config. html"),
cssls = require ("lsp. config. css")
}
创建lsp/common-config. lua
local M = {}
M.keyAttach = function (bufnr)
local function buf_set_keymap (mode, lhs, rhs)
vim.keymap.set (mode, lhs, rhs, { noremap = true, silent = true, buffer = bufnr })
end
-- 绑定快捷键
require ("keybindings"). mapLSP (buf_set_keymap)
end
-- 禁用格式化功能,交给专门插件插件处理
M.disableFormat = function (client)
if vim.fn.has ("nvim-0.8") == 1 then
client. server_capabilities. documentFormattingProvider = false
client. server_capabilities. documentRangeFormattingProvider = false
else
client. resolved_capabilities. document_formatting = false
client. resolved_capabilities. document_range_formatting = false
end
end
-- M.capabilities = require ("cmp_nvim_lsp"). update_capabilities (vim. lsp. protocol. make_client_capabilities ())
M.capabilities = require ("cmp_nvim_lsp"). default_capabilities ()
M.flags = {
debounce_text_changes = 150,
}
return M
创建lsp/config/html. lua
local common = require ("lsp. common-config")
local opts = {
capabilities = common. capabilities,
flags = common. flags,
on_attach = function (client, bufnr)
-- 禁用本身语言格式化
common.disableFormat (client)
common.keyAttach (bufnr)
end,
}
return {
on_setup = function (server)
server.setup (opts)
end,
}
创建lsp/config/css. lua
local common = require ("lsp. common-config")
local opts = {
capabilities = common. capabilities,
flags = common. flags,
on_attach = function (client, bufnr)
common.disableFormat (client)
common.keyAttach (bufnr)
end,
settings = {
css = {
validate = true,
-- tailwindcss
lint = {
unknownAtRules = "ignore",
},
},
less = {
validate = true,
lint = {
unknownAtRules = "ignore",
},
},
scss = {
validate = true,
lint = {
unknownAtRules = "ignore",
},
},
},
}
return {
on_setup = function (server)
server.setup (opts)
end,
}
上面不禁用的话也是可以的,只不过会和默认的 null-ls 中的 prettier 格式化冲突,每次格式化都需要选择
注意 html、css 文件均是需要项目根目录有package. json
文件和 prettier 依赖
# 创建 package. json 并安装 prettier 依赖,顺便把 eslint 也配置上
npm init -y && npm i -D prettier eslint
Emmet LSP 配置
使用 emmet 可是使用简单的语法可以快速打出 HTML 结构标签
创建lua/lsp/config/emmet. lua
local opts = {
filetypes = { "html", "typescriptreact", "javascriptreact", "css", "sass", "scss", "less" },
}
return {
on_setup = function (server)
server.setup (opts)
end,
}
lua/lsp/setup. lua
修改
mason_config.setup ({
ensure_installed = {"lua_ls", "html", "cssls", "emmet_ls"}
})
...
local servers = {
lua_ls = require ("lsp. config. lua"),
html = require ("lsp. config. html"),
cssls = require ("lsp. config. css"),
-- 新增
emmet_ls = require ("lsp. config. emmet")
}
配置 jsonls
JSON Schema Store 插件,即 JSON 增强包
plugins. lua
添加插件
-- JSON 增强
use ("b 0 o/schemastore. nvim")
新建lua/lsp/config/json. lua
local common = require ("lsp. common-config")
local opts = {
capabilities = common. capabilities,
flags = common. flags,
on_attach = function (client, bufnr)
-- use fixjson to format
-- https://github.com/rhysd/fixjson
common.disableFormat (client)
common.keyAttach (bufnr)
end,
settings = {
json = {
schemas = require ("schemastore"). json.schemas (),
},
},
}
return {
on_setup = function (server)
server.setup (opts)
end,
}
lsp/config/setup. lua
修改
mason_config.setup ({
ensure_installed = {"lua_ls", "html", "cssls", "emmet_ls","jsonls"}
})
local servers = {
lua_ls = require ("lsp. config. lua"),
html = require ("lsp. config. html"),
cssls = require ("lsp. config. css"),
emmet_ls = require ("lsp. config. emmet"),
-- 新增
jsonls = require ("lsp. config. json")
}
配置 tssserver
添加 TS 增强包插件
use ({ "jose-elias-alvarez/nvim-lsp-ts-utils", requires = "nvim-lua/plenary. nvim" })
创建lsp/config/ts. lua
local common = require ("lsp. common-config")
local keybindings = require ("keybindings")
local ts_utils = require ("nvim-lsp-ts-utils")
local opts = {
flags = common. flags,
capabilities = common. capabilities,
-- https://github.com/jose-elias-alvarez/nvim-lsp-ts-utils/blob/main/lua/nvim-lsp-ts-utils/utils.lua
-- 传入 tsserver 初始化参数
-- make inlay hints work
init_options = {
hostInfo = "neovim",
preferences = {
includeInlayParameterNameHints = "all",
includeInlayParameterNameHintsWhenArgumentMatchesName = true,
includeInlayFunctionParameterTypeHints = true,
includeInlayVariableTypeHints = true,
includeInlayPropertyDeclarationTypeHints = true,
includeInlayFunctionLikeReturnTypeHints = true,
includeInlayEnumMemberValueHints = true,
},
},
on_attach = function (client, bufnr)
common.disableFormat (client)
common.keyAttach (bufnr)
-- defaults
ts_utils.setup ({
debug = false,
disable_commands = false,
enable_import_on_completion = false,
-- import all
import_all_timeout = 5000, -- ms
-- lower numbers = higher priority
import_all_priorities = {
same_file = 1, -- add to existing import statement
local_files = 2, -- git files or files with relative path markers
buffer_content = 3, -- loaded buffer content
buffers = 4, -- loaded buffer names
},
import_all_scan_buffers = 100,
import_all_select_source = false,
-- if false will avoid organizing imports
always_organize_imports = true,
-- filter diagnostics
filter_out_diagnostics_by_severity = {},
-- https://github.com/microsoft/TypeScript/blob/main/src/compiler/diagnosticMessages.json
filter_out_diagnostics_by_code = {
80001,
},
-- inlay hints
auto_inlay_hints = true,
inlay_hints_highlight = "Comment",
inlay_hints_priority = 200, -- priority of the hint extmarks
inlay_hints_throttle = 150, -- throttle the inlay hint request
inlay_hints_format = { -- format options for individual hint kind
Type = {},
Parameter = {},
Enum = {},
-- Example format customization for `Type` kind:
-- Type = {
-- highlight = "Comment",
-- text = function (text)
-- return "->" .. text: sub (2)
-- end,
-- },
},
-- update imports on file move
update_imports_on_move = false,
require_confirmation_on_move = false,
watch_dir = nil,
})
-- required to fix code action ranges and filter diagnostics
ts_utils. setup_client (client)
-- no default maps, so you may want to define some here
keybindings.mapTsLSP (bufnr)
end,
}
return {
on_setup = function (server)
server.setup (opts)
end,
}
同样setup. lua
修改
mason_config.setup ({
ensure_installed = {"lua_ls", "html", "cssls", "emmet_ls", "jsonls", "tsserver"}
})
-- 安装列表
-- { key: 服务器名, value: 配置文件 }
-- key 必须为下列网址列出的 server name,不可以随便写
-- https://github.com/williamboman/nvim-lsp-installer#available-lsps
local servers = {
lua_ls = require ("lsp. config. lua"),
html = require ("lsp. config. html"),
cssls = require ("lsp. config. css"),
emmet_ls = require ("lsp. config. emmet"),
jsonls = require ("lsp. config. json"),
-- 新增
tsserver = require ("lsp. config. ts")
}
添加快捷键lua/keybindings. lua
-- typescript 快捷键
pluginKeys. mapTsLSP = function (mapbuf)
mapbuf ("n", "gs", ":TSLspOrganize<CR>", opt)
mapbuf ("n", "gr", ":TSLspRenameFile<CR>", opt)
mapbuf ("n", "gi", ":TSLspImportAll<CR>", opt)
end
- gs 删除不用的 import 语句并重新排序。
- gr 用于改变文件名,同时其他文件中引用该文件的文件名也会被修改。
- gi 导入当前文件的所有依赖,并且会自动排序
ESLint 和 Prettier 配置
null-ls 中除了格式化 Formatting,还有 Diagnostics(红字错误提示) 和 Code Actions(代码触发的行为)
lsp/null-ls. lua
修改为
local status, null_ls = pcall (require, "null-ls")
if not status then
vim.notify ("没有找到 null-ls")
return
end
local formatting = null_ls. builtins. formatting
local diagnostics = null_ls. builtins. diagnostics
local code_actions = null_ls. builtins. code_actions
null_ls.setup ({
debug = false,
sources = { -- Formatting ---------------------
-- brew install shfmt
formatting. shfmt, -- StyLua
formatting. stylua, -- frontend
formatting.prettier.with ({ -- 只比默认配置少了 markdown
filetypes = {"javascript", "javascriptreact", "typescript", "typescriptreact", "vue", "css", "scss", "less",
"html", "json", "yaml", "graphql"},
prefer_local = "node_modules/. bin"
}), -- Diagnostics ---------------------
diagnostics.eslint.with ({
prefer_local = "node_modules/. bin"
}), -- code actions ---------------------
code_actions. gitsigns, code_actions.eslint.with ({
prefer_local = "node_modules/. bin"
})},
-- #{m}: message
-- #{s}: source name (defaults to null-ls if not specified)
-- #{c}: code (if available)
diagnostics_format = "[#{s}] #{m}",
-- 保存自动格式化
on_attach = function (client, bufnr)
if client. supports_method ("textDocument/formatting") then
vim. api. nvim_clear_autocmds ({
group = augroup,
buffer = bufnr
})
vim. api. nvim_create_autocmd ("BufWritePre", {
group = augroup,
buffer = bufnr,
callback = function ()
-- on 0.8, you should use vim.lsp.buf.format ({ bufnr = bufnr }) instead
vim.lsp.buf.format ({
bufnr = bufnr
})
-- vim. lsp. buf. formatting_sync ()
end
})
end
end
})
code_actions. gitsigns 没有安装可以注释掉
使用<leader>ca
调用 Code Action 自动修复快捷键
Rust 开发配置
前文已安装 rust 环境,此处不赘述
语法高亮
plugin-config/nvim-treesitter. lua
中的 ensure_installed 中添加"rust"
或是执行: TSInstall rust
代码提示
lsp/setup. lua
mason_config.setup ({
ensure_installed = {"lua_ls", "html", "cssls", "emmet_ls", "jsonls", "rust_analyzer"}
})
...
local servers = {
-- 新增
rust_analyzer = require ("lsp. config. rust"),
}
lsp/config/rust. lua
local common = require ("lsp. common-config")
local opts = {
capabilities = common. capabilities,
flags = common. flags,
on_attach = function (client, bufnr)
common.disableFormat (client)
common.keyAttach (bufnr)
end,
settings = {
-- to enable rust-analyzer settings visit:
-- https://github.com/rust-analyzer/rust-analyzer/blob/master/docs/user/generated_config.adoc
["rust-analyzer"] = {
-- enable clippy on save
checkOnSave = {
command = "clippy",
},
},
},
}
return {
on_setup = function (server)
local ok_rt, rust_tools = pcall (require, "rust-tools")
if not ok_rt then
print ("Failed to load rust tools, will set up `rust_analyzer` without `rust-tools`.")
server.setup (opts)
else
-- We don't want to call lspconfig. rust_analyzer.setup () when using rust-tools
rust_tools.setup ({
server = opts,
-- dap = require ("dap. nvim-dap. config. rust"),
})
end
end,
}
添加 Rust 增强包插件
-- Rust 增强
use ("simrat 39/rust-tools. nvim")
代码格式化
安装相应 Formtter
rustup component add rustfmt
null-ls. lua
source 中添加
-- rustfmt
formatting. rustfmt,
filetypes 中添加"rust"
配置 C/C++开发环境
熟悉上面的流程,这个就简单讲了
相关插件:p00f/clangd_extensions.nvim: Clangd's off-spec features for neovim's LSP client. Use https://sr.ht/~p00f/clangd_extensions.nvim instead (github.com)
setup. lua
servers 添加 “c”和“cpp”
安装格式化插件:apt-get install -y clang-format
plugin-config/nvim-treesitter. lua
ensure_installed 添加 “cpp” "c"
null-ls. lua
formatting.prettier.with ({
filetypes = {
"c",
"cpp"
}
}),
-- clang-format
formatting. clang_format,
lsp/config/clangd. lua
local common = require ("lsp. common-config")
local opts = {
capabilities = common. capabilities,
flags = common. flags,
on_attach = function (client, bufnr)
common.disableFormat (client)
common.keyAttach (bufnr)
end,
}
return {
on_setup = function (server)
local ok_rt, clangd_extensions = pcall (require, "clangd_extensions")
if not ok_rt then
server.setup (opts)
else
clangd_extensions.setup ({
server = opts,
extensions = {
-- defaults:
-- Automatically set inlay hints (type hints)
autoSetHints = true,
-- These apply to the default ClangdSetInlayHints command
inlay_hints = {
-- Only show inlay hints for the current line
only_current_line = false,
-- Event which triggers a refersh of the inlay hints.
-- You can make this "CursorMoved" or "CursorMoved, CursorMovedI" but
-- not that this may cause higher CPU usage.
-- This option is only respected when only_current_line and
-- autoSetHints both are true.
only_current_line_autocmd = "CursorHold",
-- whether to show parameter hints with the inlay hints or not
show_parameter_hints = true,
-- prefix for parameter hints
parameter_hints_prefix = "<- ",
-- prefix for all the other hints (type, chaining)
other_hints_prefix = "=> ",
-- whether to align to the length of the longest line in the file
max_len_align = false,
-- padding from the left if max_len_align is true
max_len_align_padding = 1,
-- whether to align to the extreme right or not
right_align = false,
-- padding from the right if right_align is true
right_align_padding = 7,
-- The color of the hints
highlight = "Comment",
-- The highlight group priority for extmark
priority = 100,
},
ast = {
-- These are unicode, should be available in any font
role_icons = {
type = " ",
declaration = " ",
expression = " ",
statement = ";",
specifier = " ",
["template argument"] = " ",
},
kind_icons = {
Compound = " ",
Recovery = " ",
TranslationUnit = " ",
PackExpansion = " ",
TemplateTypeParm = " ",
TemplateTemplateParm = " ",
TemplateParamObject = " ",
},
--[[ These require codicons ( https://github.com/microsoft/vscode-codicons )
role_icons = {
type = "",
declaration = "",
expression = "",
specifier = "",
statement = "",
["template argument"] = "",
},
kind_icons = {
Compound = "",
Recovery = "",
TranslationUnit = "",
PackExpansion = "",
TemplateTypeParm = "",
TemplateTemplateParm = "",
TemplateParamObject = "",
}, ]]
highlights = {
detail = "Comment",
},
},
memory_usage = {
border = "none",
},
symbol_info = {
border = "none",
},
},
})
end
end,
}
代码运行器
相关插件:CRAG666/code_runner.nvim: Neovim plugin.The best code runner you could have, it is like the one in vscode but with super powers, it manages projects like in intellij but without being slow (github.com)
添加插件:
use 'CRAG 666/code_runner. nvim'
配置插件plugin-config/code-runner. lua
local status, code_runner = pcall (require, "code_runner")
if not status then
vim.notify ("没有找到 code_runner")
return
end
code_runner.setup ({
-- choose default mode (valid term, tab, float, toggle)
mode = "term",
-- Focus on runner window (only works on toggle, term and tab mode)
focus = true,
-- startinsert (see ': h inserting-ex')
startinsert = false,
term = {
-- Position to open the terminal, this option is ignored if mode is tab
position = "bot",
-- window size, this option is ignored if tab is true
size = 8,
},
float = {
-- Key that close the code_runner floating window
close_key = "<ESC>",
-- Window border (see ': h nvim_open_win')
border = "none",
-- Num from `0 - 1` for measurements
height = 0.8,
width = 0.8,
x = 0.5,
y = 0.5,
-- Highlight group for floating window/border (see ': h winhl')
border_hl = "FloatBorder",
float_hl = "Normal",
-- Transparency (see ': h winblend')
blend = 0,
},
filetype_path = "", -- No default path defined
before_run_filetype = function ()
vim.cmd (": w")
end,
filetype = {
javascript = "node",
java = {
"cd $dir &&",
"javac $fileName &&",
"java $fileNameWithoutExt",
},
c = {
"cd $dir &&",
"gcc $fileName",
"-o $fileNameWithoutExt &&",
"$dir/$fileNameWithoutExt",
},
cpp = {
"cd $dir &&",
"g++ $fileName",
"-o $fileNameWithoutExt &&",
"$dir/$fileNameWithoutExt",
},
python = "python -u",
sh = "bash",
rust = {
"cd $dir &&",
"rustc $fileName &&",
"$dir/$fileNameWithoutExt",
},
},
project_path = "", -- No default path defined
project = {},
})
之后 init. lua 中添加插件,最后添加快捷键,使用空格加r
即可运行代码
-- 代码运行器
map ('n', '<leader>r', ':RunCode<CR>', { noremap = true, silent = false })
其他配置
自动补全括号
插件仓库:windwp/nvim-autopairs: autopairs for neovim written by lua (github.com)
引入插件
use ("windwp/nvim-autopairs")
创建lua/plugin-config/nvim-autopairs. lua
-- https://github.com/windwp/nvim-autopairs
local status, autopairs = pcall (require, "nvim-autopairs")
if not status then
vim.notify ("没有找到 nvim-autopairs")
return
end
autopairs.setup ({
check_ts = true,
ts_config = {
lua = { "string" }, -- it will not add a pair on that treesitter node
javascript = { "template_string" },
java = false, -- don't check treesitter on java
},
})
-- If you want insert `(` after select function or method item
local cmp_autopairs = require ("nvim-autopairs. completion. cmp")
local cmp = require ("cmp")
cmp.event: on ("confirm_done", cmp_autopairs. on_confirm_done ({ map_char = { tex = "" } }))
init. lua
快速注释插件
插件仓库:numToStr/Comment.nvim: // Smart and powerful comment plugin for neovim. Supports treesitter, dot repeat, left-right/up-down motions, hooks, and more (github.com)
添加插件
use ("numToStr/Comment. nvim")
创建lua/plugin-config/comment. lua
local status, comment = pcall (require, "Comment")
if not status then
vim.notify ("没有找到 Comment")
return
end
local default_opts = {
---Add a space b/w comment and the line
---@type boolean|fun ():boolean
padding = true,
---Whether the cursor should stay at its position
---NOTE: This only affects NORMAL mode mappings and doesn't work with dot-repeat
---@type boolean
sticky = true,
---Lines to be ignored while comment/uncomment.
---Could be a regex string or a function that returns a regex string.
---Example: Use '^$' to ignore empty lines
---@type string|fun ():string
ignore = nil,
---LHS of toggle mappings in NORMAL + VISUAL mode
---@type table
toggler = {
---Line-comment toggle keymap
line = "gcc",
---Block-comment toggle keymap
block = "gbc",
},
---LHS of operator-pending mappings in NORMAL + VISUAL mode
---@type table
opleader = {
---Line-comment keymap
line = "gc",
---Block-comment keymap
block = "gb",
},
---LHS of extra mappings
---@type table
extra = {
---Add comment on the line above
above = "gcO",
---Add comment on the line below
below = "gco",
---Add comment at the end of line
eol = "gcA",
},
---Create basic (operator-pending) and extended mappings for NORMAL + VISUAL mode
---NOTE: If `mappings = false` then the plugin won't create any mappings
---@type boolean|table
mappings = {
---Operator-pending mapping
---Includes `gcc`, `gbc`, `gc[count]{motion}` and `gb[count]{motion}`
---NOTE: These mappings can be changed individually by `opleader` and `toggler` config
basic = true,
---Extra mapping
---Includes `gco`, `gcO`, `gcA`
extra = false,
---Extended mapping
---Includes `g>`, `g<`, `g>[count]{motion}` and `g<[count]{motion}`
extended = false,
},
---Pre-hook, called before commenting the line
---@type fun (ctx: Ctx):string
pre_hook = nil,
---Post-hook, called after commenting is done
---@type fun (ctx: Ctx)
post_hook = nil,
}
-- 关闭了 extra 快捷键,只用 keybindings 里定义的基础快捷键
comment.setup (vim. tbl_deep_extend ("force", default_opts, require ("keybindings"). comment))
定义快捷键 keybindings. lua
gcc 快捷键作为行注释,gbc 快捷键作为块注释
-- 代码注释插件
-- see ./lua/plugin-config/comment. lua
pluginKeys. comment = {
-- Normal 模式快捷键
toggler = {
line = "gcc", -- 行注释
block = "gbc", -- 块注释
},
-- Visual 模式
opleader = {
line = "gc",
bock = "gb",
},
}
init. lua
中引入
require ("plugin-config. comment")
Surround 配置
引入插件
-- surround
use ("ur 4 ltz/surround. nvim")
lua/plugin-config/surround. lua
local status, surround = pcall (require, "surround")
if not status then
vim.notify ("没有找到 surround")
return
end
surround.setup ({
mappings_style = "surround",
})
init. lua
surround 官方快捷键如下
Normal Mode - Sandwich Mode
Provides key mapping to add surrounding characters. ( visually select then press s<char> or press sa{motion}{char})
Provides key mapping to replace surrounding characters. ( sr<from><to> )
Provides key mapping to delete surrounding characters. ( sd<char> )
ss repeats last surround command.
Normal Mode - Surround Mode
Provides key mapping to add surrounding characters. ( visually select then press s<char> or press ys{motion}{char})
Provides key mapping to replace surrounding characters. ( cs<from><to> )
Provides key mapping to delete surrounding characters. ( ds<char> )
Insert Mode
<c-s><char> will insert both pairs in insert mode.
<c-s><char><space> will insert both pairs in insert mode with surrounding whitespace.
<c-s><char><c-s> will insert both pairs on newlines insert mode.
常用快捷键
ds<char>
cs<from><to>
ys{motion}{char}
其他问题
我在推送仓库时频繁遇到GnuTLS recv error (-110)
解决链接:git - GnuTLS recv error (-110)
#!/bin/bash
set -e
sudo apt-get install build-essential fakeroot dpkg-dev -y
sudo apt-get build-dep git -y
sudo apt-get install libcurl 4-openssl-dev -y
cd ~
mkdir source-git
cd source-git/
apt-get source git
cd git-2.*.*/
sed -i -- 's/libcurl 4-gnutls-dev/libcurl 4-openssl-dev/' ./debian/control
sed -i -- '/TEST\s*=\s*test/d' ./debian/rules
dpkg-buildpackage -rfakeroot -b -uc -us
sudo dpkg -i ../git_*ubuntu*. deb
直接运行这个脚本即可
之后推送遇到remote: Support for password authentication was removed on August 13, 2021
问题,虽然我不太清楚我配了 SSH key,为什么还是走的密码验证,但是我还是按照他的提示来做获取token
,直接 github 首页中 Setting->Developer settings->Personal access tokens 生成 token
执行
git remote set-url origin https://<your_token>@github. com/<USERNAME>/<REPO>.git
最后即可免密推送
备忘记录
学习 vim 快捷键网站:Vim Cheat Sheet (rtorr.com)
使用: h clipboard
查看复制粘贴命令
文档推荐使用set clipboard=unnamedplus
,或是执行set clipboard^=unnamed, unnamedplus
就可以连通 vim 剪切板和系统剪切板,但是这个命令只是暂时性的,只能当前页面生效,为了永久生效,可以在basic. lua
中添加
-- 复制粘贴联通系统粘贴板
vim. o. clipboard = "unnamedplus"
全选复制文件:%y
或是ggyG
只是删除而不将删除的部分复制到剪切板中"_dd
(本质上是将剪切的内容放到_寄存器中,以便于和+寄存器区分)
结语
对我自己而言,配置的这些功能虽然少,但是暂时够用,如果追求更多的功能,可以直接用小册作者的仓库,或是其他优秀仓库
其实我觉得其实作为个人使用来说,没有特殊需求的情况下不是很推荐自己配置,只需要看懂本篇博客,然后可以做到更改别人写好的配置即可
还有就是切忌盲目复制粘贴,一定要看官方文档
本篇博客示例配置仓库:ReturnTmp/rettmp-nvim
掘金小册作者仓库: https://github.com/nshen/learn-neovim-lua
注意:v 2 分支是 neovim 8.0+适用
或是直接使用作者的新仓库:nshen/InsisVim: An out-of-the-box Neovim IDE solution that setup development environment in an incredibly simple way. (github.com)
除了小册作者的配置仓库,这里再推荐一个优秀 Neovim 配置仓库: ayamir/nvimdots: A well configured and structured Neovim. (github.com)
至此 Neovim 配置学习就结束了:smile: