From 3402ac506ffffacbd1e2064e8386de2bdbedc697 Mon Sep 17 00:00:00 2001 From: minhtrannhat Date: Sat, 2 Sep 2023 02:31:11 -0400 Subject: [PATCH] Feat(cli): Finished all functionalities - passed all tests --- .github/workflows/rust.yml | 17 +-- Cargo.lock | 208 +++++++++++++++++++++++++++++++++++++ Cargo.toml | 1 + mk-outs.sh | 29 ++++++ src/lib.rs | 66 +++++++++++- tests/cli.rs | 2 +- tests/expected/all.b.out | 22 ++-- tests/expected/all.n.out | 24 ++--- 8 files changed, 336 insertions(+), 33 deletions(-) create mode 100755 mk-outs.sh diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index d54fa2f..6e4ef05 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -2,21 +2,22 @@ name: Rust on: push: - branches: [ "master" ] + branches: ["master"] pull_request: - branches: [ "master" ] + branches: ["master"] env: CARGO_TERM_COLOR: always jobs: build: - runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 - - name: Build - run: cargo build --verbose - - name: Run tests - run: cargo test --verbose + - uses: actions/checkout@v3 + - name: Build + run: cargo build --verbose + - name: Run pre tests + run: ./mk-outs.sh + - name: Run tests + run: cargo test --verbose diff --git a/Cargo.lock b/Cargo.lock index cf83047..e594483 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -106,6 +106,7 @@ dependencies = [ "clap", "predicates", "rand", + "rstest", ] [[package]] @@ -202,6 +203,101 @@ dependencies = [ "num-traits", ] +[[package]] +name = "futures" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23342abe12aba583913b2e62f22225ff9c950774065e4bfb61a19cd9770fec40" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" + +[[package]] +name = "futures-executor" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccecee823288125bd88b4d7f565c9e58e41858e47ab72e8ea2d64e93624386e0" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964" + +[[package]] +name = "futures-macro" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "futures-sink" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e" + +[[package]] +name = "futures-task" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65" + +[[package]] +name = "futures-timer" +version = "3.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e64b03909df88034c26dc1547e8970b91f98bdb65165d6a4e9110d94263dbb2c" + +[[package]] +name = "futures-util" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + [[package]] name = "getrandom" version = "0.2.10" @@ -213,6 +309,12 @@ dependencies = [ "wasi", ] +[[package]] +name = "glob" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" + [[package]] name = "hermit-abi" version = "0.3.2" @@ -278,6 +380,18 @@ version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +[[package]] +name = "pin-project-lite" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + [[package]] name = "ppv-lite86" version = "0.2.17" @@ -315,6 +429,24 @@ dependencies = [ "termtree", ] +[[package]] +name = "proc-macro2" +version = "1.0.66" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +dependencies = [ + "proc-macro2", +] + [[package]] name = "rand" version = "0.8.5" @@ -374,6 +506,50 @@ version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5ea92a5b6195c6ef2a0295ea818b312502c6fc94dde986c5553242e18fd4ce2" +[[package]] +name = "relative-path" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c707298afce11da2efef2f600116fa93ffa7a032b5d7b628aa17711ec81383ca" + +[[package]] +name = "rstest" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97eeab2f3c0a199bc4be135c36c924b6590b88c377d416494288c14f2db30199" +dependencies = [ + "futures", + "futures-timer", + "rstest_macros", + "rustc_version", +] + +[[package]] +name = "rstest_macros" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d428f8247852f894ee1be110b375111b586d4fa431f6c46e64ba5a0dcccbe605" +dependencies = [ + "cfg-if", + "glob", + "proc-macro2", + "quote", + "regex", + "relative-path", + "rustc_version", + "syn", + "unicode-ident", +] + +[[package]] +name = "rustc_version" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +dependencies = [ + "semver", +] + [[package]] name = "rustix" version = "0.38.4" @@ -387,24 +563,56 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "semver" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0293b4b29daaf487284529cc2f5675b8e57c61f70167ba415a463651fd6a918" + [[package]] name = "serde" version = "1.0.176" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "76dc28c9523c5d70816e393136b86d48909cfb27cecaa902d338c19ed47164dc" +[[package]] +name = "slab" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] + [[package]] name = "strsim" version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" +[[package]] +name = "syn" +version = "2.0.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c324c494eba9d92503e6f1ef2e6df781e78f6a7705a0202d9801b198807d518a" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + [[package]] name = "termtree" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3369f5ac52d5eb6ab48c6b4ffdc8efbcad6b89c765749064ba298f2c68a16a76" +[[package]] +name = "unicode-ident" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" + [[package]] name = "utf8parse" version = "0.2.1" diff --git a/Cargo.toml b/Cargo.toml index e00af02..b7808ff 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,3 +14,4 @@ clap = { version = "4", features = ["cargo", "help"] } assert_cmd = "2.0.12" predicates = "3.0.3" rand = "0.8.5" +rstest = "0.18.1" diff --git a/mk-outs.sh b/mk-outs.sh new file mode 100755 index 0000000..829cb1e --- /dev/null +++ b/mk-outs.sh @@ -0,0 +1,29 @@ +#!/usr/bin/env bash + +set -u + +ROOT="tests/inputs" +OUT_DIR="tests/expected" + +[[ ! -d "$OUT_DIR" ]] && mkdir -p "$OUT_DIR" + +EMPTY="$ROOT/empty.txt" +FOX="$ROOT/fox.txt" +SPIDERS="$ROOT/spiders.txt" +BUSTLE="$ROOT/the-bustle.txt" +ALL="$EMPTY $FOX $SPIDERS $BUSTLE" + +for FILE in $ALL; do + BASENAME=$(basename "$FILE") + cat $FILE > ${OUT_DIR}/${BASENAME}.out + cat -n $FILE > ${OUT_DIR}/${BASENAME}.n.out + cat -b $FILE > ${OUT_DIR}/${BASENAME}.b.out +done + +cat $ALL > $OUT_DIR/all.out +cat -n $ALL > $OUT_DIR/all.n.out +cat -b $ALL > $OUT_DIR/all.b.out + +cat < $BUSTLE > $OUT_DIR/$(basename $BUSTLE).stdin.out +cat -n < $BUSTLE > $OUT_DIR/$(basename $BUSTLE).n.stdin.out +cat -b < $BUSTLE > $OUT_DIR/$(basename $BUSTLE).b.stdin.out diff --git a/src/lib.rs b/src/lib.rs index c519012..6b34b7c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -70,11 +70,75 @@ fn open(filename: &str) -> MyResult> { } } +fn count_digits(mut number: usize) -> usize { + if number == 0 { + return 1; // Special case for the number 0 + } + + let mut count = 0; + + while number != 0 { + number /= 10; + count += 1; + } + + count +} + +fn cat( + buf_reader: Box, + line_num: &mut usize, + number_lines: bool, + number_nonblank_lines: bool, +) { + for line in buf_reader.lines() { + match line { + Ok(text) => match (number_lines, number_nonblank_lines) { + (true, false) => { + println!( + "{}{}\t{}", + " ".to_string().repeat(6 - count_digits(*line_num)), + line_num, + text + ); + *line_num += 1; + } + (false, true) => { + if text.trim().is_empty() { + println!() + } else { + println!( + "{}{}\t{}", + " ".to_string().repeat(6 - count_digits(*line_num)), + line_num, + text + ); + *line_num += 1; + } + } + _ => { + println!("{}", text); + *line_num += 1; + } + }, + + Err(err) => eprintln!("Error: {}", err), + } + } +} + pub fn run(config: Config) -> MyResult<()> { + let mut line_num: usize = 1; + for filepath in config.files { match open(&filepath) { Err(err) => eprintln!("Failed to open {}: {}", filepath, err), - Ok(_) => println!("Opened {}", filepath), + Ok(buf_reader) => cat( + buf_reader, + &mut line_num, + config.number_lines, + config.number_nonblank_lines, + ), } } diff --git a/tests/cli.rs b/tests/cli.rs index 7f1379f..9b74ea5 100644 --- a/tests/cli.rs +++ b/tests/cli.rs @@ -19,7 +19,7 @@ fn usage() -> TestResult { Command::cargo_bin(PRG)? .arg(flag) .assert() - .stdout(predicate::str::contains("USAGE")); + .stdout(predicate::str::contains("Usage")); } Ok(()) } diff --git a/tests/expected/all.b.out b/tests/expected/all.b.out index 152b15f..dd84a13 100644 --- a/tests/expected/all.b.out +++ b/tests/expected/all.b.out @@ -1,13 +1,13 @@ 1 The quick brown fox jumps over the lazy dog. - 1 Don't worry, spiders, - 2 I keep house - 3 casually. - 1 The bustle in a house - 2 The morning after death - 3 Is solemnest of industries - 4 Enacted upon earth,— + 2 Don't worry, spiders, + 3 I keep house + 4 casually. + 5 The bustle in a house + 6 The morning after death + 7 Is solemnest of industries + 8 Enacted upon earth,— - 5 The sweeping up the heart, - 6 And putting love away - 7 We shall not want to use again - 8 Until eternity. + 9 The sweeping up the heart, + 10 And putting love away + 11 We shall not want to use again + 12 Until eternity. diff --git a/tests/expected/all.n.out b/tests/expected/all.n.out index 9176de6..6ff74cf 100644 --- a/tests/expected/all.n.out +++ b/tests/expected/all.n.out @@ -1,13 +1,13 @@ 1 The quick brown fox jumps over the lazy dog. - 1 Don't worry, spiders, - 2 I keep house - 3 casually. - 1 The bustle in a house - 2 The morning after death - 3 Is solemnest of industries - 4 Enacted upon earth,— - 5 - 6 The sweeping up the heart, - 7 And putting love away - 8 We shall not want to use again - 9 Until eternity. + 2 Don't worry, spiders, + 3 I keep house + 4 casually. + 5 The bustle in a house + 6 The morning after death + 7 Is solemnest of industries + 8 Enacted upon earth,— + 9 + 10 The sweeping up the heart, + 11 And putting love away + 12 We shall not want to use again + 13 Until eternity.