rlmgrep 0.1.13__tar.gz → 0.1.14__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: rlmgrep
3
- Version: 0.1.13
3
+ Version: 0.1.14
4
4
  Summary: Grep-shaped CLI search powered by DSPy RLM
5
5
  Author: rlmgrep
6
6
  License: MIT
@@ -128,7 +128,7 @@ rg -l "token" . | rlmgrep --files-from-stdin --answer "What does this token cont
128
128
  ## Input selection
129
129
 
130
130
  - Directories are searched recursively by default. Use `--no-recursive` to stop recursion.
131
- - Hidden files and `.gitignore` rules are respected by default. Use `--hidden` or `--no-ignore` to include them.
131
+ - Hidden files and ignore files (`.gitignore`, `.ignore`, `.rgignore`) are respected by default. Use `--hidden` or `--no-ignore` to include them.
132
132
  - `--type` uses built-in type mappings (e.g., `py`, `js`, `md`); unknown values are treated as file extensions.
133
133
  - `-g/--glob` matches path globs against normalized paths (forward slashes).
134
134
  - Paths are printed relative to the current working directory when possible.
@@ -115,7 +115,7 @@ rg -l "token" . | rlmgrep --files-from-stdin --answer "What does this token cont
115
115
  ## Input selection
116
116
 
117
117
  - Directories are searched recursively by default. Use `--no-recursive` to stop recursion.
118
- - Hidden files and `.gitignore` rules are respected by default. Use `--hidden` or `--no-ignore` to include them.
118
+ - Hidden files and ignore files (`.gitignore`, `.ignore`, `.rgignore`) are respected by default. Use `--hidden` or `--no-ignore` to include them.
119
119
  - `--type` uses built-in type mappings (e.g., `py`, `js`, `md`); unknown values are treated as file extensions.
120
120
  - `-g/--glob` matches path globs against normalized paths (forward slashes).
121
121
  - Paths are printed relative to the current working directory when possible.
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "rlmgrep"
3
- version = "0.1.13"
3
+ version = "0.1.14"
4
4
  description = "Grep-shaped CLI search powered by DSPy RLM"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.11"
@@ -1,2 +1,2 @@
1
1
  __all__ = ["__version__"]
2
- __version__ = "0.1.13"
2
+ __version__ = "0.1.14"
@@ -11,7 +11,7 @@ from .config import ensure_default_config, load_config
11
11
  from .file_map import build_file_map
12
12
  from .ingest import (
13
13
  FileRecord,
14
- build_gitignore_spec,
14
+ build_ignore_spec,
15
15
  collect_candidates,
16
16
  load_files,
17
17
  resolve_type_exts,
@@ -88,7 +88,12 @@ def _parse_args(argv: list[str]) -> argparse.Namespace:
88
88
  parser.add_argument("-m", dest="max_count", type=int, default=None, help="Max matching lines per file")
89
89
  parser.add_argument("-a", "--text", dest="binary_as_text", action="store_true", help="Search binary files as text")
90
90
  parser.add_argument("--hidden", action="store_true", help="Include hidden files and directories")
91
- parser.add_argument("--no-ignore", dest="no_ignore", action="store_true", help="Do not respect .gitignore")
91
+ parser.add_argument(
92
+ "--no-ignore",
93
+ dest="no_ignore",
94
+ action="store_true",
95
+ help="Do not respect ignore files (.gitignore/.ignore/.rgignore)",
96
+ )
92
97
  parser.add_argument("--answer", action="store_true", help="Print a narrative answer before grep output")
93
98
  parser.add_argument("-y", "--yes", action="store_true", help="Skip file count confirmation")
94
99
  parser.add_argument(
@@ -147,11 +152,24 @@ def _pick(cli_value, config: dict, key: str, default=None):
147
152
  return default
148
153
 
149
154
 
150
- def _find_git_root(start: Path) -> Path | None:
155
+ def _find_git_root(start: Path) -> tuple[Path | None, Path | None]:
151
156
  for p in [start, *start.parents]:
152
- if (p / ".git").is_dir():
153
- return p
154
- return None
157
+ git_path = p / ".git"
158
+ if git_path.is_dir():
159
+ return p, git_path
160
+ if git_path.is_file():
161
+ try:
162
+ raw = git_path.read_text(encoding="utf-8", errors="ignore").strip()
163
+ except Exception:
164
+ raw = ""
165
+ if raw.startswith("gitdir:"):
166
+ git_dir = raw.split(":", 1)[1].strip()
167
+ git_dir_path = Path(git_dir)
168
+ if not git_dir_path.is_absolute():
169
+ git_dir_path = (p / git_dir_path).resolve()
170
+ return p, git_dir_path
171
+ return p, None
172
+ return None, None
155
173
 
156
174
 
157
175
  def _env_value(name: str) -> str | None:
@@ -442,8 +460,12 @@ def main(argv: list[str] | None = None) -> int:
442
460
  ignore_spec = None
443
461
  ignore_root = None
444
462
  if not args.no_ignore:
445
- ignore_root = _find_git_root(cwd) or cwd
446
- ignore_spec = build_gitignore_spec(ignore_root)
463
+ git_root, git_dir = _find_git_root(cwd)
464
+ ignore_root = git_root or cwd
465
+ extra_ignores: list[Path] = []
466
+ if git_dir is not None:
467
+ extra_ignores.append(git_dir / "info" / "exclude")
468
+ ignore_spec = build_ignore_spec(ignore_root, extra_paths=extra_ignores)
447
469
 
448
470
  candidates = collect_candidates(
449
471
  input_paths,
@@ -164,18 +164,28 @@ def collect_files(paths: Iterable[str], recursive: bool = True) -> list[Path]:
164
164
  return files
165
165
 
166
166
 
167
- def build_gitignore_spec(root: Path) -> "pathspec.PathSpec | None":
168
- if pathspec is None:
169
- return None
167
+ IGNORE_FILENAMES = {".gitignore", ".ignore", ".rgignore"}
168
+
169
+
170
+ def build_ignore_spec(
171
+ root: Path, extra_paths: Iterable[Path] | None = None
172
+ ) -> "pathspec.PathSpec | None":
170
173
  root = root.resolve()
171
- gitignore_paths: list[Path] = []
174
+ ignore_paths: list[Path] = []
175
+ extra_paths = list(extra_paths or [])
176
+
172
177
  for dirpath, dirnames, filenames in os.walk(root):
173
178
  if ".git" in dirnames:
174
179
  dirnames.remove(".git")
175
- if ".gitignore" in filenames:
176
- gitignore_paths.append(Path(dirpath) / ".gitignore")
180
+ for name in filenames:
181
+ if name in IGNORE_FILENAMES:
182
+ ignore_paths.append(Path(dirpath) / name)
177
183
 
178
- if not gitignore_paths:
184
+ for extra in extra_paths:
185
+ if extra.exists():
186
+ ignore_paths.append(extra)
187
+
188
+ if not ignore_paths:
179
189
  return None
180
190
 
181
191
  def _sort_key(p: Path) -> tuple[int, str]:
@@ -186,10 +196,10 @@ def build_gitignore_spec(root: Path) -> "pathspec.PathSpec | None":
186
196
  except ValueError:
187
197
  return 0, p.as_posix()
188
198
 
189
- gitignore_paths.sort(key=_sort_key)
199
+ ignore_paths.sort(key=_sort_key)
190
200
 
191
201
  patterns: list[str] = []
192
- for gi in gitignore_paths:
202
+ for gi in ignore_paths:
193
203
  try:
194
204
  rel_dir = gi.parent.relative_to(root).as_posix()
195
205
  except ValueError:
@@ -202,13 +212,18 @@ def build_gitignore_spec(root: Path) -> "pathspec.PathSpec | None":
202
212
  line = raw.rstrip("\n")
203
213
  if not line:
204
214
  continue
215
+ escaped = False
205
216
  if line.startswith("\\#") or line.startswith("\\!"):
206
217
  line = line[1:]
207
- elif line.startswith("#"):
218
+ escaped = True
219
+ if not escaped and line.startswith("#"):
208
220
  continue
209
- negated = line.startswith("!")
210
- if negated:
221
+ negated = False
222
+ if not escaped and line.startswith("!"):
223
+ negated = True
211
224
  line = line[1:]
225
+ if not line:
226
+ continue
212
227
  if line.startswith("/"):
213
228
  line = line[1:]
214
229
  if rel_dir:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: rlmgrep
3
- Version: 0.1.13
3
+ Version: 0.1.14
4
4
  Summary: Grep-shaped CLI search powered by DSPy RLM
5
5
  Author: rlmgrep
6
6
  License: MIT
@@ -128,7 +128,7 @@ rg -l "token" . | rlmgrep --files-from-stdin --answer "What does this token cont
128
128
  ## Input selection
129
129
 
130
130
  - Directories are searched recursively by default. Use `--no-recursive` to stop recursion.
131
- - Hidden files and `.gitignore` rules are respected by default. Use `--hidden` or `--no-ignore` to include them.
131
+ - Hidden files and ignore files (`.gitignore`, `.ignore`, `.rgignore`) are respected by default. Use `--hidden` or `--no-ignore` to include them.
132
132
  - `--type` uses built-in type mappings (e.g., `py`, `js`, `md`); unknown values are treated as file extensions.
133
133
  - `-g/--glob` matches path globs against normalized paths (forward slashes).
134
134
  - Paths are printed relative to the current working directory when possible.
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes