読者です 読者をやめる 読者になる 読者になる

VimのCTRL-X補完について

vim

この記事はVim Advent Calendar 2015の5日目の記事です。

Vimで補完といえばShougoさんのプラグインneocompleteが有名ですが、プラグインを使わなくてもCTRL-X サブモードで補完を行うことが可能です。
この機能はブログや書籍などでたびたび紹介されてはいますが、文字だけではイメージがつきにくいところもあるのでGIFアニメで紹介してみたいと思います。


行(全体)補完: CTRL-X CTRL-L

if から始まる行と l から始まる行を補完(go)

f:id:daisuzu:20151205000331g:plain

検索対象はcompleteオプションで設定可能


局所キーワード補完: CTRL-X CTRL-N / CTRL-X CTRL-P

現在のファイルから T で始まるキーワードを補完(perl)

f:id:daisuzu:20151205000332g:plain


辞書補完: CTRL-X CTRL-K

dictionaryオプションで設定したファイルから twist で始まる単語を補完

f:id:daisuzu:20151205000322g:plain

dictionaryオプションに使用するファイルを設定する必要がある(デフォルトは未設定)

set dictionary=/usr/share/dict/words

シソーラス補完: CTRL-X CTRL-T

thesaurusオプションで設定したファイルから twister の類語を補完

f:id:daisuzu:20151205000329g:plain

thesaurusオプションに使用するファイルを設定する必要がある(デフォルトは未設定)

set thesaurus=/usr/share/mythes/th_en_US_v2.dat

パスパターン補完: CTRL-X CTRL-I

インクルードしているSocket.pmから getpr で始まるキーワードを補完(perl)

f:id:daisuzu:20151205000325g:plain

検索対象はincludeオプションとpathオプションで設定可能


タグ補完: CTRL-X CTRL-]

tagsファイルからクラス名とメソッド名を補完(ruby)

f:id:daisuzu:20151205000328g:plain

読み込むtagsファイルはtagsオプションで設定可能


ファイル名補完: CTRL-X CTRL-F

/etc/y から始まるファイル名を補完

f:id:daisuzu:20151205000323g:plain


定義補完: CTRL-X CTRL-D

mixinを補完(sass)

f:id:daisuzu:20151205000321g:plain

検索対象はdefineオプションとincludeオプションとpathオプションで設定可能


コマンドライン補完: CTRL-X CTRL-V

vimのコマンドと関数を補完

f:id:daisuzu:20151205000330g:plain


ユーザー定義補完: CTRL-X CTRL-U

completefuncオプションに設定したCompleteMonthsで月の名前を補完

f:id:daisuzu:20151205000324g:plain

fun! CompleteMonths(findstart, base)
  if a:findstart
    " 単語の始点を検索する
    let line = getline('.')
    let start = col('.') - 1
    while start > 0 && line[start - 1] =~ '\a'
      let start -= 1
    endwhile
    return start
  else
    " "a:base" にマッチする月を探す
    let res = []
    for m in split("Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec")
      if m =~ '^' . a:base
        call add(res, m)
      endif
    endfor
    return res
  endif
endfun

オムニ補完: CTRL-X CTRL-O

omnifuncオプションに設定されたjavascriptcomplete#CompleteJSでDate型のメソッドを補完(javascript)

f:id:daisuzu:20151205000326g:plain


スペリング補完: CTRL-X s / CTRL-X CTRL-S

頭文字が大文字になっていない単語と綴りが間違っている単語の修正候補を補完

f:id:daisuzu:20151205000327g:plain

spellオプションをオンにする必要がある


上記環境はDocker上のcentos6に以下のパッケージをインストールしたものです。
プラグインは一切インストールしておらず、vimrcも作成していません。

yum install vim-enhanced ctags words mythes-en

CTRL-X サブモード について

順序が逆転してしまいましたが、CTRL-X サブモード挿入モードまたは置換モード中にCTRL-Xキーで入ることができます。

ポップアップメニューの補完候補はCTRL-N(次の候補)またはCTRL-P(前の候補)キーで選択し、CTRL-Yキーやスペース、エンターなどで挿入することができます。
また、CTRL-Eキーで補完を中止して元のテキストに戻すことができます。


最近neocompleteが入っていないVimを触ることがちょこちょことあり、ここ1週間くらいはメインのVimでもneocompleteを使わずに過ごしてみました。
昔は自動補完プラグインが無いとコーディングなんてできない...とか思っていましたがそこまで困らないくらいには成長していたようです。
ただ、CTRL-Xキーがイマイチ押しにくいと感じているのでこれさえなんとかなれば自動補完プラグインは使わなくなるかもしれません。
今はこんなマッピングを試してみています。

inoremap <expr><Tab> pumvisible() ? "\<C-n>" : MyInsCompl()
function! MyInsCompl()
  let c = nr2char(getchar())
  if c == "l"
    return "\<C-x>\<C-l>"
  elseif c == "n"
    return "\<C-x>\<C-n>"
  elseif c == "p"
    return "\<C-x>\<C-p>"
  elseif c == "k"
    return "\<C-x>\<C-k>"
  elseif c == "t"
    return "\<C-x>\<C-t>"
  elseif c == "i"
    return "\<C-x>\<C-i>"
  elseif c == "]"
    return "\<C-x>\<C-]>"
  elseif c == "f"
    return "\<C-x>\<C-f>"
  elseif c == "d"
    return "\<C-x>\<C-d>"
  elseif c == "v"
    return "\<C-x>\<C-v>"
  elseif c == "u"
    return "\<C-x>\<C-u>"
  elseif c == "o"
    return "\<C-x>\<C-o>"
  elseif c == "s"
    return "\<C-x>s"
  endif
  return "\<Tab>"
endfunction