مرزهای پایانه ای که یک سلول هزینه ندارند
آدرس مقاله: https://www.joshka.net/cell-borders/ آدرس نظرات: https://news.ycombinator.com/item?id=50491423 امتیاز: 324 # نظرات: 141
این پست (و کد پشت آن) با کمک زیادی از هوش مصنوعی نوشته شده است. من قرار نیست برای آن عذرخواهی کنم. اگر شما را آزار می دهد، با خیال راحت برگه را ببندید.
من Ratatui را حفظ می کنم، بنابراین می بینم بسیاری از TUI هایی که افراد می سازند. بسیاری از آنها در نهایت تقریبا یکسان به نظر می رسند: جعبه های ساده روی یک پس زمینه خسته کننده، از دست دادن دسته ای از چیزهایی که طراحی خوب در رسانه های دیگر برای ما به ارمغان می آورد.
مرزها بخشی از مشکل هستند. آنها باید فضا را اشغال کنند، بنابراین بخشی از پانل هایی می شوند که مردم می خواهند بسازند. یک گزینه این است که آنها را رها کنید و فقط از رنگ استفاده کنید، اما حاشیه ها برای ترسیم و اطراف چیزها واقعا خوب هستند. راههای زیادی برای مرتبسازی مرزها در ترمینال وجود دارد، اما هیچکدام 100% خوب نیستند. من به اندازه کافی با دست ┌──┐ کشیده ام تا در این مورد نظر داشته باشم.
روش معمول بلوک ترسیم جعبه یونیکد است که دارای 128 کاراکتر برای خطوط، گوشه ها و اتصالات است. به نوعی این هنوز کافی نیست:
بنابراین من روی یک پروتکل ترمینال کار کرده ام که به جای آن خطوط نازکی را روی لبه سلول ها می کشد. من آن را به عنوان یک وصله برای Ghostty (و قبل از آن نسخه قبلی در ریو) کار کرده ام، و برنامه های آزمایشی برای آن با Ratatui ساخته ام. از نویسندگان ترمینال و TUI بازخورد می خواهم.
هر خط در آن اسکرین شات یک حاشیه سلول است. هیچ یک از آنها از یک ردیف یا ستون استفاده نمی کنند. برچسبهای برگهها در لبه بالایی هر صفحه قرار میگیرند، قسمتهای نوشتاری درست زیر متن خط کشیده شدهاند، و دکمهها یک ردیف بلند و گرد هستند.
در اینجا همان برنامه در یک ترمینال بدون حاشیه سلول وجود دارد که به کاراکترهای طراحی جعبه بازمی گردد:
هر صفحه یک سطر و یک ستون را در هر طرف از دست می دهد، بنابراین صفحه گزارش دو خط کمتر را نشان می دهد و یادداشت ها به طور متفاوتی بسته می شوند. برچسب های زبانه در داخل قاب حرکت می کنند. فیلدهای متنی به جای آن از ویژگی underline استفاده می کنند و کادر و دکمه ها به پرانتز تبدیل می شوند.
فرم تنظیمات، با مرزهای سلول و سپس با طرح بازگشتی جعبه:
برگه ها هم همین داستان هستند. آنها با حاشیه های سلولی روی لبه بالای صفحه می نشینند. با کاراکترهای جعبه، آنها به ردیف خود در داخل قاب نیاز دارند:
خطوط بین سلول ها برای نمودارها نیز کار می کنند. نمودارهای بریل به سبک btop هر سلول را با نقطه پر می کنند، بنابراین جایی برای قرار دادن یک خط شبکه یا یک خط متوسط بدون رها کردن یک ردیف وجود ندارد. با مرزهای سلولی، آنها روی لبه های سلول بین نقاط می نشینند. در اینجا یک مانیتور به این سبک وجود دارد که با Ratatui ساخته شده است:
و بازگشتی که باید خطوط شبکه را حذف کند:
در اینجا دموی پنجرههای کاشیکاری، جابجایی پنجرهها، باز کردن منوها و گفتگوی درباره وجود دارد:
تا حدودی، صفحه شطرنجی سلولها را روشن میکند، که نشان میدهد چگونه همه چیز با شبکه مطابقت دارد. آن را در اینجا تغییر دهید:
ریشه آن این است که کاراکترهای ترسیم جعبه متن هستند. هر خط یک گلیف است که یک سلول کامل را اشغال می کند و تقریبا هر چیزی که در مورد آنها آزار دهنده است از آن خارج می شود.
فضا همان چیزی است که آشکار است. در لپتاپ 16 اینچی من با فونتی که در واقع میتوانم بخوانم، ترمینال چیزی شبیه به 200x50 است (پیشفرضهای شما کمی آن را جابهجا میکنند). ستونها در آن اندازه هستند.
شما همچنین نمی توانید بین دو سلول که هر دو چیزی در آنها وجود دارد خطی قرار دهید. بنابراین هیچ راهی برای خط کشیدن زیر یک فیلد متنی درست زیر متن آن، یا ترسیم طرح کلی یک دکمه، بدون اضافه کردن بالشتک در اطراف آن وجود ندارد. گوشههای گرد به نوعی کار میکنند، به جز علامت گوشه یک رنگ پسزمینه دارد، و وقتی پسزمینه پانل با آنچه در اطراف آن است متفاوت است، در هر گوشه یک مربع کوچک با رنگ اشتباه دریافت میکنید. و خود خط هر چیزی است که فونت تصمیم می گیرد، وزن و موقعیت را شامل می شود.
سپس کپی و پیست وجود دارد. متنی را در داخل یک کادر انتخاب کنید و کادر را نیز دریافت خواهید کرد. همه کسانی که از TUI به Slack چسبانده شده اند، رقص پاکسازی کوچک │ را می دانند. گاهی اوقات شما جعبه را می خواهید (مثلا چسباندن یک میز در یک چت)، اما بیشتر این جعبه آشغال است. حاشیه های سلول متنی نیستند، بنابراین هرگز کپی نمی شوند، که هر دو طرف را قطع می کند.
حاشیه سلول یک ویژگی سلول است، مانند رنگ پس زمینه. هر سلول می تواند تا دوازده بخش خط را حمل کند: دو نیمه هر یک از چهار لبه خود، و چهار بازو از مرکز آن. هر بخش رنگ، عرض، مکان و سبک خاص خود را دارد و ترمینال آنها را روی شبکه سلولی ترسیم می کند. حاشیهها در سلولها ذخیره میشوند، بنابراین آنها پیمایش میکنند، پاک میشوند، درج میشوند و با متن جریان مییابند. آنچه در پاک کردن یا اسکرول اتفاق میافتد از قبل پاسخی دارد، همان پاسخی که برای رنگها وجود دارد.
لبه ها به دو نیم تقسیم می شوند بنابراین مرزها با کاراکترهای بلوک ربع (▖▗▘▝ و دوستان) در یک راستا قرار می گیرند. این کار کشیدن شکلی را که نیم سلولی از شبکه است و همچنان یک حاشیه منظم در اطراف آن قرار می دهد، آسان می کند. بله، هنوز از یک کاراکتر برای پر کردن استفاده میشود، و ممکن است راه بهتری برای انجام آن قسمت وجود داشته باشد. یک مشکل در یک زمان.
در صورتی که طرحها به آنها نیاز داشته باشند، همین ایده میتواند به عرضهای سکستان و اکتانت یا عرض یک چهارم و هشتم کشیده شود.
خطوط می توانند یکپارچه، دوتایی، چین دار یا نقطه چین باشند. هر گوشه و مرکز یک سلول می تواند مربع یا گرد، با شعاع قابل تنظیم و قوس های ضد مستعار باشد. یک گوشه گرد میتواند یک رنگ خارجی را نامگذاری کند، بنابراین وقتی پسزمینه پانل با آنچه در پشت آن است متفاوت است، ناحیه خارج از قوس به درستی رنگآمیزی میشود.
وقتی دو سلول همسایه هر دو یک خط روی لبه مشترک خود قرار می دهند، در یک خط ادغام می شوند. ضربهای که اولویت بالاتری دارد، برنده میشود، سپس ضربهای پهنتر، سپس ضربهای که در سمت راست یا پایین است. به این ترتیب، یک صفحه متمرکز میتواند اولویت خود را افزایش دهد و کل طرح کلی خود را حفظ کند، به هر ترتیبی که همسایههایش طراحی شدهاند. اولین تلاش من "راست/پایین همیشه برنده است" بود، که تا زمانی ادامه داشت که صفحه متمرکز نیمی از طرح کلی خود را به همسایهاش از دست داد.
همه چیز یک رشته DCS با فضای نام است:
مسیر رایج یک قلم است که مانند رنگ پسزمینه فعلی در مکاننما نگه داشته میشود. آن را تنظیم کنید، متنی را چاپ کنید و سلول های چاپ شده حاشیه ها را دریافت می کنند:
همچنین دستورات مستطیلی وجود دارد که مرزهای سلول های موجود را بدون دست زدن به قلم تنظیم یا پاک می کند و یک جستجوی قابلیت وجود دارد. یک برنامه پرس و جو را به دنبال آن DA1 ارسال می کند. اگر ابتدا پاسخ DA1 بدون پاسخ مرز سلولی دریافت شود، ترمینال از آن پشتیبانی نمیکند، بنابراین برنامه به کاراکترهای جعبه برمیگردد و فضای مورد نیاز آنها را رزرو میکند. پایانه هایی که DCS را درک نمی کنند، آن را نادیده می گیرند، مانند هر DCS ناشناخته ای.
حداقل چیزی که یک ترمینال نیاز دارد قلم، دستورات مستطیل و ضربه های جامد است. من سعی کردهام آن برش اول را کوچک نگه دارم، زیرا همیشه یک «... و این» دیگر برای اضافه کردن وجود دارد، و این یک شیب لغزنده است.
سبکهای خط، اتصالات گرد، اولویت و رنگهای خارجی فیلدهای پسوندی هستند که در پاسخ قابلیت فهرست شدهاند و فیلدهای ناشناخته نادیده گرفته میشوند، بنابراین میتوان بعدا اضافه کرد. من ترجیح می دهم تصمیمات اولیه در صورت امکان دو طرفه باشد.
این مشخصات خود را نسخه 1 می نامد (این 1 در DCS 1 + b است). این v1 به معنای قدیمی است، قبل از اینکه همه ما در semver گرفتار شویم. این به معنای انجام شده یا پایدار نیست، به این معنی است که اولین موردی است که حاضر بودم آن را یادداشت کنم. آن را به عنوان نسخه 0.1 یا پیش نویس یا هر چیزی که ترجیح می دهید بخوانید.
چیزی که هیچ یک از اینها به شما نمی دهد خطی با رنگ و عرض خاص خود در هر لبه است. سند منطقی هنر قبلی را با جزئیات بیشتری پوشش می دهد و هر انتخاب را در پروتکل توضیح می دهد.
اولین نمونه اولیه خود من در ریو (raphamorim/rio#1947) بود، با یک نسخه قبلی از مشخصات که از APC به جای DCS استفاده می کرد. بازخورد اشاره کرد که APC برای استفاده مجدد ایمن نیست: Kermit 95 بارهای APC را به عنوان دستورات Kermit از دهه 90 اجرا کرده است. DCS جایی است که دستورات ترمینال ساختیافته در حال حاضر وجود دارند، و پایانهها رشتههای DCS را که نمیشناسند نادیده میگیرند، بنابراین من به آن تغییر دادم.
وقتی برای اولین بار این را نشان دادم، بیشتر سؤالات در مورد اینها بود. مشخصات به درستی به همه آنها وارد می شود، اما تقریبا در اینجا قرار گرفتم.
مولتی پلکسرها اولین چیزی بود که مردم در مورد آن سوال کردند. tmux و دوستان، پنجرهها را از ایده خودشان از شبکه سلولی دوباره ترسیم میکنند، بنابراین عبور از این دنبالهها فقط مرزها را در جای اشتباهی قرار میدهد. مالتی پلکسری که از پروتکل اطلاعی ندارد باید آنها را رها کند و به خود DA1 پاسخ دهد و سپس برنامه هایی که در داخل آن اجرا می شوند مانند هر جای دیگری به کاراکترهای جعبه برمی گردند. کسی که در مورد آن می داند می تواند مرزها را مانند هر ویژگی دیگری ذخیره کند و آنها را دوباره ترسیم کند.
خطوط متناقض در یک لبه مشترک زمانی که ترمینال رندر می شود، با استفاده از قانون اولویت بالا حل می شود، بنابراین مهم نیست که برنامه سلول ها را به چه ترتیبی نوشته است.
پاک کردن، درج و حذف همه کارها به روشی که برای رنگ های پس زمینه انجام می دهند. سلولهای پاکشده قلم فعلی را میگیرند و خطوطی که درج یا حذف میشوند، حاشیههای خود را با خود همراه میکنند. اسکرولبک، صفحهنمایش جایگزین و جریان مجدد اکثرا رایگان هستند، زیرا حاشیه در سلول زندگی میکند.
هزینه: تغییر Ghostty حدود 1650 خط است و بخش قابل توجهی از آن تست است. هر سلول یک شناسه مرزی 16 بیتی دریافت میکند، که در بالشتکی که قبلا وجود داشت قرار میگیرد، بنابراین سلولها بزرگتر نمیشوند و صفحهای بدون حاشیه هزینه اضافی ندارد. شناسهها به جدولی از مجموعههای مرزی متمایز (هر کدام حدود 100 بایت) اشاره میکنند که توسط کل پایانه مشترک است. یک TUI معمولی فقط از تعداد انگشت شماری از مجموعههای متمایز استفاده میکند، اما جدول هرگز آزاد نمیشود، بنابراین در بدترین حالت (همه 65535 ID در حال استفاده) حدود 10-15 مگابایت است.
رندر فقط برای سلول هایی که حاشیه دارند کار اضافی انجام می دهد. هر یک به چهار همسایه خود نگاه می کند تا لبه های مشترک را حل کند، بنابراین تغییر یک ردیف باعث بازسازی ردیف های دو طرف آن نیز می شود. خطوط مستقیم در هر سلول چند ربع ثابت هستند. گوشههای گرد هزینه بیشتری دارند، زیرا قوس ضد مستعار به صورت ردیفهایی از چهارتایی کوچک ترسیم میشود، تقریبا یک ردیف در هر پیکسل لبه. من هنوز هیچکدام از اینها را به درستی محک نکرده ام، و این بخشی است که بیشتر دوست دارم مجموعه دیگری به آن نگاه کنم.
مشخصات و منطق در چنگال Ghostty من است. شعبه Ghostty تمام نسخه 1 را پیاده سازی می کند. من تا کنون آن را فقط بر روی macOS ساخته و اجرا کرده ام، بنابراین بیلدهای GTK و OpenGL آزمایش نشده اند. برای ساخت و اجرای آن (شما به Zig 0.17 و Xcode نیاز دارید):
در داخل آن Ghostty، اسکریپت گالری در همان شاخه، گالری سبک بالا را ترسیم می کند. ابتدا پشتیبانی را شناسایی میکند، بنابراین یک بررسی سریع برای اجرای ترمینال دیگر است:
پس از اجرا، میتوانید با کلیدها بین نماها ورق بزنید: p placement، رنگهای c، بلوکهای h، j junctions، e halves، s styles و l live. w پهنای ضربه را چرخه میکند، b حاشیهها را خاموش میکند تا بتوانید مقایسه کنید، و q خارج میشود. هر نما همچنین دارای یک پرچم منطبق است (-placement، -styles و غیره) اگر می خواهید روی آن شروع کنید.
نسخه ی نمایشی پنجره های کاشی کاری در شاخه Ratatui است. هنگامی که ترمینال از مرزهای سلول پشتیبانی نمی کند، به کاراکترهای طراحی جعبه برمی گردد، به این ترتیب من عکس های مقایسه را در بالا انجام دادم:
پنجره ها را با ماوس به اطراف بکشید تا آنها را مجددا تغییر دهید. n و v تقسیم می شوند، x بسته می شود و کلیک راست یک منوی پنجره باز می شود. برای جابجایی بین مرزهای سلول و طراحی جعبه، b را فشار دهید، یا g را فشار دهید تا سلول های متناوب را سایه بزنید و ببینید لبه ها کجا هستند.
مانیتور به سبک btop از تصاویر نمودار در همان شاخه است. با توجه به اینکه یک هوش مصنوعی چقدر از آن را نوشته است، به طور خلاصه به این فکر کردم که آن را bslop بنامم:
این یک مانیتور واقعی سیستم است (سیپییو، حافظه، شبکه و فرآیندهای واقعی شما را میخواند)، بنابراین آزمایش بهتری برای نشان دادن این موضوع در یک صفحهنمایش شلوغ نسبت به نمایشگر صفحه است. 1 تا 4 کادرها را نشان می دهد و پنهان می کند، b و g مانند دمو پنجره ها کار می کنند و h یا ? بقیه کلیدها را لیست می کند. به دلیل وابستگی به sysinfo، به Rust جدیدتر (1.95) نسبت به بقیه Ratatui نیاز دارد.
من علاقه ای به این ندارم که این راه حل دقیق باشد، اما فکر می کنم این مشکلی است که ارزش حل کردن را دارد، و دوست دارم که بیش از یک ویژگی ترمینال باشد (و بیش از یک آخر هفته ارزش اصلاح را داشته باشد). اگر روی ترمینال کار می کنید، آیا این را اجرا می کنید و کدام قطعات گران به نظر می رسند؟ اگر روی یک کتابخانه یا برنامه TUI کار میکنید، کدام یک از ویجتهای شما از آن استفاده میکنند و به چه چیزی نیاز دارند که اینجا نیست؟ نظرات در مورد بحث Ghostty خوش آمدید.
متن اصلی (انگلیسی)
Terminal borders that don't cost a cell
Article URL: https://www.joshka.net/cell-borders/ Comments URL: https://news.ycombinator.com/item?id=50491423 Points: 324 # Comments: 141