首页 > 其他分享 >Spectre.Console-实现自己的CLI

Spectre.Console-实现自己的CLI

时间:2023-05-31 09:03:17浏览次数:48  
标签:Console CLI app Spectre class add var public

引言

最近发现自己喜欢用的 Todo 软件总是差点意思,毕竟每个人的习惯和工作流不太一样,我就想着自己写一个小的Todo 项目,核心的功能是自动记录 Todo 执行过程中消耗的时间(尤其面向程序员),按照自己的想法实现一套 GTD 工作流。

不想写 WinformWPF 也写腻了,就想着学学 MAUIAvaloniaUno Platformblazor 之类的。由于前端技术选型纠结,迟迟动不了手,想想还是暂时先不弄了。但为了测试,没有个界面总是不太行,先搞一个 CLI 吧。

更新:由于想让程序持续执行,所以后面还是替换了 CLI 。

Spectre. Console

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

  • 格式化输出文本(支持斜体等)
  • 支持对文字着色
  • 渲染复杂的组件(表格、结构树、ASCII 图片)
  • 显示进度条与状态
  • 强类型输入验证
  • 对 exception 输出着色

除此以外,它还提供了一个 Spectre.Console.Cli 类库,可以帮助我们实现类似 dotnetgit 之类的 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
    {
        [Description("Path to search. Defaults to current directory.")]
        [CommandArgument(0, "[searchPath]")]
        public string? SearchPath { get; init; }

        [CommandOption("-p|--pattern")]
        public string? SearchPattern { get; init; }

        [CommandOption("--hidden")]
        [DefaultValue(true)]
        public bool IncludeHidden { get; init; }
    }

    public override int Execute([NotNull] CommandContext context, [NotNull] 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 [green]{searchPattern}[/] files in [green]{searchPath}[/]: [blue]{totalFileSize:N0}[/] bytes");

        return 0;
    }
}

结构非常简单,标有 [CommandOption("xxx")] 会自动将参数归类,通过下列命令进行调用。

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 packagedotnet add reference 这种,add 后面还有 package 这个子命令,上面的方法还得继续拓展,首先定义 add 基类和 package 与 reference 继承类。

public class AddSettings : CommandSettings
{
    [CommandArgument(0, "[PROJECT]")]
    public string Project { get; set; }
}

public class AddPackageSettings : AddSettings
{
    [CommandArgument(0, "<PACKAGE_NAME>")]
    public string PackageName { get; set; }

    [CommandOption("-v|--version <VERSION>")]
    public string Version { get; set; }
}

public class AddReferenceSettings : AddSettings
{
    [CommandArgument(0, "<PROJECT_REFERENCE>")]
    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);
        }
    }
}

参考

标签:Console,CLI,app,Spectre,class,add,var,public
From: https://www.cnblogs.com/podolski/p/17445033.html

相关文章

  • [转]Clion+mingw环境下Assimp编译
    1、Clion+mingw环境下Assimp编译2、MinGW-w64下载......
  • Docker CLI docker container cp常用命令
    Docker是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的镜像中,然后发布到任何流行的Linux或Windows操作系统的机器上,也可以实现虚拟化。Docker是内核虚拟化,不使用Hypervisor是不完全虚拟化,依赖内核的特性实现资源隔离。本文主要介绍DockerCLI中d......
  • ROS2-Beginner:CLI tools-1、环境配置
    1、环境配置目标:本教程告诉读者怎样准备ROS2环境背景:ROS2依赖于使用shell环境组合工作空间的概念,“工作区”是一个ROS术语,表示您使用ROS2进行开发的系统上的位置。ROS2的核心工作空间称为底层(underlay)。后续的局部工作空间称为覆盖(overlays)。当使用ROS2进行开发时,通常会同......
  • WebClient发送get、post请求(form、json)(功能封装)
    1.情景展示Spring3.0引入了RestTemplate,但是在后来的官方源码中介绍,RestTemplate有可能在未来的版本中被弃用,所谓替代RestTemplate,在Spring5中引入了WebClient作为非阻塞式ReactiveHttp客户端。WebClient处理单个HTTP请求的响应时长并不比RestTemplate更快,但是它处理并发的能......
  • nmcli --- Linux下通过命令行管理WiFi连接
    1、建立和删除一个wifi连接创建wifi连接(SSID:hello,密码:12345678)的示例:$nmclidevicewificonnecthellopassword12345678每次命令执行后,会在/etc/NetworkManager/system-connections/目录下创建一个新文件hello来保存配置,重复执行则创建多个这样的文件。删除wifi连接的示例......
  • clickhouse学习资源
    ClickHouse是一个开源的列式数据库管理系统,最初由俄罗斯搜索引擎Yandex开发。它专为OLAP(联机分析处理)场景设计,可以快速处理大量数据。以下是一些ClickHouse学习资源:ClickHouse官方文档:https://clickhouse.tech/docs/zh/ClickHouse中文文档:https://clickhouse-docs-cn.......
  • leetcode 746. Min Cost Climbing Stairs
    Onastaircase,thei-thstephassomenon-negativecostcost[i]assigned(0indexed).Onceyoupaythecost,youcaneitherclimboneortwosteps.Youneedtofindminimumcosttoreachthetopofthefloor,andyoucaneitherstartfromthestepwithin......
  • android开发java.lang.NoClassDefFoundError: org/jetbrains/kotlin/cli/common/Prope
    问题:编译Android项目出现java.lang.NoClassDefFoundError:org/jetbrains/kotlin/cli/common/PropertiesKt原因:项目使用发JDK版本和Kotlin版本不一致或者说不对应导致gradle找不到对应的类解决方法:我的解决方法是降低JDK的版本到1.8,具体操作是OpenModulesSettings->SDKLoc......
  • 使用powercli 批量多线程 克隆vsphere虚拟机
    $VMS=import-csv-Path'vm001.csv'$Job=$VMS|ForEach-Object-Parallel{#忽略位$Skip=$($_.skip)if($Skip-eq"yes"){continue}#虚拟机名字$VMname=$($_.name)#资源池名字$Resource_Pool=$($_.res_po......
  • store文件夹 vue_vue-cli2使用store存储全局变量
    1.引入store安装引入vuex,在main.js里面:importstorefrom'./store'//store引入newVue({el:'#app',router,store,//store引入components:{App},template:''})在store文件夹下创建index.js入口文件,添加下面内容:importVuefrom'vue';im......