Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
10
Help us understand the problem. What is going on with this article?

More than 5 years have passed since last update.

@sosuke

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

経緯

この前、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のようなものがあればいいなあと思いました。

10
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
10
Help us understand the problem. What is going on with this article?