Как less узнает разрешение терминала?

Как less узнает разрешение терминала?

Каждый раз, когда кто-то устанавливает другой размер для виртуальной консоли, lessраспознает разрешение окна (я предполагаю, что ...); в соответствии с этим он меняет, сколько строк текста он должен визуализировать. Как вычисляется этот параметр?

решение1

Если вы ищете способ проверки из скрипта, вы можете сделать одно из следующих:

  • Запустите tput colsи tput lines, как предлагает manatwork
  • проверьте значения $LINES и $COLUMNS

Но если вам нужны подробности, вот они:

Для виртуальных терминалов (xterm и т. д.) есть ioctl()системный вызов, который сообщит вам размер окна. Если он может, lessон использует этот вызов. Кроме того, когда вы меняете размер окна, все, что выполняется в этом окне, получает сигнал SIGWINCH, который сообщает less, что ему следует проверить новый размер окна. Например, я запустил lessвыполнение (как процесс с идентификатором 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о списке действий, которые можно выполнить с помощью терминала.

решение2

Если вы посмотрите исходный код, то вы узнаете 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

решение3

Я не уверен, что это та информация, которую вы ищете. Я думаю, lessрегистрирует обработчик сигнала для SIGWINCH. Когда размер терминала изменяется, он получает SIGWINCHсигнал и проверяет информацию tty для текущего размера терминала. http://www.gnu.org/software/libc/manual/html_node/Miscellaneous-Signals.html

Связанный контент