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 注入格式化功能。
这里只讲解第二种
添加插件
-- 代码格式化
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++开发环境
熟悉上面的流程,这个就简单讲了
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,
}
代码运行器
添加插件:
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
快速注释插件
添加插件
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+适用
除了小册作者的配置仓库,这里再推荐一个优秀 Neovim 配置仓库: ayamir/nvimdots: A well configured and structured Neovim. (github.com)
至此 Neovim 配置学习就结束了:smile: