LoginSignup
14
9

More than 5 years have passed since last update.

fish shell の補完で補完関数を用いる方法と設計思想

Last updated at Posted at 2015-12-18

経緯

この前、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フォルダのソースを見てもされていないので、考えもしませんでした。すいません。

bashfishの補完の比較

bashcomplete

complete [-abcdefgjksuv] [-o comp-option] [-DE] [-A action] [-G globpat] [-W wordlist]
[-F function] [-C command] [-X filterpat]
[-P prefix] [-S suffix] name [name …]

fishcomplete

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コマンドの補完が以下のようになりました。

https://gyazo.com/20311389a5e7d74f8baf1c66ab186ad4

補完関数による候補生成ができました。

では、なぜ本家でやられていないのか?

fishの設計思想

fish: Design document

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"

https://gyazo.com/2f15213ceb99c530c45207f45b3282a4

候補の後ろに説明はつきましたが、すべて同じです。

つまり、候補ごとに説明を付加するために、候補ごとにcompleteを実行していたから、補完関数を用いる必要がなかったのですね。

納得しました。

最後に

これで、また少しfishが少しわかった気がします。
最初から設計思想読めよって話ですね汗

あと、zsh-completionsのようなものがあればいいなあと思いました。

14
9
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14
9