argparse - fishスクリプトまたは関数に渡されたオプションを解析

概要

argparse [OPTIONS] OPTION_SPEC ... -- [ARG ...]

説明

このコマンドを使用すると、fishスクリプトや関数で引数を簡単に処理できるようになります。既知のオプションを定義する引数を渡し、リテラルの -- を続けた後に、解析対象の引数(これ自体にリテラルの -- が含まれる場合もあります)を渡します。 argparse は、渡されたオプションとその値を示す変数を設定し、$argv_opts にオプションとその値を設定し、$argv に残りの引数を設定します。詳細は以下の 使用法 セクションを参照してください。

各オプション仕様(OPTION_SPEC)は、後述する ドメイン言語 で記述されます。すべての OPTION_SPEC は、argparse自体のフラグの後、かつ解析対象の引数とを区切る -- よりも前に記述する必要があります。

引数(ARG)リスト内で見つかった各オプションは、 _flag_X という名前の変数になります。ここで X は、短縮フラグの文字またはロングフラグの名前(定義されている場合)です。例えば、 --help オプションによって、argparseが _flag_h_flag_help という2つの変数を定義する場合があります。

これらの変数はローカルスコープで設定されます(つまり、スクリプトが set -l _flag_X を実行したかのように扱われます)。フラグがbool値(値を持たず、指定されたか否かのみを判別するもの)の場合、値は実際に渡された短縮フラグやロングフラグになります。オプションがbool値でない場合、値は ARG リストの処理時に収集された0個以上の値になります。フラグが指定されなかった場合、そのフラグ変数は設定されません。

オプション

以下の argparse 自体に対するオプションが利用可能です。これらはすべての OPTION_SPEC よりも前に記述する必要があります。

-n--name NAME

エラーメッセージで使用する名前(NAME)を指定します。デフォルトでは現在の関数名が使用されます。関数の外で実行された場合は argparse が使用されます。

-x--exclusive OPTIONS

互いに排他的なオプションをカンマ区切りのリストで指定します。これを複数回使用して、排他的なオプションのセットを複数定義することもできます。各オプションは短縮形式とロング形式のどちらでも指定できますが、別途そのオプション自体の定義も必要です。

-N--min-args NUMBER

許容される非オプション引数の最小数です。デフォルトは 0 です。

-X--max-args NUMBER

許容される非オプション引数の最大数です。デフォルトは 無制限 です。

-u--move-unknown

未知のオプションを許可し、それらを $argv から $argv_opts へ移動します。デフォルトでは、未知のオプションはオプション引数を取るもの(つまりオプション仕様 =? を持つもの)として扱われます。

これは、短縮オプションのグループ内に未知の短縮オプションが含まれ、その「後ろ」に既知の短縮オプションが続く場合、既知のオプションは未知のオプションへの引数として扱われることを意味します(例: --move-unknown h -- -oh では、 h-o への引数として扱われるため、 _flag_h は設定「されません」)。対照的に、既知のオプションが先に来る場合(かつ引数を取らない場合)、既知のオプションは正しく認識されます(例: argparse --move-unknown h -- -ho では、 $_flag_h-h が設定「されます」)。

-i--ignore-unknown

非推奨です。これは --move-unknown と似ていますが、不明なオプションとその引数が $argv_opts に移動されず、 $argv に保持される点が異なります。--move-unknown とは異なり、このオプションを使用すると、不明なオプションと - で始まるオプション以外の引数を区別することができなくなります($argv 内の -- セパレータがすべて削除されるためです)。

-S--strict-longopts

長い形式のオプションの解析をより厳密にします。具体的には、このフラグが「ない」場合、 long という既知の長い形式のオプションフラグは以下のように省略可能です:

  • -long-long=<value> (ただし、短縮フラグ l が存在しない場合「のみ」)。

  • --lo--lo=<value> (ただし、 lo で始まる他の長い形式のフラグが存在しない場合「のみ」)。 long の他の空でない接頭辞についても同様です。

  • -lo-lo=<value> (上記2つの組み合わせ)。

--strict-longopts フラグを指定すると、上記の3つは解析エラーになります。long という名前の長い形式のオプションを使用するには、 --long--long=<value> という構文を使用しなければなりません。

このフラグは、未知のオプションの解析には影響しません(未知のオプションは、常にこのフラグが有効であるかのように解析されます)。

このオプションは将来的に常に有効になる可能性があるため、これが無効な状態の挙動に依存しないでください。

--unknown-arguments KIND

--ignore-unknown が同時に指定されない限り、このオプションは --move-unknown を包含します。これは、 KIND の値に応じて未知のオプションの解析挙動を変更します。

  • optional (デフォルト): 各未知のオプションが任意指定の引数を取ることを許可します(つまり、オプション仕様に =? または =* が指定されているかのように扱われます)。例えば、 argparse --ignore-unknown --unknown-arguments=optional ab -- -u -a -ub を実行すると、 _flag_a は設定されますが、 _flag_b は設定「されません」。これは、 b が 2 回目の -u への引数として扱われるためです。

  • required : 各未知のオプションが引数を取ることを必須とします(つまり、オプション仕様に ==+ が指定されているかのように扱われます)。上記の例を --unknown-arguments=required に変更した場合、 _flag_a_flag_b も「どちらも」設定されません。 -a は 1 回目の -u への引数として、 b は 2 回目の -u への引数として扱われるためです。

  • none : 各未知のオプションが引数を取ることを禁止します(つまり、オプション仕様に = が指定されていないかのように扱われます)。上記の例を --unknown-arguments=none に変更した場合、 _flag_a_flag_b の「両方」が設定されます。どちらの -u も引数を取らないものとして扱われるためです。

なお、上記は未知の長い形式のフラグが -- (GNU スタイル)を使用することを前提としています(例えば、 KINDnonebar という長い形式のオプションが定義されていない場合、 -bar は 3 つの短縮フラグ bar として解釈されます。しかし、 bar が既知である場合、 -bar--bar と同様に扱われます)。

--unknown-arguments=required を使用している場合、指定された引数が未知のオプションで終わっていると、それに対する引数が存在しないためエラーになります。同様に、 --unknown-arguments=none を使用している場合に --flag=value 構文を使用し、 flag が未知のオプションである場合もエラーになります。

-s--stop-nonopt

最初の非オプション引数が見つかった時点で引数のスキャンを停止させます。これは特に、独自のオプションを持つサブコマンドを実装する場合などに便利です。

-h--help

このコマンドの使用方法に関するヘルプを表示します。

使用法

このコマンドを使用するには、オプション仕様(OPTION_SPEC)を渡し、必須の -- を置いた後に、解析対象の引数を指定します。

簡単な例:

argparse 'h/help' 'n/name=' -- $argv
or return

$argv が空の場合、解析する対象がないため、 argparse は成功を示す 0 を返します。 $argv が空でない場合、フラグ -h--help-n--name がチェックされます。これらが見つかると引数から削除され、 _flag_OPTION という名前のローカル変数が設定されるため、スクリプトはどのオプションが指定されたかを判断できます。未知のオプションや、オプションに必須の値が欠落しているといったエラーが $argv になければ、 argparse はステータス 0 で終了します。それ以外の場合は、適切なエラーメッセージを標準エラー出力(stderr)に書き出し、ステータス 1 で終了します。

or return は、 argparse が失敗した場合に関数がそのステータスを返して終了することを意味します。したがって、その後の処理が続行されれば、 argparse は成功したことになります。

argparse が抽出したフラグを使用するには:

# Checking for _flag_h and _flag_help is equivalent
# We check if it has been given at least once
if set -ql _flag_h
    echo "Usage: my_function [-h | --help] [-n | --name=NAME]" >&2
    return 1
end

set -l myname somedefault
set -ql _flag_name[1]
and set myname $_flag_name[-1] # here we use the *last* --name=

フラグ名の中に変数名として有効でない文字( - ハイフンなど)が含まれている場合、それらはアンダースコア( _ )に置き換えられます。

引数の -- は必須です。 -- の後にオプション仕様や引数を含める必要はありませんが、 -- 自体は必ず含めなければなりません。例えば、以下は許容されます:

set -l argv foo
argparse 'h/help' 'n/name' -- $argv
argparse --min-args=1 -- $argv

しかし、以下は認められません:

set -l argv
argparse 'h/help' 'n/name' $argv

最初に見つかる -- は、 argparse コマンドがオプション仕様や argparse 自体へのオプション( --move-unknown など)を、解析対象のコマンド引数から確実に分離するためのものです。そのため、これは必須となります。

オプション仕様

各オプション仕様は、以下の要素で構成されます:

  • 任意指定の英数字 1 文字による短縮フラグ。

  • / で始まる任意指定のロングフラグ名。短縮フラグとロングフラグのどちらも存在しない場合は、エラーが報告されます。

    • 短縮フラグがなく、かつロングフラグ名が 2 文字以上である場合は、 / を省略できます。

    • 後方互換性のために、短縮フラグとロングフラグがある場合、短縮フラグをユーザーが使用できないようにする(この場合、フラグ変数としても公開されません)には、 / の代わりに - を使用できます。

  • フラグが引数を取らないブール値、または整数フラグである場合は、何も記述しません。または、

    • 値を必須とし、かつ最後に出現したフラグの値のみを保存する場合は = を記述します。または、

    • 値を任意(あってもなくてもよい)とし、かつ最後に出現したフラグの値のみを保存する場合は =? を記述します。または、

    • 値を必須とし、かつフラグが出現するたびにすべての値を保存する場合は =+ を記述します。または、

    • 値を任意とし、かつフラグが出現するたびにすべての値を保存する場合は、 =* を記述します。フラグに値が与えられなかった場合は、空文字列を保存します。

  • 任意で & を付けることができます。これは、そのオプションと付随する値が $argv$argv_opts に保存されないことを示します。これは _flag_ 変数には影響しません。

  • フラグが引数を取らないブール値の場合は何も記述しません。または、

    • ! に続けて、値を検証するための fish スクリプトを記述します。通常は、実行する関数を指定します。終了ステータスが 0 であればフラグの値は有効であり、 0 以外であれば無効とみなされます。エラーメッセージは(stderr ではなく) stdout に書き出す必要があります。詳細は フラグ値の検証 セクションを参照してください。

より冗長ではありますが、親しみやすい方法でオプション仕様を作成するには、 fish_opt コマンドを参照してください。

引数の解析時にフラグが見つからなかった場合、対応する _flag_X 変数は設定されません。

整数フラグ

foo -55 のように、コマンドが数値を直接オプションとして取る場合があります。これを許可するために、オプション仕様に # 修飾子を付けることができます。これにより、任意の整数がこのフラグとして解釈され、最後の数値がその値として与えられます( = を使用した場合と同様の挙動になります)。

# は(あれば)短縮フラグ文字の直後に記述する必要があります。 - (後方互換用)を除き、 = などの他の修飾子を併用することはできません:

m#maximum

これは +NNN として与えられた数値は読み取らず、フラグのように見える -NNN の形式のみを読み取ります。

Note: 任意指定の引数(Optional arguments)

=?=* で定義されたオプションは、任意指定の引数を取ることができます。これらの任意指定の引数は、それが属するオプションに「直接連結」されていなければなりません。

つまり、引数がそのオプションのものとして扱われるのは、以下のように使用した場合のみです:

cmd --flag=value
# or
cmd  -fvalue

以下のような形式では(オプションの引数としては)扱われません:

cmd --flag value
# "value" here will be used as a positional argument
# and "--flag" won't have an argument.

もしそうでなければ、位置引数も同時に使用したい場合に、任意指定の引数を「取らない」形でそのオプションを使用することが困難になってしまいます。

例:

grep --color auto
# Here "auto" will be used as the search string,
# "color" will not have an argument and will fall back to the default,
# which also *happens to be* auto.
grep --color always
# Here grep will still only use color "auto"matically
# and search for the string "always".

これは argparse に特有の動作ではなく、 getopt(3) を使用するすべてのプログラム(もし任意指定の引数をサポートしていれば)に共通する仕様です。先ほどの grep の例は、実際の GNU grep の挙動と同じです。

フラグ値の検証

オプションの値の検証が必要になることがあります。例えば、特定範囲内の有効な整数であるか、IPアドレスであるか、あるいは全く別の何かであるかといった確認です。これは argparse の実行後に行うこともできますが、任意の fish スクリプトを実行することで argparse 自体に検証を行わせることも可能です。そのためには、! (感嘆符)に続けて実行したい fish スクリプトを記述します。そのコードが実行される際、以下の 3 つの変数が定義されます。

  • _argparse_cmd には、 argparse --name で指定された名前が設定されます。

  • _flag_name には、現在処理されている短縮フラグまたはロングフラグの名前が設定されます。

  • _flag_value には、現在処理されているフラグに関連付けられた値が設定されます。

これらの変数は、ローカルでエクスポートされた変数として関数に渡されます。

スクリプトは、エラーメッセージを stderr ではなく stdout に書き出す必要があります。フラグの値が有効であればステータス 0 を返し、無効であれば 0 以外のステータスを返してください。

fish には、 --min--max フラグを受け取る _validate_int 関数が付属しています。例えば、あなたのコマンドが -m--max フラグを受け付け、許容される最小値が 0、最大値が 5 だとしましょう。その場合、オプションを次のように定義します: m/max=!_validate_int --min 0 --max 5 。これらのフラグを付けずに _validate_int を呼び出した場合のデフォルトの挙動は、最小値や最大値の制限なしに、値が有効な整数であるかどうかのみをチェックします。

フラグ値の検証例をいくつか示します:

# validate that a path is a directory
argparse 'p/path=!test -d "$_flag_value"' -- --path $__fish_config_dir
# validate that a function does not exist
argparse 'f/func=!not functions -q "$_flag_value"' -- -f alias
# validate that a string matches a regex
argparse 'c/color=!string match -rq \'^#?[0-9a-fA-F]{6}$\' "$_flag_value"' -- -c 'c0ffee'
# validate with a validator function
argparse 'n/num=!_validate_int --min 0 --max 99' -- --num 42

OPTION_SPEC の構成例

いくつかの OPTION_SPEC の例を挙げます。

  • h/help は、 -h--help の両方が有効であることを意味します。このフラグはブール値であり、複数回使用できます。どちらかのフラグが使用されると、_flag_h_flag_help に、フラグが出現した回数分だけその形式が設定されます。例えば、 -h-h--help と指定された場合、 count $_flag_h は "3" を返します。

  • help は、 --help のみが有効であることを意味します。フラグはブール値で複数回使用可能です。使用された場合 _flag_help は上記と同様に設定されます。また、後方互換性のために h-help (任意の短縮文字を使用)という形式もサポートされています。

  • help& も同様ですが( $argv から --help を「削除」します)、大きな違いは --help$argv_opts に格納「されない」点です。

  • longonly= は、値を必須とする --longonly フラグです。短縮フラグは存在せず、短縮フラグ用の変数も生成されません。

  • n/name= は、 -n--name の両方が有効であることを意味します。値を必須とし、最大 1 回まで使用できます。フラグが指定されると、そのフラグに関連付けられた唯一の必須の値が _flag_n_flag_name に設定されます。

  • n/name=? は、 -n--name の両方が有効であることを意味します。任意指定の値を許容し、最大 1 回まで使用できます。フラグが指定された際、値が提供されていればその値が、提供されていなければ値なし(空)の状態が _flag_n および _flag_name に設定されます。

  • n/name=* も同様ですが、フラグを複数回使用できる点が異なります。フラグが指定されるたびに、その出現に関連付けられた各値が _flag_n_flag_name に設定されます。各値は、オプションに与えられた値、または値が与えられなかった場合は空文字列となります。

  • name=+ は、 --name のみが有効であることを意味します。値を必須とし、複数回使用できます。フラグが出現するたびに、それに関連付けられた各値が _flag_name に設定されます。

  • x は、 -x のみが有効であることを意味します。これは複数回使用可能なブール値です。指定された場合、 _flag_x は上記と同様に設定されます。

  • /x も同様ですが、( -x ではなく) --x のみが有効となります。

  • x=x=?x=+ は、上記の n/name の例と同様ですが、短縮フラグ -x に対する長い形式の代替フラグが存在しません。

  • #max (または #-max)は、正規表現 "^--?\d+$" にマッチするフラグが有効であることを意味します。これらが見つかると、変数 _flag_max に割り当てられます。これにより、任意の正または負の整数を、先頭に単一の "-" を付けて指定できるようになります。多くのコマンドがこの慣用句をサポートしています。例えば、 head -3 /a/file は /a/file の最初の 3 行だけを出力します。

  • n#max は、正規表現 "^--?\d+$" にマッチするフラグが有効であることを意味します。これらが見つかると、変数 _flag_n_flag_max に割り当てられます。これにより、任意の正または負の整数を、先頭に単一の "-" を付けて指定できるようになります。この例では、 -n NNN--max NNN のいずれかのフラグを使用して値を指定することも可能です。

  • #longonly は、最後に出現した整数オプションを _flag_longonly に格納します。

引数の解析後、フラグ処理中に消費されなかったすべての値が、ローカルスコープの変数 argv に設定されます。バインドされていない値がない場合でも変数は設定されますが、 count $argv は 0 になります。同様に、フラグ処理中に消費「された」引数は、ローカルスコープの変数 argv_opts に設定されます。これにより、追加の引数とともに $argv_opts を別のコマンドに転送(フォワーディング)することが可能になります。

argparse の処理中にエラーが発生した場合、0 以外のステータスで終了し、標準エラー出力(stderr)にエラーメッセージを表示します。

使用例

シンプルな使用法:

argparse h/help -- $argv
or return

if set -q _flag_help
    # TODO: Print help here
    return 0
end

これは -h / --help という 1 つのオプションをサポートしています。それ以外のオプションが指定されるとエラーになります。このオプションが与えられた場合は、ヘルプを表示して終了します。

fish_add_path - PATHにディレクトリを追加する が引数を解析する方法:

argparse -x g,U -x P,U -x a,p g/global U/universal P/path p/prepend a/append h/help m/move v/verbose n/dry-run -- $argv

ここにはさまざまなブール値フラグがあり、すべてに長い形式と短縮形式が存在します。これらの中には併用できないものがあり、そのために -x フラグが使用されます。-x g,U は、 --global--universal (またはそれらの短縮形式)が競合することを意味し、これらが同時に使用されるとエラーになります。この場合、完全なオプション仕様を記述する必要はなく、短縮フラグかロングフラグのいずれかを指定するだけで済みます。

この後、 --path フラグに従って、どの変数を操作すべきかを決定します:

set -l var fish_user_paths
set -q _flag_path
and set var PATH

# ...

# Check for --dry-run.
# The "-" has been replaced with a "_" because
# it is not valid in a variable name
not set -ql _flag_dry_run
and set $var $result

既知のオプションを別のコマンドに転送しつつ、新しいオプションを追加するために $argv_opts を使用する例:

function my-head
    # The following option is the only existing one to head that takes arguments
    # (we will forward it verbatim).
    set -l opt_spec n/lines=
    # --qwords is a new option, but --bytes is an existing one which we will modify below
    set -a opt_spec "qwords=&" "c/bytes=&"
    argparse --strict-longopts --move-unknown --unknown-arguments=none $opt_spec -- $argv || return
    if set -q _flag_qwords
        # --qwords allows specifying the size in multiples of 8 bytes
        set -a argv_opts --bytes=(math -- $_flag_qwords \* 8 || return)
    else if set -q _flag_bytes
        # Allows using a 'q' suffix, e.g. --bytes=4q to mean 4*8 bytes.
        if string match -qr 'q$' -- $_flag_bytes
            set -a argv_opts --bytes=(math -- (string replace -r 'q$' '*8' -- $_flag_bytes) || return)
        else
            # Keep the users setting
            set -a argv_opts --bytes=$_flag_bytes
        end

    end

    if test (count $argv) -eq 0
        # Default to heading /dev/kmsg (whereas head defaults to stdin)
        set -l argv /dev/kmsg
    end

    # Call the real head with our modified options and arguments.
    head $argv_opts -- $argv
end

上記の argparse 呼び出しは、処理したく「ない」すべてのオプションを $argv_opts に保存します( --qwords--bytes オプションは、オプション仕様が ~ で終わっているため、そこには保存されません)。その後、コードは $_flag_OPTION 変数を使用して --qwords--bytes オプションを処理し、変換後のオプションを $argv_opts に追加します(これには --qwords--bytes 「以外」のすべての元のオプションが既に含まれています)。

上記の argparse 呼び出しでは --move-unknown--unknown-arguments=none を使用しているため、 head の引数のうち値を取るものだけを教えるだけで済みます。これにより、ラッパースクリプトは非オプション引数(つまり、 head が操作対象とするファイル名である $argv )を正確に割り出すことができます。一方、 --unknown-arguments=optional を使用して head の既知のオプションをすべて明示的にリスト化すれば、将来 head に新しいオプションが追加された場合でも、連結形式(例: -o<arg>--opt=<arg> )であればラッパースクリプト経由で使用できるという利点があります。

短縮オプションを正しく渡すためには --strict-longopts が必要であることに注意してください。例えば、これがないと my-head -q --bytes 10q を実行した際、 -q が実際には --qwords の略称として解析されてしまいます。