Skip to content

Instantly share code, notes, and snippets.

@andydude
Last active August 29, 2015 14:11
Show Gist options
  • Save andydude/064b917d077cd9a3658e to your computer and use it in GitHub Desktop.
Save andydude/064b917d077cd9a3658e to your computer and use it in GitHub Desktop.
wc.rs
extern crate getopts;
use std::io::File;
use std::path::Path;
use getopts::optflag;
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 = File::open(&Path::new(filename)).read_to_string().unwrap();
for ch in s.chars() {
if ch == '\n' {
total.lines += 1;
}
if ch.is_whitespace() {
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!("{} ", total.lines as int);
}
if show.words {
print!("{} ", total.words as int);
}
if show.chars {
print!("{} ", total.chars as int);
} else if show.bytes {
print!("{} ", total.bytes as int);
}
if show.filename {
println!("{}", filename);
} else {
println!("");
}
}
fn wc_main() {
let program_and_args = std::os::args();
let program = program_and_args[0].clone();
let args = program_and_args.tail();
// options for getopt
let opts = [
optflag("c", "bytes", "bytes."),
optflag("l", "lines", "lines."),
optflag("m", "chars", "chars."),
optflag("w", "words", "words."),
optflag("h", "help" , "This help.")
];
// options for us to use
let mut show = Shown{
lines: false,
words: false,
chars: false,
bytes: false,
filename: true
};
// counts for output
let mut total = Total{
lines: 0,
words: 0,
chars: 0,
bytes: 0
};
let matches = getopts::getopts(args, opts.as_slice()).unwrap();
if matches.opt_present("h") ||
matches.opt_present("help") {
println!("Usage: {} [-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.as_slice();
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);
}
fn main() {
wc_main();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment