ハイパーマッスルエンジニア

Vim、ShellScriptについてよく書く

Neovim: 矩形選択したものを好きな場所に貼り付けるプラグイン nvim-block-paste

ブロックエディタっぽく、どこでも好きなところに貼り付けしたかった

github.com

矩形選択したものをどこにでも貼り付けられる

使い方

インストール

[[plugins]]
repo = 'Rasukarusan/nvim-block-paste'

矩形選択した状態で:Blockを実行。

:'<,'>Block
キー操作 説明
h ブロックを左に移動
j ブロックを下に移動
k ブロックを上に移動
l ブロックを右に移動
p ブロックを貼りつける
u 元に戻す

実装

hjklでフローティングウィンドウを移動

フローティングウィンドウ作成でnvim_open_win(buf, v:true, config)の第2引数をv:trueにしておけば作成後そのままフローティングウィンドウにフォーカスが当てられるので、続けてnnoremap ...とキーバインド設定処理を書いていけば設定できます。

また、<buffer>をつけることで、現在のbuffer=作成したフローティングウィンドウ、にのみキーバインドを設定できます。

" フローティングウィンドウ作成
let config = {'relative': 'editor', 'row': row, 'col': col, 'width':width, 'height': height, 'anchor': 'NW', 'style': 'minimal'}
let buf = nvim_create_buf(v:false, v:true)
let win_id = nvim_open_win(buf, v:true, config)

" 作成したウィンドウにキーバインドを設定
nnoremap <buffer><nowait><silent> j :call <SID>move_y(1)<CR>
nnoremap <buffer><nowait><silent> k :call <SID>move_y(-1)<CR>
nnoremap <buffer><nowait><silent> l :call <SID>move_x(1)<CR>
nnoremap <buffer><nowait><silent> h :call <SID>move_x(-1)<CR>

選択した部分を切り取ったようにみせる

vim-block-pasteでは、選択した範囲をpで貼り付けるまではuで選択をなかったことにできます。
そのため貼り付けるまでは現在のバッファをいじりたくなかったので、背景と同じ色のフローティングウィンドウを1枚作成して被せることで、さも切り取ったように見せています。

" 選択範囲にFloatingWindowを作成
let s:width = abs(end.x - start.x) + 1
let s:height = abs(end.y - start.y) + 1
let row = start.y - 1
let col = start.x - 1
let config = {'relative': 'editor', 'row': row, 'col': col, 'width':s:width, 'height': s:height, 'anchor': 'NW', 'style': 'minimal'}
" 切り取ったように見せるため、背景と同じ色でウィンドウを作成
let s:back_win_id = s:create_window(config, 'Normal:NonText')
let s:block_win_id = s:create_window(config, 'Normal:Visual')

貼り付けた後の文字列の削除処理は「スペースで埋める」もしくは「完全に切り取る」かをlet g:block_paste_fill_blank = 1 or 0で制御しています。

function! s:put()
  "...略

  " 選択範囲の文字列、FloatingWindowを削除
  if get(g:, 'block_paste_fill_blank', 0)
    " 切り取る
    silent normal gvd
  else
    " スペースで埋める
    :silent '<,'>s/\%V./ /g
  endif
  call s:close_window()
endfunction

画面横幅を取得する

行番号表示列とサイン列の幅を考慮した画面幅を取得するAPIは用意されていないっぽいので、自前で計算する必要がある。

画像は下記から拝借

ここを参考にさせていただきました。 stackoverflow.com

終わり

Notionのブロックエディタの操作感が気持ちよくて、Vimでもできないかと試行錯誤してたらこうなった。
フローティングウィンドウはビジュアル的に派手になるからとっても好き。まだまだ色々遊べそう。