Pregunta

¿Qué tengo que cambiar para hacer este trabajo?

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

de tchrist en En la columna de la fila .

¿Fue útil?

Solución

Esto funciona muy bien para mí:

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

El requieren no necesita (y no debería tener) la ruta completa; TIOCGWINSZ ya está definido por la carga de la cabecera ioctl, y no hay ninguna señal de que el escalar de destino tiene que ser inicializado al tamaño correcto (aunque si no está inicializado en absoluto, Perl lanza una advertencia, ya que no parece reconocer la read especial la naturaleza -como de ioctl, así que me puse a "" sólo para calmar eso).

Otros consejos

Para obtener el número de filas y columnas, que estoy haciendo esto:

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

¿Por qué no usar Term::Size ? Esto utiliza el método ioctl(), envuelto en buen código XS ordenada todo listo para usar desde Perl.

Una forma de la otra que va a tener pedirle C para decirle lo que el valor de TIOCGWINSZ es. Bien podría conseguir que le diga el tamaño del otro argumento, también, mientras estás en ello.

#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);
}

Tal vez algún alma caritativa le puede mostrar cómo envolver que en Inline::C para usted, pero mientras tanto, esto debería ser suficiente. Tenga en cuenta que este es un programa portable, ya que se ejecuta en ambos tipos de sistemas:

? ? 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 tiene incorporado un método para recuperar el tamaño de la terminal, y se es compatible con una gama de diferentes terminales incluyendo Windows. Teniendo en cuenta la gran número de módulos en CPAN que utilizan este módulo , es probable que ya tiene instalado.

#!/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";
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top