Alles, was dein Agent kennt, funktioniert weiter
Was du davon hast
Dein Agent arbeitet mit grep und ripgrep. Mit greppy behält er beides: greppy -rn MUSTER . ist grep, greppy rg … ist ripgrep, Ausgabe und Exit-Code sind dieselben. Dazu bekommt er greppys Befehle für Graph, Suche, Lesen und Ändern. Ein Werkzeug für alles, und kein gewohnter Aufruf bricht.
Vorher und nachher
Die Frage an serde: Wo stehen die Traits, die mit pub trait Deserialize beginnen?
Mit grep
$ grep -rn "pub trait Deserialize" --include=*.rs .
./serde_core/src/de/mod.rs:554:pub trait Deserialize<'de>: Sized {
./serde_core/src/de/mod.rs:632:pub trait DeserializeOwned: for<'de> Deserialize<'de> {}
./serde_core/src/de/mod.rs:803:pub trait DeserializeSeed<'de>: Sized {
./serde_core/src/de/mod.rs:945:pub trait Deserializer<'de>: Sized {
./test_suite/tests/test_serde_path.rs:38: pub trait Deserialize<'a>: Sized {
Mit greppy
$ greppy -rn "pub trait Deserialize" --include=*.rs .
./serde_core/src/de/mod.rs:554:pub trait Deserialize<'de>: Sized {
./serde_core/src/de/mod.rs:632:pub trait DeserializeOwned: for<'de> Deserialize<'de> {}
./serde_core/src/de/mod.rs:803:pub trait DeserializeSeed<'de>: Sized {
./serde_core/src/de/mod.rs:945:pub trait Deserializer<'de>: Sized {
./test_suite/tests/test_serde_path.rs:38: pub trait Deserialize<'a>: Sized {
Byte für Byte
cmp vergleicht beide Ausgaben, für grep und für ripgrep.
$ grep -rn "pub trait Deserialize" --include=*.rs . > grep.out; echo "exit $?"
exit 0
$ greppy -rn "pub trait Deserialize" --include=*.rs . > greppy.out; echo "exit $?"
exit 0
$ cmp grep.out greppy.out && echo identisch
identisch
$ rg -n -t rust --sort path "pub trait Deserialize" . > rg.out; echo "exit $?"
exit 0
$ greppy rg -n -t rust --sort path "pub trait Deserialize" . > greppy-rg.out; echo "exit $?"
exit 0
$ cmp rg.out greppy-rg.out && echo identisch
identisch
Dasselbe gilt für Fehlerfälle, Pipes und ripgrep-Flags. Jeder Fall lief einmal direkt und einmal über greppy, stdout und stderr getrennt verglichen:
| Fall | Aufruf über greppy | Exit direkt / über greppy | stdout und stderr |
|---|---|---|---|
| Treffer, 374 Byte | greppy -rn "pub trait Deserialize" --include=*.rs . |
0 / 0 | identisch |
| kein Treffer | greppy -rn "no_such_symbol_xyz" --include=*.rs . |
1 / 1 | identisch |
| Datei fehlt | greppy -n "Deserialize" does/not/exist.rs |
2 / 2 | identisch, auch die Meldung grep: does/not/exist.rs: No such file or directory |
| Pipe auf stdin | cat serde_core/src/de/mod.rs | greppy -c "fn deserialize" |
0 / 0 | identisch (38) |
führendes grep-Wort |
greppy grep -rlw visit_content_map serde |
0 / 0 | identisch |
| ripgrep | greppy rg -n -t rust --sort path "pub trait Deserialize" |
0 / 0 | identisch |
ripgrep-Flags ohne rg-Wort |
greppy --smart-case -t rust --sort path "pub trait deserialize" |
0 / 0 | identisch |
Wo greppy eingreift
greppy reicht echte grep-Aufrufe weiter. Zwei Fälle erkennt es vorher und sagt, was gemeint ist, statt grep etwas Falsches suchen zu lassen.
$ greppy -rn "visit_content_map" --code serde
`--code` is a greppy flag, not a grep flag - it belongs to greppy's navigation commands. Drop it, or name the command it goes with.
$ greppy who-call visit_content_map
status: invalid_invocation
command: `who-call`
message: unknown greppy command; nothing was passed to grep
next: did you mean `greppy who-calls ...`?
Beide enden mit Exit 64. Ein führendes -p startet den eingebauten Agenten; für das Muster -p schreibst du greppy -e -p DATEI, mit derselben Ausgabe wie grep -e -p DATEI.
So funktioniert es
greppy erkennt an der Form des Aufrufs, ob einer seiner Befehle gemeint ist. Alles andere startet das System-grep mit denselben Argumenten, und stdout, stderr und Exit-Code kommen unverändert zurück. Die Durchleitung ruft direkt das System-grep auf und braucht keinen Index: In einem Verzeichnis ohne Index legt greppy -rn TODO . weder einen Store noch eine Datei im greppy-Datenverzeichnis an.
ripgrep-Aufrufe erkennt greppy am Wort rg oder an Flags, die es nur bei ripgrep gibt, etwa --smart-case oder -t rust. Es gibt sie an dein installiertes rg weiter. ripgrep durchsucht Dateien parallel; mit --sort path ist die Reihenfolge bei jedem Lauf gleich.
greppy installiert sich ausschließlich unter dem Namen greppy, nie als grep-Alias. Dein System-grep bleibt dein grep.
Die Befehle
| Befehl | was er tut |
|---|---|
greppy MUSTER [DATEI], greppy -rn MUSTER PFAD |
echtes grep, Ausgabe und Exit-Code byte-gleich |
greppy grep … |
dasselbe mit führendem grep-Wort |
greppy rg … |
ripgrep über dein installiertes rg, byte-gleich |
greppy --smart-case -t rust MUSTER |
ripgrep-Flags werden erkannt und an rg geleitet |
greppy -e -p DATEI |
grep nach dem Muster -p |
greppy search-pattern REGEX |
Textsuche, die zu jedem Treffer die umgebende Definition nennt |
Mehr in der Doku
- grep- und ripgrep-Durchleitung: Erkennung, Reihenfolge der ripgrep-Wege, stdin
- Suchen:
search,search-symbolundsearch-pattern - Agent einrichten: was der Prompt deinem Agenten über grep sagt