MS_CLISharprompt - NetDevInfraWGinOSSConsortium/NetDevInfraWiki GitHub Wiki

CLI開発(Sharprompt)

概要

C# で Interactive な Prompt を構築するライブラリ。

補足(System.CommandLine との役割の違い): 兄弟ページの
CLI開発(System.CommandLine)
担当する範囲がまったく違うので、先に整理しておく
自作CUI(CLI)の話 でも触れた)。

【System.CommandLine】
   myapp create --name foo --count 3
   └──────── これを解析する ────────┘
      → 【引数・オプションの解析】。非対話が前提

【Sharprompt】
   ? 名前を入力してください: foo
   ? 種類を選択してください:
     > Web アプリ
       コンソール アプリ
       クラス ライブラリ
      → 【対話的に聞く】。TUI 寄り ★

両方を組み合わせるのが実際の使い方である。

【定石】
   ・引数で全部指定されていれば、そのまま実行する(CI で使える)
   ・足りない項目だけ Sharprompt で聞く(人が使うとき親切)
   ・--non-interactive / --yes が指定されたら、聞かずにエラーにする ★

 → [自作CUI(CLI)の話](MS_BuildingYourOwnCLI) の
   「対話を必須にしない」という設計指針そのもの

詳細

機能

以下のような機能がある模様。

Input

  • 文字列入力
  • 数値型などへのパース

Confirm

YES/NO の確認

Password

パスワード入力

Select

  • 単純な Select
  • 列挙型へのパース

MultiSelect

ページングできる Select

Custom Prompter

表示のカスタマイズ

補足(各機能の実際の書き方): 一覧だけでは掴みにくいので、
コードで示す型パラメータで戻り値の型が決まるのが特徴である。

using Sharprompt;

// Input:型を指定すればパースまで行う
var name  = Prompt.Input<string>("名前", validators: new[] { Validators.Required() });
var count = Prompt.Input<int>("件数", defaultValue: 10);

// Confirm
if (!Prompt.Confirm("実行しますか?", defaultValue: false)) return 1;

// Password:入力が画面に出ない
var pw = Prompt.Password("パスワード", placeholder: "8文字以上");

// Select:列挙型をそのまま渡せる ★
enum Kind { Web, Console, Library }
var kind = Prompt.Select<Kind>("種類");

// Select:任意のリスト(表示文字列を指定できる)
var user = Prompt.Select("担当者", users, textSelector: u => u.DisplayName);

// MultiSelect:複数選択(ページング付き)
var targets = Prompt.MultiSelect("対象", items, pageSize: 10, minimum: 1);

**Validators(入力検証)**が用意されている点が実務的である。

var mail = Prompt.Input<string>("メール", validators: new[]
{
    Validators.Required(),
    Validators.RegularExpression(@"^[^@\s]+@[^@\s]+$", "形式が不正です"),
});

列挙型を Select に渡せるのは、
列挙型(Enum)の定義 の値をそのまま
選択肢にできるということで、
選択肢の定義が 1 箇所で済む(画面とロジックがずれない)。

[Display(Name = "...")] で表示名を変えられる

enum Kind
{
    [Display(Name = "Web アプリケーション")] Web,
    [Display(Name = "コンソール アプリ")]    Console,
}

補足(対話的 CLI を作る際の注意点): Sharprompt に限らず、
対話型 UI をコンソールで作る際の共通の落とし穴を挙げておく。

① 【端末でない環境で動かない】★
     パイプ・リダイレクト・CI では標準入力が端末ではない
     → カーソル制御が効かない、入力を待って固まる

   【対策】
     if (Console.IsInputRedirected || Console.IsOutputRedirected)
     {
         // 対話をやめ、引数が足りなければエラー終了する
     }

② 【Ctrl+C の扱い】
     途中で中断された場合の後始末(一時ファイル、ロック)
     → Console.CancelKeyPress を捕まえる

③ 【文字幅】
     日本語(全角)は表示幅が 2 になる
     → 枠線やカーソル位置の計算がずれることがある
     → 選択肢に長い日本語を使う場合は要確認 ★

④ 【文字コード】
     Console.OutputEncoding = Encoding.UTF8;
     → [アプリケーションのUnicode化](MS_ApplicationUnicodeMigration) 参照

⑤ 【Windows Terminal 以外】
     古い conhost では ANSI エスケープが効かない場合がある

サンプル

https://github.com/OpenTouryoProject/OpenTouryo/blob/develop/root/programs/CS/Samples/CLI_sample/Simple_CLI/Simple_CLI/Program.cs

参考

補足(現在の選択肢): Sharprompt は
日本の開発者(しばやん氏)が作った OSSで、
軽量で C# らしい API が特徴である。
同種のライブラリと比較しておく。

ライブラリ 特徴
Sharprompt 対話プロンプトに特化。軽量。API が素直 ★
Spectre.Console 対話+描画(表・ツリー・進捗・色)+引数解析。多機能
Terminal.Gui 本格的な TUI(ウィンドウ、メニュー、フォーム)
ConsoleAppFramework 対話ではなくコマンド定義(メソッド=コマンド)
【使い分け】
   ・プロンプトだけ欲しい            → Sharprompt
   ・表や進捗も綺麗に出したい        → Spectre.Console ★
   ・全画面の TUI アプリを作る       → Terminal.Gui
// Spectre.Console の同等機能(参考)
var name = AnsiConsole.Ask<string>("名前:");
var kind = AnsiConsole.Prompt(
    new SelectionPrompt<string>().Title("種類").AddChoices("Web", "Console"));
AnsiConsole.Write(new Table().AddColumn("項目").AddColumn("値"));

どちらも現役であり、
Sharprompt の方が依存が小さく、学習コストが低い
表示にこだわる必要がなければ Sharprompt で十分である。

Microsoft Learn


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

⚠️ **GitHub.com Fallback** ⚠️