Merge pull request #2 from kemitix/ignore-extra-tokens
Add support to ignore extra tokens on a line
This commit is contained in:
commit
ca0376a181
5 changed files with 160 additions and 34 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -5,3 +5,4 @@ deps.zig
|
|||
/test.in
|
||||
/test.out
|
||||
/test.expect
|
||||
/dist
|
||||
|
|
15
Makefile
Normal file
15
Makefile
Normal file
|
@ -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
|
47
README.md
47
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.
|
||||
```
|
||||
|
|
57
src/main.zig
57
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 {
|
||||
|
@ -52,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| {
|
||||
|
@ -62,17 +57,18 @@ const Config = struct {
|
|||
|
||||
fn parseArgs(allocator: mem.Allocator) !Config {
|
||||
const params = comptime [_]clap.Param(clap.Help) {
|
||||
clap.parseParam("<N> The number of lines to skip") catch unreachable,
|
||||
clap.parseParam("[<FILE>] The file to read or stdin if not given") catch unreachable,
|
||||
clap.parseParam("-l, --line <STR> Skip until N lines matching this") catch unreachable,
|
||||
clap.parseParam("-t, --token <STR> 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("<N> The number of lines to skip") catch unreachable,
|
||||
clap.parseParam("[<FILE>] The file to read or stdin if not given") catch unreachable,
|
||||
clap.parseParam("-l, --line <STR> Skip until N lines matching this") catch unreachable,
|
||||
clap.parseParam("-t, --token <STR> 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 err;
|
||||
return error.BadArgs;
|
||||
};
|
||||
defer args.deinit();
|
||||
|
||||
|
@ -103,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;
|
||||
|
@ -128,6 +133,7 @@ fn parseArgs(allocator: mem.Allocator) !Config {
|
|||
.file = file,
|
||||
.line = line,
|
||||
.token = token,
|
||||
.ignoreExtras = ignoreExtras,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -138,22 +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| {
|
||||
c += mem.count(u8, memory, token);
|
||||
}
|
||||
} else {
|
||||
c += 1;
|
||||
if (config.token) |token| {
|
||||
const occurances = mem.count(u8, memory, token);
|
||||
if (config.ignoreExtras and occurances > 0) {
|
||||
c += 1;
|
||||
} else {
|
||||
c += occurances;
|
||||
}
|
||||
} else {
|
||||
c += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (line) |memory| {
|
||||
allocator.free(memory);
|
||||
} else return;
|
||||
}
|
||||
|
@ -172,6 +179,7 @@ test "dumpInput skip 1 line" {
|
|||
const config = Config{
|
||||
.lines = 1,
|
||||
.file = file,
|
||||
.ignoreExtras = false,
|
||||
};
|
||||
|
||||
try dumpInput(config, file, output, testing.allocator);
|
||||
|
@ -202,6 +210,7 @@ test "dumpInput skip 2 line 'alpha'" {
|
|||
.lines = 2,
|
||||
.file = file,
|
||||
.line = "alpha",
|
||||
.ignoreExtras = false,
|
||||
};
|
||||
|
||||
try dumpInput(config, file, output, testing.allocator);
|
||||
|
|
74
test.sh
74
test.sh
|
@ -2,6 +2,14 @@
|
|||
|
||||
set -e
|
||||
|
||||
SKIP="./zig-out/bin/skip"
|
||||
DIFF="diff -u --color"
|
||||
|
||||
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<<EOF
|
||||
line 1
|
||||
|
@ -9,8 +17,9 @@ line 2
|
|||
EOF
|
||||
)
|
||||
echo "line 2" > 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"
|
||||
cat<<EOF > test.in
|
||||
|
@ -18,8 +27,9 @@ 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"
|
||||
cat<<EOF > test.in
|
||||
|
@ -35,8 +45,9 @@ 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"
|
||||
cat<<EOF > test.in
|
||||
|
@ -55,9 +66,54 @@ quis nostrud exercitation ullamco
|
|||
laboris nisi ut aliquip ex ea
|
||||
commodo consequat.
|
||||
EOF
|
||||
./skip 2 test.in --token dolor > test.out
|
||||
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
|
||||
|
||||
rm test.in test.out test.expect
|
||||
echo "> handle unknown parameter with simple error message"
|
||||
cat<<EOF > test.expect.err
|
||||
Invalid argument '--foo'
|
||||
EOF
|
||||
cat<<EOF > test.expect
|
||||
EOF
|
||||
touch test.out 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
|
||||
|
||||
echo "> handle ignore-extra when token is missing"
|
||||
cat<<EOF > test.expect.err
|
||||
Error: --ignore-extras requires --token
|
||||
EOF
|
||||
cat<<EOF > test.expect
|
||||
EOF
|
||||
touch test.out 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
|
||||
|
||||
echo "> skip lines until 4 tokens seen - ignored extra tokens on same line"
|
||||
cat<<EOF > 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<<EOF > test.expect
|
||||
quis nostrud exercitation ullamco
|
||||
laboris nisi ut aliquip ex ea
|
||||
commodo consequat.
|
||||
EOF
|
||||
$SKIP 4 test.in --token m --ignore-extras > test.out
|
||||
$DIFF test.expect test.out
|
||||
rm test.in test.expect test.out
|
||||
|
||||
echo done
|
||||
|
|
Loading…
Reference in a new issue