@@ 9,6 9,14 @@ dependencies = [
]
[[package]]
+name = "getopts"
+version = "0.2.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
name = "libc"
version = "0.2.48"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ 18,6 26,7 @@ name = "livetools"
version = "0.1.0"
dependencies = [
"chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "getopts 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ 49,6 58,11 @@ dependencies = [
]
[[package]]
+name = "unicode-width"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
name = "winapi"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ 69,11 83,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[metadata]
"checksum chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "45912881121cb26fad7c38c17ba7daa18764771836b34fab7d3fbd93ed633878"
+"checksum getopts 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "0a7292d30132fb5424b354f5dc02512a86e4c516fe544bb7a25e7f266951b797"
"checksum libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)" = "e962c7641008ac010fa60a7dfdc1712449f29c44ef2d4702394aea943ee75047"
"checksum num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "e83d528d2677f0518c570baf2b7abdcf0cd2d248860b68507bdcb3e91d4c0cea"
"checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1"
"checksum redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)" = "423e376fffca3dfa06c9e9790a9ccd282fafb3cc6e6397d01dbf64f9bacc6b85"
"checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f"
+"checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526"
"checksum winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92c1eb33641e276cfa214a0522acad57be5c56b10cb348b3c5117db75f3ac4b0"
"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
@@ 1,5 1,8 @@
extern crate livetools;
+extern crate getopts;
+use getopts::Options;
+use std::env;
use std::time::{Instant};
use std::io::prelude::*;
use std::io;
@@ 14,6 17,23 @@ struct WordCount {
in_word: bool,
}
+#[derive(Debug, Copy, Clone)]
+struct WordCountConfig {
+ count_bytes: bool,
+ count_lines: bool,
+ count_words: bool,
+}
+
+impl WordCountConfig {
+ pub fn new() -> Self {
+ WordCountConfig {
+ count_bytes: false,
+ count_lines: false,
+ count_words: false,
+ }
+ }
+}
+
fn is_posix_whitespace(c: u8) -> bool {
match c {
| b' '
@@ 32,40 52,58 @@ fn is_word_char(c: u8) -> bool {
// !c.is_ascii_whitespace();
}
-fn update_wordcount(s: &WordCount, buf: &[u8]) -> WordCount {
+fn update_wordcount_chunk(cfg: &WordCountConfig, s: &WordCount, buf: &[u8]) -> WordCount {
let mut upd = *s;
upd.bytes += buf.len() as u64;
- buf.iter().for_each(|b|
- {
- if *b == b'\n' {
- upd.lines += 1;
- }
- if is_word_char(*b) {
- if !upd.in_word {
- upd.in_word = true;
- upd.words += 1;
+ if cfg.count_words || cfg.count_lines {
+ buf.iter().for_each(|b|
+ {
+ if cfg.count_lines {
+ if *b == b'\n' {
+ upd.lines += 1;
+ }
+ }
+ if cfg.count_words {
+ if is_word_char(*b) {
+ if !upd.in_word {
+ upd.in_word = true;
+ upd.words += 1;
+ }
+ } else {
+ upd.in_word = false;
+ }
}
- } else {
- upd.in_word = false;
}
- }
- );
+ );
+ }
return upd;
}
-fn format_wordcount(wc: &WordCount) -> String {
- return format!("{:8} {:7} {:8}", wc.lines, wc.words, wc.bytes);
+fn format_wordcount(cfg: &WordCountConfig, wc: &WordCount) -> String {
+ let mut output = String::with_capacity(64);
+
+ if cfg.count_lines {
+ output.push_str(&format!(" {:7}", wc.lines));
+ }
+ if cfg.count_words {
+ output.push_str(&format!(" {:7}", wc.words));
+ }
+ if cfg.count_bytes {
+ output.push_str(&format!(" {:7}", wc.bytes));
+ }
+
+ return output;
}
-fn output_wordcount(wc: &WordCount) {
- let wc_str = format_wordcount(wc);
+fn output_wordcount(cfg: &WordCountConfig, wc: &WordCount) {
+ let wc_str = format_wordcount(cfg, wc);
io::stdout().write(
format!("{}{}", CLEAR_LINE, wc_str).as_bytes()
).expect("Write failed");
io::stdout().flush().expect("Flush failed");
}
-fn live_wordcount() {
+fn live_wordcount(cfg: &WordCountConfig) {
let mut wc = WordCount {
bytes: 0,
lines: 0,
@@ 81,18 119,65 @@ fn live_wordcount() {
if read == 0 {
break
}
- wc = update_wordcount(&wc, &buffer[0..read]);
+ wc = update_wordcount_chunk(cfg, &wc, &buffer[0..read]);
if last_update.map(|i| i.elapsed().as_secs()).unwrap_or(1) >= 1 {
- output_wordcount(&wc);
+ output_wordcount(cfg, &wc);
last_update = Some(Instant::now());
}
}
- output_wordcount(&wc);
+ output_wordcount(cfg, &wc);
io::stdout().write(b"\n").expect("Output Error");
io::stdout().flush().expect("Output Error");
}
+fn print_usage(program: &String, opts: &Options) {
+ let brief = format!("Usage: {} [options]", program);
+ print!("{}", opts.usage(&brief));
+}
+
fn main() {
- live_wordcount()
+ let args: Vec<String> = env::args().collect();
+ let program = &args[0];//.clone();
+
+ let mut cfg = WordCountConfig::new();
+ let mut noflags = true;
+ let mut opts = Options::new();
+ opts.optflag("c", "bytes", "Print count of bytes");
+ opts.optflag("l", "lines", "Print count of lines");
+ opts.optflag("w", "words", "Print count of words");
+ opts.optflag("h", "help", "Show usage");
+ let matches = match opts.parse(&args[1..]) {
+ Ok(m) => { m }
+ Err(f) => {
+ print_usage(program, &opts);
+ println!("\nError parsing arguments:\n{}", f.to_string());
+ return;
+ }
+ };
+
+ if matches.opt_present("h") {
+ print_usage(program, &opts);
+ return;
+ }
+
+ if matches.opt_present("c") {
+ cfg.count_bytes = true;
+ noflags = false;
+ }
+ if matches.opt_present("l") {
+ cfg.count_lines = true;
+ noflags = false;
+ }
+ if matches.opt_present("w") {
+ cfg.count_words = true;
+ noflags = false;
+ }
+ if noflags {
+ cfg.count_bytes = true;
+ cfg.count_lines = true;
+ cfg.count_words = true;
+ }
+
+ live_wordcount(&cfg)
}