pseek 3.6.2__tar.gz → 3.7.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {pseek-3.6.2 → pseek-3.7.0}/PKG-INFO +53 -19
- {pseek-3.6.2 → pseek-3.7.0}/README.md +52 -18
- {pseek-3.6.2 → pseek-3.7.0}/pseek/cli.py +4 -2
- {pseek-3.6.2 → pseek-3.7.0}/pseek/parser.py +45 -32
- {pseek-3.6.2 → pseek-3.7.0}/pseek/structs.py +1 -0
- {pseek-3.6.2 → pseek-3.7.0}/pyproject.toml +1 -1
- {pseek-3.6.2 → pseek-3.7.0}/.gitattributes +0 -0
- {pseek-3.6.2 → pseek-3.7.0}/.github/workflows/publish.yml +0 -0
- {pseek-3.6.2 → pseek-3.7.0}/.gitignore +0 -0
- {pseek-3.6.2 → pseek-3.7.0}/Cargo.lock +0 -0
- {pseek-3.6.2 → pseek-3.7.0}/Cargo.toml +0 -0
- {pseek-3.6.2 → pseek-3.7.0}/LICENSE +0 -0
- {pseek-3.6.2 → pseek-3.7.0}/pseek/__init__.py +0 -0
- {pseek-3.6.2 → pseek-3.7.0}/pseek/archive.py +0 -0
- {pseek-3.6.2 → pseek-3.7.0}/pseek/compound_extensions +0 -0
- {pseek-3.6.2 → pseek-3.7.0}/pseek/searcher.py +0 -0
- {pseek-3.6.2 → pseek-3.7.0}/pseek/utils.py +0 -0
- {pseek-3.6.2 → pseek-3.7.0}/scripts/check_version.py +0 -0
- {pseek-3.6.2 → pseek-3.7.0}/src/lib.rs +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pseek
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.7.0
|
|
4
4
|
Classifier: Development Status :: 5 - Production/Stable
|
|
5
5
|
Classifier: Environment :: Console
|
|
6
6
|
Classifier: Intended Audience :: Developers
|
|
@@ -51,6 +51,7 @@ Fast and powerful command-line search tool for finding files, directories, and t
|
|
|
51
51
|
* [Fuzzy](#fuzzy-search)
|
|
52
52
|
* [Fuzzy Similarity Threshold](#fuzzy-similarity-threshold)
|
|
53
53
|
* [Full Path](#full-path)
|
|
54
|
+
* [Line](#line)
|
|
54
55
|
* [Expression Queries](#expression-queries)
|
|
55
56
|
* [Operators](#supported-operators)
|
|
56
57
|
* [AND](#and)
|
|
@@ -63,6 +64,7 @@ Fast and powerful command-line search tool for finding files, directories, and t
|
|
|
63
64
|
* [Whole Word](#whole-word)
|
|
64
65
|
* [Fuzzy](#fuzzy)
|
|
65
66
|
* [Full Path](#full-path-1)
|
|
67
|
+
* [Line](#line-1)
|
|
66
68
|
* [Combined Prefixes](#combined-prefixes)
|
|
67
69
|
* [Automatic Filtering](#automatic-filtering)
|
|
68
70
|
* [Manual Filtering](#manual-filtering)
|
|
@@ -215,6 +217,7 @@ psk --exclude build
|
|
|
215
217
|
| `--expr` | Enable boolean query expressions. Example: `r"foo.*bar" and ("bar" or "baz") and not "qux"`. Prefixes: `r=regex`, `c=case-sensitive`, `w=whole-word`, `f=fuzzy` |
|
|
216
218
|
| `--context` | Show N context lines before and after matches, or use N:M to specify before:after |
|
|
217
219
|
| `--full-path` | By default, query is only matched against the filename or directory name (this applies only when searching for files or directories, not file contents). Using this flag, query is matched against the full path (and, if `--absolute-path` flag is enabled, against the absolute path) |
|
|
220
|
+
| `--line` | Match lines where the entire line participates in a match |
|
|
218
221
|
| `--depth` | Limit directory traversal to given depth range. By default, there is no limit on search depth |
|
|
219
222
|
| `--timeout` | Stop the search after the specified number of seconds |
|
|
220
223
|
| `--fuzzy` | Enable fuzzy search (Highlighting and counting matches are disabled in this mode if `--word` is not enabled to prevent the program from slowing down). except when `--expr` is enabled, in which case you can make it fuzzy by putting `f` before term: `f"foo"` |
|
|
@@ -399,6 +402,39 @@ With `--full-path`, you can match `fd/f` against the entry `fd/file.txt` inside
|
|
|
399
402
|
|
|
400
403
|
> **Note:** For ordinary queries without `--regex`, backslashes are treated literally, so Windows paths can be searched without additional escaping. When using `--expr`, quoted terms use JSON-style escaping; escape backslashes accordingly. For example, `"\\"` represents a single literal backslash, while `"\\n"` represents the literal sequence `\n`.
|
|
401
404
|
|
|
405
|
+
### Line
|
|
406
|
+
|
|
407
|
+
Match the entire line or selected path instead of matching a pattern anywhere within it.
|
|
408
|
+
|
|
409
|
+
```bash
|
|
410
|
+
# Match lines exactly equal to "TODO"
|
|
411
|
+
psk TODO --line
|
|
412
|
+
|
|
413
|
+
# Match only lines containing exactly "foo" or "bar"
|
|
414
|
+
psk 'foo|bar' --regex --line
|
|
415
|
+
|
|
416
|
+
# Match files whose names are exactly "cli.py"
|
|
417
|
+
psk "cli.py" --file --line
|
|
418
|
+
```
|
|
419
|
+
|
|
420
|
+
> **Note:** If both options are specified, `--line` takes precedence over `--word`. In this case, instead of checking individual word boundaries, the entire line or selected path is matched.
|
|
421
|
+
|
|
422
|
+
By default, Pseek matches a file's or directory's **name**. Use `--full-path` to match against its full path instead.
|
|
423
|
+
|
|
424
|
+
```bash
|
|
425
|
+
# Match files named "cli.py"
|
|
426
|
+
psk "cli.py" --file --line
|
|
427
|
+
|
|
428
|
+
# Match the full relative path "pseek/cli.py"
|
|
429
|
+
psk "pseek/cli.py" --file --full-path --line
|
|
430
|
+
|
|
431
|
+
# Match the full absolute path
|
|
432
|
+
psk "/home/python/cli/pseek/utils.py" \
|
|
433
|
+
--file --full-path --absolute-path --line
|
|
434
|
+
```
|
|
435
|
+
|
|
436
|
+
> **Note:** Leading and trailing whitespace is significant. `--line` does not trim the target before matching. Use an appropriate regular expression, such as `\s*TODO\s*` with `--line`, if surrounding whitespace should be ignored.
|
|
437
|
+
|
|
402
438
|
## Expression Queries
|
|
403
439
|
|
|
404
440
|
Expression mode enables logical search expressions.
|
|
@@ -453,9 +489,7 @@ Each term can have its own search mode.
|
|
|
453
489
|
|
|
454
490
|
#### Regex
|
|
455
491
|
|
|
456
|
-
|
|
457
|
-
r"pattern"
|
|
458
|
-
```
|
|
492
|
+
Usage: `r"pattern"`
|
|
459
493
|
|
|
460
494
|
Example:
|
|
461
495
|
|
|
@@ -465,9 +499,7 @@ psk 'r"error\d+"' --expr
|
|
|
465
499
|
|
|
466
500
|
#### Case Sensitive
|
|
467
501
|
|
|
468
|
-
|
|
469
|
-
c"text"
|
|
470
|
-
```
|
|
502
|
+
Usage: `c"text"`
|
|
471
503
|
|
|
472
504
|
Example:
|
|
473
505
|
|
|
@@ -477,9 +509,7 @@ psk 'c"Error"' --expr
|
|
|
477
509
|
|
|
478
510
|
#### Whole Word
|
|
479
511
|
|
|
480
|
-
|
|
481
|
-
w"text"
|
|
482
|
-
```
|
|
512
|
+
Usage: `w"text"`
|
|
483
513
|
|
|
484
514
|
Example:
|
|
485
515
|
|
|
@@ -489,9 +519,7 @@ psk 'w"cat"' --expr
|
|
|
489
519
|
|
|
490
520
|
#### Fuzzy
|
|
491
521
|
|
|
492
|
-
|
|
493
|
-
f"text"
|
|
494
|
-
```
|
|
522
|
+
Usage: `f"text"`
|
|
495
523
|
|
|
496
524
|
Example:
|
|
497
525
|
|
|
@@ -501,9 +529,7 @@ psk 'f"apple"' --expr
|
|
|
501
529
|
|
|
502
530
|
#### Full Path
|
|
503
531
|
|
|
504
|
-
|
|
505
|
-
p"text"
|
|
506
|
-
```
|
|
532
|
+
Usage: `p"text"`
|
|
507
533
|
|
|
508
534
|
Example:
|
|
509
535
|
|
|
@@ -511,6 +537,16 @@ Example:
|
|
|
511
537
|
psk 'p"lib"' --expr
|
|
512
538
|
```
|
|
513
539
|
|
|
540
|
+
#### Line
|
|
541
|
+
|
|
542
|
+
Usage: `l"text"`
|
|
543
|
+
|
|
544
|
+
Example:
|
|
545
|
+
|
|
546
|
+
```bash
|
|
547
|
+
psk 'l"foo"' --expr
|
|
548
|
+
```
|
|
549
|
+
|
|
514
550
|
#### Combined Prefixes
|
|
515
551
|
|
|
516
552
|
Prefixes can be combined.
|
|
@@ -538,9 +574,7 @@ Meaning:
|
|
|
538
574
|
|
|
539
575
|
simultaneously.
|
|
540
576
|
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
and their permutations.
|
|
577
|
+
All modes are permitted, except for those where regex and word, or regex and fuzzy, are used simultaneously.
|
|
544
578
|
|
|
545
579
|
> **Note:** Whole word matching and regex matching cannot be used at the same time, because we can use `\b` in regex to enable whole word matching: `r"\btext\b"`
|
|
546
580
|
|
|
@@ -23,6 +23,7 @@ Fast and powerful command-line search tool for finding files, directories, and t
|
|
|
23
23
|
* [Fuzzy](#fuzzy-search)
|
|
24
24
|
* [Fuzzy Similarity Threshold](#fuzzy-similarity-threshold)
|
|
25
25
|
* [Full Path](#full-path)
|
|
26
|
+
* [Line](#line)
|
|
26
27
|
* [Expression Queries](#expression-queries)
|
|
27
28
|
* [Operators](#supported-operators)
|
|
28
29
|
* [AND](#and)
|
|
@@ -35,6 +36,7 @@ Fast and powerful command-line search tool for finding files, directories, and t
|
|
|
35
36
|
* [Whole Word](#whole-word)
|
|
36
37
|
* [Fuzzy](#fuzzy)
|
|
37
38
|
* [Full Path](#full-path-1)
|
|
39
|
+
* [Line](#line-1)
|
|
38
40
|
* [Combined Prefixes](#combined-prefixes)
|
|
39
41
|
* [Automatic Filtering](#automatic-filtering)
|
|
40
42
|
* [Manual Filtering](#manual-filtering)
|
|
@@ -187,6 +189,7 @@ psk --exclude build
|
|
|
187
189
|
| `--expr` | Enable boolean query expressions. Example: `r"foo.*bar" and ("bar" or "baz") and not "qux"`. Prefixes: `r=regex`, `c=case-sensitive`, `w=whole-word`, `f=fuzzy` |
|
|
188
190
|
| `--context` | Show N context lines before and after matches, or use N:M to specify before:after |
|
|
189
191
|
| `--full-path` | By default, query is only matched against the filename or directory name (this applies only when searching for files or directories, not file contents). Using this flag, query is matched against the full path (and, if `--absolute-path` flag is enabled, against the absolute path) |
|
|
192
|
+
| `--line` | Match lines where the entire line participates in a match |
|
|
190
193
|
| `--depth` | Limit directory traversal to given depth range. By default, there is no limit on search depth |
|
|
191
194
|
| `--timeout` | Stop the search after the specified number of seconds |
|
|
192
195
|
| `--fuzzy` | Enable fuzzy search (Highlighting and counting matches are disabled in this mode if `--word` is not enabled to prevent the program from slowing down). except when `--expr` is enabled, in which case you can make it fuzzy by putting `f` before term: `f"foo"` |
|
|
@@ -371,6 +374,39 @@ With `--full-path`, you can match `fd/f` against the entry `fd/file.txt` inside
|
|
|
371
374
|
|
|
372
375
|
> **Note:** For ordinary queries without `--regex`, backslashes are treated literally, so Windows paths can be searched without additional escaping. When using `--expr`, quoted terms use JSON-style escaping; escape backslashes accordingly. For example, `"\\"` represents a single literal backslash, while `"\\n"` represents the literal sequence `\n`.
|
|
373
376
|
|
|
377
|
+
### Line
|
|
378
|
+
|
|
379
|
+
Match the entire line or selected path instead of matching a pattern anywhere within it.
|
|
380
|
+
|
|
381
|
+
```bash
|
|
382
|
+
# Match lines exactly equal to "TODO"
|
|
383
|
+
psk TODO --line
|
|
384
|
+
|
|
385
|
+
# Match only lines containing exactly "foo" or "bar"
|
|
386
|
+
psk 'foo|bar' --regex --line
|
|
387
|
+
|
|
388
|
+
# Match files whose names are exactly "cli.py"
|
|
389
|
+
psk "cli.py" --file --line
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
> **Note:** If both options are specified, `--line` takes precedence over `--word`. In this case, instead of checking individual word boundaries, the entire line or selected path is matched.
|
|
393
|
+
|
|
394
|
+
By default, Pseek matches a file's or directory's **name**. Use `--full-path` to match against its full path instead.
|
|
395
|
+
|
|
396
|
+
```bash
|
|
397
|
+
# Match files named "cli.py"
|
|
398
|
+
psk "cli.py" --file --line
|
|
399
|
+
|
|
400
|
+
# Match the full relative path "pseek/cli.py"
|
|
401
|
+
psk "pseek/cli.py" --file --full-path --line
|
|
402
|
+
|
|
403
|
+
# Match the full absolute path
|
|
404
|
+
psk "/home/python/cli/pseek/utils.py" \
|
|
405
|
+
--file --full-path --absolute-path --line
|
|
406
|
+
```
|
|
407
|
+
|
|
408
|
+
> **Note:** Leading and trailing whitespace is significant. `--line` does not trim the target before matching. Use an appropriate regular expression, such as `\s*TODO\s*` with `--line`, if surrounding whitespace should be ignored.
|
|
409
|
+
|
|
374
410
|
## Expression Queries
|
|
375
411
|
|
|
376
412
|
Expression mode enables logical search expressions.
|
|
@@ -425,9 +461,7 @@ Each term can have its own search mode.
|
|
|
425
461
|
|
|
426
462
|
#### Regex
|
|
427
463
|
|
|
428
|
-
|
|
429
|
-
r"pattern"
|
|
430
|
-
```
|
|
464
|
+
Usage: `r"pattern"`
|
|
431
465
|
|
|
432
466
|
Example:
|
|
433
467
|
|
|
@@ -437,9 +471,7 @@ psk 'r"error\d+"' --expr
|
|
|
437
471
|
|
|
438
472
|
#### Case Sensitive
|
|
439
473
|
|
|
440
|
-
|
|
441
|
-
c"text"
|
|
442
|
-
```
|
|
474
|
+
Usage: `c"text"`
|
|
443
475
|
|
|
444
476
|
Example:
|
|
445
477
|
|
|
@@ -449,9 +481,7 @@ psk 'c"Error"' --expr
|
|
|
449
481
|
|
|
450
482
|
#### Whole Word
|
|
451
483
|
|
|
452
|
-
|
|
453
|
-
w"text"
|
|
454
|
-
```
|
|
484
|
+
Usage: `w"text"`
|
|
455
485
|
|
|
456
486
|
Example:
|
|
457
487
|
|
|
@@ -461,9 +491,7 @@ psk 'w"cat"' --expr
|
|
|
461
491
|
|
|
462
492
|
#### Fuzzy
|
|
463
493
|
|
|
464
|
-
|
|
465
|
-
f"text"
|
|
466
|
-
```
|
|
494
|
+
Usage: `f"text"`
|
|
467
495
|
|
|
468
496
|
Example:
|
|
469
497
|
|
|
@@ -473,9 +501,7 @@ psk 'f"apple"' --expr
|
|
|
473
501
|
|
|
474
502
|
#### Full Path
|
|
475
503
|
|
|
476
|
-
|
|
477
|
-
p"text"
|
|
478
|
-
```
|
|
504
|
+
Usage: `p"text"`
|
|
479
505
|
|
|
480
506
|
Example:
|
|
481
507
|
|
|
@@ -483,6 +509,16 @@ Example:
|
|
|
483
509
|
psk 'p"lib"' --expr
|
|
484
510
|
```
|
|
485
511
|
|
|
512
|
+
#### Line
|
|
513
|
+
|
|
514
|
+
Usage: `l"text"`
|
|
515
|
+
|
|
516
|
+
Example:
|
|
517
|
+
|
|
518
|
+
```bash
|
|
519
|
+
psk 'l"foo"' --expr
|
|
520
|
+
```
|
|
521
|
+
|
|
486
522
|
#### Combined Prefixes
|
|
487
523
|
|
|
488
524
|
Prefixes can be combined.
|
|
@@ -510,9 +546,7 @@ Meaning:
|
|
|
510
546
|
|
|
511
547
|
simultaneously.
|
|
512
548
|
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
and their permutations.
|
|
549
|
+
All modes are permitted, except for those where regex and word, or regex and fuzzy, are used simultaneously.
|
|
516
550
|
|
|
517
551
|
> **Note:** Whole word matching and regex matching cannot be used at the same time, because we can use `\b` in regex to enable whole word matching: `r"\btext\b"`
|
|
518
552
|
|
|
@@ -347,6 +347,8 @@ def check_rar_backend(archive_enabled: bool, tool_path: str, backend: str):
|
|
|
347
347
|
'(this applies only when searching for files or directories, not file contents). '
|
|
348
348
|
'Using this flag, query is matched against the full path '
|
|
349
349
|
'(and, if --absolute-path flag is enabled, against the absolute path).')
|
|
350
|
+
@click.option('--line', is_flag=True,
|
|
351
|
+
help='Match lines where the entire line participates in a match.')
|
|
350
352
|
@click.option('-D', '--depth', multiple=True, metavar='MIN:MAX',
|
|
351
353
|
help='Limit directory traversal to given depth range. '
|
|
352
354
|
'By default, there is no limit on search depth.')
|
|
@@ -440,10 +442,10 @@ def search(**kwargs):
|
|
|
440
442
|
|
|
441
443
|
check_rar_backend(config.archive, config.rar_backend, config.query)
|
|
442
444
|
|
|
443
|
-
if not config.expr and config.fuzzy:
|
|
445
|
+
if not config.expr and config.fuzzy and not config.line:
|
|
444
446
|
if not config.word:
|
|
445
447
|
click.secho(
|
|
446
|
-
"Warning:
|
|
448
|
+
"Warning: To improve performance, highlighting of matches is disabled.",
|
|
447
449
|
fg="yellow"
|
|
448
450
|
)
|
|
449
451
|
elif config.word and " " in config.query:
|
|
@@ -26,7 +26,8 @@ class TermNode(ExprNode):
|
|
|
26
26
|
case_sensitive: bool,
|
|
27
27
|
fuzzy: bool,
|
|
28
28
|
fuzzy_level: int | None,
|
|
29
|
-
full_path: bool
|
|
29
|
+
full_path: bool,
|
|
30
|
+
whole_line: bool
|
|
30
31
|
):
|
|
31
32
|
self.raw_term = term
|
|
32
33
|
self.term_lower = term.lower()
|
|
@@ -36,6 +37,7 @@ class TermNode(ExprNode):
|
|
|
36
37
|
self.fuzzy = fuzzy
|
|
37
38
|
self.fuzzy_level = fuzzy_level
|
|
38
39
|
self.full_path = full_path
|
|
40
|
+
self.whole_line = whole_line
|
|
39
41
|
|
|
40
42
|
if not fuzzy:
|
|
41
43
|
flags = 0 if case_sensitive else re.IGNORECASE # Adjust case sensitivity
|
|
@@ -44,7 +46,7 @@ class TermNode(ExprNode):
|
|
|
44
46
|
if not regex:
|
|
45
47
|
term = re.escape(term) # Escape if not regex
|
|
46
48
|
# Apply whole-word matching only if not using regex (or if desired behavior is defined)
|
|
47
|
-
if whole_word:
|
|
49
|
+
if whole_word and not whole_line:
|
|
48
50
|
term = r'\b' + term + r'\b'
|
|
49
51
|
|
|
50
52
|
self.pattern = compile_regex(term, flags) # Precompile the regex pattern for performance
|
|
@@ -60,20 +62,29 @@ class TermNode(ExprNode):
|
|
|
60
62
|
if not self.fuzzy:
|
|
61
63
|
# Use substring search for more speed
|
|
62
64
|
if not self.regex and not self.whole_word:
|
|
65
|
+
if self.whole_line:
|
|
66
|
+
return term == text_cmp
|
|
63
67
|
return term in text_cmp
|
|
64
68
|
|
|
65
|
-
return bool(self.pattern.search(text))
|
|
69
|
+
return bool(self.pattern.search(text)) \
|
|
70
|
+
if not self.whole_line \
|
|
71
|
+
else bool(self.pattern.fullmatch(text))
|
|
72
|
+
|
|
73
|
+
if self.whole_line:
|
|
74
|
+
score = fuzz.ratio(term, text_cmp)
|
|
75
|
+
return score >= self.fuzzy_level
|
|
66
76
|
|
|
67
77
|
if self.whole_word:
|
|
68
78
|
words = re.findall(r'\w+', text_cmp)
|
|
69
79
|
return any(fuzz.ratio(term, word) >= self.fuzzy_level for word in words)
|
|
80
|
+
|
|
81
|
+
# Use the correct method depending on the len of str to increase accuracy and avoid illogical matching
|
|
82
|
+
if len(text_cmp) > len(term):
|
|
83
|
+
score = fuzz.partial_ratio(term, text_cmp)
|
|
70
84
|
else:
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
else:
|
|
75
|
-
score = fuzz.ratio(term, text_cmp)
|
|
76
|
-
return score >= self.fuzzy_level
|
|
85
|
+
score = fuzz.ratio(term, text_cmp)
|
|
86
|
+
|
|
87
|
+
return score >= self.fuzzy_level
|
|
77
88
|
|
|
78
89
|
def get_binary_pattern(self):
|
|
79
90
|
"""
|
|
@@ -129,25 +140,8 @@ class OrNode(ExprNode):
|
|
|
129
140
|
return self.left.evaluate(text) or self.right.evaluate(text)
|
|
130
141
|
|
|
131
142
|
|
|
132
|
-
def gvp() -> str:
|
|
133
|
-
"""Generate all possible states and permutations of input prefixes
|
|
134
|
-
|
|
135
|
-
Returns:
|
|
136
|
-
str: prefixes=("f", "r", "rf") -> result="f|r|rf|fr"
|
|
137
|
-
"""
|
|
138
|
-
|
|
139
|
-
prefixes = {'r','c','w','f','p','rp','pc','wp','fp','rc','cw',
|
|
140
|
-
'cf','wf','cwf','rcp','cwp','cfp','wfp','cwfp'}
|
|
141
|
-
valid_prefixes = set()
|
|
142
|
-
|
|
143
|
-
for p in prefixes:
|
|
144
|
-
valid_prefixes |= {''.join(pr) for pr in permutations(p)}
|
|
145
|
-
|
|
146
|
-
return '|'.join(valid_prefixes)
|
|
147
|
-
|
|
148
|
-
|
|
149
143
|
# Lark grammar for parsing logical expressions
|
|
150
|
-
query_grammar =
|
|
144
|
+
query_grammar = r"""
|
|
151
145
|
?start: expr
|
|
152
146
|
|
|
153
147
|
?expr: or_expr
|
|
@@ -165,7 +159,7 @@ query_grammar = rf"""
|
|
|
165
159
|
| ESCAPED_STRING -> string
|
|
166
160
|
| "(" expr ")"
|
|
167
161
|
|
|
168
|
-
PREFIXED_STRING: /
|
|
162
|
+
PREFIXED_STRING: /[rcwfpl]+"([^"\\]|\\.)*"/
|
|
169
163
|
|
|
170
164
|
%import common.ESCAPED_STRING
|
|
171
165
|
%import common.WS
|
|
@@ -204,6 +198,7 @@ class TreeToExpr(Transformer):
|
|
|
204
198
|
False,
|
|
205
199
|
False,
|
|
206
200
|
None,
|
|
201
|
+
False,
|
|
207
202
|
False
|
|
208
203
|
)
|
|
209
204
|
|
|
@@ -213,6 +208,14 @@ class TreeToExpr(Transformer):
|
|
|
213
208
|
|
|
214
209
|
quote_index = text.index('"')
|
|
215
210
|
prefix = text[:quote_index]
|
|
211
|
+
|
|
212
|
+
if len(prefix) != len(set(prefix)):
|
|
213
|
+
raise ValueError(f'Duplicate prefix flag: {prefix}')
|
|
214
|
+
if 'r' in prefix and 'f' in prefix:
|
|
215
|
+
raise ValueError('Regex and fuzzy prefixes cannot be combined.')
|
|
216
|
+
if 'r' in prefix and 'w' in prefix:
|
|
217
|
+
raise ValueError('Regex and whole-word prefixes cannot be combined. To use whole-word matching in regex, use \\b: r"\\btext\\b"')
|
|
218
|
+
|
|
216
219
|
quoted = text[quote_index:]
|
|
217
220
|
|
|
218
221
|
is_regex = 'r' in prefix
|
|
@@ -225,7 +228,8 @@ class TreeToExpr(Transformer):
|
|
|
225
228
|
case_sensitive='c' in prefix,
|
|
226
229
|
fuzzy='f' in prefix,
|
|
227
230
|
fuzzy_level=self.fuzzy_level,
|
|
228
|
-
full_path='p' in prefix
|
|
231
|
+
full_path='p' in prefix,
|
|
232
|
+
whole_line='l' in prefix
|
|
229
233
|
)
|
|
230
234
|
|
|
231
235
|
def and_expr(self, args):
|
|
@@ -238,7 +242,7 @@ class TreeToExpr(Transformer):
|
|
|
238
242
|
return NotNode(args[0])
|
|
239
243
|
|
|
240
244
|
|
|
241
|
-
def parse_query_expression(config) -> ExprNode:
|
|
245
|
+
def parse_query_expression(config) -> ExprNode | None:
|
|
242
246
|
"""
|
|
243
247
|
Function to parse the query and return expression tree.
|
|
244
248
|
If expr is False, treat the whole query as a single term.
|
|
@@ -255,7 +259,8 @@ def parse_query_expression(config) -> ExprNode:
|
|
|
255
259
|
config.case_sensitive,
|
|
256
260
|
config.fuzzy,
|
|
257
261
|
config.fuzzy_level,
|
|
258
|
-
config.full_path
|
|
262
|
+
config.full_path,
|
|
263
|
+
config.line
|
|
259
264
|
)
|
|
260
265
|
|
|
261
266
|
# Otherwise, parse using Lark
|
|
@@ -276,7 +281,7 @@ def find_term_matches(node: TermNode, text: str | Path, num: int) -> list[tuple[
|
|
|
276
281
|
|
|
277
282
|
if node.fuzzy:
|
|
278
283
|
# Fuzzy partial matching currently has no span extraction
|
|
279
|
-
if not node.whole_word:
|
|
284
|
+
if not node.whole_word and not node.whole_line:
|
|
280
285
|
return []
|
|
281
286
|
|
|
282
287
|
text_cmp = (
|
|
@@ -288,6 +293,11 @@ def find_term_matches(node: TermNode, text: str | Path, num: int) -> list[tuple[
|
|
|
288
293
|
else node.term_lower
|
|
289
294
|
)
|
|
290
295
|
|
|
296
|
+
if node.whole_line:
|
|
297
|
+
if fuzz.ratio(term, text_cmp) >= node.fuzzy_level:
|
|
298
|
+
return [(num, len(text) + num)]
|
|
299
|
+
return []
|
|
300
|
+
|
|
291
301
|
matches = []
|
|
292
302
|
|
|
293
303
|
for match in re.finditer(r'\w+', text_cmp):
|
|
@@ -301,6 +311,9 @@ def find_term_matches(node: TermNode, text: str | Path, num: int) -> list[tuple[
|
|
|
301
311
|
|
|
302
312
|
return matches
|
|
303
313
|
|
|
314
|
+
if node.whole_line and node.pattern.fullmatch(text) is not None:
|
|
315
|
+
return [(num, len(text) + num)]
|
|
316
|
+
|
|
304
317
|
return [
|
|
305
318
|
(match.start() + num, match.end() + num)
|
|
306
319
|
for match in node.pattern.finditer(text)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|