پرش به محتوای اصلی
پرش به محتوای مقاله

Ghostel لایه‌ی libghostty-vt را به Emacs آورد تا تأخیر ترمینال را حذف کند

·۲۱ تیر ۱۴۰۵۵۶ دقیقه مطالعه
شبیه‌ساز ترمینال مبتنی بر libghostty
شبیه‌ساز ترمینال مبتنی بر libghostty
اشتراک‌گذاری
واقعاً چه چیز جدید است؟

جایگزینی کامل موتورهای قدیمی با libghostty-vt در محیط Emacs؛ این اولین باری است که قابلیتی مثل Synchronized Output و پروتکل گرافیکی Kitty به‌صورت بومی و با تأخیر نزدیک به صفر در یک بافر Emacs پیاده‌سازی شده است.

تصور کنید تمام قدرت یک ترمینال مدرن و سریع را درست در قلب Emacs داشته باشید، بدون اینکه با کندی یا تداخل کلیدها دست‌و‌پنجه نرم کنید. اگر از کاربران حرفه‌ای Emacs هستید، Ghostel دقیقاً همان حلقه‌ی گمشده‌ای است که فاصله بین سرعت اجرای دستورات و مدیریت متن در بافر را از بین می‌برد.

در جولای ۲۰۲۶، ابزاری به نام Ghostel معرفی شد که با جایگزینی موتورهای قدیمی با libghostty-vt، استانداردهای عملکردی را در محیط Emacs جابه‌جا کرد. این ابزار محدودیت‌های همیشگی ترمینال‌های داخلی Emacs را با سپردن مدیریت وضعیت ترمینال و رندرینگ به یک ماژول دینامیک بومی که با زبان Zig نوشته شده، حل کرده است.

همان‌طور که در تحلیل‌های پیشین ما درباره‌ی بهینه‌سازی محیط‌های توسعه اشاره کردیم، توازن بین سادگی و قدرت همیشه چالش اصلی کاربران Emacs بوده است. کاربران برای سال‌ها بین سادگی shell و قدرت vterm مردد بودند؛ چرا که همواره یک «ناهمگونی» (Impedance Mismatch) بین جریان زنده‌ی ترمینال و میل Emacs به مدیریت متن وجود داشت. Ghostel با استفاده از همان موتور VT که ترمینال مستقل Ghostty را می‌راند، تضمین می‌کند که پروتکل‌های مدرن ترمینال خارج از حلقه‌ی اصلی Elisp پردازش شوند.

معماری سرعت

به نقل از مستندات رسمی در dakra.github.io، ساختار Ghostel بر دو لایه‌ی مجزا استوار است. یک ماژول بومی مسئول مدیریت وضعیت‌های پیچیده‌ی ترمینال، رندرینگ و ورودی/خروجی‌های محلی PTY است، در حالی که Elisp تنها تجربه‌ی کاربری سطح بالا، نقشه‌های کلید (keymaps)، بافرها و ادغام فرآیندهای راه دور را مدیریت می‌کند. این رویکرد که از emacs-libvterm الهام گرفته شده، به دلیل بهره‌گیری از موتور مدرن Ghostty، قابلیت‌هایی را فعال می‌کند که libvterm هرگز پشتیبانی نمی‌کرد.

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

  • مسار PTY بومی: با استفاده از یک رشته (thread) پس‌زمینه برای مصرف خروجی، Emacs تنها زمانی که نیاز به بازترسیم (redraw) باشد مطلع می‌شود. این مکانیزم از خفه شدن فیلتر فرآیند Emacs توسط جریان‌های حجیم لاگ جلوگیری می‌کند. این ویژگی توسط متغیر ghostel-use-native-pty (مقدار پیش‌فرض t) کنترل می‌شود.
  • بازترسیم فوری: برای حذف تأخیر ۱۶ تا ۳۳ میلی‌ثانیه‌ای هنگام تایپ که در ترمینال‌های شبیه‌ساز رایج است، خروجی‌هایی که بلافاصله پس از یک ضربه کلید می‌رسند، از طریق ghostel-immediate-redraw-interval (مقدار پیش‌فرض ۰.۰۵ ثانیه) تایمرهای استاندارد را دور می‌زنند.
  • جذب داده‌های حجیم: این سیستم به‌گونه‌ای طراحی شده است که بتواند حجم‌های عظیم داده، مانند اجرای دستور cat برای یک فایل ۱۰ مگابایتی، را بدون منجمد کردن ادیتور مدیریت کند.
  • رندرینگ تطبیقی: Ghostel از بازترسیم‌های افزایشی برای نادیده گرفتن ردیف‌های بدون تغییر استفاده می‌کند و نرخ فریم تطبیقی را از طریق ghostel-timer-delay (مقدار پیش‌فرض ۰.۰۳۳ ثانیه) تنظیم می‌کند.

قابلیت‌های پیشرفته‌ی ترمینال

به دلیل استفاده از libghostty-vt، این ابزار ویژگی‌هایی را ارائه می‌دهد که پیش از این در گزینه‌های ترمینال Emacs مثل libvterm غیرممکن بودند:

  • پروتکل گرافیکی Kitty: کاربران می‌توانند تصاویر را به‌صورت درون‌خطی در بافر رندر کنند. این قابلیت از جایگذاری‌های سنتی (مانند timg یا kitty +kitten icat) و همچنین جایگذاری‌های جایگزین یونیکد (U+10EEEE) که توسط ابزارهایی مثل yazi استفاده می‌شود، پشتیبانی می‌کند. Ghostel برای پردازش PNGها از stbimage داخلی استفاده کرده و مقادیر RGB/RGBA/Gray را به PPM تبدیل می‌کند. لازم به ذکر است که کانال‌های آلفا در طول تبدیل حذف می‌شوند و برش مستطیلی منبع (source-rect cropping) پشتیبانی نمی‌شود. حد مجاز ذخیره‌سازی گرافیک‌ها در ghostel-kitty-graphics-storage-limit پیش‌فرض ۳۲۰ میبایت است. به دلیل مسائل امنیتی، رسانه‌های غیرمستقیم (non-direct mediums) از طریق ghostel-kitty-graphics-mediums به صورت اختیاری فعال می‌شوند.
  • خروجی همگام‌شده (دسامبر ۲۰۲۶): این پروتکل اثر «پله‌ای» یا تکه‌تکه شدن صفحه را که هنگام بازترسیم بخش‌های بزرگ توسط عامل‌های هوش مصنوعی مثل Claude Code دیده می‌شد، به‌طور کامل حذف می‌کند.
  • ویژگی‌های متنی غنی: پشتیبانی کامل از رنگ‌های ۲۴ بیتی (True Color RGB)، استایل‌های متنوع زیرخط (تک، دبل، موج‌دار/curly، نقطه‌چین و خط‌چین) و طیف کاملی از استایل‌های مکان‌نما (بلاک، خط/bar، زیرخط، بلاک توخالی؛ که هر کدام می‌توانند ثابت یا چشمک‌زن باشند).
  • هایپرلینک‌های OSC 8: لینک‌های قابل کلیکی که توسط برنامه‌های ترمینال ارسال می‌شوند، کاملاً پشتیبانی می‌شوند. علاوه بر این، ghostel-enable-url-detection لینک‌های متنی ساده http/https را به‌صورت خودکار شناسایی و فعال می‌کند.
  • هوش رنگی: برنامه‌های TUI مثل btop یا delta می‌توانند از طریق کوئری‌های رنگی OSC 4، 10 و 11، تم Emacs را شناسایی کرده و پالت رنگی روشن یا تیره را به‌صورت خودکار انتخاب کنند. ۱۶ رنگ ANSI بر اساس وجه‌هایی (faces) که از term-color-* ارث‌بری می‌کنند، مدیریت می‌شوند. همچنین ghostel-bold-color اجازه می‌دهد متن‌های Bold را به صورت یک رشته رنگی خاص #RRGGBB یا یک نسخه روشن تعریف کنید.
  • اعلان‌ها و پیشرفت: پشتیبانی از پروتکل‌های OSC 9 (iTerm2) و OSC 777 (rxvt) برای ارسال اعلان‌ها به ghostel-notification-function. اگر بسته alert نصب باشد، از بک‌اندهای بومی سیستم‌عامل مثل osascript (در macOS) یا libnotify (در لینوکس) استفاده می‌کند. برای ردیابی پیشرفت، از پروتکل OSC 9;4 مربوط به ConEmu پشتیبانی شده و درصدها (مثلاً [42%]) یا یک انیمیشن چرخان (spinner) را از طریق spinner.el در mode-line نمایش می‌دهد (تنظیمات در ghostel-progress-function).

حالت‌های ورودی هوشمند

Ghostel برای حل تداخل بین دستورات Emacs و کلیدهای ارسالی به شل، پنج حالت ورودی distinto تعریف کرده است. شما می‌توانید حالت فعلی را از طریق نشان‌گر mode-line-process ردیابی کنید:

۱. Semi-char (پیش‌فرض): اکثر کلیدها به ترمینال می‌روند. استثناهایی مثل M-x, C-x, C-u, C-h و M-: برای Emacs رزرو شده‌اند. انتقال به این حالت با C-c C-j انجام می‌شود. اکشن‌های کلیدی شامل C-c C-c برای قطع (interrupt)، C-c C-z برای تعلیق (suspend)، C-c C-d برای EOF، C-c M-w برای کپی کل تاریخچه (scrollback) به kill ring و C-c M-l برای پاک کردن تاریخچه است.
۲. Char Mode: با C-c M-d وارد این حالت می‌شوید؛ در اینجا هر کلیدی بدون استثنا به ترمینال ارسال می‌شود. این حالت برای برنامه‌های TUI پیچیده که کلیدهایی مثل C-x یا M-x را برای خود رزرو کرده‌اند، ضروری است. تنها راه خروج M-RET (یا C-M-m) است.
۳. Emacs Mode: با C-c C-e فعال می‌شود. بافر فقط-خواندنی می‌شود اما زنده می‌ماند. شما می‌توانید از isearch-forward یا occur برای فیلتر کردن لاگ‌های جاری بدون متوقف کردن فرآیند استفاده کنید. کلیدهای تایپ شده به شل نمی‌رسند، مگر C-y که متن را از طریق bracketed paste می‌چسباند. برای پرش به اعلان‌ها (prompts) در این حالت از C-c M-n یا C-c M-p استفاده کنید.
۴. Copy Mode: با C-c C-t فعال می‌شود. مشابه حالت Emacs است اما خروجی ترمینال را کاملاً منجمد می‌کند تا در هنگام استریم شدن لاگ‌ها، انتخاب متن پایدار بماند. این حالت به‌طور خودکار خطوط جدید ناشی از wrapping نرم را از متن کپی شده حذف می‌کند و با هر کلید self-insert (از طریق ghostel-readonly-fast-exit) به‌طور خودکار بسته می‌شود.
۵. Line Mode: با C-c C-l فعال می‌شود. بافر مانند یک فیلد متنی محلی عمل می‌کند که در آن می‌توانید یک خط کامل را با تمام قدرت ویرایشی Emacs (از جمله M-b, M-DEL, C-y و transpose-words) ویرایش کنید. کل خط تنها پس از فشردن RET به‌صورت یک‌جا ارسال می‌شود. اگر یک TUI تمام‌صفحه شروع شود، Ghostel به‌طور خودکار به حالت semi-char رفته و پس از خروج از TUI دوباره به line mode باز می‌گردد. این حالت از تکمیل خودکار bash (از طریق ghostel-line-mode-use-bash-completion) پشتیبانی می‌کند و در صورت نبود مارکرهای OSC 133، از ghostel-prompt-regexp استفاده می‌کند.

تعامل با ماوس و مکان‌نما

منطق پیچیده‌ی ماوس در Ghostel باعث می‌شود ادیتور روان باقی بماند. یک کلیک و کشیدن (click-and-drag) یک ناحیه (region) ایجاد می‌کند و پس از رها کردن، Ghostel بسته به تنظیم ghostel-mouse-drag-input-mode (پیش‌فرض copy) حالت ورودی را تغییر می‌دهد تا خروجی‌های جاری selection را به‌هم نریزند.

اگر یک TUI دارای ردیابی ماوس DEC (کدهای ۱۰۰۰/۱۰۰۲/۱۰۰۳ مثل htop یا lazygit) باشد، کلیک مستقیماً به برنامه ارسال می‌شود. علاوه بر این، مکانیزم ghostel-point-leave-input-mode تضمین می‌کند که هنگام استفاده از ابزارهایی مثل consult-line یا isearch مکان‌نما به‌طور تصادفی هنگام بازترسیم به موقعیت کرسر ترمینال پرتاب نشود.

برای بسته‌های Jump سفارشی، دستور ghostel-maybe-leave-input را می‌توان به عنوان یک hook (مثلاً flash-after-jump-hook) یا به عنوان advice با :after (مثلاً برای avy-action-goto) اضافه کرد تا موقعیت point خارج از کرسر زنده حفظ شود.

امنیت و ادغام راه دور

یکی از کاربردی‌ترین بخش‌ها، تشخیص اعلان رمز عبور (Password Prompt Detection) است. وقتی برنامه‌ای مثل sudo یا ssh یا gpg درخواست رمز عبور می‌کند، Ghostel تشخیص می‌دهد که slave TTY در حالت canonical با echo خاموش است. سپس یک پنجره امن read-passwd باز می‌کند. برای جلوگیری از باقی ماندن رمز در heap حافظه، مقدار آن بلافاصله پس از ارسال پاک (clear-string) می‌شود. برای میزبان‌های راه دور، سیستم به رگکس ردیف مکان‌نما (ghostel-password-prompt-regex) متکی است. این تشخیص از طریق ghostel-password-prompt-functions قابل گسترش است تا کاربر بتواند مدیریت‌کننده‌های auth-source یا KeePass را اضافه کند.

اتصالات راه دور از طریق TRAMP مدیریت می‌شوند. Ghostel می‌تواند شل‌ها را روی میزبان‌های راه دور با استفاده از ghostel-tramp-shells اجرا کند. این متغیر اجازه پیکربندی بر اساس متد را می‌دهد، مثلاً ("docker" "/bin/sh"). شل‌های شناخته شده مثل bash، zsh و fish به‌طور پیش‌فرض به صورت login+interactive (-l -i) اجرا می‌شوند. ردیابی دایرکتوری (OSC 7) با TRAMP سازگار است، به این معنی که default-directory با تغییر مسیر در شل، به مسیر TRAMP متناظر به‌روزرسانی می‌شود. اگر پیشوندی برای TRAMP وجود نداشته باشد، متد پیش‌فرض tramp-default-method یا ghostel-tramp-default-method در نظر گرفته می‌شود.

Ghostel برای اطمینان از اینکه برنامه‌های راه دور از مسیرهای سریع (fast paths) استفاده کنند، نصب فایل terminfo xterm-ghostty را مدیریت می‌کند:

  • مدل TRAMP-launched: فایل terminfo کامپایل شده را از طریق اتصال موجود به یک دایرکتوری موقت در مقصد می‌فرستد. هر دو چیدمان لینوکس (x/, g/) و macOS (78/, 67/) پشتیبانی می‌شوند و هیچ چیزی روی مقصد باقی نمی‌ماند.
  • مدل Outbound SSH: یک Wrapper دستور ssh را سایه می‌کند و با استفاده از کش در ~/.cache/ghostel/ssh-terminfo-cache بررسی می‌کند که آیا ورودی در مقصد وجود دارد یا خیر. در صورت نبود، آن را از طریق tic -x - در ~/.terminfo/ نصب می‌کند. توصیه می‌شود برای جلوگیری از درخواست‌های متعدد احراز هویت، از ControlMaster در SSH استفاده کنید.

کاربران می‌توانند با تنظیم ghostel-ssh-install-terminfo روی nil این اتوماسیون را غیرفعال کرده و به‌صورت دستی با دستور infocmp -x xterm-ghostty | ssh REMOTE 'mkdir -p ~/.terminfo && tic -x -' آن را منتقل کنند.

فراخوانی Elisp از داخل شل

Ghostel اجازه می‌دهد اسکریپت‌های شل توابع Emacs را با استفاده از یک افزونه خصوصی OSC 52 (\e]52;e;<payload>\e\) تحریک کنند. با استفاده از کمکی به نام ghostel_cmd در شل، کاربر می‌تواند علیاس‌هایی بسازد تا فایل‌ها در Emacs باز شوند.

برای مثال، افزودن کد زیر به .bashrc یا .zshrc اجازه می‌دهد شل، Magit یا Dired را برای دایرکتوری جاری باز کند:

if [[ "${INSIDE_EMACS%%,*}" = 'ghostel' ]]; then
  e() { ghostel_cmd find-file-other-window "$@"; }
  dow() { ghostel_cmd dired-other-window "${1:-$PWD}"; }
  gst() { ghostel_cmd magit-status-setup-buffer "$(pwd)"; }
fi

برای امنیت، تنها توابعی که در لیست سفید ghostel-eval-cmds (مانند find-file, dired, message) قرار دارند اجازه اجرا می‌یابند.

افزونه‌های توسعه‌دهنده

Ghostel به‌گونه‌ای طراحی شده که سبک بماند و منطق‌های تخصصی را به افزونه‌ها بسپارد:

  • Evil-mode: افزونه evil-ghostel مکان‌نمای ترمینال را با point در Emacs در طول تغییرات وضعیت همگام می‌کند تا ناوبری با hjkl در حالت Normal ممکن شود.
  • Compilation Mode: افزونه ghostel-compile جایگزین استاندارد M-x compile می‌شود و یک TTY واقعی ایجاد می‌کند. این باعث می‌شود ابزارهایی که isatty(3) را بررسی می‌کنند، رنگ‌ها و نوارهای پیشرفت را نمایش دهند، در حالی که ghostel-compile-view-mode برای ناوبری در خطاها حفظ می‌شود. دستورات make compile, recompile و project-compile همگی قابل تنظیم برای استفاده از ghostel هستند.
  • سایر ادغام‌ها: پشتیبانی از Eshell از طریق ghostel-eshell (متصل به eshell-load) و Comint از طریق بسته ghostel-comint فراهم شده است.

نصب و پیش‌نیازها

این ابزار به Emacs 28.1+ با پشتیبانی از ماژول‌های دینامیک نیاز دارد و با macOS، لینوکس، FreeBSD و ویندوز (با استفاده از ConPTY) سازگار است. در ویندوز، DLL ماژول باید با معماری Emacs مطابقت داشته باشد. ترمینال‌های محلی در ویندوز از runtime کنسول مایکروسافت (conpty.dll و OpenConsole.exe) استفاده می‌کنند و در صورت نبود، به API داخلی باز می‌گردند. ترمینال‌های راه دور TRAMP از ویندوز محدود به مقصد‌های POSIX هستند و در حال حاضر از تغییر اندازه دینامیک (dynamic resize) پشتیبانی نمی‌کنند.

جزئیات نصب

  • MELPA: استفاده از (use-package ghostel :ensure t).
  • VC (Emacs 30+): استفاده از :vc (:url "https://github.com/dakra/ghostel" :lisp-dir "lisp" :rev :newest).
  • ماژول بومی: ماژول معمولاً به‌صورت خودکار از طریق ghostel-module-auto-install (پیش‌فرض ask) دانلود می‌شود. کاربران می‌توانند دستی M-x ghostel-download-module یا M-x ghostel-module-compile را اجرا کنند. اگر مدیر بسته درخت فایل‌ها را بازسازی کند، ghostel-module-directory می‌تواند به یک مکان پایدار مثل ~/.config/emacs/ghostel/ اشاره کند.
  • ساخت از منبع: نیازمند Zig 0.15.2 است. دستور ساخت zig build --prefix . -Doptimize=ReleaseFast است. در ویندوز، معمولاً از هدف x86_64-windows-gnu برای مطابقت با بیلد بومی Emacs استفاده می‌شود.

برای شروع، کاربران باید بسته را نصب کرده و M-x ghostel را برای اولین نشست اجرا کنند. برای کاربران پیشرفته، تنظیمات از طریق M-x customize-group RET ghostel قابل تغییر است.

گام بعدی شما

  • اگر از Emacs استفاده می‌کنید، بسته ghostel را نصب کرده و اولین نشست خود را با M-x ghostel آغاز کنید.
  • برای شخصی‌سازی دقیق رفتار ترمینال، گروه تنظیمات را با M-x customize-group RET ghostel بررسی کنید.
  • اگر از TUIهای گرافیکی مثل yazi استفاده می‌کنید، پروتکل Kitty را در تنظیمات فعال کنید تا تصاویر را مستقیماً در بافر ببینید.

اما برای کسانی که به دنبال جایگزینی کامل محیط ترمینال با یک اکوسیستم هوشمندتر هستند، تحلیل ما درباره‌ی پروتکل‌های جدید مدل‌های استدلالی در تعامل با شل، قطعه گم‌شده‌ی این پازل است.

چرا این موضوع مهم است؟

این ابزار با حذف تأخیر در ورودی/خروجی و پشتیبانی از گرافیک‌های مدرن، Emacs را برای عصر عامل‌های هوش مصنوعی که خروجی‌های حجیم و پویا تولید می‌کنند، آماده می‌کند. اعتبار این پروژه از بهره‌گیری از موتور اثبات‌شده‌ی Ghostty می‌آید که استانداردهای سرعت در ترمینال‌های مدرن را تعریف کرده است.

تأثیر برای ایران

برای توسعه‌دهندگان ایرانی که از Emacs به عنوان محیط اصلی کدنویسی استفاده می‌کنند، این ابزار بهره‌وری را در مدیریت سرورهای راه دور (TRAMP) به‌شدت افزایش می‌دهد و نیازی به جابه‌جایی مداوم بین ادیتور و ترمینال‌های خارجی ندارد.

·نگاه ما
تحریریه دات‌هوش

Ghostel با انتقال لایه‌ی رندرینگ به خارج از Elisp، در واقع پذیرفته است که تفسیر پروتکل‌های پیچه‌ی ترمینال در زبان Lisp با محدودیت‌های ذاتی سرعت مواجه است. این رویکرد «ماژول بومی برای پردازش سنگین و Elisp برای مدیریت تجربه کاربری»، الگوی جدیدی برای توسعه افزونه‌های Emacs است که می‌خواهند با استانداردهای ۲۰۲۶ رقابت کنند. به نظر ما، موفقیت این ابزار در این است که سعی نکرده ترمینال را در Emacs «شبیه‌سازی» کند، بلکه یک ترمینال واقعی را در دل ادیتور «جای‌گذاری» کرده است.

منابع

این گزارش با خط‌لولهٔ خودکار دات‌هوش از منابع معتبر جهانی تدوین و زیر نظر تحریریه منتشر شده است. روش کار ما

گفتگو

پنج‌شنبه‌های هوش‌محور

بسته‌ی هفتگی دات‌هوش

۵ خبر، ۲ ابزار، ۱ پرامپت در هر شماره. به‌زودی راه‌اندازی می‌شود — هر پنج‌شنبه صبح.

خبر کلیدی
ابزار کاربردی
پرامپت حرفه‌ای
تحلیل پژوهش
به‌زودی
زاویه‌ی ایرانی
به‌زودی
تمرین این هفته
به‌زودی

راهنماهای دات‌هوش

راهنماهای کاربردیِ دات‌هوش برای کار با هوش مصنوعی — از همین‌جا شروع کنید:

دات‌هوش

راهنمای فارسی هوش مصنوعی — با نگاه به ایران

اخبار روزانه، معرفی ابزارها و مدل‌ها، و آموزشِ کار با هوش مصنوعی؛ همیشه با این پرسش که از ایران چه چیزی کار می‌کند و چه چیزی نه.