Skip Menu |

This queue is for tickets about the IO-Tty CPAN distribution.

Report information
The Basics
Id: 70651
Status: resolved
Priority: 0/
Queue: IO-Tty

People
Owner: TODDR [...] cpan.org
Requestors: leonerd-cpan [...] leonerd.org.uk
Cc:
AdminCc:

Bug Information
Severity: Wishlist
Broken in: (no value)
Fixed in: (no value)



Subject: Ability to set TTY size specifically
It would be useful if, rather than simply cloning the window size from some other TTY, that the size could be directly set. Either of my $pty = IO::Pty->new( cols => 100, lines => 30 ); or $pty->set_size( cols => 100, lines => 30 ); for instance, would be ideal for me. I am happy to provide a patch if required. Thanks, -- Paul Evans
The authors on this module are overloaded (including me). A patch would be good. Even better fork this and I'll do the release. https://github.com/toddr/IO-Tty
On Thu Sep 01 15:11:05 2011, TODDR wrote: Show quoted text
> The authors on this module are overloaded (including me). A patch > would be good.
Find attached. :) I have no idea how to test this one though, short of just create a new Pty/Tty pair, set a size, check it can be read. Not sure what you want to do in terms of unit testing / configure-time checking. -- Paul Evans
Subject: rt70651.patch
=== modified file 'Pty.pm' --- Pty.pm 2012-01-05 19:19:07 +0000 +++ Pty.pm 2012-01-05 19:59:10 +0000 @@ -141,6 +141,8 @@ } *clone_winsize_from = \&IO::Tty::clone_winsize_from; +*get_winsize = \&IO::Tty::get_winsize; +*set_winsize = \&IO::Tty::set_winsize; *set_raw = \&IO::Tty::set_raw; 1; @@ -254,6 +256,17 @@ See the C<try> script for example code how to propagate SIGWINCH. +=item get_winsize() + +Returns the terminal size, in a 4-element list. + + ($row, $col, $xpixel, $ypixel) = $tty->get_winsize() + +=item set_winsize($row, $col, $xpixel, $ypixel) + +Sets the terminal size. If not specified, C<$xpixel> and C<$ypixel> are set to +0. As with C<clone_winsize_from>, this must be called upon the I<slave>. + =back === modified file 'Tty.pm' --- Tty.pm 2012-01-05 19:19:07 +0000 +++ Tty.pm 2012-01-05 19:59:10 +0000 @@ -62,6 +62,26 @@ return undef; } +# ioctl() doesn't tell us how long the structure is, so we'll have to trim it +# after TIOCGWINSZ +my $SIZEOF_WINSIZE = length IO::Tty::pack_winsize(0,0,0,0); + +sub get_winsize { + my $self = shift; + ioctl($self, IO::Tty::Constant::TIOCGWINSZ(), my $winsize) + or croak "Cannot TIOCGWINSZ - $!"; + substr($winsize, $SIZEOF_WINSIZE) = ""; + printf STDERR "winsize{%d bytes}: %v02x\n", length $winsize, $winsize; + return IO::Tty::unpack_winsize($winsize); +} + +sub set_winsize { + my $self = shift; + my $winsize = IO::Tty::unpack_winsize(@_); + ioctl($self, IO::Tty::Constant::TIOCSWINSZ(), $winsize) + or croak "Cannot TIOCSWINSZ - $!"; +} + sub set_raw($) { require POSIX; my $self = shift; === modified file 'Tty.xs' --- Tty.xs 2012-01-05 19:19:07 +0000 +++ Tty.xs 2012-01-05 19:59:10 +0000 @@ -803,6 +803,39 @@ OUTPUT: RETVAL +SV * +pack_winsize(row, col, xpixel = 0, ypixel = 0) + int row + int col + int xpixel + int ypixel + INIT: + struct winsize ws; + CODE: + ws.ws_row = row; + ws.ws_col = col; + ws.ws_xpixel = xpixel; + ws.ws_ypixel = ypixel; + RETVAL = newSVpvn((char *)&ws, sizeof(ws)); + OUTPUT: + RETVAL + +void +unpack_winsize(winsize) + SV *winsize; + INIT: + struct winsize ws; + PPCODE: + if(SvCUR(winsize) != sizeof(ws)) + croak("IO::Tty::unpack_winsize(): Bad arg length - got %d, expected %d", + SvCUR(winsize), sizeof(ws)); + Copy(SvPV_nolen(winsize), &ws, sizeof(ws), char); + EXTEND(SP, 4); + PUSHs(sv_2mortal(newSViv(ws.ws_row))); + PUSHs(sv_2mortal(newSViv(ws.ws_col))); + PUSHs(sv_2mortal(newSViv(ws.ws_xpixel))); + PUSHs(sv_2mortal(newSViv(ws.ws_ypixel))); + BOOT: {
On Thu Jan 05 15:05:04 2012, PEVANS wrote: Show quoted text
> Find attached. :)
Oops, I just noticed there's a printf STDERR in there that ought to be removed first. :) Find attached again. -- Paul Evans
Subject: rt70651.patch
=== modified file 'Pty.pm' --- Pty.pm 2012-01-05 19:19:07 +0000 +++ Pty.pm 2012-01-05 19:57:57 +0000 @@ -141,6 +141,8 @@ } *clone_winsize_from = \&IO::Tty::clone_winsize_from; +*get_winsize = \&IO::Tty::get_winsize; +*set_winsize = \&IO::Tty::set_winsize; *set_raw = \&IO::Tty::set_raw; 1; @@ -254,6 +256,17 @@ See the C<try> script for example code how to propagate SIGWINCH. +=item get_winsize() + +Returns the terminal size, in a 4-element list. + + ($row, $col, $xpixel, $ypixel) = $tty->get_winsize() + +=item set_winsize($row, $col, $xpixel, $ypixel) + +Sets the terminal size. If not specified, C<$xpixel> and C<$ypixel> are set to +0. As with C<clone_winsize_from>, this must be called upon the I<slave>. + =back === modified file 'Tty.pm' --- Tty.pm 2012-01-05 19:19:07 +0000 +++ Tty.pm 2012-01-05 20:16:31 +0000 @@ -62,6 +62,25 @@ return undef; } +# ioctl() doesn't tell us how long the structure is, so we'll have to trim it +# after TIOCGWINSZ +my $SIZEOF_WINSIZE = length IO::Tty::pack_winsize(0,0,0,0); + +sub get_winsize { + my $self = shift; + ioctl($self, IO::Tty::Constant::TIOCGWINSZ(), my $winsize) + or croak "Cannot TIOCGWINSZ - $!"; + substr($winsize, $SIZEOF_WINSIZE) = ""; + return IO::Tty::unpack_winsize($winsize); +} + +sub set_winsize { + my $self = shift; + my $winsize = IO::Tty::unpack_winsize(@_); + ioctl($self, IO::Tty::Constant::TIOCSWINSZ(), $winsize) + or croak "Cannot TIOCSWINSZ - $!"; +} + sub set_raw($) { require POSIX; my $self = shift; === modified file 'Tty.xs' --- Tty.xs 2012-01-05 19:19:07 +0000 +++ Tty.xs 2012-01-05 19:31:37 +0000 @@ -803,6 +803,39 @@ OUTPUT: RETVAL +SV * +pack_winsize(row, col, xpixel = 0, ypixel = 0) + int row + int col + int xpixel + int ypixel + INIT: + struct winsize ws; + CODE: + ws.ws_row = row; + ws.ws_col = col; + ws.ws_xpixel = xpixel; + ws.ws_ypixel = ypixel; + RETVAL = newSVpvn((char *)&ws, sizeof(ws)); + OUTPUT: + RETVAL + +void +unpack_winsize(winsize) + SV *winsize; + INIT: + struct winsize ws; + PPCODE: + if(SvCUR(winsize) != sizeof(ws)) + croak("IO::Tty::unpack_winsize(): Bad arg length - got %d, expected %d", + SvCUR(winsize), sizeof(ws)); + Copy(SvPV_nolen(winsize), &ws, sizeof(ws), char); + EXTEND(SP, 4); + PUSHs(sv_2mortal(newSViv(ws.ws_row))); + PUSHs(sv_2mortal(newSViv(ws.ws_col))); + PUSHs(sv_2mortal(newSViv(ws.ws_xpixel))); + PUSHs(sv_2mortal(newSViv(ws.ws_ypixel))); + BOOT: {
On Thu Jan 05 15:17:15 2012, PEVANS wrote: Show quoted text
> Find attached again.
And -that- one has an unpack where I meant pack. Third attempt attached. (Honestly I do know what I'm doing.. ;) ) -- Paul Evans
Subject: rt70651.patch
=== modified file 'Pty.pm' --- Pty.pm 2012-01-05 19:19:07 +0000 +++ Pty.pm 2012-01-05 19:57:57 +0000 @@ -141,6 +141,8 @@ } *clone_winsize_from = \&IO::Tty::clone_winsize_from; +*get_winsize = \&IO::Tty::get_winsize; +*set_winsize = \&IO::Tty::set_winsize; *set_raw = \&IO::Tty::set_raw; 1; @@ -254,6 +256,17 @@ See the C<try> script for example code how to propagate SIGWINCH. +=item get_winsize() + +Returns the terminal size, in a 4-element list. + + ($row, $col, $xpixel, $ypixel) = $tty->get_winsize() + +=item set_winsize($row, $col, $xpixel, $ypixel) + +Sets the terminal size. If not specified, C<$xpixel> and C<$ypixel> are set to +0. As with C<clone_winsize_from>, this must be called upon the I<slave>. + =back === modified file 'Tty.pm' --- Tty.pm 2012-01-05 19:19:07 +0000 +++ Tty.pm 2012-01-05 23:53:02 +0000 @@ -62,6 +62,25 @@ return undef; } +# ioctl() doesn't tell us how long the structure is, so we'll have to trim it +# after TIOCGWINSZ +my $SIZEOF_WINSIZE = length IO::Tty::pack_winsize(0,0,0,0); + +sub get_winsize { + my $self = shift; + ioctl($self, IO::Tty::Constant::TIOCGWINSZ(), my $winsize) + or croak "Cannot TIOCGWINSZ - $!"; + substr($winsize, $SIZEOF_WINSIZE) = ""; + return IO::Tty::unpack_winsize($winsize); +} + +sub set_winsize { + my $self = shift; + my $winsize = IO::Tty::pack_winsize(@_); + ioctl($self, IO::Tty::Constant::TIOCSWINSZ(), $winsize) + or croak "Cannot TIOCSWINSZ - $!"; +} + sub set_raw($) { require POSIX; my $self = shift; === modified file 'Tty.xs' --- Tty.xs 2012-01-05 19:19:07 +0000 +++ Tty.xs 2012-01-05 19:31:37 +0000 @@ -803,6 +803,39 @@ OUTPUT: RETVAL +SV * +pack_winsize(row, col, xpixel = 0, ypixel = 0) + int row + int col + int xpixel + int ypixel + INIT: + struct winsize ws; + CODE: + ws.ws_row = row; + ws.ws_col = col; + ws.ws_xpixel = xpixel; + ws.ws_ypixel = ypixel; + RETVAL = newSVpvn((char *)&ws, sizeof(ws)); + OUTPUT: + RETVAL + +void +unpack_winsize(winsize) + SV *winsize; + INIT: + struct winsize ws; + PPCODE: + if(SvCUR(winsize) != sizeof(ws)) + croak("IO::Tty::unpack_winsize(): Bad arg length - got %d, expected %d", + SvCUR(winsize), sizeof(ws)); + Copy(SvPV_nolen(winsize), &ws, sizeof(ws), char); + EXTEND(SP, 4); + PUSHs(sv_2mortal(newSViv(ws.ws_row))); + PUSHs(sv_2mortal(newSViv(ws.ws_col))); + PUSHs(sv_2mortal(newSViv(ws.ws_xpixel))); + PUSHs(sv_2mortal(newSViv(ws.ws_ypixel))); + BOOT: {
On Fri Jan 06 15:21:23 2012, PEVANS wrote: Show quoted text
> On Thu Jan 05 15:17:15 2012, PEVANS wrote:
> > Find attached again.
> > And -that- one has an unpack where I meant pack. > > Third attempt attached. > > (Honestly I do know what I'm doing.. ;) )
Thanks, this patch looks good at a glance. The best I can tell, you've only added new functionality, so the risk is relatively low. I'm hesitant to try set_windowsize in a test module for fear it might work and anger cpan and cpan testers users alike. Maybe we should just start with some basic sanity tests on the return values from get and go with that. I'll try to get a dev release out in a week or so.
Well, it looks like I just accidentally released my work in progress on this into 1.11. We'll see how that goes and pull it out if there's a problem.