引言

最近发现自己喜欢用的 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);
}
}
}

参考

Spectre.Console-实现自己的CLI的更多相关文章

  1. dotnet core cli 命令

    1 dotnet new 2 创建code 程序 dotnet new console using System; namespace cli { class Program { static voi ...

  2. spark cli

    Spark SQL CLI Spark1.1增加了Spark SQL CLI和ThriftServer SparkSQL CLI配置 1.创建并配置hive-site.xml 在运行Spark SQL ...

  3. 事件冒泡和事件捕获以及解释target和currenttarget的区别

    冒泡和捕获的区别是冒泡事件是先触发子元素事件,再触发父元素事件,这个是冒泡.捕获是先触发父元素事件,再触发子元素事件.简单的来说,冒泡的顺序是由内到外,捕获的顺序是由外到内 举例:<!DOCTY ...

  4. 170多个Ionic Framework学习资源(转载)

    在Ionic官网找到的学习资源:http://blog.ionic.io/learning-ionic-in-your-living-room/ 网上的文章比较多,但是很多时候我们很难找到自己需要的. ...

  5. Yii2 捕获错误日志

    在技术开发中,捕获程序框架错误,是非常必要的一件事情,我们公司使用Yii2框架,简单说下Yii2的错误捕获处理 Yii2 web应用 1 配置如下 其中errorHandler就是错误处理配置,执行E ...

  6. Working with Data » Getting started with ASP.NET Core and Entity Framework Core using Visual Studio »迁移

    Migrations¶ 4 of 4 people found this helpful The Contoso University sample web application demonstra ...

  7. ionic项目相关的操作命令

     更新npmD:\Program Files\npm-3.9.0\npmnode cli.js install npm -gf vs安装 更新node.js  windows版直接从官网下载安装包 n ...

  8. 方法:怎么用ionic命令行调试你的ionic app

    官网上有很详细的解说  http://blog.ionic.io/live-reload-all-things-ionic-cli/ 下面说说我自己的调试过程(android版): 首先用命令行进入你 ...

  9. sparkSQL1.1入门

    http://blog.csdn.net/book_mmicky/article/details/39288715 2014年9月11日,Spark1.1.0忽然之间发布.笔者立即下载.编译.部署了S ...

  10. 基于Casperjs的网页抓取技术【抓取豆瓣信息网络爬虫实战示例】

    CasperJS is a navigation scripting & testing utility for the PhantomJS (WebKit) and SlimerJS (Ge ...

随机推荐

  1. SpringBoot---起步依赖starter

    1.简化spring应用的初始搭建和开发过程. springboot程序优点:自动配置.起步依赖(简化依赖配置).辅助功能(内置服务器...) <?xml version="1.0&q ...

  2. CSS3新特性值逻辑选择器

    1. :is 解释::is() CSS伪类函数将选择器列表作为参数,并选择该列表中任意一个选择器可以选择的元素. 例如 对于多个不同父容器的同个子元素的一些共性样式设置,传统写法如下 header p ...

  3. Unity3D中的Attribute详解(二)

    上一篇文章我们初步了解了一下Attributes的含义,并且使用系统自带的Attributes写了点代码.在进一步解剖我们的代码之前,我觉得有个概念可能需要巩固一下:什么是元数据? 我们知道C#代码会 ...

  4. MySQL--索引的数据结构

    1.为什么使用索引 索引是存储引擎用于快速找到数据记录的一种数据结构,就好比一本教科书的目录部分,通过目录中找到对应文章的页面,便可以快速定位到需要的文章,mysql中也是一样的道理,进行数据查找时, ...

  5. 实现自定义注解,实现ioc与aop

    实现自定义注解主要分三个步骤: 1.定义自己的注解类. 注解类默认继承Annotation接口. 且注解内的属性默认public(要给别人用的) 属性可以定义默认值也就是不给你的属性传值也会拥有默认. ...

  6. python注册热键方式

    #!/usr/bin/env python3   import win32con import ctypes import ctypes.wintypes from threading import  ...

  7. java调用https接口导入证书认证

    1.获取证书 浏览器访问需要调用的接口路径 如图导出证书. 2.进入java目录 jre/lib/security 导入证书 keytool -import -alias name -keystore ...

  8. Python 函数传递任意数量的实参

    函数传递任意数量的实参 *形参名,形参名中的星号让python创建了一个空元组,并将收到的所有值都封装到这个元组中 # 案例 *toppings 形参名中的星号让python创建了一个空元组,并将收到 ...

  9. MySQL概述与安装

    MySQL数据库 概要: 一.MySQL数据库的概述 二.MySQL数据库的搭建 三.MySQL数据库软件的使用 四.MySQL数据类型 五.MySQL数据库数据的操作 一.初始MySQL数据库 1. ...

  10. flink之Sink to MySQL和Redis

    前言 下面这篇文章是使用Flink的Sink 写出数据到Redis和MySQL Flink之Sink写入Redis和MySQL Flink需要添加Sink的时候,需要自己去添加写Sink,我们可以实现 ...