好饭顿坏饭 发表于 2023-5-31 09:50:47

Spectre.Console-实现自己的CLI

引言

最近发现自己喜欢用的 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)。
基本用法

这里使用官方的示例:
var app = new CommandApp<FileSizeCommand>();
return app.Run(args);

internal sealed class FileSizeCommand : Command<FileSizeCommand.Settings>
{
    public sealed class Settings : CommandSettings
    {
      
      ")]
      public string? SearchPath { get; init; }

      
      public string? SearchPattern { get; init; }

      
      
      public bool IncludeHidden { get; init; }
    }

    public override int Execute( CommandContext context, Settings settings)
    {
      var searchOptions = new EnumerationOptions
      {
            AttributesToSkip = settings.IncludeHidden
                ? FileAttributes.Hidden | FileAttributes.System
                : FileAttributes.System
      };

      var searchPattern = settings.SearchPattern ?? "*.*";
      var searchPath = settings.SearchPath ?? Directory.GetCurrentDirectory();
      var files = new DirectoryInfo(searchPath)
            .GetFiles(searchPattern, searchOptions);

      var totalFileSize = files
            .Sum(fileInfo => fileInfo.Length);

      AnsiConsole.MarkupLine($"Total file size for {searchPattern}[/] files in {searchPath}[/]: {totalFileSize:N0}[/] bytes");

      return 0;
    }
}结构非常简单,标有 会自动将参数归类,通过下列命令进行调用。
app.exe
app.exe c:\windows
app.exe c:\windows --pattern *.dll
app.exe c:\windows --hidden --pattern *.dll多命令

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

更复杂一点的,比如 dotnet add package 和 dotnet add reference 这种,add 后面还有 package 这个子命令,上面的方法还得继续拓展,首先定义 add 基类和 package 与 reference 继承类。
public class AddSettings : CommandSettings
{
    ")]
    public string Project { get; set; }
}

public class AddPackageSettings : AddSettings
{
   
    public string PackageName { get; set; }

   
    public string Version { get; set; }
}

public class AddReferenceSettings : AddSettings
{
   
    public string ProjectReference { get; set; }
}然后对不同的命令,指定不同处理函数。
public class AddPackageCommand : Command<AddPackageSettings>
{
    public override int Execute(CommandContext context, AddPackageSettings settings)
    {
      // Omitted
      return 0;
    }
}

public class AddReferenceCommand : Command<AddReferenceSettings>
{
    public override int Execute(CommandContext context, AddReferenceSettings settings)
    {
      // Omitted
      return 0;
    }
}最后使用 AddBranch 进行组合:
using Spectre.Console.Cli;

namespace MyApp
{
    public static class Program
    {
      public static int Main(string[] args)
      {
            var app = new CommandApp();

            app.Configure(config =>
            {
                config.AddBranch<AddSettings>("add", add =>
                {
                  add.AddCommand<AddPackageCommand>("package");
                  add.AddCommand<AddReferenceCommand>("reference");
                });
            });

            return app.Run(args);
      }
    }
}参考


[*]Spectre.Console - Introduction (spectreconsole.net)

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