ゆず日記

戦う Vimmer 兼 Dvorakユーザ 兼 Kinesisユーザ 兼 おぺらー が戦わないブログ

ボクが2ヶ月間で学んだVimのまとめ

続編書きました ボクが1年間で学んだVimのまとめ - ゆず日記


年末に会社の開発環境を思い切ってWindowsからLinux Mint(Ubuntu)に換えて早2ヶ月。
併せて本気でVimを使い込んでみようと、メインエディタもAptana StudioからVimへ。

VimかわいいよVim

インストール

基本的な操作

これは先人が数多く居るので割愛。
ここが非常に分り易いです。Vim 基本操作まとめ - Archiva

個人的な所感として、以下のコマンドを覚えておけば他のエディタで出来ることと同等のことはすぐ出来るようになるかと。
他のエディタと比較して気をつけるべきこととしては、ddやらxやらの削除系のコマンドでもバッファにコピーされること。頻繁に呼び出したいと思うものは"ayyや"b5yyなどでラベル("の次の文字)を付けたバッファに格納して置くように。



移動関連

hjkl 移動
c-u,c-d,c-f,c-b ページ単位移動
w,b,e,0,$ 単語毎、または行頭、行末の移動
1G, 100G,G 1行目、 100行目、最終行へ移動

コピペ関連

yy 行をバッファにコピー
5yy 5行をコピー
"a5yy 5行をaというバッファにコピー
p バッファの内容をペースト
10p バッファの内容を10回ペースト
"ap aというバッファに格納された内容をペースト
dd 行を削除(バッファに格納)
dw 1単語削除(バッファに格納)
x 1文字削除(バッファに格納)

モード切り替え関連

i 挿入モードへ
cw フォーカスされている単語を削除して挿入モードへ
r 1文字だけ置換モードへ、入力後自動でノーマルモードへ戻る
Esc ノーマルモードへ戻る

検索関連

/文字列 文字列を検索
n, N 次の文字列をフォーカス、前の文字列をフォーカス
:%s/検索文字列/置換文字列/g ファイル内の検索文字列を置換文字列へ変換
:%s//置換文字列/g 前回検索した文字列を置換文字列へ置換


保存関連

:w 保存
:w filename filenameに保存
:q 終了
:q! 現在の変更を破棄して終了


大体上記のコマンドさえ覚えて置けば何とかなるかと。
特に、「5行コピーして10回ペースト(5yy10p)」などの処理は他のエディタではまず出来ないので、慣れればVimの良さが実感できると思います。
もちろん、他にもまだまだコマンドは沢山あるので、それらもマスターすればさらにいろいろな作業もお手軽に実行できます。


以下は知ってたらなお便利というコマンド。
画面分割関連

:e filename 現在のバッファに新しいファイルを表示
:e # 現在のバッファに一つ前に開いていたファイルを表示
:vsp filename 縦に分割して新しいファイルを表示
:sp filename 横に分割して新しいファイルを表示
c-w c-w 別のバッファへ移動
c-w 10>[<,+,-] 現在のバッファを右[左, 上, 下]に10行(文字)拡張
:q 現在のバッファを閉じる

なお、filenameを省略すると現在のファイルを分割されたバッファにも展開します。


シェルコマンド実行

:! <シェルコマンド> シェルコマンドを実行する。

(:!以降のコマンドを、シェルコマンドとして処理出来る。)

vimgrep

vimには標準でgrep機能が付いています。

:vim <検索文字列> *.js | cwin フォルダ内の、jsファイルの中から検索文字列を含む行をgrep
:vim <検索文字列> **/*.js | cwin サブフォルダを含めた、jsファイルの中から検索文字列を含む行をgrep

詳しいコトはこちらVimでGrepする覚え書き 1/2 「内部grep」編 - ナレッジエース

vimdiffで比較

WindowsにはWinMerge 日本語版という便利なdiff & mergeツールがあるけど、LinuxにはそこまでGUIに特化したツールはありません。
けれど、実はVimにもvimdiffという比較方法があって、

vimdiff filename1 filename2

で比較が出来ます。

ファイルを開いている最中から実行するのであれば、

:vertical diffsplit filename

で比較開始。

比較すると、こんな感じ。差分が自動的に色分けされて表示されます。


差分のコピーや取り込みは、以下のコマンドで、

do 他のバッファから、現在のバッファにコピー
dp 現在のバッファから、他のバッファにコピー

もちろん、5yyなどでバッファにコピーした後に、c-w,c-wで別のバッファに移動してpで5行挿入なんてのも可能です。

なお、行レベルの変更は自動反映されますが、単語レベルの変更は自動反映されません。
その場合、手動で差分情報の更新をする必要がありますので、

:diffu
または
:diffupdate

を実行します。

vimdiff filename1 filename2 filename3
gvimdiff filename1 filename2

応用として、3つのファイルの比較や、gvimでのdiffも可能。

3つのファイルの比較時の画像


詳しくは、『Vim documentation: diff: http://www.ac.cyberhome.ne.jp/~yakahaira/vimdoc/diff.html 』で。
また、Mac環境でWinMerge相当の比較ツールといえば、xcode内蔵の比較ツール位しかありませんが、vimdiffがあれば各種文字コードにこだわらずに気軽に比較が出来るのでMacユーザにもオススメです。

VimgVimどちらを使うべき?

ターミナル上で動作するVimとグラフィカルに動作するgVim。両者の比較をすると、
Vim

  • ターミナル上で呼び出せる
  • レンダリングが遅い
  • シェルコマンドの実行が速い
  • ○や□が綺麗に表示されない、または正しく文字数がカウントされない。

gVim

  • ターミナルとは別に呼び出される
  • レンダリングが速い
  • シェルコマンドの実行が遅い
  • ○や□が綺麗に表示される。文字数も正しくカウントされる。

一長一短だとは思うのですが、自分は今まで何となくVimを1ヶ月以上使っていたけれど、レンダリング処理の多いプラグインを使用することからもgVimへ移行。
軽い作業や、シェルコマンドを多様する編集の際にのみVimを使用するというスタンスへなりました。
特に、後述のneocomplcacheプラグインの動作がVimgVimでは明らかに動作速度が異なりgVimの方が速いです。

.vimrc

ここら辺から本番。
.vimrcで初期設定の変更が出来ます。以下は自分の.vimrc。

" Common -------------------------------
set nocompatible				" vim
colorscheme metroid			" カラースキームの設定
set background=light			" 背景色の傾向(カラースキームがそれに併せて色の明暗を変えてくれる)

" File ---------------------------------
set autoread				" 更新時自動再読込み
set hidden				" 編集中でも他のファイルを開けるようにする
set noswapfile				" スワップファイルを作らない
set nobackup				" バックアップを取らない
autocmd BufWritePre * :%s/\s\+$//ge	" 保存時に行末の空白を除去する
syntax on				" シンタックスカラーリングオン

" Indent -------------------------------
" tabstop:				Tab文字を画面上で何文字分に展開するか
" shiftwidth:				cindentやautoindent時に挿入されるインデントの幅
" softtabstop:				Tabキー押し下げ時の挿入される空白の量,0の場合はtabstopと同じ,BSにも影響する
set tabstop=4 shiftwidth=4 softtabstop=0
set autoindent smartindent		" 自動インデント,スマートインデント

" Assist imputting ---------------------
set backspace=indent,eol,start		" バックスペースで特殊記号も削除可能に
set formatoptions=lmoq			" 整形オプション,マルチバイト系を追加
set whichwrap=b,s,h,s,<,>,[,]		" カーソルを行頭、行末で止まらないようにする
"set clipboard=unnamed,autoselect		" バッファにクリップボードを利用する

" Complement Command -------------------
set wildmenu				" コマンド補完を強化
set wildmode=list:full			" リスト表示,最長マッチ

" Search -------------------------------
set wrapscan				" 最後まで検索したら先頭へ戻る
set ignorecase				" 大文字小文字無視
set smartcase				" 大文字ではじめたら大文字小文字無視しない
set incsearch				" インクリメンタルサーチ
set hlsearch				" 検索文字をハイライト

" View ---------------------------------
set showmatch				" 括弧の対応をハイライト
set showcmd				" 入力中のコマンドを表示
set showmode				" 現在のモードを表示
set number				" 行番号表示
set nowrap				" 画面幅で折り返さない
set list					" 不可視文字表示
set listchars=tab:>\ 			" 不可視文字の表示方法
set notitle				" タイトル書き換えない
set scrolloff=5				" 行送り
set display=uhex				" 印字不可能文字を16進数で表示

hi ZenkakuSpace gui=underline guibg=DarkBlue cterm=underline ctermfg=LightBlue " 全角スペースの定義
match ZenkakuSpace / / 			" 全角スペースの色を変更

set cursorline				" カーソル行をハイライト
augroup cch
	autocmd! cch
	autocmd WinLeave * set nocursorline
	autocmd WinEnter,BufRead * set cursorline
augroup END
:hi clear CursorLine
:hi CursorLine gui=underline
hi CursorLine ctermbg=black guibg=black


" StatusLine ---------------------------
set laststatus=2				" ステータスラインを2行に
set statusline=%<%f\ #%n%m%r%h%w%{'['.(&fenc!=''?&fenc:&enc).']['.&ff.']'}%y%=%l,%c%V%8P

" Charset, Line ending -----------------
set termencoding=utf-8
set encoding=utf-8
set fileencodings=utf-8,cp932,euc-jp,iso-2022-jp
set ffs=unix,dos,mac			" LF, CRLF, CR
if exists('&ambiwidth')
	set ambiwidth=double		" UTF-8の□や○でカーソル位置がずれないようにする
endif



" --------------------------------------
"              my config
" --------------------------------------
" When insert mode, enable hjkl and enable go to home/end.
imap <c-o> <END>
imap <c-a> <HOME>
imap <c-h> <LEFT>
imap <c-j> <DOWN>
imap <c-k> <UP>
imap <c-l> <Right>

" When insert mode, change statusline.
let g:hi_insert = 'hi StatusLine gui=None guifg=Black guibg=Yellow cterm=None ctermfg=Black ctermbg=Yellow'

if has('syntax')
  augroup InsertHook
    autocmd!
    autocmd InsertEnter * call s:StatusLine('Enter')
    autocmd InsertLeave * call s:StatusLine('Leave')
  augroup END
endif

let s:slhlcmd = ''
function! s:StatusLine(mode)
  if a:mode == 'Enter'
    silent! let s:slhlcmd = 'highlight ' . s:GetHighlight('StatusLine')
    silent exec g:hi_insert
  else
    highlight clear StatusLine
    silent exec s:slhlcmd
  endif
endfunction

function! s:GetHighlight(hi)
  redir => hl
  exec 'highlight '.a:hi
  redir END
  let hl = substitute(hl, '[\r\n]', '', 'g')
  let hl = substitute(hl, 'xxx', '', '')
  return hl
endfunction


" for Opera ----------------------------
" opera -remote \"openURL()\"
function! s:ExecOpera()
	exe "! opera -remote \"openURL(%)\""
:endfunction
command! Exec call <SID>ExecOpera()
nmap <c-p> :call <SID>ExecOpera()<CR>


" for Python ---------------------------
filetype plugin on
autocmd Filetype python setl autoindent
autocmd FileType python setl smartindent cinwords=if,elif,else,for,while,try,except,finally,def,class
autocmd FileType python setl tabstop=4 shiftwidth=4 softtabstop=0

" Execute python script C-P
function! s:ExecPy()
	exe "!" . &ft . " %"
:endfunction
command! Exec call <SID>ExecPy()
autocmd FileType python map <silent> <c-p> :call <SID>ExecPy()<CR>

ちょっと解説。
上の方のset 〜 は基本的にコメント通り。
「When insert mode, enable hjkl and enable go to home/end」 は、挿入モードでも各キーで移動が出来るようにする設定。
「When insert mode, change statusline」は、挿入モード時と通常モード時のステータスラインの色を変更する設定。
「for Opera」は、現在開いているファイルをOperaで開いてくれるコマンドの設定。htmlを作っている時に便利。*1Opera's Command Line Options
「for Python」は、現在開いているファイルをPythonで実行してくれるコマンドの設定。他の言語でも同様のことが出来ます。


.gvimrc

gVim専用の設定です。各環境でディスプレイサイズや適用可能な設定が異なりますので、それに応じて設定を変更します。

colorscheme Metroid

set background=dark

if has('mac')
	set transparency=30	" opacity
	set guifont=Monaco:h14	" font
	set columns=150		" width
	set lines=200		" line
else
	set guifont=Monaco\ 12
	set columns=160
	set lines=100
endif

set mouse=a			" どのモードでもマウスを利用可能に
set nomousefocus		" マウス移動によるフォーカス切り替えを無効

プラグイン

以下のプラグインをインストールすると何かと便利なので、上記の設定を適用する場合には以下も入れちゃいましょう。

まったく関係ありませんが、Shougoさんのスライドには何かと惹かれるものがあります。


上記のプラグイン用の設定も.vimrcに設定します。自分はさっきの.vimrcに以下の設定も追加してます。

" for Plugin ---------------------------
" for zen-coding c-eでzen-coding実行
let g:user_zen_expandabbr_key = '<c-e>'

" for NERDCommenterToggle c-oでコメントアウト・コメント
let g:NERDCreateDefaultMappings = 0
let NERDSpaceDelims = 1
nmap <c-o> <Plug>NERDCommenterToggle
vmap <c-o> <Plug>NERDCommenterToggle

" for neocomplcache 自動補完を有効
let g:neocomplcache_enable_at_startup = 1

" for unite.vim unite.vimに各パスを追加
let g:unite_update_time = 1000
call unite#set_substitute_pattern('file', '\$\w\+', '\=eval(submatch(0))', 200)

call unite#set_substitute_pattern('file', '[^~.]\zs/', '*/*', 20)
call unite#set_substitute_pattern('file', '/\ze[^*]', '/*', 10)

call unite#set_substitute_pattern('file', '^@@', '\=fnamemodify(expand("#"), ":p:h")."/*"', 2)
call unite#set_substitute_pattern('file', '^@', '\=getcwd()."/*"', 1)
call unite#set_substitute_pattern('file', '^\\', '~/*')

call unite#set_substitute_pattern('file', '^;v', '~/.vim/*')
call unite#set_substitute_pattern('file', '^;r', '\=$VIMRUNTIME."/*"')

call unite#set_substitute_pattern('file', '\*\*\+', '*', -1)
call unite#set_substitute_pattern('file', '^\~', escape($HOME, '\'), -2)
call unite#set_substitute_pattern('file', '\\\@<! ', '\\ ', -20)
call unite#set_substitute_pattern('file', '\\ \@!', '/', -30)

上記の設定を有効にすると、こんな感じになります。
特にneocomplcacheの候補機能は素晴らしいです。


カラースキーム

ここまでカスタマイズしたら色設定まで!
カラースキームファイルを設定することで、Vimの各種配色を設定できるので自分で作成。
ここいらはカスタマイズ大好きおぺらーの血かも知れません。

" Vim color file
" Maintainer:   yuzuemon

set background=dark
hi clear
if exists("syntax_on")
  syntax reset
endif
let g:colors_name = "Metroid"

" テキスト
hi Normal gui=NONE guifg=White guibg=Black			" 通常
hi NonText guifg=LightBlue ctermfg=LightBlue			" EOF以降の~など
hi Comment gui=Italic guifg=LightGreen cterm=Italic ctermfg=LightGreen	" コメント
hi Statement gui=Bold guifg=Magenta cterm=Bold ctermfg=Magenta	" 命令、分岐
hi Identifier gui=Bold guifg=Green cterm=Bold ctermfg=Green	" 関数、識別子
hi PreProc gui=Bold guifg=Yellow cterm=Bold ctermfg=Yellow	" プリプロセッサメソッド
hi Type gui=Bold guifg=Cyan cterm=Bold ctermfg=Cyan		" 型(クラス、構造体)
hi Constant gui=Bold guifg=LightBlue cterm=Bold ctermfg=LightBlue	" 定数(文字列、文字、数、Boolean)
hi Special gui=Bold guifg=LightBlue cterm=Bold ctermfg=LightBlue	" 特殊記号
hi Conditional gui=Bold guifg=Yellow cterm=Bold ctermfg=Yellow	" if, not
hi Repeat gui=Bold guifg=Yellow cterm=Bold ctermfg=Yellow		" for
hi Exception gui=Bold guifg=Yellow cterm=Bold ctermfg=Yellow	" try

" テキスト状態
hi Visual guibg=Blue ctermbg=Blue					" アクティブ選択範囲
hi VisualNOS guibg=DarkBlue ctermbg=DarkBlue			" 非アクティブな選択範囲
hi Search gui=Bold guifg=White guibg=Magenta cterm=Bold ctermfg=White ctermbg=Magenta	" 検索文字列
hi IncSearch gui=Reverse,Bold cterm=Reverse,Bold			" インクリメンタル中の検索文字列
hi Folded guibg=DarkGray ctermbg=DarkGray			" 折りたたまれた行
hi FoldColumn guibg=DarkGray ctermbg=DarkGray			" フォールドカラム

" diff
hi DiffAdd guibg=DarkMagenta ctermbg=DarkMagenta				" 片側にある行
hi DiffDelete guifg=Black guibg=LightMagenta ctermfg=Black ctermbg=LightMagenta		" 片側にない行
hi DiffText guibg=DarkGreen ctermfg=Black ctermbg=DarkGreen			" 差異のある箇所
hi DiffChange guibg=Gray30 ctermbg=DarkCyan ctermfg=White			" 変更箇所

" ポップアップメニュー(未整理)
hi Pmenu ctermbg=lightcyan ctermfg=black
hi PmenuSel ctermbg=blue ctermfg=black
hi PmenuSbar ctermbg=darkgray
hi PmenuThumb ctermbg=lightgray

" その他
hi LineNr gui=NONE guifg=Green cterm=NONE ctermfg=Green				" 行番号
hi VertSplit gui=NONE guifg=Black guibg=Cyan cterm=NONE ctermfg=Black ctermbg=Cyan	" :vspの境界線

" ステータスライン
hi StatusLine gui=NONE guifg=Black guibg=Green cterm=NONE ctermfg=Black ctermbg=Blue	" アクティブなステータスライン
hi StatusLineNC gui=NONE guifg=Black guibg=Green cterm=NONE ctermfg=Black ctermbg=Blue	" 非アクティブなステータスライン
hi Question gui=NONE guifg=Black guibg=Yellow cterm=NONE ctermfg=Black ctermbg=Yellow	" プロンプトメッセージ
hi ModeMsg gui=NONE guifg=Green cterm=NONE ctermfg=Green				" --挿入--とかのメッセージ
hi MoreMsg gui=NONE guifg=Magenta cterm=NONE ctermfg=Magenta			" --継続--メッセージ
hi WarningMsg gui=NONE guifg=Yellow cterm=NONE ctermfg=Yellow				" 警告メッセージ
hi ErrorMsg gui=NONE guifg=White guibg=Magenta cterm=NONE ctermfg=White ctermbg=Magenta	" エラーメッセージ
gui, cterm gVim, vimの文字書体
guifg, ctermbg gVim, vimの文字色
guibg, ctermbg gVim, vimの背景色

なお、:hiコマンドでどのフォーマットが何色なのか確認出来ます。


上記ファイルを~/.vim/color/<カラースキーム名>.vimとして保存します。
保存したカラースキームを.vimrcに以下の行を追加して読みこめばカラースキームが適用されます。

colorscheme カラースキーム名

カラースキーム名は、カラースキームのファイル名ではなく、以下の定義部分になるので、ファイル名とg:colors_nameは一致させて登録する必要があります。(2012/03/17 修正)

let g:colors_name = "metroid" # <カラースキーム名>と同じ名前

緑とマゼンタのコントラストが美しくて何となくこんな名前になりました。


実際に適用した所。
Mac/gVim

Linux/gVim

環境によって発色が変わるのはターミナルのカラー設定の所為。


う〜ん。大体こんな感じかな。
使って1年後位にまた纏めてみます。

*1:更新コマンドがあれば尚いいのですが…。