MooseX::Getopt - コマンドライン引数を処理するためのロール
## In your class package My::App; use Moose; with 'MooseX::Getopt'; has 'out' => (is => 'rw', isa => 'Str', required => 1); has 'in' => (is => 'rw', isa => 'Str', required => 1); # ... rest of the class here ## in your script #!/usr/bin/perl use My::App; my $app = My::App->new_with_options(); # ... rest of the script here ## on the command line % perl my_app_script.pl -in file.input -out file.dump
このロールはコマンドライン引数からオブジェクトを生成するための代替コンストラクタを提供します。
このモジュールはオブジェクトのアトリビュートの定義を元に可能な限り自然にコマンドライン引数からその値の初期値を設定します。アトリビュートの名前はコマンドライン引数の名前となり、そのアトリビュートに型制約がある場合はそれを使用してGetopt::Longの設定がなされます。
この挙動についてさらに細かい設定を行いたい場合はMooseX::Getopt::Meta::Attribute::Traitか、:<MooseX::Getopt::Meta::Attribute>を参照してください。
特定のアトリビュートをコマンドライン引数から設定不可能にしたい場合はMooseX::Getopt::Meta::Attribute::Trait::NoGetoptかMooseX::Getopt::Meta::Attribute::NoGetoptを参照してください。
また、デフォルトではアンダースコア(「_」)で始まるアトリビュートはアトリビュートのメタクラスにMooseX::Getopt::Meta::Attributeが指定されていない限りはコマンドラインからの処理がされません。そのようなアトリビュートのアクセッサもアンダースコア付きにしたくない場合は以下のようにできます:
# 読み込み/書き込みアトリビュートの場合 has '_foo' => (accessor => 'foo', ...); # 読み込み専用アトリビュートの場合 has '_bar' => (reader => 'bar', ...);
このようにすることでGetoptは--foo引数を適用しなくなりますが、fooメソッドは使用できるようになります。
もし該当クラスがMooseX::SimpleConfigのようなMooseX::ConfigFromFileベースの設定ファイルを使うロールを使用している場合は、MooseX::Getoptのnew_with_optionsは--configfile引数(もしくはconfigfileアトリビュートに渡された値)に指定された内容を読み込みます。
オプションはコマンドライン、設定ファイル、そしてnew_with_optionsに渡された引数の順番で適用されます。
Bool型はGetopt::Longの論理値オプションとして認識されます。以下のような場合
has 'verbose' => (is => 'rw', isa => 'Bool');
はGetopt::Longのverbose!と同等として扱われ、以下のようなコマンドライン引数として指定できるようになります:
% my_script.pl --verbose % my_script.pl --noverbose
これらの型はそれぞれGetopt::Longの=i、=f、=sとして処理されます。
ArrayRef型は複数回指定可能な引数として処理されます。例えば以下の場合、
has 'include' => (
is => 'rw',
isa => 'ArrayRef',
default => sub { [] }
);
Getopt::Longにはincludes=s@として扱われ、以下のようにコマンドラインから指定することが可能になります:
% my_script.pl --include /usr/lib --include /usr/local/lib
HashRef型はGetopt::Longのハッシュ型引数として扱われ、名前=値のペアを指定できるようになります。例えば以下の場合、
has 'define' => (
is => 'rw',
isa => 'HashRef',
default => sub { {} }
);
Getopt::Longにはdefine=s%として扱われ、以下のようにコマンドラインから指定することが可能になります:
% my_script.pl --define os=linux --define vendor=debian
カスタムな型制約を引数スペックにマップする事も可能です。まず以下のように型制約を作成します:
use Scalar::Util qw(looks_like_number);
subtype 'ArrayOfInts' # 整数リスト
=> as 'ArrayRef'
=> where { scalar (grep { looks_like_number($_) } @$_) };
その後、引数スペックへのマッピングを登録します:
MooseX::Getopt::OptionTypeMap->add_option_type_to_map(
'ArrayOfInts' => '=i@'
);
このようにすることでこの型を使ったアトリビュートは新たに登録された引数スペックを使うようになります。
has 'nums' => (
is => 'ro',
isa => 'ArrayOfInts',
default => sub { [0] }
);
上記アトリビュートは、以下のコマンドライン引数から取得可能になります:
% my_script.pl --nums 5 --nums 88 --nums 199
この例は非常にシンプルな物ですが、ちょっと想像力を使えば複雑なバリデーションを絡めた引数も設定することができます。注意すべき点はGetopt::Longのバリデーションとアトリビュートのバリデーションをうまくバランスを保って組み合わせる事です。
もちろん、より良い例があればドキュメントに追加しますのでお知らせください :)
上記「サポートされる型制約」の項で紹介した型のsubtypeとしてカスタムな型制約を登録し、なおかつ明示的に引数スペックへのマッピングを登録しない場合、MooseX::Getoptは親の型の引数マッピングを使用します。
例えば、上記例のようにArrayOfInts型を定義し、引数スペックをOptionTypeMapに登録しない場合は普通のArrayRef型と同様の処理(=@s)がなされます。
引数@ARGVからオブジェクトのアトリビュート初期値を受け取り、新規にオブジェクトを作成します。%paramsにデフォルト値を指定します(@ARGVの値が指定されている場合はそちらを優先します)。
任意の引数argvにリストへのリファレンスを指定することにより@ARGVの代わりに使用される値を指定することができます。
GetOptions in Getopt::Longの処理が(無効な引数などの理由で)失敗した場合はnew_with_optionsは例外を投げます。
システムにGetopt::Long::Descriptiveがインストールされていて、以下のコマンドライン引数が渡された場合は、使用法を出力した後プログラムを終了します:
--? --help --usage
それぞれのアトリビュートのドキュメントははdocumentationオプションをアトリビュートに指定することによって指定することができます。
システムにGetopt::Long::Descriptiveがインストールされている場合はusage引数もnewに渡されます。
このアクセッサはnew_with_optionsが呼ばれた時点の@ARGVのコピーへのリファレンスを保持します。
このアクセッサはGetopt::Longが処理できなかった@ARGVの「余り」を保持します。@ARGV本体は変更されません。
ロールのメタオブジェクトを返します。
All complex software has bugs lurking in it, and this module is no exception. If you find a bug please either email me, or add the bug to cpan-RT.
Stevan Little <stevan@iinteractive.com>
Brandon L. Black, <blblack@gmail.com>
Yuval Kogman, <nothingmuch@woobling.org>
Ryan D Johnson, <ryan@innerfence.com>
Drew Taylor, <drew@drewtaylor.com>
Copyright 2007-2008 by Infinity Interactive, Inc.
This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
