rlmgrep 0.1.3__tar.gz → 0.1.4__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.
- {rlmgrep-0.1.3 → rlmgrep-0.1.4}/PKG-INFO +7 -7
- {rlmgrep-0.1.3 → rlmgrep-0.1.4}/README.md +6 -6
- {rlmgrep-0.1.3 → rlmgrep-0.1.4}/pyproject.toml +1 -1
- {rlmgrep-0.1.3 → rlmgrep-0.1.4}/rlmgrep/__init__.py +1 -1
- {rlmgrep-0.1.3 → rlmgrep-0.1.4}/rlmgrep/cli.py +8 -4
- {rlmgrep-0.1.3 → rlmgrep-0.1.4}/rlmgrep/render.py +33 -15
- {rlmgrep-0.1.3 → rlmgrep-0.1.4}/rlmgrep/rlm.py +19 -1
- {rlmgrep-0.1.3 → rlmgrep-0.1.4}/rlmgrep.egg-info/PKG-INFO +7 -7
- {rlmgrep-0.1.3 → rlmgrep-0.1.4}/rlmgrep/__main__.py +0 -0
- {rlmgrep-0.1.3 → rlmgrep-0.1.4}/rlmgrep/config.py +0 -0
- {rlmgrep-0.1.3 → rlmgrep-0.1.4}/rlmgrep/file_map.py +0 -0
- {rlmgrep-0.1.3 → rlmgrep-0.1.4}/rlmgrep/ingest.py +0 -0
- {rlmgrep-0.1.3 → rlmgrep-0.1.4}/rlmgrep/interpreter.py +0 -0
- {rlmgrep-0.1.3 → rlmgrep-0.1.4}/rlmgrep.egg-info/SOURCES.txt +0 -0
- {rlmgrep-0.1.3 → rlmgrep-0.1.4}/rlmgrep.egg-info/dependency_links.txt +0 -0
- {rlmgrep-0.1.3 → rlmgrep-0.1.4}/rlmgrep.egg-info/entry_points.txt +0 -0
- {rlmgrep-0.1.3 → rlmgrep-0.1.4}/rlmgrep.egg-info/requires.txt +0 -0
- {rlmgrep-0.1.3 → rlmgrep-0.1.4}/rlmgrep.egg-info/top_level.txt +0 -0
- {rlmgrep-0.1.3 → rlmgrep-0.1.4}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: rlmgrep
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.4
|
|
4
4
|
Summary: Grep-shaped CLI search powered by DSPy RLM
|
|
5
5
|
Author: rlmgrep
|
|
6
6
|
License: MIT
|
|
@@ -61,8 +61,9 @@ rlmgrep [options] "query" [paths...]
|
|
|
61
61
|
|
|
62
62
|
Common options:
|
|
63
63
|
|
|
64
|
-
- `-n` show line numbers
|
|
65
|
-
-
|
|
64
|
+
- `-n` show line numbers (default)
|
|
65
|
+
- `--no-line-number` hide line numbers
|
|
66
|
+
- `-H` always show filenames (default)
|
|
66
67
|
- `-C N` context lines before/after (grep-style)
|
|
67
68
|
- `-A N` context lines after
|
|
68
69
|
- `-B N` context lines before
|
|
@@ -109,10 +110,9 @@ rg -l "token" . | rlmgrep --stdin-files --answer "what does this token control?"
|
|
|
109
110
|
## Output contract (stable for agents)
|
|
110
111
|
|
|
111
112
|
- Matches are written to stdout; warnings go to stderr.
|
|
112
|
-
- Output uses
|
|
113
|
-
-
|
|
114
|
-
- `
|
|
115
|
-
- If `-H` or `-n` are omitted, their parts are omitted.
|
|
113
|
+
- Output uses rg-style headings by default:
|
|
114
|
+
- A file header line like `./path/to/file`
|
|
115
|
+
- Then `line:\ttext` for matches, `line-\ttext` for context lines
|
|
116
116
|
- Line numbers are 1-based.
|
|
117
117
|
- When context ranges are disjoint, a `--` line separates groups.
|
|
118
118
|
- Exit codes:
|
|
@@ -49,8 +49,9 @@ rlmgrep [options] "query" [paths...]
|
|
|
49
49
|
|
|
50
50
|
Common options:
|
|
51
51
|
|
|
52
|
-
- `-n` show line numbers
|
|
53
|
-
-
|
|
52
|
+
- `-n` show line numbers (default)
|
|
53
|
+
- `--no-line-number` hide line numbers
|
|
54
|
+
- `-H` always show filenames (default)
|
|
54
55
|
- `-C N` context lines before/after (grep-style)
|
|
55
56
|
- `-A N` context lines after
|
|
56
57
|
- `-B N` context lines before
|
|
@@ -97,10 +98,9 @@ rg -l "token" . | rlmgrep --stdin-files --answer "what does this token control?"
|
|
|
97
98
|
## Output contract (stable for agents)
|
|
98
99
|
|
|
99
100
|
- Matches are written to stdout; warnings go to stderr.
|
|
100
|
-
- Output uses
|
|
101
|
-
-
|
|
102
|
-
- `
|
|
103
|
-
- If `-H` or `-n` are omitted, their parts are omitted.
|
|
101
|
+
- Output uses rg-style headings by default:
|
|
102
|
+
- A file header line like `./path/to/file`
|
|
103
|
+
- Then `line:\ttext` for matches, `line-\ttext` for context lines
|
|
104
104
|
- Line numbers are 1-based.
|
|
105
105
|
- When context ranges are disjoint, a `--` line separates groups.
|
|
106
106
|
- Exit codes:
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
__all__ = ["__version__"]
|
|
2
|
-
__version__ = "0.1.
|
|
2
|
+
__version__ = "0.1.4"
|
|
@@ -72,11 +72,12 @@ def _parse_args(argv: list[str]) -> argparse.Namespace:
|
|
|
72
72
|
parser.add_argument("pattern", nargs="?", help="Query string (interpreted by RLM)")
|
|
73
73
|
parser.add_argument("paths", nargs="*", help="Files or directories")
|
|
74
74
|
|
|
75
|
-
parser.add_argument("-n", dest="line_numbers", action="store_true", help="Show line numbers")
|
|
76
|
-
parser.add_argument("-
|
|
75
|
+
parser.add_argument("-n", dest="line_numbers", action="store_true", help="Show line numbers (default)")
|
|
76
|
+
parser.add_argument("--no-line-number", dest="line_numbers", action="store_false", help="Hide line numbers")
|
|
77
|
+
parser.add_argument("-H", dest="with_filename", action="store_true", help="Always show filenames (default)")
|
|
77
78
|
parser.add_argument("-r", dest="recursive", action="store_true", help="Recursive (directories are searched recursively by default)")
|
|
78
79
|
parser.add_argument("--no-recursive", dest="recursive", action="store_false", help="Do not recurse directories")
|
|
79
|
-
parser.set_defaults(recursive=True)
|
|
80
|
+
parser.set_defaults(recursive=True, line_numbers=True)
|
|
80
81
|
|
|
81
82
|
parser.add_argument("-C", dest="context", type=int, default=0, help="Context lines before/after")
|
|
82
83
|
parser.add_argument("-A", dest="after", type=int, default=None, help="Context lines after")
|
|
@@ -513,13 +514,16 @@ def main(argv: list[str] | None = None) -> int:
|
|
|
513
514
|
before = args.before if args.before is not None else args.context
|
|
514
515
|
after = args.after if args.after is not None else args.context
|
|
515
516
|
|
|
517
|
+
use_color = sys.stdout.isatty() and not os.getenv("NO_COLOR")
|
|
518
|
+
|
|
516
519
|
output_lines = render_matches(
|
|
517
520
|
files=files,
|
|
518
521
|
matches=verified,
|
|
519
522
|
show_line_numbers=args.line_numbers,
|
|
520
|
-
show_filename=args.with_filename,
|
|
521
523
|
before=before,
|
|
522
524
|
after=after,
|
|
525
|
+
use_color=use_color,
|
|
526
|
+
heading=True,
|
|
523
527
|
)
|
|
524
528
|
|
|
525
529
|
if args.answer:
|
|
@@ -2,22 +2,36 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
from .ingest import FileRecord
|
|
4
4
|
|
|
5
|
+
COLOR_RESET = "\x1b[0m"
|
|
6
|
+
COLOR_PATH = "\x1b[35m"
|
|
7
|
+
COLOR_LINE_NO = "\x1b[32m"
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def _colorize(text: str, color: str, use_color: bool) -> str:
|
|
11
|
+
if not use_color:
|
|
12
|
+
return text
|
|
13
|
+
return f"{color}{text}{COLOR_RESET}"
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def _format_heading(path: str, use_color: bool) -> str:
|
|
17
|
+
if not path.startswith((".", "/")):
|
|
18
|
+
path = f"./{path}"
|
|
19
|
+
return _colorize(path, COLOR_PATH, use_color)
|
|
20
|
+
|
|
5
21
|
|
|
6
22
|
def _format_line(
|
|
7
|
-
path: str,
|
|
8
23
|
line_no: int,
|
|
9
24
|
text: str,
|
|
10
25
|
is_match: bool,
|
|
11
|
-
show_filename: bool,
|
|
12
26
|
show_line_numbers: bool,
|
|
27
|
+
use_color: bool,
|
|
28
|
+
heading: bool,
|
|
13
29
|
) -> str:
|
|
14
30
|
delim = ":" if is_match else "-"
|
|
15
|
-
if show_filename and show_line_numbers:
|
|
16
|
-
return f"{path}{delim}{line_no}{delim}{text}"
|
|
17
|
-
if show_filename:
|
|
18
|
-
return f"{path}{delim}{text}"
|
|
19
31
|
if show_line_numbers:
|
|
20
|
-
|
|
32
|
+
prefix = _colorize(str(line_no), COLOR_LINE_NO, use_color)
|
|
33
|
+
sep = "\t" if heading else ""
|
|
34
|
+
return f"{prefix}{delim}{sep}{text}"
|
|
21
35
|
return text
|
|
22
36
|
|
|
23
37
|
|
|
@@ -39,18 +53,22 @@ def render_matches(
|
|
|
39
53
|
files: dict[str, FileRecord],
|
|
40
54
|
matches: dict[str, list[int]],
|
|
41
55
|
show_line_numbers: bool,
|
|
42
|
-
show_filename: bool,
|
|
43
56
|
before: int,
|
|
44
57
|
after: int,
|
|
58
|
+
use_color: bool = False,
|
|
59
|
+
heading: bool = True,
|
|
45
60
|
) -> list[str]:
|
|
46
61
|
output: list[str] = []
|
|
47
|
-
multiple_files = len(files) > 1
|
|
48
|
-
show_filename = show_filename or multiple_files
|
|
49
62
|
|
|
50
|
-
|
|
63
|
+
paths = sorted(matches.keys())
|
|
64
|
+
for idx, path in enumerate(paths):
|
|
51
65
|
record = files.get(path)
|
|
52
66
|
if record is None:
|
|
53
67
|
continue
|
|
68
|
+
if heading:
|
|
69
|
+
if idx > 0:
|
|
70
|
+
output.append("")
|
|
71
|
+
output.append(_format_heading(path, use_color))
|
|
54
72
|
lines = record.lines
|
|
55
73
|
page_map = record.page_map
|
|
56
74
|
n_lines = len(lines)
|
|
@@ -65,12 +83,12 @@ def render_matches(
|
|
|
65
83
|
text = f"{text}\tpage={page_map[line_no - 1]}"
|
|
66
84
|
output.append(
|
|
67
85
|
_format_line(
|
|
68
|
-
path,
|
|
69
86
|
line_no,
|
|
70
87
|
text,
|
|
71
88
|
True,
|
|
72
|
-
show_filename,
|
|
73
89
|
show_line_numbers,
|
|
90
|
+
use_color,
|
|
91
|
+
heading,
|
|
74
92
|
)
|
|
75
93
|
)
|
|
76
94
|
continue
|
|
@@ -90,12 +108,12 @@ def render_matches(
|
|
|
90
108
|
is_match = line_no in match_set
|
|
91
109
|
output.append(
|
|
92
110
|
_format_line(
|
|
93
|
-
path,
|
|
94
111
|
line_no,
|
|
95
112
|
text,
|
|
96
113
|
is_match,
|
|
97
|
-
show_filename,
|
|
98
114
|
show_line_numbers,
|
|
115
|
+
use_color,
|
|
116
|
+
heading,
|
|
99
117
|
)
|
|
100
118
|
)
|
|
101
119
|
if idx < len(merged) - 1:
|
|
@@ -24,6 +24,10 @@ class RLMGrepSignature(dspy.Signature):
|
|
|
24
24
|
find relevant lines. Return all relevant matches you can find, avoid duplicates,
|
|
25
25
|
and only use exact paths from the directory keys.
|
|
26
26
|
Always read the ASCII file map first to orient yourself to the available paths.
|
|
27
|
+
Do not wrap code in backticks; only raw Python.
|
|
28
|
+
Do not import pandas or numpy; use built-ins only.
|
|
29
|
+
|
|
30
|
+
Files like "photo.jpg.md" or "audio.mp3.md" are LLM descriptions/transcriptions of images/audio that were originally in the directory but have been converted to md to make them searchable by you.
|
|
27
31
|
"""
|
|
28
32
|
|
|
29
33
|
directory: dict = dspy.InputField(
|
|
@@ -52,7 +56,21 @@ class RLMGrepSignature(dspy.Signature):
|
|
|
52
56
|
|
|
53
57
|
class RLMGrepAnswerSignature(dspy.Signature):
|
|
54
58
|
"""
|
|
55
|
-
|
|
59
|
+
You are the search engine for rlmgrep, a grep-shaped CLI for coding agents.
|
|
60
|
+
Inputs include a directory mapping of files (path -> full text), an ASCII file
|
|
61
|
+
map, and a user query string. Your output must be grep-printable matches as
|
|
62
|
+
(path, line) pairs that point to real lines in the provided texts.
|
|
63
|
+
The query may be natural language or a short pattern; interpret it freely to
|
|
64
|
+
find relevant lines. Return all relevant matches you can find, avoid duplicates,
|
|
65
|
+
and only use exact paths from the directory keys.
|
|
66
|
+
Always read the ASCII file map first to orient yourself to the available paths.
|
|
67
|
+
Do not wrap code in backticks; only raw Python.
|
|
68
|
+
Do not import pandas or numpy; use built-ins only.
|
|
69
|
+
|
|
70
|
+
In this mode you are also responsible for generating a narrative answer to the query based on the provided files.
|
|
71
|
+
|
|
72
|
+
Files like "photo.jpg.md" or "audio.mp3.md" are LLM descriptions/transcriptions of images/audio that were originally in the directory but have been converted to md to make them searchable by you.
|
|
73
|
+
|
|
56
74
|
"""
|
|
57
75
|
|
|
58
76
|
directory: dict = dspy.InputField(
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: rlmgrep
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.4
|
|
4
4
|
Summary: Grep-shaped CLI search powered by DSPy RLM
|
|
5
5
|
Author: rlmgrep
|
|
6
6
|
License: MIT
|
|
@@ -61,8 +61,9 @@ rlmgrep [options] "query" [paths...]
|
|
|
61
61
|
|
|
62
62
|
Common options:
|
|
63
63
|
|
|
64
|
-
- `-n` show line numbers
|
|
65
|
-
-
|
|
64
|
+
- `-n` show line numbers (default)
|
|
65
|
+
- `--no-line-number` hide line numbers
|
|
66
|
+
- `-H` always show filenames (default)
|
|
66
67
|
- `-C N` context lines before/after (grep-style)
|
|
67
68
|
- `-A N` context lines after
|
|
68
69
|
- `-B N` context lines before
|
|
@@ -109,10 +110,9 @@ rg -l "token" . | rlmgrep --stdin-files --answer "what does this token control?"
|
|
|
109
110
|
## Output contract (stable for agents)
|
|
110
111
|
|
|
111
112
|
- Matches are written to stdout; warnings go to stderr.
|
|
112
|
-
- Output uses
|
|
113
|
-
-
|
|
114
|
-
- `
|
|
115
|
-
- If `-H` or `-n` are omitted, their parts are omitted.
|
|
113
|
+
- Output uses rg-style headings by default:
|
|
114
|
+
- A file header line like `./path/to/file`
|
|
115
|
+
- Then `line:\ttext` for matches, `line-\ttext` for context lines
|
|
116
116
|
- Line numbers are 1-based.
|
|
117
117
|
- When context ranges are disjoint, a `--` line separates groups.
|
|
118
118
|
- Exit codes:
|
|
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
|