Beefy Boxes and Bandwidth Generously Provided by pair Networks RobOMonk
Problems? Is your data what you think it is?
 
PerlMonks  

How to determine terminal size when piped data to STDIN?

by mushu (Initiate)
on Nov 14, 2003 at 12:27 UTC ( [id://307114]=perlquestion: print w/replies, xml ) Need Help??

This is an archived low-energy page for bots and other anonmyous visitors. Please sign up if you are a human and want to interact.

mushu has asked for the wisdom of the Perl Monks concerning the following question:

Help! I need a _reliable_ way to determine the current terminal window size when my Perl program is being piped data to it. It is being run under HP-UX 11.11 under both hpterm and xterm terminals (separately, of course) :)

At issue is the fact that when I run my program with no parameters or piped-in data, I can grab the output from `stty -a` and parse it for the "rows=" and "columns=" values. HOWEVER when you are piping data to a program like this: cat passwd | ./myprog then STDIN is no longer "real", meaning that your Perl program no longer knows anything about the terminal, since its whole world is now a stream of data which has no "boundaries". If you don't believe me, try this:

#!/usr/local/bin/perl -w
my $stuff=`stty -a 2>/dev/null`;
print "\$stuff=$stuff\n";

Now run this by itself, then run it again but cat some data to it: cat ./myprog | ./myprog and you will see that $stuff is empty when having something piped to it.

Note #1: must use only standard (default) Perl installation, so no CPAN modules (such as Term::ReadKey) allowed!

Note #2: curses is unavailable in this installation (don't ask...)

Note #3: I don't consider environment variables to be reliable due to them being so volatile, so $LINES and $COLUMNS are out of the picture.

Now, after all of these are tossed, I'm thinking that there must be a POSIX escape code to read the current cursor position, so I can set the cursor position to (200,200) and read it and if it wrapped then the window isn't that big so drop the column width down and do it again, ad nauseum. However, I cannot find it after days of searching. Also, there might be a simple POSIX escape sequence that simply reads the current cursor position, but I was unable to find that either!

I sure hope someone with lots of low-level terminal experience can help me!
  • Comment on How to determine terminal size when piped data to STDIN?

Replies are listed 'Best First'.
Re: How to determine terminal size when piped data to STDIN?
by hanenkamp (Pilgrim) on Nov 14, 2003 at 12:42 UTC

    I don't know if this is a typical option, but my man-page for stty shows a --file option where you can pick the file to check the parameters on. So, on Linux I can do this:

    echo foo | perl -e '$x=`stty -a --file=/dev/stdin`; print "\$x=$x\n";'

    and get:

    speed 38400 baud; rows 50; columns 131; line = 0; intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = <undef>; eol2 = <undef>; start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R; werase = + ^W; lnext = ^V; flush = ^O; min = 1; time = 0; -parenb -parodd cs8 -hupcl -cstopb cread -clocal -crtscts -ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr icrnl ixo +n -ixoff -iuclc -ixany -imaxbel opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs +0 vt0 ff0 isig icanon iexten echo echoe echok -echonl -noflsh -xcase -tostop -ec +hoprt echoctl echoke

    Since my Unix experience is pretty well limited to Linux, I can't be much help on other platforms.

    Update: I made a mistake, I used /dev/stdout in my actual test but wrote /dev/stdin here. If you have access to any console device and a --file option, it would work. However, as mushu points out below, that is not the case.

      HP-UX doesn't appear to have the --file option for its stty command. BUT, it probably wouldn't matter, since it would be called as a child process, and children inherit their parent's environment, thus STDIO for the stty child process would be the same as the parent's STDIO and not readable either.
Re: How to determine terminal size when piped data to STDIN?
by duff (Parson) on Nov 14, 2003 at 12:43 UTC
    Try $stuff = qx(stty -a </dev/tty 2>/dev/null); I *think* that works properly.
    Note #1: must use only standard (default) Perl installation, so no CPAN modules (such as Term::ReadKey) allowed!

    I continue to boggle when people mention this constraint. It's really quite an odd thing.

      Also, you can specify 'size' to avoid parsing;
      ($rows, $cols) = split ' ', qx"stty size </dev/tty 2>/dev/null";
        OMG!!!!!!! You _ARE_ a Perl Monk!!!! IT WORKED!!! <jumping up and down for real> I utterly can't believe it...I bow to you...Thank you _so much_ for sharing your knowledge!!
        I truly thought there was no way to solve this...I am ashamed for doubting Perl...
      Only because it is being run by a "user" on a huge HP-UX network who cannot get anything installed on the server without jumping through hoop after hoop after hoop after... that is why the requirement of default installation. If I could reliably have him put the ReadKey.pm module in the current directory that would be great, but I tried that and apparently it needs "something else" to make it work. Otherwise I'd just send that module with my code and be done with it. :) Since this is my very first post here I am unaware of the "pissy" things that set people off. I will be more careful in the future...

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://307114]
Approved by Grygonos
help
Sections?
Information?
Find Nodes?
Leftovers?
    Notices?
    hippoepoptai's answer Re: how do I set a cookie and redirect was blessed by hippo!
    erzuuliAnonymous Monks are no longer allowed to use Super Search, due to an excessive use of this resource by robots.