Merge pull request #633 from jbcrail/refactor-wc

Refactor wc.
This commit is contained in:
Heather 2015-06-03 09:13:14 +03:00
commit 7bf48c8c06
6 changed files with 164 additions and 36 deletions

View file

@ -188,7 +188,8 @@ TEST_PROGS := \
truncate \
tsort \
unlink \
unexpand
unexpand \
wc
TEST ?= $(TEST_PROGS)

View file

@ -25,8 +25,44 @@ use std::str::from_utf8;
#[macro_use]
mod util;
struct Settings {
show_bytes: bool,
show_chars: bool,
show_lines: bool,
show_words: bool,
show_max_line_length: bool,
}
impl Settings {
fn new(matches: &Matches) -> Settings {
let settings = Settings {
show_bytes: matches.opt_present("bytes"),
show_chars: matches.opt_present("chars"),
show_lines: matches.opt_present("lines"),
show_words: matches.opt_present("words"),
show_max_line_length: matches.opt_present("L"),
};
if settings.show_bytes
|| settings.show_chars
|| settings.show_lines
|| settings.show_words
|| settings.show_max_line_length {
return settings;
}
Settings {
show_bytes: true,
show_chars: false,
show_lines: true,
show_words: true,
show_max_line_length: false,
}
}
}
struct Result {
filename: String,
title: String,
bytes: usize,
chars: usize,
lines: usize,
@ -73,7 +109,9 @@ pub fn uumain(args: Vec<String>) -> i32 {
matches.free.push("-".to_string());
}
match wc(&matches) {
let settings = Settings::new(&matches);
match wc(matches.free, &settings) {
Ok(()) => ( /* pass */ ),
Err(e) => return e
}
@ -93,7 +131,7 @@ fn is_word_seperator(byte: u8) -> bool {
byte == SPACE || byte == TAB || byte == CR || byte == SYN || byte == FF
}
pub fn wc(matches: &Matches) -> StdResult<(), i32> {
fn wc(files: Vec<String>, settings: &Settings) -> StdResult<(), i32> {
let mut total_line_count: usize = 0;
let mut total_word_count: usize = 0;
let mut total_char_count: usize = 0;
@ -101,9 +139,9 @@ pub fn wc(matches: &Matches) -> StdResult<(), i32> {
let mut total_longest_line_length: usize = 0;
let mut results = vec!();
let mut max_str_len: usize = 0;
let mut max_width: usize = 0;
for path in matches.free.iter() {
for path in files.iter() {
let mut reader = try!(open(&path[..]));
let mut line_count: usize = 0;
@ -154,7 +192,7 @@ pub fn wc(matches: &Matches) -> StdResult<(), i32> {
}
results.push(Result {
filename: path.to_string(),
title: path.to_string(),
bytes: byte_count,
chars: char_count,
lines: line_count,
@ -172,51 +210,47 @@ pub fn wc(matches: &Matches) -> StdResult<(), i32> {
}
// used for formatting
max_str_len = total_byte_count.to_string().len();
max_width = total_byte_count.to_string().len() + 1;
}
for result in results.iter() {
print_stats(&result.filename[..], result.lines, result.words, result.chars, result.bytes, result.max_line_length, matches, max_str_len);
print_stats(settings, &result, max_width);
}
if matches.free.len() > 1 {
print_stats("total", total_line_count, total_word_count, total_char_count, total_byte_count, total_longest_line_length, matches, max_str_len);
if files.len() > 1 {
let result = Result {
title: "total".to_string(),
bytes: total_byte_count,
chars: total_char_count,
lines: total_line_count,
words: total_word_count,
max_line_length: total_longest_line_length,
};
print_stats(settings, &result, max_width);
}
Ok(())
}
fn print_stats(filename: &str, line_count: usize, word_count: usize, char_count: usize,
byte_count: usize, longest_line_length: usize, matches: &Matches, max_str_len: usize) {
if matches.opt_present("lines") {
print!("{:1$}", line_count, max_str_len);
fn print_stats(settings: &Settings, result: &Result, max_width: usize) {
if settings.show_lines {
print!("{:1$}", result.lines, max_width);
}
if matches.opt_present("words") {
print!("{:1$}", word_count, max_str_len);
if settings.show_words {
print!("{:1$}", result.words, max_width);
}
if matches.opt_present("bytes") {
print!("{:1$}", byte_count, max_str_len);
if settings.show_bytes {
print!("{:1$}", result.bytes, max_width);
}
if matches.opt_present("chars") {
print!("{:1$}", char_count, max_str_len);
if settings.show_chars {
print!("{:1$}", result.chars, max_width);
}
if matches.opt_present("max-line-length") {
print!("{:1$}", longest_line_length, max_str_len);
if settings.show_max_line_length {
print!("{:1$}", result.max_line_length, max_width);
}
// defaults
if !matches.opt_present("bytes")
&& !matches.opt_present("chars")
&& !matches.opt_present("lines")
&& !matches.opt_present("words")
&& !matches.opt_present("max-line-length") {
print!("{:1$}", line_count, max_str_len);
print!("{:1$}", word_count, max_str_len + 1);
print!("{:1$}", byte_count, max_str_len + 1);
}
if filename != "-" {
println!(" {}", filename);
if result.title != "-" {
println!(" {}", result.title);
}
else {
println!("");

View file

@ -0,0 +1,5 @@
Alice was beginning to get very tired of sitting by
her sister on the bank, and of having nothing to do: once or twice
she had peeped into the book her sister was reading, but it had no
pictures or conversations in it, "and what is the use of a book,"
thought Alice "without pictures or conversation?"

13
test/fixtures/wc/lorem_ipsum.txt vendored Normal file
View file

@ -0,0 +1,13 @@
Lorem ipsum dolor sit amet, consectetur adipiscing
elit. Nunc interdum suscipit sem vel ornare. Proin euismod, justo
sed mollis dictum, eros urna ultricies augue, eu pharetra mi ex id
ante. Duis convallis porttitor aliquam. Nunc vitae tincidunt ex.
Suspendisse iaculis ligula ac diam consectetur lacinia. Donec vel
velit dui. Etiam fringilla, dolor quis tempor vehicula, lacus
turpis bibendum velit, et pellentesque elit odio a magna. Cras
vulputate tortor non libero vehicula euismod. Aliquam tincidunt
nisl eget enim cursus, viverra sagittis magna commodo. Cras rhoncus
egestas leo nec blandit. Suspendisse potenti. Etiam ullamcorper
leo vel lacus vestibulum, cursus semper eros efficitur. In hac
habitasse platea dictumst. Phasellus scelerisque vehicula
fringilla.

18
test/fixtures/wc/moby_dick.txt vendored Normal file
View file

@ -0,0 +1,18 @@
Call me Ishmael. Some years ago - never mind how long
precisely - having little or no money in my purse, and nothing
particular to interest me on shore, I thought I would sail about a
little and see the watery part of the world. It is a way I have of
driving off the spleen and regulating the circulation. Whenever I
find myself growing grim about the mouth; whenever it is a damp,
drizzly November in my soul; whenever I find myself involuntarily
pausing before coffin warehouses, and bringing up the rear of every
funeral I meet; and especially whenever my hypos get such an upper
hand of me, that it requires a strong moral principle to prevent me
from deliberately stepping into the street, and methodically
knocking people's hats off - then, I account it high time to get to
sea as soon as I can. This is my substitute for pistol and ball.
With a philosophical flourish Cato throws himself upon his sword; I
quietly take to the ship. There is nothing surprising in this. If
they but knew it, almost all men in their degree, some time or
other, cherish very nearly the same feelings towards the ocean with
me.

57
test/wc.rs Normal file
View file

@ -0,0 +1,57 @@
use std::process::Command;
use util::*;
static PROGNAME: &'static str = "./wc";
#[path = "common/util.rs"]
#[macro_use]
mod util;
#[test]
fn test_stdin_default() {
let mut cmd = Command::new(PROGNAME);
let result = run_piped_stdin(&mut cmd, get_file_contents("lorem_ipsum.txt"));
assert_eq!(result.stdout, " 13 109 772\n");
}
#[test]
fn test_stdin_only_bytes() {
let mut cmd = Command::new(PROGNAME);
let result = run_piped_stdin(&mut cmd.args(&["-c"]), get_file_contents("lorem_ipsum.txt"));
assert_eq!(result.stdout, " 772\n");
}
#[test]
fn test_stdin_all_counts() {
let mut cmd = Command::new(PROGNAME);
let result = run_piped_stdin(&mut cmd.args(&["-c", "-m", "-l", "-L", "-w"]), get_file_contents("alice_in_wonderland.txt"));
assert_eq!(result.stdout, " 5 57 302 302 66\n");
}
#[test]
fn test_single_default() {
let mut cmd = Command::new(PROGNAME);
let result = run(&mut cmd.arg("moby_dick.txt"));
assert_eq!(result.stdout, " 18 204 1115 moby_dick.txt\n");
}
#[test]
fn test_single_only_lines() {
let mut cmd = Command::new(PROGNAME);
let result = run(&mut cmd.args(&["-l", "moby_dick.txt"]));
assert_eq!(result.stdout, " 18 moby_dick.txt\n");
}
#[test]
fn test_single_all_counts() {
let mut cmd = Command::new(PROGNAME);
let result = run(&mut cmd.args(&["-c", "-l", "-L", "-m", "-w", "alice_in_wonderland.txt"]));
assert_eq!(result.stdout, " 5 57 302 302 66 alice_in_wonderland.txt\n");
}
#[test]
fn test_multiple_default() {
let mut cmd = Command::new(PROGNAME);
let result = run(&mut cmd.args(&["lorem_ipsum.txt", "moby_dick.txt", "alice_in_wonderland.txt"]));
assert_eq!(result.stdout, " 13 109 772 lorem_ipsum.txt\n 18 204 1115 moby_dick.txt\n 5 57 302 alice_in_wonderland.txt\n 36 370 2189 total\n");
}