補完関数を書こう(3)-コマンド配信-

mzp2007-04-30

続いて、各サブコマンドに対する補完関数を書いていきます。

ただし

local cmd=${word[2]}
((CURRENT --)
shift words
 
case $cmd
(add) 
     .........
    ;;
(commit)    
     .........
    ;;
esac    

のように書いていくとどんどん長くなっていくので、各サブコマンドごとに関数を用意してそれを呼び出すようにします。

local cmd=${word[2]}
((CURRENT --)
shift words
 
_svn_$cmd

さて、ではアルファベット順にaddの補完から行う事にします。まず、addは次のような引数を取ります。(svn help addより)

使用方法: add <パス>...

有効なオプション:
  --targets <引数>       : ファイル <引数> の内容をサブコマンドの引数に追加
                             して渡します
  -N [--non-recursive]     : 単一のディレクトリのみに (非再帰的に) 作用します
  -q [--quiet]             : 最小限の情報だけを表示します
  --config-dir <引数>    : ディレクトリ <引数> からユーザ設定ファイルを読み
                             込みます
  --force                  : 強制的に処理を実行します
  --no-ignore              : デフォルトや svn:ignore 属性が無視するような項目
                             を無視しません
  --auto-props             : 自動的な属性設定を有効にします
  --no-auto-props          : 自動的な属性設定を無効にします

それほど奇妙なことはやっていないので、_argumentsを使って補完を行います。_argumentsの構文*1http://www.ayu.ics.keio.ac.jp/~mukai/translate/write_zsh_functions.htmlをどうぞ。

_svn_add(){
    local state
    _arguments -s : \
	'--targets[add contents of file]::file:_files' \
	'--config-dir[read config files]::directory:_files -/' \
	{-N,--non-recursive}'[operate on single directory only]' \
	{-q,--quiet}'[print as little as possible]' \
	'(--no-auto-props)--auto-props[eable automatic properties]' \
	'(--auto-props)--no-auto-props[disable automatic properties]' \
	'--force[force operation to run]' \
	'*:file:->file' && return 0
 
   local expl
   case $state in
	(file)
	_description files expl 'files'
	_files "$expl[@]" && return 0
	;;
   esac
   return 1
}

結果

上で解説したこと以外にも

  • svn helpに対する補完の追加
  • コマンド一覧の補完は別の関数にした。(svn helpでも使うから)
  • _svn_XXXがない場合は、_filesで補完するようにした

などの変更がある。まあ、たいしたことではない。

#compdef svn colorsvn
 
_svn_add(){
    local state
    _arguments -s : \
	'--targets[add contents of file]::file:_files' \
	'--config-dir[read config files]::directory:_files -/' \
	{-N,--non-recursive}'[operate on single directory only]' \
	{-q,--quiet}'[print as little as possible]' \
	'(--no-auto-props)--auto-props[eable automatic properties]' \
	'(--auto-props)--no-auto-props[disable automatic properties]' \
	'--force[force operation to run]' \
	'*:file:->file' && return 0
 
   local expl
   case $state in
	(file)
	_description files expl 'files'
	_files "$expl[@]" && return 0
	;;
   esac
   return 1
}
 
# svn helpは次にコマンド一覧を表示してやればいい
_svn_help(){
    _arguments -s : \
	'--config-dir[read config files]::directory:_files -/' \
	'*:file:_svn_cmd'
}
 
# コマンド一覧の表示
_svn_cmd(){
    # command
    local line
    local -a cmd
    _call_program help-command svn help \
	| sed -n '/^ /s/[(), ]/ /gp' \
	| while read -A line; do
	    cmd=($line $cmd)
          done
    _describe -t svn-command 'Subversion command' cmd
}
 
_svn(){
    if ((CURRENT > 2)); then
	local cmd=${words[2]}

	curcontext="${curcontext%:*:*}:svn-$cmd"
	(( CURRENT -- ))

	shift words
	if (( $+functions[_svn_$cmd] )) then
	    _svn_$cmd
	else
	    _files
	fi
    else
	_svn_cmd
    fi
}
 
_svn "$@"

*1:マニュアル曰くSyntax from hell