rust/src/libstd/getopts.rs

907 lines
25 KiB
Rust
Raw Normal View History

2012-03-07 20:17:30 -06:00
#[doc = "
Simple getopt alternative.
2012-03-07 20:17:30 -06:00
Construct a vector of options, either by using reqopt, optopt, and optflag or
by building them from components yourself, and pass them to getopts, along
with a vector of actual arguments (not including argv[0]). You'll either get a
2012-04-30 21:12:17 -05:00
failure code back, or a match. You'll have to verify whether the amount of
2012-03-07 20:17:30 -06:00
'free' arguments in the match is what you expect. Use opt_* accessors to get
argument values out of the match object.
Single-character options are expected to appear on the command line with a
2012-04-30 21:12:17 -05:00
single preceding dash; multiple-character options are expected to be
proceeded by two dashes. Options that expect an argument accept their argument
following either a space or an equals sign.
2012-03-07 20:17:30 -06:00
# Example
The following example shows simple command line parsing for an application
that requires an input file to be specified, accepts an optional output file
name following -o, and accepts both -h and --help as optional flags.
use std;
import std::getopts::{optopt,optflag,getopts,opt_present,opt_maybe_str,
fail_str};
fn do_work(in: str, out: option<str>) {
// ...
}
fn print_usage(program: str) {
io::println(\"Usage: \" + program + \" [options]/~\");
io::println(\"-o\t\tOutput\");
io::println(\"-h --help\tUsage\");
}
fn main(args: [str]/~) {
check vec::is_not_empty(args);
let program : str = vec::head(args);
2012-03-07 20:17:30 -06:00
let opts = [
optopt(\"o\"),
optflag(\"h\"),
optflag(\"help\")
]/~;
let match = alt getopts(vec::tail(args), opts) {
result::ok(m) { m }
result::err(f) { fail fail_str(f) }
2012-03-07 20:17:30 -06:00
};
if opt_present(match, \"h\") || opt_present(match, \"help\") {
print_usage(program);
2012-03-07 20:17:30 -06:00
ret;
}
let output = opt_maybe_str(match, \"o\");
let input = if vec::is_not_empty(match.free) {
2012-03-07 20:17:30 -06:00
match.free[0]
} else {
print_usage(program);
2012-03-07 20:17:30 -06:00
ret;
};
2012-03-07 20:17:30 -06:00
do_work(input, output);
}
"];
import core::result::{err, ok};
import core::option;
import core::option::{some, none};
export opt;
export reqopt;
export optopt;
export optflag;
export optflagopt;
export optmulti;
export getopts;
export match;
export fail_;
export fail_str;
export opt_present;
export opts_present;
export opt_str;
export opts_str;
export opt_strs;
export opt_maybe_str;
export opt_default;
2012-03-22 22:06:01 -05:00
export result; //NDM
2012-01-19 19:55:34 -06:00
enum name { long(str), short(char), }
2012-01-19 19:55:34 -06:00
enum hasarg { yes, no, maybe, }
2012-01-19 19:55:34 -06:00
enum occur { req, optional, multi, }
2011-04-26 10:46:54 -05:00
2012-03-07 20:17:30 -06:00
#[doc = "A description of a possible option"]
2011-07-27 07:19:39 -05:00
type opt = {name: name, hasarg: hasarg, occur: occur};
2011-04-26 10:46:54 -05:00
fn mkname(nm: str) -> name {
2012-02-23 03:44:04 -06:00
ret if str::len(nm) == 1u {
short(str::char_at(nm, 0u))
} else { long(nm) };
2011-04-26 10:46:54 -05:00
}
2012-03-07 20:17:30 -06:00
#[doc = "Create an option that is required and takes an argument"]
fn reqopt(name: str) -> opt {
2011-07-27 07:19:39 -05:00
ret {name: mkname(name), hasarg: yes, occur: req};
2011-04-26 10:46:54 -05:00
}
2012-03-07 20:17:30 -06:00
#[doc = "Create an option that is optional and takes an argument"]
fn optopt(name: str) -> opt {
2011-07-27 07:19:39 -05:00
ret {name: mkname(name), hasarg: yes, occur: optional};
2011-04-26 10:46:54 -05:00
}
2012-03-07 20:17:30 -06:00
#[doc = "Create an option that is optional and does not take an argument"]
fn optflag(name: str) -> opt {
2011-07-27 07:19:39 -05:00
ret {name: mkname(name), hasarg: no, occur: optional};
2011-04-26 10:46:54 -05:00
}
2012-03-07 20:17:30 -06:00
#[doc = "Create an option that is optional and takes an optional argument"]
fn optflagopt(name: str) -> opt {
2011-07-27 07:19:39 -05:00
ret {name: mkname(name), hasarg: maybe, occur: optional};
}
2012-03-07 20:17:30 -06:00
#[doc = "
Create an option that is optional, takes an argument, and may occur
multiple times
2012-03-07 20:17:30 -06:00
"]
fn optmulti(name: str) -> opt {
2011-07-27 07:19:39 -05:00
ret {name: mkname(name), hasarg: yes, occur: multi};
2011-04-26 10:46:54 -05:00
}
2012-01-19 19:55:34 -06:00
enum optval { val(str), given, }
2011-04-26 10:46:54 -05:00
2012-03-07 20:17:30 -06:00
#[doc = "
The result of checking command line arguments. Contains a vector
of matches and a vector of free strings.
2012-03-07 20:17:30 -06:00
"]
type match = {opts: ~[opt], vals: ~[~[optval]], free: ~[str]};
2011-04-26 10:46:54 -05:00
fn is_arg(arg: str) -> bool {
2012-02-23 03:44:04 -06:00
ret str::len(arg) > 1u && arg[0] == '-' as u8;
2011-04-26 10:46:54 -05:00
}
fn name_str(nm: name) -> str {
ret alt nm { short(ch) { str::from_char(ch) } long(s) { s } };
2011-04-26 10:46:54 -05:00
}
fn find_opt(opts: ~[opt], nm: name) -> option<uint> {
2012-06-30 18:19:07 -05:00
vec::position(opts, |opt| opt.name == nm)
2011-04-26 10:46:54 -05:00
}
2012-03-07 20:17:30 -06:00
#[doc = "
The type returned when the command line does not conform to the
expected format. Pass this value to <fail_str> to get an error message.
2012-03-07 20:17:30 -06:00
"]
2012-01-19 17:20:57 -06:00
enum fail_ {
2012-01-19 19:55:34 -06:00
argument_missing(str),
unrecognized_option(str),
option_missing(str),
option_duplicated(str),
unexpected_argument(str),
2011-04-26 10:46:54 -05:00
}
2012-03-07 20:17:30 -06:00
#[doc = "Convert a `fail_` enum into an error string"]
fn fail_str(f: fail_) -> str {
2011-07-27 07:19:39 -05:00
ret alt f {
2011-09-02 17:34:58 -05:00
argument_missing(nm) { "Argument to option '" + nm + "' missing." }
unrecognized_option(nm) { "Unrecognized option: '" + nm + "'." }
option_missing(nm) { "Required option '" + nm + "' missing." }
2011-07-27 07:19:39 -05:00
option_duplicated(nm) {
2011-09-02 17:34:58 -05:00
"Option '" + nm + "' given more than once."
2011-07-27 07:19:39 -05:00
}
unexpected_argument(nm) {
2011-09-02 17:34:58 -05:00
"Option " + nm + " does not take an argument."
2011-07-27 07:19:39 -05:00
}
};
2011-04-26 10:46:54 -05:00
}
2012-03-07 20:17:30 -06:00
#[doc = "
The result of parsing a command line with a set of options
(result::t<match, fail_>)
2012-03-07 20:17:30 -06:00
"]
type result = result::result<match, fail_>;
2011-04-26 10:46:54 -05:00
2012-03-07 20:17:30 -06:00
#[doc = "
Parse command line arguments according to the provided options
2012-03-07 20:17:30 -06:00
On success returns `ok(opt)`. Use functions such as `opt_present` `opt_str`,
etc. to interrogate results. Returns `err(fail_)` on failure. Use <fail_str>
to get an error message.
"]
fn getopts(args: ~[str], opts: ~[opt]) -> result unsafe {
let n_opts = vec::len::<opt>(opts);
fn f(_x: uint) -> ~[optval] { ret ~[]; }
2012-03-12 17:52:30 -05:00
let vals = vec::to_mut(vec::from_fn(n_opts, f));
let mut free: ~[str] = ~[];
let l = vec::len(args);
let mut i = 0u;
2011-07-27 07:19:39 -05:00
while i < l {
let cur = args[i];
2012-02-23 03:44:04 -06:00
let curlen = str::len(cur);
2011-07-27 07:19:39 -05:00
if !is_arg(cur) {
vec::push(free, cur);
2011-09-02 17:34:58 -05:00
} else if str::eq(cur, "--") {
let mut j = i + 1u;
while j < l { vec::push(free, args[j]); j += 1u; }
2011-04-26 10:46:54 -05:00
break;
} else {
let mut names;
let mut i_arg = option::none::<str>;
if cur[1] == '-' as u8 {
let tail = str::slice(cur, 2u, curlen);
2012-02-11 05:20:45 -06:00
let tail_eq = str::splitn_char(tail, '=', 1u);
if vec::len(tail_eq) <= 1u {
names = ~[long(tail)];
2011-04-26 10:46:54 -05:00
} else {
names =
~[long(tail_eq[0])];
i_arg =
2012-02-11 05:20:45 -06:00
option::some::<str>(tail_eq[1]);
2011-04-26 10:46:54 -05:00
}
} else {
let mut j = 1u;
let mut last_valid_opt_id = option::none;
names = ~[];
2011-07-27 07:19:39 -05:00
while j < curlen {
let range = str::char_range_at(cur, j);
let opt = short(range.ch);
/* In a series of potential options (eg. -aheJ), if we see
one which takes an argument, we assume all subsequent
characters make up the argument. This allows options
such as -L/usr/local/lib/foo to be interpreted correctly
*/
alt find_opt(opts, opt) {
some(id) {
last_valid_opt_id = option::some(id);
}
none {
let arg_follows = option::is_some(last_valid_opt_id) &&
alt opts[option::get(last_valid_opt_id)].hasarg {
yes | maybe { true }
no { false }
};
if arg_follows && j + 1 < curlen {
i_arg = option::some(str::slice(cur, j, curlen));
break;
} else {
last_valid_opt_id = option::none;
}
}
}
vec::push(names, opt);
j = range.next;
2011-04-26 10:46:54 -05:00
}
}
let mut name_pos = 0u;
2012-06-30 18:19:07 -05:00
for vec::each(names) |nm| {
2011-04-26 10:46:54 -05:00
name_pos += 1u;
let optid = alt find_opt(opts, nm) {
some(id) { id }
none { ret err(unrecognized_option(name_str(nm))); }
};
alt opts[optid].hasarg {
no {
2011-09-02 17:34:58 -05:00
if !option::is_none::<str>(i_arg) {
ret err(unexpected_argument(name_str(nm)));
2011-04-26 10:46:54 -05:00
}
vec::push(vals[optid], given);
2011-07-27 07:19:39 -05:00
}
maybe {
2011-09-02 17:34:58 -05:00
if !option::is_none::<str>(i_arg) {
vec::push(vals[optid], val(option::get(i_arg)));
} else if name_pos < vec::len::<name>(names) ||
i + 1u == l || is_arg(args[i + 1u]) {
vec::push(vals[optid], given);
} else { i += 1u; vec::push(vals[optid], val(args[i])); }
2011-07-27 07:19:39 -05:00
}
yes {
2011-09-02 17:34:58 -05:00
if !option::is_none::<str>(i_arg) {
vec::push(vals[optid],
val(option::get::<str>(i_arg)));
} else if i + 1u == l {
ret err(argument_missing(name_str(nm)));
} else { i += 1u; vec::push(vals[optid], val(args[i])); }
2011-07-27 07:19:39 -05:00
}
2011-04-26 10:46:54 -05:00
}
}
}
i += 1u;
}
i = 0u;
2011-07-27 07:19:39 -05:00
while i < n_opts {
let n = vec::len::<optval>(vals[i]);
let occ = opts[i].occur;
2011-07-27 07:19:39 -05:00
if occ == req {
if n == 0u {
ret err(option_missing(name_str(opts[i].name)));
}
}
2011-07-27 07:19:39 -05:00
if occ != multi {
if n > 1u {
ret err(option_duplicated(name_str(opts[i].name)));
}
}
2011-04-26 10:46:54 -05:00
i += 1u;
}
ret ok({opts: opts, vals: vec::from_mut(vals), free: free});
2011-04-26 10:46:54 -05:00
}
fn opt_vals(m: match, nm: str) -> ~[optval] {
2011-07-27 07:19:39 -05:00
ret alt find_opt(m.opts, mkname(nm)) {
some(id) { m.vals[id] }
none { #error("No option '%s' defined", nm); fail }
};
2011-04-26 10:46:54 -05:00
}
fn opt_val(m: match, nm: str) -> optval { ret opt_vals(m, nm)[0]; }
2012-03-07 20:17:30 -06:00
#[doc = "Returns true if an option was matched"]
fn opt_present(m: match, nm: str) -> bool {
ret vec::len::<optval>(opt_vals(m, nm)) > 0u;
2011-04-26 10:46:54 -05:00
}
#[doc = "Returns true if any of several options were matched"]
fn opts_present(m: match, names: ~[str]) -> bool {
2012-06-30 18:19:07 -05:00
for vec::each(names) |nm| {
alt find_opt(m.opts, mkname(nm)) {
some(_) { ret true; }
_ { }
}
}
ret false;
}
2012-03-07 20:17:30 -06:00
#[doc = "
Returns the string argument supplied to a matching option
2012-03-07 20:17:30 -06:00
Fails if the option was not matched or if the match did not take an argument
"]
fn opt_str(m: match, nm: str) -> str {
2011-07-27 07:19:39 -05:00
ret alt opt_val(m, nm) { val(s) { s } _ { fail } };
2011-04-26 10:46:54 -05:00
}
#[doc = "
Returns the string argument supplied to one of several matching options
Fails if the no option was provided from the given list, or if the no such
option took an argument
"]
fn opts_str(m: match, names: ~[str]) -> str {
2012-06-30 18:19:07 -05:00
for vec::each(names) |nm| {
alt opt_val(m, nm) {
val(s) { ret s }
_ { }
}
}
fail;
}
2012-03-07 20:17:30 -06:00
#[doc = "
Returns a vector of the arguments provided to all matches of the given option.
2012-03-07 20:17:30 -06:00
Used when an option accepts multiple values.
2012-03-07 20:17:30 -06:00
"]
fn opt_strs(m: match, nm: str) -> ~[str] {
let mut acc: ~[str] = ~[];
2012-06-30 18:19:07 -05:00
for vec::each(opt_vals(m, nm)) |v| {
alt v { val(s) { vec::push(acc, s); } _ { } }
2011-04-26 10:46:54 -05:00
}
ret acc;
}
2012-03-07 20:17:30 -06:00
#[doc = "
Returns the string argument supplied to a matching option or none
2012-03-07 20:17:30 -06:00
"]
fn opt_maybe_str(m: match, nm: str) -> option<str> {
2011-07-27 07:19:39 -05:00
let vals = opt_vals(m, nm);
2011-09-02 17:34:58 -05:00
if vec::len::<optval>(vals) == 0u { ret none::<str>; }
ret alt vals[0] { val(s) { some::<str>(s) } _ { none::<str> } };
2011-04-26 10:46:54 -05:00
}
2012-03-07 20:17:30 -06:00
#[doc = "
Returns the matching string, a default, or none
Returns none if the option was not present, `def` if the option was
present but no argument was provided, and the argument if the option was
present and an argument was provided.
2012-03-07 20:17:30 -06:00
"]
fn opt_default(m: match, nm: str, def: str) -> option<str> {
2011-07-27 07:19:39 -05:00
let vals = opt_vals(m, nm);
2011-09-02 17:34:58 -05:00
if vec::len::<optval>(vals) == 0u { ret none::<str>; }
ret alt vals[0] { val(s) { some::<str>(s) } _ { some::<str>(def) } }
}
2012-01-17 21:05:07 -06:00
#[cfg(test)]
mod tests {
import opt = getopts;
import result::{err, ok};
2012-01-19 17:20:57 -06:00
enum fail_type {
2012-01-19 19:55:34 -06:00
argument_missing_,
unrecognized_option_,
option_missing_,
option_duplicated_,
unexpected_argument_,
2012-01-17 21:05:07 -06:00
}
fn check_fail_type(f: fail_, ft: fail_type) {
alt f {
argument_missing(_) { assert (ft == argument_missing_); }
unrecognized_option(_) { assert (ft == unrecognized_option_); }
option_missing(_) { assert (ft == option_missing_); }
option_duplicated(_) { assert (ft == option_duplicated_); }
unexpected_argument(_) { assert (ft == unexpected_argument_); }
}
}
// Tests for reqopt
#[test]
fn test_reqopt_long() {
let args = ~["--test=20"];
let opts = ~[reqopt("test")];
2012-01-17 21:05:07 -06:00
let rs = getopts(args, opts);
alt check rs {
2012-01-17 21:05:07 -06:00
ok(m) {
assert (opt_present(m, "test"));
assert (opt_str(m, "test") == "20");
}
}
}
#[test]
fn test_reqopt_long_missing() {
let args = ~["blah"];
let opts = ~[reqopt("test")];
2012-01-17 21:05:07 -06:00
let rs = getopts(args, opts);
alt rs {
err(f) { check_fail_type(f, option_missing_); }
_ { fail; }
}
}
#[test]
fn test_reqopt_long_no_arg() {
let args = ~["--test"];
let opts = ~[reqopt("test")];
2012-01-17 21:05:07 -06:00
let rs = getopts(args, opts);
alt rs {
err(f) { check_fail_type(f, argument_missing_); }
_ { fail; }
}
}
#[test]
fn test_reqopt_long_multi() {
let args = ~["--test=20", "--test=30"];
let opts = ~[reqopt("test")];
2012-01-17 21:05:07 -06:00
let rs = getopts(args, opts);
alt rs {
err(f) { check_fail_type(f, option_duplicated_); }
_ { fail; }
}
}
#[test]
fn test_reqopt_short() {
let args = ~["-t", "20"];
let opts = ~[reqopt("t")];
2012-01-17 21:05:07 -06:00
let rs = getopts(args, opts);
alt rs {
ok(m) {
assert (opt_present(m, "t"));
assert (opt_str(m, "t") == "20");
}
_ { fail; }
}
}
#[test]
fn test_reqopt_short_missing() {
let args = ~["blah"];
let opts = ~[reqopt("t")];
2012-01-17 21:05:07 -06:00
let rs = getopts(args, opts);
alt rs {
err(f) { check_fail_type(f, option_missing_); }
_ { fail; }
}
}
#[test]
fn test_reqopt_short_no_arg() {
let args = ~["-t"];
let opts = ~[reqopt("t")];
2012-01-17 21:05:07 -06:00
let rs = getopts(args, opts);
alt rs {
err(f) { check_fail_type(f, argument_missing_); }
_ { fail; }
}
}
#[test]
fn test_reqopt_short_multi() {
let args = ~["-t", "20", "-t", "30"];
let opts = ~[reqopt("t")];
2012-01-17 21:05:07 -06:00
let rs = getopts(args, opts);
alt rs {
err(f) { check_fail_type(f, option_duplicated_); }
_ { fail; }
}
}
// Tests for optopt
#[test]
fn test_optopt_long() {
let args = ~["--test=20"];
let opts = ~[optopt("test")];
2012-01-17 21:05:07 -06:00
let rs = getopts(args, opts);
alt rs {
ok(m) {
assert (opt_present(m, "test"));
assert (opt_str(m, "test") == "20");
}
_ { fail; }
}
}
#[test]
fn test_optopt_long_missing() {
let args = ~["blah"];
let opts = ~[optopt("test")];
2012-01-17 21:05:07 -06:00
let rs = getopts(args, opts);
alt rs {
ok(m) { assert (!opt_present(m, "test")); }
_ { fail; }
}
}
#[test]
fn test_optopt_long_no_arg() {
let args = ~["--test"];
let opts = ~[optopt("test")];
2012-01-17 21:05:07 -06:00
let rs = getopts(args, opts);
alt rs {
err(f) { check_fail_type(f, argument_missing_); }
_ { fail; }
}
}
#[test]
fn test_optopt_long_multi() {
let args = ~["--test=20", "--test=30"];
let opts = ~[optopt("test")];
2012-01-17 21:05:07 -06:00
let rs = getopts(args, opts);
alt rs {
err(f) { check_fail_type(f, option_duplicated_); }
_ { fail; }
}
}
#[test]
fn test_optopt_short() {
let args = ~["-t", "20"];
let opts = ~[optopt("t")];
2012-01-17 21:05:07 -06:00
let rs = getopts(args, opts);
alt rs {
ok(m) {
assert (opt_present(m, "t"));
assert (opt_str(m, "t") == "20");
}
_ { fail; }
}
}
#[test]
fn test_optopt_short_missing() {
let args = ~["blah"];
let opts = ~[optopt("t")];
2012-01-17 21:05:07 -06:00
let rs = getopts(args, opts);
alt rs {
ok(m) { assert (!opt_present(m, "t")); }
_ { fail; }
}
}
#[test]
fn test_optopt_short_no_arg() {
let args = ~["-t"];
let opts = ~[optopt("t")];
2012-01-17 21:05:07 -06:00
let rs = getopts(args, opts);
alt rs {
err(f) { check_fail_type(f, argument_missing_); }
_ { fail; }
}
}
#[test]
fn test_optopt_short_multi() {
let args = ~["-t", "20", "-t", "30"];
let opts = ~[optopt("t")];
2012-01-17 21:05:07 -06:00
let rs = getopts(args, opts);
alt rs {
err(f) { check_fail_type(f, option_duplicated_); }
_ { fail; }
}
}
// Tests for optflag
#[test]
fn test_optflag_long() {
let args = ~["--test"];
let opts = ~[optflag("test")];
2012-01-17 21:05:07 -06:00
let rs = getopts(args, opts);
alt rs {
ok(m) { assert (opt_present(m, "test")); }
_ { fail; }
}
}
#[test]
fn test_optflag_long_missing() {
let args = ~["blah"];
let opts = ~[optflag("test")];
2012-01-17 21:05:07 -06:00
let rs = getopts(args, opts);
alt rs {
ok(m) { assert (!opt_present(m, "test")); }
_ { fail; }
}
}
#[test]
fn test_optflag_long_arg() {
let args = ~["--test=20"];
let opts = ~[optflag("test")];
2012-01-17 21:05:07 -06:00
let rs = getopts(args, opts);
alt rs {
err(f) {
log(error, fail_str(f));
check_fail_type(f, unexpected_argument_);
}
_ { fail; }
}
}
#[test]
fn test_optflag_long_multi() {
let args = ~["--test", "--test"];
let opts = ~[optflag("test")];
2012-01-17 21:05:07 -06:00
let rs = getopts(args, opts);
alt rs {
err(f) { check_fail_type(f, option_duplicated_); }
_ { fail; }
}
}
#[test]
fn test_optflag_short() {
let args = ~["-t"];
let opts = ~[optflag("t")];
2012-01-17 21:05:07 -06:00
let rs = getopts(args, opts);
alt rs {
ok(m) { assert (opt_present(m, "t")); }
_ { fail; }
}
}
#[test]
fn test_optflag_short_missing() {
let args = ~["blah"];
let opts = ~[optflag("t")];
2012-01-17 21:05:07 -06:00
let rs = getopts(args, opts);
alt rs {
ok(m) { assert (!opt_present(m, "t")); }
_ { fail; }
}
}
#[test]
fn test_optflag_short_arg() {
let args = ~["-t", "20"];
let opts = ~[optflag("t")];
2012-01-17 21:05:07 -06:00
let rs = getopts(args, opts);
alt rs {
ok(m) {
// The next variable after the flag is just a free argument
assert (m.free[0] == "20");
}
_ { fail; }
}
}
#[test]
fn test_optflag_short_multi() {
let args = ~["-t", "-t"];
let opts = ~[optflag("t")];
2012-01-17 21:05:07 -06:00
let rs = getopts(args, opts);
alt rs {
err(f) { check_fail_type(f, option_duplicated_); }
_ { fail; }
}
}
// Tests for optmulti
#[test]
fn test_optmulti_long() {
let args = ~["--test=20"];
let opts = ~[optmulti("test")];
2012-01-17 21:05:07 -06:00
let rs = getopts(args, opts);
alt rs {
ok(m) {
assert (opt_present(m, "test"));
assert (opt_str(m, "test") == "20");
}
_ { fail; }
}
}
#[test]
fn test_optmulti_long_missing() {
let args = ~["blah"];
let opts = ~[optmulti("test")];
2012-01-17 21:05:07 -06:00
let rs = getopts(args, opts);
alt rs {
ok(m) { assert (!opt_present(m, "test")); }
_ { fail; }
}
}
#[test]
fn test_optmulti_long_no_arg() {
let args = ~["--test"];
let opts = ~[optmulti("test")];
2012-01-17 21:05:07 -06:00
let rs = getopts(args, opts);
alt rs {
err(f) { check_fail_type(f, argument_missing_); }
_ { fail; }
}
}
#[test]
fn test_optmulti_long_multi() {
let args = ~["--test=20", "--test=30"];
let opts = ~[optmulti("test")];
2012-01-17 21:05:07 -06:00
let rs = getopts(args, opts);
alt rs {
ok(m) {
assert (opt_present(m, "test"));
assert (opt_str(m, "test") == "20");
assert (opt_strs(m, "test")[0] == "20");
assert (opt_strs(m, "test")[1] == "30");
}
_ { fail; }
}
}
#[test]
fn test_optmulti_short() {
let args = ~["-t", "20"];
let opts = ~[optmulti("t")];
2012-01-17 21:05:07 -06:00
let rs = getopts(args, opts);
alt rs {
ok(m) {
assert (opt_present(m, "t"));
assert (opt_str(m, "t") == "20");
}
_ { fail; }
}
}
#[test]
fn test_optmulti_short_missing() {
let args = ~["blah"];
let opts = ~[optmulti("t")];
2012-01-17 21:05:07 -06:00
let rs = getopts(args, opts);
alt rs {
ok(m) { assert (!opt_present(m, "t")); }
_ { fail; }
}
}
#[test]
fn test_optmulti_short_no_arg() {
let args = ~["-t"];
let opts = ~[optmulti("t")];
2012-01-17 21:05:07 -06:00
let rs = getopts(args, opts);
alt rs {
err(f) { check_fail_type(f, argument_missing_); }
_ { fail; }
}
}
#[test]
fn test_optmulti_short_multi() {
let args = ~["-t", "20", "-t", "30"];
let opts = ~[optmulti("t")];
2012-01-17 21:05:07 -06:00
let rs = getopts(args, opts);
alt rs {
ok(m) {
assert (opt_present(m, "t"));
assert (opt_str(m, "t") == "20");
assert (opt_strs(m, "t")[0] == "20");
assert (opt_strs(m, "t")[1] == "30");
}
_ { fail; }
}
}
#[test]
fn test_unrecognized_option_long() {
let args = ~["--untest"];
let opts = ~[optmulti("t")];
2012-01-17 21:05:07 -06:00
let rs = getopts(args, opts);
alt rs {
err(f) { check_fail_type(f, unrecognized_option_); }
_ { fail; }
}
}
#[test]
fn test_unrecognized_option_short() {
let args = ~["-t"];
let opts = ~[optmulti("test")];
2012-01-17 21:05:07 -06:00
let rs = getopts(args, opts);
alt rs {
err(f) { check_fail_type(f, unrecognized_option_); }
_ { fail; }
}
}
#[test]
fn test_combined() {
let args =
~["prog", "free1", "-s", "20", "free2", "--flag", "--long=30",
"-f", "-m", "40", "-m", "50", "-n", "-A B", "-n", "-60 70"];
2012-01-17 21:05:07 -06:00
let opts =
~[optopt("s"), optflag("flag"), reqopt("long"),
2012-01-17 21:05:07 -06:00
optflag("f"), optmulti("m"), optmulti("n"),
optopt("notpresent")];
2012-01-17 21:05:07 -06:00
let rs = getopts(args, opts);
alt rs {
ok(m) {
assert (m.free[0] == "prog");
assert (m.free[1] == "free1");
assert (opt_str(m, "s") == "20");
assert (m.free[2] == "free2");
assert (opt_present(m, "flag"));
assert (opt_str(m, "long") == "30");
assert (opt_present(m, "f"));
assert (opt_strs(m, "m")[0] == "40");
assert (opt_strs(m, "m")[1] == "50");
assert (opt_strs(m, "n")[0] == "-A B");
assert (opt_strs(m, "n")[1] == "-60 70");
assert (!opt_present(m, "notpresent"));
}
_ { fail; }
}
}
#[test]
fn test_multi() {
let args = ~["-e", "foo", "--encrypt", "foo"];
let opts = ~[optopt("e"), optopt("encrypt")];
let match = alt getopts(args, opts) {
result::ok(m) { m }
result::err(f) { fail; }
};
assert opts_present(match, ~["e"]);
assert opts_present(match, ~["encrypt"]);
assert opts_present(match, ~["encrypt", "e"]);
assert opts_present(match, ~["e", "encrypt"]);
assert !opts_present(match, ~["thing"]);
assert !opts_present(match, ~[]);
assert opts_str(match, ~["e"]) == "foo";
assert opts_str(match, ~["encrypt"]) == "foo";
assert opts_str(match, ~["e", "encrypt"]) == "foo";
assert opts_str(match, ~["encrypt", "e"]) == "foo";
}
#[test]
fn test_nospace() {
let args = ~["-Lfoo"];
let opts = ~[optmulti("L")];
let match = alt getopts(args, opts) {
result::ok(m) { m }
result::err(f) { fail; }
};
assert opts_present(match, ~["L"]);
assert opts_str(match, ~["L"]) == "foo";
}
2012-01-17 21:05:07 -06:00
}
2011-04-26 10:46:54 -05:00
// Local Variables:
// mode: rust;
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End: