
# البدء

## التثبيت

ثبّت 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+** لدعم الأصناف للقراءة فقط والتعدادات وصياغة الدوال القابلة للاستدعاء من الدرجة الأولى وترقية المنشئات
- **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/ar/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/ar/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/ar/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/ar/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/ar/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/ar/docs/indexed/text) و[المفهرس / AST](https://greph.inline0.dev/ar/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/ar/docs/compatibility/rg) و[التوافق / sg](https://greph.inline0.dev/ar/docs/compatibility/sg) الواجهات التي تم التحقق منها، كما يعرضها [جدول الميزات](https://greph.inline0.dev/ar/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` لتخطيطات متعددة الفهارس قابلة للتكرار.
