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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pseek
3
- Version: 3.4.1
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('--depth', multiple=True, metavar='MIN:MAX',
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(p.name):
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
- p.name,
69
+ p_name,
69
70
  # Calculate number of chars that come before name of file or dir
70
- len(path_str) - len(p.name)
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, str(name))
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(name.name):
109
+ if arc_match_type and (pattern is None or pattern.evaluate(virtual_name)):
106
110
  name_matches = find_matches(
107
111
  pattern,
108
- name.name,
112
+ virtual_name,
109
113
  # Calculate number of chars that come before name of file or dir
110
- len(str(name)) - len(name.name)
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, str(name)]
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:
@@ -162,6 +162,7 @@ class SearchConfig:
162
162
  arc_size: list[tuple]
163
163
  rar_backend: str | None
164
164
  absolute_path: bool
165
+ full_path: bool
165
166
  paths_only: bool
166
167
  stats: bool
167
168
  context: tuple[int, int]
@@ -4,7 +4,7 @@ build-backend = "maturin"
4
4
 
5
5
  [project]
6
6
  name = "pseek"
7
- version = "3.4.1"
7
+ version = "3.5.0"
8
8
  description = "Pseek is a Python CLI toolkit to search files, folders, and text"
9
9
  readme = "README.md"
10
10
  license = "MIT"
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