readtags(1) Universal Ctags readtags(1)

readtags - یافتن مدخل‌های فایل برچسب منطبق با نام‌های مشخص‌شده

readtags -h | --help
readtags (-H | --help-expression) (filter|sorter|formatter)
readtags -v | --version
readtags [OPTION]... ACTION

برنامه readtags مدخل‌های برچسب موجود در یک فایل برچسب را فیلتر، مرتب و چاپ می‌کند. فیلتر کردن اولیه با استفاده از عملیات‌ها (actions) انجام می‌شود که از طریق آن‌ها می‌توانید تمام برچسب‌های عادی، شبه‌برچسب‌ها یا برچسب‌های عادی منطبق با نامی مشخص را فهرست کنید. سپس، فیلتر کردن، مرتب‌سازی و قالب‌بندی بیشتر می‌تواند با استفاده از پس‌پردازشگرها (post processors)، شامل عبارت‌های فیلتر (filter expressions)، عبارت‌های مرتب‌ساز (sorter expressions) و عبارت‌های قالب‌بند (formatter expressions) انجام شود.

فهرست کردن برچسب‌های عادی.
[-] NAME
فهرست کردن برچسب‌های عادی منطبق با NAME. استفاده از "-" به عنوان NAME مشخص می‌کند که آرگومان‌های پس از آن، حتی اگر با - شروع شوند، به عنوان NAME در نظر گرفته شوند.
فهرست کردن شبه‌برچسب‌ها. می‌توانید از این گزینه همراه با گزینه -Q برای استخراج شبه‌برچسب‌های مشخص‌شده استفاده کنید.

رفتار خواندن برچسب‌ها را می‌توان با استفاده از این گزینه‌ها کنترل کرد:

استفاده از فایل برچسب مشخص‌شده (پیش‌فرض: "tags"). دادن "-" به عنوان TAGFILE مشخص می‌کند که محتوای فایل برچسب از ورودی استاندارد خوانده شود. استفاده از "-" می‌تواند خط فرمان را ساده‌تر کند؛ با این حال، به معنای کارایی بالاتر نیست؛ زیرا readtags داده‌ها را در یک فایل موقت ذخیره کرده و آن فایل را برای اجرای ACTION می‌خواند.
نادیده گرفتن تشخیص مرتب‌سازی فایل برچسب. مقدار METHOD می‌تواند یکی از موارد unsorted|sorted|foldcase باشد.

عملیات NAME جستجوی دودویی را روی فایل‌های برچسب مرتب‌شده (شامل "foldcase") انجام می‌دهد که بسیار سریع‌تر از فایل‌های برچسب مرتب‌نشده است.

رفتار عملیات NAME را می‌توان با استفاده از این گزینه‌ها کنترل کرد:

انجام تطبیق غیرحساس به بزرگی و کوچکی حروف در عملیات NAME.
انجام تطبیق پیشوند در عملیات NAME.

به‌طور پیش‌فرض، خروجی readtags تنها شامل فیلدهای name، input و pattern است. خروجی را می‌توان با استفاده از این گزینه‌ها تغییر داد:

مشابه گزینه -C عمل می‌کند اما تنها از فرم مسیر مطلق استفاده می‌کند.
حل کردن '..' و '.' در فیلدهای ورودی برچسب‌های عادی. این کار نمایشی یکتا از مسیر ورودی تولید می‌کند. این گزینه فقط با فایل‌های برچسبی کار می‌کند که دارای شبه‌برچسب !_TAG_PROC_CWD باشند.

نکته: پیاده‌سازی فعلی فقط !_TAG_PROC_CWD را می‌پذیرد که با / شروع شود؛ نام دایرکتوری در ویندوز که با حرف درایو مانند C:\Somewhere شروع شود قابل قبول نیست.

فعال کردن خروجی اشکال‌زدایی.
اسکیپ کردن کاراکترهایی مانند تب در خروجی طبق توضیحات tags(5).
گنجاندن فیلدهای الحاقی در خروجی.
همچنین گنجاندن فیلد شماره خط در هنگام استفاده از گزینه -e.
فهرست کردن شبه‌برچسب‌ها به‌گونه‌ای که گویی گزینه -D مشخص شده است، اما بدون خروج پردازش را ادامه می‌دهد. حتی اگر گزینه‌های -Q و -P را همزمان مشخص کنید، -Q تنها بر برچسب‌های عادی اثر می‌گذارد و شبه‌برچسب‌ها را تحت تأثیر قرار نمی‌دهد.

درباره گزینه -E: برخی کاراکترها در یک فایل برچسب اسکیپ می‌شوند تا ماشین بتواند آن‌ها را بخواند؛ به عنوان مثال، اطمینان از این‌که هیچ کاراکتر تبی در فیلدهایی غیر از فیلد الگو ظاهر نشود. به‌طور پیش‌فرض، readtags آن‌ها را تبدیل می‌کند تا برای انسان خوانا باشند، اما هنگام استفاده از خروجی readtags در یک اسکریپت یا ابزار کلاینت، باید از گزینه -E استفاده شود. برای بحث بیشتر در این زمینه به ctags-client-tools(7) مراجعه کنید.

درباره چاپ فیلدهای ورودی ({tagfile} در tags(5)) با گزینه -E: برنامه readtags همواره فیلد ورودی را به همان صورتی که هست (عیناً در فایل برچسب) چاپ می‌کند، و هنگامی که ctags فایل برچسب را می‌نویسد، قوانین اسکیپ تنها زمانی اعمال می‌شوند که شبه‌برچسب TAG_OUTPUT_MODE مقدار "u-ctags" و TAG_OUTPUT_FILESEP مقدار "slash" را برای فیلدهای ورودی خود داشته باشند، همان‌گونه که در ctags-client-tools(7) توضیح داده شده است.

فیلتر کردن، مرتب‌سازی و قالب‌بندی بیشتر روی برچسب‌های فهرست‌شده توسط عملیات‌ها با استفاده از موارد زیر انجام می‌شود:

فیلتر کردن برچسب‌های فهرست‌شده توسط ACTION با EXP پیش از چاپ.
مرتب‌سازی برچسب‌های فهرست‌شده توسط ACTION با EXP پیش از چاپ.
قالب‌بندی برچسب‌های فهرست‌شده توسط ACTION با EXP هنگام چاپ.

این موارد در بخش «عبارت (EXPRESSION)» بررسی شده‌اند.

•
فهرست کردن تمام برچسب‌ها در "/path/to/tags":
$ readtags -t /path/to/tags -l
•
فهرست کردن تمام برچسب‌های موجود در "tags" که با "mymethod" شروع می‌شوند:
$ readtags -p - mymethod
•
فهرست کردن تمام برچسب‌های منطبق با "mymethod" بدون حساسیت به بزرگی و کوچکی حروف:
$ readtags -i - mymethod
•
فهرست کردن تمام برچسب‌هایی که با "myvar" شروع می‌شوند، و چاپ تمام فیلدها (یعنی کل خط):
$ readtags -p -ne - myvar

برای گزینه‌های -Q، -S و -F از عبارت‌هایی به سبک اسکیم (Scheme-style) استفاده می‌شود. برای کسانی که با زبان اسکیم یا لیسپ آشنا نیستند، تنها کافی است موارد زیر را به خاطر بسپارند:

  • یک فراخوانی تابع درون یک جفت پرانتز قرار می‌گیرد. نخستین مورد درون آن، نام تابع/عملگر است و موارد دیگر آرگومان‌ها هستند.
  • فراخوانی‌های تابع می‌توانند تودرتو باشند.
  • مقادیر ناموجود و نادرست بولی با #f نمایش داده می‌شوند. #t و تمام مقادیر دیگر درست (true) در نظر گرفته می‌شوند.

بنابراین، (+ 1 (+ 2 3)) به این معنی است که ابتدا ۲ و ۳ جمع شوند، سپس نتیجه با ۱ جمع شود. (and "string" 1 #t) به معنی AND منطقی روی "string"، 1 و #t است، و نتیجه درست خواهد بود چرا که هیچ #f وجود ندارد.

مدخل‌های برچسبی که باعث می‌شوند عبارت فیلتر مقدار درست تولید کند، توسط readtags چاپ می‌شوند.

عملگرهای پایه برای فیلتر کردن عبارتند از eq?، prefix?، suffix?، substr? و #/PATTERN/. فیلدهای مشترک زبان‌ها را می‌توان با استفاده از متغیرهایی که با $ شروع می‌شوند در دسترس قرار داد؛ برای مثال، $language نشان‌دهنده فیلد زبان است. برای نمونه:

•
فهرست کردن تمام برچسب‌هایی که با "myfunc" در فایل‌های کد پایتون شروع می‌شوند:
$ readtags -p -Q '(eq? $language "Python")' - myfunc

عملگرهای downcase یا upcase را می‌توان برای انجام تطبیق بدون حساسیت به بزرگی و کوچکی حروف به کار برد:

•
فهرست کردن تمام برچسب‌های حاوی "my"، بدون حساسیت به بزرگی و کوچکی حروف:
$ readtags -Q '(substr? (downcase $name) "my")' -l

عملگرهای منطقی مانند and، or و not نیز وجود دارند. مقدار یک فیلد ناموجود برابر با #f است، بنابراین می‌توانیم با فیلدهای ناموجود به این شکل برخورد کنیم:

•
فهرست کردن تمام برچسب‌های حاوی "impl" در فایل‌های کد پایتون، به همراه مجاز شمردن ناموجود بودن فیلد language::
$ readtags -Q '(and (substr? $name "impl")\
                    (or (not $language)\
                        (eq? $language "Python")))' -l

الگوی #/PATTERN/ برای شرایطی است که مسندهای رشته‌ای (prefix?، suffix? و substr?) کافی نیستند. می‌توانید از «عبارت باقاعده تعمیم‌یافته پوزیکس (POSIX extended regular expression)» به عنوان PATTERN استفاده کنید.

•
فهرست کردن تمام برچسب‌هایی که از کلاس "A" ارث‌بری می‌کنند:
$ readtags -Q '(#/(^|,) ?A(,|$)/ $inherits)' -l

در اینجا $inherits فهرستی از کلاس‌ها با جداکننده کاما مانند "A,B,C"، "P, A, Q"، یا فقط "A" است. توجه کنید که این فیلتر هم در حالتی که بعد از هر کاما فاصله وجود داشته باشد و هم در حالتی که فاصله نباشد، کار می‌کند.

تطبیق غیرحساس به بزرگی و کوچکی حروف را می‌توان با #/PATTERN/i انجام داد:

•
فهرست کردن تمام برچسب‌هایی که از کلاس "A" یا "a" ارث‌بری می‌کنند:
$ readtags -Q '(#/(^|,) ?A(,|$)/i $inherits)' -l

برای گنجاندن "/" در یک الگو، پیشوند \ را به "/" اضافه کنید.

نکته: الگوی عبارت باقاعده بالا برای بررسی وراثت، صرفاً مثالی برای نشان دادن نحوه استفاده از عبارت #/PATTERN/ است. تولیدکنندگان فایل‌های برچسب هیچ توافقی بر سر قالب inherits: ندارند؛ برای مثال در این باره که آیا بعد از کاما باید فاصله باشد یا خیر. حتی تجزیه‌کننده‌های موجود در ctags نیز توافقی در این زمینه ندارند. توجه به قالب فیلد inherits: در زبان‌های خاص برای چنین پرس‌وجوهایی ضروری است.

عبارت‌های #/PATTERN/ و #/PATTERN/i برای استفاده تعاملی در نظر گرفته شده‌اند. برنامه readtags همچنین نام مستعار string->regexp را ارائه می‌دهد، بنابراین #/PATTERN/ برابر با (string->regexp "PATTERN") است، و #/PATTERN/i برابر با (string->regexp "PATTERN" :case-fold #t). تابع string->regexp برای گنجاندن "/" در یک الگو نیازی به پیشوند \ ندارد. string->regexp می‌تواند ساخت عبارت را برای ابزارهای کلاینت ساده‌تر کند. همچنین برای ساخت عبارت‌ها در ابزار خود به ctags-client-tools(7) مراجعه کنید.

اکنون فیلدهای ناموجود را در نظر بگیریم. ممکن است فایل برچسب دارای مدخل‌هایی باشد که فیلد inherits: را ندارند. در این حالت $inherits برابر با #f است و تطبیق عبارت باقاعده باعث بروز خطا می‌شود، چرا که عملگرهای رشته‌ای تنها برای رشته‌ها کار می‌کنند. برای جلوگیری از این مشکل:

•
فهرست کردن ایمن تمام برچسب‌هایی که از کلاس "A" ارث‌بری می‌کنند:
$ readtags -Q '(and $inherits (#/(^|,) ?A(,|$)/ $inherits))' -l

این کار تضمین می‌کند که ابتدا $inherits ناموجود نباشد و سپس آن را با عبارت باقاعده تطبیق دهد.

گاهی مایلید برچسب‌هایی را نگه دارید که فیلد مورد نظر در آن‌ها ناموجود است. برای نمونه، می‌خواهید برچسب‌های مرجع را که توسط فیلد extras: مشخص شده‌اند کنار بگذارید؛ در این صورت می‌خواهید برچسب‌هایی را که فیلد extras: ندارند حفظ کنید، زیرا آن‌ها نیز برچسب مرجع نیستند. در ادامه نحوه انجام این کار آمده است:

•
فهرست کردن تمام برچسب‌ها به جز برچسب‌های مرجع:
$ readtags -Q '(or (not $extras) (#/(^|,) ?reference(,|$)/ $extras))' -l

توجه داشته باشید که عبارت (not $extras) هنگامی که $extras ناموجود باشد مقدار #t تولید می‌کند، بنابراین کل عبارت or مقدار #t تولید خواهد کرد.

ترکیب ctags -o - و readtags -t - برای بررسی یک فایل منبع، تا زمانی که فایل منبع به اندازه کافی کوتاه باشد، بسیار کاربردی است.

•
فهرست کردن تمام توابع بزرگ (بیش از ۱۰۰ خط) در یک فایل:
$ ctags -o - --fields=+neKz input.c \
  | ./readtags -t - -en \
               -Q '(and (eq? $kind "function") $end $line (> (- $end $line) 100))' \
               -l
•
فهرست کردن تمام برچسب‌هایی که شامل خط ۸۰ در یک فایل هستند:
$ ctags -o - --fields=+neKz input.c \
  | readtags -t - -ne \
             -Q '(and $line
                      (or (eq? $line 80)
                          (and $end (< $line 80) (< 80 $end))))' \
    -l

دستور "readtags -H filter"; را برای آگاهی از تمام توابع و متغیرهای معتبر اجرا کنید.

هنگام مرتب‌سازی، عبارت مرتب‌ساز روی دو مدخل برچسب ارزیابی می‌شود تا تعیین کند کدام‌یک باید پیش از دیگری قرار گیرد، تا زمانی که ترتیب تمام مدخل‌های برچسب مشخص شود.

در یک عبارت مرتب‌ساز، از $ و & برای دسترسی به فیلدهای دو مدخل برچسب استفاده می‌شود، و بیایید آن‌ها را $-entry و &-entry بنامیم. عبارت مرتب‌ساز باید مقداری برابر با -1، 0 یا 1 داشته باشد. مقدار -1 بدین معناست که $-entry باید بالاتر از &-entry قرار گیرد، 1 به معنای عکس آن است، و 0 ترتیب آن‌ها را در خروجی نامعین می‌سازد.

عملگر اصلی مرتب‌سازی <> است. این عملگر برای مقایسه دو رشته یا دو عدد استفاده می‌شود (اعداد مربوط به فیلدهای line: یا end: هستند). در (<> a b)، اگر a < b باشد، نتیجه -1 است؛ a > b مقدار 1 را تولید می‌کند، و a = b مقدار 0 تولید می‌کند. رشته‌ها با استفاده از تابع strcmp مقایسه می‌شوند؛ strcmp(3) را ببینید.

به عنوان مثال، مرتب‌سازی بر اساس نام‌ها، و قرار دادن مواردی که کوتاه‌ترند یا از نظر الفبایی کوچک‌تر هستند پیش از سایرین:

$ readtags -S '(<> $name &name)' -l

این عبارت به این صورت خوانده می‌شود: «اگر نام برچسب در $-entry کوچک‌تر باشد، قبل از &-entry قرار می‌گیرد».

عملگر <or> برای زنجیره‌بندی چندین عبارت به کار می‌رود تا زمانی که یکی از آن‌ها مقدار -1 یا 1 بازگرداند. برای مثال، مرتب‌سازی بر اساس نام فایل‌های ورودی، و سپس شماره خطوط در صورت وجود در یک فایل یکسان:

$ readtags -S '(<or> (<> $input &input) (<> $line &line))' -l

عملگر *- برای معکوس کردن نتیجه مقایسه استفاده می‌شود؛ یعنی (*- (<> a b)) همانند (<> b a) است.

عبارت‌های فیلتر را می‌توان در عبارت‌های مرتب‌ساز نیز به کار برد. روش کار به این صورت است که از if برای تولید اعداد صحیحی استفاده می‌شود که می‌توان آن‌ها را بر اساس فیلتر مقایسه کرد، مانند:

(<> (if filter-expr-on-$-entry -1 1)
    (if filter-expr-on-&-entry -1 1))

بنابراین اگر $-entry با فیلتر مطابقت داشته باشد، در حالی که &-entry مطابقت نداشته باشد، همانند (<> -1 1) خواهد بود که مقدار -1 را تولید می‌کند.

برای مثال، می‌خواهیم برچسب‌هایی از نوع "file" را در زیر سایر برچسب‌ها قرار دهیم؛ در این صورت مرتب‌ساز به شکل زیر خواهد بود:

(<> (if (eq? $kind "file") 1 -1)
    (if (eq? &kind "file") 1 -1))

بررسی سریع به ما نشان می‌دهد: اگر $-entry از نوع "file" باشد و &-entry نباشد، مرتب‌ساز به صورت (<> 1 -1) درمی‌آید که مقدار 1 تولید می‌کند، در نتیجه $-entry در زیر &-entry قرار می‌گیرد که دقیقاً همان خواسته ما است.

یک عبارت قالب‌بند تعیین می‌کند که readtags چگونه مدخل‌های برچسب را چاپ کند.

یک عبارت قالب‌بند ممکن است یک رشته، یک مقدار بولی، یک عدد صحیح، یا یک فهرست تولید کند. readtags رشته و عدد صحیح تولیدشده را همان‌گونه که هستند چاپ می‌کند. برای #f چیزی چاپ نمی‌کند و برای #t یک خط جدید چاپ می‌کند.

یک فهرست می‌تواند شامل هر تعداد رشته، مقادیر بولی، اعداد صحیح، و/یا فهرست‌ها باشد. readtags عناصر یک فهرست را به‌صورت ترتیبی و بازگشتی چاپ می‌کند.

تمام عملگرهای مربوط به فیلتر کردن در عبارت‌های قالب‌بند نیز در دسترس هستند. علاوه بر این عملگرها، list نیز در عبارت‌های قالب‌بند در دسترس است. همان‌طور که از نام آن مشخص است، list برای ایجاد یک فهرست به کار می‌رود. list فهرستی شامل آرگومان‌های داده‌شده به عملگر ایجاد می‌کند؛ برای نمونه، عبارت زیر فهرستی شامل 1، #f و "hello" می‌سازد:

(list 1 #f "hello")

نکته: برخلاف لیسپ واقعی، ساختارهای نقل‌قول معکوس (backquote) در دسترس نیستند.

برای نشان دادن چند مثال، فایل برچسب زیر (output.tags) به عنوان ورودی برای readtags فرض شده است:

M    input.c 4;"     macro   file:
N    input.c 3;"     macro   file:
bar  input.c 11;"    f       typeref:typename:void   file:   signature:(char ** argv,int * r)
foo  input.c 6;"     f       typeref:typename:int    file:   signature:(int v)
main input.c 16;"    f       typeref:typename:int    signature:(int argc,char ** argv)

مثالی برای چاپ فقط نام توابع:

$ readtags -t output.tags -Q '(eq? $kind "function")' -F '(list $name #t)' -l
bar
foo
main

انجام همان کار تنها با یک عبارت قالب‌بند:

$ readtags -t output.tags -F '(if (eq? $kind "function") (list $name #t) #f)' -l
bar
foo
main

تولید اعلان‌ها (declarations) برای توابع:

$ readtags -t output.tags -F \
  '(if (eq? $kind "function")
      (list (if $file "static " #f) $typeref-name " " $name $signature ";" #t)
     #f)' -l
static void bar(char ** argv,int * r);
static int foo(int v);
int main(int argc,char ** argv);

عملگر print را می‌توان برای چاپ مقدار یک عبارت استفاده کرد. برای مثال:

$ readtags -Q '(print $name)' -l

نام هر مدخل برچسب را قبل از آن چاپ می‌کند. از آنجا که مقدار بازگشتی print برابر با #f نیست، تمام مدخل‌های برچسب چاپ می‌شوند. ما می‌توانیم با استفاده از عملگرهای begin یا begin0 این مورد را کنترل کنیم. begin مقدار آخرین آرگومان خود را برمی‌گرداند، و begin0 مقدار نخستین آرگومان خود را برمی‌گرداند. برای مثال:

$ readtags -Q '(begin0 #f (print (prefix? "ctags" "ct")))' -l

تعدادی "#t" چاپ می‌کند (بسته به این‌که چه تعداد خط در فایل برچسب‌ها وجود دارد)، و خود مدخل‌های اصلی برچسب چاپ نمی‌شوند.

برای جزئیات قالب فایل برچسب‌ها tags(5) را ببینید.

برای نکاتی در خصوص نوشتن ابزاری که از فایل برچسب‌ها استفاده می‌کند ctags-client-tools(7) را ببینید.

وب‌سایت رسمی Universal Ctags در:

https://ctags.io

مخزن گیت برای کتابخانه استفاده‌شده در دستور readtags:

https://github.com/universal-ctags/libreadtags

پروژه Universal Ctags https://ctags.io

دارن هیبرت (Darren Hiebert) <<dhiebert@users.sourceforge.net>> http://DarrenHiebert.com

دستور readtags و libreadtags که در پروژه Universal Ctags نگهداری می‌شوند برگرفته از readtags.c و readtags.h هستند که در http://ctags.sourceforge.net توسعه یافته‌اند.

6.2.1