tl;dr 2021/03/26追記
コメントでautocmdを教えてもらったので書き直した簡潔なvimrcがこちら.
augroup vimrc
autocmd!
au BufWritePost ~/.vimrc so ~/.vimrc
au InsertLeave,BufLeave,TextChanged * :w
augroup END
これを追加すればもう:w<CR>を押す必要はないだろう.
以下の記事はautocmdを知らない状態で"超"強引にオートセーブを実現した記事である.
ギャグとして読んでほしい.
:w<CR>
Vimにおいて, セーブを行うときは3回キーを押す必要がある.
:w\<CR>
頻繁にセーブしないならば, これを多いとは思わないだろう.
<C-s>に1度キーを押す回数を増やすだけだからだ.
残念ながら, 自分は高頻度でセーブをしたくなるタイプだ. 毎回:w<CR>を押すのは面倒だった.
あなたもこの手の人間で, かつ.vimrcをいじくり回していないのであれば, きっとこの記事は役に立つだろう.
WHEN SHOULD YOU SAVE FILE ?
A.何らかの変更が起きたときに都度セーブしたい.
それでは変更が起きうるタイミングは?多くの場合は以下だろう.
- 挿入モードから通常モードに戻るとき: ifoo<ESC>, A;<C-[>, ...
- ペースト時: yyp, yyP, ...
- 1行削除時: dd, D
- 1文字削除時: x
- インクリメント&デクリメント: <C-a>, <C-x>
- ドット繰り返し: .
- 1文字変更時: r
- モーションやヴィジュアルを用いた削除: diw, daw, di), d3w, dt(, Vjjd, ...
- コマンド実行時: :%s/foo_bar/fooBar/g, :.,.+21 normal A;, ...
これらのうち, rによる変更, モーションやヴィジュアルを用いた削除とコマンド実行による変更は, その都度押すキーが異なり, vimrcでオートセーブを行うのは難しい.
しかし, 上6つは非常に簡単な設定でオートセーブを実現可能である.
EDIT VIMRC
具体的なvimrcを示す前に, キーバインドの変更を行うためのコマンドについてのTipsを知っておいてほしい.
vimrcの設定コマンドであるinoremapやnnoremapはそれぞれ挿入モードでのキーバインド変更と通常モードでのキーバインド変更である.
もしかしたらあなたは,
inoremap <silent>jj <ESC>
nnoremap H Hzz
などのコマンドを見たことがあるかもしれない.
これは, jjを二度続けて押す=を押す, Hを押す=Hzzを一息に押すを意味する.
このTipsの要点は, mapコマンドは第一引数は<silent>を用いて複数のキー入力を表現できること, 第二引数はデフォルトで複数のキーを表現できることである.
準備は完了した. これらのコマンドを用いて簡易的なオートセーブを可能とするvimrcを見てみよう.
ADD IT TO .vimrc
" autosave
inoremap <ESC> <ESC>:w<CR>
inoremap <C-[> <C-[>:w<CR>
nnoremap p p:w<CR>
nnoremap P P:w<CR>
nnoremap <silent>dd dd:w<CR>
nnoremap D D:w<CR>
nnoremap x x:w<CR>
nnoremap <C-a> <C-a>:w<CR>
nnoremap <C-x> <C-x>:w<CR>
nnoremap . .:w<CR>
これらの設定が意味するところは, あえて書くまでもないだろう.
あなたがjjの信奉者であるなら,
inoremap <silent>jj <ESC>:w<CR>
と書けば良い.
IF YOU WANT
上記のコマンドで実用的なオートセーブを行えるが, もしあなたが自分のvimrcを叙事詩のごとく長く書くことに抵抗がないならば, 以下をvimrcに追加しよう.
dによるモーションの多くを網羅している. これを追加すると:w<CR>を打つ頻度は大きく減るだろう.
dモーションの設定
" d mortions
nnoremap <silent>diw diw:w<CR>
nnoremap <silent>di) di):w<CR>
nnoremap <silent>di} di}:w<CR>
nnoremap <silent>di] di]:w<CR>
nnoremap <silent>di> di>:w<CR>
nnoremap <silent>di' di':w<CR>
nnoremap <silent>di" di":w<CR>
nnoremap <silent>daw daw:w<CR>
nnoremap <silent>da) da):w<CR>
nnoremap <silent>da} da}:w<CR>
nnoremap <silent>da] da]:w<CR>
nnoremap <silent>da> da>:w<CR>
nnoremap <silent>da' da':w<CR>
nnoremap <silent>da" da":w<CR>
# df mortions
nnoremap <silent>df1 df1:w<CR>
nnoremap <silent>df2 df2:w<CR>
nnoremap <silent>df3 df3:w<CR>
nnoremap <silent>df4 df4:w<CR>
nnoremap <silent>df5 df5:w<CR>
nnoremap <silent>df6 df6:w<CR>
nnoremap <silent>df7 df7:w<CR>
nnoremap <silent>df8 df8:w<CR>
nnoremap <silent>df9 df9:w<CR>
nnoremap <silent>df0 df0:w<CR>
nnoremap <silent>dfa dfa:w<CR>
nnoremap <silent>dfb dfb:w<CR>
nnoremap <silent>dfc dfc:w<CR>
nnoremap <silent>dfd dfd:w<CR>
nnoremap <silent>dfe dfe:w<CR>
nnoremap <silent>dff dff:w<CR>
nnoremap <silent>dfg dfg:w<CR>
nnoremap <silent>dfh dfh:w<CR>
nnoremap <silent>dfi dfi:w<CR>
nnoremap <silent>dfj dfj:w<CR>
nnoremap <silent>dfk dfk:w<CR>
nnoremap <silent>dfl dfl:w<CR>
nnoremap <silent>dfm dfm:w<CR>
nnoremap <silent>dfn dfn:w<CR>
nnoremap <silent>dfo dfo:w<CR>
nnoremap <silent>dfp dfp:w<CR>
nnoremap <silent>dfq dfq:w<CR>
nnoremap <silent>dfr dfr:w<CR>
nnoremap <silent>dfs dfs:w<CR>
nnoremap <silent>dft dft:w<CR>
nnoremap <silent>dfu dfu:w<CR>
nnoremap <silent>dfv dfv:w<CR>
nnoremap <silent>dfw dfw:w<CR>
nnoremap <silent>dfx dfx:w<CR>
nnoremap <silent>dfy dfy:w<CR>
nnoremap <silent>dfz dfz:w<CR>
nnoremap <silent>dfA dfA:w<cr>
nnoremap <silent>dfB dfB:w<cr>
nnoremap <silent>dfC dfC:w<CR>
nnoremap <silent>dfD dfD:w<CR>
nnoremap <silent>dfE dfE:w<CR>
nnoremap <silent>dfF dfF:w<CR>
nnoremap <silent>dfG dfG:w<CR>
nnoremap <silent>dfH dfH:w<CR>
nnoremap <silent>dfI dfI:w<CR>
nnoremap <silent>dfJ dfJ:w<CR>
nnoremap <silent>dfK dfK:w<CR>
nnoremap <silent>dfL dfL:w<CR>
nnoremap <silent>dfM dfM:w<CR>
nnoremap <silent>dfN dfN:w<CR>
nnoremap <silent>dfO dfO:w<CR>
nnoremap <silent>dfP dfP:w<CR>
nnoremap <silent>dfQ dfQ:w<CR>
nnoremap <silent>dfR dfR:w<CR>
nnoremap <silent>dfS dfS:w<CR>
nnoremap <silent>dfT dfT:w<CR>
nnoremap <silent>dfU dfU:w<CR>
nnoremap <silent>dfV dfV:w<CR>
nnoremap <silent>dfW dfW:w<CR>
nnoremap <silent>dfX dfX:w<CR>
nnoremap <silent>dfY dfY:w<CR>
nnoremap <silent>dfZ dfZ:w<CR>
nnoremap <silent>df+ df+:w<CR>
nnoremap <silent>df- df-:w<CR>
nnoremap <silent>df* df*:w<cr>
nnoremap <silent>df/ df/:w<cr>
nnoremap <silent>df, df,:w<CR>
nnoremap <silent>df< df<:w<CR>
nnoremap <silent>df. df.:w<CR>
nnoremap <silent>df> df>:w<CR>
nnoremap <silent>df_ df_:w<CR>
nnoremap <silent>df; df;:w<CR>
nnoremap <silent>df: df::w<CR>
nnoremap <silent>df] df]:w<CR>
nnoremap <silent>df} df}:w<CR>
nnoremap <silent>df@ df@:w<CR>
nnoremap <silent>df` df`:w<CR>
nnoremap <silent>df[ df[:w<CR>
nnoremap <silent>df{ df{:w<CR>
nnoremap <silent>df! df!:w<CR>
nnoremap <silent>df" df":w<CR>
nnoremap <silent>df# df#:w<CR>
nnoremap <silent>df$ df$:w<CR>
nnoremap <silent>df% df%:w<CR>
nnoremap <silent>df& df&:w<CR>
nnoremap <silent>df' df':w<CR>
nnoremap <silent>df( df(:w<CR>
nnoremap <silent>df) df):w<CR>
nnoremap <silent>df= df=:w<CR>
nnoremap <silent>df^ df^:w<CR>
nnoremap <silent>df~ df~:w<CR>
nnoremap <silent>df\ df\:w<CR>
" dF mortions
nnoremap <silent>dF1 dF1:w<CR>
nnoremap <silent>dF2 dF2:w<CR>
nnoremap <silent>dF3 dF3:w<CR>
nnoremap <silent>dF4 dF4:w<CR>
nnoremap <silent>dF5 dF5:w<CR>
nnoremap <silent>dF6 dF6:w<CR>
nnoremap <silent>dF7 dF7:w<CR>
nnoremap <silent>dF8 dF8:w<CR>
nnoremap <silent>dF9 dF9:w<CR>
nnoremap <silent>dF0 dF0:w<CR>
nnoremap <silent>dFa dFa:w<CR>
nnoremap <silent>dFb dFb:w<CR>
nnoremap <silent>dFc dFc:w<CR>
nnoremap <silent>dFd dFd:w<CR>
nnoremap <silent>dFe dFe:w<CR>
nnoremap <silent>dFf dFf:w<CR>
nnoremap <silent>dFg dFg:w<CR>
nnoremap <silent>dFh dFh:w<CR>
nnoremap <silent>dFi dFi:w<CR>
nnoremap <silent>dFj dFj:w<CR>
nnoremap <silent>dFk dFk:w<CR>
nnoremap <silent>dFl dFl:w<CR>
nnoremap <silent>dFm dFm:w<CR>
nnoremap <silent>dFn dFn:w<CR>
nnoremap <silent>dFo dFo:w<CR>
nnoremap <silent>dFp dFp:w<CR>
nnoremap <silent>dFq dFq:w<CR>
nnoremap <silent>dFr dFr:w<CR>
nnoremap <silent>dFs dFs:w<CR>
nnoremap <silent>dFt dFt:w<CR>
nnoremap <silent>dFu dFu:w<CR>
nnoremap <silent>dFv dFv:w<CR>
nnoremap <silent>dFw dFw:w<CR>
nnoremap <silent>dFx dFx:w<CR>
nnoremap <silent>dFy dFy:w<CR>
nnoremap <silent>dFz dFz:w<CR>
nnoremap <silent>dFA dFA:w<cr>
nnoremap <silent>dFB dFB:w<cr>
nnoremap <silent>dFC dFC:w<CR>
nnoremap <silent>dFD dFD:w<CR>
nnoremap <silent>dFE dFE:w<CR>
nnoremap <silent>dFF dFF:w<CR>
nnoremap <silent>dFG dFG:w<CR>
nnoremap <silent>dFH dFH:w<CR>
nnoremap <silent>dFI dFI:w<CR>
nnoremap <silent>dFJ dFJ:w<CR>
nnoremap <silent>dFK dFK:w<CR>
nnoremap <silent>dFL dFL:w<CR>
nnoremap <silent>dFM dFM:w<CR>
nnoremap <silent>dFN dFN:w<CR>
nnoremap <silent>dFO dFO:w<CR>
nnoremap <silent>dFP dFP:w<CR>
nnoremap <silent>dFQ dFQ:w<CR>
nnoremap <silent>dFR dFR:w<CR>
nnoremap <silent>dFS dFS:w<CR>
nnoremap <silent>dFT dFT:w<CR>
nnoremap <silent>dFU dFU:w<CR>
nnoremap <silent>dFV dFV:w<CR>
nnoremap <silent>dFW dFW:w<CR>
nnoremap <silent>dFX dFX:w<CR>
nnoremap <silent>dFY dFY:w<CR>
nnoremap <silent>dFZ dFZ:w<CR>
nnoremap <silent>dF+ dF+:w<CR>
nnoremap <silent>dF- dF-:w<CR>
nnoremap <silent>dF* dF*:w<CR>
nnoremap <silent>dF/ dF/:w<CR>
nnoremap <silent>dF, dF,:w<CR>
nnoremap <silent>dF< dF<:w<CR>
nnoremap <silent>dF. dF.:w<CR>
nnoremap <silent>dF> dF>:w<CR>
nnoremap <silent>dF_ dF_:w<CR>
nnoremap <silent>dF; dF;:w<CR>
nnoremap <silent>dF: dF::w<CR>
nnoremap <silent>dF] dF]:w<CR>
nnoremap <silent>dF} dF}:w<CR>
nnoremap <silent>dF@ dF@:w<CR>
nnoremap <silent>dF` dF`:w<CR>
nnoremap <silent>dF[ dF[:w<CR>
nnoremap <silent>dF{ dF{:w<CR>
nnoremap <silent>dF! dF!:w<CR>
nnoremap <silent>dF" dF":w<CR>
nnoremap <silent>dF# dF#:w<CR>
nnoremap <silent>dF$ dF$:w<CR>
nnoremap <silent>dF% dF%:w<CR>
nnoremap <silent>dF& dF&:w<CR>
nnoremap <silent>dF' dF':w<CR>
nnoremap <silent>dF( dF(:w<CR>
nnoremap <silent>dF) dF):w<CR>
nnoremap <silent>dF= dF=:w<CR>
nnoremap <silent>dF^ dF^:w<CR>
nnoremap <silent>dF~ dF~:w<CR>
nnoremap <silent>dF\ dF\:w<CR>
" dt mortions
nnoremap <silent>dt1 dt1:w<CR>
nnoremap <silent>dt2 dt2:w<CR>
nnoremap <silent>dt3 dt3:w<CR>
nnoremap <silent>dt4 dt4:w<CR>
nnoremap <silent>dt5 dt5:w<CR>
nnoremap <silent>dt6 dt6:w<CR>
nnoremap <silent>dt7 dt7:w<CR>
nnoremap <silent>dt8 dt8:w<CR>
nnoremap <silent>dt9 dt9:w<CR>
nnoremap <silent>dt0 dt0:w<CR>
nnoremap <silent>dta dta:w<CR>
nnoremap <silent>dtb dtb:w<CR>
nnoremap <silent>dtc dtc:w<CR>
nnoremap <silent>dtd dtd:w<CR>
nnoremap <silent>dte dte:w<CR>
nnoremap <silent>dtf dtf:w<CR>
nnoremap <silent>dtg dtg:w<CR>
nnoremap <silent>dth dth:w<CR>
nnoremap <silent>dti dti:w<CR>
nnoremap <silent>dtj dtj:w<CR>
nnoremap <silent>dtk dtk:w<CR>
nnoremap <silent>dtl dtl:w<CR>
nnoremap <silent>dtm dtm:w<CR>
nnoremap <silent>dtn dtn:w<CR>
nnoremap <silent>dto dto:w<CR>
nnoremap <silent>dtp dtp:w<CR>
nnoremap <silent>dtq dtq:w<CR>
nnoremap <silent>dtr dtr:w<CR>
nnoremap <silent>dts dts:w<CR>
nnoremap <silent>dtt dtt:w<CR>
nnoremap <silent>dtu dtu:w<CR>
nnoremap <silent>dtv dtv:w<CR>
nnoremap <silent>dtw dtw:w<CR>
nnoremap <silent>dtx dtx:w<CR>
nnoremap <silent>dty dty:w<CR>
nnoremap <silent>dtz dtz:w<CR>
nnoremap <silent>dtA dtA:w<cr>
nnoremap <silent>dtB dtB:w<cr>
nnoremap <silent>dtC dtC:w<CR>
nnoremap <silent>dtD dtD:w<CR>
nnoremap <silent>dtE dtE:w<CR>
nnoremap <silent>dtF dtF:w<CR>
nnoremap <silent>dtG dtG:w<CR>
nnoremap <silent>dtH dtH:w<CR>
nnoremap <silent>dtI dtI:w<CR>
nnoremap <silent>dtJ dtJ:w<CR>
nnoremap <silent>dtK dtK:w<CR>
nnoremap <silent>dtL dtL:w<CR>
nnoremap <silent>dtM dtM:w<CR>
nnoremap <silent>dtN dtN:w<CR>
nnoremap <silent>dtO dtO:w<CR>
nnoremap <silent>dtP dtP:w<CR>
nnoremap <silent>dtQ dtQ:w<CR>
nnoremap <silent>dtR dtR:w<CR>
nnoremap <silent>dtS dtS:w<CR>
nnoremap <silent>dtT dtT:w<CR>
nnoremap <silent>dtU dtU:w<CR>
nnoremap <silent>dtV dtV:w<CR>
nnoremap <silent>dtW dtW:w<CR>
nnoremap <silent>dtX dtX:w<CR>
nnoremap <silent>dtY dtY:w<CR>
nnoremap <silent>dtZ dtZ:w<CR>
nnoremap <silent>dt+ dt+:w<CR>
nnoremap <silent>dt- dt-:w<CR>
nnoremap <silent>dt* dt*:w<CR>
nnoremap <silent>dt/ dt/:w<CR>
nnoremap <silent>dt, dt,:w<CR>
nnoremap <silent>dt< dt<:w<CR>
nnoremap <silent>dt. dt.:w<CR>
nnoremap <silent>dt> dt>:w<CR>
nnoremap <silent>dt_ dt_:w<CR>
nnoremap <silent>dt; dt;:w<CR>
nnoremap <silent>dt: dt::w<CR>
nnoremap <silent>dt] dt]:w<CR>
nnoremap <silent>dt} dt}:w<CR>
nnoremap <silent>dt@ dt@:w<CR>
nnoremap <silent>dt` dt`:w<CR>
nnoremap <silent>dt[ dt[:w<CR>
nnoremap <silent>dt{ dt{:w<CR>
nnoremap <silent>dt! dt!:w<CR>
nnoremap <silent>dt" dt":w<CR>
nnoremap <silent>dt# dt#:w<CR>
nnoremap <silent>dt$ dt$:w<CR>
nnoremap <silent>dt% dt%:w<CR>
nnoremap <silent>dt& dt&:w<CR>
nnoremap <silent>dt' dt':w<CR>
nnoremap <silent>dt( dt(:w<CR>
nnoremap <silent>dt) dt):w<CR>
nnoremap <silent>dt= dt=:w<CR>
nnoremap <silent>dt^ dt^:w<CR>
nnoremap <silent>dt~ dt~:w<CR>
nnoremap <silent>dt\ dt\:w<CR>
" dT mortions
nnoremap <silent>dT1 dT1:w<CR>
nnoremap <silent>dT2 dT2:w<CR>
nnoremap <silent>dT3 dT3:w<CR>
nnoremap <silent>dT4 dT4:w<CR>
nnoremap <silent>dT5 dT5:w<CR>
nnoremap <silent>dT6 dT6:w<CR>
nnoremap <silent>dT7 dT7:w<CR>
nnoremap <silent>dT8 dT8:w<CR>
nnoremap <silent>dT9 dT9:w<CR>
nnoremap <silent>dT0 dT0:w<CR>
nnoremap <silent>dTa dTa:w<CR>
nnoremap <silent>dTb dTb:w<CR>
nnoremap <silent>dTc dTc:w<CR>
nnoremap <silent>dTd dTd:w<CR>
nnoremap <silent>dTe dTe:w<CR>
nnoremap <silent>dTf dTf:w<CR>
nnoremap <silent>dTg dTg:w<CR>
nnoremap <silent>dTh dTh:w<CR>
nnoremap <silent>dTi dTi:w<CR>
nnoremap <silent>dTj dTj:w<CR>
nnoremap <silent>dTk dTk:w<CR>
nnoremap <silent>dTl dTl:w<CR>
nnoremap <silent>dTm dTm:w<CR>
nnoremap <silent>dTn dTn:w<CR>
nnoremap <silent>dTo dTo:w<CR>
nnoremap <silent>dTp dTp:w<CR>
nnoremap <silent>dTq dTq:w<CR>
nnoremap <silent>dTr dTr:w<CR>
nnoremap <silent>dTs dTs:w<CR>
nnoremap <silent>dTt dTt:w<CR>
nnoremap <silent>dTu dTu:w<CR>
nnoremap <silent>dTv dTv:w<CR>
nnoremap <silent>dTw dTw:w<CR>
nnoremap <silent>dTx dTx:w<CR>
nnoremap <silent>dTy dTy:w<CR>
nnoremap <silent>dTz dTz:w<CR>
nnoremap <silent>dTA dTA:w<cr>
nnoremap <silent>dTB dTB:w<cr>
nnoremap <silent>dTC dTC:w<CR>
nnoremap <silent>dTD dTD:w<CR>
nnoremap <silent>dTE dTE:w<CR>
nnoremap <silent>dTF dTF:w<CR>
nnoremap <silent>dTG dTG:w<CR>
nnoremap <silent>dTH dTH:w<CR>
nnoremap <silent>dTI dTI:w<CR>
nnoremap <silent>dTJ dTJ:w<CR>
nnoremap <silent>dTK dTK:w<CR>
nnoremap <silent>dTL dTL:w<CR>
nnoremap <silent>dTM dTM:w<CR>
nnoremap <silent>dTN dTN:w<CR>
nnoremap <silent>dTO dTO:w<CR>
nnoremap <silent>dTP dTP:w<CR>
nnoremap <silent>dTQ dTQ:w<CR>
nnoremap <silent>dTR dTR:w<CR>
nnoremap <silent>dTS dTS:w<CR>
nnoremap <silent>dTT dTT:w<CR>
nnoremap <silent>dTU dTU:w<CR>
nnoremap <silent>dTV dTV:w<CR>
nnoremap <silent>dTW dTW:w<CR>
nnoremap <silent>dTX dTX:w<CR>
nnoremap <silent>dTY dTY:w<CR>
nnoremap <silent>dTZ dTZ:w<CR>
nnoremap <silent>dT+ dT+:w<CR>
nnoremap <silent>dT- dT-:w<CR>
nnoremap <silent>dT* dT*:w<CR>
nnoremap <silent>dT/ dT/:w<CR>
nnoremap <silent>dT, dT,:w<CR>
nnoremap <silent>dT< dT<:w<CR>
nnoremap <silent>dT. dT.:w<CR>
nnoremap <silent>dT> dT>:w<CR>
nnoremap <silent>dT_ dT_:w<CR>
nnoremap <silent>dT; dT;:w<CR>
nnoremap <silent>dT: dT::w<CR>
nnoremap <silent>dT] dT]:w<CR>
nnoremap <silent>dT} dT}:w<CR>
nnoremap <silent>dT@ dT@:w<CR>
nnoremap <silent>dT` dT`:w<CR>
nnoremap <silent>dT[ dT[:w<CR>
nnoremap <silent>dT{ dT{:w<CR>
nnoremap <silent>dT! dT!:w<CR>
nnoremap <silent>dT" dT":w<CR>
nnoremap <silent>dT# dT#:w<CR>
nnoremap <silent>dT$ dT$:w<CR>
nnoremap <silent>dT% dT%:w<CR>
nnoremap <silent>dT& dT&:w<CR>
nnoremap <silent>dT' dT':w<CR>
nnoremap <silent>dT( dT(:w<CR>
nnoremap <silent>dT) dT):w<CR>
nnoremap <silent>dT= dT=:w<CR>
nnoremap <silent>dT^ dT^:w<CR>
nnoremap <silent>dT~ dT~:w<CR>
nnoremap <silent>dT\ dT\:w<CR>
CONCLUSION
ここまでオートセーブを実現するvimrcを示した.
全てをそのまま利用する必要はない. vimrcを汚したくない人はあなただけではない.
自分もそうだ.
それでもinoremap <C-[> <C-[>:w<CR>はぜひ試してほしい.
セーブが快適になることを保証できる.
あとがき
初投稿ですっ!
この文書はVimを用いて作成されました.
このクソ長いvimrcを書くのにvimの繰り返しパワーはとても, ええ, とても役に立ちました.
このvimrcが少しでも多くのVimmerの役にたてば幸いです.