プログラマのための IT 教科書
第1部 開発者の道具箱

vim

読了目安 35

この章を読むとできるようになること
  • vim から確実に脱出できる
  • モードの違いを理解して意図した編集ができる
  • オペレータとモーションを組み合わせられる

「今どき vim を覚える必要があるのか」と思うかもしれません。 普段のコーディングは VS Code や JetBrains で構いません。

それでも vim を扱えなければならない場面が、必ず来ます

  • サーバーに SSH して設定ファイルを直す(GUI エディタは使えません)
  • git commit をメッセージなしで実行したら、いきなり vim が開いた
  • kubectl edit deployment を打ったら vim が開いた
  • Docker コンテナの中に入って調べる(vi しか入っていない)

この章のゴールは vim マスターになることではありません。 この4つの場面で困らない最低限を身につけることです。

まず脱出する

vim を初めて開いた人が最初にぶつかる壁は「終われない」ことです。 Ctrl+C も効かず、文字を打つと画面が壊れていく。

答えは :wq です。

vim 演習

まずは脱出です。このファイルを保存して閉じてください(この演習では内容は消えません)。

ここをクリックしてからキーを打ってください

1 # デプロイ手順
2
3 1. main を最新にする
4 2. deploy.sh を実行する
NORMAL1,1
  • 未達保存して閉じた
打鍵数 0
コマンド意味
:w保存する(write)
:q終了する(quit)
:wq保存して終了
:q!保存せずに捨てて終了(変更をなかったことにする)
迷ったら Esc を2回押す

何かおかしくなったら、まず Esc を押してください。 どのモードにいてもノーマルモードに戻れます

vim で迷子になった時の合言葉は「Esc を押して :wq」です。

モードという概念

ここが vim 最大の壁であり、理解すれば残りは楽になる部分です。

普通のエディタは、キーを打てば文字が入ります。vim は違います。 今どのモードにいるかで、同じキーの意味が変わります。

モード状態入り方抜け方
ノーマル移動・削除・コピー。vim の基本状態Esc
挿入文字を入力するi a o などEsc
コマンドライン: で始まる命令を打つ:Esc か Enter

ノーマルモードで d を押すと「削除の準備」、挿入モードで d を押すと文字の d が入ります。

なぜモードがあるのか

文字入力と操作を分けることで、すべてのキーを操作に使えるからです。

普通のエディタでは、削除やコピーに CtrlCmd を組み合わせる必要があります。 vim はモードを分けたので、d y p のような1文字のキーを操作に割り当てられます。 これが「慣れると速い」と言われる理由です。

画面の左下を見てください。 挿入モードのときは -- INSERT -- と出ます。 これが「今どのモードか」の唯一の手がかりです。

移動する

ノーマルモードでの移動です。矢印キーも使えますが、hjkl の方が手が動きません。

        k(上)
h(左)      l(右)
        j(下)

j が下、k が上です。最初は必ず迷いますが、 j はアルファベットの形が下向きに伸びていると覚えると忘れません。

vim 演習

3行目の「retry」という単語の先頭にカーソルを移動してください。矢印キーは使わず hjkl と単語移動を使います。

ここをクリックしてからキーを打ってください

1 timeout: 30
2 host: localhost
3 retry: 3
4 debug: false
NORMAL1,1
  • 未達カーソルが 3 行 1 列にある
打鍵数 0

もっと速く動く

1文字ずつ動くのは遅いので、まとめて動きます。

キー動き
w次の単語の先頭へ(word)
b前の単語の先頭へ(back)
e単語の末尾へ(end)
0行頭へ
^行の最初の文字へ(インデントを飛ばす)
$行末へ
ggファイルの先頭へ
Gファイルの末尾へ

編集する

挿入モードに入る4つの入り口

キーどこから入力が始まるか
iカーソルの(insert)
aカーソルの後ろ(append)
I行頭から
A行末から
o下に新しい行を作って
O上に新しい行を作って

行末に何か足したい時、$ で行末に行ってから a を押す人が多いですが、 A なら1回で済みます。

削除とコピー

キー動作
xカーソル位置の1文字を削除
dd1行まるごと削除
dwカーソル位置から単語の終わりまで削除
d$カーソル位置から行末まで削除
yy1行コピー(yank)
pカーソルの後ろに貼り付け(put)
Pカーソルの前に貼り付け
u元に戻す(undo)
vim 演習

デバッグ用に紛れ込んだ「console.log("ここ通った")」の行を削除してください。

ここをクリックしてからキーを打ってください

1 function search(keyword) {
2 console.log("ここ通った")
3 return items.filter((item) => item.name.includes(keyword))
4 }
NORMAL1,1
  • 未達内容が目標どおりになっている
打鍵数 0
行を移動させたい時

dd は「削除」ですが、消した内容はレジスタ(クリップボード)に入ります。 だから dd → 移動 → p で行の移動ができます。

これは実務で頻繁に使います。

vim が速い理由

ここからが本題です。vim はオペレータ + モーションという組み合わせで動きます。

 d    +    w     =  dw
削除      単語     単語を削除

 c    +   iw     =  ciw
変更    その単語   その単語を変更

覚えるのは「オペレータ」と「モーション」の組み合わせ方だけで、 掛け算のように操作が増えます。

オペレータ意味
d削除(delete)
c変更(change = 削除して挿入モードへ)
yコピー(yank)

ciw と .

ciw(change inner word)は「カーソルがある単語を丸ごと書き換える」操作です。 単語のどこにカーソルがあっても効くので、wb で先頭に合わせる必要がありません。

そして .(ドット)は「直前の変更を繰り返す」 コマンドです。

この2つを組み合わせると、同じ修正を何箇所やっても打鍵数がほとんど増えません。

vim 演習

変数名 tmp を items に変えてください。3箇所すべてです。ciw と . を使うと少ない打鍵で終わります。

ここをクリックしてからキーを打ってください

1 const tmp = await fetchItems()
2 const filtered = tmp.filter(Boolean)
3 return tmp.length
NORMAL1,7
  • 未達内容が目標どおりになっている
打鍵数 0
ここが分かれ目

vim を「移動が面倒なエディタ」と思うか「速いエディタ」と思うかは、 ciw. を知っているかどうかで決まります。

普通のエディタなら、変数名を3箇所直すのに3回タイプします。 vim は1回タイプして . を2回押すだけです。

検索と置換

コマンド動作
/検索語 + Enter下に向かって検索
n次の一致へ
:%s/old/new/g全行の old を new に置換

:%s/old/new/g の意味を分解します。

:%s/old/new/g
 │└ s = substitute(置換)
 └ % = 全行を対象に
                  └ g = 各行のすべて(付けないと行の最初の1つだけ)
vim 演習

設定ファイル内の staging をすべて production に置き換えてください。1コマンドでできます。

ここをクリックしてからキーを打ってください

1 env: staging
2 api_url: https://staging.example.com
3 bucket: staging-uploads
4 replicas: 2
NORMAL1,1
  • 未達内容が目標どおりになっている
打鍵数 0
確認しながら置換する

:%s/old/new/gc のように末尾に c(confirm)を付けると、 1箇所ずつ「置き換えますか?」と聞いてくれます。

本番の設定ファイルを触る時は c を付ける習慣をつけると安全です。

実務で本当に使う場面

git commit でエディタが開いた

git commit-m なしで実行すると vim が開きます。

  1. i を押して挿入モードに入る
  2. コミットメッセージを書く
  3. Esc を押す
  4. :wq で保存して終了

空のまま :q! で終了すると、コミットは中止されます(これも覚えておくと便利です)。

kubectl edit

kubectl edit deployment api

これで Deployment の YAML が vim で開きます。 編集して :wq すると、その場でクラスタに反映されます。

kubectl edit は即座に本番へ反映される

:wq した瞬間に反映されます。確認画面はありません。

しかもこの変更は Git に残りません。次に CI がデプロイすると上書きされて消えます。 調査のための一時的な変更以外では使わず、 恒久的な変更はマニフェストを直して PR を出してください。

サーバー上で設定ファイルを直す

ssh user@server
vi /etc/nginx/nginx.conf

GUI は使えません。ここで vim が使えないと、何もできずに終わります。

:q! と :wq を取り違える

:q!変更を捨てて終了します。1時間かけた編集も消えます。 :wq保存して終了します。

急いでいる時ほど間違えます。指が止まったら、 一度 :w だけして保存してから考えるのが安全です。

覚えるべき最小セット

この表だけ覚えれば、実務で困ることはほぼありません。

Esc      ノーマルモードに戻る(迷ったらこれ)
i / a    挿入モードに入る(前 / 後ろ)
o        下に行を作って挿入
hjkl     移動
w / b    単語単位で移動
0 / $    行頭 / 行末
gg / G   ファイルの先頭 / 末尾
x        1文字削除
dd       1行削除
yy / p   行コピー / 貼り付け
u        元に戻す
ciw      単語を書き換える
.        直前の変更を繰り返す
/word    検索、n で次へ
:w :q :wq :q!
:%s/old/new/g

まとめ

  • vim は避けられない。SSH・git commitkubectl edit で必ず出会う
  • 最大の壁はモード。ノーマル(操作)と挿入(入力)で同じキーの意味が変わる
  • 迷ったら Esc:wq。捨てたいなら :q!
  • 移動は hjklw b 0 $ gg G
  • オペレータ + モーションで操作が掛け算的に増える(dw ciw
  • ciw. が vim を速くする組み合わせ
  • kubectl edit の変更は Git に残らない。一時的な調査以外では使わない

章末問題

git commit を -m なしで実行したら vim が開きました。メッセージを書いて確定させる手順は?

変数名 tmp が10箇所あり、すべて items に変えたい。最も打鍵数が少ないのは?

kubectl edit deployment api で設定を変えて :wq しました。この変更について正しいのは?

次の章は Git です。vim と同じく、毎日使う道具になります。

読み終わったら記録しておくと、目次で進み具合が分かります。