はじめに
インストール
ComposerでGrephをインストールします。
composer require greph/greph
これにより、ライブラリと4つの実行ファイルがvendor/bin/にインストールされます。
greph: ネイティブのテキスト検索、AST検索、AST書き換えgreph-index: ウォーム済みテキストインデックス、ASTファクトインデックス、キャッシュ済みAST検索rg: ripgrep形式の互換ラッパーsg: ast-grep形式の互換ラッパー
Greph 0.2.3以降では、これらの実行ファイルをプロジェクトのvendor/bin/から使えます。それ以前のリリースでは、ComposerのオートローダーをGrephリポジトリのクローン内でしか見つけられなかったため、少なくともこのバージョンが必要です。
composer require greph/greph:^0.2.3
必要条件
- PHP 8.2+ readonlyクラス、enum、first-class callable構文、コンストラクター昇格に対応
- ext-json は JSON 出力とディスク上のインデックスペイロードに使用
- ext-ctype はパターンとオプションの解析に使用
- ext-tokenizer は PHP-Parser と AST の事前フィルターに使用
- ext-zlib はキャッシュ済み AST ストア(
greph-index ast-cache)に使用 - nikic/php-parser(Composer の依存関係として自動インストール)
ext-json、ext-ctype、ext-tokenizerは、ほぼすべてのPHPビルドで有効になっています。現時点でcomposer.jsonが宣言しているのはext-jsonのみ(#5)のため、ほかの拡張が欠けていても Composer は警告しません。
任意:
- 並列スキャンには ext-pcntl を使用します。Grephは、これがない場合も単一プロセスで動作します。
- ベンチマーク比較用の外部
rg、grep、sgバイナリ。実行時には必要ありません。
検索、書き換え、インデックス作成ではproc_open()もshell_exec()も呼び出されません。分岐するのは並列スキャンのみで、pcntl_fork()がない場合は単一プロセスにフォールバックします。proc_open()、shell_exec()、またはpcntl_fork()を無効にするホストについては、プロセス制限のあるホストをご覧ください。
テキスト検索を始める
Grephのデフォルトモードは grep 互換のテキスト検索です:
vendor/bin/greph -F "function" src
出力には、grep、ripgrep、およびほとんどのエディター連携が想定する標準file:line:content形式を使用します。
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(
大文字と小文字を区別しない検索には-i、単語全体の一致には-w、件数の表示には-c、ファイルパスのみの表示には-l、前後2行の表示には-C 2などを追加します。全オプションはCLIリファレンスに記載されています。
AST検索を始める
構造検索に切り替えるには、-pとPHP形式のパターンを渡します:
vendor/bin/greph -p 'new $CLASS()' src
$CLASSは、任意のクラス名を捕捉するメタ変数です。パターンnew $CLASS()は、クラスや書式、コメントにかかわらず、引数のないすべてのnew式に一致します。任意の引数を持つ呼び出しにはnew $CLASS($$$ARGS)を使います。
各 AST の一致結果は、ファイル名、開始行、該当するコードの順に出力されます:
src/Greph.php:43:new FileWalker()
src/Greph.php:52:new TextSearchOptions()
src/Greph.php:54:new TextSearcher()
その他の便利なパターン:
# 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
パターン構文の詳細はモード / AST検索を参照してください。
書き換えを始める
AST検索を使った書き換えを行うには、-rを追加します:
# 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
書き換えでは、一致部分以外の書式が保たれます。置き換えられるのは一致したノードのみで、周囲の空白、インデント、コメントはそのまま残ります。一致したノード自体はテンプレートから新たに出力されるため、そのレイアウトは整えられ、内部のコメントは失われる場合があります。詳しくはモード / 書き換えを参照してください。
PHP API
静的なGreph\Grephファサードでは、CLIと同じ操作を利用できます:
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";
}
すべての機能はAPIで網羅しています。
インデックス検索
同じ処理を繰り返す場合は、インデックスを事前に作成しておくと便利です。一度作成すれば、何度でも検索できます:
# 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
デフォルトでは、プロジェクトルートの.greph-index、.greph-ast-index、.greph-ast-cacheにインデックスが保存されます。
頻繁に変更されるツリーでは、事前作成したインデックスを一律に扱わず、ライフサイクルプロファイルを選択してください:
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
一般的な構成は次のとおりです:
- 安定したベースラインには
staticを使用 - 頻繁に変わるオーバーレイには
opportunistic-refreshを使用 - 古くなった場合の動作確認には
stats --dry-refreshを使用
複数のインデックスを使った検索
1つのコマンドで、複数の事前作成済みインデックスを検索できます:
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
名前付きインデックスセット
この操作を繰り返す場合は、構成を.greph-index-set.jsonに記述し、フラグを毎回指定する代わりにセット用サブコマンドを使います:
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)' .
プランナーのトレース
事前作成済みインデックス検索で候補がどのように絞り込まれるか確認するには、--trace-planを追加します:
vendor/bin/greph-index search --trace-plan -F "function" .
vendor/bin/greph-index ast-index search --trace-plan 'new $CLASS()' .
事前作成済みインデックスを使った検索の詳細は、インデックス / テキストとインデックス / ASTを参照してください。
互換ラッパー
ripgrep または ast-grep を使うツールやエージェントには、ラッパーをそのまま導入できます:
vendor/bin/rg --json -F "function" src
vendor/bin/sg --pattern 'new $CLASS()' src --lang php
どちらのラッパーも同じエンジンを使用し、上流のバイナリとのプローブ検証済みです。検証済みの機能は互換性 / rgと互換性 / sgに記載され、生成された機能マトリクスにも掲載されています。
設定
Grephは、ディスク上にある2つの規則を適用します:
.gitignore: デフォルトで適用されます。無効にするには--no-ignoreを渡します。.grephignore:.gitignoreと同じ構文で、その上に適用されます。バージョン管理に含めたくない、ツール固有の除外設定に便利です。
デフォルトのインデックスディレクトリは、選択したルートの.greph-index、.greph-ast-index、.greph-ast-cacheです。任意のgreph-indexサブコマンドで--index-dirを使って変更するか、繰り返し使える複数インデックス構成には.greph-index-set.jsonを使用してください。