vim-users.jp

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>')
    補完関数についての詳しい解説は:help command-completionを参照してください。
    input()に補完を定義する:
    input()に補完を定義するのは簡単です。オプション引数であるcompletionが補完関数の名前となっているので、ここを自作コマンドの時と同様に設定すればよいです。例えばバッファ名を補完したいときには、次のように記述します。
    let bname = input("Select buffer: ", "", "buffer")
    補完関数に求められる仕様:
    補完を自作するためには、まず補完関数を作成しなければなりません。補完関数はArgLead, CmdLine, CursorPosという三つの引数を持ちます。
  • ArgLead
      補完対象の文字列です。補完候補をフィルタリングするときに使います。
  • CmdLine
      現在入力中のCommand-line modeです。これをsplitで区切ることで、何番目の引数を補完しているのかを得ることができます。
  • CursorPos
      現在カーソルがある場所です。
  • 補完関数はこれらの引数より状況を分析して、有効な補完候補のリストを返却します。customの場合は候補を\nで区切ります。customは候補の絞り込みをVim側で行いますが、customlistでは補完関数側で行わなければなりません。
    自作補完関数についての詳しい解説は:help command-completion-customを参照してください。
    補完関数のサンプル:
    command! -nargs=+ -complete=customlist,CompletionGitCommands Git call GitCommand()
    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
    
    最後にまとめとして、補完関数のサンプルを紹介しておきます。gitのコマンドを補完するサンプルです。それだけでは面白くないので、第二引数に'mv'や'add', 'rm'といったコマンド名が与えられるとファイル名を補完するようになっています。
    Shougo

    もどる
    blog comments powered by Disqus