Viは1976年にBill JoyがBSD Unix向けに作成したテキストエディタである。当時のターミナル環境でキーボードのみで効率的な編集を可能にした革新的なツールであった。Viの核心的なアイデアである**モーダル編集(Modal Editing)**は今日まで生き続けている。
Vim(Vi IMproved)は1991年にBram Moolenaarが公開したViの大幅拡張版である。シンタックスハイライト、プラグインシステム、マルチウィンドウ、マクロ、正規表現置換など数百もの機能が追加された。VimはGNU/Linuxサーバーにデフォルトで搭載され、世界中の開発者やシステム管理者が日常的に使用する標準エディタとなった。
Neovimは2014年に始まったVimのリファクタリングフォークである。Luaベースの設定、内蔵LSP(Language Server Protocol)、非同期プラグインAPIを提供し、VS Codeレベルの IDE体験をターミナルで実現することを目指している。
| エディタ | リリース | 特徴 |
|---|
| Vi | 1976 | モーダル編集の元祖、軽量 |
| Vim | 1991 | プラグイン、シンタックスハイライト、マクロ |
| Neovim | 2014 | Lua API、内蔵LSP、非同期処理 |
- どこでも使える:SSH接続したリモートサーバー、Dockerコンテナ、組み込みデバイス — ほぼすべてのUnix環境にVi/Vimがインストールされている。
- 手がキーボードから離れない:マウスなしですべての操作が可能なため、編集速度が劇的に向上する。
- 強力な組み合わせ言語:
d3w(単語3つ削除)、ci"(引用符内の内容変更)のように、動詞+回数+名詞の構造で複雑な操作を簡潔に表現できる。 - マクロと自動化:繰り返し作業をマクロに記録し、数千行を一瞬で変換できる。
- Vimキーバインドの汎用性:VS Code、IntelliJ、Obsidian、Jupyter、bash readline、tmux copy modeなど数十のツールがVimキーバインドをサポートしている。Vimを学べばすべてのツールが速くなる。
Vimの最も重要な特徴はモーダル編集である。キーを押したときの動作が現在のモードによって完全に変わる。
| モード | 説明 | 進入方法 | 脱出方法 |
|---|
| Normal | 移動、コマンド実行 | <Esc>、<C-c> | —(デフォルトモード) |
| Insert | テキスト入力 | i、a、o、I、A、O、s、c | <Esc>、<C-c> |
| Visual | 文字単位の選択 | v | <Esc>、v |
| Visual Line | 行単位の選択 | V | <Esc>、V |
| Visual Block | ブロック(列)単位の選択 | <C-v> | <Esc>、<C-v> |
| Command-line | :コマンド入力 | :、/、?、! | <Esc>、<CR> |
| Replace | 文字の上書き | R | <Esc> |
┌─────────────────────────────────────────┐
│ Normal Mode │
│ (起動時のデフォルト / <Esc>で常に復帰) │
└────┬───────┬───────┬────────────────────┘
│ │ │
i,a,o│ v,V│ :,/,?│
│ │ │
┌────▼──┐ ┌──▼────┐ ┌▼────────────┐
│Insert │ │Visual │ │Command-line │
│ Mode │ │ Mode │ │ Mode │
└───────┘ └───────┘ └─────────────┘
ルール:いつでも<Esc>を押せばNormal Modeに戻る。迷ったときに<Esc>を2回押すのがVimサバイバルルール第1条である。
| キー | 動作 |
|---|
h | 左に1文字移動 |
j | 下に1行移動 |
k | 上に1行移動 |
l | 右に1文字移動 |
5j | 下に5行移動(数字プレフィックス可能) |
10k | 上に10行移動 |
| キー | 動作 |
|---|
w | 次の単語の先頭へ移動(句読点区切り) |
W | 次のWORDの先頭へ移動(空白区切り) |
b | 前の単語の先頭へ移動 |
B | 前のWORDの先頭へ移動 |
e | 現在/次の単語の末尾へ移動 |
E | 現在/次のWORDの末尾へ移動 |
ge | 前の単語の末尾へ移動 |
小文字(w、b、e)は句読点を単語の境界として認識し、大文字(W、B、E)は空白のみを境界として認識する。hello_worldではwは2回、Wは1回で移動する。
| キー | 動作 |
|---|
0 | 行の先頭(カラム0)へ移動 |
^ | 行の最初の非空白文字へ移動 |
$ | 行の末尾へ移動 |
g_ | 行の最後の非空白文字へ移動 |
gg | ファイルの最初の行へ移動 |
G | ファイルの最後の行へ移動 |
42G | 42行目へ移動 |
:42 | 42行目へ移動(コマンドモード) |
% | マッチする括弧/中括弧/大括弧へ移動 |
| キー | 動作 |
|---|
<C-u> | 画面を半分上にスクロール |
<C-d> | 画面を半分下にスクロール |
<C-f> | 画面全体を下にスクロール(Page Down) |
<C-b> | 画面全体を上にスクロール(Page Up) |
H | 画面最上行にカーソル移動(High) |
M | 画面中央行にカーソル移動(Middle) |
L | 画面最下行にカーソル移動(Low) |
zz | 現在行を画面中央に配置 |
zt | 現在行を画面上部に配置 |
zb | 現在行を画面下部に配置 |
| キー | 動作 |
|---|
/pattern | 下方向にpatternを検索 |
?pattern | 上方向にpatternを検索 |
n | 同じ方向に次の検索結果へ |
N | 反対方向に次の検索結果へ |
* | カーソル下の単語を下方向に検索 |
# | カーソル下の単語を上方向に検索 |
f{char} | 現在行でcharを前方検索し、その位置へ移動 |
F{char} | 現在行でcharを後方検索 |
t{char} | charの直前へ移動(till) |
T{char} | charの直後(逆方向)へ移動 |
; | f/F/t/Tの方向に繰り返し |
, | f/F/t/Tの逆方向に繰り返し |
| キー | 動作 |
|---|
<C-o> | 前のカーソル位置へ移動(jump back) |
<C-i> | 次のカーソル位置へ移動(jump forward) |
'' | 直前のジャンプ位置へ復帰(シングルクォート2回) |
m{a-z} | 現在位置をマークa〜zに保存 |
'{a-z} | マークへ移動 |
gd | ローカル定義(declaration)へ移動 |
gD | グローバル定義へ移動 |
| キー | 動作 |
|---|
i | カーソルの前でInsert Mode進入 |
I | 行の最初の非空白文字の前でInsert Mode進入 |
a | カーソルの後でInsert Mode進入(append) |
A | 行の末尾でInsert Mode進入 |
o | 現在行の下に新しい行を追加してInsert Mode進入 |
O | 現在行の上に新しい行を追加してInsert Mode進入 |
gi | 最後に編集した位置でInsert Mode進入 |
| キー | 動作 |
|---|
x | カーソル下の文字を削除 |
X | カーソル前の文字を削除(Backspace) |
dd | 現在行を削除 |
3dd | 現在行から3行削除 |
D | カーソルから行末まで削除(d$と同じ) |
dw | カーソルから次の単語の先頭まで削除 |
de | カーソルから単語の末尾まで削除 |
d0 | カーソルから行頭まで削除 |
dG | 現在行からファイル末尾まで削除 |
dgg | 現在行からファイル先頭まで削除 |
削除されたテキストはレジスタに保存され、pで貼り付けできる。Vimの削除は「カット(Cut)」と同じである。
| キー | 動作 |
|---|
r{char} | カーソル下の文字をcharに置換(Normal Mode維持) |
R | Replace Mode進入(連続上書き) |
s | カーソル下の文字を削除してInsert Mode進入 |
S | 現在行の内容を削除してInsert Mode進入(ccと同じ) |
cw | カーソルから単語の末尾まで変更 |
cc | 現在行の内容を変更 |
C | カーソルから行末まで変更(c$と同じ) |
c0 | カーソルから行頭まで変更 |
~ | カーソル下の文字の大文字/小文字を切り替え |
g~w | 単語の大文字/小文字を切り替え |
guw | 単語を小文字に変換 |
gUw | 単語を大文字に変換 |
| キー | 動作 |
|---|
yy | 現在行をコピー(yank) |
Y | 現在行をコピー(yyと同じ) |
3yy | 現在行から3行コピー |
yw | カーソルから単語の末尾までコピー |
y$ | カーソルから行末までコピー |
y0 | カーソルから行頭までコピー |
p | カーソルの後(下)に貼り付け |
P | カーソルの前(上)に貼り付け |
gp | pと同じだが、貼り付け後カーソルをテキストの末尾に移動 |
"ayy | レジスタaに現在行をコピー |
"ap | レジスタaの内容を貼り付け |
| キー | 動作 |
|---|
u | 最後の変更を取り消し(Undo) |
3u | 最後の3つの変更を取り消し |
<C-r> | Undoを取り消し(Redo) |
U | 現在行に対するすべての変更を取り消し |
| キー | 動作 |
|---|
>> | 現在行をインデント |
<< | 現在行をアウトデント |
3>> | 3行をインデント |
= | 自動インデント(Visual選択後または==で現在行) |
== | 現在行を自動インデント |
gg=G | ファイル全体を自動インデント |
| キー | モード | 説明 |
|---|
v | Visual(文字) | 文字単位の選択 |
V | Visual Line | 行単位の選択 |
<C-v> | Visual Block | 列(column)単位のブロック選択 |
gv | — | 前回のVisual選択範囲を再選択 |
| キー | 動作 |
|---|
d / x | 選択範囲を削除 |
y | 選択範囲をコピー |
c | 選択範囲を削除してInsert Mode進入 |
> / < | 選択範囲をインデント / アウトデント |
= | 選択範囲を自動インデント |
~ | 選択範囲の大文字/小文字を切り替え |
u | 選択範囲を小文字に変換 |
U | 選択範囲を大文字に変換 |
: | 選択範囲にコマンドを適用(:'<,'>) |
o | 選択範囲の反対端にカーソルを移動 |
Visual Block(<C-v>)は複数行に同時にテキストを挿入または削除する際に非常に便利である。
例:複数行の先頭に//コメントを追加する
1. <C-v>でVisual Block進入
2. jを押して必要な行数を選択
3. Iを押してブロックInsert Mode進入
4.
5. <Esc>を押すと、選択されたすべての行に
例:複数行の特定カラムの内容を削除
1. <C-v>でVisual Block進入
2. 必要な範囲を選択(hjklで列範囲を調整可能)
3. dで削除
テキストオブジェクトはVim編集の核心的な概念である。{operator}{a|i}{object}の構造で「動詞 + 前置詞 + 名詞」形式のコマンドを構成する。
a(around):オブジェクトと周囲の空白/区切り文字を含むi(inner):オブジェクトの内部のみを選択
| オブジェクト | i(inner) | a(around) |
|---|
w | 単語の内部 | 単語 + 周囲の空白 |
W | WORDの内部 | WORD + 周囲の空白 |
s | 文の内部 | 文 + 後続の空白 |
p | 段落の内部 | 段落 + 前後の空行 |
" | "..."の内側 | "..."全体 |
' | '...'の内側 | '...'全体 |
` | `...`の内側 | `...`全体 |
( / ) | (...)の内側 | (...)全体 |
[ / ] | [...]の内側 | [...]全体 |
{ / } | {...}の内側 | {...}全体 |
< / > | <...>の内側 | <...>全体 |
t | XML/HTMLタグの内部 | タグを含む全体 |
| コマンド | 動作 | 例示 |
|---|
diw | カーソル下の単語を削除 | helloの上で → 単語削除 |
daw | カーソル下の単語 + 空白を削除 | 文中の単語を完全に除去 |
ci" | "..."内の内容を変更 | "old" → 引用符を保持して内容を置換 |
ca" | "..."全体を変更 | "old" → 引用符ごと置換 |
di( | (...)内の内容を削除 | 関数の引数をすべて削除 |
da( | (...)全体を削除 | 括弧ごと削除 |
yip | 現在の段落をコピー | 段落全体をコピー |
dap | 現在の段落を削除 | 段落全体を削除 |
vit | HTMLタグ内部をVisual選択 | <div>content</div>のcontentを選択 |
cit | HTMLタグ内部を変更 | タグの内容を置換 |
=i{ | 中括弧内を自動インデント | 関数本体全体を整列 |
>i{ | 中括弧内にインデントを追加 | |
7. コマンドモード(Command-line Mode)
| コマンド | 動作 |
|---|
:w | 保存 |
:w filename | 別名で保存 |
:q | 終了(変更がない場合) |
:q! | 変更を無視して強制終了 |
:wq | 保存して終了 |
:wq! | 強制保存して終了 |
:x | 変更がある場合のみ保存して終了(ZZと同じ) |
ZZ | :xと同じ |
ZQ | :q!と同じ |
:e filename | ファイルを開く |
:e! | 現在のファイルの変更を破棄して再読み込み |
:r filename | ファイルの内容を現在位置に挿入 |
:r !command | コマンドの実行結果を現在位置に挿入 |
| コマンド | 動作 |
|---|
:%s/old/new/g | ファイル全体でoldをnewにすべて置換 |
:%s/old/new/gc | 全体置換、各項目ごとに確認 |
:%s/old/new/gi | 大文字小文字を無視して全体置換 |
:5,20s/old/new/g | 5〜20行目で置換 |
:'<,'>s/old/new/g | Visual選択範囲で置換 |
:%s/\s\+$//e | 行末の空白を除去 |
:%s/^/ / | すべての行の先頭に空白4つを追加 |
| コマンド | 動作 |
|---|
:!command | 外部コマンドを実行(例::!ls -la) |
:!python % | 現在のファイルをPythonで実行 |
:%!command | ファイル全体をcommandの入力として渡し、出力で置換 |
:.!command | 現在行をcommandの入力として渡し、出力で置換 |
:shell | 一時的にシェルに移行(exitで復帰) |
| 範囲表現 | 意味 |
|---|
:5 | 5行目 |
:5,10 | 5行目から10行目 |
:% | ファイル全体(1,$と同じ) |
:. | 現在行 |
:.,$ | 現在行からファイル末尾 |
:'<,'> | Visual選択範囲 |
:.,+5 | 現在行から5行 |
**バッファ(Buffer)**はメモリに読み込まれたファイルである。複数のファイルを同時に開いて編集できる。
| コマンド | 動作 |
|---|
:ls / :buffers | 開いているバッファの一覧を表示 |
:b2 | バッファ2に切り替え |
:bn | 次のバッファに切り替え |
:bp | 前のバッファに切り替え |
:bd | 現在のバッファを閉じる |
:ba | すべてのバッファを分割ウィンドウで開く |
| コマンド | 動作 |
|---|
:sp / :split | 水平分割(horizontal split) |
:vsp / :vsplit | 垂直分割(vertical split) |
:sp filename | ファイルを新しい水平分割で開く |
:vsp filename | ファイルを新しい垂直分割で開く |
<C-w>s | 水平分割(Normal Mode) |
<C-w>v | 垂直分割(Normal Mode) |
<C-w>w | 次のウィンドウにフォーカス移動 |
<C-w>h/j/k/l | 方向でウィンドウ移動 |
<C-w>H/J/K/L | ウィンドウをその方向に移動 |
<C-w>= | すべてのウィンドウサイズを均等化 |
<C-w>+ / <C-w>- | 水平サイズ調整 |
Ctrl-w > / Ctrl-w < | 垂直サイズ調整 |
Ctrl-w _ | 現在のウィンドウを垂直最大化 |
Ctrl-w | | 現在のウィンドウを水平最大化 |
<C-w>q | 現在のウィンドウを閉じる |
<C-w>o | 他のすべてのウィンドウを閉じる(only) |
| コマンド | 動作 |
|---|
:tabnew | 新しいタブを開く |
:tabnew filename | ファイルを新しいタブで開く |
gt | 次のタブに移動 |
gT | 前のタブに移動 |
2gt | タブ2に移動 |
:tabclose | 現在のタブを閉じる |
:tabonly | 他のすべてのタブを閉じる |
:tabs | タブ一覧を表示 |
マクロは一連のキー入力を記録して繰り返し実行する機能である。
| キー | 動作 |
|---|
q{a-z} | レジスタa〜zにマクロ記録を開始 |
q | マクロ記録を終了 |
@{a-z} | レジスタのマクロを実行 |
@@ | 最後に実行したマクロを再実行 |
10@a | レジスタaのマクロを10回繰り返し実行 |
マクロ実践例:CSVの各行の最初のフィールドに引用符を追加
原文: hello,world
目標: "hello",world
1. q a (レジスタaに記録開始)
2. 0 (行の先頭へ移動)
3. i"<Esc> (行の先頭に " を挿入)
4. f, (最初の , へ移動)
5. i"<Esc> (, の前に " を挿入)
6. j (次の行へ移動)
7. q (記録終了)
8. 99@a (残りの行に繰り返し適用)
| レジスタ | 説明 |
|---|
" (unnamed) | デフォルトレジスタ。削除/コピー時に自動使用 |
0 | 最後のyank(コピー)内容 |
1〜9 | 最近の削除/変更内容(循環) |
a〜z | ユーザー指定レジスタ |
A〜Z | 小文字レジスタに追加(append) |
+ | システムクリップボード |
* | Primary selection(Linux X11) |
_ | Black holeレジスタ(削除してもレジスタを汚染しない) |
% | 現在のファイル名 |
: | 最後に実行したコマンド |
/ | 最後の検索パターン |
レジスタの使用例:
"+yy " 現在行をシステムクリップボードにコピー
"+p " システムクリップボードの内容を貼り付け
"_dd " 行を削除するがレジスタを汚染しない
"ayy " レジスタaに現在行をコピー
"Ayy " レジスタaに現在行を追加(append)
:reg
:reg a
set nocompatible
set encoding=utf-8
set fileencoding=utf-8
set number
set relativenumber
set cursorline
set showmatch
set nowrap
set scrolloff=8
set signcolumn=yes
set hlsearch
set incsearch
set ignorecase
set smartcase
set tabstop=4
set shiftwidth=4
set softtabstop=4
set expandtab
set autoindent
set smartindent
set lazyredraw
set updatetime=250
set timeoutlen=300
set hidden
set history=1000
set undolevels=1000
filetype plugin indent on
syntax on
set background=dark
set clipboard=unnamedplus
" set clipboard=unnamed " macOS
set nobackup
set nowritebackup
set noswapfile
set laststatus=2
set ruler
set showcmd
set mouse=a
let mapleader = " "
nnoremap <Leader>w :w<CR>
nnoremap <Leader>q :q<CR>
nnoremap <Leader>wq :wq<CR>
nnoremap <Leader>ev :e ~/.vimrc<CR>
nnoremap <Leader>/ :nohlsearch<CR>
nnoremap <C-h> <C-w>h
nnoremap <C-j> <C-w>j
nnoremap <C-k> <C-w>k
nnoremap <C-l> <C-w>l
nnoremap <A-j> :m .+1<CR>==
nnoremap <A-k> :m .-2<CR>==
vnoremap <A-j> :m '>+1<CR>gv=gv
vnoremap <A-k> :m '<-2<CR>gv=gv
vnoremap < <gv
vnoremap > >gv
tnoremap <Esc> <C-\><C-n>
nnoremap Y y$
nnoremap n nzzzv
nnoremap N Nzzzv
xnoremap <Leader>p
nnoremap <Leader>bn :bnext<CR>
nnoremap <Leader>bp :bprevious<CR>
nnoremap <Leader>bd :bdelete<CR>
curl -fLo ~/.vim/autoload/plug.vim --create-dirs \
https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim
curl -fLo ~/.local/share/nvim/site/autoload/plug.vim --create-dirs \
https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim
call plug#begin('~/.vim/plugged')
Plug 'preservim/nerdtree'
Plug 'junegunn/fzf', { 'do': { -> fzf#install() } }
Plug 'junegunn/fzf.vim'
Plug 'neoclide/coc.nvim', {'branch': 'release'}
Plug 'vim-airline/vim-airline'
Plug 'vim-airline/vim-airline-themes'
Plug 'tpope/vim-fugitive'
Plug 'tpope/vim-surround'
Plug 'tpope/vim-commentary'
Plug 'airblade/vim-gitgutter'
Plug 'morhetz/gruvbox'
call plug#end()
| プラグイン | 機能 | 主要コマンド |
|---|
| NERDTree | ファイルツリーエクスプローラ | :NERDTreeToggle(<C-n>) |
| fzf.vim | ファジーファイル/内容検索 | :Files、:Rg、:Buffers |
| coc.nvim | LSP、自動補完、診断 | gd(定義へ移動)、K(ドキュメント) |
| vim-surround | 括弧/引用符の囲み/変更 | cs"'、ds"、ysiw" |
| vim-commentary | コメントトグル | gcc(行)、gc(Visual) |
| vim-fugitive | Git統合 | :G、:Gblame、:Gdiff |
| vim-gitgutter | 変更のgutter表示 | ]c / [c(hunk移動) |
| vim-airline | 強化されたステータスバー | 自動有効化 |
| gruvbox | レトロカラーテーマ | colorscheme gruvbox |
cs"' → "Hello" を 'Hello' に変更(change surrounding)
cs({ → (Hello) を { Hello } に変更
ds" → "Hello" の引用符を削除(delete surrounding)
ysiw" → カーソル下の単語に "" を追加(you surround inner word)
yss) → 現在行全体を () で囲む
S" → Visual選択範囲を "" で囲む
NeovimはVimと互換性を持ちつつ、以下の利点を提供する。
| 機能 | Vim | Neovim |
|---|
| 設定言語 | Vimscript | Vimscript + Lua |
| 内蔵LSP | なし(プラグイン必要) | 内蔵サポート |
| 非同期API | 限定的 | 完全な非同期 |
| Treesitter | なし | 内蔵サポート |
| 設定ファイル | ~/.vimrc | ~/.config/nvim/init.lua |
| 推奨ディストリビューション | — | LazyVim、AstroNvim、NvChad |
brew install neovim
sudo apt install neovim
sudo dnf install neovim
git clone https://github.com/LazyVim/starter ~/.config/nvim
| カテゴリ | コマンド | 説明 |
|---|
| 脱出 | <Esc> | Normal Modeに復帰 |
| 保存/終了 | :wq | 保存して終了 |
| 強制終了 | :q! | 変更を無視して終了 |
| 移動 | gg / G | ファイルの先頭 / 末尾 |
| 移動 | /pattern | 検索 |
| 移動 | n / N | 次/前の検索結果 |
| 編集 | dd | 行削除 |
| 編集 | yy | 行コピー |
| 編集 | p | 貼り付け |
| 編集 | u | Undo |
| 編集 | <C-r> | Redo |
| 編集 | ciw | 単語を変更 |
| モード | v / V / <C-v> | Visualモード |
| ウィンドウ | <C-w>s / <C-w>v | 分割 |
| 置換 | :%s/old/new/g | 全体置換 |
{回数}{operator}{motion または text object}
例:
3dd → 3行削除
2yy → 2行コピー
d3w → 単語3つ削除
ci" → 引用符内の内容を変更
da( → 括弧ごと削除
>ip → 段落をインデント
| キー | 動作 |
|---|
<C-w> | 前の単語を削除 |
<C-u> | 行頭まで削除 |
<C-h> | 1文字削除(Backspace) |
<C-t> | インデント追加 |
<C-d> | インデント削除 |
<C-r>{reg} | レジスタの内容を挿入 |
<C-r>= | 数式の結果を挿入(例:<C-r>=2+2<CR> → 4) |
<C-o>{cmd} | Normal Modeコマンドを1回実行後Insert Modeに復帰 |
12.4 Command Mode 必須パターン
| コマンド | 説明 |
|---|
:%s/\n/,/g | 改行をカンマに置換 |
:%s/^\s*$\n//g | 空行を除去 |
:%s/\s\+$//e | 行末の空白を除去 |
:%!sort | ファイル全体をソート |
:%!sort -u | ファイル全体をソートして重複を除去 |
:g/pattern/d | patternがある行を削除 |
:v/pattern/d | patternがない行を削除(inverse) |
:g/pattern/y A | patternがあるすべての行をレジスタAにコピー |
この記事で取り上げたコマンドは、:help {command}でVim内からいつでも詳細なドキュメントを確認できる。例::help text-objects、:help registers、:help macros