MS_CLISharprompt - NetDevInfraWGinOSSConsortium/NetDevInfraWiki GitHub Wiki
- 戻る(自作CUI(CLI)の話)
- CLI開発(Sharprompt)
- CLI開発(System.CommandLine)
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) の 「対話を必須にしない」という設計指針そのもの
以下のような機能がある模様。
- 文字列入力
- 数値型などへのパース
YES/NO の確認
パスワード入力
- 単純な Select
- 列挙型へのパース
ページングできる Select
表示のカスタマイズ
補足(各機能の実際の書き方): 一覧だけでは掴みにくいので、
コードで示す。型パラメータで戻り値の型が決まるのが特徴である。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 エスケープが効かない場合がある
- shibayan/Sharprompt: Interactive command line interface toolkit for C#
https://github.com/shibayan/Sharprompt - C# で Interactive な Prompt を構築するライブラリを作った - しばやん雑記
https://blog.shibayan.jp/entry/20190811/1565520395
補足(現在の選択肢): 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 で十分である。
- .NET でのコンソール アプリの作成
https://learn.microsoft.com/ja-jp/dotnet/core/tutorials/with-visual-studio-code - System.Console クラス
https://learn.microsoft.com/ja-jp/dotnet/api/system.console
Tags: 移行, シェル, インフラストラクチャ, .NET開発