Dart
DartDay 5

Dartメモ:コマンドライン引数の処理

自分用メモです。

引数をとる

コード
void main(List<String> args) {
    print(args);
}
実行
$ dart hoge1.dart -n -l 3 --some=1 2 3
[-n, -l, 3, --some=1, 2, 3]

hoge1.dart がargs[0]になったりはせず、純粋に引数がargsに渡されるようだ。

引数を解釈する

PythonのargparseみたいなのがDartでは標準パッケージにあるらしい。

  • true/falseをもらいたい引数には addFlag
    • --no-xxxxx という引数を処理したくないときには negatable: false
    • デフォルトtrueにしたいときには defaultsTo: true
  • 値をもらいたい引数には addOption
コード
import 'package:args/args.dart';

void main(List<String> args) {
    val parser = new ArgParser()
                    ..addFlag('no-br', negatable: false, abbr: 'n')
                    ..addOption('length', abbr: 'l')
                    ..addOption('some');
    val argResults = parser.parse(args);

    print(['no-br', argResults['no-br']]);
    print(['length', argResults['length']]);
    print(['some', argResults['some']]);
    print(['rest', argResults.rest]);
}
実行
$ dart hoge1.dart -n -l 3 --some=1 2 3
[no-br, true]
[length, 3]
[some, 1]
[rest, [2, 3]]

あとは、サブコマンドもシンプルに addCommand で定義できるっぽい。

コード
import 'package:args/args.dart';

void main(List<String> args) {
    val postParser = new ArgParser()
                    ..addOption('message')
                    ..addOption('token');
    val observeParser = new ArgParser()
                    ..addOption('channel', abbr: 'c')
                    ..addFlag('print');
    val parser = new ArgParser()
                    ..addCommand('post', postParser)
                    ..addCommand('observe', observeParser);

    val argResults = parser.parse(args);

    switch(argResults.command.name) {
        case 'post':        
            print(['message', argResults.command['message']]);
            print(['token', argResults.command['token']]);
            break;
        case 'observe':
            print(['channel', argResults.command['channel']]);
            print(['print', argResults.command['print']]);
            break;
    } 
}
実行
$ dart hoge1.dart post --message hogehoge
[message, hogehoge]
[token, null]
$ dart hoge1.dart observe -c hoge
[channel, hoge]
[print, false]

ただ、addCommandよりもCommandRunnerを使うほうが推奨らしい。

コード
import 'package:args/command_runner.dart';

class PostCommand extends Command {
    final name = "post";
    final description = "Post a new message.";
    PostCommand() {
        argParser
            ..addOption('message')
            ..addOption('token');
    }

    void run() {
        print(['message', argResults['message']]);
        print(['token', argResults['token']]);
    }
}

class ObserveCommand extends Command {
    final name = "observe";
    final description = "Observe user messages via RTM.";
    ObserveCommand() {
        argParser
            ..addOption('channel', abbr: 'c')
            ..addFlag('print');
    }

    void run() {
        print(['channel', argResults['channel']]);
        print(['print', argResults['print']]);
    }
}

void main(List<String> args) {
    new CommandRunner("slack", "Slack Commandline interface")
        ..addCommand(new PostCommand())
        ..addCommand(new ObserveCommand())
        ..run(args);
}
実行
$ dart hoge1.dart post --message hogehoge
[message, hogehoge]
[token, null]
$ dart hoge1.dart observe -c hoge
[channel, hoge]
[print, false]

ただ、CommandRunnerは argParserやargResultsが暗黙的に定義されていたり、nameとかdescriptionとかが実は定義必須だったり、暗黙的にいろいろやってるのが若干イマイチ感ある。