Neovim: winbar 上のクリックに反応させる
Neovim v0.8 で入っていたという winbar の存在を今更認識し、これを使えば最近課題感を感じていた terminal buffer の切り替えを自分好みにできそうだったので使ってみました。
動作確認は Neovim v0.11.3 で行いました。
winbar とは
window bar の略で各 window の上部に表示される部分のこと。
winbar 変数に何かしらの値が設定されると表示されます。
たとえば以下のようにすると現在開いているファイルのパスが winbar に表示されます
lua vim.o.winbar = '%f'
クリックに反応させる
表示させた部分はクリックに反応させることができます。
以下のように書くと winbar に [Hello]
と表示され、その部分をクリックすると現在開いている buffer に文字が挿入されます
function _G.my_winbar_click_handler(id, clicks, button, mods)
local comment = ("-- id: %s, num clicks %d, (button: %s), mods %s"):format(id, clicks, button, mods)
vim.api.nvim_buf_set_lines(0, -1, -1, false, { comment })
end
vim.o.winbar = "%123@v:lua.my_winbar_click_handler@[Hello]%T"
%{int}@v:lua.some_function@{display string}%T
の形式で書くと、{display string}
がクリックされたときに some_function
が呼び出されます。
関数は4つの引数を取り、第1引数には {int}
で指定した整数値が渡されます。第2引数にはクリック数、第3引数にはクリックされたボタンの種類 (l
, r
, m
の3種。それぞれ左クリック、右クリック、中クリック)、第4引数には修飾キー(ctrl, alt, etc)の名前が渡されます。
%T
はクリック可能領域の終端を表します。%T
の代わりに %X
も使うことができます。
tabbar 等では %X
と %T
で違いがあるようですが、winbar においては今のところ差はないように思います。
ref
- https://github.com/neovim/neovim/blob/v0.11.3/runtime/doc/options.txt#L6072-L6097
- https://github.com/neovim/neovim/blob/v0.11.3/runtime/doc/options.txt#L6310-L6313
buffer の切り替え
もう少し実用的な例として以下では buffer の切り替えを行えるようにしています。
クリックされたら buffer number が関数に渡るようにして vim.api.nvim_set_current_buf
で buffer の切り替えを行っています。
local bufnrs = {}
for i = 1, 5 do
local bufnr = vim.api.nvim_create_buf(false, true)
table.insert(bufnrs, bufnr)
vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, { 'Buffer ' .. bufnr })
end
local winid = vim.api.nvim_open_win(bufnrs[1], true, {
split = 'below',
height = math.floor(vim.o.lines * 0.4),
style = 'minimal',
})
local function set_winbar(winid, bufnrs)
local winbar_text_format = '%%%d@v:lua.my_winbar_click_handler@[Buffer %d]%%T'
local winbar_text = ''
for i, bufnr in ipairs(bufnrs) do
winbar_text = winbar_text .. string.format(winbar_text_format, bufnr, bufnr)
if i < #bufnrs then
winbar_text = winbar_text .. ' | '
end
end
vim.api.nvim_set_option_value('winbar', winbar_text, {
win = winid,
})
end
function _G.my_winbar_click_handler(minwid, clicks, button, mods)
vim.api.nvim_set_current_buf(minwid)
set_winbar(winid, bufnrs)
end
set_winbar(winid, bufnrs)
上記の例は普通の buffer ですが、私はこれを toggleterm で作られた terminal buffer の切り替えに使用しています。素の toggleterm でも HEAD では winbar 対応されていますがクリックすると新しい window で開きます。一方、私の使い方としては window そのままで buffer の切り替えを行いたかったため、toggleterm の custom terminal を使いつつ winbar で切り替えが行えるようにしました。
https://github.com/goropikari/tabterm.nvim
上記のように特定の条件を満たす buffer を winbar に表示して切替可能にするといった用途には結構便利だと思いました。
Discussion