انتقل إلى المحتوى

البدء

التثبيت

ثبّت 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 لتخطيطات متعددة الفهارس قابلة للتكرار.