Open40

vimのキーバインド

shotakahashotakaha

基本モード

モード名 切り替えキー
normal mode Esc
insert mode i / a / o など
visual mode v / V / C-v
command mode :
replace mode R
select mode gV
ex mode Q
  • 編集の基本は normal ↔︎ insertの切り替え
  • 矩形選択に visual
  • コマンド入力にcommand
  • その他は、あまり使わない
shotakahashotakaha

文字の削除

コマンド 動作
x 1文字を削除する
5x 5文字削除する
dl / dh 1文字削除する
dw 1単語削除する
dd 1行削除する
d$ 行末まで削除する
  • 文字を削除するコマンドはxdの2種類がある
  • xはEmacsのC-dに似ている
  • dは続けて範囲を指定できる
  • どちらのコマンドも削除した文字がレジスタ(")に保存される
shotakahashotakaha

文字のコピー(ヤンク)

コマンド 動作
yl / yh 1文字コピー
yw 1単語コピー
yy 1行コピー
y$ 行末までコピー
  • ydと同じように範囲の指定が必要なコマンド
shotakahashotakaha

文字のペースト

コマンド 動作
p(小文字) カーソルの後にペースト
P(大文字) カーソルの前にペースト
shotakahashotakaha

ヤンク&ペースト

コマンド 動作 Emacs
d$p 行末まで削除 & ペースト C-kC-y or C-SPC C-e C-wC-y
y$p 行末までコピー & ペースト C-SPC C-e M-wC-y
vyp 選択範囲をコピー & ペースト C-SPC カーソル移動 C-wC-y
  • Emacsでよく使う<C-k><C-y>に相当
shotakahashotakaha
コマンド 動作
dwp 1単語削除 & ペースト
ddp 1行削除 & ペースト
ywp 1単語コピー & ペースト
yyp 1行コピー & ペースト
shotakahashotakaha

レジスター

記号 レジスター名
" 無名レジスター
"0 last yanked
"1 - "9 delete history
"a - "z 名前付き
"- small delete
"+ システムのクリップボード
"* X11のクリップボード
"_ black hole
": last command
"= expression
". last inserted text
"/ last search pattern
"% 編集中のファイル名
"# 直前に開いていたファイル
  • dyした内容は"(無名レジスター)に保存される
  • "0は直前にyankした内容が保存される
  • "1 - "9 は削除した内容の履歴
  • "a - "z はユーザーが定義できる
  • "_ は保存されない
shotakahashotakaha

black hole レジスター

nnoremap x "_x
nnoremap X "_X
  • xXで削除した内容はレジスターに保存しなくてもよいことが多いため、black holeに送ってもよい
  • とくにxで削除した文字が"無名レジスターに入ってしまうと、ペーストのときに邪魔になる
shotakahashotakaha

クリップボード統合

set clipboard=unnamedplus
  • 無名レジスター(")がクリップボード("+)に統合される
  • ヤンクした内容が"0"+に保存される
  • 他のアプリでコピーした内容がpでペースト可能になる
  • d"1に保存されるため影響はない
shotakahashotakaha

Emacsキーバインド

  • Emacsキーバインドを割り当てる
  • 基本は次の形
nnoremap Emacsバインド vimバインド
xnoremap Emacsバインド vimバインド
inoremap Emacsバインド <C-o>vimバインド
cnoremap Emacsバインド <C-c>vimバインド 
  • C-oはinsertモードで一時的にnormalモードに抜けるコマンド
  • C-cはcommandモードでコマンドをキャンセルしてnormalモードにするコマンド
shotakahashotakaha

C-a : 行頭に移動

" C-a: beginning of the line
nnoremap <C-a> 0
xnoremap <C-a> 0
inoremap <C-a> <Home>
cnoremap <C-a> <Home>
  • vimには^(空白でない行頭に移動)があるが、使わないことにする

vim操作

  • normal: 0を押す
  • insert: <C-o>0
shotakahashotakaha

C-e : 行末に移動

" C-e: end of the line
nnoremap <C-e> $
xnoremap <C-e> $
inoremap <C-e> <End>
cnoremap <C-e> <End>
shotakahashotakaha

C-n : 次の行に移動

" C-n: next line
nnoremap <C-n> j
xnoremap <C-n> j
inoremap <C-n> <Down>
cnoremap <C-n> <Down>
shotakahashotakaha

C-p: 前の行に移動

" C-p: previous line
nnoremap <C-p> k
xnoremap <C-p> k
inoremap <C-p> <Up>
cnoremap <C-n> <Down>
shotakahashotakaha

C-f: 次の文字に移動

" C-f: forward char
nnoremap <C-f> l
xnoremap <C-f> l
inoremap <C-f> <Right>
cnoremap <C-f> <Right>
shotakahashotakaha

C-b: 前の文字に移動

" C-b: backward char
nnoremap <C-b> h
xnoremap <C-b> h
inoremap <C-b> <Left>
cnoremap <C-b> <Left>
shotakahashotakaha

C-v: 次のページに移動

" C-v: page down
nnoremap <C-v> <PageDown>
xnoremap <C-v> <PageDown>
inoremap <C-v> <PageDown>
cnoremap <C-v> <PageDown>
shotakahashotakaha

M-v: 前のページに移動

" M-v: page up
nnoremap <M-v> <PageUp>
xnoremap <M-v> <PageUp>
inoremap <M-v> <PageUp>
cnoremap <M-v> <PageUp>
  • Meta / Optionキーを使う
shotakahashotakaha

C-s: 前方検索

" C-s: search forward
nnoremap <C-s> /
xnoremap <C-s> /
inoremap <C-s> <Esc>/
cnoremap <C-s> <C-c>/
  • insertモードで<C-o>ではなく<Esc>にしたほうが、そのあと(normalモードで)連続で検索できてよい
shotakahashotakaha

C-r: 後方検索

" C-r: search backward
nnoremap <C-r> ?
xnoremap <C-r> ?
inoremap <C-r> <Esc>?
cnoremap <C-r> <C-c>?
  • <C-r>は insertモードやcommandモードで、レジスターの値を挿入するコマンド
  • そちらをよく使う場合は、この割り当てはしないほうがよいかもしれない
shotakahashotakaha

C-x C-f: ファイルを開く

nnoremap <C-x><C-f> :e<SPACE>
xnoremap <C-x><C-f> :e<SPACE>
inoremap <C-x><C-f> <C-o>:e<SPACE>
cnoremap <C-x><C-f> <C-c>:e<SPACE>
  • C-x C-f:e (:edit)に割り当て
  • <SPACE>まで含めることで、ファイル名をそのまま入力できるようにしてある
shotakahashotakaha

C-x C-s: ファイルを保存する

" C-x C-s: save file
nnoremap <C-x><C-s> :w<CR>
xnoremap <C-x><C-s> :w<CR>
inoremap <C-x><C-s> <C-o>:w<CR>
cnoremap <C-x><C-s> <C-c>:w<CR>
shotakahashotakaha

C-x C-c: ファイルを閉じる

" C-x C-c: close file
nnoremap <C-x><C-c> :q<CR>
xnoremap <C-x><C-c> :q<CR>
inoremap <C-x><C-c> <C-o>:q<CR>
cnoremap <C-x><C-c> <C-c>:q<CR>
  • insertモードではType :qa!というエラーがでてうまくいかないかもしれない
shotakahashotakaha

C-k: 行末までカット

" C-k: kill-line
nnoremap <C-k> d$
xnoremap <C-k> d$
inoremap <C-k> <C-o>d$
cnoremap <C-k> <C-c>d$
  • Emacsでよく使うバインドのひとつ(C-yとセットでよく使う)
  • d$でカットした内容は"(無名レジスター)に保存される
shotakahashotakaha

C-y: ヤンク(ペースト)

" C-y: yank
nnoremap <C-y> p
xnoremap <C-y> p
inoremap <C-y> <C-o>p
cnoremap <C-y> <C-c>p
  • C-k(=d$)した内容は"(無名レジスター)に保存されるのでpでペーストできる
  • 外部のクリップボードの内容も使いたい場合は"+p"(もしくは<C-r>+にするとよい
    • set clipboard=unnamedplusしていればpのままでもOKなはず
" C-y: yank from clipboard
nnoremap <C-y> "+p
xnoremap <C-y> "+p
inoremap <C-y> <C-r>+
cnoremap <C-y> <C-r>+
  • "+p+レジスター(=クリップボード)からペースト
  • <C-r>はnormalモードではredoに割り当てられているので"+pを使う必要がある
  • insertモード、commandモードでは<C-r>のまま使える
shotakahashotakaha

言語表示の設定

set langmenu=en
language messages en
language messages en_US.UTF-8
  • 日本語設定になっているとモード名が「挿入」「置換」などと表示される
  • :language enで「Insert」「Replace」に変更できる
shotakahashotakaha
set langmenu=en
language messages C
  • :language en:language en_US.UTF-8したら「言語にenは設定できません」とエラー
  • :language Cで英語表示に変更できることを確認
  • .vimrcにはlanguage messages Cを追加した
shotakahashotakaha

AddEmacsKey

.vimrc
function! AddEmacsKey(lhs, rhs)
    execute 'nnoremap' lhs rhs
    execute 'xnoremap' lhs rhs
    execute 'inoremap' lhs '<C-o>' . rhs
    execute 'xnoremap' lhs '<C-c>' . rhs
endfunction

" C-x C-f: open file
call AddEmacsKey('<C-x><C-f>', ':e<SPACE>')
  • Emacsのキーを複数のモードにnomapできる関数を作成した
  • function!で関数を定義し、endfunctionで閉じる
  • executeでコマンドを実行する
shotakahashotakaha

autocmd

  • autocmdの設定で特定のイベントが発生したときに自動的にコマンドを実行できる
shotakahashotakaha

ファイルタイプごとの設定

.vimrc
" Python: use 4 spaces for indent
autocmd FileType python setlocal expandtab shiftwidth=4 tabstop=4

" Markdown: enable text wrap
autocmd FileType markdown setlocal wrap
shotakahashotakaha

ファイルの再読み込み

.vimrc
" Reload files edited outside vim editor
autocmd FocusGained,BufEnter * checktime

" Reload specific filetype
autocmd BufEnter *.log checktime
shotakahashotakaha

保存時のメッセージ

.vimrc
" Warn before you leave
autocmd BufLeave,FocusLost * if &modified | echo "File is not saved" | endif
shotakahashotakaha

カーソル位置を復元

.vimrc
autocmd BufReadPost *
  \ if line("'\"") > 0 && line("'\"") <= line("$") |
  \    exe "normal! g`\"" |
  \ endif
shotakahashotakaha

行末の空白を削除

.vimrc
" Remove extra spaces at the end of the line
autocmd BufWritePre * :%s/\s\+$//e
  • BufWritePre: ファイルを保存する直前
  • *: すべてのファイルに適用
    • :s/foo/bar/g: 現在の行にある すべて(g)foobar に置換
    • :%s/foo/bar/g : 現在のファイル(%)すべて(g)foobar に置換
  • :[範囲]s/検索パターン/置換文字列/フラグ
    • [範囲]: %(=全バッファ)を指定
    • 検索パターン: \s\+$ = \s\+$ : \s(空白)、\+(1つ以上)、$行末
    • 置換文字列: なし=削除
    • フラグ: e: エラーを抑制
フラグ 動作
g すべて置換(デフォルトは最初の1つだけ)
c 置換前に確認(yで置換、nでスキップ)
i 大文字・小文字を無視して検索
I 大文字・小文字を区別して検索
e エラーを無視
shotakahashotakaha

ヘルプウィンドウを閉じる

.vimrc
" Close help window with q
autocmd FileType help,qf,man nnoremap <buffer> q :close<CR>
  • helpやquickfixのウィンドウはデフォルトで:q<C-w> qで閉じることができる
  • qで閉じられるようにしておくと便利
  • ただしすべてもモードでは設定したくないのでautocmdでファイル指定(バッファーの種類)を指定する
shotakahashotakaha

ステータスライン

.vimrc
function! GetMode()
    let l:mode = mode()
    highlight StatusLine ctermfg=Grey ctermbg=Black
    
    if l:mode ==# "n"
        highlight StatusLine ctermfg=Red ctermbg=Black
        return "NORMAL"
    elseif l:mode ==# "i"
        highlight StatusLine ctermfg=Green ctermbg=Black
        return "INSERT"
    elseif l:mode ==# "v"
        highlight StatusLine ctermfg=DarkMagenta ctermbg=Black
        return "VISUAL"
    elseif l:mode ==# "V"
        highlight StatusLine ctermfg=DarkMagenta ctermbg=Black
        return "V-LINE"
    elseif l:mode ==# "\<C-v>"
        highlight StatusLine ctermfg=DarkMagenta ctermbg=Black
        return "V-BLOCK"
    elseif l:mode ==# "R"
        return "REPLACE"
    elseif l:mode ==# "c"
        return "COMMAND"
    elseif l:mode ==# "t"
        return "TERMINAL"
    else
        return "UNKNOWN"
    endif
endfunction

set showmode    " Show status line
set laststatus=2    " Always show status line
set showcmd    " Show command at status line
set statusline=%#StatusLine#\ [%{GetMode()}]\ %F%m\ \(%l,%c\)[%p%%\ %LL]%<%=%r%h%w%y[%{&fileencoding}][%{&fileformat}]%=[b=%n][t=%{&tabstop}][i=%{&shiftwidth}]
  • モードごとに表示名と色を変更できる
  • デフォルトのモード名はn/i/v/V/cのように省略形
shotakahashotakaha

モードと色の設定

  • GetMode()関数では次のように色を設定している
  • モードごとに色を変更できるようにしてある
  • また、万が一、モードを取得できない場合にはUNKNOWNと表示されるようにしてある
モード 表示名
n NORMAL Red (編集NGの意味)
i INSERT Green (編集OKの意味)
v VISUAL DarkMagenta
V V-LINE DarkMagenta
V-BLOCK DarkMagenta
r REPLACE Yellow
c COMMAND Cyan
t TERMINAL Blue
else UNKNOWN
shotakahashotakaha

ローカル変数と比較演算子

  • l:mode
    • l:はローカル変数であることを表すprefix
    • mode()の戻り値をl:modeに格納している
  • ==#
    • 大文字と小文字を区別する比較演算子
演算子 大文字・小文字の区別
== 区別しない
==# 区別する
==? 区別しない(==と同じ)