vimの検索機能の拡張~ファイルを超えて検索~

田中太郎
田中太郎

vimの検索機能を拡張するスクリプトを作成します。

完成イメージ

vimで検索するとき、ファイルをまたいで検索したくなることはないでしょうか。

例えば、File1で使う関数をFile2で定義しているとき、

中身がどうなっているか見たくなることありませんか?

今回は、そんな機能をvimスクリプトで作成していきます。

vimの検索機能

vimはノーマルモードで/(スラッシュ)を入力すると、検索機能が作動します。

そして、/(スラッシュ)の後に文字を続けてEnterを押すとその文字の位置までジャンプします。

そしてnを押すと次の位置までジャンプし、Nで前の位置までジャンプします。

ここで、複数のファイルで関数を定義、参照するようなプログラムを書いているとき、vimのバッファを使い、複数ファイルを開くことがあると思います。

そのとき、定義した関数、変数がどこで参照されているか、検索できれば非常に便利です。

vimの検索機能はそのファイルに閉じているため、nで次の文字にジャンプし、最終行まで達すると、ファイルの先頭にもどってしまいます。

そこで、検索機能を拡張し、ファイルの最終行に達したら別なバッファに自動で移動するコマンドを作成しました。

vimの検索機能を拡張する

n, N の拡張。拡張といっても、別なキーに割り当てています。

【通常】

「n」:次の文字に移動。最終行に達したらファイルの先頭に戻る。

「N」:前の文字に移動。ファイルの先頭に達したら最終行に戻る。

【拡張後】

「;」:次の文字に移動。最終行に達したら次のバッファに移動する。

「+」:前の文字に移動。ファイルの先頭に達したら前のバッファに移動する。

コード

下記のコードをvimrcに追加します。

function! New_next() abort
    let s:now_line_num = line(".")
    let s:now_column_num = col(".")
    try
        normal n
    catch
        :
    endtry

    if s:now_line_num > line(".") || s:now_line_num == line(".") && s:now_column_num == col(".")
        :bnext
        normal G
        normal $
        try
            normal n
        catch
            :
        endtry
    endif
endfunction

function! New_prev() abort
    let s:now_line_num = line(".")
    let s:now_column_num = col(".")
    try
        normal N
    catch
        :
    endtry

    if s:now_line_num < line(".") || s:now_line_num == line(".") && s:now_column_num == col(".")
        :bnext
        normal gg
        try
            normal N
        catch
            :
        endtry
    endif
endfunction

command Newnext :call New_next()
command Newprev :call New_prev()
nnoremap ; :Newnext<CR>
nnoremap + :Newprev<CR>

解説

function! New_next() abort

「n」を拡張する関数です。

function!の「!」で同じ名前の関数があったときに上書きされます。

abortを付けると、関数内でErrorが起きるとそこで処理が中断されます。

    let s:now_line_num = line(".")
    let s:now_column_num = col(".")

現在の位置(何行、何列)を取得します。

line(“.”)でカーソルがある位置の行数、col(“.”)で列数が取得できます。

それをlet s:<変数名>に格納しています。

    try
        normal n
    catch
        :
    endtry

try文で「n」で検索して、マッチする文字があればジャンプし、なければ何もしません。

normal <コマンド> で、ノーマルモードで使うコマンドを実行できます。

    if s:now_line_num > line(".") || s:now_line_num == line(".") && s:now_column_num == col(".")
        :bnext
        normal G
        normal $
        try
            normal n
        catch
            :
        endtry
    endif

位置が変わらない もしくは先ほど取得した位置よりも上(ファイルの下まで検索して先頭にもどったとき)であるとき、次のバッファに移動します。

:bnextは次のバッファに移動するExコマンドです。

ここで、バッファを移動してすぐ「n」を使うと、ファイルの先頭にマッチする文字があるとき、その文字を飛ばしてしまうので

norml G, normal $でファイルの末尾に移動してから「n」を使います。

function! New_prev() abort ではこれと逆のことをしています。

command Newnext :call New_next()
command Newprev :call New_prev()
nnoremap ; :Newnext<CR>
nnoremap + :Newprev<CR>

作成した関数を「;」、「+」に割り当てています。

まとめ

今回は、vimのn/Nを拡張する関数を作成しました。

内容はシンプルなので、簡単に理解していただけると思います。

タイトルとURLをコピーしました