6 个版本 (稳定)

使用旧的 Rust 2015

1.1.2 2015年7月2日
1.1.1 2015年3月20日
1.1.0 2015年2月7日
1.0.1 2015年1月24日
0.0.1 2015年1月17日

#421 in 命令行界面

Download history 2/week @ 2024-02-25 93/week @ 2024-03-31

每月93 次下载

MIT 许可证

14KB
214

Rust 中的类型感知命令行解析

Build Status

理由

虽然 Rust 平台上有 getopts,但使用起来不是很方便,因为生成的属性映射必须检查是否存在,然后转换为所需的类型,导致大量选项和模式匹配。

Typedopts 可在 crates.io 上找到

用法

使用此库,您可以定义一个表示可能的参数的结构,派生 Decodable,然后直接解析它

extern crate getopts;
extern crate typedopts;

extern crate "rustc-serialize" as rustc_serialize;
use getopts::Options;
use std::os;
use typedopts::{DecodeResult,ErrorType};
use rustc_serialize::Decodable;

#[derive(RustcDecodable)]
struct Args {
  name:     String,
  quantity: uint
}

fn main() {
  let args = env::args().collect();
  let mut opts = Options::new();
  opts.reqopt("n", "name", "insert a name here", "");
  opts.reqopt("q", "quantity", "insert a quantity here", "");

  let matches = match opts.parse(args.tail()) {
    Ok(m) => { m },
    Err(f) => { println!("{}", f.to_err_msg()); return; }
  };

  let result: DecodeResult<Args> = typedopts::decode(matches);
  match result {
    Ok(decoded) => {
      println!("name is {}", decoded.name);
      println!("quantity is {}", decoded.quantity);
    },
    Err(f) => { println!("{}", f.to_err_msg()); return; }
  }
}

如果 decode 函数找到正确的参数并能解析它们,您将在 Result 中得到所需结构的实例。否则,您将收到一个错误枚举

  • UnimplementedDecoder:需要但不应发生(如果您发现使用场景,请提交问题)
  • MissingField:未找到选项。如果您使用 getopts 的 reqopt 函数,typedopts 会先警告您
  • ExpectedType:选项的值不是所需的类型

除非您想自己处理错误,否则可以直接使用 to__err__msg 函数。

示例

大多数类型都可以由库处理,只要它们可以派生自 Decodable。整数、无符号整数、浮点数、布尔值、字符、字符串都很容易处理。

枚举也需要您将其定义为 Decodable

#[deriving(RustcDecodable)]
enum Color {
  red,
  green,
  blue
}

#[deriving(RustcDecodable)]
pub struct ParseEnum {
  color: Color
}
/* ... */
if(decoded.color == blue) {
  /* ... */
}

选项也受到支持

#[deriving(RustcDecodable)]
pub struct ParseOption {
  option: Option<uint>
}

/* ... */
match decoded.option {
  Some(i) => println!("optional number is {}", i),
  None    => println!("no number was provided")
}

处理带有必选选项的 --help

默认情况下,如果您定义任何选项为必选,getopts 每次都会需要它们,即使您只想显示帮助和用法说明。

在 examples/getopt.rs 文件中有一个解决方案。基本上,您定义一个函数来生成 getopts 实例(请相信我,这将避免移动问题)

extern crate getopts;
extern crate typedopts;
extern crate "rustc-serialize" as rustc_serialize;

use std::os;
use getopts::Options;
use typedopts::{DecodeResult,ErrorType};
use rustc_serialize::Decodable;

#[derive(RustcDecodable)]
struct TestStruct1  {
  data_int: u8,
  maybe: Option<u8>
}

fn generate_options() -> Options {
  let mut opts = Options::new();
  opts.reqopt("d", "data-int", "number", "NB");
  opts.optopt("m", "maybe", "maybe number", "");
  opts.optflag("h", "help", "print this help menu");

  return opts;
}

然后您定义使用函数(来自 getopts 文档)

fn print_usage(program: &str, opts: Options) {
    let brief = format!("Usage: {} [options]", program);
    print!("{}", opts.usage(brief.as_slice()));
}

然后,在您的参数解析函数中,您将解析选项两次,一次检测帮助参数,另一次解析主参数。

fn main() {
  let args = os::args();
  let program = args[0].clone();

  let mut help_opts = Options::new();
  help_opts.optflag("h", "help", "print this help menu");

  help_opts.parse(args.tail()).map(|m| {
    if m.opt_present("h") {
      print_usage(program.as_slice(), generate_options());
      return;
    }
  });

  let mut opts = generate_options();
  let matches = match opts.parse(args.tail()) {
    Ok(m) => { m }
    Err(f) => { println!("{}", f.to_err_msg()); return }
  };

  if matches.opt_present("h") {
    print_usage(program.as_slice(), opts);
    return;
  }

  let result: typedopts::DecodeResult<TestStruct1> = typedopts::decode(matches);

如果发现帮助参数,显示帮助并立即返回,否则正常解析参数。

依赖关系

~360KB