~cypheon/livetools

cd4a81236c176904357a41d62b7bc5b85c6da3dc — Johann Rudloff 2 years ago e09daf9
Implement flags for lwc.
3 files changed, 125 insertions(+), 23 deletions(-)

M Cargo.lock
M Cargo.toml
M src/bin/lwc.rs
M Cargo.lock => Cargo.lock +16 -0
@@ 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"

M Cargo.toml => Cargo.toml +1 -0
@@ 6,3 6,4 @@ edition = "2018"

[dependencies]
chrono = "0.4"
getopts = "0.2"

M src/bin/lwc.rs => src/bin/lwc.rs +108 -23
@@ 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)
}