From: Tom Christiansen <tchrist@mox.perl.com>
Subject: SRC: here docs
Date: 22 May 1998 13:22:16 GMT
Ever want to use a here document with interpolation? Here's an example
that does that:
die "Couldn't send mail" unless send_mail(<<"EOTEXT", $target);
To: $fatboy
From: Your Manager ($0)
Cc: @{ get_manager_list($fatboy) }
Date: @{[ my $now = `date`; chomp $now; $now ]} (today)
Dear $fatboy,
Today, you exceeded your 5 kilobyte disk quota for the ${\( 500 +
int rand(100)) }th and last time. Your account is now closed.
Sincerely,
the management
EOTEXT
Ever want to indent the body of your here document? Use a s/// to strip
out leading white space.
# all in one
($VAR = <<HERE_TARGET) =~ s/^\s+//gm;
your text
goes here
HERE_TARGET
# or with two steps
$VAR = <<HERE_TARGET;
your text
goes here
HERE_TARGET
$VAR =~ s/^\s+//gm;
Larry shows us in s2p how a simple fixerupper function can make this
even easier.
sub fix {
my $string = shift;
$string =~ s/^\s+//gm;
return $string;
}
print fix(<<"END");
My stuff goes here
END
# With function predeclaration, you can omit the parens:
print fix <<"END";
My stuff goes here
END
Ever want to indent your end token as well? Quote it as well!
($quote = <<' FINIS') =~ s/^\s+//gm;
...we will have peace, when you and all your works have
perished--and the works of your dark master to whom you would
deliver us. You are a liar, Saruman, and a corrupter of men's
hearts. --Theoden in /usr/src/perl/taint.c
FINIS
$quote =~ s/\s*--/\n--/;
Another trick that Larry shows us in s2p is putting a leading
string in front of the code that's not alive yet. Let's imagine
we have a dequote fixerupper function predeclared. We can do this:
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
$got_it++;
}
Destroying indentation also tends to get you in trouble with poets.
So you want this to work as well:
$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";
Here's a dequote() function that handles all of these cases. It looks
to see whether each line begins with a common string, and if so, strips
that off. Otherwise, it takes the leading white space from the first
line and removes only that much off each 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 $_;
}
--tom
--
"A well-written program is its own heaven;
a poorly-written program is its own hell."