ホーム > タグ > neocomplcache

neocomplcache

Hack #128: neocomplcache Hacks(3) キーワード補完

三回目の今回はneocomplcacheのキーワード補完と拡張プラグインを解説します。

キーワード補完とは

neocomplcacheのキーワード補完は、<C-n><C-p>で呼び出すことのできるVim組み込みのキーワード補完を模倣して設計されています。 言語ごとにキーワードパターンを定義して、一括して候補を検索できるのが最大の特徴です。 使用するキーワードパターンはg:NeoComplCache_KeywordPatternsで定義されています。

pluginとcomplfuncの違い

neocomplcacheには補完候補を収集するために、pluginとcomplfuncという二つの拡張プラグインが存在します。 それぞれ、autoload/neocomplcache/pluginautoload/neocomplcache/complfuncに配置します。 pluginはkeyword_complete.vimから一括して呼びだされる拡張プラグインで、単純なため実装が比較的簡単です。 complfuncは補完開始位置を拡張プラグイン側で計算しないといけません。 その代わり、補完開始位置は自由に決定できるので、ファイル名補完のような複雑な補完を実装できます。 初期のneocomplcacheでは、complfuncは一つのプラグインしか呼べないという制限がありました。 現在のバージョンでは、complfuncの候補も統合できるように改良されているため、そのような制限はありません。

標準添付のplugin

buffer_complete.vim

開いているバッファから補完候補を収集するプラグインです。バッファ内の単語を解析することで、使用頻度の学習も行います。

dictionary_complete.vim

g:NeoComplCache_DictionaryFileTypeListsから補完候補を収集するプラグインです。

include_complete.vim

バッファで開いているインクルードファイルから補完候補を収集するプラグインです。Vimにもインクルード補完はありますが、より拡張されています。

snippets_complete.vim

スニペットを補完するプラグインです。補完するだけではなく、単体でスニペット展開プラグインとしても動作します。

syntax_complete.vim

シンタックスファイルからキーワードを補完するプラグインです。Vim標準添付のsyntaxcomplete.vimよりも高機能であり、結果をキャッシュするので高速です。複雑なTeXのシンタックスも解析できます。

tags_complete.vim

タグファイルからキーワードを補完するプラグインです。

標準添付のcomplfunc

completefunc_complete.vim

補完関数を登録することで、自動呼び出しするプラグインです。neocomplcacheはcompletefuncを上書きしてしまうので、その対策に使えます。 手動補完として補完関数を個別に呼び出しすることもできます。

filename_complete.vim

ファイル名を補完するプラグインです。詳しい解説は、[Hack #119: neocomplcache Hacks(2) オムニ補完]を参照してください。

keyword_complete.vim

pluginから候補を収集し、キーワードを補完するプラグインです。

omni_complete.vim

オムニ補完を呼び出し、候補を収集するプラグインです。詳しい解説は、[Hack #119: neocomplcache Hacks(2) オムニ補完]を参照してください。

vim_complete.vim

Vimのオムニ補完機能を提供するプラグインです。Vim標準の<C-x><C-v>よりも機能が拡張されていて、ローカル変数や引数の補完も可能です。

Shougo

Hack #119: neocomplcache Hacks(2)  オムニ補完

二回目の今回はオムニ補完です。AutoComplPopでも自動呼び出しが可能ですが、neocomplcacheでは、それに改良を加え、設定しやすくなっています。

オムニ補完とは

オムニ補完とは、Vim組み込みで用意されている補完とは違い、文脈を解析して行う補完です。関数を'omnifunc'に設定し、<C-x><C-o>のキーシーケンスを入力することで呼び出されます。標準でもいくつかの言語のオムニ補完関数が用意されていますが、ユーザーが自分で定義することができます。

inoremap <expr><C-x><C-o> &filetype == 'vim' ? "\<C-x><C-v><C-p>" : neocomplcache#manual_omni_complete()

私はこのようにキーマッピングを設定し、Vim組み込みのオムニ補完を置き換えています。

拡張機能

neocomplcacheのオムニ補完には次のような拡張機能があります。

自動補完の文脈定義

g:NeoComplCache_OmniPatterns[filetype]を設定すれば、呼び出し条件をカスタマイズしたり、呼び出しを無効化することができます。

多数の言語に対応

AutoComplPopでは標準でPerl/Ruby/html/CSS/Pythoのオムニ補完が可能です。neocomplcacheではPerl以外の確認できたすべての言語に対応しています。キーワードパターンに追加するだけなので、新たな言語に対応させることが容易です。

補完スキップ

g:NeoComplCache_EnableSkipCompletionが1ならば(デフォルト)、候補の取得に時間がかかりすぎる場合、補完をスキップすることができます。

ワイルドカード

ほかの補完と同様、ワイルドカードによる絞り込みに対応しています。

エラーを出さない

特定のオムニ補完では、変な場所で呼び出すとエラーを出したりすることがあります。neocomplcacheではエラーをcatchしているので、neocomplcache内部にバグがない限り、オムニ補完中にエラーになることはありません。

補完環境の厳密な判定

PythonやRubyのオムニ補完は:python:rubyが正常に動作する環境でなければ動作しません。よって、内部で判定しています。

ファイル名補完やバッファ名補完との同時呼び出し

オムニ補完とほかの補完を同時に呼び出せないAutoComplPopとは違い、neocomplcacheのオムニ補完はほかの補完と統合されています。 よって、同時に候補を出すことができるので、さらに便利に使えます。 ただし、オムニ補完の開始パターンが先にマッチした場合、オムニ補完の候補のみが計算されて表示されます。 これはVim自体の仕様です。これを防ぐためには、一度補完のポップアップを閉じて、補完を再呼び出しするしかありません。

キーワードの収集

空文字列でオムニ補完を呼び出してキーワードを収集してキャッシュし、オムニ補完候補として利用することができます。

neocomplcacheからオムニ補完関数を呼び出すときの注意

neocomplcacheは大抵のオムニ補完関数に対応していますが、オムニ補完関数を内部で無理矢理呼んで変換するという動作を行っているので、呼び出す関数によっては補完がうまく働かないことがあります。現在、complete_add()関数を内部で呼んでいる場合には動作がおかしくなることがわかっています。これはオムニ補完関数側がcomplete_add()を呼ばないようにするしかありません。 他に、Rubyのオムニ補完は時々フリーズする現象があることが報告されています。 これはRubyのオムニ補完が外部インタフェースを内部で使用しているためだと思われます。 Vimの外部インタフェース機能は不安定なので、時々エラーをはいたりフリーズすることがあります。 無効にしたい場合は.vimrcで

if !exists('g:NeoComplCache_OmniPatterns')
let g:NeoComplCache_OmniPatterns = {}
endif
let g:NeoComplCache_OmniPatterns['ruby'] = ''

と設定すると、無効にできます。これでは不便なので、Rubyのオムニ補完を書き直してくれる人を現在募集中です。

Shougo

Hack #111: neocomplcache Hacks(1) ファイル名補完

neocomplcache Hacksでは、neocomplcacheの機能を詳細に解説していきます。一回目の今回はファイル名補完です。一見地味な補完ですが、うまく活用すると非常に便利です。

ファイル名補完とは

ファイル名補完とは、Vim組み込みで用意されているファイル名補完を置き換えるためにneocomplcache上で実装した補完です。Ver.3.0より機能が分離され、neocomplcacheの1プラグインとなっています。を解析して候補を出すため、組み込みのファイル名補完と同じように動作しますが、機能が大幅に拡張されています。特にファイル名を指定するときや、シェル拡張系のプラグインを使用するときに効果を発揮します。

inoremap <expr><C-x><<C-f>  neocomplcache#manual_filename_complete()

私はこのようにキーマッピングを設定し、Vim組み込みのファイル名補完を置き換えています。

拡張機能

neocomplcacheのファイル名補完には次のような拡張機能があります。

ワイルドカードに対応

*.txtのような、ワイルドカード文字が補完に使えます。 実行ファイル、読み取り専用ファイル、ディレクトリの表示 表示をわかりやすくするため、ファイルの種類を判別し、実行ファイルには*を、読み取り専用ファイルには[-]を、ディレクトリには/をそれぞれ付加します。 Windowsでは$PATHEXTを参照するので、より正確な判別が可能です。

短縮ファイル名補完

/u/s/lのようにディレクトリの先頭名だけ入力することで、/u*/s*/lのように解釈されます。素早く補完したいときに便利ですが、候補が多いと重くなります。

補完スキップ

g:NeoComplCache_EnableSkipCompletionが1ならば(デフォルト)、ファイル名の取得に時間がかかりすぎる場合、補完をスキップすることができます。

Cygwin対応

Vim組み込みのファイル名補完では/cygdrive/の入力で補完が重くなってしまいますが、neocomplcacheのファイル名補完では対策されています。

…->../..変換

…を../..に変換して解釈することができます。上のディレクトリを参照するときに便利です。

_, -, .による区切り補完

_, -, .を区切り文字として曖昧補完ができます。たとえば、h_.txtはh_.txtと同じ意味です。

環境変数を展開しない

組み込みのファイル名補完の場合、環境変数が勝手に展開されてしまうので、逆に邪魔になってしまうことが多々あります。neocomplcacheのファイル名補完は環境変数とマッチする部分はそのままにするので、便利に使うことができます。

zshとの比較

neocomplcacheのファイル名補完は自動的に候補が表示できるのが一番の魅力で、特にvimshellとの連携はすばらしいです。zshでも設定すれば自動補完ができないことはないのですが、誤爆の可能性も高く、おすすめできません。自動でファイル名補完ができることに慣れてしまうと、いちいち<TAB>を連打しなくてはいけないシェルの補完が煩わしく感じることでしょう。

vimshellとの併用

neocomplcacheのファイル名補完は元々vimshell上で利用するために作られました。vimshellとはVim上でシェルを実装したプラグインです。neocomplcacheとは独立していますが、neocomplcacheがインストールされている場合、補完時にneocomplcacheの機能を使用します。vimshellはneocomplcacheと比較しても複雑なプラグインなので、機会があれば詳しく解説したいと思います。

Shougo

USSR#1: neocomplcache ソースコード読解会

文責: ujihisa, Shougo, sorah

今日は neocomplcache-4.0.3/autoload/neocomplcache.vim を読みました。

勉強会チャットログはこちら: http://lingr.com/room/vim/archives/2009/12/22

特にしっかりと読んだ関数:

  • function! neocomplcache#enable()
  • function! s:complete()
  • function! s:integrate_completion(complete_result)

APIとなるneocomplcache#ではじまる関数群がautoload/neocomplcache.vimの上部にまとめて定義されています。 また、内部で使う関数群が続いて下部にスクリプトローカルで定義されています。

興味深い部分の抜粋:

echo ''
redraw

redraw!だと画面がちらつくので、そういうときはこの二行で、ということだそうです。

まとめ

“neocomplcacheのソースコードは魔界

コード自体はすばらしく整理されているものの、 Vim自体とその周囲の問題を解決するために涙が止まらない努力が随所に見られます。

  • ATOK
  • 画面のチラツキ
  • 速度 (skip)
  • プラグイン
  • 補完の統合
  • 頻度解析

Home > Tags > neocomplcache

Search
Feeds
Links
  • 公式
  • 勉強会
  • 情報
  • コミュニティ
  • プラグイン
  • vimrc
  • Meta
    Etc
    Creative Commons License
    This blog is licensed under a Creative Commons License.

    Return to page top