Bram Moolenaarさんの開発したVimはキーボード操作を前提としたテキストエディタです.
Unix系で使えるテキストエディタviの発展系(‘vi improved’)で,プログラマーやシステム管理者に使用されています.

学習コストが高いものの,テキストファイルを加工・編集することに特化した軽快さが魅力で,macOSであればターミナル.appから使用できます.

目次

  1. ターミナルからの使用
  2. 基礎的なモードの使い分け
  3. ノーマルモードの移動機能など
    1. 保存と終了
    2. カーソル移動
    3. スクロール
    4. ジャンプ
    5. テキストの加工
    6. アンドゥ
  4. 削除・変更・コピペ
    1. 削除
    2. 変更
    3. コピペ
    4. レジスタ
  5. 反復
    1. ドット
    2. マクロ
  6. 検索・置換
    1. 検索
    2. 置換
    3. 現在のカーソル位置の単語をコマンドへ入力する
    4. 複数ファイルで置換
  7. ウィンドウとタブページ
    1. 画面分割
    2. ウィンドウ切り替え
    3. タブ
  8. vimgrepコマンド
    1. パターンを含むファイルを検索
    2. ファイルパスが決まっていて,複数のパターンを調べたいとき
  9. 挿入モード
    1. 挿入モードでの削除
    2. 入力補完
    3. 計算
    4. 特殊文字の入力
    5. 同一文言の再入力
    6. 挿入ノーマルモード
  10. ビジュアルモード
  11. Exコマンドとアドレス
    1. 全範囲
    2. 選択範囲
    3. 指定範囲
    4. Exコマンドを反復
    5. Exモードに入る
  12. シェルの利用
    1. ターミナル・ノーマルモード
  13. vimrc
    1. マッピング
  14. プラグイン
    1. vim-surround
  15. 参考文献

ターミナルからの使用

次の形で,カレントディレクトリに指定したファイル名のテキストファイルを作成し,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 ←↓↑→(3j3k 3行下・上へ)
  • hjklを折り返しのある表示行で動かすには,頭にgをつける

ノーマルモードのgは特殊なニュアンスを与える接頭辞なので,例えばgjだと,通常は改行ごとにカーソルが移動するところ,折り返しごとにカーソルを移動することができます.

単語間の移動はwordの頭文字よりwです.
1つ前の単語に移動するには,backよりbとします.

  • 単語移動はw(次のワード), e(この単語のエンドに), b(バックする), ge(バックした単語のエンドに)

ファイルの先頭または末尾へのジャンプはgを重ね打ちしたり,大文字にしたりします.

  • ggG ファイル先頭・末尾へ

カーソルを画面内で移動させるには,High / Middle / Lowのどの位置にカーソルをもってくるかで指定します.

  • HML 画面上部・中央・下部へ

行頭・行末の文字への移動は正規表現に倣います.

  • ^$ 行頭・行末の文字へ(インデントを無視した行頭は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>で進む)

テキストの加工

  • iI 挿入モードへ・行頭から挿入モードへ
  • aA アペンドする(=続きから挿入モードへ)・行末から挿入モードへ
  • oO 次行(前行)に行挿入して挿入モードへ
  • J 次の行とジョイント
  • >><< インデントの追加・削除

アンドゥ

  • u<C-r> アンドゥ・リドゥ

削除・変更・コピペ

削除

1文字だけ削除(extract)するにはxキーを使います.

  • xX カーソル位置・直前の文字を削除

テキストの削除(delete)はdで開始します.

  • diwdaw カーソルのある単語の内部/外部までを削除(正確には削除でなくカット)
  • dipditカーソルのあるパラグラフ/タグの内部を削除
  • 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]で,現在レジスタに入っているマクロをコピペできる)

検索・置換

検索

全体

  • / スラッシュ以下の単語を検索(上方向には?
  • * カーソルのある単語を検索(上方向には#
  • nN 次・前へ

行内

  • 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>を前置して,hlkj:それぞれ左右上下へ切り替え
  • <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 パス
:vim {パターン1} ##
:vim {パターン2} ##

挿入モード

挿入モードでの削除

挿入モードでは,行頭からカーソルまでの位置を<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を開いた時に諸々の設定が読み込まれます.

"シンタックス・ハイライトをオンに
syntax on

"入力数値は十進法に従う
set nrformats=

"ビープ音を無効化する
set vb t_vb=

"行番号を表示する
set number

"検索
set ignorecase " 検索パターンに大文字小文字を区別しない
set smartcase " 検索パターンに大文字を含んでいたら大文字小文字を区別する
set wrapscan " 検索時に最後まで行ったら最初に戻る

"方向キーの無効化
noremap <Up> <Nop>
noremap <Down> <Nop>
noremap <Left> <Nop>
noremap <Right> <Nop>
inoremap <Up> <Nop>
inoremap <Down> <Nop>
inoremap <Left> <Nop>
inoremap <Right> <Nop>

マッピング

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"  #ダブルクオーテーション内を削除
cit #<div>等のタグ内を変更

さらに,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.)