C#/.NET のコンソールアプリで、実行コマンドに渡された引数の解析と、helpオプションで表示するヘルプメッセージ(Usage)用の文字列生成を行う機能をあわせてライブラリ化しました。
CuiCommandParser(NuGet)
ソースはこちら。
READMEにだいたい書いたんだけども、一応こちらにも日本語で。
何をするもの?
一般的なUnixスタイルのコマンド引数の解析をするのと、Usageのメッセージをそれっぽい書式で作るもの。
-h
とか--hoge
とかの形でオプションを指定する想定-xyz
のようにオプションをまとめて指定することもできる- オプションとその値とは
=
または半角スペースでつなぐ
使い方
主なクラスは以下2つ
CommandParser
コマンド解析クラス。
オプション情報を RegisterOption
で登録してから Parse
を実行する。
$ mv -S=_bu note.txt child_dir/
という感じで実行されたmvコマンドの解析例を以下に。
static void Main(string[] args) { var parser = new CommandParser(); var options = new[] { new CommandOption(null, "backup", "CONTROL", "削除されるファイルのバックアップを作成する", CommandOptionKind.HasOptionalValue), new CommandOption('b', null, null, "backupオプションと同じだが、引数をとれない", CommandOptionKind.NoValue), new CommandOption('f', "force", null, "確認をせずに上書きをする", CommandOptionKind.NoValue), new CommandOption('S', "suffix", "SUFFIX", "バックアップの形式を決める", CommandOptionKind.NeedsValue), //... }; foreach (var opt in options) { parser.RegisterOption(opt); } var parsed = parser.Parse(args); if (parsed == null) { //オプションの指定が不正だった場合 return; } //オプション以外のパラメータ var parameters = parsed.CommandParameters; // -> [ "note.txt", "child_dir/" ] //オプションの有無を確認(以下全て同じ) var forced = parsed.HasOption('f'); // -> false // var forced = parsed.HasOption("force"); // var forced = parsed.HasOption(options[2]); //オプションの値を取得(以下全て同じ) var suffix = parsed.GetOptionValue('S'); // -> "_bu" // var suffix = parsed.GetOptionValue("suffix"); // var suffix = parsed.GetOptionValue(options[3]); }
CommandUsageBuilder
Usage生成クラス。
CommandParser
に RegisterOption
してから NewUsageBuilder
を呼べば、登録したオプション情報を引き継いでビルダインスタンスを生成できる。
同じく mv
コマンドの例。
var builder = parser.NewUsageBuilder("mv"); builder.OptionKeyValueSeparator = '='; builder.Summary = "ファイル名の変更、もしくは複数のファイルをディレクトリへ移動します。"; builder.AddUseCase(builder.NewUseCase().AddArg(builder.NewUseCaseArg("OPTION").AsMultiple().AsOptional()) .AddArg(builder.NewUseCaseArg("-T").AsOptional()) .AddArg(builder.NewUseCaseArg("SOURCE")) .AddArg(builder.NewUseCaseArg("DEST"))); builder.AddUseCase(builder.NewUseCase().AddArg(builder.NewUseCaseArg("OPTION").AsMultiple().AsOptional()) .AddArg(builder.NewUseCaseArg("SOURCE").AsMultiple()) .AddArg(builder.NewUseCaseArg("DIRECTORY"))); builder.AddUseCase(builder.NewUseCase().AddArg(builder.NewUseCaseArg("OPTION").AsMultiple().AsOptional()) .AddArg(builder.NewUseCaseArg("-t").Value("DIRECTORY")) .AddArg(builder.NewUseCaseArg("SOURCE").AsMultiple())); Console.WriteLine(builder.ToString());
出力結果
ファイル名の変更、もしくは複数のファイルをディレクトリへ移動します。 Usage: mv [OPTION]... [-T] SOURCE DEST or: mv [OPTION]... SOURCE... DIRECTORY or: mv [OPTION]... -t=DIRECTORY SOURCE... Arguments: --backup[=CONTROL] 削除されるファイルのバックアップを作成する -b backupオプションと同じだが、引数をとれない -f, --force 確認をせずに上書きをする -S, --suffix=SUFFIX バックアップの形式を決める
以上。
NuGetで検索すると似たような名前のライブラリがけっこうあったので、たぶん同じようなことできるライブラリもあるんだろうけど、期待通りの動きするものを探すのもけっこう手間で、このくらいのものなら作ってしまったほうが早かったりしますね。