はじめに
Vimにはデフォルトで補完機能が備わっている. 実践Vim 思考のスピードで編集しよう!であったり,daisuzuさんの2015年のVim Advent Calendarの記事VimのCTRL-X補完について - daisuzu's notesを読むと,neocompleteやdeopleteに頼るだけではなく,デフォルトの補完機能を活用したいと考えるようになるものである.
しかし, ins-completion
を見るとわかるように,Vimの <C-x>
から始まる補完は12種類もあり,初めのうちはとても覚えきれるものではない.
そこで,この記事では, <C-x>
補完初心者が使いこなせるようになるまでのヒント表示キーマッピングを考えた.
ins-completion
まずは,補完にはどのような種類があるかを簡単にまとめる.
以下の表は ins-completion
の内容と同じなので,先程見た人は無視してよい.
キーマッピング | 補完 | 必須オプション |
---|---|---|
<C-X><C-l> |
行全体 | |
<C-X><C-n> , <C-X><C-n> |
現在のファイルのキーワード | |
<C-X><C-k> |
'dictionary' のキーワード |
'dictionary' |
<C-X><C-t> |
'thesaurus' のキーワード |
'thesaurus' |
<C-X><C-i> |
編集中と外部参照(インクルード)しているファイルのキーワード | |
<C-X><C-]> |
タグファイル('tags' で設定したパスで見つかるファイル) |
|
<C-X><C-f> |
ファイル名 | |
<C-X><C-d> |
定義もしくはマクロ | |
<C-X><C-v> |
Vimのコマンドライン | |
<C-X><C-u> |
ユーザ定義補完 | 'completefunc' |
<C-X><C-o> |
オムニ補完 | 'omnifunc' |
<C-X>s , <C-X><C-s> |
スペリング補完 | 'spell' |
<C-n> , <C-p> |
'complete' のキーワード |
この内, <C-n>
, <C-p>
は <C-x>
の先行入力を伴わないので,ヒント表示の対象から外す.
ヒント表示キーマッピング
とにかく,以下のようにしただけという話.
" 入力キーの辞書 let s:compl_key_dict = { \ char2nr("\<C-l>"): "\<C-x>\<C-l>", \ char2nr("\<C-n>"): "\<C-x>\<C-n>", \ char2nr("\<C-p>"): "\<C-x>\<C-p>", \ char2nr("\<C-k>"): "\<C-x>\<C-k>", \ char2nr("\<C-t>"): "\<C-x>\<C-t>", \ char2nr("\<C-i>"): "\<C-x>\<C-i>", \ char2nr("\<C-]>"): "\<C-x>\<C-]>", \ char2nr("\<C-f>"): "\<C-x>\<C-f>", \ char2nr("\<C-d>"): "\<C-x>\<C-d>", \ char2nr("\<C-v>"): "\<C-x>\<C-v>", \ char2nr("\<C-u>"): "\<C-x>\<C-u>", \ char2nr("\<C-o>"): "\<C-x>\<C-o>", \ char2nr('s'): "\<C-x>s", \ char2nr("\<C-s>"): "\<C-x>s" \} " 表示メッセージ let s:hint_i_ctrl_x_msg = join([ \ '<C-l>: While lines', \ '<C-n>: keywords in the current file', \ "<C-k>: keywords in 'dictionary'", \ "<C-t>: keywords in 'thesaurus'", \ '<C-i>: keywords in the current and included files', \ '<C-]>: tags', \ '<C-f>: file names', \ '<C-d>: definitions or macros', \ '<C-v>: Vim command-line', \ "<C-u>: User defined completion ('completefunc')", \ "<C-o>: omni completion ('omnifunc')", \ "s: Spelling suggestions ('spell')" \], "\n") function! s:hint_i_ctrl_x() abort echo s:hint_i_ctrl_x_msg let c = getchar() return get(s:compl_key_dict, c, nr2char(c)) endfunction inoremap <expr> <C-x> <SID>hint_i_ctrl_x()
途中で :echo
した上でキー入力待ち状態を作るには, <expr>
を活用するのがよい.
上記のキーマッピングを行うと,以下のようになる.
これで,補完を行おうとしたときに「あの補完はどの <C-x>
の後にどのキーを押下すればよかったんだっけ?」とならず,とりあえず <C-x>
を押下してみて,「お~このキーであの補完ができるんだった!」となるのではないかと思う.
もちろん,これは <C-x>
補完に不慣れな人向けのキーマッピングである.
いちいち,複数行の :echo
が表示されるのは,常用するレベルになると鬱陶しいことこの上ないだろう.
慣れるまではヒント表示を使い,慣れた頃に .vimrc
から削除するのがよいと思われる.
おまけ
本記事におけるヒントの表示は,レジスタ内容やマーク位置の表示にも応用できるのではないかと思い,以下のキーマッピングを考えた.
function! s:hint_cmd_output(prefix, cmd) abort redir => str execute a:cmd redir END echo str return a:prefix . nr2char(getchar()) endfunction " カーソル位置のマーク nnoremap <expr> m <SID>hint_cmd_output('m', 'marks') " マーク位置へのジャンプ nnoremap <expr> ` <SID>hint_cmd_output('`', 'marks') " マーク位置へのジャンプ nnoremap <expr> ' <SID>hint_cmd_output("'", 'marks') " レジスタ参照(ヤンクや削除) nnoremap <expr> " <SID>hint_cmd_output('"', 'registers') " マクロ記録 nnoremap <expr> q <SID>hint_cmd_output('q', 'registers') " マクロ再生 nnoremap <expr> @ <SID>hint_cmd_output('@', 'registers')
これらは次のようにヒントを表示する.
まずは,マークの例.
次に,ヤンクや削除時のレジスタ指定.
4"ayy
のような行数指定を行っても問題ない.
まとめ
この記事では,VimのCtrl-X補完を使いこなせるようになるための初心者練習用ヒント表示のキーマッピングを紹介した.
また,ヒント表示を応用して,マークやレジスタの内容を表示するキーマッピングも紹介した.
あくまで初心者向けのキーマッピングであり,熟達するにつれて,ヒント表示がだんだん鬱陶しくなると思う.
その頃に,この記事で紹介したキーマッピングを .vimrc
から削除し,よりスパルタンを目指すとよいだろう.