pseek 3.4.1__tar.gz → 3.5.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.4.1 → pseek-3.5.0}/PKG-INFO +64 -1
- {pseek-3.4.1 → pseek-3.5.0}/README.md +63 -0
- {pseek-3.4.1 → pseek-3.5.0}/pseek/cli.py +10 -5
- {pseek-3.4.1 → pseek-3.5.0}/pseek/parser.py +6 -0
- {pseek-3.4.1 → pseek-3.5.0}/pseek/searcher.py +14 -10
- {pseek-3.4.1 → pseek-3.5.0}/pseek/structs.py +1 -0
- {pseek-3.4.1 → pseek-3.5.0}/pyproject.toml +1 -1
- {pseek-3.4.1 → pseek-3.5.0}/.gitattributes +0 -0
- {pseek-3.4.1 → pseek-3.5.0}/.github/workflows/publish.yml +0 -0
- {pseek-3.4.1 → pseek-3.5.0}/.gitignore +0 -0
- {pseek-3.4.1 → pseek-3.5.0}/Cargo.lock +0 -0
- {pseek-3.4.1 → pseek-3.5.0}/Cargo.toml +0 -0
- {pseek-3.4.1 → pseek-3.5.0}/LICENSE +0 -0
- {pseek-3.4.1 → pseek-3.5.0}/pseek/__init__.py +0 -0
- {pseek-3.4.1 → pseek-3.5.0}/pseek/archive.py +0 -0
- {pseek-3.4.1 → pseek-3.5.0}/pseek/compound_extensions +0 -0
- {pseek-3.4.1 → pseek-3.5.0}/pseek/utils.py +0 -0
- {pseek-3.4.1 → pseek-3.5.0}/scripts/check_version.py +0 -0
- {pseek-3.4.1 → pseek-3.5.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.5.0
|
|
4
4
|
Classifier: Development Status :: 5 - Production/Stable
|
|
5
5
|
Classifier: Environment :: Console
|
|
6
6
|
Classifier: Intended Audience :: Developers
|
|
@@ -50,6 +50,7 @@ Fast and powerful command-line search tool for finding files, directories, and t
|
|
|
50
50
|
* [Regular Expression (Regex)](#regular-expression-search)
|
|
51
51
|
* [Fuzzy](#fuzzy-search)
|
|
52
52
|
* [Fuzzy Similarity Threshold](#fuzzy-similarity-threshold)
|
|
53
|
+
* [Full Path](#full-path)
|
|
53
54
|
* [Expression Queries](#expression-queries)
|
|
54
55
|
* [Operators](#supported-operators)
|
|
55
56
|
* [AND](#and)
|
|
@@ -174,6 +175,26 @@ To search for a query that starts with `-`, use `--` to mark the end of options:
|
|
|
174
175
|
psk -- --path
|
|
175
176
|
```
|
|
176
177
|
|
|
178
|
+
Of course the search query is optional. When no query is provided, Pseek displays the files and directories and file contents within the selected scope.
|
|
179
|
+
|
|
180
|
+
All other filters still apply, including `--glob`, `--depth`, `--size`, ignore rules, and other filtering options.
|
|
181
|
+
|
|
182
|
+
This makes Pseek useful as a flexible alternative to `ls` or `cat`, allowing you to inspect a filtered view of a directory tree and file contents.
|
|
183
|
+
|
|
184
|
+
```bash
|
|
185
|
+
# List files and directories and file contents
|
|
186
|
+
psk
|
|
187
|
+
|
|
188
|
+
# List only Python files
|
|
189
|
+
psk --ext py
|
|
190
|
+
|
|
191
|
+
# List everything up to depth 2
|
|
192
|
+
psk --depth :2
|
|
193
|
+
|
|
194
|
+
# List everything except the build directory
|
|
195
|
+
psk --exclude build
|
|
196
|
+
```
|
|
197
|
+
|
|
177
198
|
## Command Options
|
|
178
199
|
|
|
179
200
|
| Option | Description |
|
|
@@ -189,6 +210,7 @@ psk -- --path
|
|
|
189
210
|
| `--word` | Match the whole word only (except when `--expr` is enabled, in which case you can make it match whole word by putting `w` before term: `w"foo"`) |
|
|
190
211
|
| `--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` |
|
|
191
212
|
| `--context` | Show N context lines before and after matches, or use N:M to specify before:after |
|
|
213
|
+
| `--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
214
|
| `--depth` | Limit directory traversal to given depth range. By default, there is no limit on search depth |
|
|
193
215
|
| `--timeout` | Stop the search after the specified number of seconds |
|
|
194
216
|
| `--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"` |
|
|
@@ -331,6 +353,45 @@ Examples:
|
|
|
331
353
|
|
|
332
354
|
Default: `80`
|
|
333
355
|
|
|
356
|
+
### Full Path
|
|
357
|
+
|
|
358
|
+
By default, Pseek matches file and directory queries against the entry's name only. Use `--full-path` to match against its full path within the search scope instead. This option affects file and directory searches, not content searches.
|
|
359
|
+
|
|
360
|
+
For example, given the relative path `pseek/utils.py`, you can match part of the path rather than just the filename:
|
|
361
|
+
|
|
362
|
+
```bash
|
|
363
|
+
# Match against the full relative path
|
|
364
|
+
psk "seek/utils" --full-path
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
**Relative paths vs. absolute paths**
|
|
368
|
+
|
|
369
|
+
`--full-path` does not automatically include the absolute path. If the file's absolute path is:
|
|
370
|
+
|
|
371
|
+
```text
|
|
372
|
+
/home/python/cli/pseek/utils.py
|
|
373
|
+
```
|
|
374
|
+
|
|
375
|
+
a query such as `python/cli` will not match unless `--absolute-path` is also enabled:
|
|
376
|
+
|
|
377
|
+
```bash
|
|
378
|
+
psk "python/cli" --full-path --absolute-path
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
**Nested archives**
|
|
382
|
+
|
|
383
|
+
When searching nested archives, `--full-path` applies only to the path within the current archive level, not the entire nested archive chain.
|
|
384
|
+
|
|
385
|
+
For example:
|
|
386
|
+
|
|
387
|
+
```text
|
|
388
|
+
archive.zip::folder/arc.zip::fd/file.txt
|
|
389
|
+
```
|
|
390
|
+
|
|
391
|
+
With `--full-path`, you can match `fd/f` against the entry `fd/file.txt` inside the innermost archive. A query such as `zip::fd` does not match across archive boundaries. Without `--full-path`, matching is limited to the entry name, `file.txt`.
|
|
392
|
+
|
|
393
|
+
> **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`.
|
|
394
|
+
|
|
334
395
|
## Expression Queries
|
|
335
396
|
|
|
336
397
|
Expression mode enables logical search expressions.
|
|
@@ -564,6 +625,8 @@ psk TODO \
|
|
|
564
625
|
|
|
565
626
|
Only search inside those paths.
|
|
566
627
|
|
|
628
|
+
> **Note:** Paths manually included by the user take precedence over other filters; this means that even if a path conflicts with rules related to [--glob](#globs), [--exclude](#exclude-paths), etc., it will still be included in the results.
|
|
629
|
+
|
|
567
630
|
#### Exclude Paths
|
|
568
631
|
|
|
569
632
|
```bash
|
|
@@ -22,6 +22,7 @@ Fast and powerful command-line search tool for finding files, directories, and t
|
|
|
22
22
|
* [Regular Expression (Regex)](#regular-expression-search)
|
|
23
23
|
* [Fuzzy](#fuzzy-search)
|
|
24
24
|
* [Fuzzy Similarity Threshold](#fuzzy-similarity-threshold)
|
|
25
|
+
* [Full Path](#full-path)
|
|
25
26
|
* [Expression Queries](#expression-queries)
|
|
26
27
|
* [Operators](#supported-operators)
|
|
27
28
|
* [AND](#and)
|
|
@@ -146,6 +147,26 @@ To search for a query that starts with `-`, use `--` to mark the end of options:
|
|
|
146
147
|
psk -- --path
|
|
147
148
|
```
|
|
148
149
|
|
|
150
|
+
Of course the search query is optional. When no query is provided, Pseek displays the files and directories and file contents within the selected scope.
|
|
151
|
+
|
|
152
|
+
All other filters still apply, including `--glob`, `--depth`, `--size`, ignore rules, and other filtering options.
|
|
153
|
+
|
|
154
|
+
This makes Pseek useful as a flexible alternative to `ls` or `cat`, allowing you to inspect a filtered view of a directory tree and file contents.
|
|
155
|
+
|
|
156
|
+
```bash
|
|
157
|
+
# List files and directories and file contents
|
|
158
|
+
psk
|
|
159
|
+
|
|
160
|
+
# List only Python files
|
|
161
|
+
psk --ext py
|
|
162
|
+
|
|
163
|
+
# List everything up to depth 2
|
|
164
|
+
psk --depth :2
|
|
165
|
+
|
|
166
|
+
# List everything except the build directory
|
|
167
|
+
psk --exclude build
|
|
168
|
+
```
|
|
169
|
+
|
|
149
170
|
## Command Options
|
|
150
171
|
|
|
151
172
|
| Option | Description |
|
|
@@ -161,6 +182,7 @@ psk -- --path
|
|
|
161
182
|
| `--word` | Match the whole word only (except when `--expr` is enabled, in which case you can make it match whole word by putting `w` before term: `w"foo"`) |
|
|
162
183
|
| `--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` |
|
|
163
184
|
| `--context` | Show N context lines before and after matches, or use N:M to specify before:after |
|
|
185
|
+
| `--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) |
|
|
164
186
|
| `--depth` | Limit directory traversal to given depth range. By default, there is no limit on search depth |
|
|
165
187
|
| `--timeout` | Stop the search after the specified number of seconds |
|
|
166
188
|
| `--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"` |
|
|
@@ -303,6 +325,45 @@ Examples:
|
|
|
303
325
|
|
|
304
326
|
Default: `80`
|
|
305
327
|
|
|
328
|
+
### Full Path
|
|
329
|
+
|
|
330
|
+
By default, Pseek matches file and directory queries against the entry's name only. Use `--full-path` to match against its full path within the search scope instead. This option affects file and directory searches, not content searches.
|
|
331
|
+
|
|
332
|
+
For example, given the relative path `pseek/utils.py`, you can match part of the path rather than just the filename:
|
|
333
|
+
|
|
334
|
+
```bash
|
|
335
|
+
# Match against the full relative path
|
|
336
|
+
psk "seek/utils" --full-path
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
**Relative paths vs. absolute paths**
|
|
340
|
+
|
|
341
|
+
`--full-path` does not automatically include the absolute path. If the file's absolute path is:
|
|
342
|
+
|
|
343
|
+
```text
|
|
344
|
+
/home/python/cli/pseek/utils.py
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
a query such as `python/cli` will not match unless `--absolute-path` is also enabled:
|
|
348
|
+
|
|
349
|
+
```bash
|
|
350
|
+
psk "python/cli" --full-path --absolute-path
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
**Nested archives**
|
|
354
|
+
|
|
355
|
+
When searching nested archives, `--full-path` applies only to the path within the current archive level, not the entire nested archive chain.
|
|
356
|
+
|
|
357
|
+
For example:
|
|
358
|
+
|
|
359
|
+
```text
|
|
360
|
+
archive.zip::folder/arc.zip::fd/file.txt
|
|
361
|
+
```
|
|
362
|
+
|
|
363
|
+
With `--full-path`, you can match `fd/f` against the entry `fd/file.txt` inside the innermost archive. A query such as `zip::fd` does not match across archive boundaries. Without `--full-path`, matching is limited to the entry name, `file.txt`.
|
|
364
|
+
|
|
365
|
+
> **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`.
|
|
366
|
+
|
|
306
367
|
## Expression Queries
|
|
307
368
|
|
|
308
369
|
Expression mode enables logical search expressions.
|
|
@@ -536,6 +597,8 @@ psk TODO \
|
|
|
536
597
|
|
|
537
598
|
Only search inside those paths.
|
|
538
599
|
|
|
600
|
+
> **Note:** Paths manually included by the user take precedence over other filters; this means that even if a path conflicts with rules related to [--glob](#globs), [--exclude](#exclude-paths), etc., it will still be included in the results.
|
|
601
|
+
|
|
539
602
|
#### Exclude Paths
|
|
540
603
|
|
|
541
604
|
```bash
|
|
@@ -306,7 +306,7 @@ def check_rar_backend(archive_enabled: bool, tool_path: str, backend: str):
|
|
|
306
306
|
|
|
307
307
|
|
|
308
308
|
@click.command()
|
|
309
|
-
@click.argument('query')
|
|
309
|
+
@click.argument('query', required=False)
|
|
310
310
|
@click.argument('path', type=click.Path(exists=True, file_okay=False, dir_okay=True),
|
|
311
311
|
default='.', required=False)
|
|
312
312
|
# Search type options
|
|
@@ -336,12 +336,14 @@ def check_rar_backend(archive_enabled: bool, tool_path: str, backend: str):
|
|
|
336
336
|
help='Fuzzy matching threshold (1-99). Higher values require closer matches.')
|
|
337
337
|
@click.option('-C', '--context', metavar='BEFORE:AFTER',
|
|
338
338
|
help='Show N context lines before and after matches, or use N:M to specify before:after.')
|
|
339
|
-
@click.option('--
|
|
339
|
+
@click.option('-p', '--full-path', is_flag=True,
|
|
340
|
+
help='By default, query is only matched against the filename or directory name '
|
|
341
|
+
'(this applies only when searching for files or directories, not file contents). '
|
|
342
|
+
'Using this flag, query is matched against the full path '
|
|
343
|
+
'(and, if --absolute-path flag is enabled, against the absolute path).')
|
|
344
|
+
@click.option('-D', '--depth', multiple=True, metavar='MIN:MAX',
|
|
340
345
|
help='Limit directory traversal to given depth range. '
|
|
341
346
|
'By default, there is no limit on search depth.')
|
|
342
|
-
@click.option('--timeout', metavar='FLOAT',
|
|
343
|
-
type=click.FloatRange(min=0, min_open=True),
|
|
344
|
-
help='Stop the search after the specified number of seconds.')
|
|
345
347
|
# Automatic filtering
|
|
346
348
|
@click.option('-u', '--unrestricted', is_flag=True,
|
|
347
349
|
help='Disable all automatic filters except the binary file filter for content search.')
|
|
@@ -419,6 +421,9 @@ def check_rar_backend(archive_enabled: bool, tool_path: str, backend: str):
|
|
|
419
421
|
@click.option('-l', '--paths-only', is_flag=True, help='Only show matching file paths for content search.')
|
|
420
422
|
@click.option('-S', '--stats', is_flag=True,
|
|
421
423
|
help='Show search statistics including result counts and search time.')
|
|
424
|
+
@click.option('--timeout', metavar='FLOAT',
|
|
425
|
+
type=click.FloatRange(min=0, min_open=True),
|
|
426
|
+
help='Stop the search after the specified number of seconds.')
|
|
422
427
|
def search(**kwargs):
|
|
423
428
|
"""Search for files, directories, and file content based on the query."""
|
|
424
429
|
|
|
@@ -206,6 +206,9 @@ def parse_query_expression(config) -> ExprNode:
|
|
|
206
206
|
If expr is False, treat the whole query as a single term.
|
|
207
207
|
"""
|
|
208
208
|
|
|
209
|
+
if config.query is None:
|
|
210
|
+
return None
|
|
211
|
+
|
|
209
212
|
if not config.expr:
|
|
210
213
|
return TermNode(
|
|
211
214
|
config.query,
|
|
@@ -371,6 +374,9 @@ def evaluate_with_matches(
|
|
|
371
374
|
def find_matches(expr: ExprNode, text: str, num: int = 0) -> list[tuple[int, int]]:
|
|
372
375
|
"""Find spans that contribute to a successful expression"""
|
|
373
376
|
|
|
377
|
+
if expr is None:
|
|
378
|
+
return []
|
|
379
|
+
|
|
374
380
|
matched, matches = evaluate_with_matches(expr, text, num)
|
|
375
381
|
# Remove duplicate ranges
|
|
376
382
|
return list(dict.fromkeys(matches)) if matched else []
|
|
@@ -60,14 +60,15 @@ def search_file_and_dir(config, matches: dict, pattern, p: Path,
|
|
|
60
60
|
'directory' if config.directory and p.is_dir() else
|
|
61
61
|
None
|
|
62
62
|
)
|
|
63
|
+
p_name = p.name if not config.full_path else path_str
|
|
63
64
|
|
|
64
|
-
if match_type and pattern.evaluate(
|
|
65
|
+
if match_type and (pattern is None or pattern.evaluate(p_name)):
|
|
65
66
|
# Find matched query in the name
|
|
66
67
|
name_matches = find_matches(
|
|
67
68
|
pattern,
|
|
68
|
-
|
|
69
|
+
p_name,
|
|
69
70
|
# Calculate number of chars that come before name of file or dir
|
|
70
|
-
len(path_str) - len(
|
|
71
|
+
len(path_str) - len(p_name)
|
|
71
72
|
)
|
|
72
73
|
|
|
73
74
|
add_result(
|
|
@@ -83,8 +84,10 @@ def search_file_and_dir(config, matches: dict, pattern, p: Path,
|
|
|
83
84
|
# Search for files and directories name inside archive files if archive is active
|
|
84
85
|
if config.archive and p_ext in ARCHIVE_EXTS[:-3]:
|
|
85
86
|
for virtual_path, name, is_dir in extract_names_from_archive(p, config):
|
|
87
|
+
name_str = str(name)
|
|
88
|
+
|
|
86
89
|
if config.stats:
|
|
87
|
-
full_virtual_path = (path_str, *virtual_path,
|
|
90
|
+
full_virtual_path = (path_str, *virtual_path, name_str)
|
|
88
91
|
|
|
89
92
|
if not is_dir and config.file:
|
|
90
93
|
add_metric(metrics, result_queue, 'files_scanned', full_virtual_path)
|
|
@@ -101,13 +104,14 @@ def search_file_and_dir(config, matches: dict, pattern, p: Path,
|
|
|
101
104
|
'directory' if config.directory and is_dir else
|
|
102
105
|
None
|
|
103
106
|
)
|
|
107
|
+
virtual_name = name.name if not config.full_path else name_str
|
|
104
108
|
|
|
105
|
-
if arc_match_type and pattern.evaluate(
|
|
109
|
+
if arc_match_type and (pattern is None or pattern.evaluate(virtual_name)):
|
|
106
110
|
name_matches = find_matches(
|
|
107
111
|
pattern,
|
|
108
|
-
|
|
112
|
+
virtual_name,
|
|
109
113
|
# Calculate number of chars that come before name of file or dir
|
|
110
|
-
len(
|
|
114
|
+
len(name_str) - len(virtual_name)
|
|
111
115
|
)
|
|
112
116
|
|
|
113
117
|
add_result(
|
|
@@ -117,7 +121,7 @@ def search_file_and_dir(config, matches: dict, pattern, p: Path,
|
|
|
117
121
|
FileDirResult(
|
|
118
122
|
path=path_str,
|
|
119
123
|
matches=name_matches,
|
|
120
|
-
virtual_path=[*virtual_path,
|
|
124
|
+
virtual_path=[*virtual_path, name_str]
|
|
121
125
|
)
|
|
122
126
|
)
|
|
123
127
|
|
|
@@ -231,7 +235,7 @@ def search_content(config, matches: dict, pattern, binary_pattern,
|
|
|
231
235
|
|
|
232
236
|
collector = ContextCollector(config.context)
|
|
233
237
|
for num, line in enumerate(decoded_content.splitlines(), 1):
|
|
234
|
-
matched = pattern.evaluate(line)
|
|
238
|
+
matched = pattern is None or pattern.evaluate(line)
|
|
235
239
|
|
|
236
240
|
if config.paths_only and matched:
|
|
237
241
|
add_result(
|
|
@@ -285,7 +289,7 @@ def search_content(config, matches: dict, pattern, binary_pattern,
|
|
|
285
289
|
# Skip lines that can't be decoded
|
|
286
290
|
continue
|
|
287
291
|
|
|
288
|
-
matched = pattern.evaluate(line_decoded)
|
|
292
|
+
matched = pattern is None or pattern.evaluate(line_decoded)
|
|
289
293
|
|
|
290
294
|
# Avoid searching through the entire file content if the paths-only flag is True
|
|
291
295
|
if config.paths_only and matched:
|
|
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
|