【问题标题】:How do I get width and height of my terminal with ioctl?如何使用 ioctl 获取终端的宽度和高度?
【发布时间】:2010-11-26 14:37:20
【问题描述】:

我必须改变什么才能使它工作?

 #!/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;
 }

灵感来自tchrist's answer in From column to row

【问题讨论】:

  • 你真的有一个正确安装了sys/ioctl.ph的系统吗?哪一个?

标签: perl terminal ioctl


【解决方案1】:

要获取行数和列数,我这样做:

#!/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";

【讨论】:

    【解决方案2】:

    为什么不直接使用Term::Size?这使用了ioctl() 方法,包裹在漂亮整洁的 XS 代码中,所有这些都可以从 Perl 中使用。

    【讨论】:

      【解决方案3】:

      Term::ReadKey 有一个内置的方法来检索终端的大小,它supports a range of different terminals 包括 Windows。考虑到sheer number of modules on CPAN that use this module,您可能已经安装了它。

      #!/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";
      

      【讨论】:

        【解决方案4】:

        这对我来说很好用:

        #!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";
        }
        

        require 不需要(也不应该有)完整路径; TIOCGWINSZ 已经通过加载 ioctl 标头进行了定义,并且没有迹象表明必须将目标标量初始化为正确的大小(尽管如果根本没有初始化,perl 会抛出警告,因为它似乎无法识别特殊的 @ 987654322@-like ioctl 的性质,所以我将它设置为 "" 只是为了让它安静)。

        【讨论】:

        • 您会发现很少系统实际安装了sys/ioctl.ph文件。
        【解决方案5】:

        另一种方法是让 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 中,但与此同时,这应该就足够了。请注意,这是一个可移植的程序,因为它可以在 ̲b̲o̲t̲h̲  类型的系统上运行:

        ☺ 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
        

        【讨论】:

          猜你喜欢
          • 2010-09-20
          • 2012-09-30
          • 2011-07-12
          • 2014-05-01
          • 2012-01-21
          • 1970-01-01
          • 1970-01-01
          • 2019-12-26
          • 2011-09-25
          相关资源
          最近更新 更多