>Today around 4:30pm, Tom Christiansen hammered out this masterpiece:
>: print <<FOO =~ /^\s+(.*\n)/g;
>According to current implementation, that has to look like:
> print <<" FOO" =~ /^\s+(.*\n)/gm;
>Unless, of course, you want `xx oo' to be indented still, and the blank <SNIP>
>remain. That requires more thought.
> print <<" FOO" =~ m/[\r\f\t ]*(.*\n)/mg;
>Will preserve the empty line but not the indentation.
>I can't, without more thought, preserve the indentation within this syntax
>style. I'd have to break it's scope and have two passes on the data.
Oh, I see what was meant now. Perhaps just ignore the heredoc's leading
and trailing whitespace, then.
The Ram has something on this. First it talks about " FOO", which
you can't really do much about and which I now infer was the original
thrust, and then the following for helping things stand out better.
I'm thinking now in retrospect that dequote() here might have been
some Larry code, actually.
--tom
Another embellishment is to use a special leading string for
code that isn't ``real'' yet so that it stands out. For example,
here we'll prepend each line with C<@@@>, properly indented.
if ($REMEMBER_THE_MAIN) {
$perl_main_C = dequote<<' MAIN_INTERPRETER_LOOP';
@@@ int
@@@ runops() {
@@@ SAVEI32(runlevel);
@@@ runlevel++;
@@@ while ( op = (*op->op_ppaddr)() ) ;
@@@ TAINT_NOT;
@@@ return 0;
@@@ }
MAIN_INTERPRETER_LOOP
# add more code here if you wnat
}
Destroying indentation also tends to get you in trouble with poets.
$poem = dequote<<EVER_ON_AND_ON;
Now far ahead the Road has gone,
And I must follow, if I can,
Pursuing it with eager feet,
Until it joins some larger way
Where many paths and errands meet.
And whither then? I cannot say.
--Bilbo in /usr/src/perl/pp_ctl.c
EVER_ON_AND_ON
print "Here's your poem:\n\n$poem\n";
The following C<dequote> function handles all these cases. It
expects to be called with a here document as its argument. It
looks to see whether each line begins with a common substring,
and if so, strips that off. Otherwise, it takes the amount of
leading white space found on the first line and removes that
much off each subsequent line.
sub dequote {
local $_ = shift;
my ($white, $leader); # common white space and common leading string
if (/^\s*(?:([^\w\s]+)(\s*).*\n)(?:\s*\1\2?.*\n)+$/) {
($white, $leader) = ($2, quotemeta($1));
} else {
($white, $leader) = (/^(\s+)/, '');
}
s/^\s*?$leader(?:$white)?//gm;
return $_;
}
If that pattern makes your eyes glaze over, you can always break
it up and add comments by adding C</x>:
if (m{
^ # start of line
\s * # 0 or more whitespace chars
(?: # begin first non-remembered grouping
( # begin save buffer $1
[^\w\s] # one byte neither space nor word
+ # 1 or more of such
) # end save buffer $1
( \s* ) # put 0 or more white in buffer $2
.* \n # match through the end of first line
) # end of first grouping
(?: # begin second non-remembered grouping
\s * # 0 or more whitespace chars
\1 # whatever string is destined for $1
\2 ? # what'll be in $2, but optionally
.* \n # match through the end of the line
) + # now repeat that group idea 1 or more
$ # until the end of the line
}x
)
}
($white, $leader) = ($2, quotemeta($1));
} else {
($white, $leader) = (/^(\s+)/, '');
}
s{
^ # start of each line (due to /m)
\s * # any amount of leading white space
? # but minimally matched
$leader # our quoted, saved per-line leader
(?: # begin unremembered grouping
$white # the same amount
) ? # optionalize in case EOL after leader
}{}xgm;
There, wasn't that much easier to read? Well, maybe not;
sometimes it doesn't help all to pepper your code with insipid
comments that just mirror the code. This may be one of those
cases.