
# ファイルウォーカー

すべてのGrephモード（テキスト、AST、書き換え、インデックス付きテキスト、インデックス付きAST、キャッシュ済みAST、`rg`ラッパー、`sg`ラッパー）は、ファイルツリーを走査して`Greph\Walker\FileList`を生成するところから始まります。ウォーカーは共通で、同じフラグと動作がすべてのモードに適用されます。

## デフォルトの動作

標準設定では、ウォーカーは次のように動作します。

- 指定されたパスの下にあるすべてのディレクトリを再帰的に走査します。
- ネストされた上書きや否定パターンを含め、すべての階層で`.gitignore`と`.grephignore`のルールに従います。
- `.git`ディレクトリをスキップします。
- 隠しファイルと隠しディレクトリ（`.`で始まるもの）をスキップします。
- バイナリファイル（ファイル先頭512バイト内のヌルバイトで判定）をスキップします。
- 10 MiBを超えるファイルをスキップします。
- シンボリックリンクをたどりません。

## 上書きフラグ

| フラグ | 効果 |
|---|---|
| `--no-ignore` | `.gitignore`と`.grephignore`を無視する |
| `--hidden` | 隠しファイルと隠しディレクトリを含める |
| `--type NAME` | 指定されたタイプエイリアスに一致するファイルのみを含める |
| `--type-not NAME` | 指定されたタイプエイリアスに一致するファイルを除外する |
| `--glob GLOB` | パスがGLOBに一致するファイルのみを含める。複数回指定できます。 |

同じオプションはプログラムから使うために`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'],
));
```

## ファイルタイプのエイリアス

Grephには、名前付きのファイルタイプがいくつか用意されています。各エイリアスは拡張子のリストに対応します。

| エイリアス | 拡張子 |
|---|---|
| `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` |

全リストは`Greph\Walker\FileTypeFilter::TYPE_MAP`にあります。

## .gitignoreのセマンティクス

Grephは純粋なPHPでgitignoreのマッチングを実装しています。動作は`git check-ignore`に準拠しています。

- パターンは、それが記述されたディレクトリを基準に評価されます。
- ネストされた`.gitignore`ファイルは親のルールを上書きします。
- 否定パターン（`!pattern`）は、以前に除外されたパスを再び含めます。
- 末尾の`/`は、パターンをディレクトリのみに適用します。
- 先頭の`/`は、パターンを`.gitignore`のディレクトリに固定します。
- `**`は任意の数のパスセグメントに一致します。

`.grephignore`は同じ構文を使い、`.gitignore`のルールに追加して適用されます。バージョン管理に含めたくないツール固有の除外ルールを記述するのに適しています。

実装は`Greph\Walker\GitignoreFilter`にあります。

## バイナリの検出

ウォーカーは各ファイルの先頭512バイトを調べ、ヌルバイトが含まれていればバイナリとして扱い、スキップします。これにより、インデックス対象のディレクトリ内に画像、アーカイブ、コンパイル済みファイルなどが含まれる一般的なケースに対応します。

バイナリファイルも検索するには、該当する`Options`オブジェクトで`skipBinaryFiles: false`を設定します。CLIには現在このフラグがないため、ファサードを使用してください。

## シンボリックリンク

既定ではシンボリックリンクをたどりません。たどるには`followSymlinks: true`を設定するか、`rg`ラッパーで`-L` / `--follow`を渡してください。ウォーカーは訪問済みディレクトリを追跡するため、シンボリックリンクのループによる無限再帰を防げます。

## 最大ファイルサイズ

`maxFileSizeBytes`を超えるファイル（既定値は10 MiB）はスキップされます。これにより、1 GBのログファイルを誤ってメモリに読み込む事態を防げます。より大きな入力を扱う必要がある場合は、`Options`オブジェクトで上限を変更してください。

## カスタムウォーカーを使う理由

Grephでは`glob()`や`RecursiveDirectoryIterator`を使うこともできますが、どちらもgitignoreのセマンティクスを実装しておらず、`.grephignore`にも対応せず、ワーカープールとも適切に統合できません。ウォーカーを一度実装して各モードで共有すれば、すべてのモードに同一のフィルタリングルールが適用されます。これはオラクル駆動のテスト戦略に不可欠です。`grep`、`ripgrep`、`ast-grep`と比較するには、それらのツールが走査するファイルと同じ集合を走査する必要があります。
