ความละเอียดของเทอร์มินัลน้อยลงได้อย่างไร


13

ทุกครั้งที่มีคนกำหนดขนาดที่แตกต่างกันสำหรับคอนโซลเสมือนlessตระหนักถึงความละเอียดของหน้าต่าง (ฉันสมมติว่า ... ); ตามที่มันเปลี่ยนจำนวนบรรทัดของข้อความที่ควรเห็นภาพ พารามิเตอร์นั้นคำนวณอย่างไร?


เอ่อ ... โอเค แต่ฉันจะหาขั้นตอนที่ดำเนินการได้ที่ไหน
Giuseppe Crinò

คำตอบ:


22

หากคุณกำลังมองหาวิธีตรวจสอบจากสคริปต์คุณสามารถทำสิ่งใดสิ่งหนึ่งต่อไปนี้:

  • เรียกใช้tput colsและtput linesเป็น manatwork แนะนำ
  • ตรวจสอบค่าของ $ LINES และ $ COLUMNS

แต่ถ้าคุณต้องการรายละเอียดที่นี่เราไป:

สำหรับเทอร์มินัลเสมือน (xterm, et al) มีการioctl()เรียกระบบที่จะบอกคุณว่าขนาดของหน้าต่างคืออะไร หากทำได้ให้lessใช้การโทรนี้ นอกจากนี้เมื่อคุณเปลี่ยนขนาดของหน้าต่างสิ่งที่กำลังทำงานอยู่ในหน้าต่างนั้นจะได้รับSIGWINCHสัญญาณที่แจ้งให้lessทราบว่าควรตรวจสอบขนาดหน้าต่างใหม่ ตัวอย่างเช่นฉันเริ่มการlessทำงาน (ตามกระบวนการ ID 16663) เชื่อมต่อกับstraceและปรับขนาดหน้าต่าง นี่คือสิ่งที่ฉันเห็น:

$ strace -p 16663
Process 16663 attached - interrupt to quit
read(3, 0xbfb1f10f, 1)                  = ? ERESTARTSYS (To be restarted)
--- SIGWINCH (Window changed) @ 0 (0) ---
rt_sigaction(SIGWINCH, {0x805cf10, [WINCH], SA_RESTART}, {0x805cf10, [WINCH], SA_RESTART}, 8) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
ioctl(1, SNDCTL_TMR_TIMEBASE or TCGETS, {B38400 opost isig -icanon -echo ...}) = 0
ioctl(1, SNDCTL_TMR_TIMEBASE or TCGETS, {B38400 opost isig -icanon -echo ...}) = 0
ioctl(1, TIOCGWINSZ, {ws_row=40, ws_col=80, ws_xpixel=0, ws_ypixel=0}) = 0
ioctl(2, TIOCGWINSZ, {ws_row=40, ws_col=80, ws_xpixel=0, ws_ypixel=0}) = 0

นี่คือสิ่งที่ต้องทำtput colsและtput linesเบื้องหลังถ้าพวกเขาทำได้ สำหรับข้อมูลเพิ่มเติมเกี่ยวกับวิธีนี้ให้ดูman tty-ioctlและค้นหา TIOCGWINSZ

สำหรับอาคารอื่น ๆ เช่นที่เชื่อมต่อกับพอร์ตอนุกรมไม่มีวิธีรับข้อมูลนี้โดยตรง ในกรณีนี้lessเริ่มมองหาเบาะแสในตัวแปรสภาพแวดล้อม

  • LINESและCOLUMNSมักจะถูกตั้งค่าให้ขนาดเทอร์มินัล ในความเป็นจริงหากbashหรือzshสามารถหาขนาดเทอร์มินัลมันจะตั้งค่าตัวแปรเหล่านี้โดยอัตโนมัติเพื่อให้ง่ายสำหรับโปรแกรมที่ไม่ฉลาดเพื่อดูขนาดเทอร์มินัล อย่างไรก็ตามเชลล์อื่น ๆ ส่วนใหญ่รวมถึงdashและtcshไม่ได้ตั้งค่าตัวแปรเหล่านี้
  • TERMมักจะถูกตั้งค่าเป็นประเภทอาคารซึ่งในกรณีนี้ฐานข้อมูล terminfo อาจมีขนาดที่คาดหวังของสถานี หากtput rowsไม่สามารถใช้ IOCTL (ตัวอย่างเช่นหากคุณเชื่อมต่อผ่านพอร์ตอนุกรม) จะกลับไปใช้ค่าที่บันทึกไว้ที่นี่ สำหรับเทอร์มินัลที่มีขนาดสามารถเปลี่ยนแปลงได้นี่เป็นเพียงการเดาและน่าจะผิด

สำหรับข้อมูลเพิ่มเติมให้ดูman tputที่คำสั่งเพื่อควบคุมเทอร์มินัลและman terminfoสำหรับรายการสิ่งต่าง ๆ ที่คุณสามารถบอกให้เทอร์มินัลทำ


ฐานข้อมูล terminfo ไม่ได้ทำสิ่งที่ระบุไว้ที่นี่ คำตอบโดย @ warl0ck ซึ่งมีข้อมูลน้อยกว่ามีความแม่นยำมากขึ้น
โทมัส Dickey

@ThomasDickey คุณพูดถูก ทั้งหมดมีค่าที่คาดหวัง แก้ไขคำตอบของฉัน; ขอบคุณ
Jander

7

หากคุณดูซอร์สโค้ดคุณจะรู้ว่าการlessโทรioctl()เพื่อดึงขนาดหน้าต่างบน Linux

#ifdef TIOCGWINSZ
    {
        struct winsize w;
        if (ioctl(2, TIOCGWINSZ, &w) == 0)
        {
            if (w.ws_row > 0)
                sys_height = w.ws_row;
            if (w.ws_col > 0)
                sys_width = w.ws_col;
        }
    }
#else
#ifdef WIOCGETD
    {
        struct uwdata w;
        if (ioctl(2, WIOCGETD, &w) == 0)
        {
            if (w.uw_height > 0)
                sys_height = w.uw_height / w.uw_vs;
            if (w.uw_width > 0)
                sys_width = w.uw_width / w.uw_hs;
        }
    }
#endif

1

ฉันไม่แน่ใจว่านี่เป็นข้อมูลที่คุณกำลังมองหาหรือไม่ ผมคิดว่าการลงทะเบียนจัดการสัญญาณสำหรับless SIGWINCHเมื่อขนาดของเทอร์มินัลเปลี่ยนไปเครื่องจะรับSIGWINCHสัญญาณและโพรบข้อมูล tty สำหรับมิติปัจจุบันของเทอร์มินัล http://www.gnu.org/software/libc/manual/html_node/Miscellaneous-Signals.html

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.