mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-08-01 21:47:46 +00:00
commit
7bf48c8c06
6 changed files with 164 additions and 36 deletions
3
Makefile
3
Makefile
|
@ -188,7 +188,8 @@ TEST_PROGS := \
|
||||||
truncate \
|
truncate \
|
||||||
tsort \
|
tsort \
|
||||||
unlink \
|
unlink \
|
||||||
unexpand
|
unexpand \
|
||||||
|
wc
|
||||||
|
|
||||||
TEST ?= $(TEST_PROGS)
|
TEST ?= $(TEST_PROGS)
|
||||||
|
|
||||||
|
|
104
src/wc/wc.rs
104
src/wc/wc.rs
|
@ -25,8 +25,44 @@ use std::str::from_utf8;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
mod util;
|
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 {
|
struct Result {
|
||||||
filename: String,
|
title: String,
|
||||||
bytes: usize,
|
bytes: usize,
|
||||||
chars: usize,
|
chars: usize,
|
||||||
lines: usize,
|
lines: usize,
|
||||||
|
@ -73,7 +109,9 @@ pub fn uumain(args: Vec<String>) -> i32 {
|
||||||
matches.free.push("-".to_string());
|
matches.free.push("-".to_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
match wc(&matches) {
|
let settings = Settings::new(&matches);
|
||||||
|
|
||||||
|
match wc(matches.free, &settings) {
|
||||||
Ok(()) => ( /* pass */ ),
|
Ok(()) => ( /* pass */ ),
|
||||||
Err(e) => return e
|
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
|
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_line_count: usize = 0;
|
||||||
let mut total_word_count: usize = 0;
|
let mut total_word_count: usize = 0;
|
||||||
let mut total_char_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 total_longest_line_length: usize = 0;
|
||||||
|
|
||||||
let mut results = vec!();
|
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 reader = try!(open(&path[..]));
|
||||||
|
|
||||||
let mut line_count: usize = 0;
|
let mut line_count: usize = 0;
|
||||||
|
@ -154,7 +192,7 @@ pub fn wc(matches: &Matches) -> StdResult<(), i32> {
|
||||||
}
|
}
|
||||||
|
|
||||||
results.push(Result {
|
results.push(Result {
|
||||||
filename: path.to_string(),
|
title: path.to_string(),
|
||||||
bytes: byte_count,
|
bytes: byte_count,
|
||||||
chars: char_count,
|
chars: char_count,
|
||||||
lines: line_count,
|
lines: line_count,
|
||||||
|
@ -172,51 +210,47 @@ pub fn wc(matches: &Matches) -> StdResult<(), i32> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// used for formatting
|
// 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() {
|
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 {
|
if files.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);
|
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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print_stats(filename: &str, line_count: usize, word_count: usize, char_count: usize,
|
fn print_stats(settings: &Settings, result: &Result, max_width: usize) {
|
||||||
byte_count: usize, longest_line_length: usize, matches: &Matches, max_str_len: usize) {
|
if settings.show_lines {
|
||||||
if matches.opt_present("lines") {
|
print!("{:1$}", result.lines, max_width);
|
||||||
print!("{:1$}", line_count, max_str_len);
|
|
||||||
}
|
}
|
||||||
if matches.opt_present("words") {
|
if settings.show_words {
|
||||||
print!("{:1$}", word_count, max_str_len);
|
print!("{:1$}", result.words, max_width);
|
||||||
}
|
}
|
||||||
if matches.opt_present("bytes") {
|
if settings.show_bytes {
|
||||||
print!("{:1$}", byte_count, max_str_len);
|
print!("{:1$}", result.bytes, max_width);
|
||||||
}
|
}
|
||||||
if matches.opt_present("chars") {
|
if settings.show_chars {
|
||||||
print!("{:1$}", char_count, max_str_len);
|
print!("{:1$}", result.chars, max_width);
|
||||||
}
|
}
|
||||||
if matches.opt_present("max-line-length") {
|
if settings.show_max_line_length {
|
||||||
print!("{:1$}", longest_line_length, max_str_len);
|
print!("{:1$}", result.max_line_length, max_width);
|
||||||
}
|
}
|
||||||
|
|
||||||
// defaults
|
if result.title != "-" {
|
||||||
if !matches.opt_present("bytes")
|
println!(" {}", result.title);
|
||||||
&& !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);
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
println!("");
|
println!("");
|
||||||
|
|
5
test/fixtures/wc/alice_in_wonderland.txt
vendored
Normal file
5
test/fixtures/wc/alice_in_wonderland.txt
vendored
Normal 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
13
test/fixtures/wc/lorem_ipsum.txt
vendored
Normal 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
18
test/fixtures/wc/moby_dick.txt
vendored
Normal 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
57
test/wc.rs
Normal 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");
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue