「Dart Advent Calendar 2014」 11日目は@zukkunが担当します。
Dartは、JavaScriptの代替として登場しましたが、独自のVMを持ち、コマンドラインからDartのプログラムを実行する環境が提供されています。
今回は、Dartでのコマンドラインツールを作る方法を、以下のページを参考にしながら紹介しようと思います。
Write Command-Line Apps | Dart: Structured web apps
動作確認環境はMac OS X 10.9.5です。(Dartは、Windows、Linuxでも使えます)
Dartをインストール
Dartがインストールされていなければ、まずDartをインストールします。
Mac環境では、Homebrewを使ってDartをインストールすることができます。
$ brew tap dart-lang/dart
$ brew install dart
はじめにbrew tap
でリポジトリを追加する必要があるので注意です。
参考:Dart News & Updates: Dart launches support for Homebrew
インストールができたら、Dartがインストールされたか確認します。
$ dart --version
Dart VM version: 1.7.2 (Tue Oct 14 06:58:25 2014) on "macos_x64"
簡単なDartプログラムを書く
まず、簡単なDartのプログラムを書きます。
main() {
print('hello');
}
これを実行してみます。
$ dart hello.dart
hello
hello
が出力されます。
これで一応コマンドラインのアプリケーションが作れました。
もう少しコマンドラインツールっぽくしてみましょう。
コマンドライン引数を受け取る
Dartでコマンドライン引数を受け取るには、main
関数の引数にList<string>
を型とした引数を加えます。
main(List<string> arguments) {
print('hello $arguments');
}
引数の内容をそのままhello
のあとに表示するようにしてみました。
試しに適当に引数を与えて実行してみます。
$ dart hello.dart foo bar 123
hello [foo, bar, 123]
コマンドライン引数がリストとしてそのまま文字列展開されて出力されました。
コマンドライン引数を解析する
自力でコマンドライン引数の内容を解析してもいいですが、複雑なものとなるとけっこう大変です。
そんなときは、このパッケージを使いましょう。
args 0.12.1 | Pub Package Manager
こちら、パッケージとして公開されていますが、Dart Team謹製の公式パッケージです。
パッケージをインストールするために、pubspec.yaml
を書きます。
name: hello
dependencies:
args: any
依存パッケージにargs
を追加しました。
pub get
で依存パッケージを取得します。
$ pub get
Resolving dependencies... (2.5s)
+ args 0.12.1
+ collection 1.1.0
Downloading collection 1.1.0...
Changed 2 dependencies!
真偽値としてオプションを受け付ける
Dartプログラムに、コマンドライン引数の解析の処理を追加します。
import 'package:args/args.dart';
ArgResults argResults;
main(List<string> arguments) {
final parser = new ArgParser()
..addFlag('hoge', negatable: false, abbr: 'h');
argResults = parser.parse(arguments);
print('hello ${argResults['hoge']}');
}
ArgParser
のaddFlag
で「オプションを指定したか、していないか」の真偽値で引数を受け取ることができます。
negatable
は、否定形の引数を受け付けるかを指定できます。(falseを指定しなければ、--no-hoge
という指定を受け付ける)
abbr
はAbbreviationの略で、「省略」を意味します。今回'h'
としているので、-h
という指定でも--hoge
と同じ意味を持たせることが出来ます。
$ dart hello.dart --hoge
hello true
$ dart hello.dart
hello false
$ dart hello.dart -h
hello true
値付きのオプションを受け付ける
真偽値ではなく値付きでオプションを受け付ける場合は、addOption
を使います。
import 'package:args/args.dart';
ArgResults argResults;
main(List<string> arguments) {
final parser = new ArgParser()
..addFlag('hoge', negatable: false, abbr: 'h')
..addOption('foo', abbr: 'f');
argResults = parser.parse(arguments);
print('hello ${argResults['foo']}');
}
$ dart hello.dart --foo bar
hello bar
$ dart hello.dart
hello null
他にも、デフォルト値の指定や、バリデーションの機能など、盛りだくさんです。
また、GitやRailsなどで見る<プログラム名> <コマンド名> <パラメータ>
のような「コマンド形式」でのコマンドライン引数の受け取りのためのaddCommand
などもあります。
コマンドラインツールをインストールする
作ったコマンドラインツールを実行するためにはdart hello.dart
のように、dart
コマンドの引数としてプログラムのファイル名を指定してあげる必要がありましたが、これをhello
という独立したコマンドとして実行できるように環境にインストールすることができます。
まず、先ほど作ったhello.dart
を、pubspec.yaml
があるディレクトリから見てbin/hello.dart
としてファイルを移動させます。(binディレクトリ無ければ作ります)
そして、pubspec.yaml
にexecutables
を追加し、その中にhello
を追加します。
name: hello
dependencies:
args: any
executables:
hello:
次にpub global
というコマンドを使用します。
参考:pub global | Dart: Structured web apps
通常は、pub.dartlang.orgに公開された実行可能なパッケージをインストールするときに使用しますが、先ほど作成したhello.dartをインストールしてみます。(pub global上では「インストール」ではなく「アクティベート」と呼んでいますが、便宜上インストールと書きます)
pub global
のあとにactivate
を指定し、--source path
オプションをつけ、そのあとにpubspec.yaml
が存在するパスを指定することで、ローカル環境にあるパッケージを指定してインストールできます。
$ cd <pubspec.yamlがあるパス>
$ pub global activate --source path .
Activated hello 0.0.0 at path "<pubspec.yamlがあるパス>".
Installed executable hello.
これでhello
というコマンドが使えるようになりました。
$ hello
hello null
$ hello --foo bar
hello bar
hello
コマンドの実態は~/.pub-cache/bin/hello
として作られており、中身は以下のようになっています。
#!/usr/bin/env sh
# This file was created by pub v1.7.2.
# Package: hello
# Version: 0.0.0
# Executable: hello
# Script: hello
pub global run hello:hello "$@"
pub global
のアクティベートまわりやrun
などの仕様の説明については割愛します。
コマンドラインツールをアンインストールする
インストールしたコマンドラインツールをアンインストールする場合はpub global deactivate
を使います。
$ pub global deactivate hello
Deactivated package hello 0.0.0 at path "<先ほどのpubspec.yamlがあったパス>".
これでhello
が使えなくなりました。
$ hello
zsh: command not found: hello
細かい機能や仕様の話など、まだまだ語り尽くせないものがありますので、機会があれば触って解説できたらと思います。
明日は…………担当者がいない?!どうする @laco0416 さん!
Twitterより引用
@zukkun「@laco0416 Dart Advent Calendarの明日の担当者いません!」
@laco0416「@zukkun 書いてどうぞ!」
明日は@zukkunさんです!俺だ!