11
11

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Dartでコマンドライン引数を受け取る

Last updated at Posted at 2014-07-20

DartはサーバーサイドでもスタンドアロンVMにより実行可能ですので、当然コマンドライン引数を受け取ることが出来ます。

引数を文字列として受け取る

単純にコマンドライン引数を文字列のリストとして受け取る方法です。

simple_args.dart
void main(List<String> args){
  print(args);
}
command-line
$ dart simple_args.dart --test simple -r hogehoge
stdout
[--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引数を渡します。

ここまでで次のようなコードになります。

concat_args.dart
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]

完成したコードがこちら

concat_args.dart
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);
}
command-line
$ dart concat_args.dart --output out.min.js -t js -c input1.js input2.js
stdout
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を定義する際は次のようにパースを移譲することができます。

git.dart
  var parser = new ArgParser();
  var commitParser= new ArgParser();
  parser.addCommand('commit', commitParser);

実行されたコマンドはresults.command.nameで取得することができ、コマンドに渡されたオプションはresults.command[name]で取得します。

git.dart
  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"]);
help
--type            Target file type
                  [js, css]

フラグでないオプションにはヘルプ用の値を与えることが出来ます。

parser.addOption("output", help: "The output path", helpValue: "path");
help
--output=<path>      The output path

あとはヘルプ用のフラグを受け取って、getUsage()を出力するだけです。

git.dart
  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()); // 出力
    }
  }

その他細かい仕様や使い方は公式のドキュメントを読んでください。

11
11
1

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
11
11

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?