🌴
pythonのコードブロックの始点終点に移動するVimプラグインを作った
はじめに
画面に収まらない長大なコードブロックを持ったりif文やfor文で多重にネストされてインデントが深くなったりするpythonコード[1]では現在のインデントに注意を払う労力が増えると思います。
内部の処理を関数で切り出すなどしてその労力を軽減するアプローチもあるかと思いますがコードを読む際などそれが実現出来ない場合もあると思います。
VimではC言語の{}などに対して対になる括弧に移動するコマンド%
が提供されていますが、このようなコマンドがpythonのコードでも使えれば役立つのではと思い、現在のコードブロックの始点や終点に移動するVimプラグインを作りました。 本記事ではそのVim プラグインの使い方、処理を紹介します。
リポジトリはこちらです。
使い方
インストール
vim-plugを使っていれば.vimrc
に以下の行を加えてPlugInstall
すればコマンドが使えるようになります。
Plug 'kawagh/jumpblock.vim'
コマンド
:JumpBlock
:RjumpBlock
:JumpBlock
でコードブロック終点に移動、:RjumpBlock
で始点に移動します。
処理
始点の捉え方
- pythonのコードブロックを形成する合図は文末のコロン(:)なのでここを始点に捉えます(
{}
での{
に相当)。
終点の捉え方
- インデントが同一以下になる行が見つかるまで下の行を見るループをします。インデントが同一以下の行が見つかったらそこではコードブロックが終了しているとみなせるのでその前の行にジャンプします。
- この時に空行の存在に注意が必要です。終端ではないがインデントが同一以下になる行なので終端と認識されてしまうので空行をスキップしてループをすると良いです(Vim Scriptでは
nextnonblank()
など次の非空行の番号を返す関数が提供されていて便利でした)。
- この時に空行の存在に注意が必要です。終端ではないがインデントが同一以下になる行なので終端と認識されてしまうので空行をスキップしてループをすると良いです(Vim Scriptでは
実装
- 上で説明したような捉え方で始点終点を捉えてカーソル移動を実装したコードが以下のようになります。
- jumpblock.vim/jumpblock.vim at master · kawagh/jumpblock.vim · GitHub
function! s:jump_block_f()
let cline = getline(".")
let lastchar = cline[strlen(cline)-1]
if lastchar == ":"
let lnum = line(".")
let start_indent = indent(line("."))
while indent((lnum+1)->nextnonblank()) > start_indent
let lnum = (lnum+1)->nextnonblank()
endwhile
:call cursor((lnum)->prevnonblank(),1000)
endif
endfunction
function! s:rev_jump_block_f()
if indent(".") != 0
let cline = getline(".")
let lastchar = cline[strlen(cline)-1]
let lnum = line(".")
let start_indent = indent(line("."))
while indent((lnum-1)->prevnonblank()) >= start_indent
let lnum = (lnum-1)->prevnonblank()
endwhile
:call cursor((lnum-1)->prevnonblank(),1000)
endif
endfunction
-
個人的にindent jungleと呼んでいます ↩︎
Discussion