あまり深く理解してないので識者のツッコミ大歓迎
取り敢えず最低限だけ
# 補完を有効にする
autoload -U compinit
compinit -u
# 補完メッセージを読みやすくする
zstyle ':completion:*' verbose yes
zstyle ':completion:*' format '%B%d%b'
zstyle ':completion:*:warnings' format 'No matches for: %d'
zstyle ':completion:*' group-name ''$fpath の通ったディレクトリに補完関数を置く
nyan コマンドの補完関数なら _nyan という名前で保存する
補完関数の先頭には #compdef nyan と補完対象のコマンド名を書く
ファイル名と同じ名前の関数を作りその中に補完関数を書く
~/zsh/functions/_nyan
#compdef nyan
_nyan() {
# 補完関数
}あるいは下記のように書いたファイルを source ~/zsh/lib/_nyan.zsh と読み込むことで補完関数を有効にすることも出来る
compdef _nyan nyan は _nyan 関数を nyan コマンドの補完関数として使うという意味になる
~/zsh/lib/_nyan.zsh
_nyan() {
# 補完関数
}
compdef _nyan nyanまずは猫を表示してくれる可愛い nyan コマンドを作る
~/bin/nyan
#!/usr/bin/env zsh
function nyan() {
typeset -a modes
help() {
echo 'Usage: nyan <mode>'
echo
echo 'Modes:'
echo ' neko, usagi, kuma, github'
}
neko() {
echo ' ∧_∧'
echo "ฅ'ω'ฅ < ニャーン"
}
usagi() {
echo ' /) /)'
echo '_( _ ๑❛ᴗ❛)_ < ニャーン'
}
kuma() {
echo '(´(ェ)`) < ニャーン'
}
github() {
echo '=͟͟͞͞=͟͟͞͞=͟͟͞͞ (\ (\'
echo '=͟͟͞͞=͟͟͞͞=͟͟͞͞(,, 0 ω 0) < ニャーン'
echo '=͟͟͞͞=͟͟͞͞=͟͟͞͞(/ (/ \) \)'
}
while [ $1 ]; do
case $1 in
-h|--help)
help
return
;;
*)
modes=($modes[*] $1)
;;
esac
shift
done
if (( $#modes == 0 )); then
neko
return
fi
for mode in $modes; do
if type $mode > /dev/null 2>&1; then
$mode
else
echo "No such mode \"$mode\""
fi
done
}
nyan $@動かしてみる
$ nyan
∧_∧
ฅ'ω'ฅ < ニャーン
$ nyan wan
No such mode "wan"
$ nyan --help
Usage: nyan <mode>
Modes:
neko, usagi, kuma, github
$ nyan usagi
/) /)
_( _ ๑❛ᴗ❛)_ < ニャーン
$ nyan kuma github
(´(ェ)`) < ニャーン
=͟͟͞͞=͟͟͞͞=͟͟͞͞ (\ (\
=͟͟͞͞=͟͟͞͞=͟͟͞͞(,, 0 ω 0) < ニャーン
=͟͟͞͞=͟͟͞͞=͟͟͞͞(/ (/ \) \)neko, usagi, kuma, github の4つのモードと
--help の1つのオプションがある
モードは複数指定することが出来る
まずは4つの全てのモードを補完候補に出してみる
~/zsh/functions/_nyan
#compdef nyan
_nyan() {
_values \
'mode' \
'neko' \
'usagi' \
'kuma' \
'github'
}_values 関数を使うとひとつ目の引数が補完候補のグループ名、その後の引数が補完候補となる
_values で指定した補完候補は複数かつ同じものを何度でも補完出来る
もしひとつの候補を一度しか入力させたくない場合は _values 関数に -w オプションを渡せば良い
ついでに説明文も表示してみる
#compdef nyan
_nyan() {
_values \
'mode' \
'neko[kawaii normal neko]' \
'usagi[kawaii usa-neko]' \
'kuma[kawaii kuma-neko]' \
'github[kawaii octcat]'
}[] 内に説明を書くことで、補完候補の横に説明が表示される
次は --help オプションを補完候補に出してみる
#compdef nyan
_nyan() {
_arguments \
{-h,--help}'[show help]' \
'*: :__nyan_modes'
}
__nyan_modes() {
_values \
'mode' \
'neko[kawaii normal neko]' \
'usagi[kawaii usa-neko]' \
'kuma[kawaii kuma-neko]' \
'github[kawaii octcat]'
}オプションと補完候補に同時に出すために _arguments 関数を使う
オプションの指定は optname[desc] と指定する
同じ意味のオプションがある場合は {optname1,optiname2} とカンマ区切りで書く
引数の指定は n:message:action と指定する
n は何番目の引数に対して動作するかを表す
何回でも同じ引数を補完出来て良いので * と指定しておく
message はその補完候補の説明を表す
今回は引数を省略する(理由は後述)
action はどういう動作をするかを表す
*: :__nyan_modes と書くことで、全ての補完候補で __nyan_modes 関数が使われる
__nyan_modes 関数内の _values 関数で mode というグループ名(説明)指定しているため message を省略してる
説明を出すため/見通しをよくするためモードの補完候補を別関数に分けたが、説明を伴わない場合は '*:mode:(neko usagi kuma github)' のように書くことも出来る
出来れば --help が入力された時はそこで補完を終了させたい
最後にそのための改良をする
#compdef nyan
_nyan() {
_arguments \
'(- *)'{-h,--help}'[show help]' \
'*: :->modes'
case $state in
modes)
_values \
'mode' \
'neko[kawaii normal neko]' \
'usagi[kawaii usa-neko]' \
'kuma[kawaii kuma-neko]' \
'github[kawaii octcat]'
;;
esac
}nyan コマンドの補完関数完全版である
'(- *)' で排他指定をしている
- の部分で --help(-h)が補完された時に -h(--help)を補完候補から除く
* の部分で --help(-h)が補完された時にそれ以降の補完を終了している
_arguments は他にもオプションや指定がたくさんあったり
_files でマッチしたファイルのみ候補に出したり
_alternative と _describe を使って複数のグループの補完候補を表示したり
_store_cache を使って補完候補をキャッシュしたり
他にもたくさんあるけどイマイチ理解が浅いので気が向いた時に続編を書くかも書かないかも
補完関数は先人たちが書いたものがたくさんある
git の補完関数はでかいが参考になる
自分が普段よく使うコマンドの補完関数を読んでみると良い
後、これを入れておくと便利
zsh-users/zsh-completions
Mac で homebrew なら brew install zsh-completions で入る
zsh: 20. Completion System(英語)
多分これに全て書かれてるけど要所しか読んでない
zsh補完関数の書き方(訳)
大体の雰囲気が分かる
zsh補完関数を自作すると便利 - はこべブログ♨
ひとつの補完関数を書く過程を書かれてて分かりやすい




Sorry, I have pushed 'Report as abuse' by my mistake. But, I don't know what erase my act... Your post is nice . Really sorry.