Перейти до вмісту

Початок роботи

Встановлення

Встановіть Greph через Composer:

Командна оболонка
composer require greph/greph

Це встановить бібліотеку й чотири виконувані файли в vendor/bin/:

  • greph: нативний пошук у тексті, пошук AST і перезапис AST
  • greph-index: прогрітий текстовий індекс, індекс фактів AST і кешований пошук AST
  • rg: обгортка сумісності у стилі ripgrep
  • sg: обгортка сумісності у стилі ast-grep

Ці виконувані файли працюють із каталогу vendor/bin/ вашого проєкту, оскільки Greph 0.2.3. Раніші випуски знаходили автозавантажувач Composer лише всередині клону репозиторію Greph, тому потрібна принаймні ця версія:

Командна оболонка
composer require greph/greph:^0.2.3

Вимоги

  • PHP 8.2+ для класів лише для читання, переліків, синтаксису виклику функцій першого класу та просування властивостей конструктора
  • 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

У виводі використовується канонічний формат file:line:content, на який очікують grep, ripgrep і більшість інтеграцій із редакторами.

Text
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 — щоб виводити лише шляхи до файлів, -C 2 — щоб показувати два контекстні рядки, тощо. Повний список наведено в довідці CLI.

Передайте -p і шаблон у формі PHP, щоб перейти до структурного пошуку:

Командна оболонка
vendor/bin/greph -p 'new $CLASS()' src

$CLASS — метазмінна, що захоплює будь-яке ім’я класу. Шаблон new $CLASS() відповідає кожному виразу new без аргументів, незалежно від класу, форматування чи коментарів. Використовуйте new $CLASS($$$ARGS), щоб шукати виклики з будь-якими аргументами.

Кожен збіг AST виводиться у вигляді файлу, початкового рядка та знайденого фрагмента коду:

Text
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.

Ваш перший перезапис

Додайте -r, щоб перетворити пошук AST на перезапис:

Командна оболонка
# 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:

PHP
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

Ви можете шукати в кількох прогрітих індексах однією командою:

Командна оболонка
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 враховує дві домовленості щодо файлів на диску:

  • .gitignore: враховується за замовчуванням. Передайте --no-ignore, щоб вимкнути.
  • .grephignore: той самий синтаксис, що й у .gitignore, застосовується додатково. Корисно для виключень, специфічних для інструмента, які не потрібно додавати до системи контролю версій.

За замовчуванням каталоги індексів .greph-index, .greph-ast-index і .greph-ast-cache створюються у вибраному кореневому каталозі. Перевизначте їх за допомогою --index-dir у будь-якій підкоманді greph-index або скористайтеся .greph-index-set.json для повторюваних структур із кількома індексами.