fa-console
- مخزن: https://github.com/Padandish/fa-console (بستهٔ PyPI با نام
fa-consoleنسخهٔ 2.2.0) · کامیت خواندهشده: 007d75a (۲۰۲۶-۰۹-۰۹) · مجوز: MIT · زبان: Python ≥3.8، یک فایل واحدfa_console.py(۱٬۳۳۱ خط) · سکو: ویندوز (conhost کلاسیک + ترمینال VS Code)؛ در جاهای دیگر بیاثر است مگر بهاجبار فعال شود - دسته: تبدیل خروجی (پوششدهندهٔ درونفرایندی
sys.stdout) + کتابخانه
این پروژه چیست
Section titled “این پروژه چیست”اصلاحکنندهای برای برنامههای پایتون روی ویندوز که هنگام import اجرا میشود. دو کار انجام میدهد:
- رمزگذاری: صفحهٔ کد (code page) کنسول را روی UTF-8 میگذارد، جریانهای استاندارد را دوباره پیکربندی میکند،
PYTHONUTF8/PYTHONIOENCODINGرا تثبیت میکند و یک قلم TrueType برای کنسول تنظیم میکند. - نمایش: روی
sys.stdout/sys.stderrیکVisualStreamنصب میکند که هر نوشتن را با شکلدهی (shaping) مبتنی بر فرمهای نمایشی (presentation forms) به ترتیب دیداری (visual order) تبدیل میکند.
همچنین یک ویرایشگر خط با پژواک زنده (fa_input) و یک یکسانساز نویسههای همشکل فارسی/عربی (fa_normalize) همراه دارد.
چگونه کار میکند (تأییدشده در کد)
Section titled “چگونه کار میکند (تأییدشده در کد)”- راهاندازی خودکار هنگام import:
setup_console()هنگام import ماژول اجرا میشود (fa_console.py:1305-1308). مقدارos.environ["PYTHONIOENCODING"]="utf-8"وPYTHONUTF8="1"را مینویسد (:1087-1088). روی ویندوزSetConsoleOutputCP/SetConsoleCP(65001)(:432-459) وSetCurrentConsoleFontEx("Courier New")(:462-527،_DEFAULT_FONTدر:235) را فرا میخواند. سپس روی هر سه جریانstream.reconfigure(encoding="utf-8", errors="replace")را صدا میزند (:549-583). - چه زمانی تبدیل دیداری روشن است (
:1110-1127):FA_CONSOLE_NO_VISUAL/FA_CONSOLE_FORCE_VISUALتصمیم را تغییر میدهند. در غیر این صورت فقط روی ویندوز، وقتیstdout.isatty()برقرار است و ترمینال «مدرن» نیست، روشن میشود._modern_terminal()یعنیWT_SESSIONتنظیم شده باشد، یا هرTERM_PROGRAMبهجزvscode(:586-602). لولهها و فایلها منطقی میمانند (قرارداد:101-104،:1121). - دو پیشانه (backend) (
_VisualTransformer،:633-851):- اختیاری:
arabic_reshaper.ArabicReshaper({"language":"Farsi"})+bidi.algorithm.get_display(:658-679، بهصورت extras درpyproject.toml). این UAX #9 واقعی از طریق python-bidi است، اما همچنان ترتیب دیداری و فرمهای نمایشی تولید میکند. - درونی (بدون وابستگی):
shape()(:710-776) حروف را از طریق_DUAL_FORMS/_RIGHT_FORMS/_LAM_ALEFبه فرمهای نمایشی U+FB50–FDFF / U+FE70–FEFF نگاشت میکند (:258-322). حروف فارسی پ چ ژ ک گ ی ۀ، هر دو صورت ي/ی و ك/ک، و چند حرف اردو را پوشش میدهد. نیمفاصله (ZWNJ) اتصال را میشکند و از خروجی حذف میشود (:728-730). نشانههای شفاف فقط U+064B–065F و U+0670 هستند (:334). باگ لامالف: پیشنگری از روی اعراب رد میشود (:750-751)، اما کد سپسi += 2انجام میدهد (:764)، پس در «لَا» الف و فتحه بهاشتباه حذف میشوند. - جابهجایی درونی (
reorder_line،:780-821): UAX #9 نیست. اگر خطی هر حرف راستبهچپی داشته باشد، کل خط وارونه میشود. فقط بیشینهبخشهایی از نویسههای غیر راستبهچپisalnum، ارقام فارسی/عربی، ٫/٬ و./,میان ارقام سرپا نگه داشته میشوند. شش کروشهٔ ASCII قرینه میشوند. جهت پاراگراف تشخیص داده نمیشود: یک جملهٔ انگلیسی با یک واژهٔ فارسی کاملاً وارونه میشود. عبارتهای لاتین چندواژهای ترتیب واژههایشان برعکس میشود، چون فاصله یک توکن LTR به حساب نمیآید.
- اختیاری:
- دانهبندی:
VisualStream.writeهر فراخوانیwrite()را جداگانه تبدیل میکند (:901-903) و آن را روی\nمیشکند (:844-851).print(a, b)برای مقدارها، جداکنندهها و پایان، نوشتنهای جداگانه انجام میدهد، پس یک خط دیداری ممکن است بهصورت چند تکهٔ جدا جابهجا شود. - ANSI/CSI: اصلاً مدیریت نمیشود (در کل ماژول هیچ
\x1bی نیست). در جابهجایی درونی،ESC(<0x20) یک مرز است، اما[، ارقام و حرف پایانی نویسههای معمولیاند. بنابراین\x1b[31mدر یک خط راستبهچپ بهصورت31m]و پس از آنESCبیرون میآید: خراب، و[هم قرینه شده است.get_displayدر python-bidi هم به همان اندازه از ANSI بیخبر است. مستندات به کاربران میگویندcoloramaرا پس از این ماژول import کنند (:123-125،README.md:204). - ورودی:
_ConhostLineEditor(:965-1052) کلیدها را باmsvcrt.getwch()میخواند، یک بافر منطقی (logical buffer) نگه میدارد و با هر کلید\r + visual(prompt+buffer)را دوباره میکشد. کلیدهای جهتنما، کلیدهای F و Tab بلعیده میشوند (مکاننما جابهجا نمیشود)؛ برای پرکردن فاصله ازlen()بهعنوان پهنا استفاده میشود (:1012). متن منطقی را برمیگرداند، و در صورت انتخاب آن را باfa_normalizeیکسانسازی میکند (:1154-1196). - یکسانسازی (normalization):
fa_normalizeي→ی و ك→ک را یکی میکند و میتواند ارقام ASCII، عربی-هندی و فارسی را یکسان کند؛ این کار باstr.translateو بدون تغییر طول انجام میشود (:362-401،:1199-1245). - آزمونها:
tests/test_fa_console.pyلیگاتورها، نیمفاصله، جداکنندههای رقم، قرینهسازی، دروازهگذاری با متغیرهای محیطی و یکسانسازی را پوشش میدهد. هیچ آزمونی برای دنبالههای گریز یا پاراگرافهای دوجهته (mixed-direction) وجود ندارد.
پوشش لایهها
Section titled “پوشش لایهها”| لایه | وضعیت | شاهد |
|---|---|---|
| ۱ رمزگذاری و یکسانسازی | ✅ | صفحهٔ کد UTF-8 + پیکربندی دوبارهٔ جریانها + تثبیت متغیرهای محیطی (:432-459, 549-583, 1087)؛ یکسانسازی ي/ك←ی/ک و ارقام (:362-401, 1199-1245). NFC/NFKC و یکسانسازی نیمفاصله ندارد |
| ۲ ورودی | ◐ | ویرایشگر خط با بافر منطقی و پژواک دیداری زنده (:965-1052)؛ یکسانسازی گونههای چیدمان صفحهکلید؛ جابهجایی مکاننما و آگاهی از IME ندارد |
| ۳ پهنا | ❌ | len() بهعنوان تعداد ستونها به کار رفته (:1012-1016)؛ حذف نیمفاصله از نمایش تعداد خانهها را تغییر میدهد |
| ۴ شکلدهی | ◐ | جایگزینی با فرمهای نمایشی (جدولهای درونی یا arabic-reshaper) |
| ۵ دوجهتی | ◐ | پیشانهٔ python-bidi = UAX #9؛ پیشانهٔ درونی = روش حدسی وارونهسازی کل خط (:780-821) |
| ۶ مکاننما، انتخاب و کپی | ◐ | دادههای برنامه منطقی میمانند (خوب)، اما صفحهٔ کنسول فرمهای نمایشی را با ترتیب دیداری نگه میدارد، پس کپی از پنجرهٔ کنسول خراب است |
| ۷ قلمها | ◐ | قلم conhost را برای پوشش گلیفهای عربی بهزور روی Courier New میگذارد (:462-527) |
| ۸ مالتیپلکسرها | ❌ | در نظر گرفته نشده |
| ۹ برنامهها و چارچوبهای TUI | ❌ | فقط print() خطی؛ ANSI را خراب میکند؛ از صفحهٔ جایگزین (alternate screen) و خروجی مکاننما-محور آگاه نیست |
ادعاشده اما تأییدنشده
Section titled “ادعاشده اما تأییدنشده”- «Windows Terminal عربی را بهصورت بومی شکلدهی و جابهجا میکند» (
fa_console.py:111-113،README.md:185, 196). این ادعایی بیرونی است و کد فقط با دیدنWT_SESSIONکنار میکشد. آزمونهای خود ما باید رفتار دوجهتی WT را تأیید کنند، نه اینکه آن را مسلم بگیرند. - اینکه هر
TERM_PROGRAMغیر از vscode (mintty و غیره) را قادر بداند که «عربی را بهصورت بومی و قابلاعتماد شکلدهی و جابهجا کند» (:586-602) یک فرض است، نه چیزی که تشخیص داده شود. - «جابهجایی دوجهتی» برای موتور درونی (
README.md:22, 46) یک روش حدسی وارونهسازی است، نه الگوریتم دوجهتی. فقط پیشانهٔ اختیاری «UAX #9 کامل» است (README.md:48-49). - سرآیند docstring نسخه را 2.1.0 میگوید (
:10)؛__version__برابر 2.2.0 است (:158).
آنچه میآموزیم یا برمیداریم
Section titled “آنچه میآموزیم یا برمیداریم”- لایهٔ ۱ روی ویندوز اینجا بهشکلی تمیز حل شده است:
SetConsoleCP/OutputCP(65001)،reconfigure(encoding="utf-8")،PYTHONUTF8، و قراردادی که در صورت شکست، کار را متوقف نمیکند (fail-open) همراه با یکConsoleSetupReportساختاریافته و عیبیابی از طریقget_console_info(). مرجع خوبی برای بخش ویندوز در راهنمای ما است. - سیاست یکسانسازی اصولی است: فقط نویسههای واقعاً همشکل (ي/ی، ك/ک) یکی شوند و هرگز ة/ه یکی نشود؛ یکسانسازی ارقام اختیاری باشد؛ طول ثابت بماند. ارزش دارد در توصیههای لایهٔ ۱ ما برداشته شود.
- «ناوردای دادهٔ منطقی» (
:99-104) قرارداد درستی است: مقادیر برنامه منطقی میمانند، تبدیل فقط هنگام نمایش انجام میشود، و وقتی خروجی TTY نیست دستنخورده میماند. مرزبندی درستی است، هرچند نیمهٔ نمایشی آن از تکنیکهایی استفاده میکند که ما رد میکنیم. - راههای گریز مبتنی بر متغیر محیطی (
FA_CONSOLE_FORCE_VISUAL/FA_CONSOLE_NO_VISUAL) الگویی ساده و مؤثر برای مذاکرهٔ «چه کسی مسئول دوجهتی است» هستند، تا زمانی که ترمینالها توانایی خود را اعلام کنند.
محدودیتها و الگوهای نادرست
Section titled “محدودیتها و الگوهای نادرست”- جایگزینی با فرمهای نمایشی و ارسال متن با ترتیب دیداری به ترمینال. اصول ما هر دو را رد میکند؛ کپی و جستوجو در کنسول متن وارونه و ازپیششکلدادهشده برمیگرداند.
- «دوجهتی» درونی، وارونهسازی خط با جزیرههایی از توکنهای LTR است. جهت پاراگراف برای خطهایی که غالباً LTR هستند نادرست است، و عبارتهای لاتین ترتیب واژههایشان برعکس میشود.
- دنبالههای گریز ANSI (ANSI escape sequences) را در خطهای راستبهچپ خراب میکند، پس با خروجی رنگی CLI و برنامههای TUI ناسازگار است.
- تبدیل بهازای هر
write()یعنی مرزهای جابهجایی به نحوهٔ تکهتکهکردن خروجی توسط فراخواننده بستگی دارد. - اثرات جانبی سراسری هنگام import:
sys.stdout/sys.stderrوos.environرا تغییر میدهد و قلم کنسول کاربر را عوض میکند. - تشخیص توانایی با بو کشیدن متغیرهای محیطی (
WT_SESSION،TERM_PROGRAM) بهجای پرسوجو از خود ترمینال.