From 8b7176253231169889efa52c3417bc0ffd26ff1b Mon Sep 17 00:00:00 2001 From: Paul Campbell Date: Fri, 14 Jan 2022 07:05:09 +0000 Subject: [PATCH 01/13] Add test to handle unknown arguments gracfully --- test.sh | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/test.sh b/test.sh index 769152f..8f8b547 100755 --- a/test.sh +++ b/test.sh @@ -58,6 +58,13 @@ EOF ./skip 2 test.in --token dolor > test.out diff --brief test.expect test.out +echo "> handle unknown parameter with simple error message" +cat< test.expect +Invalid argument '--foo' +EOF +./skip --foo > test.out 2>&1 || ## error is expected +diff --brief test.expect test.out + rm test.in test.out test.expect echo done From c682546640bffbde46abd416811412d97b823725 Mon Sep 17 00:00:00 2001 From: Paul Campbell Date: Fri, 14 Jan 2022 07:05:42 +0000 Subject: [PATCH 02/13] remove out-of-date dev notes --- src/main.zig | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/main.zig b/src/main.zig index 7a9b0d5..2908980 100644 --- a/src/main.zig +++ b/src/main.zig @@ -11,12 +11,6 @@ const clap = @import("clap"); const version = "0.1.0"; -// step 1: [x] read in a file from stdin and write out to stdout -// step 2: [x] read in a named file in parameters and write out to stdout -// step 3: [x] skip a number of lines -// step 4: [ ] skip a number of matching lines -// step 5: [ ] skip a number of tokens - const maxLineLength = 4096; pub fn main() anyerror!void { From b19b1751b5fba348bc9ab7a7efa0dad57acbb903 Mon Sep 17 00:00:00 2001 From: Paul Campbell Date: Fri, 14 Jan 2022 07:06:08 +0000 Subject: [PATCH 03/13] Add test for option --ignore-extras --- test.sh | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/test.sh b/test.sh index 8f8b547..4e647d5 100755 --- a/test.sh +++ b/test.sh @@ -65,6 +65,25 @@ EOF ./skip --foo > test.out 2>&1 || ## error is expected diff --brief test.expect test.out +echo "> skip lines until 3 tokens seen - ignored extra tokens on same line" +cat< test.in +Lorem ipsum dolor sit amet, +consectetur adipiscing elit, +sed do eiusmod tempor incididunt +ut labore et dolore magna aliqua. +Ut enim ad minim veniam, +quis nostrud exercitation ullamco +laboris nisi ut aliquip ex ea +commodo consequat. +EOF +cat< test.expect +quis nostrud exercitation ullamco +laboris nisi ut aliquip ex ea +commodo consequat. +EOF +./skip 3 test.in --token m --ignore-extras > test.out +diff --brief test.expect test.out + rm test.in test.out test.expect echo done From 683d71ff8b79d3821002df9850ab40cb5ca686f7 Mon Sep 17 00:00:00 2001 From: Paul Campbell Date: Fri, 14 Jan 2022 07:38:50 +0000 Subject: [PATCH 04/13] Don't show error trace when bar args --- src/main.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.zig b/src/main.zig index 2908980..9a1a7a0 100644 --- a/src/main.zig +++ b/src/main.zig @@ -66,7 +66,7 @@ fn parseArgs(allocator: mem.Allocator) !Config { var diag = clap.Diagnostic{}; var args = clap.parse(clap.Help, ¶ms, .{ .diagnostic = &diag }) catch |err| { diag.report(io.getStdErr().writer(), err) catch {}; - return err; + return error.EarlyExit; }; defer args.deinit(); From 6119e528886cb97b78f210d99420d680445740d2 Mon Sep 17 00:00:00 2001 From: Paul Campbell Date: Fri, 14 Jan 2022 07:39:42 +0000 Subject: [PATCH 05/13] Clean up after each test and test stderr --- test.sh | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/test.sh b/test.sh index 4e647d5..06408d2 100755 --- a/test.sh +++ b/test.sh @@ -11,6 +11,7 @@ EOF echo "line 2" > test.expect echo "$INPUT" | ./skip 1 > test.out diff --brief test.expect test.out +rm test.expect test.out echo "> skip a line when reading from a file" cat< test.in @@ -20,6 +21,7 @@ EOF echo "line 2" > test.expect ./skip 1 test.in > test.out diff --brief test.expect test.out +rm test.expect test.out echo "> skip until 2 matching lines seen" cat< test.in @@ -37,6 +39,7 @@ alpha EOF ./skip 2 test.in --line alpha > test.out diff --brief test.expect test.out +rm test.in test.expect test.out echo "> skip lines until 2 tokens seen" cat< test.in @@ -55,15 +58,22 @@ quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. EOF -./skip 2 test.in --token dolor > test.out +./skip 2 test.in --token dolor > test.out 2 diff --brief test.expect test.out +rm test.in test.expect test.out echo "> handle unknown parameter with simple error message" -cat< test.expect +cat< test.expect.err Invalid argument '--foo' EOF -./skip --foo > test.out 2>&1 || ## error is expected +cat< test.expect +EOF +touch test.out test.err +./skip --foo > test.out 2> test.err diff --brief test.expect test.out +diff --brief test.expect.err test.err +rm test.expect test.out +rm test.expect.err test.err echo "> skip lines until 3 tokens seen - ignored extra tokens on same line" cat< test.in @@ -83,7 +93,6 @@ commodo consequat. EOF ./skip 3 test.in --token m --ignore-extras > test.out diff --brief test.expect test.out - -rm test.in test.out test.expect +rm test.in test.expect test.out echo done From 96832abac60531acc24aa47c310a9cb21a12eece Mon Sep 17 00:00:00 2001 From: Paul Campbell Date: Fri, 14 Jan 2022 07:48:47 +0000 Subject: [PATCH 06/13] Accept --ignore-extras argument --- src/main.zig | 26 +++++++++++++++++++------- test.sh | 13 +++++++++++++ 2 files changed, 32 insertions(+), 7 deletions(-) diff --git a/src/main.zig b/src/main.zig index 9a1a7a0..f5241d0 100644 --- a/src/main.zig +++ b/src/main.zig @@ -46,6 +46,7 @@ const Config = struct { file: ?fs.File, line: ?[]const u8 = null, token: ?[]const u8 = null, + ignoreExtras: bool, pub fn deinit(self: @This()) void { if (self.file) |f| { @@ -56,17 +57,18 @@ const Config = struct { fn parseArgs(allocator: mem.Allocator) !Config { const params = comptime [_]clap.Param(clap.Help) { - clap.parseParam(" The number of lines to skip") catch unreachable, - clap.parseParam("[] The file to read or stdin if not given") catch unreachable, - clap.parseParam("-l, --line Skip until N lines matching this") catch unreachable, - clap.parseParam("-t, --token Skip lines until N tokens found") catch unreachable, - clap.parseParam("-h, --help Display this help and exit") catch unreachable, - clap.parseParam("-v, --version Display the version") catch unreachable, + clap.parseParam(" The number of lines to skip") catch unreachable, + clap.parseParam("[] The file to read or stdin if not given") catch unreachable, + clap.parseParam("-l, --line Skip until N lines matching this") catch unreachable, + clap.parseParam("-t, --token Skip lines until N tokens found") catch unreachable, + clap.parseParam("-i, --ignore-extras Only count the first token on each line") catch unreachable, + clap.parseParam("-h, --help Display this help and exit") catch unreachable, + clap.parseParam("-v, --version Display the version") catch unreachable, }; var diag = clap.Diagnostic{}; var args = clap.parse(clap.Help, ¶ms, .{ .diagnostic = &diag }) catch |err| { diag.report(io.getStdErr().writer(), err) catch {}; - return error.EarlyExit; + return error.BadArgs; }; defer args.deinit(); @@ -97,6 +99,15 @@ fn parseArgs(allocator: mem.Allocator) !Config { if (args.option("--token")) |match| { token = try allocator.dupe(u8, match); } + var ignoreExtras: bool = false; + if (args.flag("--ignore-extras")) { + if (token) |_| { + ignoreExtras = true; + } else { + try io.getStdErr().writer().print("Error: --ignore-extras requires --token\n", .{}); + return error.BadArgs; + } + } var n: u32 = 0; var file: ?fs.File = null; @@ -122,6 +133,7 @@ fn parseArgs(allocator: mem.Allocator) !Config { .file = file, .line = line, .token = token, + .ignoreExtras = ignoreExtras, }; } diff --git a/test.sh b/test.sh index 06408d2..ce149ea 100755 --- a/test.sh +++ b/test.sh @@ -75,6 +75,19 @@ diff --brief test.expect.err test.err rm test.expect test.out rm test.expect.err test.err +echo "> handle ignore-extra when token is missing" +cat< test.expect.err +Error: --ignore-extras requires --token +EOF +cat< test.expect +EOF +touch test.out test.err +./skip --ignore-extras > test.out 2> test.err +diff --brief test.expect test.out +diff --brief test.expect.err test.err +rm test.expect test.out +rm test.expect.err test.err + echo "> skip lines until 3 tokens seen - ignored extra tokens on same line" cat< test.in Lorem ipsum dolor sit amet, From a90d17bb971b1c11ad7bab22758aa9ecae10bc1a Mon Sep 17 00:00:00 2001 From: Paul Campbell Date: Fri, 14 Jan 2022 08:01:59 +0000 Subject: [PATCH 07/13] ignore extra tokens on line - broken --- src/main.zig | 6 +++++- test.sh | 4 ++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/main.zig b/src/main.zig index f5241d0..78213b3 100644 --- a/src/main.zig +++ b/src/main.zig @@ -153,7 +153,11 @@ fn dumpInput(config: Config, in: fs.File, out: fs.File, allocator: mem.Allocator } else { if (config.token) |token| { if (line) |memory| { - c += mem.count(u8, memory, token); + if (config.ignoreExtras) { + c += 1; + } else { + c += mem.count(u8, memory, token); + } } } else { c += 1; diff --git a/test.sh b/test.sh index ce149ea..1036877 100755 --- a/test.sh +++ b/test.sh @@ -88,7 +88,7 @@ diff --brief test.expect.err test.err rm test.expect test.out rm test.expect.err test.err -echo "> skip lines until 3 tokens seen - ignored extra tokens on same line" +echo "> skip lines until 4 tokens seen - ignored extra tokens on same line" cat< test.in Lorem ipsum dolor sit amet, consectetur adipiscing elit, @@ -104,7 +104,7 @@ quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. EOF -./skip 3 test.in --token m --ignore-extras > test.out +./skip 4 test.in --token m --ignore-extras > test.out diff --brief test.expect test.out rm test.in test.expect test.out From 2f3bf35b02a746bf85f949648efdd9ce743c15e3 Mon Sep 17 00:00:00 2001 From: Paul Campbell Date: Sat, 15 Jan 2022 14:29:27 +0000 Subject: [PATCH 08/13] test: work with skip in zig-out and show diff on error --- test.sh | 40 ++++++++++++++++++++++++---------------- 1 file changed, 24 insertions(+), 16 deletions(-) diff --git a/test.sh b/test.sh index 1036877..0cb497e 100755 --- a/test.sh +++ b/test.sh @@ -2,6 +2,14 @@ set -e +SKIP="./zig-out/bin/skip" +DIFF="diff -u" + +if test ! -x $SKIP ; then + echo "File missing: $SKIP - try 'zig build'" + exit 1 +fi + echo "> skip a line when reading from stdin" INPUT=$(cat< test.expect -echo "$INPUT" | ./skip 1 > test.out -diff --brief test.expect test.out +echo "$INPUT" | $SKIP 1 > test.out +$DIFF test.expect test.out rm test.expect test.out echo "> skip a line when reading from a file" @@ -19,8 +27,8 @@ line 1 line 2 EOF echo "line 2" > test.expect -./skip 1 test.in > test.out -diff --brief test.expect test.out +$SKIP 1 test.in > test.out +$DIFF test.expect test.out rm test.expect test.out echo "> skip until 2 matching lines seen" @@ -37,8 +45,8 @@ alpha gamma alpha EOF -./skip 2 test.in --line alpha > test.out -diff --brief test.expect test.out +$SKIP 2 test.in --line alpha > test.out +$DIFF test.expect test.out rm test.in test.expect test.out echo "> skip lines until 2 tokens seen" @@ -58,8 +66,8 @@ quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. EOF -./skip 2 test.in --token dolor > test.out 2 -diff --brief test.expect test.out +$SKIP 2 test.in --token dolor > test.out 2 +$DIFF test.expect test.out rm test.in test.expect test.out echo "> handle unknown parameter with simple error message" @@ -69,9 +77,9 @@ EOF cat< test.expect EOF touch test.out test.err -./skip --foo > test.out 2> test.err -diff --brief test.expect test.out -diff --brief test.expect.err test.err +$SKIP --foo > test.out 2> test.err +$DIFF test.expect test.out +$DIFF test.expect.err test.err rm test.expect test.out rm test.expect.err test.err @@ -82,9 +90,9 @@ EOF cat< test.expect EOF touch test.out test.err -./skip --ignore-extras > test.out 2> test.err -diff --brief test.expect test.out -diff --brief test.expect.err test.err +$SKIP --ignore-extras > test.out 2> test.err +$DIFF test.expect test.out +$DIFF test.expect.err test.err rm test.expect test.out rm test.expect.err test.err @@ -104,8 +112,8 @@ quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. EOF -./skip 4 test.in --token m --ignore-extras > test.out -diff --brief test.expect test.out +$SKIP 4 test.in --token m --ignore-extras > test.out +$DIFF test.expect test.out rm test.in test.expect test.out echo done From b0a28f9f16487fb44495964e61f9431a3f78d0fa Mon Sep 17 00:00:00 2001 From: Paul Campbell Date: Sat, 15 Jan 2022 14:29:51 +0000 Subject: [PATCH 09/13] Add Makefile --- Makefile | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 Makefile diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..c05bd82 --- /dev/null +++ b/Makefile @@ -0,0 +1,15 @@ +dist: inttest + mkdir dist + cp zig-out/bin/skip dist/ + +inttest: zig-out/bin/skip + ./test.sh + +zig-out/bin/skip: unittest + zig build + +unittest: zigmod src/main.zig + zig build test + +zigmod: zig.mod + zigmod ci From 427f2773bfecd3d6f4f3a30411ea50f3b87946b9 Mon Sep 17 00:00:00 2001 From: Paul Campbell Date: Sat, 15 Jan 2022 14:38:26 +0000 Subject: [PATCH 10/13] colourise diff output --- test.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test.sh b/test.sh index 0cb497e..09148e1 100755 --- a/test.sh +++ b/test.sh @@ -3,7 +3,7 @@ set -e SKIP="./zig-out/bin/skip" -DIFF="diff -u" +DIFF="diff -u --color" if test ! -x $SKIP ; then echo "File missing: $SKIP - try 'zig build'" From f8f6dd49171b30dcfb608bf2f7c9fee314ec18fb Mon Sep 17 00:00:00 2001 From: Paul Campbell Date: Sat, 15 Jan 2022 14:38:56 +0000 Subject: [PATCH 11/13] ignore dist dir --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 76d6532..560b4b0 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ deps.zig /test.in /test.out /test.expect +/dist From c3188ae353071bde257a7d0bc8bfa41ac5fccc4a Mon Sep 17 00:00:00 2001 From: Paul Campbell Date: Sat, 15 Jan 2022 14:39:08 +0000 Subject: [PATCH 12/13] Ignore extras by only counting line with a token --- src/main.zig | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/src/main.zig b/src/main.zig index 78213b3..04c9a63 100644 --- a/src/main.zig +++ b/src/main.zig @@ -144,26 +144,23 @@ fn dumpInput(config: Config, in: fs.File, out: fs.File, allocator: mem.Allocator var c: usize = 0; while (c < config.lines) { const line = it.next(); - if (config.line) |match| { - if (line) |memory| { + if (line) |memory| { + if (config.line) |match| { if (mem.eql(u8, match, memory)) { c += 1; } - } - } else { - if (config.token) |token| { - if (line) |memory| { - if (config.ignoreExtras) { + } else { + if (config.token) |token| { + const occurances = mem.count(u8, memory, token); + if (config.ignoreExtras and occurances > 0) { c += 1; } else { - c += mem.count(u8, memory, token); + c += occurances; } + } else { + c += 1; } - } else { - c += 1; } - } - if (line) |memory| { allocator.free(memory); } else return; } @@ -182,6 +179,7 @@ test "dumpInput skip 1 line" { const config = Config{ .lines = 1, .file = file, + .ignoreExtras = false, }; try dumpInput(config, file, output, testing.allocator); @@ -212,6 +210,7 @@ test "dumpInput skip 2 line 'alpha'" { .lines = 2, .file = file, .line = "alpha", + .ignoreExtras = false, }; try dumpInput(config, file, output, testing.allocator); From 9d97a50e6e48565ff23cf32e5d9e1d800a907ac1 Mon Sep 17 00:00:00 2001 From: Paul Campbell Date: Sat, 15 Jan 2022 14:44:21 +0000 Subject: [PATCH 13/13] README: add notes in --ignore-extras --- README.md | 47 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index aee0153..88eda5e 100644 --- a/README.md +++ b/README.md @@ -42,6 +42,8 @@ line 4 ### Skip until a number of matching lines +The whole line must match. + This example reads the named file. File: `input.txt` @@ -67,7 +69,9 @@ gamma alpha ``` -### Skip lines until a number of tokens as seen +### Skip lines until a number of tokens are seen + +Looks for a string within a line, counting each occurance. This example reads the file from stdin. @@ -99,3 +103,44 @@ commodo consequat. It matches the first `dolor` on line 1, and the second on line 4 as part of the word `dolore`. + +### Skip lines until a lines with tokens are seen + +Looks for a string within a line, only counting each matching line once. + +This example reads the file from stdin. + +File: `input.txt` + +```text +Lorem ipsum dolor sit amet, +consectetur adipiscing elit, +sed do eiusmod tempor incididunt +ut labore et dolore magna aliqua. +Ut enim ad minim veniam, +quis nostrud exercitation ullamco +laboris nisi ut aliquip ex ea +commodo consequat. +``` + +```bash +cat input.txt | skip 4 --token m --ignore-extras +``` + +Will output: + +```text +quis nostrud exercitation ullamco +laboris nisi ut aliquip ex ea +commodo consequat. +``` + +Without `--ignore-extras`, it would have found the fourth `m` on line 3, and displayed: + +```text +ut labore et dolore magna aliqua. +Ut enim ad minim veniam, +quis nostrud exercitation ullamco +laboris nisi ut aliquip ex ea +commodo consequat. +```