因为偶尔需要修改 Neovim 的高亮,涉及到颜色调整,以往使用的是外部工具,来回切换非常麻烦。也找了一些 Neovim/Vim 的插件,但是使用的感觉确实不尽如人意。
因此,自己实现了一个简便版本的调色板插件 cpicker.nvim
,该插件存储于 SpaceVim 的 bundle/cpicker.nvim
文件夹内。
为了方便单独使用,手动同步更新到 wsdjeg/cpicker.nvim。
如果是 SpaceVim 用户,只需要启用 tools#cpicker 模块即可:
[[layers]]
name = 'tools#cpicker'
对于非 SpaceVim 用户,可以用插件管理器安装:
Plug 'https://spacevim.org/git/repos/SpaceVim/'
Plug 'wsdjeg/cpicker.nvim'
操作快捷键:
按键 | 功能描述 |
---|---|
h / <Left> |
减小光标下的值 |
l / <Right> |
增加光标下的值 |
<Enter> |
复制光标下的颜色值 |
最近在使用 SpaceVim 的标签栏(tabline)时发现,对于新增的空内容的缓冲区(buffer),标签栏上方并不会列出。
检查源码发现标签栏跟踪缓冲区新增的代码只监听了:BufNewFile
跟 BufReadPost
事件。
vim.api.nvim_create_autocmd({ 'BufNewFile', 'BufReadPost' }, {
callback = vim.schedule_wrap(function(event)
if
vim.api.nvim_buf_is_valid(event.buf)
and index(right_hide_bufs, event.buf) == -1
and index(visiable_bufs, event.buf) == -1
and index(left_hide_bufs, event.buf) == -1
then
table.insert(right_hide_bufs, event.buf)
end
end),
group = tabline_augroup,
})
测试发现 :enew
命令及 :new
命令并不会触发这两个事件。修改源码增加监听 BufNew
事件。
虽然问题是修复了,但是我觉得有必要整理下缓冲区相关事件的触发时机。
可以使用命令 :echo getcompletion('Buf', 'event')
快速查看当前 Neovim 版本支持的缓冲区事件列表。
通过一些实例来测试事件触发的时机,测试代码如下:
需要忽略掉 *Cmd
事件,避免文件读写失败。
local log = require("spacevim.logger").derive("logevent")
local group = vim.api.nvim_create_augroup("logevent", { clear = true })
vim.api.nvim_create_autocmd(
vim.tbl_filter(function(e)
return not vim.endswith(e, "Cmd")
end, vim.fn.getcompletion("Buf", "event")),
{
callback = vim.schedule_wrap(function(event)
log.debug(event.event .. event.buf)
end),
group = group,
}
)
:new
[ logevent ] [13:20:39:562] [ Debug ] BufNew5
[ logevent ] [13:20:39:562] [ Debug ] BufAdd5
[ logevent ] [13:20:39:562] [ Debug ] BufAdd5
[ logevent ] [13:20:39:562] [ Debug ] BufLeave4
[ logevent ] [13:20:39:562] [ Debug ] BufEnter5
[ logevent ] [13:20:39:562] [ Debug ] BufWinEnter5
:enew
[ logevent ] [13:22:42:452] [ Debug ] BufNew6
[ logevent ] [13:22:42:452] [ Debug ] BufAdd6
[ logevent ] [13:22:42:452] [ Debug ] BufAdd6
[ logevent ] [13:22:42:452] [ Debug ] BufLeave4
[ logevent ] [13:22:42:452] [ Debug ] BufWinLeave4
[ logevent ] [13:22:42:452] [ Debug ] BufHidden4
[ logevent ] [13:22:42:452] [ Debug ] BufEnter6
[ logevent ] [13:22:42:452] [ Debug ] BufWinEnter6
:echo bufadd('')
[ logevent ] [13:47:57:482] [ Debug ] BufNew6
echo nvim_create_buf(v:false, v:true)
[ logevent ] [14:25:06:555] [ Debug ] BufNew5
echo nvim_create_buf(v:true, v:true)
[ logevent ] [14:26:32:389] [ Debug ] BufNew11
[ logevent ] [14:26:32:389] [ Debug ] BufAdd11
[ logevent ] [14:26:32:389] [ Debug ] BufAdd11
当打开一个文件后,执行 :set nobuflisted
, 在执行 :set buflisted
[ logevent ] [14:38:15:888] [ Debug ] BufDelete4
[ logevent ] [14:38:19:857] [ Debug ] BufAdd4
[ logevent ] [14:38:19:857] [ Debug ] BufAdd4
打开一个存在的文件::e README.md
[ logevent ] [14:44:15:717] [ Debug ] BufNew8
[ logevent ] [14:44:15:717] [ Debug ] BufAdd8
[ logevent ] [14:44:15:717] [ Debug ] BufAdd8
[ logevent ] [14:44:15:717] [ Debug ] BufLeave4
[ logevent ] [14:44:15:717] [ Debug ] BufWinLeave4
[ logevent ] [14:44:15:717] [ Debug ] BufHidden4
[ logevent ] [14:44:15:717] [ Debug ] BufReadPre8
[ logevent ] [14:44:15:717] [ Debug ] BufReadPost8
[ logevent ] [14:44:15:717] [ Debug ] BufReadPost8
[ logevent ] [14:44:15:717] [ Debug ] BufEnter8
[ logevent ] [14:44:15:717] [ Debug ] BufWinEnter8
打开一个不存在的新文件: :e newfile.txt
[ logevent ] [14:45:56:519] [ Debug ] BufNew10
[ logevent ] [14:45:56:519] [ Debug ] BufAdd10
[ logevent ] [14:45:56:519] [ Debug ] BufAdd10
[ logevent ] [14:45:56:519] [ Debug ] BufLeave4
[ logevent ] [14:45:56:519] [ Debug ] BufWinLeave4
[ logevent ] [14:45:56:519] [ Debug ] BufHidden4
[ logevent ] [14:45:56:519] [ Debug ] BufNewFile10
[ logevent ] [14:45:56:519] [ Debug ] BufEnter10
[ logevent ] [14:45:56:519] [ Debug ] BufWinEnter10
输入模式下,成对符号的自动补全一直是比较常用的功能。使用了很多年 delimitMate ,
基本功能正常,但是偶尔会出现卡屏现象,等一段时间或者按下 ctrl-c
可以结束卡屏,但是会输入很多个 <Plug>delimitMate(
。
但是这一现象并无法百分百重现。
想着这么多年过去了,会不会有新的更好用的插件,于是搜了下,目前已知的括号补全插件有:
exists('#CompleteDone') == 1
仓库中 Vim 脚本只有 plugin/auto-pairs.vim
(673 行)。 监听 BufEnter
事件,映射 g:AutoPairs
所设定的成对符号。
通过监听 CompleteDone
事件,判断补全 item 的结尾是否匹配设定的成对符号。
是使用 Lua 实现的 Neovim 插件。在 nvim-autopairs.setup 函数里使用以下三组事件监听来实现补全。
local group = api.nvim_create_augroup('autopairs_buf', { clear = true })
api.nvim_create_autocmd({ 'BufEnter', 'BufWinEnter' }, {
--- M.on_attach
})
api.nvim_create_autocmd('BufDelete', {
---
})
api.nvim_create_autocmd('FileType', {
---
})
在 M.on_attach
函数里,主要有一个 expr
映射及一个 InsertCharPre
事件监听:
local enable_insert_auto = false -- 初始化是否插入的 flag
local expr_map = function(key)
api.nvim_buf_set_keymap(bufnr, 'i', key, '', {
expr = true
--- 设定 expr 映射
})
end
for _, rule in pairs(rules) do
-- 根据每个规则映射快捷键,并计算是 enable_insert_auto 值
end
if enable_insert_auto then
api.nvim_create_autocmd('InsertCharPre', {
--- 如果 enable_insert_auto 为 true, 则监听 InsertCharPre 事件
})
end
repo | Github stars | Issues | pull requests | last commit |
---|---|---|---|---|
auto-pairs | 4.1k | 138 Open / 155 Closed | 27 Open / 53 Closed | Feb 27, 2019 |
delimitMate | 2k | 47 Open / 219 Closed | 5 Open / 36 Closed | Dec 14, 2020 |
nvim-autopairs | 3k | 12 Open / 287 Closed | 1 Open / 157 Closed | May 20 2024 |
neopairs.vim | 31 | 0 Open / 4 Closed | 0 Open / 0 Closed | Mar 16, 2016 |
mini.pairs 仓库有2个:mini.nvim、mini.pairs。 因为 mini.nvim 仓库实际上是由几十个独立插件组合而成,其 Issues 跟 pull requests 列表应对到 mini.pairs 上到底有多少,无法评估。
auto-pairs 有一个较活跃的 fork 版本LunarWatcher/auto-pairs,目前维护状态正常:
在使用 Neovim 之前,一直使用的是 Vim Script 写 Vim 脚本。随着 Neovim 的出现,以及 Lua 的速度优势,于是将之前写的插件使用 Lua 进行重写了。 在这里记录一些从 Vim Script 切换到 Lua 遇到的一些问题,以及前后兼容的写法。
个人比较看重脚本的向后兼容,在非必要的情况下,对外的接口函数不会改变,通过以下一个示例大致展示了如何做到前后版本的脚本兼容。
比如,早期的 Vim Script 脚本实现的脚本如下:
autoload/test.vim
function! test#test(name)
echo "hello " . name
endfunction
那么,对于 Neovim 新版本的支持,可以使用 Lua 实现类似的功能:
lua/test.lua
local M = {}
function M.test(name)
print('hello ' .. name)
end
return M
为了让前面的 test.vim 使用 Lua 函数,可以做如下修改:
function! test#test(name)
if has('nvim')
lua require('test').test(vim.api.nvim_eval('name'))
else
echo "hello " . name
endif
endfunction
以上函数存在一个问题,就是每次调用时,都会去检测一次版本,可以将脚本修改为:
if has('nvim')
function! test#test(name)
lua require('test').test(vim.api.nvim_eval('name'))
endfunction
else
function! test#test(name)
echo "hello " . name
endfunction
endif
这样一来,版本检测仅仅在这个脚本文件被读取载入时才执行一次,在这之后 test#test(name)
这个函数的本体仅限于一行代码。
lua require('test').test(vim.api.nvim_eval('name'))
上述的示例中只有一种调用方式,即使用 :lua
命令,该命令使用有两种方式。
lua print('hello')
lua << EOF
print('hello')
EOF
此外,使用 :lua
命令,如果遇到 Vim Script 函数原先需要有返回值的话,比较麻烦,可以使用 luaeval()
函数,比如:
function! test#test(name)
call luaeval("require('test').test(vim.api.nvim_eval('name'))")
" 也可以使用 return 返回值
return luaeval("require('test').test(vim.api.nvim_eval('name'))")
endfunction
Neovim 0.5.0 增加了 v:lua
,可以更加方便地在 Vim Script 中调用 Lua, 示例如下:
function! test#test(name)
" 这里可以直接使用参数,而不需要使用 nvim_eval
return v:lua.require('test').test(a:name)
endfunction
Neovim 提供了 vim.fn
以及 nvim_call_function(fn, argv)
。
-- built-in functions
vim.fn.executable(var)
-- User autoload function
vim.fn['test#test'](name)
对于 Vim 的 funcref 变量,可以使用如下方式调用:
function! s:test_hello(name)
endfunction
let s:fn = function('s:test_hello')
function! test#run(fn)
if type(a:fn) == 2
let fn = string(a:fn)[10:-3]
elseif type(a:fn) == type('')
let fn = a:fn
endif
call v:lua.require('test').run(fn)
endf
因为在维护 SpaceVim 这一项目,虽然我自己目前日常使用 neovim-0.9.5,但是还有不少用户会使用 neovim-nightly 版本。 因此,升级至每日构建版本测试 SpaceVim。
Windows 下升级也比较简单,使用 scoop 命令即可:
scoop uninstall neovim
scoop install neovim-nightly
安装后,启动一堆错误,也做了一部分修复,commits 如下:
* 2ad0da42 - perf(treesitter): add default setup function (Eric Wong 49 minutes ago)
* f8b280e0 - fix(flygrep): remove `t_ve` option (Eric Wong 68 minutes ago)
* c46968d5 - fix(colorscheme): link WinSeparator to VertSplit (Eric Wong 79 minutes ago)
* 9ee8606e - fix(telescope): fix deoplete autocmd (Eric Wong 82 minutes ago)
* 74c93c6c - chore(treesitter): update nvim-treesitter to 0.9.1 for Nvim-0.8.x (Eric Wong 2 hours ago)
vim.o.v_te
报错原先,在我的代码里有很多通过设置 &v_te
选项来实现修改光标的造型。但是升级到新版本后,就报如下错误:
Error detected while processing function SpaceVim#plugins#flygrep#open:
line 1:
E5108: Error executing lua C:\Users\wsdjeg\.SpaceVim\/lua/spacevim/plugin/flygrep.lua:780: Unknown option 't_ve'
stack traceback:
[C]: in function '__index'
C:\Users\wsdjeg\.SpaceVim\/lua/spacevim/plugin/flygrep.lua:780: in function 'open'
[string ":lua"]:1: in main chunk
检查了下源码,原来是因为执行了 vim.o.v_te
,尝试做了一些测试,增加exists()
判断,可恨的是 exists('&t_ve')
居然返回 1。
那么就无法判断了,只能是删除这些设置。
VertSplit
失效更新后,分割窗口的竖线没有高亮了。查了下 :hi VertSplit
,输出结果显示高亮设置正常。看了 :h hl-VertSplit
才知道,原来分割窗口的高亮组名称修改了。
修改成了 WinSeparator
。因此在 ColorScheme 的 autocmd 内增加了:
hi link WinSeparator VertSplit
treesitter
高亮报错这是我遇到最无语的错误。每当打开 lua 文件、help 文件 就会弹出报错 treesitter parser 不存在。起初我以为是 nvim-treesitter 的问题,更新并增加配置禁用所有的高亮都不行。
报错如下:
Error detected while processing function startify#open_buffers[13]..<SNR>276_open_buffer[12]..BufReadPost Autocommands for "*":
Error executing lua callback: ...s\neovim-nightly\current\share\nvim\runtime\filetype.lua:30: Error executing lua: ...s\neovim-nightly\current\share\nvim\runtime\filetype.lua:31: function startify#open_buffers[13]..<SNR>276_open_buffer[12]..BufReadPost Autocommands for "*"..FileType Autocommands for "*"..function <SNR>1_LoadFTPlugin[20]..script D:\Scoop\apps\neovim-nightly\current\share\nvim\runtime\ftplugin\lua.lua: Vim(runtime):E5113: Error while calling lua chunk: ...rrent\share\nvim\runtime/lua/vim/treesitter/language.lua:104: no parser for 'lua' language, see :help treesitter-parsers
stack traceback:
[C]: in function 'error'
...rrent\share\nvim\runtime/lua/vim/treesitter/language.lua:104: in function 'add'
...t\share\nvim\runtime/lua/vim/treesitter/languagetree.lua:112: in function 'new'
...ightly\current\share\nvim\runtime/lua/vim/treesitter.lua:41: in function '_create_parser'
...ightly\current\share\nvim\runtime/lua/vim/treesitter.lua:108: in function 'get_parser'
...ightly\current\share\nvim\runtime/lua/vim/treesitter.lua:416: in function 'start'
...ovim-nightly\current\share\nvim\runtime\ftplugin\lua.lua:2: in main chunk
执行 :help treesitter-parsers
同样报错,理解为打开 help 文件也报错,同只执行 :h
。
Error detected while processing modelines[274]..FileType Autocommands for "*"..function <SNR>1_LoadFTPlugin[20]..script D:\Scoop\apps\neovim-nightly\current\share\nvim\runtime\ftplugin\help.lua:
E5113: Error while calling lua chunk: ...rrent\share\nvim\runtime/lua/vim/treesitter/language.lua:104: no parser for 'vimdoc' language, see :help treesitter-parsers
stack traceback:
[C]: in function 'error'
...rrent\share\nvim\runtime/lua/vim/treesitter/language.lua:104: in function 'add'
...t\share\nvim\runtime/lua/vim/treesitter/languagetree.lua:112: in function 'new'
...ightly\current\share\nvim\runtime/lua/vim/treesitter.lua:41: in function '_create_parser'
...ightly\current\share\nvim\runtime/lua/vim/treesitter.lua:108: in function 'get_parser'
...ightly\current\share\nvim\runtime/lua/vim/treesitter.lua:416: in function 'start'
...vim-nightly\current\share\nvim\runtime\ftplugin\help.lua:2: in main chunk
于是,禁用 SpaceVim 的 treesitter 模块,任然报错。查看了 neovim-nightly 的源码,发现,原来在这几个文件里面默认增加了:vim.treesitter.start()
D:\Scoop\apps\neovim-nightly\current\share\nvim\runtime\ftplugin\help.lua
D:/Scoop/apps/neovim-nightly/0.10.0-2559/share/nvim/runtime/ftplugin/lua.lua
执行 cat D:/Scoop/apps/neovim-nightly/0.10.0-2559/share/nvim/runtime/ftplugin/lua.lua
, 发现就两行代码,也没有任何条件判断跟 error handle。
-- use treesitter over syntax
vim.treesitter.start()
说实话,没空去这样试错。
scoop uninstall neovim-nightly
scoop install neovim
nvim --version
NVIM v0.9.5
Build type: RelWithDebInfo
LuaJIT 2.1.1703942320
Compilation: C:/Program Files (x86)/Microsoft Visual Studio/2019/Enterprise/VC/Tools/MSVC/14.29.30133/bin/Hostx64/x64/cl.exe /MD /Zi /O2 /Ob1 -W3 -wd4311 -wd4146 -DUNIT_TESTING -D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_DEPRECATE -D_WIN32_WINNT=0x0602 -DMSWIN -DINCLUDE_GENERATED_DECLARATIONS -ID:/a/neovim/neovim/.deps/usr/include/luajit-2.1 -ID:/a/neovim/neovim/.deps/usr/include -ID:/a/neovim/neovim/.deps/usr/include -ID:/a/neovim/neovim/build/src/nvim/auto -ID:/a/neovim/neovim/build/include -ID:/a/neovim/neovim/build/cmake.config -ID:/a/neovim/neovim/src -ID:/a/neovim/neovim/.deps/usr/include -ID:/a/neovim/neovim/.deps/usr/include -ID:/a/neovim/neovim/.deps/usr/include -ID:/a/neovim/neovim/.deps/usr/include -ID:/a/neovim/neovim/.deps/usr/include -ID:/a/neovim/neovim/.deps/usr/include -ID:/a/neovim/neovim/.deps/usr/include
system vimrc file: "$VIM\sysinit.vim"
fall-back for $VIM: "C:/Program Files (x86)/nvim/share/nvim"
Run :checkhealth for more info
今天在 wsl 内将 ~/.SpaceVim
仓库的远程地址设置成 https://spacevim.org/git/repos/SpaceVim/
后,再执行 git pull
出现错误:
fatal: unable to access 'https://spacevim.org/git/repos/SpaceVim/': gnutls_handshake() failed: Error in the pull function.
但是,恢复成 github 或者 gitlab 仓库地址后,就又可以执行 git pull
了。
执行如下命令,看看网络链接到底怎么回事:
GIT_CURL_VERBOSE=1 git pull
输出为:
23:29:04.865626 http.c:664 == Info: Couldn't find host spacevim.org in the (nil) file; using defaults
23:29:04.884061 http.c:664 == Info: Trying 104.21.53.107:443...
23:29:05.085433 http.c:664 == Info: Trying 2606:4700:3037::ac43:d405:443...
23:29:05.085549 http.c:664 == Info: Immediate connect fail for 2606:4700:3037::ac43:d405: Network is unreachable
23:29:05.085601 http.c:664 == Info: Trying 2606:4700:3032::6815:356b:443...
23:29:05.085623 http.c:664 == Info: Immediate connect fail for 2606:4700:3032::6815:356b: Network is unreachable
23:29:05.118268 http.c:664 == Info: Connected to spacevim.org (104.21.53.107) port 443 (#0)
23:29:05.138108 http.c:664 == Info: found 372 certificates in /etc/ssl/certs
23:29:05.138186 http.c:664 == Info: GnuTLS ciphers: NORMAL:-ARCFOUR-128:-CTYPE-ALL:+CTYPE-X509:-VERS-SSL3.0
23:29:05.138223 http.c:664 == Info: ALPN, offering h2
23:29:05.138240 http.c:664 == Info: ALPN, offering http/1.1
23:29:05.149601 http.c:664 == Info: gnutls_handshake() failed: Error in the pull function.
23:29:05.149680 http.c:664 == Info: Closing connection 0
fatal: unable to access 'https://spacevim.org/git/repos/SpaceVim/': gnutls_handshake() failed: Error in the pull function.
删除已有 git
:
sudo apt uninstall git
下载 git 源码
wget "https://mirrors.edge.kernel.org/pub/software/scm/git/git-2.9.5.tar.xz"
tar -xvf git-2.9.5.tar.xz
安装依赖
sudo apt-get update
sudo apt-get install curl jq -y
sudo apt-get install build-essential autoconf dh-autoreconf -y
sudo apt-get install libcurl4-openssl-dev gettext -y
编译
make configure
./configure --prefix=/usr --with-openssl
make -j4
安装
sudo make install