あまり深く理解してないので識者のツッコミ大歓迎
取り敢えず最低限だけ
# 補完を有効にする
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補完関数を自作すると便利 - はこべブログ♨
ひとつの補完関数を書く過程を書かれてて分かりやすい