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

I'm writing a program that finds a large chunk of text in an even larger text file (it was a database in a former life). Right now, it prints the text to a separate file. I'd like to be able to view the text on the screen, in a way that won't involve it scrolling past and only showing the last screen-length. Is there a way to pipe the output through a pager (like "more")?

--Ziva

Replies are listed 'Best First'.
Re: Paging STDOUT?
by chromatic (Archbishop) on Dec 14, 2000 at 06:29 UTC
    The Damian wrote a small IO::Pager module for Object Oriented Perl. It's in chapter five, and the complete source code is available.

    Basically, he blesses a typeglob, makes it open a pipe to itself, and sets the child to read from STDIN and display a customizable number of lines before prompting for keyboard input.

    I suppose you could open a pipe to a pager program in the same fashion... but it's just sexier to bless a typeglob.

(jptxs) Re: Paging STDOUT?
by jptxs (Curate) on Dec 14, 2000 at 05:04 UTC
    If this is *nix, then what I would do is is simply pipe it. You could even write a wrapper if needed. So if finder.pl is the perl that searches, then you write findIt.sh which basically runs:
    #!/bin/<some>sh finder.pl | more
    Obviously edit the above for taste, proper shell and other switches you may feed it. Then when you want it you call findIt.sh. Saves you the trouble of reinventing a pager in some way. That's what I'd do...
    "A man's maturity -- consists in having found again the seriousness one had as a child, at play." --Nietzsche
(tye)Re: Paging STDOUT?
by tye (Sage) on Dec 14, 2000 at 20:46 UTC

    Something like:

    my $pager= $ENV{PAGER} || "more"; open STDOUT, "| $pager" or warn "Not paging STDOUT: $!\n";
    should work even under Windows. I think it'd work under even more OSes so long as you set PAGER or have a version of "more" installed.

    But, in testing this, I did find one wrinkle. Under Win32, the process model is rather basic and I couldn't find a way to get the shell to wait for "more" to finish. Here is the closest I came which seems to demonstrate a bug:

    perl -le "open STDOUT, '| more'; $|=1; print for 0..50; close(STDOUT) +or warn $!; wait" ... Bad file descriptor at -e line 1. ...
    so the close fails which means that "more" never gets EOF and never exits. Note that the wait really shouldn't be there as an explicit close on a piped command does a wait. I just added that when Perl wasn't waiting for "more" to exit [ which made Perl wait forever which made me wonder why close wasn't sending an EOF which made me add the warn which showed me a bug in Perl -- now where is my prize? ;-) ].

    So on OSes where Perl isn't broken (: you'd probably want to add:

    END { close(STDOUT) }
    so that Perl sends "more" an EOF and then waits for "more" to exit.

            - tye (but my friends call me "Tye")