Vimで高速にテキスト編集
Bram Moolenaarさんの開発したVimはキーボード操作を前提としたテキストエディタです.
Unix系で使えるテキストエディタviの発展系(‘vi improved’)で,プログラマーやシステム管理者に使用されています.
学習コストが高いものの,テキストファイルを加工・編集することに特化した軽快さが魅力で,macOSであればターミナル.appから使用できます.
目次
- ターミナルからの使用
- 基礎的なモードの使い分け
- ノーマルモードの移動機能など
- 削除・変更・コピペ
- 反復
- 検索・置換
- ウィンドウとタブページ
- vimgrepコマンド
- 挿入モード
- ビジュアルモード
- Exコマンドとアドレス
- シェルの利用
- vimrc
- プラグイン
- 参考文献
ターミナルからの使用
次の形で,カレントディレクトリに指定したファイル名のテキストファイルを作成し,vimで開きます.
この時点では保存はされていません.
vim ファイル名 |
基礎的なモードの使い分け
Vimにはいくつかのモードがあります.
いつでもEsc
キーでデフォルトの「ノーマルモード」となり,ノーマルモードはキーボードを使って高速な移動や加工を指示することができます.
後述しますが,G
と打てばファイル最終行にジャンプし,dd
と打てば現在行を削除することができます.
ノーマルモードこそVimを特徴付けるモードであり,最も重要なモードです.
ノーマルモードでは,:100
と入力すれば100行目にジャンプし,:s/test/Test/g
とすると同一行内のtestという文字列を全てTestに置換することができます.
認識としてはノーマルモードの延長ですが,ノーマルモードから:
を入力したモードは特に「コマンドラインモード」と呼ばれています.
コマンドラインモード中にEsc
を押すと,ノーマルモードに戻ります.
ノーマルモードからi
とだけ入力すると「挿入モード」に入ります.
このモードでは通常のキーボード入力を行うことができます.
入力が終わったらEsc
でノーマルモードに戻ってください.
ノーマルモードからv
とだけ入力すると「ヴィジュアルモード」になります.
マウス代わりに範囲選択したいときに使います.
範囲を選択したら,ノーマルモードの持つ多彩な機能をその範囲に対して適用することができます.
Esc
でキャンセルすればノーマルモードに戻ります.
以下,チートシートです.
<C- >
という形になっている部分はctrl +
の意味です.(Vim本体用のファイルを作成するときの記法に倣っています.)Esc
は<C-[>
と同値です.[a-z]
は小文字アルファベット1文字の意味です.
ノーマルモードの移動機能など
保存と終了
上書き保存はwriteよりw
,vimの終了はquitよりq
を使います.
:w
上書き保存:w ファイル名
別名で保存して,元のファイルの編集を続ける:save ファイル名
別名で保存して,保存したファイルの編集を続ける:q
閉じる:q!
強制終了:wq
上書き保存して終了
複数のバッファを開いているときには:wa
で全て保存することができる.
カーソル移動
ブラインドタッチでの右手のホームポジションで,人差し指のj
を押下するとカーソルは下に移動し,中指のk
で上に移動します.
それらから1つ左のキーであるh
を押すとカーソルは左に,1つ右のキーであるl
を押すと右に移動します.
hjkl
←↓↑→(3j
・3k
3行下・上へ)hjkl
を折り返しのある表示行で動かすには,頭にg
をつける
ノーマルモードのg
は特殊なニュアンスを与える接頭辞なので,例えばgj
だと,通常は改行ごとにカーソルが移動するところ,折り返しごとにカーソルを移動することができます.
単語間の移動はwordの頭文字よりw
です.
1つ前の単語に移動するには,backよりb
とします.
- 単語移動は
w
(次のワード),e
(この単語のエンドに),b
(バックする),ge
(バックした単語のエンドに)
ファイルの先頭または末尾へのジャンプはg
を重ね打ちしたり,大文字にしたりします.
gg
・G
ファイル先頭・末尾へ
カーソルを画面内で移動させるには,High / Middle / Lowのどの位置にカーソルをもってくるかで指定します.
H
・M
・L
画面上部・中央・下部へ
行頭・行末の文字への移動は正規表現に倣います.
^
・$
行頭・行末の文字へ(インデントを無視した行頭は0
)
スクロール
ctrlキーに加えてup(<C-u>
)で上に,down(<C-d>
)で画面をスクロールします.
もっと大きく進めたいなら,forward(<C-f>
)とback(<C-b>
)です.
<C-u>
,<C-d>
1/2画面上に,下に<C-f>
,<C-b>
1画面進む,戻る
ジャンプ
:n
n行目へm[a-zA-Z]
・`[a-zA-Z]
マークをする・マーク箇所へジャンプする(大文字はグローバルにマーク.小文字だとローカルなバッファにマーク.)%
で対応する反対側の括弧へ移動- バッククオート2連続でジャンプ前の位置に戻る
<C-o>
で前の挿入モードとの切り替え位置に戻る(<C-i>
で進む)
テキストの加工
i
・I
挿入モードへ・行頭から挿入モードへa
・A
アペンドする(=続きから挿入モードへ)・行末から挿入モードへo
・O
次行(前行)に行挿入して挿入モードへJ
次の行とジョイント>>
・<<
インデントの追加・削除
アンドゥ
u
・<C-r>
アンドゥ・リドゥ
削除・変更・コピペ
削除
1文字だけ削除(extract)するにはx
キーを使います.
x
・X
カーソル位置・直前の文字を削除
テキストの削除(delete)はd
で開始します.
diw
・daw
カーソルのある単語の内部/外部までを削除(正確には削除でなくカット)dip
・dit
カーソルのあるパラグラフ/タグの内部を削除dt + 文字
カーソル位置から文字直前まで削除dd
行削除2dd
2回,行削除d2d
2行削除D
その行のカーソルより右側を全部消す
変更
テキストの変更(change)はc
で開始します.
どの範囲を変更するかを続けて書きます.
ciw
カーソルのある単語の内部を変更(=削除して挿入モードへ)C
現在行でカーソル位置以下を変更
アッパーケース,すなわち大文字とするには,gU
とします.
小文字の変換はUの文字を小さくしたgu
です.
gu
小文字化gU
大文字化g~
大文字・小文字の反転
コピペ
yy
行をヤンク(=コピー)p
カーソル直後にペースト(カーソル直下にしたいならP
)
レジスタ
- コピペにレジスタを使うなら
"[a-zA-Z]
を前置 y
でヤンクしたものはヤンクレジスタ(0)に入るので"0
で呼べ,d
では上書きされない- デフォルトの無名レジスタに入れないようにするにはブラックホールレジスタを使えばよく,例えば
\_d
で削除すれば削除したものはレジスタに残らない - クリップボードにコピーまたはクリップボードからペーストしたい場合,システムクリップボードレジスタを使って
"+
を前置
反復
ドット
.
直前の操作の繰り返し2.
直前の操作を2回反復
マクロ
q[a-z]
ノーマルモードで次にq
が押されるまでの間,マクロを記録@[a-z]
対応するマクロを実行:reg [a-z]
レジスタに保持されたマクロの確認:let @[a-z]='foo'
マクロをfoo
に書き換え(<C-r>[a-z]
で,現在レジスタに入っているマクロをコピペできる)
検索・置換
検索
全体
/
スラッシュ以下の単語を検索(上方向には?
)*
カーソルのある単語を検索(上方向には#
)n
・N
次・前へ
行内
f
+文字
とすると,カーソル以降で,その行で文字が現れるところを探す(前方に向かってはF
+文字
)f
に代えてt
だと検索結果直前の位置にカーソルが動く;
・,
次・前へ
オプション
\c
大文字・小文字を区別しない\C
大文字・小文字を区別する\v
特殊記号に関する規則を正規化(エスケープせずに正規表現を書けるように)\V
そのままのテキストを検索
置換
文字置換
r
で次に入力する1字へカーソル位置の文字を置換(R
なら,Esc
キーが入力されるまで,この置換を維持)
単語置換
:s/word1/word2/g
置換- オプション:
:3,5s
以下の形式なら,3〜5行目の置換 g
はその行でグローバルに置換するオプション.書類全体にするなら:%s/word1/word2/g
とする- オプションを
c
にすると,都度チェックして置換 S
現在行を丸ごと書き換えるため,挿入モードへ
現在のカーソル位置の単語をコマンドへ入力する
<C-r><C-w>
複数ファイルで置換
カレントディレクトリ以下で置換を行う場合について.
まず,保存なくファイル間を移動できるようにしておく.
:set hidden |
さて,拡張子py
のファイルを対象にするという例であれば,まず引数リストを作る.
:args **/*.py |
この引数リストで当たったファイル全てについて置換を実行する.
:argdo %s/置換前/置換後/ge |
ここで最後のe
オプションはエラーメッセージの抑制であり,置換前の語が含まれないファイルでエラーメッセージが出ないようにするためのものである.
ウィンドウとタブページ
ウィンドウ操作の始動キーは,windowに由来して<C-w>
です.
画面分割
<C-w>s
or:sp
(:split
の略):水平方向に分割<C-w>v
or:vs
(:vertical split
の略):垂直方向に分割
:sp
・:vs
は引数にファイル名をとり,別のファイルを開くことができます.
:vs
(:vertical split
)のバリエーションとして,現在表示しているファイルと差分を表示する特別なコマンドがあります.
:vertical diffsplit ファイル名 |
ウィンドウ切り替え
<C-w><C-w>
または<C-w>w
:ウィンドウ切り替え<C-w>
を前置して,h
・l
・k
・j
:それぞれ左右上下へ切り替え<C-w>c
or 前置なく:close
:閉じる<C-w>o
or 前置なく:only
:その他のウィンドウを閉じる
タブ
:tabe
(:tabedit
の略):新規タブ作成:tabe ファイルパス
:新規タブで指定したファイルを開く:tabc
(:tabclose
の略):タブを閉じるgt
:次のタブへ3gt
:第3タブへgT
:前のタブへ
vimgrepコマンド
パターンを含むファイルを検索
省略形は:vim
であり,
:vim <パターン> ファイルパス |
で,パターンを含むファイルを検索します.
ファイルパス中,dir/*
は該当するディレクトリdir内の任意のファイルを対象とするが,再帰的には検索しません.
再帰的に検索させるにはdir/**
と書きます.
ヒットしたファイル間で次に移動するにはcn
,前に移動するにはcN
とします.
一覧するにはcw
です.
ファイルパスが決まっていて,複数のパターンを調べたいとき
:args パス |
挿入モード
挿入モードでの削除
挿入モードでは,行頭からカーソルまでの位置を<C-u>
で削除することができます.
直前の単語だけを削除するには<C-w>
です.
入力補完
パスの途中まで記述してあるとして,あるいはカレントディレクトリを前提として,
<C-x><C-f> |
によりファイル名を補完して入力することができます.
計算
挿入モードで
<C-r>=式 |
とすると,式の答えが入力されます.(registerのr
)
カーソルの置かれた数値に加減したい場合,100加えるならaddという単語より,
100<C-a> |
とし,100引くときは100<C-x>
とします.(それぞれ,addのa
とextractのx
)
なお,数値を指定しないと,1の増減となります.
特殊文字の入力
Unicodeを使うなら,
<C-v>u06bf |
のように<C-v>u
を使って16進数を書きます.
同一文言の再入力
ノーマルモードでマクロを使用するには@
を使いました.
挿入モードにおいて,直前の挿入モードで入力した内容を繰り返して入力するには
<C-@> |
とします.
挿入ノーマルモード
挿入モードから<C-o>
で,1コマンドだけノーマルモードを使え,使用後は挿入モードに戻ります.(one-shotのo
)
ビジュアルモード
ノーマルモードからv
(visualのv
)を入力することで,カーソルの現在位置より文字範囲を選択することができます.
適当な終点まで来たところで,ノーマルモードでカットを意味していたd
を押すと,ヴィジュアルモードで選択した範囲がカットされます.
範囲選択中に始点を変更したくなったらo
で始点と終点をトグルできます.
ノーマルモードからV
を入力すると,行範囲を選択します.
しばしば次のようなイディオムを使用するでしょう.
Vd
:現在行のカットVy
:現在行のコピーggVG
:全選択
また,特殊なヴィジュアルモードとして,<C-v>
で入ることのできるブロックビジュアルモードがあります.
ブロックビジュアルモードは,複数行にわたりコードの同じ文字数目から範囲選択することができます.
例えば,下にカーソルを動かすj
と文末までジャンプする$
を組み合わせることで,<C-v>j$
というイディオムを作れば,現在の文字数目から文末までの範囲を2行にわたって選択することができます.
Exコマンドとアドレス
全範囲
ノーマルモードに存在するコマンド呼び出しは,明示的に:norm
(:normal
の省略形)と書いて行うこともできます.
例えば,行頭に#
を追加する場合だと
:norm I# |
と書けます.
これだけであれば冗長な記述になっただけですが,:
によってコマンドモードに入ると,:
の直後でどの範囲に処理を施すか指定することができます.
コマンドモードにおいて,%
は全選択を意味します.
したがって,任意の行頭に#
を追加するには,
:%norm I# |
とします.
別の便利な例です.
マクロがレジスタq
に保持されているとするとすれば,
:%norm @q |
で全範囲にマクロ適用することができます.
選択範囲
ビジュアルモードで範囲選択し,:
を押下すると,その範囲は:'<,'>
となります.
したがって,行選択した範囲において行頭に#
を書き加えるには,
:'<,'>norm I# |
とします.
指定範囲
,
は連続した行を表すのに用います.
例えば,
:3,5d |
で,3-5行目を削除(delete)することができます.
.
は現在行を意味するので,
:.,.+1p |
であれば,現在行から次行まで出力(print)します.
特定の1行だけであれば,単に行番号を書くだけでOKです.
2行目を最終行の下に移動したいなら,
:2m$ |
となります.
なお,m
に代えてco
(またはそれと同値であるt
)なら,コピーします.
Exコマンドを反復
Exコマンドを反復するのはマクロの実行と似ています.
@
を使い,対象として:
を指定します.
@: |
Exモードに入る
Exモードは,:
の入力を省略することができるモードです.
Q
で入り,:vi
で出ます.
シェルの利用
!
を宣言することで,Vimからシェルを利用できます.
ls
コマンドであれば,
:!ls |
です.
ls
コマンドの出力結果を現在カーソルの下に挿入するには
:read !ls |
とします.
ターミナル・ノーマルモード
Vimから:term
(:terminal
の省略形)で分割ウィンドウにターミナルを呼び出せます.
分割されたウィンドウの移動は通常通りです.
ターミナルのウィンドウをノーマルモードとみなしてコピー等を行うには,ターミナルのウィンドウを有効にした上で,
<C-w>N |
とします.
vimrc
次の要領で.vimrc
ファイルを~/
に作成しておくと,vimを開いた時に諸々の設定が読み込まれます.
"シンタックス・ハイライトをオンに |
マッピング
map
とそのバリエーションはマップ先をマップすることを許すので,わかりにくくなります.
このため,マップ先をマップすることを許さないnoremap
とそのバリエーションを使います.
:no[remap] マップ前のキー マップ後のキー |
モードごとのリマップと短縮系があり,次のようになります.
:ino[remap]
:挿入モードでのリマップ:vn[oremap]
:ヴィジュアルモードでのリマップ:nn[oremap]
:ノーマルモードからのリマップ
例えば,
:ino jj <Esc> |
で,挿入モードにてjj
を入力すると<Esc>
を入力した扱いになります.
(すなわち,ノーマルモードに移ります.)
マッピングでキーの組み合わせを書く場合,ctrl + a
なら<C-a>
と書きます.
同様に,シフトキーは<S- >
,コマンドキーは<D- >
を使います.
十字キーは<Up>
・<Down>
,<Left>
,<Right>
です.
マッピングを解除するには:unmap
とそのバリエーションを使います.
プラグイン
vim-surround
Vimはデフォルトで囲み内部の指定ができます.
di" #ダブルクオーテーション内を削除 |
さらに,vim-surroundプラグインを~/.vim
以下の階層に配置することで,囲み記号の編集もできるようになります.
モーションでi
(inside)やa
(around)するのと同様に,囲みをs
(surround)で指定します.
例えば,
cs"{ |
で,ダブルクオーテーション囲みをブレース囲みに変更します.
新たに囲むには,c
(change)やd
(delete)に代えて,y
(you)を接頭辞とします.
単語をダブルクオーテーション(=iw
を"
)で囲むとすれば,
ysiw" |
です.
ビジュアルモードでは大文字S
を使います.
例えば,
viwS" |
とすると,ビジュアルモード(v
)で単語選択して(iw
)ダブルクオーテーションで囲む(S"
)という意味になります.
参考文献
Vimにもともと備わっている機能を解説した書籍です.
- Drew Neil (2013)「実践Vim 思考のスピードで編集しよう!」アスキー・メディアワークス(Drew Neil (2012) “Practical Vim: Edit Text at the Speed of Thought” Pragmatic Bookshelf.)