
# Начало работы

## Установка

Установите Greph с помощью Composer:

```bash
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, поэтому требуется как минимум эта версия:

```bash
composer require greph/greph:^0.2.3
```

## Требования

- **PHP 8.2+** для readonly-классов, перечислений, синтаксиса первоклассных вызываемых объектов и продвижения аргументов конструктора
- **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](https://github.com/inline0/greph/issues/5)), поэтому Composer не предупреждает об отсутствии остальных расширений.

Необязательно:

- **ext-pcntl** для параллельного сканирования. При его отсутствии Greph корректно переходит к однопроцессному выполнению.
- Внешние бинарные файлы `rg`, `grep` и `sg` для сравнения результатов тестов производительности. Во время работы они не требуются.

Поиск, переписывание и индексирование никогда не вызывают `proc_open()` или `shell_exec()`; только параллельное сканирование запускает дочерние процессы и при отсутствии `pcntl_fork()` переключается на один процесс. См. раздел [Хосты с ограничением процессов](https://greph.inline0.dev/ru/docs/advanced/process-restricted-hosts) о хостах, где отключены `proc_open()`, `shell_exec()` или `pcntl_fork()`.

## Первый текстовый поиск

Режим по умолчанию для Greph — текстовый поиск, совместимый с grep:

```bash
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](https://greph.inline0.dev/ru/docs/cli).

## Первый поиск по AST

Передайте `-p` и шаблон в формате PHP, чтобы включить структурный поиск:

```bash
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()
```

Другие полезные шаблоны:

```bash
# 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](https://greph.inline0.dev/ru/docs/modes/ast).

## Первое переписывание

Добавьте `-r`, чтобы превратить поиск по AST в переписывание:

```bash
# 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
```

При переписывании формат сохраняется за пределами совпадения: заменяется только найденный узел, а окружающие пробелы, отступы и комментарии остаются нетронутыми. Сам найденный узел заново выводится по шаблону, поэтому его оформление нормализуется, а комментарий внутри него может потеряться. Подробнее см. в разделе [Режимы / переписывание](https://greph.inline0.dev/ru/docs/modes/rewrite).

## 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](https://greph.inline0.dev/ru/docs/api).

## Поиск по индексу

Для повторяющихся задач полезны прогретые индексы. Создайте индекс один раз, затем выполняйте запросы многократно:

```bash
# 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` в корне проекта.

Для активно меняющихся деревьев выберите профиль жизненного цикла, а не считайте все прогретые индексы одинаковыми:

```bash
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`

### Поиск по нескольким прогретым индексам

Можно искать сразу в нескольких прогретых индексах одной командой:

```bash
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` и используйте подкоманды наборов вместо повторения параметров:

```bash
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`:

```bash
vendor/bin/greph-index search --trace-plan -F "function" .
vendor/bin/greph-index ast-index search --trace-plan 'new $CLASS()' .
```

Полный рабочий процесс с прогретыми индексами описан в разделах [Индексированный поиск / текст](https://greph.inline0.dev/ru/docs/indexed/text) и [Индексированный поиск / AST](https://greph.inline0.dev/ru/docs/indexed/ast).

## Оболочки совместимости

Если ваши инструменты или агенты уже используют ripgrep или ast-grep, просто подключите оболочки:

```bash
vendor/bin/rg --json -F "function" src
vendor/bin/sg --pattern 'new $CLASS()' src --lang php
```

Обе оболочки используют один и тот же движок; их работа проверена сравнением с исходными бинарными файлами. Проверенные возможности описаны в разделах [Совместимость / rg](https://greph.inline0.dev/ru/docs/compatibility/rg) и [Совместимость / sg](https://greph.inline0.dev/ru/docs/compatibility/sg) и представлены в сгенерированной [таблице возможностей](https://greph.inline0.dev/ru/docs/advanced/feature-matrix).

## Настройка

Greph учитывает два соглашения о расположении файлов:

- `.gitignore`: учитывается по умолчанию. Передайте `--no-ignore`, чтобы отключить.
- `.grephignore`: тот же синтаксис, что у `.gitignore`, применяется поверх него. Удобно для исключений, специфичных для инструмента, которые не нужно добавлять в систему контроля версий.

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