首页 > 编程语言 >文盘Rust——起手式,CLI程序 | 京东云技术团队

文盘Rust——起手式,CLI程序 | 京东云技术团队

时间:2023-09-07 11:33:19浏览次数:47  
标签:Command CLI 起手式 rs matches cmd 文盘 requestsample new

技术的学习从不会到会的过程是最有意思的,也是体会最多的。一旦熟练了,知识变成了常识,可能就失去了记录学习过程的最佳时机。

在我看来学习一门计算机语言和学习人类语言有很多共通之处。我们学习人类语言是从单个的词开始,然后是简单句子,通过不断的与他人交互练习掌握语法和语言习惯。当熟练到一定程度就可以表达思想。计算的语言也差不多,熟悉关键词,基本逻辑,标准库,写应用。只是沟通的对象是机器而已。

既然是学就不能在开始搞的太难。学习本来就是个艰苦的差事。上来就干特别复杂的事情往往会坚持不下去。天下难事必做于易,从简入繁,从易到难,方为正道。

先聊聊最简单的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各种功能是如何实现的。

作者:京东科技 贾世闻

来源:京东云开发者社区 转载请注明来源

标签:Command,CLI,起手式,rs,matches,cmd,文盘,requestsample,new
From: https://blog.51cto.com/u_15714439/7395511

相关文章

  • Eclipse开发经典教程:常用快捷键
    window——preferences...——(General——keys)或者直接输入key(即可看到keys)编辑相关快捷键  Eclipse的编辑功能非常强大,掌握了Eclipse快捷键功能,能够大大提高开发效率。Eclipse中有如下一些和编辑相关的快捷键。  1.【ALT+/】  此快捷键为用户编辑的好帮手,能为用户......
  • 文盘Rust——起手式,CLI程序
    技术的学习从不会到会的过程是最有意思的,也是体会最多的。一旦熟练了,知识变成了常识,可能就失去了记录学习过程的最佳时机。在我看来学习一门计算机语言和学习人类语言有很多共通之处。我们学习人类语言是从单个的词开始,然后是简单句子,通过不断的与他人交互练习掌握语法和语言习惯......
  • clickhouse的简单介绍及使用
    转:https://blog.csdn.net/qq_44275894/article/details/123973699一、介绍cliskhouse官方地址ClickHouse是一个真正的面向列的数据库管理系统(DBMS),用于查询的在线分析处理(OLAP)。数据按列存储,并且在执行数组(向量或列块)期间存储。只要有可能,操作就会被发送到数组上,而不是单......
  • Clion开发C程序多项目配置
    Clion是写C语言神器,吧啦吧啦......对于初学者来讲,一个项目,包含多个模块是多么美好的事情,于是就有了这篇博客!Clion是Cmake项目,因此只需要稍微配置一下CmakeLists.txt就可以实现如下效果 具体配置如下:根CmakeLists.txt配置cmake_minimum_required(VERSION3.25)project(dem......
  • 用pm2管理php cli
    新建mq.json文件:{"apps":{"name":"consumerMQ",//应用名称"script":"phpthinkrecharge",//命令名称"error_file":"./log/err.log",//错误日志"out_file":"./lo......
  • Go HTTP Client 持久连接失效
    调用Go的 HTTPClient 的 Get\Post 之类的方法时,默认是开启 HTTPkeepalive 的,不过直接使用还是会遇到一些情况导致持久连接失效。首先,Client构造好HTTP请求后,利用Transport来发送请求并等待结果,默认使用 DefaultTransport 来实现,大多数情况下,自定义Client时,配置......
  • 文盘Rust -- 生命周期问题引发的 static hashmap 锁
    2021年上半年,撸了个rustcli开发的框架,基本上把交互模式,子命令提示这些cli该有的常用功能做进去了。项目地址:https://github.com/jiashiwen/interactcli-rs。春节以前看到axum已经0.4.x了,于是想看看能不能用rust做个服务端的框架。春节后开始动手,在做的过程中会碰到各种有趣的问......
  • 【ToolChains】CLion(VS2019) + CMake + Vcpkg 的使用
    参考博客:https://blog.51cto.com/u_15075510/4201238http://t.csdn.cn/pADDUhttps://zhuanlan.zhihu.com/p/454233496https://blog.csdn.net/weixin_43803955/article/details/123544106Vcpkg概述Vcpkg是微软社区开发的一个跨平台的C++包管理工具。它旨在解决C++......
  • HBASE shell操作CLI
    server查看hbase(main)>statushbase(main)>version创建命名空间:namespace指的是一个表的逻辑分组,同一组中的表有类似的用途,相当于关系型数据库中的database创建该命名空间的表:hbase(main):060:0>create_namespace'test1'hbase(main):061:0>create'test1:test','f1',�......
  • 文盘Rust -- 生命周期问题引发的 static hashmap 锁 | 京东云技术团队
    2021年上半年,撸了个rustcli开发的框架,基本上把交互模式,子命令提示这些cli该有的常用功能做进去了。项目地址:https://github.com/jiashiwen/interactcli-rs。春节以前看到axum已经0.4.x了,于是想看看能不能用rust做个服务端的框架。春节后开始动手,在做的过程中会碰到各种有趣的问题......