什么是 tablineat
熟悉 Vim 或者 Neovim 的用户对于其状态栏(statusline)和标签栏(tabline)应该也不陌生,对于这两个 UI 组件上面的点击事件, 早期是只有 tabline 上面支持点击操控 Vim 的标签页。
很早以前,就有用户想在 vim-airline 插件的标签栏实现 Buffer 切换的功能, 但是似乎直到现在,Vim 都未增加该功能。
2016 年,Neovim 增加了 tablineat 特性,使得用户可以在自定义状态栏和标签栏时,
指定某个区域设定对应的点击事件回调函数,以此实现监控状态栏和标签栏的点击事件。可以使用 has('tablineat')
检测当前 Neovim 是否支持该特性。
以下内容摘自 :h statusline
@ N Start of execute function label. Use %X or %T to end the label,
e.g.: %10@[email protected]%X. Clicking this label runs the
specified function: in the example when clicking once using left
mouse button on "foo.c", a `SwitchBuffer(10, 1, 'l', ' ')`
expression will be run. The specified function receives the
following arguments in order:
1. minwid field value or zero if no N was specified
2. number of mouse clicks to detect multiple clicks
3. mouse button used: "l", "r" or "m" for left, right or middle
button respectively; one should not rely on third argument
being only "l", "r" or "m": any other non-empty string value
that contains only ASCII lower case letters may be expected
for other mouse buttons
4. modifiers pressed: string which contains "s" if shift
modifier was pressed, "c" for control, "a" for alt and "m"
for meta; currently if modifier is not pressed string
contains space instead, but one should not rely on presence
of spaces or specific order of modifiers: use |stridx()| to
test whether some modifier is present; string is guaranteed
to contain only ASCII letters and spaces, one letter per
modifier; "?" modifier may also be present, but its presence
is a bug that denotes that new mouse button recognition was
added without modifying code that reacts on mouse clicks on
this label.
Use |getmousepos()|.winid in the specified function to get the
corresponding window id of the clicked item.
测试标签栏点击事件
按照前面的帮助文档描述的内容,可以使用格式 %N@function_name@text%X
来指定区域监控点击事件,
回调函数的名称为两个 @
标记之间的字符串,%
与 @
之间的数字作为第一个参数。
写一个测试函数,看一看点击事件的具体执行效果:
function! OnClick(a, b, c, d) abort
echom a:a
echom a:b
echom a:c
echom '>' . a:d . '<'
endfunction
set tabline=xxxxxxx%1@OnClick@11111%X%2@OnClick@22222%X
将以上文件保存为 vim 文件并执行 :so %
后,状态栏变成了
xxxxxxx1111122222
, 鼠标左键单击 11111
区域,看到如下输出。
1
1
l
> <
上述四行分别对应函数的四个参数:
- 第一个参数是
%
与@
之间的数字 - 第二个参数是鼠标点击的次数
- 第三个参数是鼠标键位, 可以是左键(
l
)、右键(r
)或者中键(m
) - 第四个参数对应的时按下的组合键,Ctrl 键(
c
)、Shift 键(s
)、Alt 键(a
)、Meta 键(m
) - 最后一个参数是对应的
shift/alt/ctrl
。
多次点击存在的问题
在使用前面的测试脚本测试的过程中,发现第二个参数返回的是点击的次数,其结果不是完全可预期的。为了更加方便测试,将测试的脚本修改如下:
function! OnClick(a, b, c, d) abort
echom '点击次数:' .. a:b
endfunction
set tabline=xxxxxxx%1@OnClick@11111%X%2@OnClick@22222%X
多次点击后,其结果如下:
点击次数:1
点击次数:2
点击次数:3
点击次数:4
点击次数:1
点击次数:2
点击次数:3
点击次数:4
点击次数:1
点击次数:2
点击次数:1
点击次数:2
点击次数:3
点击次数:4
点击次数:1
点击次数:2
上面的输出可以看到,当连续点击时,回调函数会在每次点击时被调用。并且点击次数会增加,
当间隔时间超过 mousetime
时,点击次数计数归零,
间隔时间可以查阅 :h mousetime
, 默认为 500 毫秒。