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

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.

Replies are listed 'Best First'.
Re^4: Group __DATA__ lines in a while?
by Lady_Aleena (Priest) on Oct 21, 2013 at 07:51 UTC

    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...

        I just want you to know, I did it your way when I made a handful of additions. You were right about the elsifs spiraling out of control. Here is the updated version. :)

        sub story { my ($source,$magic) = @_; my $tab = 3; my $inc = 0; my @sections; my @toc; while (my $line = <$source>) { chomp($line); next if !$line; if ($line =~ /^2/) { my ($number,$text) = split(/ /,$line,2); push @toc, anchor(textify($text), { href => '#'.idify($text) }); $inc++; } push @{$sections[$inc]}, $line; } $inc = 0; for my $section (@sections) { if ($section) { section($tab, sub { for my $line (@{$section}) { line($tab, $line), next if $line =~ /^</; line($tab, "<$line>"), next if $line =~ /^[bh]r$/; $magic->{$1}->(), next if $line =~ /^&\s+(.*)/; blockquote($tab, $1), next if $line =~ /^bq\s(.*)/; item($tab, $1), next if $line =~ /^\*\s(.*)/; item($tab, $2, { value => $1 }), next if $line =~ /^\*(\d+)\ +s(.*)/; heading($tab, $1, $2, { id => idify($2) }), next if $line + =~ /^([1-6])\s+(.*)/; paragraph($tab, $line, { class => 'author' }), next if $line + =~ /^by /; paragraph($tab, $line); } }); } if ($inc == 0 && @toc > 3) { section($tab, sub { my $class = @toc > 25 ? @toc > 50 ? 'four' : 'three' : 'two'; my $style = @toc > 50 ? 'font-size:smaller' : undef; list($tab, 'u', \@toc, { class => $class, style => $style }); }, { class => 'contents'} ); } $inc++; } # paragraph($tab,"written by $root_user", { class => '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

        hdb, it got a little more complicated than it was. Here is the the most recent version. There are a few more elsif statements. I am almost content with it now. :)

        sub story { my ($source,$magic) = @_; my $tab = 3; my $inc = 0; my @sections; my @toc; while (my $line = <$source>) { chomp($line); next if !$line; if ($line =~ /^2/) { $inc++; my ($number,$text) = split(/ /,$line,2); push @toc, anchor(textify($text), { href => '#'.idify($text) }); } push @{$sections[$inc]}, $line; } $inc = 0; for my $section (@sections) { if ($section) { section($tab, sub { for my $line (@{$section}) { if ($line =~ m/^</) { line($tab,$line); } elsif ($line =~ /^& /) { my ($symbol,$magic_word) = split(/ /,$line,2); $magic->{$magic_word}->(); } elsif ($line =~ /^[1-6]\s/) { my ($heading,$text) = split(/ /,$line,2); my $id = idify($text); heading($tab,$heading,$text, { id => $id }); } elsif ($line =~ /^bq\s/) { my ($symbol,$text) = split(/ /,$line,2); blockquote($tab,$text); } elsif ($line =~ /^[bh]r$/) { line($tab,"<$line>"); } else { paragraph($tab,$line); } } }); } if ($inc == 0 && @toc > 3) { section($tab, sub { list($tab, 'u', \@toc, { class => 'two' }); }, { class => 'contents'} ); } $inc++; } # paragraph($tab,"written by $root_user", { class => '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