熟悉 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
)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 毫秒。
最近,我在 Reddit 上面分享了一个新的代码格式化的插件 format.nvim, 回复大多是是在问为什么要做这个插件以及跟现有插件的区别。
在 SpaceVim v2.3.0 之前,一直使用的代码格式化插件是 neoformat, 这个插件是使用 Vim 脚本写的,同时支持 Neovim 和 Vim。
但是美中不足的地方是这个插件执行格式化命令是调用 Vim 的 system()
函数,当命令执行消耗时间很长时,就会卡住界面无法进行下一步操作。
我也尝试过给 neoformat 增加异步支持,但是考虑到其他几个原因,还是决定重新写一个插件。
其实 neoformat 的插件代码实现逻辑还是非常好的,因此我也是参考了 neoformat 的实现逻辑, 使用 Lua 来实现了这个异步代码格式化的插件 format.nvim。 这个插件使用了 SpaceVim 的 job api 可以异步执行格式化命令,使得 Neovim 的操作更加顺畅。
对于 SpaceVim 用户来说,只需要在启用 format 模块的时候,指定格式化方法为 format.nvim 即可,配置如下:
[[layers]]
name = 'format'
format_method = 'format.nvim'
虽然 format.nvim 是基于 SpaceVim 的 Job API 实现的,但是该插件已经包含的改 API 的必须文件, 因此可以任意插件管理器独立安装,例如使用 vim-plug:
Plug 'wsdjeg/format.nvim'
以 Lua 语言为例,设置使用 stylua 命令进行格式化:
require('format').setup({
custom_formatters = {
lua = {
exe = 'stylua',
args = { '-' },
stdin = true,
},
},
})
1、格式化整个 Buffer
format.nvim 只提供了一个命令 :Fromat
, 执行该命令时就可以根据当前文件的文件类型选择对应的 formatter 对整个 Buffer 进行格式化。
2、选中区域进行格式化
:Format
命令支持指定区域进行格式化,因此可以在 Neovim 中选中几行代码进行格式化。
3、指定文件类型
通常执行 :Format
命令时,会读取当前 Buffer 的 &filetype 选项,但是如果需要指定其他文件类型,比如 java,可以使用如下格式执行命令:
:Format! java
4、指定 formatter
如果一个文件类型有多个 formatters,可以在执行改命令时指定一个 formatter 的名字,比如 :Format prettier
前面提到 :Format
命令支持指定区域格式,这里需要借助一个插件 context_filetype.vim。
通过这个插件获取到代码块的区域和文件类型,传给 Format 命令。
以下示例使用 <Leader>f
格式化光标所在的代码块:
function! s:format_code_block() abort
let cf = context_filetype#get()
if cf.filetype !=# 'markdown'
let command = printf('%s,%sFormat! %s', cf.range[0][0], cf.range[1][0], cf.filetype)
exe command
endif
endfunction
nnoremap <silent> <Leader>f <cmd><sid>format_code_block()<cr>
前段时间整理自己的个人维基发现笔记太零散,很难快速定位到自己需要的笔记。 以往借助自己的 flygrep 插件根据记忆的关键字倒是可以找到相关的内容, 但是随着笔记越来越多,关键字筛选已经不足以快速定位了。 于是就想找一个更好的方式来组织管理日常的笔记,后来就了解到了《卢曼卡片盒笔记法》
最开始,我是想找一个三端(手机、电脑、网页)同步的笔记软件,但是似乎没有合适的。因为都是文本编辑,而且如果要使用卡片盒笔记法的话, 那么笔记就需要遵循一定的格式。日常使用 Neovim 也非常多,几乎文本的编辑都是在 Neovim 内完成的,索性就不再舍近求远去找笔记软件了, 就直接在 Neovim 内完成。检索了下 Github 发现还是有不少现成的插件实现,但是功能似乎都不是很完善。
因此自己 Fork 了一个插件,在这个插件的基础上做了一些功能的改进和增加,有兴趣的话欢迎尝试:vim-zettelkasten。
浏览笔记列表时,展示笔记的引用数量以及被引用数量,同时列出笔记包含的 Tags 列表,如下图所示:
同时,在 ZkBrowser 窗口内支持的快捷键包括:
快捷键 | 功能描述 |
---|---|
q |
退出 ZkBrowser 窗口 |
<LeftRelease> |
鼠标左键点击 Tag,筛选包含该 Tag 的笔记 |
gf |
打开光标 ID 下的笔记 |
Ctrl-l |
清除 Tags 筛选,列出所有笔记 |
Ctrl-] |
使用 preview-window 窗口预览笔记 |
[I |
使用 quickfix-window 列出 References |
F2 |
打开 Tags 列表侧栏 |
侧栏的效果图如下,可以在侧栏窗口中使用回车键或者鼠标左键点击 Tag 实现筛选:
侧栏中,标签按照首字母归类,鼠标左键点击归类的字母,可以折叠这些标签。
当笔记 Tags 非常多的时候,可以使用 telescope.nvim 进行检索,检索后默认的回车键行为是列出包含该 Tag 的所有笔记。
默认的快捷键为 SPC m z g
。
笔记的标题(Title)也可以使用 telescope.nvim 进行检索,默认的快捷键是 SPC m z f
。
在编辑笔记过程中,可以使用快捷键 ctrl-x ctrl-u
来打开补全窗口,补全引用的笔记 ID。
如果是使用 SpaceVim,可以通过 zettelkasten 模块选项设置笔记模板的文件夹,新建一些常用的笔记模板,比如:
[[layers]]
name = 'zettelkasten'
zettel_dir = 'D:\me\zettelkasten'
zettel_template_dir = 'D:\me\zettelkasten_template'
通常基于默认新建笔记直接使用 SPC m z n
快捷键即可,如果需要基于其他模板来新建,可以使用快捷键 SPC m z t
调用 Telescope 检索常用模板。
因为 SpaceVim 默认是兼容 Neovim 和 Vim 的,因此后面是有计划让这个插件也支持 Vim 的,但是为了减少重复实现的一些代码,可能是需要 Vim 有 +lua
特性。
新的工作环境感觉不是想象中那么理想,但是也在努力去适应。 最近感觉也比较压抑,本来周末想去看的一部电影,因为一些事情耽搁了,今晚抽空一个人去电影院看了。
正如电影的名字一样,即便是生活很多时候不是很如意,但是有些人还是很善于发现身边的一些“好东西”。
可能是因为自己工作的原因,很多时候太过追求结果,而忽略了过程中一些美好的事情。
曾今的我一直固执的认为谎言就是谎言,没有善恶之分,因为总有方式更好地呈现事实。 但很多时候,一些善意的谎言其实可以让事情变得更加简单。
其实,说实在的,电影不是特别的好看,很多情节、对话太过于刻意。 就感觉正常的两个人对话,不该是这样,很多时候刻意的制造一些“鸡汤”类的说教, 或者刻意的制造一些搞笑的对话。
但是,其中确实有很多“鸡汤”值得去好好想想,比如:
1、小女孩上台表演前的那段对话,有时候因为害怕别人的眼光、说辞、看法, 而退缩,其实,这个社会上,在意你的人,真的没有你想象的那么多。 可能明天,他就会忘记你所做的事。
2、又比如小孩的作文,我最喜欢的、以及出现了两次的跟幻想相关的话题。 我觉得小孩子还没有这样的思想,更多的是电影呈现给观众的一些观点。 是的,即便是现在,后面的生活,还有很多年,你永远不会知道自己最喜欢的将会是什么,还是要保留一些幻想。
周末跟家人们去看了一部电影,小朋友们选了柯南,我就去看了张家辉主演的《重生》。
剧中角色:
安渡(阮经天 饰)
安渡缉毒组小队长,被其舅舅安佩长期长期压抑不得势再加上自幼经历悲惨,造成了阴暗的性格,被权力、金钱迷失倒也正常。 人性这种东西其实很奇怪,不能去深究其好坏。
张耀(张家辉 饰)
张耀的剧情也算还能理解,想要在监狱里替换掉沙旺,并且通过各种检查,没有安渡他们的安排跟支持几乎不可能。
巴莱(马浴柯 饰)
完全没有想到的是南茜和巴莱也是也是提前安排好的碟中谍角色。
前不久,删除了用了很久的 Telegram 账号 @wsdjeg
。
为了避免非本人使用该用户名带来不必要的麻烦,原来的用户名转移给了一个无管理员的公共的 Channel。
个人是非常抵触使用手机号注册和登录的软件,因为手机号实际上运营商是可以二次销售的。 大学期间至今,前面大概有三个手机号已经停机不用了,但是现在搜了下,居然有别人已经用它来注册了微信。
此外,如果提供足够的材料或者“特殊情况”下,运营商可以重新制作一张 SIM 卡,原 SIM 会废弃。 那么新卡就可以接受验证信息,这就意味着,对于账号的所有权,你没有绝对的控制权。