経緯
この前、fish shell で補完の実装 - completeという記事を書きました。
ざっと目を通していただけるとありがたいのですが、まとめると以下です。
前回のまとめ
fish
の補完を定義するcomplete
コマンドでは
-a
オプションで補完候補の単語を指定するのですが
サブコマンドなどで補完候補を変えるには
-n
オプションで指定する関数によって場合分けをする。
# fish completion example
complete -c {コマンド} -n "{現在のコマンドに対する引数が0個の時0を返す関数}" -a "{引数が0個の時補完したい候補}"
complete -c {コマンド} -n "{現在のコマンドに対する引数が1個の時0を返す関数}" -a "{引数が1個の時補完したい候補}"
という話でした。
fish
では補完関数による候補生成ができないのか?
Shell Script Advent Calendar 2015 15日目の @akinomyogaさんの記事内にて。
fish
では補完関数による候補生成ができないのですかね…??
そうですよね。できて欲しいです。
fish-shellのcompletionsフォルダのソースを見てもされていないので、考えもしませんでした。すいません。
bash
とfish
の補完の比較
bash
のcomplete
complete [-abcdefgjksuv] [-o comp-option] [-DE] [-A action] [-G globpat] [-W wordlist]
[-F function] [-C command] [-X filterpat]
[-P prefix] [-S suffix] name [name …]
fish
のcomplete
complete ( -c | --command | -p | --path ) COMMAND
[( -s | --short-option ) SHORT_OPTION]
[( -l | --long-option | -o | --old-option ) LONG_OPTION]
[( -a | --arguments ) OPTION_ARGUMENTS]
[( -w | --wraps ) WRAPPED_COMMAND]
[( -d | --description ) DESCRIPTION]
今回注目するオプションだけ表にまとめると
オプションの機能 | bash | fish |
---|---|---|
候補単語を指定 | -W | -a |
補完関数を指定 | -F | なし |
候補の説明を付加 | なし | -d |
となります。
ただし、-a
オプションでコマンド置換によってコマンドの出力を候補単語に指定すれば補完関数を指定することと同様なことが可能です。
コマンド置換による補完関数の代替
function demo
echo "demo"
end
function __demo_subcommand
set cmd (commandline -opc)
if [ (count $cmd) -eq 2 ]
ls
else
set -l DEMO_SUBCOMMAND yes no
for SUB in $DEMO_SUBCOMMAND
echo $SUB
end
end
end
complete -f -c demo -a "(__demo_subcommand)"
上記のコードを実行するとdemo
コマンドの補完が以下のようになりました。
補完関数による候補生成ができました。
では、なぜ本家でやられていないのか?
fish
の設計思想
fish
の設計思想の中の1つにThe law of discoverability
というものがあり、以下のように記されています。
The law of discoverability
A program should be designed to make its features as easy as possible to discover for the user.
...
Examples:
Everything should be tab-completable, and every tab completion should have a description.
すべての補完候補に説明がついているべき ということらしいです。
-d
オプション
上のデモでのコード下記のように一部変えてみます。
complete -f -c demo -a "(__demo_subcommand)" -d "demo sub command"
候補の後ろに説明はつきましたが、すべて同じです。
つまり、候補ごとに説明を付加するために、候補ごとにcomplete
を実行していたから、補完関数を用いる必要がなかったのですね。
納得しました。
最後に
これで、また少しfish
が少しわかった気がします。
最初から設計思想読めよって話ですね汗
あと、zsh-completionsのようなものがあればいいなあと思いました。