Beefy Boxes and Bandwidth Generously Provided by pair Networks
laziness, impatience, and hubris
 
PerlMonks  

Re^2: Group __DATA__ lines in a while?

by Lady_Aleena (Priest)
on Oct 21, 2013 at 06:12 UTC ( [id://1059070]=note: print w/replies, xml ) Need Help??


in reply to Re: Group __DATA__ lines in a while?
in thread Group __DATA__ lines in a while?

I would like to wrap each section in an HTML <section>. Also, the subroutines (line, heading, and paragraph) used in story print immediately. It appears to get the table of contents, I will have to go through the lines twice.

sub story { my ($source,$author) = @_; my $tab = 3; my @toc; while (my $line = <$source>) { chomp($line); if ($line =~ /^2/) { my ($number,$text) = split(/ /,$line,2); push @toc, anchor($text, { href => '#'.idify($text) }); } } list($tab, 'u', \@toc, { class => 'two' }); # I ran $source above, so I can't have it here! /me head desks. while (my $line = <$source>) { chomp($line); # If a line starts with a bracket, just print the line. if ($line =~ m/^</) { line($tab,$line); } # If a line starts with a numeral 1-6, print a heading. elsif ($line =~ /^[1-6]\s/) { my ($heading,$text) = split(/ /,$line,2); my $id = idify($text); heading($tab,$heading,$text, { id => $id }); } # If a line is a break or horizontal rule, print the line in brack +ets. elsif ($line =~ /^[bh]r$/) { line($tab,"<$line>"); } # All other lines are paragraphs. else { paragraph($tab,$line); } } # If I wrote a story, I want people to know I wrote it at the bottom +. paragraph($tab,"written by $root_user", { class => 'author' }) if !$ +author; }
No matter how hysterical I get, my problems are not time sensitive. So, relax, have a cookie, and a very nice day!
Lady Aleena

Replies are listed 'Best First'.
Re^3: Group __DATA__ lines in a while?
by hdb (Monsignor) on Oct 21, 2013 at 07:01 UTC

    How about delayed execution? You push all commands onto a stack and only execute after reading all data:

    sub story { my ($source,$author) = @_; my $tab = 3; my @toc; my @commands; push @commands, [ \&startsection, "Lead" ]; # I ran $source above, so I can't have it here! /me head desks. while (my $line = <$source>) { chomp($line); # If a line starts with a bracket, just print the line. if ($line =~ m/^</) { push @commands, [ \&line, $tab, $line ]; } # If a line starts with a numeral 1-6, print a heading. elsif ($line =~ /^[1-6]\s/) { my ($heading,$text) = split(/ /,$line,2); if( $heading == 2 ) { push @toc, anchor($text, { href => '#'.idify($text) } +); if( $commands[-1]->[0] eq \&startsection ) { # not sur +e this comparison is valid... pop @commands; # to avoid empty sections } else { push @commands, [ \&endsection ]; } push @commands, [ \&startsection, $text ]; # adapt arg +uments as required } my $id = idify($text); push @commands, [ \&heading, $tab,$heading,$text, { id => +$id } ]; } # If a line is a break or horizontal rule, print the line in b +rackets. elsif ($line =~ /^[bh]r$/) { push @commands, [ \&line, $tab, "<$line>" ]; } # All other lines are paragraphs. else { push @commands, [ \&paragraph, $tab, $line ]; } } push @commands, [ \&endsection ]; # do the table of contents list($tab, 'u', \@toc, { class => 'two' }); # delayed execution of all print commands for (@commands) { my $cmd = shift @$_; $cmd->(@$_); } # If I wrote a story, I want people to know I wrote it at the bott +om. paragraph($tab,"written by $root_user", { class => 'author' }) if +!$author; }

    I cannot test this code but it hopefully conveys the idea...

    startsection and endsection would be two subs to print the HTML to start and end a section.

    Update: some changes in formatting of the post and added a missing comma in the code.

    Update: added a missing endsection at the end.

      I think I got it, however, I didn't use your code. I'm sorry. Here is how I did it.

      sub story { my ($source,$author) = @_; my $tab = 3; my $inc = 0; my @sections; my @toc; while (my $line = <$source>) { chomp($line); if ($line =~ /^2/) { $inc++; my ($number,$text) = split(/ /,$line,2); push @toc, anchor($text, { href => '#'.idify($text) }); } push @{$sections[$inc]}, $line; } list($tab, 'u', \@toc, { class => 'two' }) if @toc > 3; for my $section (@sections) { section($tab, sub { for my $line (@{$section}) { chomp($line); if ($line =~ m/^</) { line($tab,$line); } elsif ($line =~ /^[1-6]\s/) { my ($heading,$text) = split(/ /,$line,2); my $id = idify($text); heading($tab,$heading,$text, { id => $id }); } elsif ($line =~ /^[bh]r$/) { line($tab,"<$line>"); } else { paragraph($tab,$line); } } }); } paragraph($tab,"written by $root_user", { class => 'author' }) if !$ +author; }
      No matter how hysterical I get, my problems are not time sensitive. So, relax, have a cookie, and a very nice day!
      Lady Aleena

        If you are interested in a more compact style, you could be writing your @sections loop as

        section($tab, sub { for my $line (@$_) { heading($tab,$1,$2, { id => idify($2) }), next if $line =~ /^( +[1-6])\s+(.*)/; line($tab,$line), next if $line =~ /^< +/; line($tab,"<$line>"), next if $line =~ /^[ +bh]r$/; paragraph($tab,$line); } }) for @sections;

        I like this for its tabular look where the action is on the left and the condition on the right. It also avoids the chain of elsifs. The danger is that it becomes difficult to stay the course when the actions become more complex...

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://1059070]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others goofing around in the Monastery: (5)
As of 2024-04-19 07:09 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found