読者です 読者をやめる 読者になる 読者になる

M12i.

学術書・マンガ・アニメ・映画の消費活動とプログラミングについて

CLI構築ライブラリ"Unclazz.Commons.CLI"をつくってみた

C#

昨日JSONパーサー/ビルダーでしたが、調子に乗って今度はCLI構築ライブラリを切り出しました。「切り出す」といってもだいぶ独自のものに仕上がってしまいましたが。。

Unclazz.Commons.CLIは.NETランタイム上で実行するコンソール・アプリケーションからコマンドライン・オプションのパースを行うためのライブラリです。開発開始の当初念頭にあったのはApache Commons CLIですが結果的にはまったくの別物となっています。アセンブリNuGet Galleryで公開されているので、NuGetを通じて取得することができます。

コンポーネント

このライブラリの提供するAPIはいずれもUnclazz.Commons.CLI名前空間で提供されています。

ICommandLineIOptionはそれぞれコマンドラインとそのオプションの定義を表わすものです。このインターフェースが提供するAPIを通じて定義済みのコマンドラインの情報にアクセスできることはもちろん、アプリケーションのユーザがシェルやコマンドプロンプトで指定した引数のパースを行うことができます。

CommandLineOptionは前述のインターフェースを実装した具象クラスです。CommandLine.Builder(string)Option.Builder(string)を通じて得られるビルダーを使うことでそのインスタンスを構築することができます。

HelpFormatterはICommandLineのインスタンスをもとにヘルプ表示のフォーマットを行うクラスです。

使用例

Unclazz.Commons.CLI.Sampleプロジェクトにサンプル・コードを格納しています。これはTac.MetaServlet.Clientのサンプル・アプリケーションのCLIを模倣したものです:

var ps = new Parameters();
var b = CommandLine.Builder("TACRPC.EXE");

// コマンドライン全体に関わる設定
b.Description("TAC(Talend Administration Center)のRPCインターフェースである" +
               "MetaServletに対してコマンドラインからアクセスする手段を提供します.")
 .CaseSensitive(false);

// Jオプション
b.AddOption(Option.Builder("/J")
    .AlternativeName("/JSON")
    .ArgumentName("json-file")
    .Description("RPCリクエストを表わすJSONが記述されたファイルのパス.")
    .HasArgument()
    .Required()
    .SetterDelegate((string s) => ps.RequestJson = s));

// H, P, Qオプション
b.AddOption(Option.Builder("/H")
    .AlternativeName("/HOST")
    .ArgumentName("host")
    .Description("RPCリクエスト先のホスト名. デフォルトは\"localhost\".")
    .HasArgument()
    .SetterDelegate((string s) => ps.RemoteHost = s))
.AddOption(Option.Builder("/P")
    .AlternativeName("/PORT")
    .ArgumentName("port")
    .Description("RPCリクエスト先のポート名. デフォルトは8080.")
    .HasArgument()
    .SetterDelegate((int i) => ps.RemotePort = i))
.AddOption(Option.Builder("/Q")
    .AlternativeName("/PATH")
    .ArgumentName("path")
    .Description("RPCリクエスト先のパス名. デフォルトは" +
    "\"/org.talend.administrator/metaServlet\".")
    .HasArgument()
    .SetterDelegate((string s) => ps.RemotePath = s));

// Tオプション
b.AddOption(Option.Builder("/T")
    .AlternativeName("/TIMEOUT")
    .ArgumentName("timeout")
    .Description("RPCリクエストのタイムアウト時間. 単位はミリ秒. デフォルトは100000.")
    .HasArgument()
    .SetterDelegate((int i) => ps.RemotePort = i));

// Dオプション(フラグ)
b.AddOption(Option.Builder("/D")
    .AlternativeName("/DUMP")
    .Description("リクエストとレスポンスのダンプ出力を行う.")
    .SetterDelegate(() => ps.ShowDump = true));

// コマンドライン定義を構築
var cmdln = b.Build();

// コマンドラインをパース
cmdln.Parse(new string[] { "/j", "path/to/json", "/d", "/p", "8888" });

Console.WriteLine("ps.RequestJson = {0}", ps.RequestJson);
Console.WriteLine("ps.RemotePort  = {0}", ps.RemotePort);
Console.WriteLine("ps.ShowDump    = {0}", ps.ShowDump);

コードの末尾でコマンドラインのパースを行っています。標準出力には以下のような出力がなされるでしょう:

ps.RequestJson = path/to/json
ps.RemotePort  = 8888
ps.ShowDump    = True

最後にヘルプ表示を行ってみましょう:

// デフォルトのオプションでヘルプ表示
Console.WriteLine(new HelpFormatter().Format(cmdln));

このコードを実行すると以下のような出力がなされます:

Syntax:
                    TACRPC.EXE /J <json-file> [/D] [/H <host>] [/P <port>] [/Q <
                    path>] [/T <timeout>]

Description:
                    TAC(Talend Administration Center)のRPCインターフェースであるMetaServletに
                    対してコマンドラインからアクセスする手段を提供します.

Options:
/D, /DUMP           リクエストとレスポンスのダンプ出力を行う.
/H, /HOST           RPCリクエスト先のホスト名. デフォルトは"localhost".
/J, /JSON           RPCリクエストを表わすJSONが記述されたファイルのパス.
/P, /PORT           RPCリクエスト先のポート名. デフォルトは8080.
/Q, /PATH           RPCリクエスト先のパス名. デフォルトは"/org.talend.administrator/metaServlet"
                    .
/T, /TIMEOUT        RPCリクエストのタイムアウト時間. 単位はミリ秒. デフォルトは100000.