rgapi 0.1.1__tar.gz → 0.1.2__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.
@@ -26,7 +26,8 @@ jobs:
26
26
  - uses: actions/setup-python@v5
27
27
  with:
28
28
  python-version: ${{ matrix.python }}
29
- - run: tools/build.sh release
29
+ - run: pip install fastship
30
+ - run: ship-rs-prep --release
30
31
  - uses: PyO3/maturin-action@v1
31
32
  with:
32
33
  command: build
@@ -1,3 +1,4 @@
1
+ dist/
1
2
  Cargo.lock
2
3
  tags
3
4
  /target/
@@ -306,7 +306,7 @@ checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4"
306
306
 
307
307
  [[package]]
308
308
  name = "rgapi"
309
- version = "0.1.1"
309
+ version = "0.1.2"
310
310
  dependencies = [
311
311
  "globset",
312
312
  "grep-matcher",
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "rgapi"
3
- version = "0.1.1"
3
+ version = "0.1.2"
4
4
  edition = "2021"
5
5
  license = "MIT OR Apache-2.0"
6
6
  description = "Python API for ripgrep-style file walking and searching"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: rgapi
3
- Version: 0.1.1
3
+ Version: 0.1.2
4
4
  Classifier: Programming Language :: Rust
5
5
  Classifier: Programming Language :: Python :: Implementation :: CPython
6
6
  Summary: Python API for ripgrep-style file walking and searching
@@ -54,6 +54,7 @@ pip install rgapi
54
54
  ## Semantics
55
55
 
56
56
  `fd` and `walk` return slash-separated paths relative to `root`. They use the `ignore` crate, so `.gitignore` and the usual ripgrep filters apply by default. Hidden files are skipped unless `hidden=True`. Pass `ignore=False` to disable ignore filtering. Symlinks are not followed unless `follow_links=True`; `same_file_system=True` avoids crossing filesystem boundaries. Traversal is parallel, and result order is not guaranteed; use `sorted(...)` if order matters.
57
+ `root` arguments accept `str` or `pathlib.Path` and expand `~`; `search_path` also accepts path-like file paths. Display labels such as `display_path` are stringified without expansion.
57
58
 
58
59
  `fd` adds fd-like filtering on top of `walk`: `pattern` is a substring match on the relative path, and `include`/`exclude` use glob syntax. `glob=` is accepted as an alias for `include=`. A basename glob such as `*.py` also matches recursively, so it finds `src/app.py`. Use `ext="py"` or `ext=["py", "rs"]` for extension filters, `min_depth=`/`max_depth=` to bound recursion, and `max_filesize=` to skip files above a byte limit.
59
60
 
@@ -73,12 +74,10 @@ matches list of (start, end) byte offsets for match rows
73
74
 
74
75
  `SearchLine` has a structured `repr`, an rg-style `str`, and `SearchLine.asdict()` returns row fields as a plain Python dict. `rg(..., paths=True)` returns unique matched paths, and `rg(..., count=True)` returns the total number of match spans. `paths` and `count` cannot both be set.
75
76
 
76
- `before_context`, `after_context`, and `context` match the shape of `rg -B`, `rg -A`, and `rg -C`. Files containing NUL bytes or invalid UTF-8 are skipped.
77
+ `before_context`, `after_context`, and `context` are like `rg -B`, `rg -A`, and `rg -C`. Files containing NUL bytes or invalid UTF-8 are skipped.
77
78
 
78
79
  Search is case-sensitive by default, matching `rg`. Use `smart_case=True` for `rg --smart-case` behavior, or `case_sensitive=False` to force case-insensitive matching.
79
80
 
80
- `rg` and `rg_iter` check Python signals while waiting for search results, so notebook interrupts and `KeyboardInterrupt` cancel traversal cooperatively. Cancellation is prompt between files and while results are streaming; a single huge file that produces no callbacks may continue until that file scan returns.
81
-
82
81
  ## Benchmarks
83
82
 
84
83
  `tools/bench.py` compares the `rg` CLI with in-process `rgapi`. Run it against a release build. One run on this machine, using best time from seven repeats:
@@ -39,6 +39,7 @@ pip install rgapi
39
39
  ## Semantics
40
40
 
41
41
  `fd` and `walk` return slash-separated paths relative to `root`. They use the `ignore` crate, so `.gitignore` and the usual ripgrep filters apply by default. Hidden files are skipped unless `hidden=True`. Pass `ignore=False` to disable ignore filtering. Symlinks are not followed unless `follow_links=True`; `same_file_system=True` avoids crossing filesystem boundaries. Traversal is parallel, and result order is not guaranteed; use `sorted(...)` if order matters.
42
+ `root` arguments accept `str` or `pathlib.Path` and expand `~`; `search_path` also accepts path-like file paths. Display labels such as `display_path` are stringified without expansion.
42
43
 
43
44
  `fd` adds fd-like filtering on top of `walk`: `pattern` is a substring match on the relative path, and `include`/`exclude` use glob syntax. `glob=` is accepted as an alias for `include=`. A basename glob such as `*.py` also matches recursively, so it finds `src/app.py`. Use `ext="py"` or `ext=["py", "rs"]` for extension filters, `min_depth=`/`max_depth=` to bound recursion, and `max_filesize=` to skip files above a byte limit.
44
45
 
@@ -58,12 +59,10 @@ matches list of (start, end) byte offsets for match rows
58
59
 
59
60
  `SearchLine` has a structured `repr`, an rg-style `str`, and `SearchLine.asdict()` returns row fields as a plain Python dict. `rg(..., paths=True)` returns unique matched paths, and `rg(..., count=True)` returns the total number of match spans. `paths` and `count` cannot both be set.
60
61
 
61
- `before_context`, `after_context`, and `context` match the shape of `rg -B`, `rg -A`, and `rg -C`. Files containing NUL bytes or invalid UTF-8 are skipped.
62
+ `before_context`, `after_context`, and `context` are like `rg -B`, `rg -A`, and `rg -C`. Files containing NUL bytes or invalid UTF-8 are skipped.
62
63
 
63
64
  Search is case-sensitive by default, matching `rg`. Use `smart_case=True` for `rg --smart-case` behavior, or `case_sensitive=False` to force case-insensitive matching.
64
65
 
65
- `rg` and `rg_iter` check Python signals while waiting for search results, so notebook interrupts and `KeyboardInterrupt` cancel traversal cooperatively. Cancellation is prompt between files and while results are streaming; a single huge file that produces no callbacks may continue until that file scan returns.
66
-
67
66
  ## Benchmarks
68
67
 
69
68
  `tools/bench.py` compares the `rg` CLI with in-process `rgapi`. Run it against a release build. One run on this machine, using best time from seven repeats:
@@ -4,7 +4,7 @@ build-backend = "maturin"
4
4
 
5
5
  [project]
6
6
  name = "rgapi"
7
- version = "0.1.1"
7
+ version = "0.1.2"
8
8
  description = "Python API for ripgrep-style file walking and searching"
9
9
  license = {text = "MIT OR Apache-2.0"}
10
10
  requires-python = ">=3.10"
@@ -24,3 +24,9 @@ Issues = "https://github.com/AnswerDotAI/rgapi/issues"
24
24
  features = ["extension-module"]
25
25
  python-source = "python"
26
26
  module-name = "rgapi._core"
27
+
28
+ [tool.fastship]
29
+ branch = "main"
30
+
31
+ [tool.fastship.rs]
32
+ bins = []
@@ -0,0 +1,211 @@
1
+ from os import fspath
2
+ from pathlib import Path
3
+
4
+ from . import _core
5
+
6
+ Regex = _core.Regex
7
+ SearchLine = _core.SearchLine
8
+ RgIter = _core.RgIter
9
+ def compile(
10
+ pattern:str, # Regex pattern to compile
11
+ case_sensitive:bool|None=None, # True/False forces case; None allows `smart_case`
12
+ smart_case:bool=False # Match `rg --smart-case` behavior
13
+ ) -> Regex:
14
+ "Compile a regex matcher for `search_text`, `search_path`, and direct matching."
15
+ return _core.compile(pattern, case_sensitive=case_sensitive, smart_case=smart_case)
16
+
17
+ class SearchResults(list):
18
+ "List of `SearchLine` rows with rg-style text display."
19
+ def __str__(self): return "\n".join(map(str, self))
20
+ def _repr_pretty_(self, p, cycle): p.text("..." if cycle else str(self))
21
+
22
+
23
+ def _listify(value):
24
+ if value is None: return []
25
+ if isinstance(value, str): return [value]
26
+ return list(value)
27
+ def _fs_path(path): return str(Path(path).expanduser())
28
+ def _display_path(path): return None if path is None else fspath(path)
29
+ def _filters(glob=None, include=None, exclude=None, ext=None):
30
+ includes = _listify(include) + _listify(glob)
31
+ for suffix in _listify(ext):
32
+ suffix = str(suffix)
33
+ if suffix.startswith("."): suffix = suffix[1:]
34
+ includes.append(f"*.{suffix}")
35
+ return includes, _listify(exclude)
36
+
37
+
38
+ def _context(context, before_context, after_context):
39
+ if context: return context, context
40
+ return before_context, after_context
41
+
42
+
43
+ def walk(
44
+ root:str|Path=".", # Directory to walk (expands `~`)
45
+ hidden:bool=False, # Include hidden files and directories
46
+ ignore:bool=True, # Respect `.gitignore` and other ignore files
47
+ max_depth:int|None=None, # Maximum directory depth to descend
48
+ min_depth:int|None=None, # Minimum depth for returned paths
49
+ max_filesize:int|None=None, # Skip files larger than this many bytes
50
+ follow_links:bool=False, # Follow symbolic links while walking
51
+ same_file_system:bool=False, # Do not cross filesystem boundaries
52
+ path_re:str|None=None, # Regex that returned relative paths must match
53
+ skip_path_re:str|None=None, # Regex for relative paths to skip
54
+ skip_dir=None, # Directory glob or globs to prune
55
+ skip_dir_re:str|None=None, # Directory regex used to prune traversal
56
+ files:bool=True, # Include files in results
57
+ dirs:bool=False # Include directories in results
58
+ ) -> list[str]:
59
+ "Walk a directory and return relative file and/or directory paths."
60
+ return _core.walk(_fs_path(root), hidden, ignore, max_depth, min_depth, max_filesize, follow_links,
61
+ same_file_system, path_re, skip_path_re, _listify(skip_dir), skip_dir_re, files, dirs)
62
+
63
+
64
+ def fd(
65
+ root:str|Path=".", # Directory to walk (expands `~`)
66
+ pattern:str|None=None, # Substring that relative paths must contain
67
+ glob=None, # Include glob or globs; alias for `include`
68
+ include=None, # Include glob or globs, e.g. `*.py`
69
+ exclude=None, # Exclude glob or globs, e.g. `test_*.py`
70
+ ext=None, # Extension or extensions to include, without needing `*.`
71
+ hidden:bool=False, # Include hidden files and directories
72
+ ignore:bool=True, # Respect `.gitignore` and other ignore files
73
+ max_depth:int|None=None, # Maximum directory depth to descend
74
+ min_depth:int|None=None, # Minimum depth for returned paths
75
+ max_filesize:int|None=None, # Skip files larger than this many bytes
76
+ follow_links:bool=False, # Follow symbolic links while walking
77
+ same_file_system:bool=False, # Do not cross filesystem boundaries
78
+ path_re:str|None=None, # Regex that returned relative paths must match
79
+ skip_path_re:str|None=None, # Regex for relative paths to skip
80
+ skip_dir=None, # Directory glob or globs to prune
81
+ skip_dir_re:str|None=None, # Directory regex used to prune traversal
82
+ files:bool=True, # Include files in results
83
+ dirs:bool=False # Include directories in results
84
+ ) -> list[str]:
85
+ "Find paths with fd-style filters and gitignore support."
86
+ include, exclude = _filters(glob, include, exclude, ext)
87
+ return _core.find(_fs_path(root), pattern, include, exclude, hidden, ignore, max_depth, min_depth, max_filesize,
88
+ follow_links, same_file_system, path_re, skip_path_re, _listify(skip_dir), skip_dir_re, files, dirs)
89
+
90
+
91
+ def _rg_args(pattern, root, glob, include, exclude, ext, hidden, ignore, max_depth, min_depth, max_filesize,
92
+ follow_links, same_file_system, path_re, skip_path_re, skip_dir, skip_dir_re, case_sensitive, smart_case,
93
+ before_context, after_context, context):
94
+ include, exclude = _filters(glob, include, exclude, ext)
95
+ before_context, after_context = _context(context, before_context, after_context)
96
+ return (pattern, _fs_path(root), include, exclude, hidden, ignore, max_depth, min_depth, max_filesize, follow_links, same_file_system,
97
+ path_re, skip_path_re, _listify(skip_dir), skip_dir_re, case_sensitive, smart_case, before_context, after_context)
98
+
99
+
100
+ def rg(
101
+ pattern:str, # Regex pattern to search for
102
+ root:str|Path=".", # Directory to search (expands `~`)
103
+ glob=None, # Include glob or globs; alias for `include`
104
+ include=None, # Include glob or globs, e.g. `*.py`
105
+ exclude=None, # Exclude glob or globs, e.g. `test_*.py`
106
+ ext=None, # Extension or extensions to include, without needing `*.`
107
+ hidden:bool=False, # Include hidden files and directories
108
+ ignore:bool=True, # Respect `.gitignore` and other ignore files
109
+ max_depth:int|None=None, # Maximum directory depth to descend
110
+ min_depth:int|None=None, # Minimum depth for returned/searched files
111
+ max_filesize:int|None=None, # Skip files larger than this many bytes
112
+ follow_links:bool=False, # Follow symbolic links while walking
113
+ same_file_system:bool=False, # Do not cross filesystem boundaries
114
+ path_re:str|None=None, # Regex that searched relative paths must match
115
+ skip_path_re:str|None=None, # Regex for relative paths to skip
116
+ skip_dir=None, # Directory glob or globs to prune
117
+ skip_dir_re:str|None=None, # Directory regex used to prune traversal
118
+ case_sensitive:bool|None=None, # True/False forces case; None allows `smart_case`
119
+ smart_case:bool=False, # Match `rg --smart-case` behavior
120
+ before_context:int=0, # Lines of context before each match, like `rg -B`
121
+ after_context:int=0, # Lines of context after each match, like `rg -A`
122
+ context:int=0, # Sets both before and after context, like `rg -C`
123
+ paths:bool=False, # Return unique matched paths instead of rows
124
+ count:bool=False # Return total match span count instead of rows
125
+ ):
126
+ "Search files and return `SearchResults`, matched paths, or a count."
127
+ assert not (paths and count), "paths and count are mutually exclusive"
128
+ args = _rg_args(pattern, root, glob, include, exclude, ext, hidden, ignore, max_depth, min_depth, max_filesize,
129
+ follow_links, same_file_system, path_re, skip_path_re, skip_dir, skip_dir_re, case_sensitive, smart_case,
130
+ before_context, after_context, context)
131
+ if paths:
132
+ seen, res = set(), []
133
+ for row in _core.rg_iter(*args):
134
+ if row.kind != "match" or row.path in seen: continue
135
+ seen.add(row.path)
136
+ res.append(row.path)
137
+ return res
138
+ if count: return sum(len(row.matches) for row in _core.rg_iter(*args) if row.kind == "match")
139
+ return SearchResults(_core.rg(*args))
140
+
141
+
142
+ def rg_iter(
143
+ pattern:str, # Regex pattern to search for
144
+ root:str|Path=".", # Directory to search (expands `~`)
145
+ glob=None, # Include glob or globs; alias for `include`
146
+ include=None, # Include glob or globs, e.g. `*.py`
147
+ exclude=None, # Exclude glob or globs, e.g. `test_*.py`
148
+ ext=None, # Extension or extensions to include, without needing `*.`
149
+ hidden:bool=False, # Include hidden files and directories
150
+ ignore:bool=True, # Respect `.gitignore` and other ignore files
151
+ max_depth:int|None=None, # Maximum directory depth to descend
152
+ min_depth:int|None=None, # Minimum depth for returned/searched files
153
+ max_filesize:int|None=None, # Skip files larger than this many bytes
154
+ follow_links:bool=False, # Follow symbolic links while walking
155
+ same_file_system:bool=False, # Do not cross filesystem boundaries
156
+ path_re:str|None=None, # Regex that searched relative paths must match
157
+ skip_path_re:str|None=None, # Regex for relative paths to skip
158
+ skip_dir=None, # Directory glob or globs to prune
159
+ skip_dir_re:str|None=None, # Directory regex used to prune traversal
160
+ case_sensitive:bool|None=None, # True/False forces case; None allows `smart_case`
161
+ smart_case:bool=False, # Match `rg --smart-case` behavior
162
+ before_context:int=0, # Lines of context before each match, like `rg -B`
163
+ after_context:int=0, # Lines of context after each match, like `rg -A`
164
+ context:int=0 # Sets both before and after context, like `rg -C`
165
+ ) -> RgIter:
166
+ "Search files lazily, yielding `SearchLine` rows."
167
+ args = _rg_args(pattern, root, glob, include, exclude, ext, hidden, ignore, max_depth, min_depth, max_filesize,
168
+ follow_links, same_file_system, path_re, skip_path_re, skip_dir, skip_dir_re, case_sensitive, smart_case,
169
+ before_context, after_context, context)
170
+ return _core.rg_iter(*args)
171
+
172
+
173
+ def search_text(
174
+ matcher:Regex, # Compiled `Regex` from `compile()`
175
+ text:str, # Text to search
176
+ path:str|Path="<text>", # Path label stored in results
177
+ before_context:int=0, # Lines of context before each match
178
+ after_context:int=0, # Lines of context after each match
179
+ context:int=0 # Sets both before and after context, like `rg -C`
180
+ ) -> SearchResults:
181
+ "Search an in-memory string with a compiled matcher."
182
+ before_context, after_context = _context(context, before_context, after_context)
183
+ return SearchResults(_core.search_text(matcher, text, _display_path(path), before_context, after_context))
184
+
185
+
186
+ def search_path(
187
+ matcher:Regex, # Compiled `Regex` from `compile()`
188
+ path:str|Path, # File path to search (expands `~`)
189
+ display_path:str|Path|None=None, # Path stored in results; defaults to `path`
190
+ before_context:int=0, # Lines of context before each match
191
+ after_context:int=0, # Lines of context after each match
192
+ context:int=0 # Sets both before and after context, like `rg -C`
193
+ ) -> SearchResults:
194
+ "Search one file with a compiled matcher."
195
+ before_context, after_context = _context(context, before_context, after_context)
196
+ return SearchResults(_core.search_path(matcher, _fs_path(path), _display_path(display_path), before_context, after_context))
197
+
198
+
199
+ __all__ = [
200
+ "Regex",
201
+ "RgIter",
202
+ "SearchLine",
203
+ "SearchResults",
204
+ "compile",
205
+ "fd",
206
+ "rg",
207
+ "rg_iter",
208
+ "search_path",
209
+ "search_text",
210
+ "walk",
211
+ ]
@@ -35,6 +35,21 @@ def test_fd_is_relative_and_respects_ignore_hidden_and_globs(tmp_path):
35
35
  assert set(fd(str(tmp_path), exclude="*.py")) == {"bad.txt", "bin.dat"}
36
36
  assert set(walk(str(tmp_path), files=True, dirs=False)) == found
37
37
 
38
+ def test_pathlike_arguments_and_expanduser(tmp_path, monkeypatch):
39
+ make_tree(tmp_path)
40
+ assert "src/app.py" in fd(tmp_path)
41
+ assert walk(tmp_path, path_re=r"\.py$") == ["src/app.py"]
42
+ assert [r.path for r in rg("TODO", tmp_path, include="*.py")] == ["src/app.py"]
43
+ assert list(rg_iter("TODO", tmp_path, include="*.py")) == rg("TODO", tmp_path, include="*.py")
44
+ matcher = compile("TODO")
45
+ text_label = tmp_path / "memory.txt"
46
+ assert search_text(matcher, "TODO\n", path=text_label)[0].path == str(text_label)
47
+ display = tmp_path / "display.py"
48
+ assert search_path(matcher, tmp_path / "src" / "app.py", display_path=display)[0].path == str(display)
49
+
50
+ monkeypatch.setenv("HOME", str(tmp_path))
51
+ assert fd("~", glob="*.py") == ["src/app.py"]
52
+
38
53
 
39
54
  def test_path_filters_prune_dirs_and_follow_links(tmp_path):
40
55
  (tmp_path / "src").mkdir()
@@ -1,208 +0,0 @@
1
- from . import _core
2
-
3
- Regex = _core.Regex
4
- SearchLine = _core.SearchLine
5
- RgIter = _core.RgIter
6
- def compile(
7
- pattern, # Regex pattern to compile
8
- case_sensitive=None, # True/False forces case; None allows `smart_case`
9
- smart_case=False # Match `rg --smart-case` behavior
10
- ):
11
- "Compile a regex matcher for `search_text`, `search_path`, and direct matching."
12
- return _core.compile(pattern, case_sensitive=case_sensitive, smart_case=smart_case)
13
-
14
- class SearchResults(list):
15
- "List of `SearchLine` rows with rg-style text display."
16
- def __str__(self): return "\n".join(map(str, self))
17
- def _repr_pretty_(self, p, cycle): p.text("..." if cycle else str(self))
18
-
19
-
20
- def _listify(value):
21
- if value is None: return []
22
- if isinstance(value, str): return [value]
23
- return list(value)
24
-
25
-
26
- def _filters(glob=None, include=None, exclude=None, ext=None):
27
- includes = _listify(include) + _listify(glob)
28
- for suffix in _listify(ext):
29
- suffix = str(suffix)
30
- if suffix.startswith("."): suffix = suffix[1:]
31
- includes.append(f"*.{suffix}")
32
- return includes, _listify(exclude)
33
-
34
-
35
- def _context(context, before_context, after_context):
36
- if context: return context, context
37
- return before_context, after_context
38
-
39
-
40
- def walk(
41
- root=".", # Directory to walk
42
- hidden=False, # Include hidden files and directories
43
- ignore=True, # Respect `.gitignore` and other ignore files
44
- max_depth=None, # Maximum directory depth to descend
45
- min_depth=None, # Minimum depth for returned paths
46
- max_filesize=None, # Skip files larger than this many bytes
47
- follow_links=False, # Follow symbolic links while walking
48
- same_file_system=False, # Do not cross filesystem boundaries
49
- path_re=None, # Regex that returned relative paths must match
50
- skip_path_re=None, # Regex for relative paths to skip
51
- skip_dir=None, # Directory glob or globs to prune
52
- skip_dir_re=None, # Directory regex used to prune traversal
53
- files=True, # Include files in results
54
- dirs=False # Include directories in results
55
- ):
56
- "Walk a directory and return relative file and/or directory paths."
57
- return _core.walk(root, hidden, ignore, max_depth, min_depth, max_filesize, follow_links,
58
- same_file_system, path_re, skip_path_re, _listify(skip_dir), skip_dir_re, files, dirs)
59
-
60
-
61
- def fd(
62
- root=".", # Directory to walk
63
- pattern=None, # Substring that relative paths must contain
64
- glob=None, # Include glob or globs; alias for `include`
65
- include=None, # Include glob or globs, e.g. `*.py`
66
- exclude=None, # Exclude glob or globs, e.g. `test_*.py`
67
- ext=None, # Extension or extensions to include, without needing `*.`
68
- hidden=False, # Include hidden files and directories
69
- ignore=True, # Respect `.gitignore` and other ignore files
70
- max_depth=None, # Maximum directory depth to descend
71
- min_depth=None, # Minimum depth for returned paths
72
- max_filesize=None, # Skip files larger than this many bytes
73
- follow_links=False, # Follow symbolic links while walking
74
- same_file_system=False, # Do not cross filesystem boundaries
75
- path_re=None, # Regex that returned relative paths must match
76
- skip_path_re=None, # Regex for relative paths to skip
77
- skip_dir=None, # Directory glob or globs to prune
78
- skip_dir_re=None, # Directory regex used to prune traversal
79
- files=True, # Include files in results
80
- dirs=False # Include directories in results
81
- ):
82
- "Find paths with fd-style filters and gitignore support."
83
- include, exclude = _filters(glob, include, exclude, ext)
84
- return _core.find(root, pattern, include, exclude, hidden, ignore, max_depth, min_depth, max_filesize,
85
- follow_links, same_file_system, path_re, skip_path_re, _listify(skip_dir), skip_dir_re, files, dirs)
86
-
87
-
88
- def _rg_args(pattern, root, glob, include, exclude, ext, hidden, ignore, max_depth, min_depth, max_filesize,
89
- follow_links, same_file_system, path_re, skip_path_re, skip_dir, skip_dir_re, case_sensitive, smart_case,
90
- before_context, after_context, context):
91
- include, exclude = _filters(glob, include, exclude, ext)
92
- before_context, after_context = _context(context, before_context, after_context)
93
- return (pattern, root, include, exclude, hidden, ignore, max_depth, min_depth, max_filesize, follow_links, same_file_system,
94
- path_re, skip_path_re, _listify(skip_dir), skip_dir_re, case_sensitive, smart_case, before_context, after_context)
95
-
96
-
97
- def rg(
98
- pattern, # Regex pattern to search for
99
- root=".", # Directory to search
100
- glob=None, # Include glob or globs; alias for `include`
101
- include=None, # Include glob or globs, e.g. `*.py`
102
- exclude=None, # Exclude glob or globs, e.g. `test_*.py`
103
- ext=None, # Extension or extensions to include, without needing `*.`
104
- hidden=False, # Include hidden files and directories
105
- ignore=True, # Respect `.gitignore` and other ignore files
106
- max_depth=None, # Maximum directory depth to descend
107
- min_depth=None, # Minimum depth for returned/searched files
108
- max_filesize=None, # Skip files larger than this many bytes
109
- follow_links=False, # Follow symbolic links while walking
110
- same_file_system=False, # Do not cross filesystem boundaries
111
- path_re=None, # Regex that searched relative paths must match
112
- skip_path_re=None, # Regex for relative paths to skip
113
- skip_dir=None, # Directory glob or globs to prune
114
- skip_dir_re=None, # Directory regex used to prune traversal
115
- case_sensitive=None, # True/False forces case; None allows `smart_case`
116
- smart_case=False, # Match `rg --smart-case` behavior
117
- before_context=0, # Lines of context before each match, like `rg -B`
118
- after_context=0, # Lines of context after each match, like `rg -A`
119
- context=0, # Sets both before and after context, like `rg -C`
120
- paths=False, # Return unique matched paths instead of rows
121
- count=False # Return total match span count instead of rows
122
- ):
123
- "Search files and return `SearchResults`, matched paths, or a count."
124
- assert not (paths and count), "paths and count are mutually exclusive"
125
- args = _rg_args(pattern, root, glob, include, exclude, ext, hidden, ignore, max_depth, min_depth, max_filesize,
126
- follow_links, same_file_system, path_re, skip_path_re, skip_dir, skip_dir_re, case_sensitive, smart_case,
127
- before_context, after_context, context)
128
- if paths:
129
- seen, res = set(), []
130
- for row in _core.rg_iter(*args):
131
- if row.kind != "match" or row.path in seen: continue
132
- seen.add(row.path)
133
- res.append(row.path)
134
- return res
135
- if count: return sum(len(row.matches) for row in _core.rg_iter(*args) if row.kind == "match")
136
- return SearchResults(_core.rg(*args))
137
-
138
-
139
- def rg_iter(
140
- pattern, # Regex pattern to search for
141
- root=".", # Directory to search
142
- glob=None, # Include glob or globs; alias for `include`
143
- include=None, # Include glob or globs, e.g. `*.py`
144
- exclude=None, # Exclude glob or globs, e.g. `test_*.py`
145
- ext=None, # Extension or extensions to include, without needing `*.`
146
- hidden=False, # Include hidden files and directories
147
- ignore=True, # Respect `.gitignore` and other ignore files
148
- max_depth=None, # Maximum directory depth to descend
149
- min_depth=None, # Minimum depth for returned/searched files
150
- max_filesize=None, # Skip files larger than this many bytes
151
- follow_links=False, # Follow symbolic links while walking
152
- same_file_system=False, # Do not cross filesystem boundaries
153
- path_re=None, # Regex that searched relative paths must match
154
- skip_path_re=None, # Regex for relative paths to skip
155
- skip_dir=None, # Directory glob or globs to prune
156
- skip_dir_re=None, # Directory regex used to prune traversal
157
- case_sensitive=None, # True/False forces case; None allows `smart_case`
158
- smart_case=False, # Match `rg --smart-case` behavior
159
- before_context=0, # Lines of context before each match, like `rg -B`
160
- after_context=0, # Lines of context after each match, like `rg -A`
161
- context=0 # Sets both before and after context, like `rg -C`
162
- ):
163
- "Search files lazily, yielding `SearchLine` rows."
164
- args = _rg_args(pattern, root, glob, include, exclude, ext, hidden, ignore, max_depth, min_depth, max_filesize,
165
- follow_links, same_file_system, path_re, skip_path_re, skip_dir, skip_dir_re, case_sensitive, smart_case,
166
- before_context, after_context, context)
167
- return _core.rg_iter(*args)
168
-
169
-
170
- def search_text(
171
- matcher, # Compiled `Regex` from `compile()`
172
- text, # Text to search
173
- path="<text>", # Path label stored in results
174
- before_context=0, # Lines of context before each match
175
- after_context=0, # Lines of context after each match
176
- context=0 # Sets both before and after context, like `rg -C`
177
- ):
178
- "Search an in-memory string with a compiled matcher."
179
- before_context, after_context = _context(context, before_context, after_context)
180
- return SearchResults(_core.search_text(matcher, text, path, before_context, after_context))
181
-
182
-
183
- def search_path(
184
- matcher, # Compiled `Regex` from `compile()`
185
- path, # File path to search
186
- display_path=None, # Path stored in results; defaults to `path`
187
- before_context=0, # Lines of context before each match
188
- after_context=0, # Lines of context after each match
189
- context=0 # Sets both before and after context, like `rg -C`
190
- ):
191
- "Search one file with a compiled matcher."
192
- before_context, after_context = _context(context, before_context, after_context)
193
- return SearchResults(_core.search_path(matcher, path, display_path, before_context, after_context))
194
-
195
-
196
- __all__ = [
197
- "Regex",
198
- "RgIter",
199
- "SearchLine",
200
- "SearchResults",
201
- "compile",
202
- "fd",
203
- "rg",
204
- "rg_iter",
205
- "search_path",
206
- "search_text",
207
- "walk",
208
- ]
@@ -1,5 +0,0 @@
1
- #!/bin/bash
2
- set -e
3
- profile=${1:-debug}
4
- if [ "$profile" = "release" ]; then flags="--release"; else flags=""; fi
5
- cargo build $flags
rgapi-0.1.1/tools/bump.sh DELETED
@@ -1,6 +0,0 @@
1
- #!/bin/bash
2
- set -e
3
- cur=$(grep '^version = ' pyproject.toml | head -1 | sed 's/version = "\(.*\)"/\1/')
4
- new=$(echo "$cur" | awk -F. '{print $1"."$2"."$3+1}')
5
- sed -i '' "s/^version = \"$cur\"/version = \"$new\"/" pyproject.toml Cargo.toml
6
- echo "$cur -> $new"
@@ -1,6 +0,0 @@
1
- #!/bin/bash
2
- set -e
3
- cur=$(grep '^version = ' pyproject.toml | head -1 | sed 's/version = "\(.*\)"/\1/')
4
- new=$(echo "$cur" | awk -F. '{print $1"."$2+1"."0}')
5
- sed -i '' "s/^version = \"$cur\"/version = \"$new\"/" pyproject.toml Cargo.toml
6
- echo "$cur -> $new"
@@ -1,6 +0,0 @@
1
- #!/bin/bash
2
- set -e
3
- v=$(grep '^version = ' pyproject.toml | head -1 | sed 's/version = "\(.*\)"/\1/')
4
- git tag "v$v"
5
- git push origin main --tags
6
- echo "Released v$v"
rgapi-0.1.1/tools/test.sh DELETED
@@ -1,4 +0,0 @@
1
- #!/bin/bash
2
- set -e
3
- cargo test
4
- pytest -q
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes