使用 lua 配置 neovim
neovim 0.4.4 to 0.6.1
直到 2 月份我用的都是 nvim 0.4.4,去年 0.5 发布的时候没有更新,然后 2 月初直接更新到了 0.6.1,并且把配置改成了 lua,再陆陆续续用了 2 个月,划个水写点东西记一下。
配置结构
nvim 的配置放在 $HOME/.config/nvim
下,这点没变,只不过启动配置由 vimscript 的 init.vim
改为 lua 的 init.lua
,如果需要分成多个模块,则需要在 init.lua 所在目录下创建 lua
目录,把其他模块放入 lua 目录下,init.lua
中通过 require '模块名'
来加载模块。
我的配置比较简单,最终呈现的是这样的目录结构:
1 | ├── init.lua |
新配置介绍
在 nvim 里,除了 init.lua,你还可以在命令模式下通过 :lua <lua 语句>
执行 lua 语句,lua 运行时可以通过默认加载的 vim
模块来访问和控制 vim 运行时。
常用模块
vim.{o/wo/bo}
: vim 选项,例如:lua vim.wo.number = true
等价于:set number
vim.g
:全局变量,相当于set g:variable = value
vim.env
: 访问和配置环境变量vim.fn
: 访问 vim 运行时函数,例如:lua print(vim.fn.getenv('HOME'))
等价于:echo getenv('HOME')
写法vim.api
: 提供了一些 api 代替 vim 命令,例如不严格来说,vim 中的 map 对应vim.api.nvim_set_keymap
vim.cmd
: 在 lua 中执行 vimscript,例如:lua vim.cmd('echo getenv("HOME")')
vim.lsp
: 提供了 lsp 相关的功能,例如::lua vim.lsp.buf.formatting()
vim.inspect
: 可以把 vim 运行时对象转成可以打印的 lua 对象格式,例如lua print(vim.inspect(vim.opt.completeopt))
其他没写到的都是因为我没怎么用到。
o/wo/bo 和 opt
vim 中有 3 种范围的选项:global、window-local、buffer-local,在旧版(vimscript 版)里,统一使用 set <option> [ = value ]
语法设置,新版改用带范围的 o/wo/bo 设置选项,并且使用布尔值代替了 no*
选项,并且 nvim 还提供了一种配置方法,那就是 vim.opt
,opt 的写法比较像旧版的 set,也有一些区别,我把三种写法都写出来感受一下
vimscript 写法:
1 | set backup |
lua o/wo/bo 写法:
1 | vim.o.backup = false |
lua opt 写法:
1 | vim.opt.backup = false |
用哪种全凭个人喜好
插件
- 包管理: packer.nvim
之前用的是 vim-plug 管理插件,这次升级也跟着换成了 lua 管理 packer,用的过程中需要注意的是,如果一个插件(参考我配置中使用 cmp-buffer 的方式)没有直接 use,那么它不会触发编译 plugin/packer_compiled.lua,需要在 PackerInstall
后手动 :PackerCompile
。
- 语法高亮: nvim-treesitter
nvim 0.5 开始支持 treesitter 高亮,安装配置 nvim-treesitter 插件后开启,插件还能提供折叠和基于语法选择的功能。分析语法需要通过额外的 parser,这个是要额外下载的,通过 :TSInstall <lang>
安装指定语法的 parser,通过 :TSInstallInfo
查看已经安装完成的 parser。
- lsp 配置: nvim-lspconfig
neovim 团队维护的 lsp 配置,要用自带的 lsp 基本都要安装这个插件,如果自己不太想管理 lsp,可以用 nvim-lsp-installer 插件来管理,如果 lspconfig 目前不支持你用的 lsp server,只能通过 fork 项目在 server_configurations 下增加对应的 lsp server。
- 自动完成: nvim-cmp 和 luasnip
两个要一起说,因为 nvim-cmp 必须要配置 snippet 的 expand 函数
遇到的一些小问题
- bufferline 不刷新
我之前一直习惯用 :badd
,但是 bufferline 不会刷新,必须要手动 :redrawtabline
才会刷新,改成了 :edit
就可以了
- luasnip 光标乱飞
我找到了相关 issue,大概原因是使用 snippet 时没有跳转所有位置,那么没被跳转过的位置都会被记录下来,哪怕你离开了这个 snippet 的区域,在下次 jump 还会 jump 回来,解决方法更加邪门,配置 region_check_events 每次光标移动都会触发 luasnip 调用 exit_out_of_region。
- treesitter 导致代码变乱
触发条件是快速撤回代码,过程中一旦 treesitter 保持,就会让高亮失效,然后代码变乱,暂时没解决。
结尾
我不太懂 lua,不过用到目前感觉影响不大,lua 是一门非常简单易懂的语言,唯一想吐槽的是当 strng 或 table 作为唯一参数可以省略函数括号这个语法糖,让大家给的例子功能一样,写法不一样。
目前整体配置还是没办法完全绕开 vimscript,例如 autocmd 之类,官方正在跟进 api,等 0.7 发布应该基本可以脱离 vimscript 了。