
# Walker di file

Ogni modalità Greph (testo, AST, riscrittura, testo indicizzato, AST indicizzato, AST memorizzato in cache, wrapper `rg`, wrapper `sg`) inizia esplorando l’albero dei file e generando un `Greph\Walker\FileList`. Il walker è condiviso, quindi flag e comportamenti sono gli stessi ovunque.

## Comportamento predefinito

Configurazione predefinita del walker:

- Esplora ricorsivamente tutte le directory nelle percorsi richiesti.
- Rispetta le regole di `.gitignore` e `.grephignore` a ogni livello, incluse le eccezioni e le negazioni annidate.
- Esclude la directory `.git`.
- Esclude file e directory nascosti, ovvero quelli che iniziano con `.`.
- Esclude i file binari, rilevati dalla presenza di byte nulli nei primi 512 byte del file.
- Esclude i file più grandi di 10 MiB.
- Non segue i link simbolici.

## Flag di override

| Flag | Effetto |
|---|---|
| `--no-ignore` | Ignora le regole di `.gitignore` e `.grephignore` |
| `--hidden` | Include file e directory nascosti |
| `--type NAME` | Include solo i file che corrispondono all’alias di tipo specificato |
| `--type-not NAME` | Esclude i file che corrispondono all’alias di tipo specificato |
| `--glob GLOB` | Include solo i file il cui percorso corrisponde a GLOB. Ripetibile. |

Per l’uso programmatico, le stesse opzioni sono disponibili tramite `Greph\Walker\WalkOptions`.

```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'],
));
```

## Alias dei tipi di file

Greph include un piccolo insieme di tipi di file con nome. Ogni alias corrisponde a un elenco di estensioni:

| Alias | Estensioni |
|---|---|
| `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` |

L’elenco completo si trova in `Greph\Walker\FileTypeFilter::TYPE_MAP`.

## Semantica di .gitignore

Greph implementa la corrispondenza con gitignore in PHP puro. La semantica è allineata a `git check-ignore`:

- I pattern vengono valutati rispetto alla directory in cui si trovano.
- I file `.gitignore` annidati sovrascrivono le regole delle directory genitrici.
- La negazione (`!pattern`) reinclude un percorso escluso in precedenza.
- `/` finale limita il pattern alle directory.
- `/` iniziale ancora un pattern alla directory di `.gitignore`.
- `**` corrisponde a un numero qualsiasi di segmenti del percorso.

`.grephignore` usa la stessa sintassi ed è sovrapposto a `.gitignore`. È il posto giusto per le esclusioni specifiche degli strumenti che non volete inserire nel controllo delle versioni.

L’implementazione si trova in `Greph\Walker\GitignoreFilter`.

## Rilevamento dei file binari

Il walker controlla la presenza di byte nulli nei primi 512 byte di ogni file. Se ne trova, il file viene considerato binario ed escluso. Questo intercetta il caso comune in cui un repository contiene immagini, archivi o artefatti compilati in una directory indicizzata.

Per cercare comunque nei file binari, impostate `skipBinaryFiles: false` sull’oggetto `Options` pertinente. Al momento CLI non espone un flag per questa opzione; usate la facade.

## Link simbolici

Per impostazione predefinita, i link simbolici non vengono seguiti. Impostate `followSymlinks: true` (oppure passate `-L` / `--follow` al wrapper `rg`) per seguirli. Il walker tiene traccia delle directory visitate, così i cicli nei link simbolici non causano ricorsioni infinite.

## Dimensione massima dei file

I file più grandi di `maxFileSizeBytes` (10 MiB per impostazione predefinita) vengono esclusi. In questo modo si evita che una scansione carichi accidentalmente in memoria un file di log da 1 GB. Se dovete elaborare file più grandi, potete aumentare il limite sull’oggetto `Options`.

## Perché usare un walker personalizzato

Greph potrebbe basarsi su `glob()` o `RecursiveDirectoryIterator`, ma nessuno dei due implementa la semantica di gitignore, riconosce `.grephignore` o si integra facilmente con il pool di worker. Scrivere il walker una sola volta e condividerlo tra le modalità significa anche applicare esattamente gli stessi filtri a ciascuna modalità, un requisito fondamentale per la strategia di test basata sull’oracolo: l’unico modo per confrontare con `grep`, `ripgrep` e `ast-grep` è esaminare lo stesso insieme di file di questi strumenti.
