Skip to content

Latest commit

 

History

History
177 lines (142 loc) · 4.65 KB

README_cn.md

File metadata and controls

177 lines (142 loc) · 4.65 KB

interactcli-rs

English

interactcli-rs 是一个命令行程序框架,用于解决命令行与交互模式一体化问题,包括命令行交互模式统一、子命令提示等功能。该框架集成了clap和shellwords。

快速指南

框架中包含了访问www.baidu.com的例子

快速上手过程如下:

  • clone 项目

    git clone https://github.com/jiashiwen/interactcli-rs.git
    cd interactcli-rs
  • 命令行模式

    cargo run requestsample baidu
  • 交互模式

    cargo run -- -i
    interact-rs> requestsample baidu

交互模式

交互模式下使用"Tab"键,进行命令提示

开发步骤

  • 定义命令 cmd 模块用于定义命令以及相关子命令

    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("Shiwen Jia. <[email protected]>")
            .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. <[email protected]>")
                    .arg(
                        Arg::new("debug")
                            .short('d')
                            .help("print debug information verbosely")
                    )
            );
        static ref SUBCMDS: Vec<SubCmd> = 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<String>) {
        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);
    
          ...
      }
      
      ...
    }