Vim の地味だけどよく使う設定

普段 Vim を使っていて、つくづく「このマッピング便利だな〜」と思うものをご紹介します。

空行・スペース処理

1行ごとに空行を入れる

このような設定で。
※以下、「<Leader>al」などのマッピングは説明用の一例です。

nnoremap <Leader>al  :%s/$/\r/gc<CR>
vnoremap <Leader>al  :s/$/\r/gc<CR>

f:id:note103:20160706002100g:plain

選択するとその範囲だけ、選択しなければバッファ全体を対象として、1行おきに空行を入れていきます。

空行をカットする

上記の逆。

nnoremap <Leader>dl  :%s/^$\n//gc<CR>
vnoremap <Leader>dl  :s/^$\n//gc<CR>

f:id:note103:20160706010907g:plain

複数行でも一気に詰めてくれます。

行内のスペースをカットする

nnoremap <Leader>db  :%s/\s\+//gc<CR>
vnoremap <Leader>db  :s/\s\+//gc<CR>

f:id:note103:20160706002336g:plain

まれに使います。

全角英数字を半角にする

普段はあまり遭遇しないものの、それだけにたまにぶつかると対応コスト・負担が大きい案件。

マッピングを設定しておいて数秒で解決するとストレスが最小限で収まります。

nnoremap <Leader>zh :HzjaConvert han_eisu
vnoremap <Leader>zh :HzjaConvert han_eisu

f:id:note103:20160706002409g:plain

これは選択範囲のみ有効なので(選択しなければカーソル行のみ)、バッファ全体に適用したい場合は全体を選択してから実行します。

f:id:note103:20160706002424g:plain

ちなみに、ほとんどやりませんが逆(半角→全角)も一応設定しています。

nnoremap <Leader>hz :HzjaConvert zen_eisu
vnoremap <Leader>hz :HzjaConvert zen_eisu

全角<=>半角の変換については以下が大変詳しい&わかりやすいです。
nanasi.jp

Markdown記法のリスト化

メモや議事録、週報など、Markdown記法でドキュメントを作成する機会が多いので、もしかすると現在一番使っているかもしれない地味設定。

直下の行頭にハイフン+半角スペースを入れる。

nnoremap <Leader>rh o<ESC>I- 

リスト行の直下に同じくハイフン+半角スペースを入れる。

nnoremap <Leader>ri A<CR>

1段深くインデントしてからハイフン+半角スペースを入れる。

nnoremap <Leader>rt A<CR><ESC>I<TAB><ESC>A 

f:id:note103:20160706002545g:plain

なお、Markdown まわりのサポート・プラグインとして以下を利用しているので、

上記はそれを前提としたマッピングです。

プラグインに関しては以下でも少し触れました。
note103.hateblo.jp

また、ぼくが主に使うファイル形式はじつは Markdown ファイル(.mdなど)よりもテキストファイル(.txt)なので、テキストファイルでも Markdown として振る舞うよう、「~/.vim/filetype.vim」の中に以下のような記述を入れています。

if exists("did_load_filetypes")
  finish
endif

augroup filetypedetect
  au BufRead,BufNewFile *.{md,mdown,mkd,mkdn,markdown,mdwn,txt,text,html}   set filetype=markdown
augroup END

この辺の設定については vimdoc の以下あたりが詳しそうです。

日時をすぐに出す

これも日報、週報的な記録を取る際に重宝しています。ほぼ毎日叩いているかも。

inoremap <expr> ,df strftime('%Y-%m-%d %H:%M')
inoremap <expr> ,dd strftime('%Y-%m-%d')
inoremap <expr> ,dt strftime('%H:%M')

曜日もすぐに出す

let weeks = [ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" ]
let wday = strftime("%w")
inoremap <expr> ,ds strftime('%Y-%m-%d ').weeks[wday]

f:id:note103:20160706002749g:plain

便利。曜日の部分以外は、以下のムックから学びました。

開発ツール徹底攻略 (WEB+DB PRESS plus)

開発ツール徹底攻略 (WEB+DB PRESS plus)

曜日の部分はいろいろ検索して作りました。先人に多謝。

.vimrc をすぐ操作する

上記のムックにも近いことが書かれていましたが、まず簡単に vimrc を操作できるよう、現在使っているウィンドウに vimrc を出すマッピング

nnoremap <silent> <Leader>. :<C-u>sp ~/.vimrc<CR>
nnoremap <silent> <Leader><Leader>. :<C-u>edit ~/.vimrc<CR>

Leader を1回叩いたら下方に画面分割で、2回叩いたらウィンドウ全体が vimrc ファイルになります。

そうしてチャチャッと書き換えたら、すぐに再読み込みできるように以下も設定。

nnoremap <Leader><C-e> :source ~/.vimrc<CR>

一時的なゴミ箱ファイルをすぐに出す

画面分割ワザの応用ですが、普段テキストの編集作業をしていると、「ん〜、この辺りの説明、冗長だからバッサリカットしてもいいんじゃないかな……でももしかしたらやっぱり必要かもしれないから、一旦別の場所に避難させておきたいな……」と思うことが少なくありません。

そのようなときに、一時的に不要な文章を保管しておけるファイルを作っておいて、それをいつでも呼び出せるようにする設定。

nnoremap <Leader><C-t> :<C-u>sp /path/to/trash.txt<CR>

ここでは「trash.txt」というファイル名にしていますが、それがウィンドウ下方にパッと出てくるので、その中に不要な文章をカット&ペーストで移動。(大抵は最下行)

f:id:note103:20160706183848g:plain

一方、こうした部分的な保存ではなく、バッファ全体をとりあえず保存しておきたい、という場合もあります。
そのようなときは、以下の方法を使います。

今見ているバッファを現在時刻のファイル名で保存する

:w 版

function! s:wsave()
  execute ":w /path/to/".strftime('%Y-%m-%d-%H-%M-%S').".txt"
endfunction
nnoremap <silent> <Leader><Leader>w :<C-u>call <SID>wsave()<CR>

:f 版

function! s:fsave()
  execute ":f /path/to/".strftime('%Y-%m-%d-%H-%M-%S').".txt"
endfunction
nnoremap <silent> <Leader><Leader>f :<C-u>call <SID>fsave()<CR>

あちこち調べて、関数で設定してみました。

なお、最近の Vim では undo オプションが大変強力で、ぼくも以下のように設定していますが、

if v:version >= 703
  set undofile
  set undodir=~/.vim/undo
endif

そして実際、これによってかなり以前の状態までさかのぼれますが、それでも時々期待の動作をしないこともあるので、「今見ているバッファ、万一のために別名で保存しておきたい……!」というときには上の保存コマンドをパパッと叩いておきます。

実際にはそのように保存したファイルを使うことはほぼありませんが、無用な心配事が減るので、実用上のメリットというより精神的なメリットがある設定です。

追記: 2016-12-30
この方法については、その後に改訂版を作成して以下で紹介しました。
Vimで今見ているバッファを「現在日時+好きなファイル名」で保存する - the code to rock

簡単に連番を振る

最後に、これは vimrc の設定ではありませんが、よく使うのでシェアさせて頂きます。
何気に使う場面が多い&むちゃくちゃ便利。

f:id:note103:20160706003059g:plain

情報源は以下の @thinca さんの回答より。
ja.stackoverflow.com

Vim 7.4.765 以降であれば、対象をビジュアルモードで選択して g<C-a> をすると連番が生成されます。

知らなかった〜……。

まだ他にもいろいろありそうな気はしますが、ひとまず以上です。