翼度科技»论坛 编程开发 .net 查看内容

Spectre.Console-实现自己的CLI

6

主题

6

帖子

18

积分

新手上路

Rank: 1

积分
18
引言

最近发现自己喜欢用的 Todo 软件总是差点意思,毕竟每个人的习惯和工作流不太一样,我就想着自己写一个小的Todo 项目,核心的功能是自动记录 Todo 执行过程中消耗的时间(尤其面向程序员),按照自己的想法实现一套 GTD 工作流。
不想写 Winform ,WPF 也写腻了,就想着学学 MAUI、Avalonia、Uno Platform 、blazor 之类的。由于前端技术选型纠结,迟迟动不了手,想想还是暂时先不弄了。但为了测试,没有个界面总是不太行,先搞一个 CLI 吧。
更新:由于想让程序持续执行,所以后面还是替换了 CLI 。
Spectre. Console

Spectre.Console(spectreconsole.net) 是一个美化 Console 输出的类库,通过它可以实现丰富多样的 Console 输出。核心的特性有这些:

  • 格式化输出文本(支持斜体等)
  • 支持对文字着色
  • 渲染复杂的组件(表格、结构树、ASCII 图片)
  • 显示进度条与状态
  • 强类型输入验证
  • 对 exception 输出着色
除此以外,它还提供了一个 Spectre.Console.Cli 类库,可以帮助我们实现类似 dotnet 、git 之类的 CLI(Command Line Interface)。
基本用法

这里使用官方的示例:
  1. var app = new CommandApp<FileSizeCommand>();
  2. return app.Run(args);
  3. internal sealed class FileSizeCommand : Command<FileSizeCommand.Settings>
  4. {
  5.     public sealed class Settings : CommandSettings
  6.     {
  7.         [Description("Path to search. Defaults to current directory.")]
  8.         [CommandArgument(0, "[searchPath]")]
  9.         public string? SearchPath { get; init; }
  10.         [CommandOption("-p|--pattern")]
  11.         public string? SearchPattern { get; init; }
  12.         [CommandOption("--hidden")]
  13.         [DefaultValue(true)]
  14.         public bool IncludeHidden { get; init; }
  15.     }
  16.     public override int Execute([NotNull] CommandContext context, [NotNull] Settings settings)
  17.     {
  18.         var searchOptions = new EnumerationOptions
  19.         {
  20.             AttributesToSkip = settings.IncludeHidden
  21.                 ? FileAttributes.Hidden | FileAttributes.System
  22.                 : FileAttributes.System
  23.         };
  24.         var searchPattern = settings.SearchPattern ?? "*.*";
  25.         var searchPath = settings.SearchPath ?? Directory.GetCurrentDirectory();
  26.         var files = new DirectoryInfo(searchPath)
  27.             .GetFiles(searchPattern, searchOptions);
  28.         var totalFileSize = files
  29.             .Sum(fileInfo => fileInfo.Length);
  30.         AnsiConsole.MarkupLine($"Total file size for [green]{searchPattern}[/] files in [green]{searchPath}[/]: [blue]{totalFileSize:N0}[/] bytes");
  31.         return 0;
  32.     }
  33. }
复制代码
结构非常简单,标有 [CommandOption("xxx")] 会自动将参数归类,通过下列命令进行调用。
  1. app.exe
  2. app.exe c:\windows
  3. app.exe c:\windows --pattern *.dll
  4. app.exe c:\windows --hidden --pattern *.dll
复制代码
多命令

上面这个示例只支持一个默认的命令,但是一般的 CLI 都有很多支持的命令,需要调整一下实现:
  1. var app = new CommandApp();
  2. app.Configure(config =>
  3. {
  4.     config.AddCommand<AddCommand>("add");
  5.     config.AddCommand<CommitCommand>("commit");
  6.     config.AddCommand<RebaseCommand>("rebase");
  7. });
复制代码
层级命令

更复杂一点的,比如 dotnet add package 和 dotnet add reference 这种,add 后面还有 package 这个子命令,上面的方法还得继续拓展,首先定义 add 基类和 package 与 reference 继承类。
  1. public class AddSettings : CommandSettings
  2. {
  3.     [CommandArgument(0, "[PROJECT]")]
  4.     public string Project { get; set; }
  5. }
  6. public class AddPackageSettings : AddSettings
  7. {
  8.     [CommandArgument(0, "<PACKAGE_NAME>")]
  9.     public string PackageName { get; set; }
  10.     [CommandOption("-v|--version <VERSION>")]
  11.     public string Version { get; set; }
  12. }
  13. public class AddReferenceSettings : AddSettings
  14. {
  15.     [CommandArgument(0, "<PROJECT_REFERENCE>")]
  16.     public string ProjectReference { get; set; }
  17. }
复制代码
然后对不同的命令,指定不同处理函数。
  1. public class AddPackageCommand : Command<AddPackageSettings>
  2. {
  3.     public override int Execute(CommandContext context, AddPackageSettings settings)
  4.     {
  5.         // Omitted
  6.         return 0;
  7.     }
  8. }
  9. public class AddReferenceCommand : Command<AddReferenceSettings>
  10. {
  11.     public override int Execute(CommandContext context, AddReferenceSettings settings)
  12.     {
  13.         // Omitted
  14.         return 0;
  15.     }
  16. }
复制代码
最后使用 AddBranch 进行组合:
  1. using Spectre.Console.Cli;
  2. namespace MyApp
  3. {
  4.     public static class Program
  5.     {
  6.         public static int Main(string[] args)
  7.         {
  8.             var app = new CommandApp();
  9.             app.Configure(config =>
  10.             {
  11.                 config.AddBranch<AddSettings>("add", add =>
  12.                 {
  13.                     add.AddCommand<AddPackageCommand>("package");
  14.                     add.AddCommand<AddReferenceCommand>("reference");
  15.                 });
  16.             });
  17.             return app.Run(args);
  18.         }
  19.     }
  20. }
复制代码
参考


来源:https://www.cnblogs.com/podolski/archive/2023/05/31/17445033.html
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

举报 回复 使用道具