nimgrep: add --inContext and --notinContext options (#19528)
* nimgrep: add `--matchContext` and `--noMatchContext` options * Rename options for uniformity * Revise option names, add `--parentPath` options * Revert --bin deprecation * Copy-paste an original test from quantimnot The origin was: https://gist.githubusercontent.com/quantimnot/5d23b32fe0936ffc453220d20a87b9e2/raw/96544656d52332118295e55aa73718c389e5d194/tnimgrep.nim * Change ! to n * Attempt to fix test * Fix test on Windows * Change --contentsFile -> --inFile, add more tests * Bump * Change --parentPath to --dirpath
This commit is contained in:
parent
08faa04d78
commit
2140d05f34
4 changed files with 683 additions and 104 deletions
402
tests/tools/tnimgrep.nim
Normal file
402
tests/tools/tnimgrep.nim
Normal file
|
|
@ -0,0 +1,402 @@
|
|||
discard """
|
||||
output: '''
|
||||
|
||||
[Suite] nimgrep filesystem
|
||||
|
||||
[Suite] nimgrep contents filtering
|
||||
'''
|
||||
"""
|
||||
## Authors: quantimnot, a-mr
|
||||
|
||||
import osproc, os, streams, unittest, strutils
|
||||
|
||||
#=======
|
||||
# setup
|
||||
#=======
|
||||
|
||||
var process: Process
|
||||
var ngStdOut, ngStdErr: string
|
||||
var ngExitCode: int
|
||||
let previousDir = getCurrentDir()
|
||||
let tempDir = getTempDir()
|
||||
let testFilesRoot = tempDir / "nimgrep_test_files"
|
||||
|
||||
template nimgrep(optsAndArgs): untyped =
|
||||
process = startProcess(previousDir / "bin/nimgrep " & optsAndArgs,
|
||||
options = {poEvalCommand})
|
||||
ngExitCode = process.waitForExit
|
||||
ngStdOut = process.outputStream.readAll
|
||||
ngStdErr = process.errorStream.readAll
|
||||
|
||||
func fixSlash(s: string): string =
|
||||
if DirSep == '/':
|
||||
result = s
|
||||
else: # on Windows
|
||||
result = s.replace('/', DirSep)
|
||||
|
||||
func initString(len = 1000, val = ' '): string =
|
||||
result = newString(len)
|
||||
for i in 0..<len:
|
||||
result[i] = val
|
||||
|
||||
# Create test file hierarchy.
|
||||
createDir testFilesRoot
|
||||
setCurrentDir testFilesRoot
|
||||
createDir "a" / "b"
|
||||
createDir "c" / "b"
|
||||
createDir ".hidden"
|
||||
writeFile("do_not_create_another_file_with_this_pattern_KJKJHSFSFKASHFBKAF", "PATTERN")
|
||||
writeFile("a" / "b" / "only_the_pattern", "PATTERN")
|
||||
writeFile("c" / "b" / "only_the_pattern", "PATTERN")
|
||||
writeFile(".hidden" / "only_the_pattern", "PATTERN")
|
||||
writeFile("null_in_first_1k", "\0PATTERN")
|
||||
writeFile("null_after_first_1k", initString(1000) & "\0")
|
||||
writeFile("empty", "")
|
||||
writeFile("context_match_filtering", """
|
||||
-
|
||||
CONTEXTPAT
|
||||
-
|
||||
PATTERN
|
||||
-
|
||||
-
|
||||
-
|
||||
|
||||
-
|
||||
-
|
||||
-
|
||||
PATTERN
|
||||
-
|
||||
-
|
||||
-
|
||||
""")
|
||||
writeFile("only_the_pattern.txt", "PATTERN")
|
||||
writeFile("only_the_pattern.ascii", "PATTERN")
|
||||
|
||||
|
||||
#=======
|
||||
# tests
|
||||
#=======
|
||||
|
||||
suite "nimgrep filesystem":
|
||||
|
||||
test "`--filename` with matching file":
|
||||
nimgrep "-r --filename:KJKJHSFSFKASHFBKAF PATTERN"
|
||||
check ngExitCode == 0
|
||||
check ngStdErr.len == 0
|
||||
check ngStdOut == fixSlash dedent"""
|
||||
./do_not_create_another_file_with_this_pattern_KJKJHSFSFKASHFBKAF:1: PATTERN
|
||||
1 matches
|
||||
"""
|
||||
|
||||
|
||||
test "`--dirname` with matching dir":
|
||||
nimgrep "-r --dirname:.hid PATTERN"
|
||||
check ngExitCode == 0
|
||||
check ngStdErr.len == 0
|
||||
check ngStdOut == fixSlash dedent"""
|
||||
.hidden/only_the_pattern:1: PATTERN
|
||||
1 matches
|
||||
"""
|
||||
|
||||
let only_the_pattern = fixSlash dedent"""
|
||||
a/b/only_the_pattern:1: PATTERN
|
||||
c/b/only_the_pattern:1: PATTERN
|
||||
2 matches
|
||||
"""
|
||||
|
||||
let only_a = fixSlash dedent"""
|
||||
a/b/only_the_pattern:1: PATTERN
|
||||
1 matches
|
||||
"""
|
||||
|
||||
test "`--dirname` with matching grandparent path segment":
|
||||
nimgrep "-r --dirname:a PATTERN"
|
||||
check ngExitCode == 0
|
||||
check ngStdErr.len == 0
|
||||
check ngStdOut == only_a
|
||||
|
||||
test "`--dirpath` with matching grandparent path segment":
|
||||
nimgrep "-r --dirp:a PATTERN"
|
||||
check ngExitCode == 0
|
||||
check ngStdErr.len == 0
|
||||
check ngStdOut == only_a
|
||||
|
||||
test "`--dirpath` with matching grandparent path segment":
|
||||
nimgrep "-r --dirpath:a/b PATTERN".fixSlash
|
||||
check ngExitCode == 0
|
||||
check ngStdErr.len == 0
|
||||
check ngStdOut == only_a
|
||||
|
||||
|
||||
test "`--dirname` with matching parent path segment":
|
||||
nimgrep "-r --dirname:b PATTERN"
|
||||
check ngExitCode == 0
|
||||
check ngStdErr.len == 0
|
||||
check ngStdOut == only_the_pattern
|
||||
|
||||
test "`--dirpath` with matching parent path segment":
|
||||
nimgrep "-r --dirpath:b PATTERN"
|
||||
check ngExitCode == 0
|
||||
check ngStdErr.len == 0
|
||||
check ngStdOut == only_the_pattern
|
||||
|
||||
|
||||
let patterns_without_directory_a_b = fixSlash dedent"""
|
||||
./context_match_filtering:4: PATTERN
|
||||
./context_match_filtering:12: PATTERN
|
||||
./do_not_create_another_file_with_this_pattern_KJKJHSFSFKASHFBKAF:1: PATTERN
|
||||
./null_in_first_1k:1: """ & "\0PATTERN\n" & dedent"""
|
||||
./only_the_pattern.ascii:1: PATTERN
|
||||
./only_the_pattern.txt:1: PATTERN
|
||||
.hidden/only_the_pattern:1: PATTERN
|
||||
c/b/only_the_pattern:1: PATTERN
|
||||
8 matches
|
||||
"""
|
||||
|
||||
let patterns_without_directory_b = fixSlash dedent"""
|
||||
./context_match_filtering:4: PATTERN
|
||||
./context_match_filtering:12: PATTERN
|
||||
./do_not_create_another_file_with_this_pattern_KJKJHSFSFKASHFBKAF:1: PATTERN
|
||||
./null_in_first_1k:1: """ & "\0PATTERN\n" & dedent"""
|
||||
./only_the_pattern.ascii:1: PATTERN
|
||||
./only_the_pattern.txt:1: PATTERN
|
||||
.hidden/only_the_pattern:1: PATTERN
|
||||
7 matches
|
||||
"""
|
||||
|
||||
test "`--ndirname` not matching grandparent path segment":
|
||||
nimgrep "-r --ndirname:a PATTERN"
|
||||
check ngExitCode == 0
|
||||
check ngStdErr.len == 0
|
||||
check ngStdOut == patterns_without_directory_a_b
|
||||
|
||||
test "`--ndirname` not matching parent path segment":
|
||||
nimgrep "-r --ndirname:b PATTERN"
|
||||
check ngExitCode == 0
|
||||
check ngStdErr.len == 0
|
||||
check ngStdOut == patterns_without_directory_b
|
||||
|
||||
test "`--notdirpath` not matching grandparent path segment":
|
||||
nimgrep "-r --notdirpath:a PATTERN"
|
||||
check ngExitCode == 0
|
||||
check ngStdErr.len == 0
|
||||
check ngStdOut == patterns_without_directory_a_b
|
||||
|
||||
test "`--notdirpath` not matching parent path segment":
|
||||
nimgrep "-r --ndirp:b PATTERN"
|
||||
check ngExitCode == 0
|
||||
check ngStdErr.len == 0
|
||||
check ngStdOut == patterns_without_directory_b
|
||||
|
||||
test "`--notdirpath` with matching grandparent/parent path segment":
|
||||
nimgrep "-r --ndirp:a/b PATTERN".fixSlash
|
||||
check ngExitCode == 0
|
||||
check ngStdErr.len == 0
|
||||
check ngStdOut == patterns_without_directory_a_b
|
||||
|
||||
|
||||
test "`--text`, `-t`, `--bin:off` with file containing a null in first 1k chars":
|
||||
nimgrep "-r --text PATTERN null_in_first_1k"
|
||||
check ngExitCode == 0
|
||||
check ngStdErr.len == 0
|
||||
check ngStdOut == "0 matches\n"
|
||||
checkpoint "`--text`"
|
||||
nimgrep "-r -t PATTERN null_in_first_1k"
|
||||
check ngExitCode == 0
|
||||
check ngStdErr.len == 0
|
||||
check ngStdOut == "0 matches\n"
|
||||
checkpoint "`-t`"
|
||||
nimgrep "-r --bin:off PATTERN null_in_first_1k"
|
||||
check ngExitCode == 0
|
||||
check ngStdErr.len == 0
|
||||
check ngStdOut == "0 matches\n"
|
||||
checkpoint "`--binary:off`"
|
||||
|
||||
|
||||
test "`--bin:only` with file containing a null in first 1k chars":
|
||||
nimgrep "--bin:only -@ PATTERN null_in_first_1k null_after_first_1k only_the_pattern.txt"
|
||||
check ngExitCode == 0
|
||||
check ngStdErr.len == 0
|
||||
check ngStdOut == dedent"""
|
||||
null_in_first_1k:1: ^@PATTERN
|
||||
1 matches
|
||||
"""
|
||||
|
||||
|
||||
test "`--bin:only` with file containing a null after first 1k chars":
|
||||
nimgrep "--bin:only PATTERN null_after_first_1k only_the_pattern.txt"
|
||||
check ngExitCode == 0
|
||||
check ngStdErr.len == 0
|
||||
check ngStdOut == "0 matches\n"
|
||||
|
||||
|
||||
# TODO: we need to throw a warning if e.g. both extension was provided and
|
||||
# inappropriate filename was directly provided via command line
|
||||
#
|
||||
# test "`--ext:doesnotexist` without a matching file":
|
||||
# # skip() # FIXME: this test fails
|
||||
# nimgrep "--ext:doesnotexist PATTERN context_match_filtering only_the_pattern.txt"
|
||||
# check ngExitCode == 0
|
||||
# check ngStdErr.len == 0
|
||||
# check ngStdOut == """
|
||||
#0 matches
|
||||
#"""
|
||||
#
|
||||
#
|
||||
# test "`--ext:txt` with a matching file":
|
||||
# nimgrep "--ext:txt PATTERN context_match_filtering only_the_pattern.txt"
|
||||
# check ngExitCode == 0
|
||||
# check ngStdErr.len == 0
|
||||
# check ngStdOut == """
|
||||
#only_the_pattern.txt:1: PATTERN
|
||||
#1 matches
|
||||
#"""
|
||||
#
|
||||
#
|
||||
# test "`--ext:txt|doesnotexist` with some matching files":
|
||||
# nimgrep "--ext:txt|doesnotexist PATTERN context_match_filtering only_the_pattern.txt only_the_pattern.ascii"
|
||||
# check ngExitCode == 0
|
||||
# check ngStdErr.len == 0
|
||||
# check ngStdOut == """
|
||||
#only_the_pattern.txt:1: PATTERN
|
||||
#1 matches
|
||||
#"""
|
||||
#
|
||||
#
|
||||
# test "`--ext` with some matching files":
|
||||
# nimgrep "--ext PATTERN context_match_filtering only_the_pattern.txt only_the_pattern.ascii"
|
||||
# check ngExitCode == 0
|
||||
# check ngStdErr.len == 0
|
||||
# check ngStdOut == """
|
||||
#context_match_filtering:4: PATTERN
|
||||
#context_match_filtering:12: PATTERN
|
||||
#2 matches
|
||||
#"""
|
||||
#
|
||||
#
|
||||
# test "`--ext:txt --ext` with some matching files":
|
||||
# nimgrep "--ext:txt --ext PATTERN context_match_filtering only_the_pattern.txt only_the_pattern.ascii"
|
||||
# check ngExitCode == 0
|
||||
# check ngStdErr.len == 0
|
||||
# check ngStdOut == """
|
||||
#context_match_filtering:4: PATTERN
|
||||
#context_match_filtering:12: PATTERN
|
||||
#only_the_pattern.txt:1: PATTERN
|
||||
#3 matches
|
||||
#"""
|
||||
|
||||
|
||||
suite "nimgrep contents filtering":
|
||||
|
||||
test "`--inFile` with matching file":
|
||||
nimgrep "-r --inf:CONTEXTPAT PATTERN"
|
||||
check ngExitCode == 0
|
||||
check ngStdErr.len == 0
|
||||
check ngStdOut == fixSlash dedent"""
|
||||
./context_match_filtering:4: PATTERN
|
||||
./context_match_filtering:12: PATTERN
|
||||
2 matches
|
||||
"""
|
||||
|
||||
|
||||
test "`--notinFile` with matching files":
|
||||
nimgrep "-r --ninf:CONTEXTPAT PATTERN"
|
||||
check ngExitCode == 0
|
||||
check ngStdErr.len == 0
|
||||
check ngStdOut == fixSlash dedent"""
|
||||
./do_not_create_another_file_with_this_pattern_KJKJHSFSFKASHFBKAF:1: PATTERN
|
||||
./null_in_first_1k:1: """ & "\0PATTERN\n" & dedent"""
|
||||
./only_the_pattern.ascii:1: PATTERN
|
||||
./only_the_pattern.txt:1: PATTERN
|
||||
.hidden/only_the_pattern:1: PATTERN
|
||||
a/b/only_the_pattern:1: PATTERN
|
||||
c/b/only_the_pattern:1: PATTERN
|
||||
7 matches
|
||||
"""
|
||||
|
||||
|
||||
test "`--inContext` with missing context option":
|
||||
# Using `--inContext` implies default -c:1 is used
|
||||
nimgrep "-r --inContext:CONTEXTPAT PATTERN"
|
||||
check ngExitCode == 0
|
||||
check ngStdErr.len == 0
|
||||
check ngStdOut == "0 matches\n"
|
||||
|
||||
|
||||
test "`--inContext` with PAT matching PATTERN":
|
||||
# This tests the scenario where PAT always matches PATTERN and thus
|
||||
# has the same effect as excluding the `inContext` option.
|
||||
# I'm not sure of the desired behaviour here.
|
||||
nimgrep "--context:2 --inc:PAT PATTERN context_match_filtering"
|
||||
check ngExitCode == 0
|
||||
check ngStdErr.len == 0
|
||||
check ngStdOut == dedent"""
|
||||
context_match_filtering:2 CONTEXTPAT
|
||||
context_match_filtering:3 -
|
||||
context_match_filtering:4: PATTERN
|
||||
context_match_filtering:5 -
|
||||
context_match_filtering:6 -
|
||||
|
||||
context_match_filtering:10 -
|
||||
context_match_filtering:11 -
|
||||
context_match_filtering:12: PATTERN
|
||||
context_match_filtering:13 -
|
||||
context_match_filtering:14 -
|
||||
|
||||
2 matches
|
||||
"""
|
||||
|
||||
|
||||
test "`--inContext` with PAT in context":
|
||||
nimgrep "--context:2 --inContext:CONTEXTPAT PATTERN context_match_filtering"
|
||||
check ngExitCode == 0
|
||||
check ngStdErr.len == 0
|
||||
check ngStdOut == dedent"""
|
||||
context_match_filtering:2 CONTEXTPAT
|
||||
context_match_filtering:3 -
|
||||
context_match_filtering:4: PATTERN
|
||||
context_match_filtering:5 -
|
||||
context_match_filtering:6 -
|
||||
|
||||
1 matches
|
||||
"""
|
||||
|
||||
|
||||
test "`--notinContext` with PAT matching some contexts":
|
||||
nimgrep "--context:2 --ninContext:CONTEXTPAT PATTERN context_match_filtering"
|
||||
check ngExitCode == 0
|
||||
check ngStdErr.len == 0
|
||||
check ngStdOut == dedent"""
|
||||
context_match_filtering:10 -
|
||||
context_match_filtering:11 -
|
||||
context_match_filtering:12: PATTERN
|
||||
context_match_filtering:13 -
|
||||
context_match_filtering:14 -
|
||||
|
||||
1 matches
|
||||
"""
|
||||
|
||||
|
||||
test "`--notinContext` with PAT not matching any of the contexts":
|
||||
nimgrep "--context:1 --ninc:CONTEXTPAT PATTERN context_match_filtering"
|
||||
check ngExitCode == 0
|
||||
check ngStdErr.len == 0
|
||||
check ngStdOut == dedent"""
|
||||
context_match_filtering:3 -
|
||||
context_match_filtering:4: PATTERN
|
||||
context_match_filtering:5 -
|
||||
|
||||
context_match_filtering:11 -
|
||||
context_match_filtering:12: PATTERN
|
||||
context_match_filtering:13 -
|
||||
|
||||
2 matches
|
||||
"""
|
||||
|
||||
|
||||
#=========
|
||||
# cleanup
|
||||
#=========
|
||||
|
||||
setCurrentDir previousDir
|
||||
removeDir testFilesRoot
|
||||
Loading…
Add table
Add a link
Reference in a new issue