
# Bestandswalker

Elke modus van Greph (tekst, AST, herschrijven, geïndexeerde tekst, geïndexeerde AST, gecachte AST, wrapper `rg`, wrapper `sg`) begint met het doorlopen van de bestandsstructuur en het maken van een `Greph\Walker\FileList`. De walker wordt gedeeld, dus overal gelden dezelfde flags en hetzelfde gedrag.

## Standaardgedrag

Standaard doet de walker het volgende:

- Doorloopt recursief elke directory onder de opgegeven paden.
- Houdt zich op elk niveau aan de regels van `.gitignore` en `.grephignore`, inclusief geneste overschrijvingen en ontkenningen.
- Slaat de directory `.git` over.
- Slaat verborgen bestanden en directories over (alles wat begint met `.`).
- Slaat binaire bestanden over (gedetecteerd aan de hand van nulbytes in de eerste 512 bytes van het bestand).
- Slaat bestanden groter dan 10 MiB over.
- Volgt geen symlinks.

## Overschrijfflags

| Flag | Effect |
|---|---|
| `--no-ignore` | Negeer de regels van `.gitignore` en `.grephignore` |
| `--hidden` | Neem verborgen bestanden en directories op |
| `--type NAME` | Neem alleen bestanden op die overeenkomen met de genoemde typealias |
| `--type-not NAME` | Sluit bestanden uit die overeenkomen met de genoemde typealias |
| `--glob GLOB` | Neem alleen bestanden op waarvan de paden overeenkomen met GLOB. Herhaalbaar. |

Dezelfde opties zijn beschikbaar via `Greph\Walker\WalkOptions` voor programmatisch gebruik.

```php
use Greph\Greph;
use Greph\Walker\FileTypeFilter;
use Greph\Walker\WalkOptions;

$files = Greph::walk('src', new WalkOptions(
    respectIgnore: false,
    includeHidden: true,
    fileTypeFilter: new FileTypeFilter(['php']),
    globPatterns: ['src/**/*.php'],
));
```

## Aliassen voor bestandstypen

Greph bevat een kleine set benoemde bestandstypen. Elke alias verwijst naar een lijst met extensies:

| Alias | Extensies |
|---|---|
| `css` | `css`, `sass`, `scss` |
| `html` | `htm`, `html`, `phtml` |
| `js` | `cjs`, `js`, `mjs` |
| `json` | `json` |
| `md` | `markdown`, `md` |
| `php` | `inc`, `php`, `php3`, `php4`, `php5`, `php7`, `php8`, `phpt`, `phtml` |
| `txt` | `txt` |
| `ts` | `ts`, `tsx` |
| `xml` | `xml` |
| `yaml` | `yaml`, `yml` |

De volledige lijst staat in `Greph\Walker\FileTypeFilter::TYPE_MAP`.

## Betekenis van .gitignore

Greph implementeert matching volgens gitignore in pure PHP. De semantiek komt overeen met die van `git check-ignore`:

- Patronen worden geëvalueerd ten opzichte van de directory waarin ze staan.
- Geneste `.gitignore`-bestanden overschrijven regels van bovenliggende directories.
- Met ontkenning (`!pattern`) wordt een eerder uitgesloten pad weer opgenomen.
- Een afsluitende `/` beperkt een patroon tot directories.
- Een voorloop-`/` verankert een patroon aan de directory van de `.gitignore`.
- `**` komt overeen met een willekeurig aantal padsegmenten.

`.grephignore` gebruikt dezelfde syntaxis en is een aanvulling op `.gitignore`. Hier horen toolspecifieke uitsluitingen thuis die u niet in versiebeheer wilt opnemen.

De implementatie staat in `Greph\Walker\GitignoreFilter`.

## Binaire detectie

De walker controleert de eerste 512 bytes van elk bestand op nulbytes. Als die aanwezig zijn, wordt het bestand als binair beschouwd en overgeslagen. Zo worden veelvoorkomende gevallen opgevangen waarin een repository afbeeldings-, archief- of gecompileerde bestanden bevat in een directory die wordt geïndexeerd.

Als u toch in binaire bestanden wilt zoeken, stelt u `skipBinaryFiles: false` in op het betreffende `Options`-object. De CLI biedt hiervoor momenteel geen flag; gebruik de facade.

## Symlinks

Symlinks worden standaard niet gevolgd. Stel `followSymlinks: true` in (of geef `-L` / `--follow` door aan de wrapper `rg`) om ze te volgen. De walker houdt bijgehouden welke directories zijn bezocht, zodat lussen door symlinks geen oneindige recursie veroorzaken.

## Maximale bestandsgrootte

Bestanden groter dan `maxFileSizeBytes` (standaard 10 MiB) worden overgeslagen. Zo wordt voorkomen dat een logbestand van 1 GB per ongeluk in het geheugen wordt geladen tijdens een scan. Pas de limiet aan op het `Options`-object als u grotere invoerbestanden wilt verwerken.

## Waarom een eigen walker

Greph zou kunnen vertrouwen op `glob()` of `RecursiveDirectoryIterator`, maar geen van beide implementeert de semantiek van gitignore, begrijpt geen `.grephignore` en integreert niet goed met de workerpool. Door de walker één keer te schrijven en in alle modi te delen, gelden bovendien in elke modus precies dezelfde filterregels. Dat is essentieel voor de teststrategie op basis van een orakel: vergelijking met `grep`, `ripgrep` en `ast-grep` is alleen mogelijk als dezelfde set bestanden wordt doorlopen als die tools doorlopen.
