Hack #29: Command-line mode補完 自作編
Posted at 2009/06/20ツイート
Command-line modeの補完はinput()による入力や、自分が定義したコマンドにも有効です。ここではCommand-line modeにおける補完の設定方法についてレクチャーします。さらに、標準では用意されていない補完関数を自作する方法まで解説します。
- 自作コマンドに補完を定義する:
- 自作コマンドに引数の補完を定義する場合、-complete=に続けて補完関数の名前を指定します。指定できる補完関数には、次のようなものがあります。
-
- augroup
- autocmdのグループ名を補完します。
- buffer
- バッファ名を補完します。
- command
- VimのExコマンド名と、その引数を補完します。
- dir
- ディレクトリ名を補完します。
- event
- autocmdイベント名を補完します。
- expression
- Vimの式を補完します。
- file
- ファイル名を補完します。
- shellcmd
- シェルコマンド名を補完します。
- function
- 関数名を補完します。
- help
- ヘルプのタグを補完します。
- highlight
- シンタックスハイライト名を補完します。
- mapping
- キーマッピング名を補完します。
- menu
- メニュー名を補完します。
- option
- オプション名を補完します。
- tag
- タグ名を補完します。
- tag_listfiles
- タグと<C-d>でリスト表示されるファイル名を補完します。
- var
- Vimユーザ変数を補完します。
- custom,{func}
- 関数名funcで与えられる自作補完を行います。
- customlist,{func}
- 関数名funcで与えられる自作リスト補完を行います。
- 設定例
command! -nargs=? -complete=dir -bang CD call s:ChangeCurrentDir('<args>', '<bang>')
- augroup
- 補完関数についての詳しい解説は
:help command-completion
を参照してください。 - input()に補完を定義する:
- input()に補完を定義するのは簡単です。オプション引数であるcompletionが補完関数の名前となっているので、ここを自作コマンドの時と同様に設定すればよいです。例えばバッファ名を補完したいときには、次のように記述します。
let bname = input("Select buffer: ", "", "buffer")
- 補完関数に求められる仕様:
- 補完を自作するためには、まず補完関数を作成しなければなりません。補完関数はArgLead, CmdLine, CursorPosという三つの引数を持ちます。
-
- ArgLead
- 補完対象の文字列です。補完候補をフィルタリングするときに使います。
- CmdLine
- 現在入力中のCommand-line modeです。これをsplitで区切ることで、何番目の引数を補完しているのかを得ることができます。
- CursorPos
- 現在カーソルがある場所です。
- ArgLead
- 補完関数はこれらの引数より状況を分析して、有効な補完候補のリストを返却します。customの場合は候補を\nで区切ります。customは候補の絞り込みをVim側で行いますが、customlistでは補完関数側で行わなければなりません。
- 自作補完関数についての詳しい解説は
:help command-completion-custom
を参照してください。
- 補完関数のサンプル:
- 最後にまとめとして、補完関数のサンプルを紹介しておきます。gitのコマンドを補完するサンプルです。それだけでは面白くないので、第二引数に'mv'や'add', 'rm'といったコマンド名が与えられるとファイル名を補完するようになっています。
command! -nargs=+ -complete=customlist,CompletionGitCommands Git call GitCommand(<q-args>)
function! CompletionGitCommands(ArgLead, CmdLine, CusorPos)
let l:cmd = split(a:CmdLine)
let l:len_cmd = len(l:cmd)
if l:len_cmd <= 1
" Commands name completion.
let l:filter_cmd = printf('v:val =~ "^%s"', a:ArgLead)
return filter(['add', 'bisect', 'branch', 'checkout', 'clone', 'commit', 'diff', 'fetch',
\'grep', 'init', 'log', 'merge', 'mv', 'pull', 'push', 'rebase', 'reset', 'rm',
\'show', 'status', 'tag'], l:filter_cmd)
else
" Commands argments completion.
let l:cmdname = l:cmd[1]
if l:cmdname == 'add' || l:cmdname == 'mv' || l:cmdname == 'rm'
let l:arg = get(l:cmd, 2, '')
return split(glob(l:arg.'*'), '\n')
else
return []
endfunction
もどる
blog comments powered by Disqus