MS_CLISystemCommandLine - NetDevInfraWGinOSSConsortium/NetDevInfraWiki GitHub Wiki

CLI開発System.CommandLine

抂芁

自䜜 CUICLIを開発する際に䟿利なのではず。

https://github.com/dotnet/command-line-api/blob/main/docs/History.md

補足System.CommandLine の立ち䜍眮ず、泚意すべき珟況: 本ラむブラリは
**Microsoft 公匏dotnet 組織**であり、
dotnet CLI 自身の蚭蚈思想が反映されおいる。

【䜕を提䟛するか】
   ・コマンドラむン匕数の【解析】
   ・ヘルプの【自動生成】
   ・シェルの【タブ補完】の生成
   ・゚ラヌ メッセヌゞの敎圢
      → 「CLI ずしお圓然備えるべきもの」を䞀通り面倒みる ★

移行メモバヌゞョンに匷く䟝存する点に泚意: 本ラむブラリは
長期にわたりプレビュヌbetaのたた提䟛され、
API が䜕床も砎壊的に倉曎された
。

【経緯】
   2019   2.0.0-beta1 系。長期間 beta のたた
   2023頃   2.0.0-beta4 で倧きく敎理
   その埌   さらに API を簡玠化Handler の曞き方が倉わった★

【実務での察応】
   ・【バヌゞョンを固定しお䜿う】PackageReference で明瀺
   ・Web 䞊のサンプルが【どの beta 版のものか】を必ず確認する
      → 本ペヌゞのサンプルも圓時のもの
   ・曎新する際は【必ず動䜜確認する】

以降の各節では、原文の内容抂念は珟圚も通甚するため
そのたた残し、珟圚の曞き方を補足する圢をずる。

詳现

機胜

System.CommandLine

  • コマンドラむン・パヌサヌ

    • コマンド

      • ルヌト・コマンド
      • サブ・コマンド
    • オプション

      • スタむル
        ・POSIX-XXX
        ・Windows/XXX

      • ゚むリアス
        ・POSIX-v ず --verbose
        ・Windows゚むリアス無し

    • 匕数

      • デリミタ
        ・スペヌス
        ・「:」や「=」

      • arity
        匕数の最小倀ず最倧倀を蚭定できる。

      • バンドル
        ・文字のオプションはバンドル可胜。
        ・バンドルした堎合、バンドル内の最埌のオプションに匕数が適甚される。

    • バむンディング

    • Ctrl-C
      https://github.com/dotnet/command-line-api/blob/main/docs/Process-termination-handling.md

    • レスポンス・ファむル
      レスポンス・ファむルを䜿甚しおコマンドを指定できる。

補足甚語の具䜓化: 䞀芧が簡朔なので、
実際のコマンドラむンでの意味を瀺しおおく。

【コマンドサブコマンド】
   dotnet build --configuration Release
   └─┬─┘ └─┬─┘ └────────┬────────┘
   ルヌト  サブ         オプション

【arity匕数の個数】
   ExactlyOne  
 --name foo            必ず 1 ぀
   ZeroOrOne   
 --verbose             倀なしでもよい
   ZeroOrMore  
 --file a.txt b.txt    0 個以䞊
   OneOrMore   
 少なくずも 1 ぀
     → 「--file を 3 回たで」ずいった制玄も衚珟できる ★

【バンドル】
   -a -b -c   →  -abc      1 文字オプションをたずめる
   -abc value →  c に value が適甚される最埌のオプションに付く

【デリミタ】
   --name foo   /  --name:foo  /  --name=foo   
 すべお同じ

レスポンス ファむルは知られおいないが䟿利である。

【問題】 コマンドラむン長には OS の䞊限があるWindows は玄 32,767 文字
         → 倧量のファむルを匕数で枡すず超える ★

【解】  匕数をファむルに曞き、@ で参照する
         > myapp @args.rsp

         args.rsp:
           --input a.txt
           --input b.txt
           --verbose

csc.exeC# コンパむラや MSBuild が叀くから䜿う仕組みで、
System.CommandLine はこれを暙準で解釈する。

  • その他

    • ヘルプ

      • ヘルプ

        > myapp -h
        > myapp /h
        > myapp --help
        > myapp -?
        > myapp /?
        
      • 解析ディレクティブ
        構文解析結果を衚瀺する。

        > myapp [parse]
        > myapp [parse] ...(コマンド)...
        
      • バヌゞョン

        > myapp --version
        1.0.0
        
    • Debug ディレクティブ

      > myapp [debug] ...(コマンド)...
      ココの埌、デバッガをアタッチしおデバッグ
      
    • パむプラむン

      • ハンドラぞのルヌティングの前の
        パむプラむンに呌び出しを远加できる。
      • ディレクティブは、この機胜を䜿甚しおいる。
  • 参考

補足ディレクティブが秀逞: [parse] ず [debug] は
この皮のラむブラリでは珍しい機胜で、実務で非垞に圹に立぀。

【[parse] ── 匕数がどう解釈されたかを芋る】★
   > myapp [parse] create --name foo -c 3
   [ myapp [ create <foo> [ --count <3> ] ] ]

   → 「なぜこのオプションが効かないのか」を
     【実行せずに】確認できる
   → 匕数の蚭蚈を怜蚌する際にも䜿える

【[debug] ── デバッガをアタッチする】★
   > myapp [debug] create --name foo
   Attach your debugger to process 12345

   → 【CLI をデバッグする難しさ】を解消する
     通垞、CLI は起動しお即実行されるため、
       デバッガを付ける隙がない
   → 本番環境で再珟する䞍具合の調査に有甚

ヘルプの自動生成も重芁な䟡倀である。

【手で曞くず必ず陳腐化する】
   ・オプションを远加したのにヘルプを盎し忘れる
   ・既定倀を倉えたのにヘルプが叀い

【自動生成なら】
   ・定矩が唯䞀の情報源single source of truth★
   ・ずれようがない

パむプラむンは OWIN /
ASP.NET Core のミドルりェアず同じ発想である
凊理の前埌に局を挟む。
ログ出力、実行時間の蚈枬、䟋倖の敎圢などを
党コマンド共通で挟める。

System.CommandLine.DragonFruit

匷力に型付けされた Main メ゜ッドを䜿っお、
慣習的にコマンドラむンアプリを構築する。

補足DragonFruit の発想ず珟況: **「芏玄による蚭定」**を
極端に掚し進めたもので、発想が面癜いので補足する。

// DragonFruitMain のシグネチャが【そのたたコマンドラむン仕様になる】★
/// <summary>ファむルを凊理したす。</summary>
/// <param name="input">入力ファむル</param>
/// <param name="verbose">詳现出力</param>
/// <param name="count">繰り返し回数</param>
static void Main(FileInfo input, bool verbose = false, int count = 1)
{
    // --input file.txt --verbose --count 3 が自動で解析されおくる
    // XML ドキュメント コメントが【ヘルプ文になる】
}
【利点】
   ・蚘述量が【ほがれロ】
   ・型FileInfo、int、enumから解析芏則が決たる
   ・XML コメントがヘルプになる ドキュメントず実装がずれない

【限界】
   ・サブコマンドが䜜れないMain は 1 ぀しかない
   ・现かい制埡ができない゚むリアス、arity、怜蚌
      → 【単機胜のツヌル向け】★

移行メモ: DragonFruit は珟圚ほが曎新されおいない。
同皮の「芏玄ベヌス」の遞択肢ずしおは、
ConsoleAppFramework自䜜CUICLIの話が
珟圹で、サブコマンドにも察応しおいる。

System.CommandLine.Rendering

移行メモRendering は開発が止たった: System.CommandLine.Rendering は
実隓的なパッケヌゞのたた、事実䞊開発が停止しおいる。

【珟圚、端末ぞの描画をしたいなら】
   ・【Spectre.Console】★ 衚・ツリヌ・進捗・色・マヌクアップ
   ・Terminal.Gui       
 党画面 TUI
   ・自前で ANSI ゚スケヌプ 
 単玔な色付けだけなら十分
// 単玔な色付けなら暙準 API で足りる
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine("゚ラヌ");
Console.ResetColor();

// ただし、リダむレクト時は色を出さない配慮が芁る ★
if (!Console.IsOutputRedirected && Environment.GetEnvironmentVariable("NO_COLOR") is null)
{ /* 色を䜿う */ }

NO_COLOR 環境倉数は近幎広く尊重されおいる慣習である
自䜜CUICLIの話 の「色ず装食は環境を芋お切る」。

System.CommandLine.Hosting

Microsoft.Extensions.Hosting で System.CommandLine を䜿甚するためのサポヌト

補足Hosting ずの統合の意味: これは
DI ず蚭定ずログを CLI にも持ち蟌むためのものである。

// ハンドラの匕数に、DI 登録したサヌビスを泚入できる ★
var builder = Host.CreateApplicationBuilder();
builder.Services.AddSingleton<IOrderService, OrderService>();
builder.Services.AddDbContext<AppDbContext>(...);
【これが効く堎面】
   ・CLI から【Web アプリず同じサヌビス局】を呌びたい
      → 䟋 バッチ凊理、デヌタ移行ツヌル、管理コマンド
   ・appsettings.json / 環境倉数から蚭定を読みたい
      → [.NET Core における DI](MS_DotNetCoreDI)
        [FaaS config](MS_FaaSConfig) ず同じ仕組み
   ・ILogger でログを出したい
      → [.NETのログ](MS_DotNetLogging)

 → 【Web / バッチ / CLI で実装を共有できる】★

珟圚は Microsoft.Extensions.Hosting を盎接䜿い、
Worker Service テンプレヌトから䜜る
方が玠盎な堎合も倚い
ASP.NET のプロゞェクト・テンプレヌトの倉遷。

dotnet-suggest

System.CommandLine を䜿っお䜜られたアプリに
シェルの補完機胜を提䟛するコマンドラむンツヌル。

補足タブ補完は CLI の䜿い勝手を倧きく倉える: 地味だが
利甚者䜓隓に最も効く機胜である。

【仕組み】
  ① シェルPowerShell / bash / zshに補完スクリプトを登録
  ② Tab を抌すず、シェルが dotnet-suggest を呌ぶ
  ③ dotnet-suggest が【察象アプリに問い合わせお】候補を返す
      → アプリ自身が候補を知っおいるので、【垞に最新】★
# PowerShell ぞの登録$PROFILE に曞く
dotnet-suggest register --command-path "C:\tools\myapp.exe"
【補完の蚭蚈】
   ・オプション名は自動で補完される
   ・【倀の候補も指定できる】
       option.AcceptOnlyFromAmong("dev", "stg", "prod");
       → --env <Tab> で 3 ぀が出る
   ・動的な候補DB から取埗等も蚭定できるが、
     【補完のたびに実行される】ので軜い凊理に限る ★

珟圚は dotnet-suggest を䜿わず、
各シェル向けの補完スクリプトを生成する方匏
も䞀般的である
myapp completion powershell > profile.ps1 のような圢。

サンプル実装

System.CommandLine

補足珟圚の曞き方の䟋: バヌゞョンによっお曞き方が倉わるため、
抂念が分かる圢で瀺す2.0 beta4 系以降のスタむル。

using System.CommandLine;

// オプションず匕数を定矩する
var fileOption = new Option<FileInfo>("--file", "-f")
{
    Description = "入力ファむル",
    Required = true,
};
var countOption = new Option<int>("--count", "-c")
{
    Description = "繰り返し回数",
    DefaultValueFactory = _ => 1,
};
countOption.Validators.Add(r =>          // ← 怜蚌もここに曞く ★
{
    if (r.GetValue(countOption) < 1) r.AddError("count は 1 以䞊");
});

// サブコマンドを組み立おる
var readCommand = new Command("read", "ファむルを読む")
    { fileOption, countOption };
readCommand.SetAction(parseResult =>
{
    var file  = parseResult.GetValue(fileOption);
    var count = parseResult.GetValue(countOption);
    for (var i = 0; i < count; i++) Console.WriteLine(file!.FullName);
    return 0;                            // ← 終了コヌドを返す ★
});

var root = new RootCommand("サンプル CLI") { readCommand };
return root.Parse(args).Invoke();
【蚭蚈䞊の芁点】
 ・【終了コヌドを返す】
     → 0 = 成功、非 0 = 倱敗
     → CI / スクリプトから䜿われる以䞊、唯䞀の機械可読な結果 ★
 ・怜蚌はハンドラではなく【Validator に曞く】
     → 実行前に匟ける。゚ラヌ メッセヌゞも敎圢される
 ・Required / DefaultValue を定矩に持たせる
     → ヘルプにも自動的に反映される

System.CommandLine.DragonFruit

https://github.com/dotnet/command-line-api/blob/main/docs/Your-first-app-with-System-CommandLine-DragonFruit.md

System.CommandLine.Rendering

System.CommandLine.Hosting

...

dotnet-suggest

...

参考

Microsoft Learn


Tags: 移行, シェル, むンフラストラクチャ, .NET開発

⚠ **GitHub.com Fallback** ⚠