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 命令行界面
每月93 次下载
14KB
214 行
Rust 中的类型感知命令行解析
理由
虽然 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