I just started a new job a few weeks ago, and they had me learn perl. It's a very nice language... mostly because you get to yell "CHOMP" whenever you type chomp.

And now, thanks to perl, I can easily solve a problem that was too much bother to deal with before...

Internet guitar tab is the bastard child of ASCII art and musical notation. It looks like this, and as you can see, it's most undesirable to have a page break in the middle of a line of tab (which consists of 6 or more lines of text).

So I wrote this script to prevent paragraphs from spanning a page break. Perhaps someone's done this before but I figured it would be good practice... what do you guys think?

#!/usr/bin/perl -w use strict; use constant LPP => 63; # for enscript my @chunk = (); my $line = 0; while (<>) { if (/^\s*$/) { &printchunk; ++$line; print; } else { push @chunk,$_; } } &printchunk; sub printchunk { if (@chunk + $line >= LPP) { print "\n" while $line++ < LPP; $line = 0; } $line += @chunk; print @chunk; @chunk = (); }

Replies are listed 'Best First'.
Re: page break at paragraph break
by dewey (Pilgrim) on Jul 28, 2007 at 23:27 UTC
    Nice! Heh, CHOMP... what would we do without fun keywords? I'm rather fond of carp, croak, cluck, and confess.

    As for the script itself, cool use for Perl. It looks just fine. I don't know if you're looking for suggestions, but a couple things popped into my head as I was reading. You could pass @chunk and $line into printchunk, returning the new line number. That way, if the program becomes larger it won't be cluttered up with globals. Also, LPP is a seldom-used constant. It could have a more expressive name without too much extra typing.

    That's all! Welcome to PerlMonks.

    ~dewey
      Thanks dewey! :)

      Not only does the constant have a mysterious name, it should probably be a variable settable by a command line option... but whatever :P

      And as far as passing arguments to printchunk... I agree again. It was done this way because I didn't originally have the second call, but then I realized I was cutting off the last few bars of every song. o.O So I jammed it in a sub and added a second call---which is more elegant than copy-pasting it, though not as elegant as what you suggest.

Re: page break at paragraph break
by SuicideJunkie (Vicar) on Jul 31, 2007 at 14:10 UTC

    Watch out for paragraphs which are longer than one page; Your code will blank out the current page (even if there is nothing on the page yet), and then print over the page break and end up with $line > LPP.

    After that, the $line will be inaccurate, and no longer match your actual position on the page.

    Try using: $line %= LPP; which will set $line to zero in the typical case of $line == LPP, but will maintain your page position if you overflow.


    Instead of printing a series of "\n", could you print a FormFeed character (0x0C) and then set $line to 0? It would work best on an actual printer or a fancy document viewer.

Re: page break at paragraph break
by jwkrahn (Abbot) on Jul 30, 2007 at 04:57 UTC
    If you don't mind losing some whitespace (blank lines) you could do it like this:
    #!/usr/bin/perl -w use strict; use constant LPP => 63; # for enscript my @chunk; my $line = 0; $/ = ''; while ( <> ) { if ( $line + y/\n// >= LPP ) { print "\n" x ( LPP - $line ); $line = 0; } print; $line += y/\n//; }
      Well, a file might have lines of tab, followed by a blank line, followed by a line of lyrics, followed by two blanks, followed by more tab. Mangling the whitespace could make this confusing.