Как получить ширину и высоту моего терминала с IOCTL?

StackOverflow https://stackoverflow.com/questions/4286158

  •  28-09-2019
  •  | 
  •  

Вопрос

Что мне нужно изменить, чтобы сделать эту работу?

 #!/usr/bin/perl
 use 5.012;
 use warnings;
 require "/usr/lib/perl5/vendor_perl/5.12.1/x86_64-linux-thread-multi/sys/ioctl.ph";
 my ($rows, $cols, $xpix, $ypix);

 my $winsize = "\0" x 8;
 my $TIOCGWINSZ = 0x40087468;  # should be require sys/ioctl.pl
 if (ioctl(STDOUT, $TIOCGWINSZ, $winsize)) {
     ($rows, $cols, $xpix, $ypix) = unpack('S4', $winsize);
 } else {
     say "something didn't work" and exit;
 }

Вдохновлен Ответ тжириста в Из колонны до строки.

Это было полезно?

Решение

Это работает просто для меня:

#!perl

use strict;
use warnings;

require 'sys/ioctl.ph';

my $winsize = ""; # Silence warning
if (ioctl(STDOUT, TIOCGWINSZ() , $winsize)) {
        my ($rows, $cols, $xpix, $ypix) = unpack 'S4', $winsize;
        print join ":", $rows, $cols, $xpix, $ypix;
        print "\n";
} else {
        warn "Something didn't work.\n";
}

Требуется не нужен (и не должен иметь) полный путь; Tiocgwinsz уже определяется путем загрузки заголовка IOCTL, и нет никаких признаков того, что среднее значение CALAR должен быть инициализирован в правильном размере (хотя, если он вообще не инициализируется, Perl бросает предупреждение, потому что это не распознает специальные read- Подобная природа IOCTL, поэтому я настроил ее на «просто тихо).

Другие советы

Чтобы получить количество рядов и столбцов, я делаю это:

#!/usr/bin/perl
use strict;
use warnings;

my $cols = 80;
my $rows = 24;
for (`stty -a`) {
    /columns ([0-9]+);/ and do { if ($1 > 0) { $cols = $1; }};
    /rows ([0-9]+);/    and do { if ($1 > 0) { $rows = $1; }};
}
print "cols=$cols\trows=$rows\n";

Почему бы просто не использовать Term::Size? Это использует ioctl() Метод, завернутый в приятный аккуратный код XS, готов к использованию из Perl.

Один из способов другого вы собираетесь попросить C, чтобы сказать вам, какова ценность TIOCGWINSZ является. Может также получить его, чтобы рассказать вам размер другого аргумента, пока вы на нем.

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <termios.h>

int
main(argc, argv)
    int   argc;
    char *argv[];
{
    struct winsize mywinsize;
    int ttyfd;

    if ((ttyfd = open("/dev/tty", O_RDWR|O_NOCTTY)) == -1) {
        perror("open /dev/tty");
        exit(-1);
    }

    if (ioctl(ttyfd, TIOCGWINSZ, &mywinsize) == -1) {
        perror("ioctl TIOCGWINSZ");
        exit(-1);
    }

    printf("TIOCGWINSZ %#08lx\n",           TIOCGWINSZ             );
    printf("sizeof struct winsize %lu\n",   sizeof(struct winsize) ); 
    printf("rows %d\n",                     mywinsize.ws_row       );
    printf("cols %d\n",                     mywinsize.ws_col       );

    if (fclose(stdout) == EOF) {
        perror("close stdout");
        exit(-1);
    }

    exit(0);
}

Возможно, какая-то душа может показать вам, как обернуть это в Inline::C Для вас, но тем временем это должно хватить. Обратите внимание, что это портативная программа, поскольку она работает на обоих видах систем:

☺ BSD ☺.

    OpenBSD% cc getwinsz.c && a.out
    TIOCGWINSZ 0x40087468
    sizeof struct winsize 8
    rows 81
    cols 166

    Darwin% cc getwinsz.c && a.out
    TIOCGWINSZ 0x40087468
    sizeof struct winsize 8
    rows 37
    cols 126

☹ sysv ☹.

   Slolaris% cc getwinsz.c && a.out
   TIOCGWINSZ 0x005468
   sizeof struct winsize 8
   rows 37
   cols 126

   Leenooxe% cc getwinsz.c && a.out
   TIOCGWINSZ 0x005413
   sizeof struct winsize 8
   rows 37
   cols 126

Term::ReadKey имеет встроенный метод для извлечения размера терминала, и это Поддерживает диапазон различных терминалов в том числе Windows. Принимая во внимание Чистое количество модулей на CPAN, которое использует этот модуль, Вы, скорее всего, уже установили это.

#!/usr/bin/perl -w
use strict;
use Term::ReadKey   qw/ GetTerminalSize /;

my @winsize = &GetTerminalSize(\*STDOUT);
my ($cols, $rows, $xpix, $ypix) = @winsize;
print "cols:$cols rows:$rows xpix:$xpix ypix:$ypix\n";
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top