
# Percorredor de arquivos

Cada modo Greph (texto, AST, reescrita, texto indexado, AST indexada, AST em cache, wrapper `rg`, wrapper `sg`) começa percorrendo a árvore de arquivos e produzindo um `Greph\Walker\FileList`. O percorridor é compartilhado, então as mesmas flags e comportamentos se aplicam em todos os modos.

## Comportamento padrão

Por padrão, o percorridor:

- Percorre recursivamente todos os diretórios abaixo dos caminhos solicitados.
- Respeita as regras de `.gitignore` e `.grephignore` em todos os níveis, incluindo substituições aninhadas e negações.
- Ignora o diretório `.git`.
- Ignora arquivos e diretórios ocultos (qualquer item que comece com `.`).
- Ignora arquivos binários (detectados por bytes nulos nos primeiros 512 bytes do arquivo).
- Ignora arquivos maiores que 10 MiB.
- Não segue links simbólicos.

## Flags de substituição

| Flag | Efeito |
|---|---|
| `--no-ignore` | Deixar de respeitar `.gitignore` e `.grephignore` |
| `--hidden` | Incluir arquivos e diretórios ocultos |
| `--type NAME` | Incluir apenas arquivos que correspondam ao alias de tipo indicado |
| `--type-not NAME` | Excluir arquivos que correspondam ao alias de tipo indicado |
| `--glob GLOB` | Incluir apenas arquivos cujos caminhos correspondam a GLOB. Pode ser repetida. |

As mesmas opções são disponibilizadas por `Greph\Walker\WalkOptions` para uso programático.

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

## Aliases de tipo de arquivo

Greph inclui um pequeno conjunto de tipos de arquivo nomeados. Cada alias corresponde a uma lista de extensões:

| Alias | Extensões |
|---|---|
| `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` |

A lista completa está em `Greph\Walker\FileTypeFilter::TYPE_MAP`.

## Semântica de .gitignore

Greph implementa a correspondência de gitignore em PHP puro. A semântica segue `git check-ignore`:

- Os padrões são avaliados em relação ao diretório onde estão.
- Arquivos `.gitignore` aninhados substituem as regras dos diretórios pai.
- A negação (`!pattern`) volta a incluir um caminho excluído anteriormente.
- Um `/` no final restringe um padrão a diretórios.
- Um `/` no início ancora um padrão ao diretório do `.gitignore`.
- `**` corresponde a qualquer quantidade de segmentos de caminho.

`.grephignore` usa a mesma sintaxe e funciona sobre `.gitignore`. É o lugar adequado para exclusões específicas da ferramenta que não se deseja incluir no controle de versão.

A implementação fica em `Greph\Walker\GitignoreFilter`.

## Detecção de binários

O percorridor verifica os primeiros 512 bytes de cada arquivo em busca de bytes nulos. Se encontrar algum, trata o arquivo como binário e o ignora. Isso cobre o caso comum em que um repositório contém imagens, arquivos compactados ou artefatos compilados dentro de um diretório indexado.

Para pesquisar arquivos binários mesmo assim, defina `skipBinaryFiles: false` no objeto `Options` correspondente. Atualmente, CLI não disponibiliza uma flag para isso; use a fachada.

## Links simbólicos

Por padrão, os links simbólicos não são seguidos. Defina `followSymlinks: true` (ou passe `-L` / `--follow` no wrapper `rg`) para segui-los. O percorridor mantém o controle dos diretórios visitados para que ciclos de links simbólicos não causem recursão infinita.

## Tamanho máximo de arquivo

Arquivos maiores que `maxFileSizeBytes` (10 MiB por padrão) são ignorados. Isso evita que uma varredura carregue acidentalmente um arquivo de log de 1 GB na memória. Altere o limite no objeto `Options` quando precisar lidar com entradas maiores.

## Por que usar um percorridor personalizado

Greph poderia depender de `glob()` ou `RecursiveDirectoryIterator`, mas nenhum deles implementa a semântica de gitignore, entende `.grephignore` ou se integra bem ao pool de trabalhadores. Escrever o percorridor uma vez e compartilhá-lo entre os modos também significa que todos aplicam exatamente as mesmas regras de filtragem, algo essencial para a estratégia de testes orientada por oráculo: a única maneira de comparar com `grep`, `ripgrep` e `ast-grep` é percorrer o mesmo conjunto de arquivos que essas ferramentas percorrem.
