viを使う 3 (.vimrc / map)

viを使う 2
の続きです。

.vimrcを編集してviの設定をします。

mapを設計します。
方針として、既存のmapは出来るだけ変更しないで、2つのリーダーを使って機能を使い分けるようにしています。

vimのバージョンは7.4と8.0を想定しています。

Macの最初から入っているvim、brewでインストールしたvim、さくらのレンタルサーバーのvimで動作確認しています。
Raspberry Piでも動作すると思います。

既存のmapを確認する 1

最初に、viの既存のmapに空きがほぼ無いことを確認します。一覧を掲載します。
これがviの便利さであり、導入の難しさであると思います。
i、a、A、o、を覚えて、dd、10dd、を覚えて、yy p、10yy pを覚えて、:w、:q、:q!、:qa、:wqを覚えて、:e .を覚えて、と一つずつ覚えていくことになると思います。


"" a : insert mode
"" b : move back word
"" c : change command (cw | ciw | cc | 2cc | c$(=C))
"" d : delete command (dw | diw | dd | 2dd | d$(=D))
"" e : move end of word
"" f : find and move forward (f a|f b|f c|...) (f a ; ; ; ...) (f a ; , ; ...)
"" g : gg(first line) | g;(changes) | g,(changes) | g* | g# | g~w | g~~ | gt(tab) | gT(tab)
"" h : left
"" i : insert mode
"" j : up
"" k : down
"" l : right
"" m : mark current line and position (ma | 'a(line) | `a(position) | mb)
"" n : search next forward
"" o : insert mode
"" p : put the text after the cursor
"" q : macro ('q:' command history)
"" r : replace mode, only one character
"" s : delete one character, begin insert mode
"" t : find and move forward (t a|t b|t c|...) (t a ; ; ; ...) (t a ; , ; ...)
"" u : undo (<-> Ctrl-r)
"" v : visual mode
"" w : move next word
"" x : delete characters after ther cursor (x | 2x)
"" y : yank command (yw | yiw | yy | 2yy | y$(=Y))
"" z : scroll (zz | z. | zt(top) | z<Enter> | zb(bottom) | z-)

"" A : move end of line, insert mode
"" B : move back word (move more than 'b')
"" C : == c$
"" D : == d$
"" E : move end of word (move more than 'e')
"" F : find and move backward (F a|F b|F c|...)
"" G : move last line | move line (1G | 100G)
"" H : move first line on screen
"" I : move ^, insert mode
"" J : join current line with next line
"" K : man
"" L : move last line on screen
"" M : move middle line on screen
"" N : search next backward
"" O : insert mode
"" P : put the text before the cursor
"" Q : ex mode
"" R : replace mode
"" S : == cc
"" T : find and move backward (T a|T b|T c|...)
"" U : undo all latest changes on one line (U undoes a previous U)
"" V : visual mode linewise
"" W : move next word (move more than 'w')
"" X : delete characters before ther cursor (X | 2X)
"" Y : == yy (-> should change map (nnoremap Y y$))
"" Z : (ZZ : == ':x' | ZQ : == ':q!')

"" Ctrl-a : increse integer value
"" Ctrl-b : one page up
"" Ctrl-c : initial state <- command / visual / insert / replace
"" Ctrl-d : half page down
"" Ctrl-e : one line scroll up (<-> Ctrl + y)
"" Ctrl-f : one page down
"" Ctrl-g : show status (file name with path, line number, ...)
"" Ctrl-h : back space
"" Ctrl-i : jump next position (<-> Ctrl + o) | when insert mode, put tab
"" Ctrl-j : move one line down
"" Ctrl-k : (unbound (?))
"" Ctrl-l : reflesh screen
"" Ctrl-m : move to first non-whitespace of next line
"" Ctrl-n : == Ctrl-j | when insert mode, do completion
"" Ctrl-o : jump previos position (<-> Ctrl + i)
"" Ctrl-p : plugin CtrlP | move one line up | when insert mode, do completion
"" Ctrl-q : XON (on UART, make partner to send bytes)
"" Ctrl-r : (ToDo: write simply)
"" Ctrl-s : XOFF (on UART, make partner not to send bytes)
"" Ctrl-t : back tag jump
"" Ctrl-u : half page up
"" Ctrl-v : visual mode
"" Ctrl-w : (ToDo: write simply)
"" Ctrl-x : decrese integer value
"" Ctrl-y : one line scroll down (<-> Ctrl + e)
"" Ctrl-z : vim to back ground process

"" Ctrl-Right : == w
"" Ctrl-Left  : == b

既存のmapを確認する 2

続いて、記号と数字についても確認しておきます。

バックスラッシュはリーダーとして使うことを想定されているようで、スペースは一文字だけ次に進む動作なので不要と判断して(もっと便利な移動の方法がいくらでもある)、この2つをリーダーとして使うことにします。


"" Esc   : normal mode
"" Tab   : == Ctrl + i
"" Space : == l (almost)

"" ` : see 'm'
"" ~ : switching case of character
"" ! : (:!ruby -e | :!ruby % | :!ls | :'<,'>!cat -n)
"" @ : macro
"" # : search backward
"" $ : move
"" % : move ([{}]) /* */ #if, #ifdef, #else, #elif, #endif
"" ^ : move
"" & : repeat previous substitute (:& | : &&)
"" * : search forward
"" ( : move sentences backward
"" ) : move sentences forward
"" _ : move
"" + : move down (+ | 2+)

"" - : move up (- | 2-)
"" = : indent
"" [ : ([# on #endif line -> jump to #ifdef|...)
"" ] : (]# on #ifdef line -> jump to #endif|...)
"" { : move paragraphs backward (=move blank line)
"" } : move paragraphs forward (=move blank line)
"" \ :
"" | : move (10| | 20| | 30|)
"" ; : see 'f' 't'
"" : : command-line mode is used to enter Ex commands
"" ' : see 'm'
"" " : register
"" , : see 'f' 't'
"" . : repeat last change
"" < : indent (<< | 5<< | <5j | <5k)
"" > : indent (>> | 5>> | >5j | >5k)
"" / : search forward
"" ? : search backward

"" 0 : move
"" 1 :
"" 2 :
"" 3 :
"" 4 :
"" 5 :
"" 6 :
"" 7 :
"" 8 :
"" 9 :

.vimrcを編集する 2 : mapの上書き

少しだけ既存のmapを上書きします。

ホームディレクトリの.vimrcを編集します。


% vi ~/.vimrc

.vimrc


"" copy from now position to the end of line -> Y
"" (copy one line -> yy)

nnoremap Y y$
Yを押すと、カーソルから行末までの文字列をヤンクします。


"" enforce show list on ctags

nnoremap <C-]> g<C-]>
ctagsで、複数のジャンプ先があるとき、自動でどれかが選択されてジャンプするのを止めて、必ず全ての候補を表示させます。


" nnoremap <silent> <Space><Space> "zyiw:let @/ = '\<' . @z . '\>'<CR>:set hlsearch<CR>
nnoremap * mz*`z
nmap <silent> <Space><Space> * 
参考にしたホームページの通りです。
スペースキーを2回押すとカーソルがあるところの文字列がハイライトされます。

便利なのですが、自分はこの検索履歴を使いまわしたい場合が多いので、*に対するmapを少しだけ変更しています。
検索履歴を残しつつ、カーソルを移動させた先から戻すようにしています。
自分の場合、場所を記憶させておくのはa/b/cくらいあれば事足りるため、移動前の場所の記憶のためにzを使っています。

用途により、1行目と2-3行目を切り替えて使います。


"" indent for comment in python

inoremap # X<C-h>#
Pythonで実装しているときに、コメント行が行頭に配置されないようにします。


nnoremap <C-e> 3j3<C-e>
nnoremap <C-y> 3k3<C-y>
色々と値を変えて、3に落ち着きました。
自分がスクロールを見失わない最大速度にしています。

.vimrcを編集する 3 : mapを設計する

mapを設計します。

2つのリーダーには、スペースとバックスラッシュを利用しています。
スペースで始まるmapには、色を切り替える、vimgrep、Unite、に対する機能を割り当てています。
バックスラッシュで始まるmapには、コピー & ペースト、画面分割、に対する機能を割り当てています。

.vimrc


nnoremap <Space> <Nop>
nnoremap \ <Nop>
リーダーを無効にしておきます。
nnoremap \ <Nop>の行は無くてもいいと思います。


nnoremap <Space>1 :<C-u>windo set filetype=python<CR>

"" highlight function (in legacy code)

"" white
nnoremap <Space>7 :<C-u>highlight Function ctermfg=255 ctermbg=none cterm=none<CR>

"" red
nnoremap <Space>8 :<C-u>highlight Function ctermfg=161 ctermbg=none cterm=none<CR>

"" back ground red
nnoremap <Space>9 :<C-u>highlight Function ctermfg=255 ctermbg=1    cterm=bold<CR>

"" light green (molokai's default)
nnoremap <Space>0 :<C-u>highlight Function ctermfg=118 ctermbg=none cterm=none<CR>
Spaceキーをリーダーとして、ソースコードの色を変更する設定をしています。
自分の場合、XXXXX.py.001のような名前のPythonソースコードの開発をする場合があるので、Space 1(Spaceを押して離して、1を押して離す)でfiletypeをPythonとして認識して色が変わるようにしています。

7から0は、レガシーコードを追いかけるとき、関数を見逃さないように自分を支援させるための設定です。
7が白、8が赤、9が背景赤、0が緑(molokaiの設定のまま)です。
レガシーコードを追いかけるとき、Space 8、Space 9、として切り替えると作業効率が上がる場合があります。

NetBSDのgrep.cに対して使用した場合はこうなります。関数の定義へのジャンプはctagsを使っています。

関数名の色が切り替わらない場合は、下記からc.vimとcpp.vimを取得して、自分の環境の~/.vim/after/syntax/の下に置くと改善するかもしれません。
Additional Vim syntax highlighting for C++ (including C++11/14/17)


% cd
% cd .vim
% mkdir after
% cd after
% mkdir syntax
% cd syntax
% (cp ~/Downloads/c*vim .)

Macのcpを使うことは避けたいので、Finderを使ってコピーします。
Finderで隠しファイルを表示する、表示しないをトグルするキーボードショットカットは下記です。
shift + command + .


"" Ctrl-f Ctrl-b (Ctrl-d Ctrl-u)

nnoremap <Space><Up> 20<C-y>
nnoremap <Space><Down> 20<C-e>

"" toggle highlight

nnoremap <Space>h :<C-u>set hlsearch!<CR>

nnoremap <Space>c :<C-u>TComment<CR>
vnoremap <Space>c :<C-u>'<,'>TComment<CR>
移動と、ハイライトのトグルと、コメントアウトのトグル、です。

ハイライトのトグルです。
コメントもトグルです。操作を間違えることが非常に少なくなりました。

コメントのトグルはこうなります。Space cをタイプミスすることはまずなく、コメントアウトのトグルは業務上よく発生するので、この設計はとても良かったと思っています。

TCommentについては、viを使う 4で説明します。


"" vimgrep

nnoremap <Space>n :<C-u>cnext<CR>
nnoremap <Space>p :<C-u>cprevious<CR>
nnoremap <Space>N :<C-u>clast<CR>
nnoremap <Space>P :<C-u>cfirst<CR>
vimgrepは便利なのですが、ソースコードが1000万行を超える場合はしばらく待っても結果が出てきません。
grepであたりをつけておいて、10万行未満のディレクトリに移動してvimgrepを実行する場合が多かったです。稀にきちんとした説明がコメントで書かれている場合があり、一気に進捗が出ることもあります。
vimgrepの検索結果が100-200くらいだと心が折れずに作業できました。


"" Unite

nnoremap <Space>f :<C-u>Unite file<CR>:<C-u>set number<CR>
nnoremap <Space>r :<C-u>Unite file_rec<CR>
nnoremap <Space>b :<C-u>Unite buffer<CR>
nnoremap <Space>g :<C-u>Unite grep<CR>
nnoremap <Space>a :<C-u>UniteBookmarkAdd<CR>
nnoremap <Space>m :<C-u>Unite bookmark<CR>
自分はほとんど使っていませんが、Uniteに対するmapの設定です。


nnoremap \v :<C-u>vnew %<CR>

"" Ctrl-w Ctrl-w : move other split window
"" Ctrl-w Ctrl-h : move left split window
"" Ctrl-w Ctrl-l : move right split window

nnoremap \w <C-w><C-w>

nnoremap \h <C-w><C-h>
nnoremap \l <C-w><C-l>

nnoremap \o :<C-u>only<CR>

nnoremap \<Left> :<C-u>vertical resize -2<CR>
nnoremap \<Right> :<C-u>vertical resize +2<CR>

"" (toggle set scrollbind)

"" win do / buf do
nnoremap \s :<C-u>windo set scrollbind!<CR><C-w><C-w>
画面を分割することに関する設定を\をリーダーとしたmapに集めています。
\ vの後、1つのファイルで片方を固定しながら編集する場合もあります。:e .として別のファイルを編集する場合もあります。`0、`1とする場合もあります。Ctrl + oを連続して押す場合もあります。


"" like a double click

nnoremap \\ yiw
nnoremap \p ciw<C-r>0<ESC>
yiwとciw<C-r>0<ESC>をどう割り当てるかは悩みましたが、上記に落ち着いています。
一つの単語をコピーして、ある単語をコピーした文字列で置き換えます。
\ \してpすることもPすることもあります。
ダブルクリックして、Ctrl + c、Ctrl + vすることに感覚的に近いかな、と思って、このmapにしています。

操作を間違えることが非常に少なくなりました。
レガシーコードに少しだけ機能追加するときに非常に役に立ちました。

まとめ

mapを設計しました。

自分が必要を感じたときに付け足していき、整理した内容なので、ほぼ全て多用しています。
レガシーコードと戦うための設定が多くなっています。レガシーコードと戦うための設定は、ctagsとcscopeと一緒に使うことがほぼ前提です。

徹底的に調べたわけでもなく、やりたいことできればOKでやっています。

次は、NeoBundleを使うための設定です。

参考

俺的にはずせない【Vim】こだわりのmap(説明付き)

広告

IT開発関連書とビジネス書が豊富な翔泳社の通販『SEshop』
さくらのレンタルサーバ
ムームードメイン
Oisix(おいしっくす)
らでぃっしゅぼーや
珈琲きゃろっと
エプソムソルト




«       »