diff --git a/mk/crates.mk b/mk/crates.mk index ea573b9db8d21..65fb242576452 100644 --- a/mk/crates.mk +++ b/mk/crates.mk @@ -49,19 +49,20 @@ # automatically generated for all stage/host/target combinations. ################################################################################ -TARGET_CRATES := std extra green rustuv native flate arena glob term semver uuid serialize sync +TARGET_CRATES := std extra green rustuv native flate arena glob term semver \ + uuid serialize sync getopts HOST_CRATES := syntax rustc rustdoc CRATES := $(TARGET_CRATES) $(HOST_CRATES) TOOLS := compiletest rustdoc rustc DEPS_std := native:rustrt -DEPS_extra := std serialize sync term +DEPS_extra := std term sync serialize getopts DEPS_green := std DEPS_rustuv := std native:uv native:uv_support DEPS_native := std DEPS_syntax := std extra term serialize -DEPS_rustc := syntax native:rustllvm flate arena serialize sync -DEPS_rustdoc := rustc native:sundown serialize sync +DEPS_rustc := syntax native:rustllvm flate arena serialize sync getopts +DEPS_rustdoc := rustc native:sundown serialize sync getopts DEPS_flate := std native:miniz DEPS_arena := std extra DEPS_glob := std @@ -70,8 +71,9 @@ DEPS_term := std DEPS_semver := std DEPS_uuid := std serialize DEPS_sync := std +DEPS_getopts := std -TOOL_DEPS_compiletest := extra green rustuv +TOOL_DEPS_compiletest := extra green rustuv getopts TOOL_DEPS_rustdoc := rustdoc green rustuv TOOL_DEPS_rustc := rustc green rustuv TOOL_SOURCE_compiletest := $(S)src/compiletest/compiletest.rs diff --git a/src/compiletest/compiletest.rs b/src/compiletest/compiletest.rs index 8896b44f06008..b3151ac99b249 100644 --- a/src/compiletest/compiletest.rs +++ b/src/compiletest/compiletest.rs @@ -14,13 +14,13 @@ #[deny(warnings)]; extern mod extra; +extern mod getopts; use std::os; use std::io; use std::io::fs; -use extra::getopts; -use extra::getopts::groups::{optopt, optflag, reqopt}; +use getopts::{optopt, optflag, reqopt}; use extra::test; use common::config; @@ -49,7 +49,7 @@ pub fn main() { pub fn parse_config(args: ~[~str]) -> config { - let groups : ~[getopts::groups::OptGroup] = + let groups : ~[getopts::OptGroup] = ~[reqopt("", "compile-lib-path", "path to host shared libraries", "PATH"), reqopt("", "run-lib-path", "path to target shared libraries", "PATH"), reqopt("", "rustc-path", "path to rustc to use for compiling", "PATH"), @@ -85,20 +85,20 @@ pub fn parse_config(args: ~[~str]) -> config { let args_ = args.tail(); if args[1] == ~"-h" || args[1] == ~"--help" { let message = format!("Usage: {} [OPTIONS] [TESTNAME...]", argv0); - println!("{}", getopts::groups::usage(message, groups)); + println!("{}", getopts::usage(message, groups)); println!(""); fail!() } let matches = - &match getopts::groups::getopts(args_, groups) { + &match getopts::getopts(args_, groups) { Ok(m) => m, Err(f) => fail!("{}", f.to_err_msg()) }; if matches.opt_present("h") || matches.opt_present("help") { let message = format!("Usage: {} [OPTIONS] [TESTNAME...]", argv0); - println!("{}", getopts::groups::usage(message, groups)); + println!("{}", getopts::usage(message, groups)); println!(""); fail!() } diff --git a/src/doc/index.md b/src/doc/index.md index 54b8b484693a9..39dc196b6a051 100644 --- a/src/doc/index.md +++ b/src/doc/index.md @@ -39,6 +39,7 @@ li {list-style-type: none; } * [The `arena` allocation library](arena/index.html) * [The `flate` compression library](flate/index.html) +* [The `getopts` argument parsing library](getopts/index.html) * [The `glob` file path matching library](glob/index.html) * [The `semver` version collation library](semver/index.html) * [The `serialize` value encoding/decoding library](serialize/index.html) diff --git a/src/libextra/lib.rs b/src/libextra/lib.rs index 37b4d3cc524be..97c38a59af85b 100644 --- a/src/libextra/lib.rs +++ b/src/libextra/lib.rs @@ -73,7 +73,6 @@ pub mod lru_cache; // And ... other stuff pub mod url; -pub mod getopts; pub mod json; pub mod tempfile; pub mod time; diff --git a/src/libextra/test.rs b/src/libextra/test.rs index c4d27b25b5503..4af0fa1623361 100644 --- a/src/libextra/test.rs +++ b/src/libextra/test.rs @@ -15,10 +15,9 @@ // simplest interface possible for representing and running tests // while providing a base that other test frameworks may build off of. +extern mod getopts; extern mod term; -use getopts; -use getopts::groups; use json::ToJson; use json; use serialize::Decodable; @@ -209,29 +208,29 @@ pub struct TestOpts { /// Result of parsing the options. pub type OptRes = Result; -fn optgroups() -> ~[getopts::groups::OptGroup] { - ~[groups::optflag("", "ignored", "Run ignored tests"), - groups::optflag("", "test", "Run tests and not benchmarks"), - groups::optflag("", "bench", "Run benchmarks instead of tests"), - groups::optflag("h", "help", "Display this message (longer with --help)"), - groups::optopt("", "save-metrics", "Location to save bench metrics", +fn optgroups() -> ~[getopts::OptGroup] { + ~[getopts::optflag("", "ignored", "Run ignored tests"), + getopts::optflag("", "test", "Run tests and not benchmarks"), + getopts::optflag("", "bench", "Run benchmarks instead of tests"), + getopts::optflag("h", "help", "Display this message (longer with --help)"), + getopts::optopt("", "save-metrics", "Location to save bench metrics", "PATH"), - groups::optopt("", "ratchet-metrics", + getopts::optopt("", "ratchet-metrics", "Location to load and save metrics from. The metrics \ loaded are cause benchmarks to fail if they run too \ slowly", "PATH"), - groups::optopt("", "ratchet-noise-percent", + getopts::optopt("", "ratchet-noise-percent", "Tests within N% of the recorded metrics will be \ considered as passing", "PERCENTAGE"), - groups::optopt("", "logfile", "Write logs to the specified file instead \ + getopts::optopt("", "logfile", "Write logs to the specified file instead \ of stdout", "PATH"), - groups::optopt("", "test-shard", "run shard A, of B shards, worth of the testsuite", + getopts::optopt("", "test-shard", "run shard A, of B shards, worth of the testsuite", "A.B")] } fn usage(binary: &str, helpstr: &str) { let message = format!("Usage: {} [OPTIONS] [FILTER]", binary); - println!("{}", groups::usage(message, optgroups())); + println!("{}", getopts::usage(message, optgroups())); println!(""); if helpstr == "help" { println!("{}", "\ @@ -261,7 +260,7 @@ Test Attributes: pub fn parse_opts(args: &[~str]) -> Option { let args_ = args.tail(); let matches = - match groups::getopts(args_, optgroups()) { + match getopts::getopts(args_, optgroups()) { Ok(m) => m, Err(f) => return Some(Err(f.to_err_msg())) }; diff --git a/src/libextra/getopts.rs b/src/libgetopts/lib.rs similarity index 51% rename from src/libextra/getopts.rs rename to src/libgetopts/lib.rs index f29caec5d3307..e5e7c50d2cecd 100644 --- a/src/libextra/getopts.rs +++ b/src/libgetopts/lib.rs @@ -30,8 +30,8 @@ //! file name following `-o`, and accepts both `-h` and `--help` as optional flags. //! //! ~~~{.rust} -//! extern mod extra; -//! use extra::getopts::{optopt,optflag,getopts,Opt}; +//! extern mod getopts; +//! use getopts::{optopt,optflag,getopts,OptGroup}; //! use std::os; //! //! fn do_work(inp: &str, out: Option<~str>) { @@ -42,7 +42,7 @@ //! } //! } //! -//! fn print_usage(program: &str, _opts: &[Opt]) { +//! fn print_usage(program: &str, _opts: &[OptGroup]) { //! println!("Usage: {} [options]", program); //! println!("-o\t\tOutput"); //! println!("-h --help\tUsage"); @@ -54,15 +54,14 @@ //! let program = args[0].clone(); //! //! let opts = ~[ -//! optopt("o"), -//! optflag("h"), -//! optflag("help") +//! optopt("o", "", "set output file name", "NAME"), +//! optflag("h", "help", "print this help menu") //! ]; //! let matches = match getopts(args.tail(), opts) { //! Ok(m) => { m } //! Err(f) => { fail!(f.to_err_msg()) } //! }; -//! if matches.opt_present("h") || matches.opt_present("help") { +//! if matches.opt_present("h") { //! print_usage(program, opts); //! return; //! } @@ -77,6 +76,14 @@ //! } //! ~~~ +#[crate_id = "getopts#0.10-pre"]; +#[crate_type = "rlib"]; +#[crate_type = "dylib"]; +#[license = "MIT/ASL2"]; +#[allow(missing_doc)]; + +#[feature(globs)]; + use std::cmp::Eq; use std::result::{Err, Ok}; use std::result; @@ -122,6 +129,24 @@ pub struct Opt { priv aliases: ~[Opt], } +/// One group of options, e.g., both -h and --help, along with +/// their shared description and properties. +#[deriving(Clone, Eq)] +pub struct OptGroup { + /// Short Name of the `OptGroup` + short_name: ~str, + /// Long Name of the `OptGroup` + long_name: ~str, + /// Hint + hint: ~str, + /// Description + desc: ~str, + /// Whether it has an argument + hasarg: HasArg, + /// How often it can occur + occur: Occur +} + /// Describes wether an option is given at all or has a value. #[deriving(Clone, Eq)] enum Optval { @@ -185,6 +210,50 @@ impl Name { } } +impl OptGroup { + /// Translate OptGroup into Opt. + /// (Both short and long names correspond to different Opts). + pub fn long_to_short(&self) -> Opt { + let OptGroup { + short_name: short_name, + long_name: long_name, + hasarg: hasarg, + occur: occur, + .. + } = (*self).clone(); + + match (short_name.len(), long_name.len()) { + (0,0) => fail!("this long-format option was given no name"), + (0,_) => Opt { + name: Long((long_name)), + hasarg: hasarg, + occur: occur, + aliases: ~[] + }, + (1,0) => Opt { + name: Short(short_name.char_at(0)), + hasarg: hasarg, + occur: occur, + aliases: ~[] + }, + (1,_) => Opt { + name: Long((long_name)), + hasarg: hasarg, + occur: occur, + aliases: ~[ + Opt { + name: Short(short_name.char_at(0)), + hasarg: hasarg, + occur: occur, + aliases: ~[] + } + ] + }, + (_,_) => fail!("something is wrong with the long-form opt") + } + } +} + impl Matches { fn opt_vals(&self, nm: &str) -> ~[Optval] { match find_opt(self.opts, Name::from_str(nm)) { @@ -300,65 +369,89 @@ fn find_opt(opts: &[Opt], nm: Name) -> Option { None } -/// Create an option that is required and takes an argument. -pub fn reqopt(name: &str) -> Opt { - Opt { - name: Name::from_str(name), +/// Create a long option that is required and takes an argument. +pub fn reqopt(short_name: &str, long_name: &str, desc: &str, hint: &str) -> OptGroup { + let len = short_name.len(); + assert!(len == 1 || len == 0); + OptGroup { + short_name: short_name.to_owned(), + long_name: long_name.to_owned(), + hint: hint.to_owned(), + desc: desc.to_owned(), hasarg: Yes, - occur: Req, - aliases: ~[] + occur: Req } } -/// Create an option that is optional and takes an argument. -pub fn optopt(name: &str) -> Opt { - Opt { - name: Name::from_str(name), +/// Create a long option that is optional and takes an argument. +pub fn optopt(short_name: &str, long_name: &str, desc: &str, hint: &str) -> OptGroup { + let len = short_name.len(); + assert!(len == 1 || len == 0); + OptGroup { + short_name: short_name.to_owned(), + long_name: long_name.to_owned(), + hint: hint.to_owned(), + desc: desc.to_owned(), hasarg: Yes, - occur: Optional, - aliases: ~[] + occur: Optional } } -/// Create an option that is optional and does not take an argument. -pub fn optflag(name: &str) -> Opt { - Opt { - name: Name::from_str(name), +/// Create a long option that is optional and does not take an argument. +pub fn optflag(short_name: &str, long_name: &str, desc: &str) -> OptGroup { + let len = short_name.len(); + assert!(len == 1 || len == 0); + OptGroup { + short_name: short_name.to_owned(), + long_name: long_name.to_owned(), + hint: ~"", + desc: desc.to_owned(), hasarg: No, - occur: Optional, - aliases: ~[] + occur: Optional } } -/// Create an option that is optional, does not take an argument, -/// and may occur multiple times. -pub fn optflagmulti(name: &str) -> Opt { - Opt { - name: Name::from_str(name), +/// Create a long option that can occur more than once and does not +/// take an argument. +pub fn optflagmulti(short_name: &str, long_name: &str, desc: &str) -> OptGroup { + let len = short_name.len(); + assert!(len == 1 || len == 0); + OptGroup { + short_name: short_name.to_owned(), + long_name: long_name.to_owned(), + hint: ~"", + desc: desc.to_owned(), hasarg: No, - occur: Multi, - aliases: ~[] + occur: Multi } } -/// Create an option that is optional and takes an optional argument. -pub fn optflagopt(name: &str) -> Opt { - Opt { - name: Name::from_str(name), +/// Create a long option that is optional and takes an optional argument. +pub fn optflagopt(short_name: &str, long_name: &str, desc: &str, hint: &str) -> OptGroup { + let len = short_name.len(); + assert!(len == 1 || len == 0); + OptGroup { + short_name: short_name.to_owned(), + long_name: long_name.to_owned(), + hint: hint.to_owned(), + desc: desc.to_owned(), hasarg: Maybe, - occur: Optional, - aliases: ~[] + occur: Optional } } -/// Create an option that is optional, takes an argument, and may occur +/// Create a long option that is optional, takes an argument, and may occur /// multiple times. -pub fn optmulti(name: &str) -> Opt { - Opt { - name: Name::from_str(name), +pub fn optmulti(short_name: &str, long_name: &str, desc: &str, hint: &str) -> OptGroup { + let len = short_name.len(); + assert!(len == 1 || len == 0); + OptGroup { + short_name: short_name.to_owned(), + long_name: long_name.to_owned(), + hint: hint.to_owned(), + desc: desc.to_owned(), hasarg: Yes, - occur: Multi, - aliases: ~[] + occur: Multi } } @@ -390,7 +483,8 @@ impl Fail_ { /// On success returns `Ok(Opt)`. Use methods such as `opt_present` /// `opt_str`, etc. to interrogate results. Returns `Err(Fail_)` on failure. /// Use `to_err_msg` to get an error message. -pub fn getopts(args: &[~str], opts: &[Opt]) -> Result { +pub fn getopts(args: &[~str], optgrps: &[OptGroup]) -> Result { + let opts = optgrps.map(|x| x.long_to_short()); let n_opts = opts.len(); fn f(_x: uint) -> ~[Optval] { return ~[]; } @@ -516,393 +610,232 @@ pub fn getopts(args: &[~str], opts: &[Opt]) -> Result { }) } -/// A module which provides a way to specify descriptions and -/// groups of short and long option names, together. -pub mod groups { - use getopts::{HasArg, Long, Maybe, Multi, No, Occur, Opt, Optional, Req}; - use getopts::{Short, Yes}; - - /// One group of options, e.g., both -h and --help, along with - /// their shared description and properties. - #[deriving(Clone, Eq)] - pub struct OptGroup { - /// Short Name of the `OptGroup` - short_name: ~str, - /// Long Name of the `OptGroup` - long_name: ~str, - /// Hint - hint: ~str, - /// Description - desc: ~str, - /// Whether it has an argument - hasarg: HasArg, - /// How often it can occur - occur: Occur - } - - impl OptGroup { - /// Translate OptGroup into Opt. - /// (Both short and long names correspond to different Opts). - pub fn long_to_short(&self) -> Opt { - let OptGroup { - short_name: short_name, - long_name: long_name, - hasarg: hasarg, - occur: occur, - .. - } = (*self).clone(); - - match (short_name.len(), long_name.len()) { - (0,0) => fail!("this long-format option was given no name"), - (0,_) => Opt { - name: Long((long_name)), - hasarg: hasarg, - occur: occur, - aliases: ~[] - }, - (1,0) => Opt { - name: Short(short_name.char_at(0)), - hasarg: hasarg, - occur: occur, - aliases: ~[] - }, - (1,_) => Opt { - name: Long((long_name)), - hasarg: hasarg, - occur: occur, - aliases: ~[ - Opt { - name: Short(short_name.char_at(0)), - hasarg: hasarg, - occur: occur, - aliases: ~[] - } - ] - }, - (_,_) => fail!("something is wrong with the long-form opt") - } - } - } +/// Derive a usage message from a set of long options. +pub fn usage(brief: &str, opts: &[OptGroup]) -> ~str { - /// Create a long option that is required and takes an argument. - pub fn reqopt(short_name: &str, long_name: &str, desc: &str, hint: &str) -> OptGroup { - let len = short_name.len(); - assert!(len == 1 || len == 0); - OptGroup { - short_name: short_name.to_owned(), - long_name: long_name.to_owned(), - hint: hint.to_owned(), - desc: desc.to_owned(), - hasarg: Yes, - occur: Req - } - } + let desc_sep = "\n" + " ".repeat(24); - /// Create a long option that is optional and takes an argument. - pub fn optopt(short_name: &str, long_name: &str, desc: &str, hint: &str) -> OptGroup { - let len = short_name.len(); - assert!(len == 1 || len == 0); - OptGroup { - short_name: short_name.to_owned(), - long_name: long_name.to_owned(), - hint: hint.to_owned(), - desc: desc.to_owned(), - hasarg: Yes, - occur: Optional - } - } + let mut rows = opts.iter().map(|optref| { + let OptGroup{short_name: short_name, + long_name: long_name, + hint: hint, + desc: desc, + hasarg: hasarg, + ..} = (*optref).clone(); - /// Create a long option that is optional and does not take an argument. - pub fn optflag(short_name: &str, long_name: &str, desc: &str) -> OptGroup { - let len = short_name.len(); - assert!(len == 1 || len == 0); - OptGroup { - short_name: short_name.to_owned(), - long_name: long_name.to_owned(), - hint: ~"", - desc: desc.to_owned(), - hasarg: No, - occur: Optional - } - } + let mut row = " ".repeat(4); - /// Create a long option that can occur more than once and does not - /// take an argument. - pub fn optflagmulti(short_name: &str, long_name: &str, desc: &str) -> OptGroup { - let len = short_name.len(); - assert!(len == 1 || len == 0); - OptGroup { - short_name: short_name.to_owned(), - long_name: long_name.to_owned(), - hint: ~"", - desc: desc.to_owned(), - hasarg: No, - occur: Multi - } - } - - /// Create a long option that is optional and takes an optional argument. - pub fn optflagopt(short_name: &str, long_name: &str, desc: &str, hint: &str) -> OptGroup { - let len = short_name.len(); - assert!(len == 1 || len == 0); - OptGroup { - short_name: short_name.to_owned(), - long_name: long_name.to_owned(), - hint: hint.to_owned(), - desc: desc.to_owned(), - hasarg: Maybe, - occur: Optional - } - } - - /// Create a long option that is optional, takes an argument, and may occur - /// multiple times. - pub fn optmulti(short_name: &str, long_name: &str, desc: &str, hint: &str) -> OptGroup { - let len = short_name.len(); - assert!(len == 1 || len == 0); - OptGroup { - short_name: short_name.to_owned(), - long_name: long_name.to_owned(), - hint: hint.to_owned(), - desc: desc.to_owned(), - hasarg: Yes, - occur: Multi + // short option + match short_name.len() { + 0 => {} + 1 => { + row.push_char('-'); + row.push_str(short_name); + row.push_char(' '); + } + _ => fail!("the short name should only be 1 ascii char long"), } - } - /// Parse command line args with the provided long format options. - pub fn getopts(args: &[~str], opts: &[OptGroup]) -> ::getopts::Result { - ::getopts::getopts(args, opts.map(|x| x.long_to_short())) - } - - fn format_option(opt: &OptGroup) -> ~str { - let mut line = ~""; - - if opt.occur != Req { - line.push_char('['); + // long option + match long_name.len() { + 0 => {} + _ => { + row.push_str("--"); + row.push_str(long_name); + row.push_char(' '); + } } - // Use short_name is possible, but fallback to long_name. - if opt.short_name.len() > 0 { - line.push_char('-'); - line.push_str(opt.short_name); - } else { - line.push_str("--"); - line.push_str(opt.long_name); + // arg + match hasarg { + No => {} + Yes => row.push_str(hint), + Maybe => { + row.push_char('['); + row.push_str(hint); + row.push_char(']'); + } } - if opt.hasarg != No { - line.push_char(' '); - if opt.hasarg == Maybe { - line.push_char('['); - } - line.push_str(opt.hint); - if opt.hasarg == Maybe { - line.push_char(']'); + // FIXME: #5516 should be graphemes not codepoints + // here we just need to indent the start of the description + let rowlen = row.char_len(); + if rowlen < 24 { + for _ in range(0, 24 - rowlen) { + row.push_char(' '); } + } else { + row.push_str(desc_sep) } - if opt.occur != Req { - line.push_char(']'); - } - if opt.occur == Multi { - line.push_str(".."); + // Normalize desc to contain words separated by one space character + let mut desc_normalized_whitespace = ~""; + for word in desc.words() { + desc_normalized_whitespace.push_str(word); + desc_normalized_whitespace.push_char(' '); } - line - } - - /// Derive a short one-line usage summary from a set of long options. - pub fn short_usage(program_name: &str, opts: &[OptGroup]) -> ~str { - let mut line = ~"Usage: " + program_name + " "; - line.push_str(opts.iter().map(format_option).to_owned_vec().connect(" ")); - - line - } - - /// Derive a usage message from a set of long options. - pub fn usage(brief: &str, opts: &[OptGroup]) -> ~str { - - let desc_sep = "\n" + " ".repeat(24); - - let mut rows = opts.iter().map(|optref| { - let OptGroup{short_name: short_name, - long_name: long_name, - hint: hint, - desc: desc, - hasarg: hasarg, - ..} = (*optref).clone(); - - let mut row = " ".repeat(4); - - // short option - match short_name.len() { - 0 => {} - 1 => { - row.push_char('-'); - row.push_str(short_name); - row.push_char(' '); - } - _ => fail!("the short name should only be 1 ascii char long"), - } + // FIXME: #5516 should be graphemes not codepoints + let mut desc_rows = ~[]; + each_split_within(desc_normalized_whitespace, 54, |substr| { + desc_rows.push(substr.to_owned()); + true + }); - // long option - match long_name.len() { - 0 => {} - _ => { - row.push_str("--"); - row.push_str(long_name); - row.push_char(' '); - } - } + // FIXME: #5516 should be graphemes not codepoints + // wrapped description + row.push_str(desc_rows.connect(desc_sep)); - // arg - match hasarg { - No => {} - Yes => row.push_str(hint), - Maybe => { - row.push_char('['); - row.push_str(hint); - row.push_char(']'); - } - } + row + }); - // FIXME: #5516 should be graphemes not codepoints - // here we just need to indent the start of the description - let rowlen = row.char_len(); - if rowlen < 24 { - for _ in range(0, 24 - rowlen) { - row.push_char(' '); - } - } else { - row.push_str(desc_sep) - } - - // Normalize desc to contain words separated by one space character - let mut desc_normalized_whitespace = ~""; - for word in desc.words() { - desc_normalized_whitespace.push_str(word); - desc_normalized_whitespace.push_char(' '); - } - - // FIXME: #5516 should be graphemes not codepoints - let mut desc_rows = ~[]; - each_split_within(desc_normalized_whitespace, 54, |substr| { - desc_rows.push(substr.to_owned()); - true - }); + format!("{}\n\nOptions:\n{}\n", brief, rows.collect::<~[~str]>().connect("\n")) +} - // FIXME: #5516 should be graphemes not codepoints - // wrapped description - row.push_str(desc_rows.connect(desc_sep)); +fn format_option(opt: &OptGroup) -> ~str { + let mut line = ~""; - row - }); + if opt.occur != Req { + line.push_char('['); + } - format!("{}\n\nOptions:\n{}\n", brief, rows.collect::<~[~str]>().connect("\n")) + // Use short_name is possible, but fallback to long_name. + if opt.short_name.len() > 0 { + line.push_char('-'); + line.push_str(opt.short_name); + } else { + line.push_str("--"); + line.push_str(opt.long_name); } - /// Splits a string into substrings with possibly internal whitespace, - /// each of them at most `lim` bytes long. The substrings have leading and trailing - /// whitespace removed, and are only cut at whitespace boundaries. - /// - /// Note: Function was moved here from `std::str` because this module is the only place that - /// uses it, and because it was to specific for a general string function. - /// - /// #Failure: - /// - /// Fails during iteration if the string contains a non-whitespace - /// sequence longer than the limit. - fn each_split_within<'a>(ss: &'a str, lim: uint, it: |&'a str| -> bool) - -> bool { - // Just for fun, let's write this as a state machine: - - enum SplitWithinState { - A, // leading whitespace, initial state - B, // words - C, // internal and trailing whitespace - } - enum Whitespace { - Ws, // current char is whitespace - Cr // current char is not whitespace + if opt.hasarg != No { + line.push_char(' '); + if opt.hasarg == Maybe { + line.push_char('['); } - enum LengthLimit { - UnderLim, // current char makes current substring still fit in limit - OverLim // current char makes current substring no longer fit in limit + line.push_str(opt.hint); + if opt.hasarg == Maybe { + line.push_char(']'); } + } - let mut slice_start = 0; - let mut last_start = 0; - let mut last_end = 0; - let mut state = A; - let mut fake_i = ss.len(); - let mut lim = lim; + if opt.occur != Req { + line.push_char(']'); + } + if opt.occur == Multi { + line.push_str(".."); + } - let mut cont = true; - let slice: || = || { cont = it(ss.slice(slice_start, last_end)) }; + line +} - // if the limit is larger than the string, lower it to save cycles - if lim >= fake_i { - lim = fake_i; - } +/// Derive a short one-line usage summary from a set of long options. +pub fn short_usage(program_name: &str, opts: &[OptGroup]) -> ~str { + let mut line = ~"Usage: " + program_name + " "; + line.push_str(opts.iter().map(format_option).to_owned_vec().connect(" ")); - let machine: |(uint, char)| -> bool = |(i, c)| { - let whitespace = if ::std::char::is_whitespace(c) { Ws } else { Cr }; - let limit = if (i - slice_start + 1) <= lim { UnderLim } else { OverLim }; - - state = match (state, whitespace, limit) { - (A, Ws, _) => { A } - (A, Cr, _) => { slice_start = i; last_start = i; B } - - (B, Cr, UnderLim) => { B } - (B, Cr, OverLim) if (i - last_start + 1) > lim - => fail!("word starting with {} longer than limit!", - ss.slice(last_start, i + 1)), - (B, Cr, OverLim) => { slice(); slice_start = last_start; B } - (B, Ws, UnderLim) => { last_end = i; C } - (B, Ws, OverLim) => { last_end = i; slice(); A } - - (C, Cr, UnderLim) => { last_start = i; B } - (C, Cr, OverLim) => { slice(); slice_start = i; last_start = i; last_end = i; B } - (C, Ws, OverLim) => { slice(); A } - (C, Ws, UnderLim) => { C } - }; + line +} - cont + +/// Splits a string into substrings with possibly internal whitespace, +/// each of them at most `lim` bytes long. The substrings have leading and trailing +/// whitespace removed, and are only cut at whitespace boundaries. +/// +/// Note: Function was moved here from `std::str` because this module is the only place that +/// uses it, and because it was to specific for a general string function. +/// +/// #Failure: +/// +/// Fails during iteration if the string contains a non-whitespace +/// sequence longer than the limit. +fn each_split_within<'a>(ss: &'a str, lim: uint, it: |&'a str| -> bool) + -> bool { + // Just for fun, let's write this as a state machine: + + enum SplitWithinState { + A, // leading whitespace, initial state + B, // words + C, // internal and trailing whitespace + } + enum Whitespace { + Ws, // current char is whitespace + Cr // current char is not whitespace + } + enum LengthLimit { + UnderLim, // current char makes current substring still fit in limit + OverLim // current char makes current substring no longer fit in limit + } + + let mut slice_start = 0; + let mut last_start = 0; + let mut last_end = 0; + let mut state = A; + let mut fake_i = ss.len(); + let mut lim = lim; + + let mut cont = true; + let slice: || = || { cont = it(ss.slice(slice_start, last_end)) }; + + // if the limit is larger than the string, lower it to save cycles + if lim >= fake_i { + lim = fake_i; + } + + let machine: |(uint, char)| -> bool = |(i, c)| { + let whitespace = if ::std::char::is_whitespace(c) { Ws } else { Cr }; + let limit = if (i - slice_start + 1) <= lim { UnderLim } else { OverLim }; + + state = match (state, whitespace, limit) { + (A, Ws, _) => { A } + (A, Cr, _) => { slice_start = i; last_start = i; B } + + (B, Cr, UnderLim) => { B } + (B, Cr, OverLim) if (i - last_start + 1) > lim + => fail!("word starting with {} longer than limit!", + ss.slice(last_start, i + 1)), + (B, Cr, OverLim) => { slice(); slice_start = last_start; B } + (B, Ws, UnderLim) => { last_end = i; C } + (B, Ws, OverLim) => { last_end = i; slice(); A } + + (C, Cr, UnderLim) => { last_start = i; B } + (C, Cr, OverLim) => { slice(); slice_start = i; last_start = i; last_end = i; B } + (C, Ws, OverLim) => { slice(); A } + (C, Ws, UnderLim) => { C } }; - ss.char_indices().advance(|x| machine(x)); + cont + }; - // Let the automaton 'run out' by supplying trailing whitespace - while cont && match state { B | C => true, A => false } { - machine((fake_i, ' ')); - fake_i += 1; - } - return cont; - } + ss.char_indices().advance(|x| machine(x)); - #[test] - fn test_split_within() { - fn t(s: &str, i: uint, u: &[~str]) { - let mut v = ~[]; - each_split_within(s, i, |s| { v.push(s.to_owned()); true }); - assert!(v.iter().zip(u.iter()).all(|(a,b)| a == b)); - } - t("", 0, []); - t("", 15, []); - t("hello", 15, [~"hello"]); - t("\nMary had a little lamb\nLittle lamb\n", 15, - [~"Mary had a", ~"little lamb", ~"Little lamb"]); - t("\nMary had a little lamb\nLittle lamb\n", ::std::uint::MAX, - [~"Mary had a little lamb\nLittle lamb"]); + // Let the automaton 'run out' by supplying trailing whitespace + while cont && match state { B | C => true, A => false } { + machine((fake_i, ' ')); + fake_i += 1; } -} // end groups module + return cont; +} + +#[test] +fn test_split_within() { + fn t(s: &str, i: uint, u: &[~str]) { + let mut v = ~[]; + each_split_within(s, i, |s| { v.push(s.to_owned()); true }); + assert!(v.iter().zip(u.iter()).all(|(a,b)| a == b)); + } + t("", 0, []); + t("", 15, []); + t("hello", 15, [~"hello"]); + t("\nMary had a little lamb\nLittle lamb\n", 15, + [~"Mary had a", ~"little lamb", ~"Little lamb"]); + t("\nMary had a little lamb\nLittle lamb\n", ::std::uint::MAX, + [~"Mary had a little lamb\nLittle lamb"]); +} #[cfg(test)] mod tests { - - use getopts::groups::OptGroup; - use getopts::*; + use super::*; use std::result::{Err, Ok}; use std::result; @@ -917,73 +850,37 @@ mod tests { } } - // Tests for reqopt #[test] - fn test_reqopt_long() { - let args = ~[~"--test=20"]; - let opts = ~[reqopt("test")]; - let rs = getopts(args, opts); + fn test_reqopt() { + let long_args = ~[~"--test=20"]; + let opts = ~[reqopt("t", "test", "testing", "TEST")]; + let rs = getopts(long_args, opts); match rs { Ok(ref m) => { assert!(m.opt_present("test")); assert_eq!(m.opt_str("test").unwrap(), ~"20"); + assert!(m.opt_present("t")); + assert_eq!(m.opt_str("t").unwrap(), ~"20"); } - _ => { fail!("test_reqopt_long failed"); } + _ => { fail!("test_reqopt failed (long arg)"); } } - } - - #[test] - fn test_reqopt_long_missing() { - let args = ~[~"blah"]; - let opts = ~[reqopt("test")]; - let rs = getopts(args, opts); - match rs { - Err(f) => check_fail_type(f, OptionMissing_), - _ => fail!() - } - } - - #[test] - fn test_reqopt_long_no_arg() { - let args = ~[~"--test"]; - let opts = ~[reqopt("test")]; - let rs = getopts(args, opts); - match rs { - Err(f) => check_fail_type(f, ArgumentMissing_), - _ => fail!() - } - } - - #[test] - fn test_reqopt_long_multi() { - let args = ~[~"--test=20", ~"--test=30"]; - let opts = ~[reqopt("test")]; - let rs = getopts(args, opts); - match rs { - Err(f) => check_fail_type(f, OptionDuplicated_), - _ => fail!() - } - } - - #[test] - fn test_reqopt_short() { - let args = ~[~"-t", ~"20"]; - let opts = ~[reqopt("t")]; - let rs = getopts(args, opts); - match rs { + let short_args = ~[~"-t", ~"20"]; + match getopts(short_args, opts) { Ok(ref m) => { - assert!(m.opt_present("t")); + assert!((m.opt_present("test"))); + assert_eq!(m.opt_str("test").unwrap(), ~"20"); + assert!((m.opt_present("t"))); assert_eq!(m.opt_str("t").unwrap(), ~"20"); } - _ => fail!() + _ => { fail!("test_reqopt failed (short arg)"); } } } #[test] - fn test_reqopt_short_missing() { + fn test_reqopt_missing() { let args = ~[~"blah"]; - let opts = ~[reqopt("t")]; + let opts = ~[reqopt("t", "test", "testing", "TEST")]; let rs = getopts(args, opts); match rs { Err(f) => check_fail_type(f, OptionMissing_), @@ -992,20 +889,25 @@ mod tests { } #[test] - fn test_reqopt_short_no_arg() { - let args = ~[~"-t"]; - let opts = ~[reqopt("t")]; - let rs = getopts(args, opts); + fn test_reqopt_no_arg() { + let long_args = ~[~"--test"]; + let opts = ~[reqopt("t", "test", "testing", "TEST")]; + let rs = getopts(long_args, opts); match rs { Err(f) => check_fail_type(f, ArgumentMissing_), _ => fail!() } + let short_args = ~[~"-t"]; + match getopts(short_args, opts) { + Err(f) => check_fail_type(f, ArgumentMissing_), + _ => fail!() + } } #[test] - fn test_reqopt_short_multi() { - let args = ~[~"-t", ~"20", ~"-t", ~"30"]; - let opts = ~[reqopt("t")]; + fn test_reqopt_multi() { + let args = ~[~"--test=20", ~"-t", ~"30"]; + let opts = ~[reqopt("t", "test", "testing", "TEST")]; let rs = getopts(args, opts); match rs { Err(f) => check_fail_type(f, OptionDuplicated_), @@ -1013,62 +915,26 @@ mod tests { } } - // Tests for optopt #[test] - fn test_optopt_long() { - let args = ~[~"--test=20"]; - let opts = ~[optopt("test")]; - let rs = getopts(args, opts); + fn test_optopt() { + let long_args = ~[~"--test=20"]; + let opts = ~[optopt("t", "test", "testing", "TEST")]; + let rs = getopts(long_args, opts); match rs { Ok(ref m) => { assert!(m.opt_present("test")); assert_eq!(m.opt_str("test").unwrap(), ~"20"); + assert!((m.opt_present("t"))); + assert_eq!(m.opt_str("t").unwrap(), ~"20"); } _ => fail!() } - } - - #[test] - fn test_optopt_long_missing() { - let args = ~[~"blah"]; - let opts = ~[optopt("test")]; - let rs = getopts(args, opts); - match rs { - Ok(ref m) => assert!(!m.opt_present("test")), - _ => fail!() - } - } - - #[test] - fn test_optopt_long_no_arg() { - let args = ~[~"--test"]; - let opts = ~[optopt("test")]; - let rs = getopts(args, opts); - match rs { - Err(f) => check_fail_type(f, ArgumentMissing_), - _ => fail!() - } - } - - #[test] - fn test_optopt_long_multi() { - let args = ~[~"--test=20", ~"--test=30"]; - let opts = ~[optopt("test")]; - let rs = getopts(args, opts); - match rs { - Err(f) => check_fail_type(f, OptionDuplicated_), - _ => fail!() - } - } - - #[test] - fn test_optopt_short() { - let args = ~[~"-t", ~"20"]; - let opts = ~[optopt("t")]; - let rs = getopts(args, opts); - match rs { + let short_args = ~[~"-t", ~"20"]; + match getopts(short_args, opts) { Ok(ref m) => { + assert!((m.opt_present("test"))); + assert_eq!(m.opt_str("test").unwrap(), ~"20"); assert!((m.opt_present("t"))); assert_eq!(m.opt_str("t").unwrap(), ~"20"); } @@ -1077,31 +943,39 @@ mod tests { } #[test] - fn test_optopt_short_missing() { + fn test_optopt_missing() { let args = ~[~"blah"]; - let opts = ~[optopt("t")]; + let opts = ~[optopt("t", "test", "testing", "TEST")]; let rs = getopts(args, opts); match rs { - Ok(ref m) => assert!(!m.opt_present("t")), + Ok(ref m) => { + assert!(!m.opt_present("test")); + assert!(!m.opt_present("t")); + } _ => fail!() } } #[test] - fn test_optopt_short_no_arg() { - let args = ~[~"-t"]; - let opts = ~[optopt("t")]; - let rs = getopts(args, opts); + fn test_optopt_no_arg() { + let long_args = ~[~"--test"]; + let opts = ~[optopt("t", "test", "testing", "TEST")]; + let rs = getopts(long_args, opts); match rs { Err(f) => check_fail_type(f, ArgumentMissing_), _ => fail!() } + let short_args = ~[~"-t"]; + match getopts(short_args, opts) { + Err(f) => check_fail_type(f, ArgumentMissing_), + _ => fail!() + } } #[test] - fn test_optopt_short_multi() { - let args = ~[~"-t", ~"20", ~"-t", ~"30"]; - let opts = ~[optopt("t")]; + fn test_optopt_multi() { + let args = ~[~"--test=20", ~"-t", ~"30"]; + let opts = ~[optopt("t", "test", "testing", "TEST")]; let rs = getopts(args, opts); match rs { Err(f) => check_fail_type(f, OptionDuplicated_), @@ -1109,26 +983,39 @@ mod tests { } } - // Tests for optflag #[test] - fn test_optflag_long() { - let args = ~[~"--test"]; - let opts = ~[optflag("test")]; - let rs = getopts(args, opts); + fn test_optflag() { + let long_args = ~[~"--test"]; + let opts = ~[optflag("t", "test", "testing")]; + let rs = getopts(long_args, opts); match rs { - Ok(ref m) => assert!(m.opt_present("test")), + Ok(ref m) => { + assert!(m.opt_present("test")); + assert!(m.opt_present("t")); + } + _ => fail!() + } + let short_args = ~[~"-t"]; + match getopts(short_args, opts) { + Ok(ref m) => { + assert!(m.opt_present("test")); + assert!(m.opt_present("t")); + } _ => fail!() } } #[test] - fn test_optflag_long_missing() { + fn test_optflag_missing() { let args = ~[~"blah"]; - let opts = ~[optflag("test")]; + let opts = ~[optflag("t", "test", "testing")]; let rs = getopts(args, opts); match rs { - Ok(ref m) => assert!(!m.opt_present("test")), + Ok(ref m) => { + assert!(!m.opt_present("test")); + assert!(!m.opt_present("t")); + } _ => fail!() } } @@ -1136,7 +1023,7 @@ mod tests { #[test] fn test_optflag_long_arg() { let args = ~[~"--test=20"]; - let opts = ~[optflag("test")]; + let opts = ~[optflag("t", "test", "testing")]; let rs = getopts(args, opts); match rs { Err(f) => { @@ -1148,9 +1035,9 @@ mod tests { } #[test] - fn test_optflag_long_multi() { - let args = ~[~"--test", ~"--test"]; - let opts = ~[optflag("test")]; + fn test_optflag_multi() { + let args = ~[~"--test", ~"-t"]; + let opts = ~[optflag("t", "test", "testing")]; let rs = getopts(args, opts); match rs { Err(f) => check_fail_type(f, OptionDuplicated_), @@ -1158,32 +1045,10 @@ mod tests { } } - #[test] - fn test_optflag_short() { - let args = ~[~"-t"]; - let opts = ~[optflag("t")]; - let rs = getopts(args, opts); - match rs { - Ok(ref m) => assert!(m.opt_present("t")), - _ => fail!() - } - } - - #[test] - fn test_optflag_short_missing() { - let args = ~[~"blah"]; - let opts = ~[optflag("t")]; - let rs = getopts(args, opts); - match rs { - Ok(ref m) => assert!(!m.opt_present("t")), - _ => fail!() - } - } - #[test] fn test_optflag_short_arg() { let args = ~[~"-t", ~"20"]; - let opts = ~[optflag("t")]; + let opts = ~[optflag("t", "test", "testing")]; let rs = getopts(args, opts); match rs { Ok(ref m) => { @@ -1195,22 +1060,11 @@ mod tests { } } - #[test] - fn test_optflag_short_multi() { - let args = ~[~"-t", ~"-t"]; - let opts = ~[optflag("t")]; - let rs = getopts(args, opts); - match rs { - Err(f) => check_fail_type(f, OptionDuplicated_), - _ => fail!() - } - } - // Tests for optflagmulti #[test] fn test_optflagmulti_short1() { let args = ~[~"-v"]; - let opts = ~[optflagmulti("v")]; + let opts = ~[optflagmulti("v", "verbose", "verbosity")]; let rs = getopts(args, opts); match rs { Ok(ref m) => { @@ -1223,7 +1077,7 @@ mod tests { #[test] fn test_optflagmulti_short2a() { let args = ~[~"-v", ~"-v"]; - let opts = ~[optflagmulti("v")]; + let opts = ~[optflagmulti("v", "verbose", "verbosity")]; let rs = getopts(args, opts); match rs { Ok(ref m) => { @@ -1236,7 +1090,7 @@ mod tests { #[test] fn test_optflagmulti_short2b() { let args = ~[~"-vv"]; - let opts = ~[optflagmulti("v")]; + let opts = ~[optflagmulti("v", "verbose", "verbosity")]; let rs = getopts(args, opts); match rs { Ok(ref m) => { @@ -1249,7 +1103,7 @@ mod tests { #[test] fn test_optflagmulti_long1() { let args = ~[~"--verbose"]; - let opts = ~[optflagmulti("verbose")]; + let opts = ~[optflagmulti("v", "verbose", "verbosity")]; let rs = getopts(args, opts); match rs { Ok(ref m) => { @@ -1262,7 +1116,7 @@ mod tests { #[test] fn test_optflagmulti_long2() { let args = ~[~"--verbose", ~"--verbose"]; - let opts = ~[optflagmulti("verbose")]; + let opts = ~[optflagmulti("v", "verbose", "verbosity")]; let rs = getopts(args, opts); match rs { Ok(ref m) => { @@ -1272,67 +1126,40 @@ mod tests { } } - // Tests for optmulti #[test] - fn test_optmulti_long() { - let args = ~[~"--test=20"]; - let opts = ~[optmulti("test")]; + fn test_optflagmulti_mix() { + let args = ~[~"--verbose", ~"-v", ~"-vv", ~"verbose"]; + let opts = ~[optflagmulti("v", "verbose", "verbosity")]; let rs = getopts(args, opts); match rs { Ok(ref m) => { - assert!((m.opt_present("test"))); - assert_eq!(m.opt_str("test").unwrap(), ~"20"); + assert_eq!(m.opt_count("verbose"), 4); + assert_eq!(m.opt_count("v"), 4); } _ => fail!() } } + // Tests for optmulti #[test] - fn test_optmulti_long_missing() { - let args = ~[~"blah"]; - let opts = ~[optmulti("test")]; - let rs = getopts(args, opts); - match rs { - Ok(ref m) => assert!(!m.opt_present("test")), - _ => fail!() - } - } - - #[test] - fn test_optmulti_long_no_arg() { - let args = ~[~"--test"]; - let opts = ~[optmulti("test")]; - let rs = getopts(args, opts); - match rs { - Err(f) => check_fail_type(f, ArgumentMissing_), - _ => fail!() - } - } - - #[test] - fn test_optmulti_long_multi() { - let args = ~[~"--test=20", ~"--test=30"]; - let opts = ~[optmulti("test")]; - let rs = getopts(args, opts); + fn test_optmulti() { + let long_args = ~[~"--test=20"]; + let opts = ~[optmulti("t", "test", "testing", "TEST")]; + let rs = getopts(long_args, opts); match rs { Ok(ref m) => { - assert!(m.opt_present("test")); - assert_eq!(m.opt_str("test").unwrap(), ~"20"); - let pair = m.opt_strs("test"); - assert!(pair[0] == ~"20"); - assert!(pair[1] == ~"30"); + assert!((m.opt_present("test"))); + assert_eq!(m.opt_str("test").unwrap(), ~"20"); + assert!((m.opt_present("t"))); + assert_eq!(m.opt_str("t").unwrap(), ~"20"); } _ => fail!() } - } - - #[test] - fn test_optmulti_short() { - let args = ~[~"-t", ~"20"]; - let opts = ~[optmulti("t")]; - let rs = getopts(args, opts); - match rs { + let short_args = ~[~"-t", ~"20"]; + match getopts(short_args, opts) { Ok(ref m) => { + assert!((m.opt_present("test"))); + assert_eq!(m.opt_str("test").unwrap(), ~"20"); assert!((m.opt_present("t"))); assert_eq!(m.opt_str("t").unwrap(), ~"20"); } @@ -1341,61 +1168,65 @@ mod tests { } #[test] - fn test_optmulti_short_missing() { + fn test_optmulti_missing() { let args = ~[~"blah"]; - let opts = ~[optmulti("t")]; + let opts = ~[optmulti("t", "test", "testing", "TEST")]; let rs = getopts(args, opts); match rs { - Ok(ref m) => assert!(!m.opt_present("t")), + Ok(ref m) => { + assert!(!m.opt_present("test")); + assert!(!m.opt_present("t")); + } _ => fail!() } } #[test] - fn test_optmulti_short_no_arg() { - let args = ~[~"-t"]; - let opts = ~[optmulti("t")]; - let rs = getopts(args, opts); + fn test_optmulti_no_arg() { + let long_args = ~[~"--test"]; + let opts = ~[optmulti("t", "test", "testing", "TEST")]; + let rs = getopts(long_args, opts); match rs { Err(f) => check_fail_type(f, ArgumentMissing_), _ => fail!() } + let short_args = ~[~"-t"]; + match getopts(short_args, opts) { + Err(f) => check_fail_type(f, ArgumentMissing_), + _ => fail!() + } } #[test] - fn test_optmulti_short_multi() { - let args = ~[~"-t", ~"20", ~"-t", ~"30"]; - let opts = ~[optmulti("t")]; + fn test_optmulti_multi() { + let args = ~[~"--test=20", ~"-t", ~"30"]; + let opts = ~[optmulti("t", "test", "testing", "TEST")]; let rs = getopts(args, opts); match rs { Ok(ref m) => { - assert!((m.opt_present("t"))); - assert_eq!(m.opt_str("t").unwrap(), ~"20"); - let pair = m.opt_strs("t"); - assert!(pair[0] == ~"20"); - assert!(pair[1] == ~"30"); + assert!(m.opt_present("test")); + assert_eq!(m.opt_str("test").unwrap(), ~"20"); + assert!(m.opt_present("t")); + assert_eq!(m.opt_str("t").unwrap(), ~"20"); + let pair = m.opt_strs("test"); + assert!(pair[0] == ~"20"); + assert!(pair[1] == ~"30"); } _ => fail!() } } #[test] - fn test_unrecognized_option_long() { - let args = ~[~"--untest"]; - let opts = ~[optmulti("t")]; - let rs = getopts(args, opts); + fn test_unrecognized_option() { + let long_args = ~[~"--untest"]; + let opts = ~[optmulti("t", "test", "testing", "TEST")]; + let rs = getopts(long_args, opts); match rs { Err(f) => check_fail_type(f, UnrecognizedOption_), _ => fail!() } - } - - #[test] - fn test_unrecognized_option_short() { - let args = ~[~"-t"]; - let opts = ~[optmulti("test")]; - let rs = getopts(args, opts); - match rs { + let short_args = ~[~"-u"]; + match getopts(short_args, opts) { Err(f) => check_fail_type(f, UnrecognizedOption_), _ => fail!() } @@ -1408,9 +1239,13 @@ mod tests { ~"--flag", ~"--long=30", ~"-f", ~"-m", ~"40", ~"-m", ~"50", ~"-n", ~"-A B", ~"-n", ~"-60 70"]; let opts = - ~[optopt("s"), optflag("flag"), reqopt("long"), - optflag("f"), optmulti("m"), optmulti("n"), - optopt("notpresent")]; + ~[optopt("s", "something", "something", "SOMETHING"), + optflag("", "flag", "a flag"), + reqopt("", "long", "hi", "LONG"), + optflag("f", "", "another flag"), + optmulti("m", "", "mmmmmm", "YUM"), + optmulti("n", "", "nothing", "NOTHING"), + optopt("", "notpresent", "nothing to see here", "NOPE")]; let rs = getopts(args, opts); match rs { Ok(ref m) => { @@ -1435,7 +1270,9 @@ mod tests { #[test] fn test_multi() { - let opts = ~[optopt("e"), optopt("encrypt"), optopt("f")]; + let opts = ~[optopt("e", "", "encrypt", "ENCRYPT"), + optopt("", "encrypt", "encrypt", "ENCRYPT"), + optopt("f", "", "flag", "FLAG")]; let args_single = ~[~"-e", ~"foo"]; let matches_single = &match getopts(args_single, opts) { @@ -1475,7 +1312,8 @@ mod tests { #[test] fn test_nospace() { let args = ~[~"-Lfoo", ~"-M."]; - let opts = ~[optmulti("L"), optmulti("M")]; + let opts = ~[optmulti("L", "", "library directory", "LIB"), + optmulti("M", "", "something", "MMMM")]; let matches = &match getopts(args, opts) { result::Ok(m) => m, result::Err(_) => fail!() @@ -1488,125 +1326,42 @@ mod tests { } #[test] - fn test_groups_reqopt() { - let opt = groups::reqopt("b", "banana", "some bananas", "VAL"); - assert!(opt == OptGroup { short_name: ~"b", - long_name: ~"banana", - hint: ~"VAL", - desc: ~"some bananas", - hasarg: Yes, - occur: Req }) - } - - #[test] - fn test_groups_optopt() { - let opt = groups::optopt("a", "apple", "some apples", "VAL"); - assert!(opt == OptGroup { short_name: ~"a", - long_name: ~"apple", - hint: ~"VAL", - desc: ~"some apples", - hasarg: Yes, - occur: Optional }) - } - - #[test] - fn test_groups_optflag() { - let opt = groups::optflag("k", "kiwi", "some kiwis"); - assert!(opt == OptGroup { short_name: ~"k", - long_name: ~"kiwi", - hint: ~"", - desc: ~"some kiwis", - hasarg: No, - occur: Optional }) - } - - #[test] - fn test_groups_optflagopt() { - let opt = groups::optflagopt("p", "pineapple", "some pineapples", "VAL"); - assert!(opt == OptGroup { short_name: ~"p", - long_name: ~"pineapple", - hint: ~"VAL", - desc: ~"some pineapples", - hasarg: Maybe, - occur: Optional }) - } - - #[test] - fn test_groups_optmulti() { - let opt = groups::optmulti("l", "lime", "some limes", "VAL"); - assert!(opt == OptGroup { short_name: ~"l", - long_name: ~"lime", - hint: ~"VAL", - desc: ~"some limes", - hasarg: Yes, - occur: Multi }) - } - - #[test] - fn test_groups_long_to_short() { - let mut short = reqopt("banana"); - short.aliases = ~[reqopt("b")]; - let verbose = groups::reqopt("b", "banana", "some bananas", "VAL"); + fn test_long_to_short() { + let mut short = Opt { name: Long(~"banana"), + hasarg: Yes, + occur: Req, + aliases: ~[] }; + short.aliases = ~[Opt { name: Short('b'), + hasarg: Yes, + occur: Req, + aliases: ~[] }]; + let verbose = reqopt("b", "banana", "some bananas", "VAL"); assert_eq!(verbose.long_to_short(), short); } #[test] - fn test_groups_getopts() { - let mut banana = reqopt("banana"); - banana.aliases = ~[reqopt("b")]; - let mut apple = optopt("apple"); - apple.aliases = ~[optopt("a")]; - let mut kiwi = optflag("kiwi"); - kiwi.aliases = ~[optflag("k")]; - let short = ~[ - banana, - apple, - kiwi, - optflagopt("p"), - optmulti("l") - ]; - - // short and verbose should always be in the same order. if they - // aren't the test will fail (and in mysterious ways) - - let verbose = ~[ - groups::reqopt("b", "banana", "Desc", "VAL"), - groups::optopt("a", "apple", "Desc", "VAL"), - groups::optflag("k", "kiwi", "Desc"), - groups::optflagopt("p", "", "Desc", "VAL"), - groups::optmulti("l", "", "Desc", "VAL"), - ]; - - let sample_args = ~[~"--kiwi", ~"15", ~"--apple", ~"1", ~"k", - ~"-p", ~"16", ~"l", ~"35"]; - - assert!(getopts(sample_args, short) - == groups::getopts(sample_args, verbose)); - } - - #[test] - fn test_groups_aliases_long_and_short() { + fn test_aliases_long_and_short() { let opts = ~[ - groups::optflagmulti("a", "apple", "Desc"), + optflagmulti("a", "apple", "Desc"), ]; let args = ~[~"-a", ~"--apple", ~"-a"]; - let matches = groups::getopts(args, opts).unwrap(); + let matches = getopts(args, opts).unwrap(); assert_eq!(3, matches.opt_count("a")); assert_eq!(3, matches.opt_count("apple")); } #[test] - fn test_groups_usage() { + fn test_usage() { let optgroups = ~[ - groups::reqopt("b", "banana", "Desc", "VAL"), - groups::optopt("a", "012345678901234567890123456789", + reqopt("b", "banana", "Desc", "VAL"), + optopt("a", "012345678901234567890123456789", "Desc", "VAL"), - groups::optflag("k", "kiwi", "Desc"), - groups::optflagopt("p", "", "Desc", "VAL"), - groups::optmulti("l", "", "Desc", "VAL"), + optflag("k", "kiwi", "Desc"), + optflagopt("p", "", "Desc", "VAL"), + optmulti("l", "", "Desc", "VAL"), ]; let expected = @@ -1621,7 +1376,7 @@ Options: -l VAL Desc "; - let generated_usage = groups::usage("Usage: fruits", optgroups); + let generated_usage = usage("Usage: fruits", optgroups); debug!("expected: <<{}>>", expected); debug!("generated: <<{}>>", generated_usage); @@ -1629,14 +1384,14 @@ Options: } #[test] - fn test_groups_usage_description_wrapping() { + fn test_usage_description_wrapping() { // indentation should be 24 spaces // lines wrap after 78: or rather descriptions wrap after 54 let optgroups = ~[ - groups::optflag("k", "kiwi", + optflag("k", "kiwi", "This is a long description which won't be wrapped..+.."), // 54 - groups::optflag("a", "apple", + optflag("a", "apple", "This is a long description which _will_ be wrapped..+.."), // 55 ]; @@ -1649,7 +1404,7 @@ Options: wrapped..+.. "; - let usage = groups::usage("Usage: fruits", optgroups); + let usage = usage("Usage: fruits", optgroups); debug!("expected: <<{}>>", expected); debug!("generated: <<{}>>", usage); @@ -1657,11 +1412,11 @@ Options: } #[test] - fn test_groups_usage_description_multibyte_handling() { + fn test_usage_description_multibyte_handling() { let optgroups = ~[ - groups::optflag("k", "k\u2013w\u2013", + optflag("k", "k\u2013w\u2013", "The word kiwi is normally spelled with two i's"), - groups::optflag("a", "apple", + optflag("a", "apple", "This \u201Cdescription\u201D has some characters that could \ confuse the line wrapping; an apple costs 0.51€ in some parts of Europe."), ]; @@ -1676,7 +1431,7 @@ Options: some parts of Europe. "; - let usage = groups::usage("Usage: fruits", optgroups); + let usage = usage("Usage: fruits", optgroups); debug!("expected: <<{}>>", expected); debug!("generated: <<{}>>", usage); @@ -1686,16 +1441,16 @@ Options: #[test] fn test_short_usage() { let optgroups = ~[ - groups::reqopt("b", "banana", "Desc", "VAL"), - groups::optopt("a", "012345678901234567890123456789", - "Desc", "VAL"), - groups::optflag("k", "kiwi", "Desc"), - groups::optflagopt("p", "", "Desc", "VAL"), - groups::optmulti("l", "", "Desc", "VAL"), + reqopt("b", "banana", "Desc", "VAL"), + optopt("a", "012345678901234567890123456789", + "Desc", "VAL"), + optflag("k", "kiwi", "Desc"), + optflagopt("p", "", "Desc", "VAL"), + optmulti("l", "", "Desc", "VAL"), ]; let expected = ~"Usage: fruits -b VAL [-a VAL] [-k] [-p [VAL]] [-l VAL].."; - let generated_usage = groups::short_usage("fruits", optgroups); + let generated_usage = short_usage("fruits", optgroups); debug!("expected: <<{}>>", expected); debug!("generated: <<{}>>", generated_usage); diff --git a/src/librustc/driver/driver.rs b/src/librustc/driver/driver.rs index c3b851b76ac04..70974fae5cc28 100644 --- a/src/librustc/driver/driver.rs +++ b/src/librustc/driver/driver.rs @@ -34,8 +34,8 @@ use std::io::fs; use std::io::MemReader; use std::os; use std::vec; -use extra::getopts::groups::{optopt, optmulti, optflag, optflagopt}; -use extra::getopts; +use getopts::{optopt, optmulti, optflag, optflagopt}; +use getopts; use syntax::ast; use syntax::abi; use syntax::attr; @@ -992,7 +992,7 @@ pub fn parse_pretty(sess: Session, name: &str) -> PpMode { } // rustc command line options -pub fn optgroups() -> ~[getopts::groups::OptGroup] { +pub fn optgroups() -> ~[getopts::OptGroup] { ~[ optflag("c", "", "Compile and assemble, but do not link"), optmulti("", "cfg", "Configure the compilation @@ -1188,7 +1188,7 @@ mod test { use driver::driver::{build_configuration, build_session}; use driver::driver::{build_session_options, optgroups}; - use extra::getopts::groups::getopts; + use getopts::getopts; use syntax::attr; use syntax::attr::AttrMetaMethods; use syntax::diagnostic; diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index 52ddc8c810888..9a6cbcc9b9620 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -37,6 +37,7 @@ extern mod arena; extern mod syntax; extern mod serialize; extern mod sync; +extern mod getopts; use back::link; use driver::session; @@ -50,8 +51,6 @@ use std::os; use std::str; use std::task; use std::vec; -use extra::getopts::groups; -use extra::getopts; use syntax::ast; use syntax::attr; use syntax::diagnostic::Emitter; @@ -142,7 +141,7 @@ pub fn usage(argv0: &str) { Additional help: -W help Print 'lint' options and default settings -Z help Print internal options for debugging rustc\n", - groups::usage(message, d::optgroups())); + getopts::usage(message, d::optgroups())); } pub fn describe_warnings() { @@ -201,7 +200,7 @@ pub fn run_compiler(args: &[~str], demitter: @diagnostic::Emitter) { if args.is_empty() { usage(binary); return; } let matches = - &match getopts::groups::getopts(args, d::optgroups()) { + &match getopts::getopts(args, d::optgroups()) { Ok(m) => m, Err(f) => { d::early_error(demitter, f.to_err_msg()); diff --git a/src/librustc/middle/typeck/infer/test.rs b/src/librustc/middle/typeck/infer/test.rs index 6ac4c5ff395ce..dd96018d4af25 100644 --- a/src/librustc/middle/typeck/infer/test.rs +++ b/src/librustc/middle/typeck/infer/test.rs @@ -23,12 +23,9 @@ use middle::lang_items::{LanguageItems, language_items}; use middle::ty::{FnTyBase, FnMeta, FnSig}; use util::ppaux::ty_to_str; -use extra::getopts::groups::{optopt, optmulti, optflag, optflagopt, getopts}; -use extra::getopts::groups; -use extra::getopts::{opt_present}; -use extra::getopts; -use extra::getopts; use extra::oldmap::HashMap; +use getopts::{optopt, optmulti, optflag, optflagopt, getopts}; +use getopts::opt_present; use syntax::codemap::DUMMY_SP; use syntax::parse::parse_crate_from_source_str; use syntax::{ast, attr, parse}; diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 7256e8923fa87..f659c8646f5e4 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -20,13 +20,12 @@ extern mod rustc; extern mod extra; extern mod serialize; extern mod sync; +extern mod getopts; use std::local_data; use std::io; use std::io::{File, MemWriter}; use std::str; -use extra::getopts; -use extra::getopts::groups; use extra::json; use serialize::{Decodable, Encodable}; use extra::time; @@ -80,8 +79,8 @@ pub fn main() { std::os::set_exit_status(main_args(std::os::args())); } -pub fn opts() -> ~[groups::OptGroup] { - use extra::getopts::groups::*; +pub fn opts() -> ~[getopts::OptGroup] { + use getopts::*; ~[ optflag("h", "help", "show this help message"), optflag("", "version", "print rustdoc's version"), @@ -107,11 +106,11 @@ pub fn opts() -> ~[groups::OptGroup] { } pub fn usage(argv0: &str) { - println!("{}", groups::usage(format!("{} [options] ", argv0), opts())); + println!("{}", getopts::usage(format!("{} [options] ", argv0), opts())); } pub fn main_args(args: &[~str]) -> int { - let matches = match groups::getopts(args.tail(), opts()) { + let matches = match getopts::getopts(args.tail(), opts()) { Ok(m) => m, Err(err) => { println!("{}", err.to_err_msg()); diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index 28e62f8fb299a..12f2f2ca9361c 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -16,11 +16,11 @@ use std::run; use std::str; use extra::tempfile::TempDir; -use extra::getopts; use extra::test; use rustc::driver::driver; use rustc::driver::session; use rustc::metadata::creader::Loader; +use getopts; use syntax::diagnostic; use syntax::parse; diff --git a/src/test/bench/shootout-pfib.rs b/src/test/bench/shootout-pfib.rs index 040c8526ee04f..86a2043527e21 100644 --- a/src/test/bench/shootout-pfib.rs +++ b/src/test/bench/shootout-pfib.rs @@ -19,8 +19,9 @@ */ extern mod extra; +extern mod getopts; -use extra::{time, getopts}; +use extra::time; use std::os; use std::result::{Ok, Err}; use std::task; @@ -52,7 +53,7 @@ struct Config { } fn parse_opts(argv: ~[~str]) -> Config { - let opts = ~[getopts::optflag("stress")]; + let opts = ~[getopts::optflag("", "stress", "")]; let opt_args = argv.slice(1, argv.len()); diff --git a/src/test/run-pass/getopts_ref.rs b/src/test/run-pass/getopts_ref.rs index bfc140065655f..db8098a79acb9 100644 --- a/src/test/run-pass/getopts_ref.rs +++ b/src/test/run-pass/getopts_ref.rs @@ -10,13 +10,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -extern mod extra; +extern mod getopts; -use extra::getopts::{optopt, getopts}; +use getopts::{optopt, getopts}; pub fn main() { let args = ~[]; - let opts = ~[optopt("b")]; + let opts = ~[optopt("b", "", "something", "SMTHNG")]; match getopts(args, opts) { Ok(ref m) =>