Skip to content

neovim

6 posts with the tag “neovim”

Neovim拼写检查

这里记录如何在Neovim启用内置的拼写检查功能。

首先,添加拼写检查语言:

set spelllang=en,cjk

上面的配置,将拼写语言设置为encjkcjk选项用于防止将CJK字符被标记为拼写错误。

CJK: 中日韩统一表意文字(英语:CJK Unified Ideographs),也称统一汉字、统汉码(英语:Unihan),目的是要把分别来自中文、日文、韩文、越南文、壮文、琉球文中,起源相同、本义相同、形状一样或稍异的表意文字,在ISO 10646及Unicode标准赋予相同编码。 所谓“起源相同、本义相同”、主要是汉字,包括繁体字、简化字、日本汉字(漢字/かんじ)、韩国汉字(漢字/한자)、琉球汉字(漢字/ハンジ)、越南的喃字(𡨸喃/Chữ Nôm)与儒字(𡨸儒/Chữ Nho)、方块壮字(𭨡倱/sawgun)。

cjk配置项,也记录在 Nvim doc 文档中:

Chinese, Japanese and other East Asian characters are normally marked as errors, because spell checking of these characters is not supported. If ‘spelllang’ includes “cjk”, these characters are not marked as errors. This is useful when editing text with spell checking while some Asian words are present.

使Nvim启用拼写检查功能,需要运行命令:set spell。下面可以添加一个映射来切换拼写检查:

nnoremap <silent> <F11> :set spell!<cr>

或者

vim.api.nvim_set_keymap('n', '<F11>', [[<Cmd>set spell!<CR>]], { noremap = true, silent = true })

此时,可以按来切换拼写检查。

此外,也可以在init.lua中通过创建autocmd,根据文件类型(filetype),来自动切换拼写检查功能,如:

local spell_group = vim.api.nvim_create_augroup("spell_group", { clear = true })
vim.api.nvim_create_autocmd("FileType", {
pattern = { "lua", "python", "go" },
command = "setlocal spell spelllang=en_us,cjk",
group = spell_group,
})
vim.api.nvim_create_autocmd("FileType", {
pattern = { "markdown" },
command = "setlocal nospell",
group = spell_group,
})
vim.api.nvim_create_autocmd("TermOpen", {
pattern = "*", -- disable spellchecking in the embeded terminal
command = "setlocal nospell",
group = spell_group,
})

上面的配置,在luaptyhongo文件中启用拼写检查,并将拼写语言设置为en_us,cjk,在Markdown文件禁用拼写检查, 同时在内嵌终端(embeded terminal)中禁用拼写检查。

在插入模式时,当输入了NeoVim认为是拼写错误的单词时,会在其下方显示下划线。要更正错误,可以依次按下<C-x>s键,此时 会显示一个建议正确单词的菜单列表,可以选择其中一项来更正拼写。

normal模式,可以使用下面的快捷键来快速处理拼写错误问题:

  • [s: 跳转到上一处拼写错误
  • ]s: 跳转到下一处拼写错误
  • z=: 对光标下或之后的单词,显示建议正确的拼写单词
  • zg: 将光标下的单词作为正确拼写单词加入到’spellfile’
  • zw: 和zg类似,只是zw是将这个单词标记为拼写错误的单词

spelloptions配置选项默认值是"",此时,注释中的驼峰拼写的单词,会被判定为拼写错误,如: camel case

可以通过配spelloptions启动驼峰单词拼写:

vim.opt.spelloptions = "camel"

判断规则:

When a word is CamelCased, assume “Cased” is a

separate word: every upper-case character in a word
that comes after a lower case character indicates the
start of a new word.

Neovim调试Lua

使用 nvim-lsp-installer, 安装插件。

Plug 'neovim/nvim-lspconfig'
Plug 'williamboman/nvim-lsp-installer'

首先安装 Lua language server:

Terminal window
brew install lua-language-server

其次在 Neovim 中安装 sumneko_lua 配置:

: LspInstall sumneko_lua

查看 Lsp 详情:

: LspInstallInfo

image-20220217164510148

安装成功后,开始进行Lsp配置:

local runtime_path = vim.split(package.path, ';')
table.insert(runtime_path, "lua/?.lua")
table.insert(runtime_path, "lua/?/init.lua")
require'lspconfig'.sumneko_lua.setup {
settings = {
Lua = {
runtime = {
-- Tell the language server which version of Lua you're using (most likely LuaJIT in the case of Neovim)
version = 'LuaJIT',
-- Setup your lua path
path = runtime_path,
},
diagnostics = {
-- Get the language server to recognize the `vim` global
globals = {'vim'},
},
workspace = {
-- Make the server aware of Neovim runtime files
library = vim.api.nvim_get_runtime_file("", true),
},
-- Do not send telemetry data containing a randomized but unique identifier
telemetry = {
enable = false,
},
},
},
}
:VimspectorInstall local-lua-debugger-vscode

添加配置.vimspector.json:

{
"configurations": {
"luajit": {
"adapter": "lua-local",
"filetypes": ["lua"],
"configuration": {
"request": "launch",
"type": "lua-local",
"cwd": "${workspaceFolder}",
"program": {
"lua": "luajit",
"file": "${file}"
}
}
}
}
}
call vimspector#Launch()

image-20220217170431671

Neovim小结

对目前配置使用的Neovim做一个小结回顾梳理。

使用的是v0.9版本。

Terminal window
NVIM v0.10.0-dev-340+g33687f5e8
Build type: RelWithDebInfo
LuaJIT 2.1.0-beta3

插件管理器多种选择,如:packer.nvimwbthomason/packer.nvimsavq/paq-nvimNTBBloodbath/cheovim,我选用的是vim-plug(原因是他很常见,刚接触插件安装时遇到的就是它,后面也没有再做调整)。

后续进行启动时间优化时,将插件管理改为了 packer.nvim,并改用纯 lua 进行配置 neovim。 使用纯lua进行一些优化后,成功将启动时间从214.900ms 降低到了121.062ms。 优化方向:

  1. 使用效率更好的插件进行替代;
  2. 延迟加载插件;
  3. 使用基于Lua编写的插件;
  4. 使用纯lua替代VimScript进行配置NeoVim;
  5. 缓存lua模块编译 lewis6991/impatient
  6. 设置Lazyredraw;
  7. 删除或者禁用不用的插件;
  8. 禁用一些内置插件

最后,我将iterm2 更换成alacritty + tmux + Hammerspoon , Neovim 平均启动时间进一步降低到了98ms。 在使用 Packer 延迟加载功能,对相关插件进行延迟加载;使用filetype.nvim 优化filetype.vim在启动过程中的行为,将平均启时间降低到42ms

使用的是Nerd Fonts中的Blex*(详见:https://github.com/ryanoasis/nerd-fonts#option-4-homebrew-fonts) 。macOS平台上 Nerd Fonts所有字体在Homebrew Cask Fonts 都是可用的:

Terminal window
brew tap homebrew/cask-fonts
brew install --cask font-blex-mono-nerd-font
  • Awesome Neovim - Collections of awesome Neovim plugins. Mostly targeting Neovim specific features.
  • Vimawesome - Showcases various plugins for vim and has a neovim tag for other plugins targeting Neovim.
  • awesome-vim - Short list of vim plugins and helpful guides.

img

  • :e- 重新加载当前文档
  • :w- 保存修改
  • :wq- 保存并退出
  • ZZ- 保存并退出
  • :x- 保存并退出
  • :q[uit]- 退出当前窗口(CTRL-W q或CTRL-W CTRL-Q)
  • :gf- 跳转到当前光标下文字对应的文件
  • vim -o file1.txt file2.txt- 同时打开文件,水平分割窗口
  • vim -O file1.txt file2.txt- 同时打开文件,垂直分割窗口
  • <CTRL+w>+s- 水平切分当前窗口,新窗口仍显示当前缓冲区
  • <CTRL+w>+v- 垂直切分当前窗口,新窗口仍显示当前缓冲区
  • :sp[lit] {file}- 水平切分当前窗口, 并在新窗口中载入{file}
  • :vsp[lit] {file}- 垂直切分当前窗口, 并在新窗口中载入{file}
  • <CTRL-w>-- 将分割窗口高度减少一行
  • <CTRL-w>+- 高度增加一行
  • <CTRL-w>>- 将分割窗口宽度增加一行
  • <CTRL-w><- 宽度减少一行
Ex 命令普通模式命令用途
:clo[se]<CTRL+w>+c关闭活动窗口
:on[ly]<CTRL+w>+o只保留活动窗口,关闭其他所有窗口
  • <CTRL+w>w- 在窗口见循环切换
  • <CTRL+w>h- 切换到左边窗口
  • <CTRL+w>l- 切换到右边窗口
  • <CTRL+w>k- 切换到上边窗口
  • <CTRL+w>j- 切换到下边窗口
  • :buffers:files:ls- 列出当前缓冲区,默认情况下列出可以显示的缓存区
  • :ls!- 列出所有缓存区,包括不显示的
  • :bNext- 切换到下一个缓冲区
  • :bprevious- 切换到上一个缓冲区
  • :blast- 切换到最后一个缓冲区
  • :bfirst- 切换到第一个缓冲区
  • :bdelete- 删除缓冲区
  • :bunload- 卸载缓冲区,为缓冲区打开的窗口也会关闭,但文件名仍保留在缓冲区列表中
  • :badd- 添加缓冲区
  • H- 把光标移到屏幕最顶端一行
  • M- 把光标移到屏幕中间一行
  • L- 把光标移到屏幕最底端一行
  • gg- 到文件头部
  • G- 到文件尾部
  • i- 在光标前插入;一个小技巧:按8,再按i,进入插入模式,输入=, 按esc进入命令模式,就会出现8个=。 这在插入分割线时非常有用,如30i+就插入了36个+组成的分割线
  • I- 在当前行第一个非空字符前插入
  • I- 在当前行第一列插入
  • a- 在光标后插入
  • A- 在当前行最后插入
  • o- 在下面新建一行插入
  • O- 在上面新建一行插入
  • :r filename- 在当前位置插入另一个文件的内容
  • :[n]r filename- 在第n行插入另一个文件的内容
  • :r !date- 在光标处插入当前日期与时间。同理,:r !command可以将其它shell命令的输出插入当前文档
  • *- 向下搜索光标所在词
  • g*- 同上,但部分符合即可
  • #- 向上搜索光标所在词
  • g#- 同上,但部分符合即可
  • g CTRL-g- 统计全文或统计部分的字数
  • c[n]w- 改写光标后1(n)个词
  • c[n]l- 改写光标后n个字母
  • c[n]h- 改写光标前n个字母
  • [n]cc- 修改当前[n]行
  • C- C可更改光标所在位置到此行结尾间的文本。它的功用和c加上特殊行末指示符$的效果―样(c$)
  • [n]s- 以输入的文本替代光标之后1(n)个字符,相当于c[n]l
  • [n]S- 删除指定数目的行,并以所输入文本代替之
  • r- 把一个字符替换成宁外一个,结束后不需要按 ESC 回到命令模式
  • s/old/new- 将当前行第一个出现的模式 old 改为 new
  • s/old/new/g- 将当前行每一个 old 改为 new
  • 50,100s/old/new/g- 将第50行到第100行之间每一个 old 修改为 new
  • %s/old/new/g- 全局替换每一个出现的 old 为 new
  • %s/bacsdfws/&,HELLO/- 将每一行的第一个 bacsdfws 替换为 bacsdfws,HELLO 。& 在模式匹配替换字符串时,会被替换成搜索模式匹配出的完整文本,这可以避免重复输入要被替换的文本
  • %s/\(foo\)hello\(world\)/\1 \2/g 将每一行的foohelloworld 替换为fooworld.
    • \(foo\)foo反向引用
    • \& 插入搜索模式匹配的文本
    • \0 插入与整个模式匹配的文本
    • \1 插入第一个反向引用的文本
    • \2 插入第二个反向引用, \3,\4 依次类推
  • s#/usr/local/bin#/usr/sbin#g - 将行中所有的usr/local/bin 替换成/usr/sbin,vim/neovim 允许在在模式替换中使用任何正则表达式 分隔符,根本不需要使用 /,使用#进行替代,这样就可以避免转义斜线
  • dw- dw会删除光标所在位置的单词,请注意单词后的空白也会被删除
  • ddD- 删除当前光标所在行
  • d0- 从光标位置删除当前光标所在行的开头
  • d$- 从光标位置删除当前光标所在行的结尾
  • x- 它只会删除光标所在位置的字符
  • :g/re/d- 删除所有的匹配行,global 命令允许在某个指定模式的所有匹配行上运行Ex命令: :[range] global[!] /{pattern}/ [cmd]
  • :v/re/d- 只保留匹配行
  • :g/^$/d - 删除掉所有的空白行
  • :g/^#/d - 删除所有#开头的行
  • .- “想要重复相同的编辑命令时,可以使用重复命令——句号(.),以节省时间”
  • u- “以撤销上一个命令只要按下u即可,光标不需要在原来下命令时所在的位置”
  • >>- 向右缩进
  • <<- 向左缩进
  • ctrl+f- 下翻一屏
  • ctrl+b- 上翻一屏
  • ctrl+d- 下翻半屏
  • ctrl+u- 上翻半屏
  • ctrl+e- 向下滚动一行
  • ctrl+y- 向上滚动一行
  • n%- 到文件n%的位置
  • zz- 将当前行移动到屏幕中央
  • zt- 将当前行移动到屏幕顶端
  • zb- 将当前行移动到屏幕底端
  • [[- 跳转到上一个函数块开始,需要有单独一行的{
  • ]]- 跳转到下一个函数块开始,需要有单独一行的{
  • []- 跳转到上一个函数块结束,需要有单独一行的}
  • ][- 跳转到下一个函数块结束,需要有单独一行的}
  • ci’, di’, yi’- 修改、剪切或复制’之间的内容
  • ca’, da’, ya’- 修改、剪切或复制’之间的内容,包含’
  • ci”, di”, yi”- 修改、剪切或复制”之间的内容
  • ca”, da”, ya”- 修改、剪切或复制”之间的内容,包含”
  • ci(, di(, yi(- 修改、剪切或复制()之间的内容
  • ca(, da(, ya(- 修改、剪切或复制()之间的内容,包含()
  • ci[, di[, yi[- 修改、剪切或复制[]之间的内容
  • ca[, da[, ya[- 修改、剪切或复制[]之间的内容,包含[]
  • ci{, di{, yi{- 修改、剪切或复制{}之间的内容
  • ca{, da{, ya{- 修改、剪切或复制{}之间的内容,包含{}
  • ci<, di<, yi<- 修改、剪切或复制<>之间的内容
  • ca<, da<, ya<- 修改、剪切或复制<>之间的内容,包含<>
  • va'- 选中’之间的内容,包括`
  • vi'- 选中’之间的内容
  • xp- 交换两个字母位置
  • :23t.- 复制第23行且将其粘贴到当前行的下一行
  • :t23- 复制当前行到第23行的下一行
  • Vu- 整行小写
  • guu- 整行小写
  • VU- 整行大写
  • gUU- 整行大写
  • ~- 反转光标所在字符的大小写

If the ignorecase option is on, the case of normal letters is ignored. smartcase can be set to ignore case when the pattern contains lowercase letters only. When \c appears anywhere in the pattern, the whole pattern is handled like ignorecase is on. The actual value of ignorecase and smartcase is ignored. \C does the opposite: Force matching case for the whole pattern. {only Vim supports \c and \C} Note that ignorecase, \c and \C are not used for the character classes.

Examples:
pattern 'ignorecase' 'smartcase' matches
foo off - foo
foo on - foo Foo FOO
Foo on off foo Foo FOO
Foo on on Foo
\cfoo - - foo Foo FOO
foo\C - - foo
  • [s: 跳转到上一处拼写错误
  • ]s: 跳转到下一处拼写错误
  • z=: 对光标下或之后的单词,显示建议正确的拼写单词
  • zg: 将光标下的单词作为正确拼写单词加入到‘spellfile’
  • zw: 和zg类似,只是zw是将这个单词标记为拼写错误的单词
  • :!- cmd 执行外部命令
  • :!!- 执行上一次的外部命令
  • :sh- 调用shell,用exit返回vim
  • :r !cmd- 将命令的返回结果插入文件当前位置
  • :m,nw !cmd- 将文件的m行到n行之间的内容做为命令输入执行命令
  • qa- 开始录制宏a(键盘操作记录)
  • q- 停止录制
  • @a- 播放宏a
  • :6t.- 把第六行复制到当前行下方,:t是命令:copy简写形式 [range]copy {address}
  • :6m.- 把第六行移动到当前行下方,:move是命令:move简写形式,格式:[range] {address}
  • :'<,'>m$- 把选中的文本移动到文件结尾,其中:'<,'>代表高亮选区,‘<是代表高亮选区行首的位置标记,‘>是代表高亮选区的最后一行
  • :'<,>'p- 回显上一次高亮选区选中的内容
  • :sort- 升序重排所有行
  • :sort!- 降序重排所有行
  • :sort u- 升序号所有行,并去除重复行
  • :sort n- 按数值升序重拍所有行(此时100排在20后面)
  • 1,100sort- 第1行到第100行,进行升序重排
  • :g/start/.,/end/-1 sort n- 使用正则表达式进行匹配开始和结束行,对从start开始到end结束的所有文本行,进行数值升序重排
  • 1,$!sort -t',' -k2 -r- 使用外部命令sort,将第一行到最后一行,-t参数指定以,为分隔,-k参数指定按第二个字段进行降序排列
  • v- 进入可视化模式, 移动光标高亮选择, 然后可以对选择的文本执行命令(比如y-复制)
  • V- 进入可视化模式(行粒度选择)
  • o- 切换光标到选择区开头/结尾
  • Ctrl + v- 进入可视化模式(矩阵选择)
  • O- 切换光标到选择区的角
  • aw- 选择当前单词
  • ab- 选择被 () 包裹的区域(含括号)
  • aB- 选择被 {} 包裹的区域(含花括号)
  • at- 选择被 <> 标签包裹的区域(含<>标签)
  • ib- 选择被 () 包裹的区域(不含括号)
  • iB- 选择被 {} 包裹的区域(不含花括号)
  • it- 选择被 <> 标签包裹的区域(不含<>标签)
  • Esc- 退出可视化模式
  • 使用可视模式选择和normal 命令来注释和取消注释代码:
    • 可视模式下选择目标
    • normal i#norm i#: 添加 #
    • normal xnorm x: 取消每行开头的第一个字符,这里也就是开头的#
  • >- 向右缩进
  • <- 向左缩进
  • y- 复制
  • d- 剪切
  • ~- 大小写切换
  • u- 将选中文本转换为小写
  • U- 将选中文本转换为大写
  • zo- 在光标下打开折叠
  • zc- 在光标下关闭折叠
  • za- 切换光标下打开、关闭状态
  • zr- 将所有折叠打开一层
  • zm- 将所有折叠关闭一层
  • zR- 打开全部折叠
  • zM- 关闭全部折叠

检查Neovim启动耗时情况,可以使用参数--startuptime <file>,将启动时间消耗信息写入的文件<file>中。

可以通过执行外部命令:

:%!python -m json.tool

也可以通过NeoVim支持的LSP功能进行格式化,先通过安装JSON LSP server:

npm i -g vscode-langservers-extracted

再在配置文件中激活LSP server:

local on_attach = function(client, bufnr)
buf_set_keymap('n', '<space>f', '<cmd>lua vim.lsp.buf.formatting()<CR>', opts)
end
local servers = { 'jsonls' }
for _, lsp in ipairs(servers) do
nvim_lsp[lsp].setup {
on_attach = on_attach,
flags = {
debounce_text_changes = 150,
}
}
end

配置成功后,在使用<sapce>f快捷键就可以完成格式化JSON文件

如有下面的一段文本,要计算第一列表数字的平均值:

106.826 000.003- --- NVIM STARTED ---
107.274 000.003- --- NVIM STARTED ---
107.374 000.003- --- NVIM STARTED ---
107.436 000.003- --- NVIM STARTED ---
108.689 000.004- --- NVIM STARTED ---
108.824 000.004- --- NVIM STARTED ---
109.007 000.003- --- NVIM STARTED ---
109.509 000.003- --- NVIM STARTED ---
109.715 000.003- --- NVIM STARTED ---
110.581 000.003- --- NVIM STARTED ---
111.096 000.004- --- NVIM STARTED ---

可以使用Ex命令 :r!awk '{total+=$1} END {print "Average- " total/NR}' %, 文件末尾添加:

Average- 111.244

命令详解:

  • :r- 读取文件内容插入到光标所在位置的下一行
  • !- 执行外部命令
  • awk- 外部命令awk
  • {total+=$1}- 累加第一列数值求和赋值给total
  • {print "Average- " total/NR}:计算并输出平均值(NR:已读取的记录数)
  • %- 当前文件

4、给文件的每一行开头添加序号

Section titled “4、给文件的每一行开头添加序号”
:%!nl -ba
:%!cat -n
:%!awk '{print NR $0}'

5、tabstop, softtabstop, expandtab, shiftwidth 和 空格

Section titled “5、tabstop, softtabstop, expandtab, shiftwidth 和 空格”
  • tabstop: tabstop选项设置tab字符显示宽度为多少个空格
  • expandtab: set expandtab后,在插入模式,按TAB键所插入的tab字符会被替换成合适数目的空格
  • softtabstop: softtabstop 选项影响Vim在插入模式下按TAB键所得到的实际字符,可能是特定数目的空格,也可能是一个tab字符。具体受到 tabstopexpandtab 配置项影响
  • shiftwidth: 配置进行缩进时插列数

使用下面的配置:

: set tabstop=2
: set shiftwidth=2
: set softtabstop=2
: set expandtab

或者

: set tabstop=2 shiftwidth=2 softtabstop=2 expandtab

将tab字符显示为2个空格,缩进时使用2个空格,插入模式下键入TA替换成两个空格 在上述配置下,如果文件中已经有tab字符,此时要将替换成2个空格,可以使用命令:

: retab
  • auto[cmd] [group]: 显示所有autocommands,如果提供[group]参数,Vim 仅会列出[group]相关的autocommands
  • verbose autocmd BufEnter: 显示最后定义的BufEnter autocommands
  • auto[cmd] [group] {event}: 显示{event}事件相关的所有 autocommands
  • verbose highlight: 显示所有 hightlight 组样式定义
  • verbose highlight GroupName: 显示指定的 highlight 组的样式定义

系统环境:

❯ kitty --version
kitty 0.31.0 created by Kovid Goyal
❯ nvim --version
NVIM v0.10.0-dev-1873+g8f08b1efb
Build type: RelWithDebInfo
LuaJIT 2.1.1702233742
Run "nvim -V1 -v" for more info
  1. 修改 kitty 背景透明度为0.9, macos_traditional_fullscreen 从 no 设置为 yes
  2. 修改 neovim 配置,设置:
vim.cmd [[highlight Normal guibg=none]]
vim.cmd [[highlight NonText guibg=none]]
vim.cmd [[highlight Normal ctermbg=none]]
vim.cmd [[highlight NonText ctermbg=none]]

ed 是最初的 UNIX 文本编辑器,它编写于图形显示器很稀有的年代,那时源代码通常是打印在纸带上,并在电传终端机 上编辑。 在终端上输入的命令被送到大型机上进行处理,每条命令的输出会被打印出来。在那个年代,从终端到大型机之间的连接很慢,以至于一个快速打字员比网络还快,他们输入命令的速度要比命令被发出去处理更快。 在这种情况下,ed 能够提供一个简洁的语法变得异常重要。p 被用来打印当前行,而 %p 被用来打印整个文件,皆缘于此。

ed 历经了几代的改进,包括em (意为“editor for mortals”,即“人类的编辑器”)、en ,最终到ex。此时图形显示器已经比较普及了,ex 增加了一个把终端屏幕设置成交互窗口的功能,并在窗口内显示文件的内容。这样,在做修改时实时看到变化成为了可能。此屏幕编辑模式由 :visual 命令激活,其简写为 :vi,这即是 vi 这个名字的由来。

Vim 代表改进版的 vi (vi improved),更多信息通过查阅 :h vi-differences,我们可以看到Vim支持而 vi 不支持的功能列表。 Vim 对功能的增强是必要的,但另一方面它却仍继承了大量的遗产。这些指导 Vim 先祖们设计的约束,提供了一个非常高效的命令集,这在今天依然很有价值。

  1. Neovim
  2. Awesome Neovim
  3. VIM 命令操作教程
  4. 简明 VIM 练级攻略
  5. 130+vim基本命令
  6. vi / vim 初学者入门(系列文章)
  7. nanotee/nvim-lua-guide
  8. getting-started-with-vim
  9. 《学习vi和vim编辑器》
  10. 《Vim实用技巧》
  11. nvim lua guide
  12. The 300 line init.lua challenge
  13. configuring neovim using lua
  14. Speedup neovim
  15. reduce startup and improve lua config
  16. turning neovim into a full fledged code editor with lua
  17. Vim Tips Wiki
  18. Neovim Tips
  19. Vim Cheat Sheet
  20. Easier buffer switching
  21. Variables Reference in Debugging configuration files
  22. Motion
  23. Using marks

NeoVim调试Python、Golang

在上两篇中NeoVim开发环境配置NeoVim配置Go开发环境(进阶), 完成了将NeoVim作为IDE最基本常用功能的,这里将进一步完成对Python、Golang调试环境的配置。

在NeoVim上进行调试(Python、Golang)有nvim-dapvimspector可做选择,这里 将使用vimspector进行调试工作。

在plug.vim中添加:

Plug 'puremourning/vimspector'

:PlugInstall安装插件。 在init.vim中,添加:

let g:vimspector_enable_mappings='HUMAN'

将vimspector 快捷键映射配置为HUMAN模式:

KeyMappingFunction
F5<Plug>VimspectorContinueWhen debugging, continue. Otherwise start debugging.
F3<Plug>VimspectorStopStop debugging.
F4<Plug>VimspectorRestartRestart debugging with the same configuration.
F6<Plug>VimspectorPausePause debuggee.
F9<Plug>VimspectorToggleBreakpointToggle line breakpoint on the current line.
<leader>F9<Plug>VimspectorToggleConditionalBreakpointToggle conditional line breakpoint or logpoint on the current line.
F8<Plug>VimspectorAddFunctionBreakpointAdd a function breakpoint for the expression under cursor
<leader>F8<Plug>VimspectorRunToCursorRun to Cursor
F10<Plug>VimspectorStepOverStep Over
F11<Plug>VimspectorStepIntoStep Into
F12<Plug>VimspectorStepOutStep out of current function scope

下面是各个语言调试使用的Adapter:

通过:VimspectorInstall debugpy:VimspectorInstall delve 完成对python、go 调试adapter的安装。

由于NeoVim的LSP指定当前根目录是各LSP Server提供的功能,在调试Ptyon时,在目录中添加.pyrightconfig.json文件:

{
"executionEnvironments": [
{"root": "."}
]
}

如上配置,将.pyrightconfig.json文件所在目录,作为Root目录。

配置调试器,添加配置文件 .vimspector.json:

{
"configurations": {
"run": {
"adapter": "debugpy",
"default": true,
"configuration": {
"request": "launch",
"type": "python",
"cwd": "${workspaceRoot}",
"stopOnEntry": true,
"program": "${file}"
},
"breakpoints": {
"exception": {
"raised": "N",
"uncaught": "",
"userUnhandled": ""
}
}
}
}
}

configuration.program指定要调试的程序,可以通过configuration.env配置调试时程序的环境变量,configuration.args配置参数。 如在调试一个scrapy的爬虫程序时,通过program指定scrapy位置,args指定启动的具体spider:

{
"configurations": {
"run": {
"adapter": "debugpy",
"default": true,
"configuration": {
"request": "launch",
"type": "python",
"program": "~/opt/miniconda3/envs/p3/bin/scrapy",
"cwd": "${workspaceRoot}",
"stopOnEntry": true,
"args": ["crawl", "${fileBasenameNoExtension}"]
},
"breakpoints": {
"exception": {
"raised": "N",
"uncaught": "",
"userUnhandled": ""
}
}
}
}
}

配置调试器,添加配置文件 .vimspector.json,如:

{
"configurations": {
"default": {
"adapter": "delve",
"default": true,
"configuration": {
"request": "launch",
"mode": "debug",
"cwd": "${workspaceRoot}",
"stopOnEntry": true,
"program": "${file}",
"args": [
"-http_addr","localhost:8084"
]
},
"breakpoints": {
"exception": {
"raised": "N",
"uncaught": "",
"userUnhandled": ""
}
}
}
}
}

指定adapter为delve来调试go程序,program指定要调试的程序文件,args指定参数http_addr=localhost:8084

  1. vimspector
  2. Debugging python in neovim
  3. Neovim — Debugging Application
  4. Programming Go in Neovim
  5. nvim-lsconfig Configurations
  6. vim-delve
  7. golang: debugging application in neovim
  8. nvim-dap
  9. debug-adapter-configuration

NeoVim配置Go开发环境

在上一篇NeoVim开发环境配置中记录了NeoVim的基本插件配置,随着了解的深入,这里对NeoVim的插件配置进行一步优化处理。

首先对配置进行切分,避免配置都混杂在init.vim中,不利于管理,下面是我的配置文件结构:

Terminal window
$HOME/.config/nvim/
├── after
└── plugin
├── coq_nvim.rc.vim
├── defx.rc.vim
├── fugitive.rc.vim
├── lspconfig.rc.vim
└── treesitter.rc.vim
├── init.vim
├── macos.vim
├── maps.vim
└── plug.vim

init.vim: 根配置文件

macos.vim: mscOS特殊配置

plug.vim :Vim-plug插件配置

maps.vim:快捷键配置

after/plugin: 放置插件的配置脚本,这里面的文件也会在vim每次启动的时候加载,不过是等待plugin加载完成之后才加载after里的内容,所以叫做after。VIM USER MANUAL runtimepath

安装 vim-plug$HOME/.local/share/nvim/site/autoload/plug.vim:

Terminal window
sh -c 'curl -fLo $HOME/.local/share/nvim/site/autoload/plug.vim --create-dirs \
https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim'

我在$HOME/.config/nvim/plug.vim管理配置插件:

if has("nvim")
let g:plug_home = stdpath('data') . '/plugged'
endif
call plug#begin()
...
call plug#end()

为了使plug.vim配置生效,需要在init.vim中进行配置加载:

runtime ./plug.vim

此时,重启NeoVim,运行:PlugInstall进行插件安装。

此外其他几个配置文件:maps.vim,macos.vim 也需要手动配置加载:

if has("unix")
let s:uname = system("uname -s")
" Do mac stuff
if s:uname == "Darwin\n"
runtime ./macos.vim
endif
endif
runtime ./maps.vim

后续安装的插件,分个单独配置,放置到after/plugin目录下。

至此root配置(init.vim)、插件管理、快捷键管理、各插件独立进行配置,配置分离便于管理。

NERDTree是Vim最常用的插件之一,可以在Vim运行时显示目录和文件结构,类似TextMate左侧的文件浏览器,但操作起来更为方便。

目前还有另外一个目录和文件结构管理插件defx.nvim

  • 不依赖于 denite.nvim
  • Vim8/neovim 兼容(Vim8 需要 nvim-yarp)
  • 由 Python3 实现
  • 没有双重过滤器功能
  • 列功能
  • 类似于 denite.nvim 一样支持 source
  • 支持选项
  • 突出显示由列定义
  • 很少的命令(仅:Defx 命令?)
  • 扩展重命名
  • 支持标记
Plug 'Shougo/defx.nvim', { 'do': ':UpdateRemotePlugins' }

安装完成后,使用:Defx命令来使用:

img

每次使用时Buffer会充满整个窗口,并不是我们常用形态,此时需要再进行配置,指定显示的位置以及大小等:

call defx#custom#option('_', {
\ 'winwidth': 38,
\ 'direction': 'topleft',
\ 'split': 'vertical',
\ 'show_ignored_files': 0,
\ 'buffer_name': '',
\ 'toggle': 1,
\ 'resume': 1,
\ })

效果如下:

Defx -split=vertical

使用时通过输入Defx命令太过繁琐效率不高,可以通过设置快捷键来改善,maps.vim中添加:

nnoremap <silent>sf :<C-u>Defx
\ -auto-cd
\ -columns=mark:indent:icon:icons:filename:type:git<CR>

后续通过键入sf即可唤出文件目录管理。

after/plugin/defx.rc.vim 添加快捷键配置:

autocmd FileType defx call s:defx_my_settings()
function! s:defx_my_settings() abort
" Define mappings
nnoremap <silent><buffer><expr> <CR>
\ defx#do_action('open')
nnoremap <silent><buffer><expr> c
\ defx#do_action('copy')
nnoremap <silent><buffer><expr> m
\ defx#do_action('move')
nnoremap <silent><buffer><expr> p
\ defx#do_action('paste')
nnoremap <silent><buffer><expr> l
\ defx#do_action('open')
nnoremap <silent><buffer><expr> E
\ defx#do_action('open', 'vsplit')
nnoremap <silent><buffer><expr> P
\ defx#do_action('preview')
nnoremap <silent><buffer><expr> o
\ defx#do_action('open_tree', 'toggle')
nnoremap <silent><buffer><expr> K
\ defx#do_action('new_directory')
nnoremap <silent><buffer><expr> N
\ defx#do_action('new_file')
nnoremap <silent><buffer><expr> M
\ defx#do_action('new_multiple_files')
nnoremap <silent><buffer><expr> C
\ defx#do_action('toggle_columns',
\ 'mark:indent:icon:filename:type:size:time')
nnoremap <silent><buffer><expr> S
\ defx#do_action('toggle_sort', 'time')
nnoremap <silent><buffer><expr> d
\ defx#do_action('remove')
nnoremap <silent><buffer><expr> r
\ defx#do_action('rename')
nnoremap <silent><buffer><expr> !
\ defx#do_action('execute_command')
nnoremap <silent><buffer><expr> x
\ defx#do_action('execute_system')
nnoremap <silent><buffer><expr> yy
\ defx#do_action('yank_path')
nnoremap <silent><buffer><expr> .
\ defx#do_action('toggle_ignored_files')
nnoremap <silent><buffer><expr> ;
\ defx#do_action('repeat')
nnoremap <silent><buffer><expr> h
\ defx#do_action('cd', ['..'])
nnoremap <silent><buffer><expr> ~
\ defx#do_action('cd')
nnoremap <silent><buffer><expr> q
\ defx#do_action('quit')
nnoremap <silent><buffer><expr> <Space>
\ defx#do_action('toggle_select') . 'j'
nnoremap <silent><buffer><expr> *
\ defx#do_action('toggle_select_all')
nnoremap <silent><buffer><expr> j
\ line('.') == line('$') ? 'gg' : 'j'
nnoremap <silent><buffer><expr> k
\ line('.') == 1 ? 'G' : 'k'
nnoremap <silent><buffer><expr> <C-l>
\ defx#do_action('redraw')
nnoremap <silent><buffer><expr> <C-g>
\ defx#do_action('print')
nnoremap <silent><buffer><expr> cd
\ defx#do_action('change_vim_cwd')
endfunction

设置文件图标可以让文件目录使用起来更加舒适,此时需要使用任意一种Nerd Fonts字体,并配置好iTerm,以便在iTerm2中可以正常显示字体图标:

Terminal window
brew tap homebrew/cask-fonts
brew cask install font-hack-nerd-font

iTerm2配置:

image-20220121123108917

这里有一点需要注意的是,如果勾选了Use a different font for non-ASSII text,那么第二种字体也需要使用Nerd Fonts中的一种,不然还是无法正常显示图标。

配置好iTerm2后,还需要安装defx-icons插件,才能使defx.nvim显示出文件图标,plug.vim添加:

Plug 'kristijanhusak/defx-icons'

:PlugInstall安装重启后,就可以看到:

image-20220121123639182

此时发现文件图片和文件名重叠,添加下面配置即可:

let g:defx_icons_column_length = 2

此时效果如下:

image-20220121123849035

使用官方文档中的默认快捷键配置后,发现总是从当前窗口中,打开文件,很不符合习惯:

image-20220121124512001

如果想要和vscode一样,从右侧窗口打开文件,可以使用drop替代open来配置快捷键:

nnoremap <silent><buffer><expr> <CR> defx#do_action('drop')
nnoremap <silent><buffer><expr> l defx#do_action('drop')

文件名太长导致显示问题时,可以通过下面的方式,限制文件名可以显示的最大长度:

call defx#custom#column('filename', {
\ 'max_width': 26,
\})

mhinz/vim-startify 启动屏可以记录最近编辑的文件,使用对应数字编号就可以快速打开文件,使用起来非常方便。

image-20220121125121988

Neovim已经内置了语言服务器协议 (LSP)。LSP时一种开放的、基于JSON- RPC的协议,用于源代码编辑器和语言服务器之间的通信,可以提供特定于编程语言的功能,如:

  1. 调转到定义
  2. 自动完成
  3. 代码操作(自动格式化、包导入…)
  4. 显示方法签名
  5. 显示、转到参考
  6. 代码片段

从 0.5 版本开始,NeoVim 原生支持该协议。NeoVim在nvim-lspconfig 插件中维护了一个配置列表。该存储库包含设置和排除许多服务器故障的说明。

如果需要为自己刚兴趣的编程语言,需要为其安装和配置相应的LSP服务器,这些可以通过nvim-lspconfig插件来处理。

Plug 'neovim/nvim-lspconfig'

需要注意的是这个插件只是配置管理,我们还需要单独为相应的编程语言安装LSP服务器,具体详见server_configurations

安装Google的 golang lsp server见:

https://github.com/golang/tools/tree/master/gopls

激活LSP服务,以及完整配置如下, lspconfig.rc.vim:

require'lspconfig'.gopls.setup{}
if !exists('g:lspconfig')
finish
endif
lua << EOF
vim.lsp.set_log_level("debug")
EOF
lua << EOF
local nvim_lsp = require('lspconfig')
nvim_lsp.pyright.setup{}
nvim_lsp.gopls.setup{}
local capabilities = vim.lsp.protocol.make_client_capabilities()
capabilities.textDocument.completion.completionItem.snippetSupport = true
-- Use an on_attach function to only map the following keys
-- after the language server attaches to the current buffer
local on_attach = function(client, bufnr)
local function buf_set_keymap(...) vim.api.nvim_buf_set_keymap(bufnr, ...) end
local function buf_set_option(...) vim.api.nvim_buf_set_option(bufnr, ...) end
-- Enable completion triggered by <c-x><c-o>
buf_set_option('omnifunc', 'v:lua.vim.lsp.omnifunc')
-- Mappings.
local opts = { noremap=true, silent=true }
-- See `:help vim.lsp.*` for documentation on any of the below functions
buf_set_keymap('n', 'gD', '<cmd>lua vim.lsp.buf.declaration()<CR>', opts)
buf_set_keymap('n', 'gd', '<cmd>lua vim.lsp.buf.definition()<CR>', opts)
buf_set_keymap('n', 'ga', '<Cmd>lua vim.lsp.buf.code_action()<CR>', opts)
buf_set_keymap('n', 'gr', '<cmd>lua vim.lsp.buf.references()<CR>', opts)
buf_set_keymap('n', 'gi', '<cmd>lua vim.lsp.buf.implementation()<CR>', opts)
buf_set_keymap('n', 'K', '<cmd>lua vim.lsp.buf.hover()<CR>', opts)
buf_set_keymap('n', '<C-k>', '<cmd>lua vim.lsp.buf.signature_help()<CR>', opts)
buf_set_keymap('n', '<space>wa', '<cmd>lua vim.lsp.buf.add_workspace_folder()<CR>', opts)
buf_set_keymap('n', '<space>wr', '<cmd>lua vim.lsp.buf.remove_workspace_folder()<CR>', opts)
buf_set_keymap('n', '<space>wl', '<cmd>lua print(vim.inspect(vim.lsp.buf.list_workspace_folders()))<CR>', opts)
buf_set_keymap('n', '<space>D', '<cmd>lua vim.lsp.buf.type_definition()<CR>', opts)
buf_set_keymap('n', '<space>rn', '<cmd>lua vim.lsp.buf.rename()<CR>', opts)
buf_set_keymap('n', '<space>e', '<cmd>lua vim.diagnostic.open_float()<CR>', opts)
buf_set_keymap('n', '[d', '<cmd>lua vim.diagnostic.goto_prev()<CR>', opts)
buf_set_keymap('n', ']d', '<cmd>lua vim.diagnostic.goto_next()<CR>', opts)
buf_set_keymap('n', '<space>q', '<cmd>lua vim.diagnostic.setloclist()<CR>', opts)
buf_set_keymap('n', '<space>f', '<cmd>lua vim.lsp.buf.formatting()<CR>', opts)
end
-- Use a loop to conveniently call 'setup' on multiple servers and
-- map buffer local keybindings when the language server attaches
local servers = { 'pyright', 'rust_analyzer', 'tsserver' }
for _, lsp in ipairs(servers) do
nvim_lsp[lsp].setup {
on_attach = on_attach,
flags = {
debounce_text_changes = 150,
}
}
end
nvim_lsp.gopls.setup{
cmd = {'gopls'},
-- for postfix snippets and analyzers
capabilities = capabilities,
settings = {
gopls = {
experimentalPostfixCompletions = true,
analyses = {
unusedparams = true,
shadow = true,
},
staticcheck = true,
},
},
on_attach = on_attach,
}
function goimports(timeoutms)
local context = { source = { organizeImports = true } }
vim.validate { context = { context, "t", true } }
local params = vim.lsp.util.make_range_params()
params.context = context
-- See the implementation of the textDocument/codeAction callback
-- (lua/vim/lsp/handler.lua) for how to do this properly.
local result = vim.lsp.buf_request_sync(0, "textDocument/codeAction", params, timeout_ms)
if not result or next(result) == nil then return end
local actions = result[1].result
if not actions then return end
local action = actions[1]
-- textDocument/codeAction can return either Command[] or CodeAction[]. If it
-- is a CodeAction, it can have either an edit, a command or both. Edits
-- should be executed first.
if action.edit or type(action.command) == "table" then
if action.edit then
vim.lsp.util.apply_workspace_edit(action.edit)
end
if type(action.command) == "table" then
vim.lsp.buf.execute_command(action.command)
end
else
vim.lsp.buf.execute_command(action)
end
end
EOF

配置gopls服务,提供跳转、查看定义、重命名等:

-- Mappings.
local opts = { noremap=true, silent=true }
-- See `:help vim.lsp.*` for documentation on any of the below functions
buf_set_keymap('n', 'gD', '<cmd>lua vim.lsp.buf.declaration()<CR>', opts)
buf_set_keymap('n', 'gd', '<cmd>lua vim.lsp.buf.definition()<CR>', opts)
buf_set_keymap('n', 'ga', '<Cmd>lua vim.lsp.buf.code_action()<CR>', opts)
buf_set_keymap('n', 'gr', '<cmd>lua vim.lsp.buf.references()<CR>', opts)
buf_set_keymap('n', 'gi', '<cmd>lua vim.lsp.buf.implementation()<CR>', opts)

format img

格式化代码快捷键配置:

buf_set_keymap('n', '<space>f', '<cmd>lua vim.lsp.buf.formatting()<CR>', opts)

保存文件时自动格式化:

" 保存代码前进行自动格式化
autocmd BufWritePre *.go lua vim.lsp.buf.formatting()

触发包导入有两种方式来解决,一种时通过code action来手动触发:

buf_set_keymap('n', 'ga', '<Cmd>lua vim.lsp.buf.code_action()<CR>', opts)

也可以通过保存文件时,自动触发:

function goimports(timeoutms)
local context = { source = { organizeImports = true } }
vim.validate { context = { context, "t", true } }
local params = vim.lsp.util.make_range_params()
params.context = context
-- See the implementation of the textDocument/codeAction callback
-- (lua/vim/lsp/handler.lua) for how to do this properly.
local result = vim.lsp.buf_request_sync(0, "textDocument/codeAction", params, timeout_ms)
if not result or next(result) == nil then return end
local actions = result[1].result
if not actions then return end
local action = actions[1]
-- textDocument/codeAction can return either Command[] or CodeAction[]. If it
-- is a CodeAction, it can have either an edit, a command or both. Edits
-- should be executed first.
if action.edit or type(action.command) == "table" then
if action.edit then
vim.lsp.util.apply_workspace_edit(action.edit)
end
if type(action.command) == "table" then
vim.lsp.buf.execute_command(action.command)
end
else
vim.lsp.buf.execute_command(action)
end
end

并配置:

autocmd BufWritePre *.go lua goimports(1000)

完成是开箱即用的。我们只需要将它映射到 vimomnifunc即可使我们的Ctrl+x,Ctrl+o工作:

buf_set_option('omnifunc', 'v:lua.vim.lsp.omnifunc')

完成

但是,每次触发都需要通过Ctrl+x,Ctrl+o来触发,十分不方便,为了自动触发,可以在通过安装新的插件ms-jpq/coq_nvim来完成,如:

" 增强代码自动完成
Plug 'ms-jpq/coq_nvim', {'branch': 'coq'}
" 9000+ Snippets
Plug 'ms-jpq/coq.artifacts', {'branch': 'artifacts'}
Plug 'ms-jpq/coq.thirdparty', {'branch': '3p'}

始终将所有操作复制到系统剪贴板:

set clipboard+=unnamedplus

目前基于内置lsp的功能已经比较完善,但是缺乏一个良好的操作UI,如重命名时,输入新名字的地方在窗口底部:

image-20220121173142281

使用async-lsp-finder后:

img

安装

Plug 'glepnir/lspsaga.nvim'

快捷键配置:

" 异步lsp查找
nnoremap <silent> gh :Lspsaga lsp_finder<CR>
" Code Action
nnoremap <silent><leader>ca :Lspsaga code_action<CR>
vnoremap <silent><leader>ca :<C-U>Lspsaga range_code_action<CR>
" 悬停文档
nnoremap <silent>K :Lspsaga hover_doc<CR>
" scroll down hover doc or scroll in definition preview
nnoremap <silent> <C-f> <cmd>lua require('lspsaga.action').smart_scroll_with_saga(1)<CR>
" scroll up hover doc
nnoremap <silent> <C-b> <cmd>lua require('lspsaga.action').smart_scroll_with_saga(-1)<CR>
" help
nnoremap <silent> gs :Lspsaga signature_help<CR>
" 重命名
nnoremap <silent>gr :Lspsaga rename<CR>
" 预览定义
nnoremap <silent> gd :Lspsaga preview_definition<CR>
" 浮动终端
nnoremap <silent> <A-d> :Lspsaga open_floaterm<CR>
tnoremap <silent> <A-d> <C-\><C-n>:Lspsaga close_floaterm<CR>
  1. neovim-lsp
  2. nvim-treesitter
  3. nvim-lspconfig
  4. defx.nvim
  5. defx.txt
  6. How to set up Neovim 0.5 + Modern plugins (LSP, Treesitter, Fuzzy finder, etc)
  7. dotfiles-public
  8. programming-go-in-neovim
  9. go-vim
  10. awesome-neovim
  11. VIM USER MANUAL
  12. runtimepath
  13. 如何配置 Vim 的 Golang 开发环境

NeoVim开发环境配置

img

在vscode等IDE中使用vim插件也已经很久了,最近发现了NeoVim的存在,之前也非常好奇国外的程序员为啥有许多,执着于编辑器之神(Vim) & 神的编辑器(Emacs),因此也尝试使用NeoVim配置了一套环境。

Bram Moolenaar 在写 Vim 时还是 90 年代初,至今已经 20 多年 过去了。其中,不仅包含了大量的遗留代码,而且程序的维护、Bug 的 修复、以及新特性的添加都变得越来越困难。为了解决这些问题,Neovim 项目应运而生。Neo 即“新”之意,它是 Vim 在这个新时代的重生。

根据 Neovim 的自述说明,在总体上,它将达到下列目的:

  • 通过简化维护以改进 Bug 修复及特性添加的速度;
  • 分派各个开发人员的工作;
  • 实现新的、现代化的用户界面,而不必修改核心源代码;
  • 利用新的、基于协同进程的新插件架构改善扩展性,并支持使用任何语言 编写插件

以上介绍来自linuxtoy

此外, 在最近的版本中, 还有非常值得注意的几点:

  • 实现了嵌入式终端模拟器, 可以跟各种REPL插件说再见了
  • 使用远程API(好像是socket), 不光能使用各种语言编写插件, 而且可以很方便的编写GUI版本, 甚至嵌入至IDE中
  • 由于内部优化了事件监听器还是什么的, 代码粘贴的时候, 可以自动识别, 不像vim里一样需要:set paste, 不然会出现蜜汁缩进和括号对
  • 直接支持剪贴板, 不需要重新编译

macOS/OS X 上使用Homebrew安装

Terminal window
brew install neovim

更多安装方式参考:Installing Neovim

安装

Terminal window
sh -c 'curl -fLo "${XDG_DATA_HOME:-$HOME/.local/share}"/nvim/site/autoload/plug.vim --create-dirs \
https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim'

基本使用

neovim继承自vim,基本支持vim的所有特性,可以直接使用vim的配置文件:

Terminal window
mkdir -p ${XDG_CONFIG_HOME:=$HOME/.config}
ln -s ~/.vim $XDG_CONFIG_HOME/nvim
ln -s ~/.vimrc $XDG_CONFIG_HOME/nvim/init.vim

也可以重新开始配置neovim

Terminal window
mkdir -p ~/.config/ ~/.config/nvim
touch ~/.config/ ~/.config/nvim/init.vim

Plug插件,需要在 call plug#begin()call plug#end() 节点中,使用Plug命令进行声明,如:

Terminal window
call plug#begin()
" The default plugin directory will be as follows:
" - Vim (Linux/macOS): '~/.vim/plugged'
" - Vim (Windows): '~/vimfiles/plugged'
" - Neovim (Linux/macOS/Windows): stdpath('data') . '/plugged'
" You can specify a custom plugin directory by passing it as the argument
" - e.g. `call plug#begin('~/.vim/plugged')`
" - Avoid using standard Vim directory names like 'plugin'
" Make sure you use single quotes
" Using a tagged release; wildcard allowed (requires git 1.9.2 or above)
Plug 'fatih/vim-go', { 'tag': '*' }
" Initialize plugin system
call plug#end()

配置好插件后,进行安装升级

Terminal window
:PlugInstall
:PlugUpdate
:PlugUpgrade

查看已经安装的插件状态

Terminal window
:PlugStatus

更多资料,参考vim-plug

方便开发使用,需要对下面一些基本功能进行配置:

  1. 目录管理 - nerdtree
  2. 文件模糊搜索 - fzf
  3. 代码缩略图 - tagbar
  4. 主题配色 - molokai
  5. 状态栏 - airline
  6. 编程语言相关插件(vim-go)
  7. 自动补全- neocomplete.vim
  8. 其他(vim-stratify)

常用非常流行的目录管理插件nerdtree

Terminal window
Plug 'scrooloose/nerdtree'
nnoremap <leader>n :NERDTreeFocus<CR>
nnoremap <C-n> :NERDTree<CR>
nnoremap <C-t> :NERDTreeToggle<CR>
nnoremap <C-f> :NERDTreeFind<CR>

配置快捷键Ctr + n, Ctrl + t, Ctrl +f

fzf 是一个非常高效实用且美观的命令行工具,并且配置有对应的 vim 插件 fzf.vim。比如下面这个效果图,我们可以让 fzf 在中间进行显示,有点类似于 IDEA 的搜索窗口。

image-20220118164902042

fzf.vim 依赖fzf,安装插件前需要先安装好fzf:

Terminal window
brew install fzf

使用插件:

Terminal window
Plug 'junegunn/fzf', { 'do': { -> fzf#install() } }
Plug 'junegunn/fzf.vim'

NeoVim命令模式下输入:Files :Buffers即可弹出模糊搜索窗口进行搜索

更多信息参考:fzf.vimfzf

Tagbar是一个Vim插件,它提供了一种简单的方法来浏览当前文件的标记并获得其结构的概述。它通过创建一个侧边栏来显示当前文件的ctags-generated标记,并按其范围排序。

image-20220118170918463

安装插件,并配置快捷键F8:

Terminal window
" tagbar
Plug 'majutsushi/tagbar'
nnoremap <F8> :TagbarToggle<cr>

如果您这样做,F8键将切换Tagbar窗口,当然也可以配置任何其他自己想要的快捷键。

更多资料参考:tagbar

主题的话根据个人喜好选择。

Terminal window
Plug 'fatih/molokai'
syntax enable
set t_Co=256
let g:rehash256 = 1
let g:molokai_original = 1
colorscheme molokai
Terminal window
Plug 'vim-airline/vim-airline'
Plug 'vim-airline/vim-airline-themes'

或者

Terminal window
Plug 'morhetz/gruvbox'
" 使用配色方案gruvbox
colorscheme gruvbox

更多主题样式配置,常见:vim-airline gruvbox

使用vim/neogim进行go语言的开发需要vim-go

Terminal window
" go 主要插件
Plug 'fatih/vim-go', { 'tag': '*' }
" go 中的代码追踪,输入 gd 就可以自动跳转
Plug 'dgryski/vim-godef'

更多配置参考:vim-go

代码自动补全,需要使用deoplete.nvim

安装依赖:

Terminal window
pip3 install pynvim
pip3 install msgpack

安装配置插件

Plug 'Shougo/deoplete.nvim', { 'do': ':UpdateRemotePlugins' }
let g:deoplete#enable_at_startup = 1

配置TAB快捷键完成自动提示输入:

Terminal window
" <TAB>: completion.
inoremap <expr><TAB> pumvisible() ? "\<C-n>" : "\<TAB>"

至此重启NeoVim后,自动补全会根据当前文件中已有的名字进行猜测并补全。为了根据不同的语言特性提供更加完善的补全效果,需要安装相应的。 如对于Python可以再安装deoplete-jedi 依赖安装

Terminal window
pip3 install --user jedi --upgrade

插件安装:

Plug 'deoplete-plugins/deoplete-jedi'

修改配置后,使用:PlugInstall命令进行安装完成后重启NeoVim,此时就可以基于jedi在NeoVim上对Python提供完美的自动补全功能。

更多配置参考:deoplete.nvim

vim-startify 为Vim/NeoVim开屏页美化插件,可以记录最近编辑的文件,使用对应数字编号就可以快速打开文件,使用起来非常方便。

image-20220118172551047

安装:

Terminal window
Plug 'mhinz/vim-startify'

完整的配置init.vim

Terminal window
call plug#begin()
" The default plugin directory will be as follows:
" - Vim (Linux/macOS): '~/.vim/plugged'
" - Vim (Windows): '~/vimfiles/plugged'
" - Neovim (Linux/macOS/Windows): stdpath('data') . '/plugged'
" You can specify a custom plugin directory by passing it as the argument
" - e.g. `call plug#begin('~/.vim/plugged')`
" - Avoid using standard Vim directory names like 'plugin'
" Make sure you use single quotes
" The NERDTree is a file system explorer for the Vim editor.
Plug 'preservim/nerdtree'
" indentation guides to all lines
Plug 'lukas-reineke/indent-blankline.nvim'
" fzf
Plug 'junegunn/fzf', { 'do': { -> fzf#install() } }
Plug 'junegunn/fzf.vim'
" 状态栏美化
Plug 'vim-airline/vim-airline'
Plug 'vim-airline/vim-airline-themes'
" tagbar
Plug 'majutsushi/tagbar'
nnoremap <F8> :TagbarToggle<cr>
" vim开屏页美化插件,可以记录最近编辑的文件,使用对应数字编号就可以快速打开文件,使用起来非常方便。
Plug 'mhinz/vim-startify'
" AutoComplete
Plug 'Shougo/deoplete.nvim'
" Python AutoComplete
Plug 'deoplete-plugins/deoplete-jedi'
let g:deoplete#enable_at_startup = 1
" Insert or delete brackets, parens, quotes in pair.
Plug 'jiangmiao/auto-pairs'
" 配色方案
Plug 'morhetz/gruvbox'
call plug#end()
set encoding=utf-8
set tabstop=4
set softtabstop=4
set shiftwidth=4
" 表示Tab自动转换成空格
set expandtab
" 表示换行后自动缩进
set autoindent
" 智能对齐
set smartindent
" 当文件在外部被修改时,自动重新读取
set autoread
" 显示行号、 显示当前行行号,其它行的行号都是以当前行为基准从 1 开始增加(即相对行号)
set number relativenumber
" 设置配色方案
colorscheme gruvbox
let g:airline_theme='gruvbox'
" 启用语法高亮
syntax enable
" 使用黑色主题-light dark
set bg=dark
" vim记住的历史操作的数量,默认的是20
set history=40
" NERDTree
nnoremap <leader>n :NERDTreeFocus<CR>
nnoremap <C-n> :NERDTree<CR>
nnoremap <C-t> :NERDTreeToggle<CR>
nnoremap <C-f> :NERDTreeFind<CR>
" <TAB>: completion.
inoremap <expr><TAB> pumvisible() ? "\<C-n>" : "\<TAB>"
  1. 维基百科-Vim
  2. 精通 VIM ,此文就够了
  3. nerdtree
  4. fzf
  5. him-startify
  6. tagbar
  7. vim-airline
  8. vim-go
  9. neocomplete.vim
  10. programming-go-in-neovim