Zum Inhalt springen

Erste Schritte

Installation

Installiere Greph mit Composer:

Shell
composer require greph/greph

Dadurch werden die Bibliothek und vier ausführbare Dateien unter vendor/bin/ installiert:

  • greph: native Textsuche, AST-Suche und AST-Umschreibung
  • greph-index: aufgewärmter Textindex, AST-Faktenindex und Suche mit AST-Cache
  • rg: Kompatibilitätswrapper im Stil von ripgrep
  • sg: Kompatibilitätswrapper im Stil von ast-grep

Diese ausführbaren Dateien funktionieren ab Greph 0.2.3 im vendor/bin/ deines Projekts. Frühere Versionen fanden den Composer-Autoloader nur innerhalb eines Klons des Repositorys Greph. Verwende daher mindestens diese Version:

Shell
composer require greph/greph:^0.2.3

Voraussetzungen

  • PHP 8.2+ für readonly-Klassen, Enums, First-Class-Callable-Syntax und Constructor Promotion
  • ext-json für JSON-Ausgaben und Indexdaten auf der Festplatte
  • ext-ctype für die Verarbeitung von Mustern und Optionen
  • ext-tokenizer für den PHP-Parser und die AST-Vorfilter
  • ext-zlib für den zwischengespeicherten AST-Speicher (greph-index ast-cache)
  • nikic/php-parser (wird automatisch als Composer-Abhängigkeit installiert)

ext-json, ext-ctype und ext-tokenizer sind in fast jedem PHP-Build aktiviert. composer.json deklariert derzeit nur ext-json (#5), daher gibt Composer keine Warnung aus, wenn eine der anderen Erweiterungen fehlt.

Optional:

  • ext-pcntl für parallele Scans. Greph wechselt bei fehlender Erweiterung problemlos zur Ausführung in einem einzelnen Prozess.
  • Externe rg-, grep- und sg-Binärdateien für Benchmark-Vergleiche. Zur Laufzeit werden sie nie benötigt.

Suchen, Umschreiben und Indexieren rufen proc_open() oder shell_exec() nie auf; nur parallele Scans starten Unterprozesse und fallen ohne pcntl_fork() auf einen einzelnen Prozess zurück. Unter Hosts mit eingeschränkten Prozessen erfährst du mehr zu Hosts, die proc_open(), shell_exec() oder pcntl_fork() deaktivieren.

Der Standardmodus von Greph ist eine grep-kompatible Textsuche:

Shell
vendor/bin/greph -F "function" src

Die Ausgabe verwendet das kanonische file:line:content-Format, das grep, ripgrep und die meisten Editor-Integrationen erwarten.

Text
src/Greph.php:41:    public static function walk(string|array $paths, ?WalkOptions $options = null): FileList
src/Greph.php:50:    public static function searchText(string $pattern, string|array $paths, ?TextSearchOptions $options = null): array
src/Greph.php:81:    public static function buildTextIndex(

Füge -i für die Suche ohne Beachtung der Groß- und Kleinschreibung hinzu, -w für ganze Wörter, -c für Trefferzahlen, -l nur für Dateipfade, -C 2 für zwei Kontextzeilen und vieles mehr. Die vollständige Liste findest du in der Referenz zu CLI.

Übergib -p und ein Muster im Format PHP, um zur strukturellen Suche zu wechseln:

Shell
vendor/bin/greph -p 'new $CLASS()' src

$CLASS ist eine Metavariable, die jeden Klassennamen erfasst. Das Muster new $CLASS() findet jeden new-Ausdruck ohne Argumente, unabhängig von Klasse, Formatierung oder Kommentaren. Mit new $CLASS($$$ARGS) findest du Aufrufe mit beliebigen Argumenten.

Jeder AST-Treffer wird mit Datei, Startzeile und passendem Code ausgegeben:

Text
src/Greph.php:43:new FileWalker()
src/Greph.php:52:new TextSearchOptions()
src/Greph.php:54:new TextSearcher()

Weitere nützliche Muster:

Shell
# Any method call with any arguments
vendor/bin/greph -p '$obj->$method($$$ARGS)' src

# Any function declaration with a void return type
vendor/bin/greph -p 'function $name($$$PARAMS): void {}' src

# Old-style array calls
vendor/bin/greph -p 'array($$$ITEMS)' src

Die vollständige Mustersyntax findest du unter Modi / AST-Suche.

Dein erstes Rewrite

Füge -r hinzu, um die AST-Suche in ein Rewrite umzuwandeln:

Shell
# Preview only
vendor/bin/greph -p 'array($$$ITEMS)' -r '[$$$ITEMS]' --dry-run src

# Apply
vendor/bin/greph -p 'array($$$ITEMS)' -r '[$$$ITEMS]' src

# Confirm each file before writing
vendor/bin/greph -p 'array($$$ITEMS)' -r '[$$$ITEMS]' --interactive src

Bei Rewrites bleibt die Formatierung außerhalb des Treffers erhalten: Nur der passende Knoten wird ersetzt, Leerzeichen, Einrückungen und Kommentare im Umfeld bleiben unverändert. Der Knoten selbst wird anhand der Vorlage neu ausgegeben, wodurch seine Formatierung vereinheitlicht werden kann. Ein Kommentar innerhalb des Knotens kann dabei verloren gehen. Details findest du unter Modi / Rewrite.

PHP API

Die statische Fassade Greph\Greph bietet dieselben Operationen wie die CLI:

PHP
use Greph\Greph;
use Greph\Ast\AstSearchOptions;
use Greph\Text\TextSearchOptions;

$results = Greph::searchText(
    'function',
    'src',
    new TextSearchOptions(fixedString: true, caseInsensitive: true),
);

foreach ($results as $file) {
    foreach ($file->matches as $match) {
        echo "{$file->file}:{$match->line}:{$match->content}\n";
    }
}

$matches = Greph::searchAst(
    'new $CLASS()',
    'src',
    new AstSearchOptions(),
);

foreach ($matches as $match) {
    echo "{$match->file}:{$match->startLine}:{$match->code}\n";
}

Den vollständigen Funktionsumfang findest du unter API.

Bei wiederholten Aufgaben profitierst du von aufgewärmten Indizes. Erstelle den Index einmal und führe dann beliebig viele Abfragen aus:

Shell
# Text index
vendor/bin/greph-index build .
vendor/bin/greph-index search -F "function" .

# AST fact index
vendor/bin/greph-index ast-index build .
vendor/bin/greph-index ast-index search 'new $CLASS()' src

# Cached parsed-tree index
vendor/bin/greph-index ast-cache build .
vendor/bin/greph-index ast-cache search 'array($$$ITEMS)' src

Standardmäßig liegen die Indizes im Projektstammverzeichnis unter .greph-index, .greph-ast-index und .greph-ast-cache.

Wähle für Bäume, die sich häufig ändern, ein Lebenszyklusprofil, anstatt alle aufgewärmten Indizes gleich zu behandeln:

Shell
vendor/bin/greph-index build . --lifecycle static
vendor/bin/greph-index build . \
  --lifecycle opportunistic-refresh \
  --auto-refresh-max-files 32 \
  --auto-refresh-max-bytes 1048576
vendor/bin/greph-index stats . --dry-refresh

Das übliche Vorgehen:

  • eine stabile Ausgangsbasis als static behalten
  • häufig geänderte Overlays als opportunistic-refresh behalten
  • veraltetes Verhalten mit stats --dry-refresh prüfen

Du kannst mehrere aufgewärmte Indizes mit einem einzigen Befehl durchsuchen:

Shell
vendor/bin/greph-index search -F "apply_filters" . \
  --index-dir wordpress/.greph-index \
  --index-dir wp-content/plugins/my-plugin/.greph-index \
  --show-index-origin

vendor/bin/greph-index ast-index search 'new $CLASS()' . \
  --index-dir wordpress/.greph-ast-index \
  --index-dir wp-content/plugins/my-plugin/.greph-ast-index \
  --show-index-origin

Benannte Indexgruppen

Wenn du das regelmäßig tust, speichere das Layout in .greph-index-set.json und nutze die Unterbefehle für Gruppen, statt die Flags jedes Mal neu anzugeben:

Shell
vendor/bin/greph-index set build
vendor/bin/greph-index set stats --dry-refresh
vendor/bin/greph-index set search --show-index-origin -F "apply_filters" .
vendor/bin/greph-index set search --mode ast-index 'new $CLASS()' .
vendor/bin/greph-index set search --mode ast-cache 'array($$$ITEMS)' .

Planner-Trace

Um zu sehen, wie die aufgewärmte Suche die Kandidaten eingrenzt, füge --trace-plan hinzu:

Shell
vendor/bin/greph-index search --trace-plan -F "function" .
vendor/bin/greph-index ast-index search --trace-plan 'new $CLASS()' .

Den vollständigen Ablauf der aufgewärmten Suche findest du unter Indexiert / Text und Indexiert / AST.

Kompatibilitäts-Wrapper

Wenn deine Tools oder Agents bereits ripgrep oder ast-grep verwenden, kannst du einfach die Wrapper einsetzen:

Shell
vendor/bin/rg --json -F "function" src
vendor/bin/sg --pattern 'new $CLASS()' src --lang php

Beide Wrapper verwenden dieselbe Engine und wurden durch Tests mit den vorgelagerten Binärdateien geprüft. Die verifizierten Funktionen sind unter Kompatibilität / rg und Kompatibilität / sg dokumentiert und in der generierten Funktionsmatrix aufgeführt.

Konfiguration

Greph berücksichtigt zwei Konventionen für Dateien auf der Festplatte:

  • .gitignore: wird standardmäßig berücksichtigt. Mit --no-ignore kannst du das deaktivieren.
  • .grephignore: gleiche Syntax wie .gitignore, wird zusätzlich angewendet. Damit kannst du werkzeugspezifische Ausschlüsse festlegen, die du nicht in der Versionsverwaltung speichern möchtest.

Die Standardverzeichnisse der Indizes sind am gewählten Stammverzeichnis .greph-index, .greph-ast-index und .greph-ast-cache. Du kannst sie mit --index-dir bei jedem greph-index-Unterbefehl überschreiben oder mit .greph-index-set.json wiederverwendbare Layouts für mehrere Indizes nutzen.