表示している範囲の行だけ欲しい
Vimで画面に表示している範囲の内容だけ欲しいので、表示している行番号のリストがとれればなーとか思ったのですが、なかなかスマートな取得方法に辿り着かなかったので、共有も兼ねて記しておきます。
何が問題か
echo getline('w0','w$')
上記のようなw0
、w$
という便利な記法があるのですが、w0
、w$
を指定することで、表示されている一番上の行番号と下の行番号を指定することができるのです。
ですが、これで表示している範囲だけ取れると思って使っていると、折りたたみ(fold)があると不都合が起きます。
下記のような折りたたみがあるファイルでの結果は
" vim: foldmethod=marker
aaaa
" {{{
bbbb
" }}}
cccc
(↓↓↓結果のスクショ。最下行がecho getline('w0', 'w$')
の結果)
['" vim: foldmethod=marker','','aaaa','','" {{{','','bbbb','','" }}}','','cccc']
foldで非表示になっている内容も取れてしまうんですよね。これだと、折りたたみの行数が大きいほど無駄に内容取得されてしまって困っちゃいます。
(私はここで、getline('w1')
、getline('w2')
...と1行ずつ順番にアクセスしていけば、表示している内容だけ取れるのではと思ったのですが、w0
が特別なだけで、w1、w2...なんてものは無いんですよね...うーむ。)
解決方法
ループしつつfoldclosed()
、foldclosedend()
を使って非表示行をスキップします。foldclosed()
は、もし引数の行番号が畳まれていた場合はfoldの開始行番号を返し、foldclosedend()
は引数の行番号が畳まれている場合はfoldの終了行番号を返します。
ドキュメントはこちら
https://vim-jp.org/vimdoc-ja/eval.html#foldclosed()
サンプルを書いてみました。
行番号だけ欲しければ、l:current_line
をよしなに使ってください。
function! EchoDisplayedAll()letl:lines =[]letl:current_line = line("w0")letl:end_line = line("w$")while1if foldclosed(l:current_line)>0letl:current_line = foldclosedend(l:current_line)+1endififl:current_line >l:end_line
breakendifcall add(l:lines, getline(l:current_line))letl:current_line =l:current_line +1endwhile
echo l:lines
endfunction
先程のテキストでの結果は以下の通り。
(↓↓↓call EchoDisplayedAll()
の結果)
['" vim: foldmethod=marker','','aaaa','','','cccc']
これでVim scriptで表示されている範囲だけ取得することができました💪