DartはサーバーサイドでもスタンドアロンVMにより実行可能ですので、当然コマンドライン引数を受け取ることが出来ます。
引数を文字列として受け取る
単純にコマンドライン引数を文字列のリストとして受け取る方法です。
void main(List<String> args){
print(args);
}
$ dart simple_args.dart --test simple -r hogehoge
[--test, sample, -r, hogehoge]
main()
の引数の型はList<String>
です。『配列じゃないのか』と思うかもしれませんが Dartに配列はないです 。また、言うまでもありませんがmain(List args)
やmain(args)
でもOKです。
受け取るのは簡単ですがこのままだと文字列なので扱いづらいですね。受け取った文字列配列をいい感じにパースしてくれるライブラリがあります。args
( https://pub.dartlang.org/packages/args )です。
argsパッケージを使う
まずはpubでargsをインストールしてください。
$ pub install args
ArgParserを定義する
コマンドライン引数から受け取るオプション(--key value)やフラグ(--flag)を定義します。省略形も簡単に定義できます。
今回は複数のjsファイルまたはcssファイルを結合・圧縮するminifyプログラムを想定します。次のコマンドをパースして4つの引数を取得してみます。
$ dart concat_args.dart --output out.min.js -t js -c input1.js input2.js
-
--output
,-o
: 出力先ファイル名(オプション, 無制限) -
--type
,-t
: 形式(オプション, js | css) -
--compress
,-c
: 圧縮するかどうか(フラグ, 規定値:false) - 結合されるファイル名(複数)
まずoutput
オプションを定義します。
parser.addOption("output", abbr:"o");
特に制限のない--key value
ペアのオプションはparser.addOption(name)
で定義できます。省略形の定義はabbr:
引数を渡します。
次にtype
オプションを定義します。type
オプションはjs
もしくはcss
を受け取ります。
parser.addOption("type", abbr:"t", allowed:["js", "css"]);
いくつかの候補から選択させるタイプのオプションはallowed:[]
引数を渡すことで内容を制限できます。
最後にcompress
フラグを定義します。規定値はfalseとします。
parser.addFlag("compress", abbr:"c", defaultsTo:false);
規定値を設定したい場合はdefaultsTo
引数を渡します。
ここまでで次のようなコードになります。
import "package:args/args.dart";
void main(List<String> args){
var parser = new ArgParser();
parser.addOption("output", abbr:"o");
parser.addOption("type", abbr:"t", allowed:["js", "css"]);
parser.addFlag("compress", abbr:"c", defaultsTo:false);
}
パースする
定義したArgParserを使ってコマンドライン引数をパースします。
パースを行うにはparser.parse
メソッドを呼びます。
var results = parser.parse(args);
resultsの型はArgResultsです。ArgResultsから値を取り出すにはそれぞれ定義したオプション、フラグの名前を使います。
print(results["output"]); //out.min.js
print(results["type"]); // js
print(results["compress"]); // true
オプション、フラグの後に与えられるrest引数はresults.rest
でアクセスできます。
print(results.rest); //[input1.js, input2.js]
完成したコードがこちら
import "package:args/args.dart";
void main(List<String> args){
var parser = new ArgParser();
parser.addOption("output", abbr:"o");
parser.addOption("type", abbr:"t", allowed:["js", "css"]);
parser.addFlag("compress", abbr:"c", defaultsTo:false);
var results = parser.Parse(args);
print(results["output"]);
print(results["type"]);
print(results["compress"]);
print(results.rest);
}
$ dart concat_args.dart --output out.min.js -t js -c input1.js input2.js
out.min.js
js
true
[input1.js, input2.js]
注意
定義していない名前のオプション、フラグが与えられるとFormatExceptionが発生する
予想外の名前のオプション、フラグが与えられるとパースに失敗して例外が発生します。try-catchで処理して、適切なエラーメッセージを返すといいでしょう。
allowedに含まれていない値が与えられるとFormatExceptionが発生する
上記のプログラムに-t html
等、許容外の値を与えると例外が発生します。
フラグに値を与えてはいけない
フラグである-c
に-c true
等、値を与えると、true
はオプションでもフラグでもないrest引数とみなされ、それ以降のパースに影響します。(次の注意を参照)
rest引数は必ずオプション、フラグの後でなければならない
ArgParserは、オプションでもフラグでもない引数を見つけるとそこから後の引数を全てrest引数であるとみなします。なので前述のフラグに与えられた値は最初のrest引数ということになって、その後の引数もすべてrestになります。
オプションを順序に関係なく受理するにはArgParserの生成時にallowTrailingOptions
を渡します。
var parser = new ArgParser(allowTrailingOptions: true);
コマンドの定義
例えばgitではcommitやpushなど、gitに続けてコマンド名を渡します。コマンドによってその後のオプションの種類や処理は変わるので、上記のArgParserで定義するのは至難の業です。そこで2番目に与えられるコマンド名によってArgParserを切り替えるcommand
という仕組みがあります。
例えばgit commit
を定義する際は次のようにパースを移譲することができます。
var parser = new ArgParser();
var commitParser= new ArgParser();
parser.addCommand('commit', commitParser);
実行されたコマンドはresults.command.name
で取得することができ、コマンドに渡されたオプションはresults.command[name]
で取得します。
var parser = new ArgParser();
var commitParser= new ArgParser();
parser.addCommand("commit", commitParser);
commit.addFlag("all", abbr:"a");
var results = parser.parse(["commit", "-a"]);
// print(result["all"]); // FormatException
print(result.command.name); // commit
print(result.command["all"]); // true
コマンド名を取得した後はswitch-caseでコマンドごとに処理をするといいと思います。
helpを表示する
--help
で使い方を表示するために、オプションに説明文を付け足すことが出来ます。
parser.addOption("type", help: "Target file type",
allowed: ["js", "css"]);
--type Target file type
[js, css]
フラグでないオプションにはヘルプ用の値を与えることが出来ます。
parser.addOption("output", help: "The output path", helpValue: "path");
--output=<path> The output path
あとはヘルプ用のフラグを受け取って、getUsage()
を出力するだけです。
var parser = new ArgParser();
var commitParser= new ArgParser();
parser.addCommand("commit", commitParser);
commit.addFlag("all", abbr:"a", help:"Commit all files");
parser.addFlag("help", abbr:"h"); // helpフラグは親Parserに
var results = parser.parse(["commit", "--help"]);
if(results["help"]){
switch(results.command.name){
case "commit":
print(commitParser.getUsage()); // 出力
}
}
その他細かい仕様や使い方は公式のドキュメントを読んでください。