Skip to content

Instantly share code, notes, and snippets.

@andydude
Last active December 18, 2015 02:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save andydude/5711998 to your computer and use it in GitHub Desktop.
Save andydude/5711998 to your computer and use it in GitHub Desktop.
POSIX wc (word count)
extern mod extra;
use extra::getopts::*;
pub struct Total {
lines: uint,
words: uint,
chars: uint,
bytes: uint
}
pub struct Shown {
lines: bool,
words: bool,
chars: bool,
bytes: bool,
filename: bool
}
fn count(filename: &str) -> Total {
let mut total = Total{
lines: 0,
words: 0,
chars: 0,
bytes: 0
};
let s = match std::io::read_whole_file_str(&Path(filename)) {
std::result::Err(f) => fail!(f),
std::result::Ok(s) => s
};
for ch in s.iter() {
if ch == '\n' {
total.lines += 1;
}
if std::char::is_whitespace(ch) {
total.words += 1;
}
}
total.chars = s.char_len();
total.bytes = s.len();
return total;
}
fn print_count(filename: &str, show: &Shown) -> Total {
let total = count(filename);
print_total(filename, show, total);
return total;
}
fn print_total(filename: &str, show: &Shown, total: Total) {
if show.lines {
print(fmt!("%d ", total.lines as int));
}
if show.words {
print(fmt!("%d ", total.words as int));
}
if show.chars {
print(fmt!("%d ", total.chars as int));
} else if show.bytes {
print(fmt!("%d ", total.bytes as int));
}
if show.filename {
println(filename);
} else {
println("");
}
}
fn main() {
let program_and_args = std::os::args();
let program = program_and_args[0].clone();
let opts = [
optflag("c"), optflag("bytes"),
optflag("l"), optflag("lines"),
optflag("m"), optflag("chars"),
optflag("w"), optflag("words"),
optflag("h"), optflag("help")
];
let mut show = Shown{
lines: false,
words: false,
chars: false,
bytes: false,
filename: true
};
let mut total = Total{
lines: 0,
words: 0,
chars: 0,
bytes: 0
};
let args = program_and_args.tail();
let matches = match getopts(args, opts) {
std::result::Err(f) => fail!(f.to_err_msg()),
std::result::Ok(m) => m
};
if matches.opt_present("h") ||
matches.opt_present("help") {
println(fmt!("Usage: %s [-clmw] [FILE ...]", program));
println("\t-c | --bytes Print bytes");
println("\t-m | --chars Print chars");
println("\t-w | --words Print words");
println("\t-l | --lines Print lines");
std::os::set_exit_status(1);
return;
}
// HACK: getopt should provide this
let optcount = args.len() - matches.free.len();
if optcount == 0 {
show.lines = true;
show.words = true;
show.bytes = true;
}
if matches.opt_present("l") ||
matches.opt_present("lines") {
show.lines = true;
}
if matches.opt_present("w") ||
matches.opt_present("words") {
show.words = true;
}
if matches.opt_present("m") ||
matches.opt_present("chars") {
show.chars = true;
} else if matches.opt_present("c") ||
matches.opt_present("bytes") {
show.bytes = true;
}
if matches.free.len() == 0 {
show.filename = false;
print_count("/dev/stdin", &show);
return;
}
for arg in matches.free.iter() {
let subtotal;
let filename = arg.to_str();
if filename == ~"-" {
subtotal = print_count("/dev/stdin", &show);
} else {
subtotal = print_count(filename, &show);
}
total.lines += subtotal.lines;
total.words += subtotal.words;
total.chars += subtotal.chars;
total.bytes += subtotal.bytes;
}
show.filename = false;
print_total("total", &show, total);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment