VimScriptで区切り文字までをサクサク削除できるやつ書いた

はい、タイトルの通りです。

普段、かなり使うコマンドの一つに以下のものがあります。


dfX- 文字Xまで削除 (Xを含む)
dtX- 文字Xの前まで削除 (Xを含まない)
cfX- 文字Xまで削除し、インサートモードへ (Xを含む)
ctX- 文字Xの前まで削除し、インサートモードへ (Xを含まない)

ランダムなアルファベットの時などは別によいのですが
コードを書いていてセミコロンの前まで消したい時、閉じ括弧の前まで消したい時などがあります。
そんな時に毎回毎回同じようなコマンドを打つのは面倒です。
"."は使いますがそれでもVimを開くたびに打ち直すのすら面倒_(:3」∠ )_

ということで、現在のカーソル位置から予め設定した、任意の区切り文字まで上記の4つのコマンドを実行出来るVimScript書きました。
VimScriptの練習にもなっていいことです(・∀・)。


" 区切り文字までを削除する
" @isInsert 削除後に挿入するか否か
" @isInclude 区切り文字を含むか否か
function! g:deleteDelimitChar(isInsert, isInclude)
    " 区切り文字リスト 優先順位はリストの並びごとに高→低
    let l:delimitList = [';', ':', ')', '}', ']', '.', '"', '''']

    let l:cursolPos = getpos('.')

    " 現在カーソルのある列、以降の文字列を取得(カーソル文字も含む)
    let l:afterCursolStr =  strpart(getline(line('.')), remove(l:cursolPos, 2) - 1)

    " 区切り文字のいずれかがあるか検出
    for l:i in l:delimitList

    " 区切り文字が存在すれば削除処理開始
        if(-1 != stridx(l:afterCursolStr, l:i))

            " 検出された区切り文字の前まで削除 引数で動作変化
            execute "normal d".['t', 'f'][a:isInclude].l:i

            " 削除後に入力するか否か
            if(1 == a:isInsert)
                startinsert
            endif

            " 削除したのでループを抜ける
            break
        endif
    endfor
endfunction

noremap dli :call g:deleteDelimitChar(0, 1)<CR>
noremap dla :call g:deleteDelimitChar(0, 0)<CR>
noremap cli :call g:deleteDelimitChar(1, 1)<CR>
noremap cla :call g:deleteDelimitChar(1, 0)<CR>

関数内初めのl:delimitListが区切りとして設定する値です。
任意の区切りを追加すれば動きます。

注意としては、要素初めにある区切りのほうが優先されます。
:call g:deleteDelimitChar(0, 0)<CR>とあった場合、:が先なので)まで削除されません。

マッピングは以下のようになります。

dli- 区切り文字まで削除 (区切り文字を含む)
dla- 区切り文字の前まで削除 (区切り文字を含まない)
cli- 区切り文字まで削除し、インサートモードへ (区切り文字を含む)
cla- 区切り文字の前まで削除し、インサートモードへ (区切り文字を含まない)

この記事を書いてて思いましたが、関数名がダメですね…

コメント

このブログの人気の投稿

カーソルキーさん@つかわない インサートモード編

Android で MIME Type 判別

Erlang & Elixir Fest 2019 に参加してきた