文盘Rust——起手式,CLI程序
技术的学习从不会到会的过程是最有意思的,也是体会最多的。一旦熟练了,知识变成了常识,可能就失去了记录学习过程的最佳时机。
在我看来学习一门计算机语言和学习人类语言有很多共通之处。我们学习人类语言是从单个的词开始,然后是简单句子,通过不断的与他人交互练习掌握语法和语言习惯。当熟练到一定程度就可以表达思想。计算的语言也差不多,熟悉关键词,基本逻辑,标准库,写应用。只是沟通的对象是机器而已。
既然是学就不能在开始搞的太难。学习本来就是个艰苦的差事。上来就干特别复杂的事情往往会坚持不下去。天下难事必做于易,从简入繁,从易到难,方为正道。
先聊聊最简单的CLI(Command Line Interface)程序。其实我们每学习一门语言的 hello world 程序就是CLI,只是没那么多交互而已。
做命令行程序最繁琐的事情是处理交互。交互大体分两种。一种是我们最熟悉shell下的交互模式,每次一个命令,配合参数实现一次处理返回一组结果。这种模式处理起来比较容易Rust也有相当优秀的第三方lib (clap)。第二种是领域交互,就像我是使用MySql或者redis的客户端程序。这种程序可以玩儿的东西就比较多了像如何实现交互,如何来做子命令的提示。这些东西 clap 并没有提供,需要我们自己来实现。
interactcli-rs是我在工作过程中做的一个交互模式命令行脚手架。实现了一些常用功能。
下面我们来看看如何通过几个步骤快速的实现一个功能相对齐全的CLI程序。和做饭一样,能够快速获得成就感的方式是找半成品直接下锅炒一盘:)。
下面我们具体看看,如何通过interactcli-rs实现一个功能齐全的命令行程序
来点感性认识
先把项目clone下来运行个例子
clone 项目
git clone https://github.com/jiashiwen/interactcli-rs.git
cd interactcli-rs命令行模式
cargo run requestsample baidu交互模式
cargo run -- -i
interact-rs> requestsample baidu
运行上面的命令是通过http来请求百度
四步做个CLI
首先我们先来看看框架的目录结构
.
├── examples
├── log
├── logs
└── src
├── cmd
├── commons
├── configure
├── interact
├── logger
└── request
cmd目录是我们做自己功能时要动的主要目录,下面我们一步一步的实现requestsample命令。
定义命令
cmd 模块用于定义命令以及相关子命令,requestsample.rs 中定义了访问百度的命令use clap::Command; pub fn new_requestsample_cmd() -> Command<'static> {
clap::Command::new("requestsample")
.about("requestsample")
.subcommand(get_baidu_cmd())
} pub fn get_baidu_cmd() -> Command<'static> {
clap::Command::new("baidu").about("request www.baidu.com")
}new_requestsample_cmd 函数定义了命令 "requestsample",get_baidu_cmd 函数定义了 requestsample 的子命令 baidu
注册命令
src/cmd/rootcmd.rs 文件中定义了命令树,可以在此注册定义好的子命令lazy_static! {
static ref CLIAPP: clap::Command<'static> = clap::Command::new("interact-rs")
.version("1.0")
.author("Your Name. ")
.about("command line sample")
.arg_required_else_help(true)
.arg(
Arg::new("config")
.short('c')
.long("config")
.value_name("FILE")
.help("Sets a custom config file")
.takes_value(true)
)
.arg(
Arg::new("daemon")
.short('d')
.long("daemon")
.help("run as daemon")
)
.arg(
Arg::new("interact")
.short('i')
.long("interact")
.conflicts_with("daemon")
.help("run as interact mod")
)
.arg(
Arg::new("v")
.short('v')
.multiple_occurrences(true)
.takes_value(true)
.help("Sets the level of verbosity")
)
.subcommand(new_requestsample_cmd())
.subcommand(new_config_cmd())
.subcommand(new_multi_cmd())
.subcommand(new_task_cmd())
.subcommand(new_loop_cmd())
.subcommand(
clap::Command::new("test")
.about("controls testing features")
.version("1.3")
.author("Someone E. ")
.arg(
Arg::new("debug")
.short('d')
.help("print debug information verbosely")
)
);
static ref SUBCMDS: Vec = subcommands();
} pub fn run_app() {
let matches = CLIAPP.clone().get_matches();
if let Some(c) = matches.value_of("config") {
println!("config path is:{}", c);
set_config_file_path(c.to_string());
}
set_config(&get_config_file_path());
cmd_match(&matches);
} pub fn run_from(args: Vec) {
match clap_Command::try_get_matches_from(CLIAPP.to_owned(), args.clone()) {
Ok(matches) => {
cmd_match(&matches);
}
Err(err) => {
err.print().expect("Error writing Error");
}
};
}定义好的命令不需其他处理,框架会在系统运行时生成子命令树,用于在领域交互模式下命令提示的支持
命令解析
src/cmd/rootcmd.rs 中的 cmd_match 负责解析命令,可以把解析逻辑写在该函数中fn cmd_match(matches: &ArgMatches) {
if let Some(ref matches) = matches.subcommand_matches("requestsample") {
if let Some(_) = matches.subcommand_matches("baidu") {
let rt = tokio::runtime::Runtime::new().unwrap();
let async_req = async {
let result = req::get_baidu().await;
println!("{:?}", result);
};
rt.block_on(async_req);
};
}
}修改交互模式的命令提示
提示符可以在src/interact/cli.rs 中定义pub fn run() { ... loop {
let p = format!("{}> ", "interact-rs");
rl.helper_mut().expect("No helper").colored_prompt = format!("\x1b[1;32m{}\x1b[0m", p); ...
} ...
}
先写到这里,下次为大家介绍一下interactcli-rs各种功能是如何实现的。
作者:京东科技 贾世闻
来源:京东云开发者社区 转载请注明来源
文盘Rust——起手式,CLI程序的更多相关文章
- 文盘Rust -- 把程序作为守护进程启动
当我们写完一个服务端程序,需要上线部署的时候,或多或少都会和操作系统的守护进程打交道,毕竟谁也不希望shell关闭既停服.今天我们就来聊聊这个事儿. 最早大家部署应用的通常操作是 "nohu ...
- 文盘Rust -- 给程序加个日志
作者:贾世闻 日志是应用程序的重要组成部分.无论是服务端程序还是客户端程序都需要日志做为错误输出或者业务记录.在这篇文章中,我们结合[log4rs](https://github.com/estk/l ...
- 文盘Rust -- struct 中的生命周期
最近在用rust 写一个redis的数据校验工具.redis-rs中具备 redis::ConnectionLike trait,借助它可以较好的来抽象校验过程.在开发中,不免要定义struct 中的 ...
- 文盘Rust -- rust 连接云上数仓 starwift
作者:京东云 贾世闻 最近想看看 rust 如何集成 clickhouse,又犯了好吃懒做的心理(不想自己建环境),刚好京东云发布了兼容ck 的云原生数仓 Starwfit,于是搞了个实例折腾一番. ...
- 文盘Rust -- 本地库引发的依赖冲突
作者:京东科技 贾世闻 问题描述 clickhouse 的原生 rust 客户端目前比较好的有两个clickhouse-rs 和 clickhouse.rs .clickhouse-rs 是 tcp ...
- 文盘Rust -- 用Tokio实现简易任务池
作者:京东科技 贾世闻 Tokio 无疑是 Rust 世界中最优秀的异步Runtime实现.非阻塞的特性带来了优异的性能,但是在实际的开发中我们往往需要在某些情况下阻塞任务来实现某些功能. 我们看看下 ...
- 【译】写个好的 CLI 程序
写个好的 CLI 程序 Write a Good CLI Program 译文 原文链接:https://qiita.com/tigercosmos/items/678f39b1209e60843cc ...
- 快速构建CLI程序并发布到PyPi
构造一个简单的CLI程序 typer 这个从去年就被各种营销号吹成Web框架的 第三方库, 与 FastAPI 同出一人之手,它不是Web框架,它是一个用来构建CLI程序的库,我们就简单搞个例子 # ...
- go如何编写命令行(cli)程序
创建一个命令行程序 问题 如何使用golang创建可以在命令行当中传递参数的程序?go如何带参数执行程序? 比如我们期望使用hello -version来查看hello程序的版本号码.或者输入hell ...
- 回文链表 牛客网 程序员面试金典 C++ Python
回文链表 牛客网 程序员面试金典 C++ Python 题目描述 请编写一个函数,检查链表是否为回文. 给定一个链表ListNode* pHead,请返回一个bool,代表链表是否为回文. 测试样例 ...
随机推荐
- Vue——前端发展史、Vue介绍和使用、插值语法、文本指令、事件指令
前端的发展史 # 1 HTML(5).CSS(3).JavaScript(ES5.ES6):编写一个个的页面 -> 给后端(PHP.Python.Go.Java) -> 后端嵌入模板语法 ...
- tryhackem_wonderland
涉及,解密,扫描,横向移动,纵向移动 仙境 掉进兔子洞,进入仙境. 获得shell 解法一: 目录扫描 ffuf -u http://10.10.134.189/FUZZ -w /usr/share/ ...
- .netcore中的虚拟文件EmbeddedFile
以前一直比较好奇像swagger,cap,skywalking等组件是如何实现引用一个dll即可在网页上展示界面的,难道这么多html,js,css等都是硬编码写死在代码文件中的?后面接触apb里面也 ...
- 深入探究for...range语句
1. 引言 在Go语言中,我们经常需要对数据集合进行遍历操作.对于数组来说,使用for语句可以很方便地完成遍历.然而,当我们面对其他数据类型,如map.string 和 channel 时,使用普通的 ...
- NVIDIA Maxine Video Effects SDK 編程指南 - 实践小记
NVIDIA Maxine Video Effects SDK 編程指南 - 实践小记 本篇博客重点只说Video Effect的部分,此外还有Audio Effect的部分.还有AR部分,不在本篇范 ...
- 分享6个SQL小技巧
原创:扣钉日记(微信公众号ID:codelogs),欢迎分享,非公众号转载保留此声明. 简介 经常有小哥发出疑问,SQL还能这么写?我经常笑着回应,SQL确实可以这么写.其实SQL学起来简单,用起来也 ...
- maven报错:不再支持源选项 5。请使用 6 或更高版本
问题描述 在执行命令 mvn compile 发生错误 D:\Github_NOTES\JavaWeb_Learning\02Java\JavaWeb\Code\Maven1>mvn clean ...
- Microsoft edge锁定在任务栏上,被修改主页360的解决方法
今天从桌面下边的任务栏打开Microsoft edge浏览器,突然发现主页被篡改为360导航了(生气!恶龙咆哮ooo 在桌面上是Microsoft edge,固定到任务栏就成为Microsoft ed ...
- Java扩展Nginx之六:两大filter
欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos 本篇概览 本文是<Java扩展Nginx> ...
- .net 6 winform启动器:调用CMD命令行执行dotnet命令启动.net core程序并将控制台输出日志输出到winform textbox实现实时日志显示
背景 历史遗留问题,生产车间运行的一个.net core signalr程序使用命令行程序启动,经常由于生产人员误操作将光标停留在控制台上导致程序假死,丢失部分测试数据,车间随便找了一台win10系统 ...