
# Erste Schritte

## Installation

Installiere Greph mit Composer:

```bash
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:

```bash
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](https://github.com/inline0/greph/issues/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](https://greph.inline0.dev/de/docs/advanced/process-restricted-hosts) erfährst du mehr zu Hosts, die `proc_open()`, `shell_exec()` oder `pcntl_fork()` deaktivieren.

## Deine erste Textsuche

Der Standardmodus von Greph ist eine grep-kompatible Textsuche:

```bash
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](https://greph.inline0.dev/de/docs/cli).

## Deine erste AST-Suche

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

```bash
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:

```bash
# 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](https://greph.inline0.dev/de/docs/modes/ast).

## Dein erstes Rewrite

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

```bash
# 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](https://greph.inline0.dev/de/docs/modes/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](https://greph.inline0.dev/de/docs/api).

## Indexierte Suche

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

```bash
# 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:

```bash
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

### Suche mit mehreren aufgewärmten Indizes

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

```bash
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:

```bash
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:

```bash
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](https://greph.inline0.dev/de/docs/indexed/text) und [Indexiert / AST](https://greph.inline0.dev/de/docs/indexed/ast).

## Kompatibilitäts-Wrapper

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

```bash
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](https://greph.inline0.dev/de/docs/compatibility/rg) und [Kompatibilität / sg](https://greph.inline0.dev/de/docs/compatibility/sg) dokumentiert und in der generierten [Funktionsmatrix](https://greph.inline0.dev/de/docs/advanced/feature-matrix) 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.
