Rust命令行工具开发库proto_cli的使用,快速构建高效CLI应用与协议处理工具

Rust命令行工具开发库proto_cli的使用,快速构建高效CLI应用与协议处理工具

Crates.io Crates.io

proto是一个可插拔的新一代多编程语言版本管理器。它是一个统一的工具链。

为什么使用proto?

  • 极速!使用Rust,我们可以保证卓越的性能
  • 多语言支持。一个CLI即可管理所有语言的版本
  • 跨平台,提供一致的机器和团队体验
  • 上下文版本检测,确保始终使用正确的工具版本
  • 校验和验证,确保工具来自可信来源
  • 检测并推断语言生态系统以实现最大兼容性
  • 通过WASM的可插拔架构,支持自定义集成

支持的语言

  • Bun
  • Deno
  • Go
  • moon
  • Node (以及 npm, pnpm, yarn)
  • Python (以及 poetry, uv)
  • Ruby
  • Rust
  • 以及更多通过插件支持的语言

示例代码

这里是一个使用proto_cli构建基本CLI工具的示例:

use proto_cli::{Proto, ProtoCommand, ProtoError};

fn main() -> Result<(), ProtoError> {
    // 创建Proto实例
    let mut proto = Proto::new();
    
    // 添加命令
    proto.add_command(
        ProtoCommand::new("version")
            .about("显示proto版本信息")
            .action(|_| {
                println!("proto version: {}", env!("CARGO_PKG_VERSION"));
                Ok(())
            })
    );
    
    // 添加另一个命令示例
    proto.add_command(
        ProtoCommand::new("install")
            .about("安装工具版本")
            .arg("<tool>", "要安装的工具名称")
            .arg("[version]", "要安装的版本")
            .action(|args| {
                let tool = args.get_str("<tool>")?;
                let version = args.get_opt_str("[version]");
                
                println!("正在安装 {} 版本 {:?}", tool, version);
                // 这里添加实际的安装逻辑
                Ok(())
            })
    );
    
    // 运行CLI
    proto.run()
}

完整示例Demo

下面是一个更完整的CLI应用示例,展示了proto_cli的主要功能:

use proto_cli::{Proto, ProtoCommand, ProtoError, ProtoArgs};
use std::path::PathBuf;

fn main() -> Result<(), ProtoError> {
    let mut proto = Proto::new()
        .name("mycli")
        .version("1.0.0")
        .about("一个示例CLI工具");
    
    // 添加版本命令
    proto.add_command(
        ProtoCommand::new("version")
            .about("显示版本信息")
            .action(|_| {
                println!("mycli version 1.0.0");
                Ok(())
            })
    );
    
    // 添加安装命令
    proto.add_command(
        ProtoCommand::new("install")
            .about("安装工具")
            .arg("<tool>", "要安装的工具名称")
            .arg("[version]", "要安装的特定版本")
            .flag("--global", "全局安装")
            .action(|args| {
                let tool = args.get_str("<tool>")?;
                let version = args.get_opt_str("[version]");
                let global = args.contains_flag("--global");
                
                println!("安装配置:");
                println!("- 工具: {}", tool);
                println!("- 版本: {:?}", version);
                println!("- 全局: {}", global);
                
                // 这里添加实际的安装逻辑
                Ok(())
            })
    );
    
    // 添加配置命令
    proto.add_command(
        ProtoCommand::new("config")
            .about("管理配置")
            .subcommand(
                ProtoCommand::new("set")
                    .about("设置配置值")
                    .arg("<key>", "配置键")
                    .arg("<value>", "配置值")
                    .action(|args| {
                        let key = args.get_str("<key>")?;
                        let value = args.get_str("<value>")?;
                        
                        println!("设置配置 {} = {}", key, value);
                        Ok(())
                    })
            )
            .subcommand(
                ProtoCommand::new("get")
                    .about("获取配置值")
                    .arg("<key>", "配置键")
                    .action(|args| {
                        let key = args.get_str("<key>")?;
                        
                        println!("获取配置 {} = (模拟值)", key);
                        Ok(())
                    })
            )
    );
    
    // 添加复杂命令示例
    proto.add_command(
        ProtoCommand::new("complex")
            .about("复杂命令示例")
            .arg("<input>", "输入文件路径")
            .option("--output <path>", "输出文件路径")
            .flag("--verbose", "显示详细输出")
            .action(|args| {
                let input = PathBuf::from(args.get_str("<input>")?);
                let output = args.get_opt_str("--output")
                    .map(PathBuf::from);
                let verbose = args.contains_flag("--verbose");
                
                println!("处理文件:");
                println!("- 输入: {:?}", input);
                if let Some(out) = output {
                    println!("- 输出: {:?}", out);
                }
                println!("- 详细模式: {}", verbose);
                
                // 添加实际的文件处理逻辑
                Ok(())
            })
    );
    
    // 运行CLI
    proto.run()
}

贡献者

特别感谢为这个项目做出贡献的优秀人员:

Contributors

安装

cargo install proto_cli

运行上述命令将全局安装protoproto-shim二进制文件。


1 回复

Rust命令行工具开发库proto_cli的使用指南

概述

proto_cli是一个用于快速构建高效命令行界面(CLI)应用的Rust库,特别适合需要处理协议数据的工具开发。它提供了简洁的API和强大的功能,帮助开发者快速实现命令行工具。

主要特性

  1. 简洁的命令行参数解析
  2. 内置协议处理功能
  3. 自动生成帮助信息
  4. 支持子命令
  5. 高效错误处理

安装

Cargo.toml中添加依赖:

[dependencies]
proto_cli = "0.3.0"

基本使用方法

1. 创建简单CLI应用

use proto_cli::{ProtoApp, ProtoCommand, ProtoArg};

fn main() {
    // 创建新的CLI应用
    let app = ProtoApp::new("myapp")
        .version("1.0.0")
        .author("Your Name")
        .about("A simple CLI application")
        .arg(ProtoArg::new("input")
            .short('i')
            .long("input")
            .help("Input file path")
            .required(true))
        .arg(ProtoArg::new("output")
            .short('o')
            .long("output")
            .help("Output file path"));

    // 解析命令行参数
    let matches = app.get_matches();
    
    // 获取参数值
    let input = matches.value_of("input").unwrap();
    let output = matches.value_of("output").unwrap_or("default.txt");
    
    println!("Processing {} to {}", input, output);
}

2. 使用子命令

use proto_cli::{ProtoApp, ProtoCommand};

fn main() {
    // 创建带子命令的CLI应用
    let app = ProtoApp::new("network-tool")
        .subcommand(ProtoCommand::new("send")
            .about("Send data to a server")
            .arg(ProtoArg::new("host")
                .required(true)
                .help("Server host address")))
        .subcommand(ProtoCommand::new("receive")
            .about("Receive data from a server")
            .arg(ProtoArg::new("port")
                .short('p')
                .help("Port to listen on")));

    // 解析命令行参数
    let matches = app.get_matches();
    
    // 处理子命令
    match matches.subcommand() {
        Some(("send", sub_m)) => {
            let host = sub_m.value_of("host").unwrap();
            println!("Sending data to {}", host);
        }
        Some(("receive", sub_m)) => {
            let port = sub_m.value_of("port").unwrap_or("8080");
            println!("Listening on port {}", port);
        }
        _ => unreachable!(),
    }
}

3. 协议处理功能

use proto_cli::{ProtoApp, ProtoCommand};
use proto_cli::protocol::{Protocol, ProtocolType};

fn main() {
    // 创建协议分析工具
    let app = ProtoApp::new("protocol-analyzer")
        .arg(ProtoArg::new("protocol")
            .short('p')
            .long("protocol")
            .help("Protocol type (http, tcp, udp)")
            .required(true))
        .arg(ProtoArg::new("data")
            .help("Data to analyze")
            .required(true));

    // 解析命令行参数
    let matches = app.get_matches();
    
    // 获取参数值
    let protocol_type = matches.value_of("protocol").unwrap();
    let data = matches.value_of("data").unwrap();
    
    // 创建协议处理器并分析数据
    let protocol = Protocol::new(ProtocolType::from_str(protocol_type).unwrap());
    let analysis = protocol.analyze(data);
    
    println!("Analysis result: {:?}", analysis);
}

高级功能

自定义验证器

use proto_cli::{ProtoApp, ProtoArg};

// 自定义端口验证函数
fn validate_port(port: &str) -> Result<(), String> {
    port.parse::<u16>()
        .map(|_| ())
        .map_err(|_| format!("'{}' is not a valid port number", port))
}

fn main() {
    // 创建带验证器的CLI应用
    let app = ProtoApp::new("port-checker")
        .arg(ProtoArg::new("port")
            .validator(validate_port)
            .required(true));

    let matches = app.get_matches();
    let port = matches.value_of("port").unwrap();
    println!("Valid port: {}", port);
}

自动补全支持

use proto_cli::{ProtoApp, ProtoCommand, ProtoArg};

fn main() {
    // 创建支持自动补全的CLI应用
    let app = ProtoApp::new("autocomplete-demo")
        .arg(ProtoArg::new("mode")
            .possible_values(&["fast", "slow", "debug"])
            .required(true));
    
    // 生成补全脚本
    // 通常在build.rs中调用
    // ProtoApp::gen_completions("myapp", Shell::Bash, "./completions");
}

完整示例Demo

下面是一个结合多个特性的完整示例,展示如何构建一个功能完善的网络工具:

use proto_cli::{ProtoApp, ProtoCommand, ProtoArg};
use proto_cli::protocol::{Protocol, ProtocolType};
use std::sync::Arc;

// 自定义验证器 - 验证IP地址格式
fn validate_ip(ip: &str) -> Result<(), String> {
    if ip.split('.').count() == 4 && 
       ip.split('.').all(|s| s.parse::<u8>().is_ok()) {
        Ok(())
    } else {
        Err(format!("'{}' is not a valid IPv4 address", ip))
    }
}

fn main() {
    // 共享数据
    let shared_config = Arc::new("v1.0-config".to_string());
    
    // 创建CLI应用
    let app = ProtoApp::new("network-utils")
        .version("1.0.0")
        .author("Network Team")
        .about("Advanced network utilities")
        // 全局参数
        .arg(ProtoArg::new("verbose")
            .short('v')
            .long("verbose")
            .help("Enable verbose output"))
        // 子命令 - ping
        .subcommand(ProtoCommand::new("ping")
            .about("Ping a network host")
            .arg(ProtoArg::new("host")
                .validator(validate_ip)
                .required(true)
                .help("Host to ping")))
        // 子命令 - analyze
        .subcommand(ProtoCommand::new("analyze")
            .about("Analyze protocol data")
            .arg(ProtoArg::new("protocol")
                .short('p')
                .long("protocol")
                .possible_values(&["http", "tcp", "udp"])
                .required(true)
                .help("Protocol type"))
            .arg(ProtoArg::new("data")
                .required(true)
                .help("Data to analyze")));

    // 解析参数
    let matches = app.get_matches();
    
    // 处理全局verbose标志
    let verbose = matches.is_present("verbose");
    if verbose {
        println!("Running in verbose mode with config: {}", shared_config);
    }
    
    // 处理子命令
    match matches.subcommand() {
        Some(("ping", sub_m)) => {
            let host = sub_m.value_of("host").unwrap();
            println!("Pinging {}...", host);
            // 实际ping逻辑...
        }
        Some(("analyze", sub_m)) => {
            let protocol_type = sub_m.value_of("protocol").unwrap();
            let data = sub_m.value_of("data").unwrap();
            
            let protocol = Protocol::new(ProtocolType::from_str(protocol_type).unwrap());
            let analysis = protocol.analyze(data);
            
            println!("Analysis result:");
            println!("Protocol: {}", protocol_type);
            println!("Data size: {} bytes", data.len());
            println!("Details: {:?}", analysis);
        }
        _ => {
            println!("No subcommand specified. Use --help for usage information.");
        }
    }
}

最佳实践

  1. 对于复杂的CLI应用,使用子命令组织功能
  2. 为所有参数和子命令添加详细的帮助信息
  3. 使用验证器确保输入数据的有效性
  4. 考虑为常用工具添加自动补全支持
  5. 使用Protocol特性处理特定协议数据时,遵循相关RFC标准

性能提示

  1. 避免在参数解析过程中进行大量计算
  2. 对于频繁调用的工具,考虑使用Arc共享数据
  3. 使用Protocol的批处理模式处理大量数据

proto_cli通过简洁的API和强大的功能,使得开发命令行工具变得更加高效和愉快。无论是简单的脚本还是复杂的协议分析工具,都能从中受益。

回到顶部