NeoVimのPluginを作ってみる①
とりあえずコマンドを呼んで、そこに入力したものを表示しながらeditができて、そのeditした情報をRust側で取得したい。
やりたいこととしては、vim-fugitiveでcommitをする時に指定してるeditorが立ち上がり、ファイルとしてどこかに保存するわけではないが保存した内容を取得はしたい。
とりあえずvim-fugitiveのコードを呼んでそれっぽいのを探してみる。
commitは :Gcommit
というコマンドで行っているのでそこから紐解いてみる。
特定のコマンドを探すときはまずは docs/*.txt
で検索をすると発見しやすそう。
vim-fugitiveの :Gcommit
は :Git
のwrapperっぽい。ちょっとここから追いかけるのしんどい気がしてきた
実際に :Gcommit
を使ってみて、開いたbufferを調べてみる。すると buftype
という設定があるっぽい。
これも頭に入れておきながら調べていたら以下の記事をみつけた。結構今回やりたいことにあってる気がする
大事なのはここら辺っぽい
function! testplugin#open_buffer() abort
split hoge
call append(0, 'hoge')
call deletebufline('%', '$')
setlocal buftype=nofile
setlocal bufhidden=hide
setlocal noswapfile nobuflisted
endfunction
これを読むと良さそう
何かを閲覧するだけとか、特定のキーを押したときにだけ反応させるとかであれば
nnoremap <silent> <buffer> call ...
で <CR>
にひっかけて getline('.')
すればいい感じに出来るので buftype=nofile
とかでひらけば良さそう。
上のやつ試したけど、書き込めないなと思って :Git
を見直したけど、gitは .git/COMMIT_EDITMSG
というファイルでやりとりしてるっぽいな...
plugin配下に適当にファイルを作って、それを操作してあとで消すみたいな方針が無難か...??
いったんそうの方針にしてみようか...
- fileを作る
-
split filename
でそのfileを開く - 編集する
- 保存したらそのfileの中身を読み込む
- stdoutに吐く
- fileを削除する
でやってみるか👀
4が激ムズな気がする...
bufferを開くまではいいが開いたbufferを保存したかどうかってどうやったらわかるんだ...?
うーん、どうやらvirtual bufferというのがあるっぽい?👀
autocmdで BufWriteCmd
をひっかけてコールするといけるっぽい。
ただautocmdを書くときにこれで指定をしないとうお〜〜〜って感じになりそう。
function! s:read(args)
augroup vimrpcsample-new-buffer
autocmd!
autocmd BufWriteCmd new-buffer call s:on_save()
augroup END
new
call setline(1, a:args)
file new-buffer
set nomodified
setlocal buftype=acwrite
setlocal filetype=md
setlocal noswapfile
endfunction
function! s:on_save()
let lines = getline(0, line("$"))
" bw new-buffer
echo lines
" call rpcnotify(s:vimrpcsampleJobId, "save", lines)
endfunction
こんな感じで、とりあえず :call s:read('hoge')
実行すると hoge
って文字列が入った状態で画面上に新しいbufferが生まれる。んで、 :w
や :wq
をするとその情報が取得できる。が、bufferを削除出来ていない。
bw new-buffer
を実行すれば消せるんだけど、 :wq
をしてた場合は元々開いてたbufferも抜けてしまう
こういうのはfilterを作ってる人は rename
とかの機能でやってると思うからvaffleのコードを眺めてる。
多分ここら辺なんだよな...
function! s:read(args)
augroup vimrpcsample-new-buffer
autocmd!
autocmd BufWriteCmd new-buffer call s:on_save()
augroup END
let s:parent_bufnr = bufnr('%')
new
call setline(1, a:args)
file new-buffer
set nomodified
setlocal buftype=acwrite
setlocal filetype=md
setlocal noswapfile
endfunction
function! s:find_buf(bufnr) abort
if !exists('*win_findbuf')
" win_findbuf() is available since patch 7.4.1558
return []
endif
return win_findbuf(a:bufnr)
endfunction
function! s:get_winid() abort
if !exists('*win_getid')
" win_getid() is available since patch 7.4.1557
return 0
endif
return win_getid()
endfunction
function! s:gotoid(expr) abort
if !exists('*win_gotoid')
" win_gotoid() is available since patch 7.4.1557
return 0
endif
return win_gotoid(a:expr)
endfunction
function! s:on_save()
let lines = getline(1, line("$"))
set nomodified
echo lines
let win_ids = s:find_buf(s:parent_bufnr)
if empty(win_ids)
return
endif
let win_id = s:get_winid()
if s:gotoid(win_ids[0])
call s:gotoid(win_id)
endif
" call rpcnotify(s:vimrpcsampleJobId, 'save', lines)
endfunction
こんな感じでいけた