aboutsummaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
authorGraydon Hoare <[email protected]>2011-04-26 20:39:33 +0000
committerGraydon Hoare <[email protected]>2011-04-26 20:39:33 +0000
commitbc6e9815379e31ac42b4d9fd2b0e20f708c1cc1c (patch)
treef9ccd0dac288b2751536a6e552ec8e094e2a6739 /src/lib
parentVarious bits of trans lint, nothing major. (diff)
parentrustc: Cap ridiculous type name sizes (diff)
downloadrust-bc6e9815379e31ac42b4d9fd2b0e20f708c1cc1c.tar.xz
rust-bc6e9815379e31ac42b4d9fd2b0e20f708c1cc1c.zip
Merge branch 'master' of ssh://github.com/graydon/rust
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/GetOpts.rs249
-rw-r--r--src/lib/Term.rs54
-rw-r--r--src/lib/_str.rs8
-rw-r--r--src/lib/std.rc2
4 files changed, 311 insertions, 2 deletions
diff --git a/src/lib/GetOpts.rs b/src/lib/GetOpts.rs
new file mode 100644
index 00000000..f85ce85c
--- /dev/null
+++ b/src/lib/GetOpts.rs
@@ -0,0 +1,249 @@
+/* Simple getopt alternative. 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 failure code back, or a match.
+ * You'll have to verify whether the amount of 'free' arguments in the match
+ * is what you expect. Use opt_* accessors (bottom of the file) to get
+ * argument values out of the match object.
+ */
+
+import option.some;
+import option.none;
+
+tag name { long(str); short(char); }
+tag hasarg { yes; no; maybe; }
+tag occur { req; optional; multi; }
+
+type opt = rec(name name, hasarg hasarg, occur occur);
+
+fn mkname(str nm) -> name {
+ if (_str.char_len(nm) == 1u) { ret short(_str.char_at(nm, 0u)); }
+ else { ret long(nm); }
+}
+fn reqopt(str name) -> opt {
+ ret rec(name=mkname(name), hasarg=yes, occur=req);
+}
+fn optopt(str name) -> opt {
+ ret rec(name=mkname(name), hasarg=yes, occur=optional);
+}
+fn optflag(str name) -> opt {
+ ret rec(name=mkname(name), hasarg=no, occur=optional);
+}
+fn optmulti(str name) -> opt {
+ ret rec(name=mkname(name), hasarg=yes, occur=multi);
+}
+
+tag optval {
+ val(str);
+ given;
+}
+
+type match = rec(vec[opt] opts, vec[mutable vec[optval]] vals, vec[str] free);
+
+fn is_arg(str arg) -> bool {
+ ret _str.byte_len(arg) > 1u && arg.(0) == '-' as u8;
+}
+fn name_str(name nm) -> str {
+ alt (nm) {
+ case (short(?ch)) {ret _str.from_char(ch);}
+ case (long(?s)) {ret s;}
+ }
+}
+
+// FIXME rustboot workaround
+fn name_eq(name a, name b) -> bool {
+ alt (a) {
+ case (long(?a)) {
+ alt (b) {
+ case (long(?b)) { ret _str.eq(a, b); }
+ case (_) { ret false; }
+ }
+ }
+ case (_) { if (a == b) { ret true; } else {ret false; } }
+ }
+}
+fn find_opt(vec[opt] opts, name nm) -> option.t[uint] {
+ auto i = 0u;
+ auto l = _vec.len[opt](opts);
+ while (i < l) {
+ if (name_eq(opts.(i).name, nm)) { ret some[uint](i); }
+ i += 1u;
+ }
+ ret none[uint];
+}
+
+tag fail_ {
+ argument_missing(str);
+ unrecognized_option(str);
+ option_missing(str);
+ option_duplicated(str);
+}
+
+fn fail_str(fail_ f) -> str {
+ alt (f) {
+ case (argument_missing(?nm)) {
+ ret "Argument to option '" + nm + "' missing.";
+ }
+ case (unrecognized_option(?nm)) {
+ ret "Unrecognized option: '" + nm + "'.";
+ }
+ case (option_missing(?nm)) {
+ ret "Required option '" + nm + "' missing.";
+ }
+ case (option_duplicated(?nm)) {
+ ret "Option '" + nm + "' given more than once.";
+ }
+ }
+}
+
+tag result {
+ success(match);
+ failure(fail_);
+}
+
+fn getopts(vec[str] args, vec[opt] opts) -> result {
+ auto n_opts = _vec.len[opt](opts);
+ fn empty_(uint x) -> vec[optval]{ret _vec.empty[optval]();}
+ auto f = empty_;
+ auto vals = _vec.init_fn_mut[vec[optval]](f, n_opts);
+ let vec[str] free = vec();
+
+ auto l = _vec.len[str](args);
+ auto i = 0u;
+ while (i < l) {
+ auto cur = args.(i);
+ auto curlen = _str.byte_len(cur);
+ if (!is_arg(cur)) {
+ _vec.push[str](free, cur);
+ } else if (_str.eq(cur, "--")) {
+ free += _vec.slice[str](args, i + 1u, l);
+ break;
+ } else {
+ auto names;
+ auto i_arg = option.none[str];
+ if (cur.(1) == '-' as u8) {
+ auto tail = _str.slice(cur, 2u, curlen);
+ auto eq = _str.index(tail, '=' as u8);
+ if (eq == -1) {
+ names = vec(long(tail));
+ } else {
+ names = vec(long(_str.slice(tail, 0u, eq as uint)));
+ i_arg = option.some[str]
+ (_str.slice(tail, (eq as uint) + 1u, curlen - 2u));
+ }
+ } else {
+ auto j = 1u;
+ names = vec();
+ while (j < curlen) {
+ auto range = _str.char_range_at(cur, j);
+ _vec.push[name](names, short(range._0));
+ j = range._1;
+ }
+ }
+ auto name_pos = 0u;
+ for (name nm in names) {
+ name_pos += 1u;
+ auto optid;
+ alt (find_opt(opts, nm)) {
+ case (some[uint](?id)) {optid = id;}
+ case (none[uint]) {
+ ret failure(unrecognized_option(name_str(nm)));
+ }
+ }
+ alt (opts.(optid).hasarg) {
+ case (no) {
+ _vec.push[optval](vals.(optid), given);
+ }
+ case (maybe) {
+ if (!option.is_none[str](i_arg)) {
+ _vec.push[optval](vals.(optid),
+ val(option.get[str](i_arg)));
+ } else if (name_pos < _vec.len[name](names) ||
+ i + 1u == l || is_arg(args.(i + 1u))) {
+ _vec.push[optval](vals.(optid), given);
+ } else {
+ i += 1u;
+ _vec.push[optval](vals.(optid), val(args.(i)));
+ }
+ }
+ case (yes) {
+ if (!option.is_none[str](i_arg)) {
+ _vec.push[optval](vals.(optid),
+ val(option.get[str](i_arg)));
+ } else if (i + 1u == l) {
+ ret failure(argument_missing(name_str(nm)));
+ } else {
+ i += 1u;
+ _vec.push[optval](vals.(optid), val(args.(i)));
+ }
+ }
+ }
+ }
+ }
+ i += 1u;
+ }
+
+ i = 0u;
+ while (i < n_opts) {
+ auto n = _vec.len[optval](vals.(i));
+ auto occ = opts.(i).occur;
+ if (occ == req) {if (n == 0u) {
+ ret failure(option_missing(name_str(opts.(i).name)));
+ }}
+ if (occ != multi) {if (n > 1u) {
+ ret failure(option_duplicated(name_str(opts.(i).name)));
+ }}
+ i += 1u;
+ }
+
+ ret success(rec(opts=opts, vals=vals, free=free));
+}
+
+fn opt_vals(match m, str nm) -> vec[optval] {
+ alt (find_opt(m.opts, mkname(nm))) {
+ case (some[uint](?id)) { ret m.vals.(id); }
+ case (none[uint]) {
+ log_err "No option '" + nm + "' defined.";
+ fail;
+ }
+ }
+}
+fn opt_val(match m, str nm) -> optval {
+ ret opt_vals(m, nm).(0);
+}
+fn opt_present(match m, str nm) -> bool {
+ ret _vec.len[optval](opt_vals(m, nm)) > 0u;
+}
+fn opt_str(match m, str nm) -> str {
+ alt (opt_val(m, nm)) {
+ case (val(?s)) { ret s; }
+ case (_) { fail; }
+ }
+}
+fn opt_strs(match m, str nm) -> vec[str] {
+ let vec[str] acc = vec();
+ for (optval v in opt_vals(m, nm)) {
+ alt (v) {
+ case (val(?s)) { _vec.push[str](acc, s); }
+ case (_) {}
+ }
+ }
+ ret acc;
+}
+fn opt_maybe_str(match m, str nm) -> option.t[str] {
+ auto vals = opt_vals(m, nm);
+ if (_vec.len[optval](vals) == 0u) { ret none[str]; }
+ alt (vals.(0)) {
+ case (val(?s)) { ret some[str](s); }
+ case (_) { ret none[str]; }
+ }
+}
+
+// Local Variables:
+// mode: rust;
+// fill-column: 78;
+// indent-tabs-mode: nil
+// c-basic-offset: 4
+// buffer-file-coding-system: utf-8-unix
+// compile-command: "make -k -C .. 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
+// End:
diff --git a/src/lib/Term.rs b/src/lib/Term.rs
new file mode 100644
index 00000000..9bf90b1c
--- /dev/null
+++ b/src/lib/Term.rs
@@ -0,0 +1,54 @@
+// Simple ANSI color library.
+//
+// TODO: Windows support.
+
+const u8 color_black = 0u8;
+const u8 color_red = 1u8;
+const u8 color_green = 2u8;
+const u8 color_yellow = 3u8;
+const u8 color_blue = 4u8;
+const u8 color_magenta = 5u8;
+const u8 color_cyan = 6u8;
+const u8 color_light_gray = 7u8;
+const u8 color_light_grey = 7u8;
+const u8 color_dark_gray = 8u8;
+const u8 color_dark_grey = 8u8;
+const u8 color_bright_red = 9u8;
+const u8 color_bright_green = 10u8;
+const u8 color_bright_yellow = 11u8;
+const u8 color_bright_blue = 12u8;
+const u8 color_bright_magenta = 13u8;
+const u8 color_bright_cyan = 14u8;
+const u8 color_bright_white = 15u8;
+
+fn esc(io.buf_writer writer) {
+ writer.write(vec(0x1bu8, '[' as u8));
+}
+
+fn reset(io.buf_writer writer) {
+ esc(writer);
+ writer.write(vec('0' as u8, 'm' as u8));
+}
+
+fn set_color(io.buf_writer writer, u8 first_char, u8 color) {
+ check (color < 16u8);
+
+ esc(writer);
+ if (color >= 8u8) {
+ writer.write(vec('1' as u8, ';' as u8));
+ color -= 8u8;
+ }
+ writer.write(vec(first_char, ('0' as u8) + color, 'm' as u8));
+}
+
+fn fg(io.buf_writer writer, u8 color) {
+ ret set_color(writer, '3' as u8, color);
+}
+
+fn bg(io.buf_writer writer, u8 color) {
+ ret set_color(writer, '4' as u8, color);
+}
+
+// export fg;
+// export bg;
+
diff --git a/src/lib/_str.rs b/src/lib/_str.rs
index 3922acb6..41a86cf3 100644
--- a/src/lib/_str.rs
+++ b/src/lib/_str.rs
@@ -391,10 +391,14 @@ fn ends_with(str haystack, str needle) -> bool {
}
fn substr(str s, uint begin, uint len) -> str {
+ ret slice(s, begin, begin + len);
+}
+
+fn slice(str s, uint begin, uint end) -> str {
let str accum = "";
let uint i = begin;
- while (i < begin+len) {
- accum += unsafe_from_byte(s.(i));
+ while (i < end) {
+ push_byte(accum, s.(i));
i += 1u;
}
ret accum;
diff --git a/src/lib/std.rc b/src/lib/std.rc
index 1056f375..8a9ee42d 100644
--- a/src/lib/std.rc
+++ b/src/lib/std.rc
@@ -70,6 +70,8 @@ mod ebml;
mod UFind;
mod ExtFmt;
mod Box;
+mod GetOpts;
+mod Term;
// Local Variables:
// mode: rust;