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