Re: Here documents in blocks
by hippo (Bishop) on Dec 19, 2020 at 16:36 UTC
|
It's not very neat, but you could alter indent() to take an optional second argument which is the maximum amount of leading space to trim. eg:
#!/usr/bin/perl
use strict;
print "Content-type: text/plain\n\n";
print "Test\n\n";
sub indent {
my ($text, $cols) = @_;
$cols //= 1000;
$text =~ s/^\s{0,$cols}//gm;
return $text;
}
if (1) {
print indent(<<"END_TEXT", 1);
Here is
some test text
with plenty of space
and an indent here
at the start
END_TEXT
}
exit 0;
Note that you'll need to be careful with tabs v spaces. The value of 1 for $cols here is fine for a tab. You'll see that with that level, the indent on line 4 of the paragraph is preserved.
PS. indent is probably better named outdent since that is effectively what it is doing.
| [reply] [d/l] [select] |
Re: Here documents in blocks
by Discipulus (Canon) on Dec 19, 2020 at 16:50 UTC
|
Hello Bod,
if I understand your question, prior of perl 5.26 you can use some trick to indent heredocs: substitution (but the token in not indented):
($var = <<"HEREDOC") =~ s/^\s+//gm;
your text
goes here
HEREDOC
But note you can also use " HEREDOC" as token: see (and follow the white rabbit) here
L*
There are no rules, there are no thumbs..
Reinvent the wheel, then learn The Wheel; may be one day you reinvent one of THE WHEELS.
| [reply] [d/l] [select] |
|
| [reply] [d/l] [select] |
|
print <<"HEREDOC" =~ s/^\s+//gm; # <- Doesn't work
your text
goes here
HEREDOC
I guess it could just be followed by print $var; but that continues the theme of inelegant solutions. I am sure there is a 'nice' solution to this...
| [reply] [d/l] [select] |
|
print <<"HEREDOC" =~ s/^\s+//gmr; # <- works
your text
goes here
HEREDOC
__END__
your text
goes here
| [reply] [d/l] [select] |
|
use strict;
use warnings;
print $_=<<" EOT";
indented
as
intended
EOT
exit;
L*
There are no rules, there are no thumbs..
Reinvent the wheel, then learn The Wheel; may be one day you reinvent one of THE WHEELS.
| [reply] [d/l] |
|
|
|
Re: Here documents in blocks
by BillKSmith (Monsignor) on Dec 19, 2020 at 19:50 UTC
|
The book "Perl Best Practices" recommends factoring out such a heredoc into a subroutine. "The heredoc does compromise the indentation of the subroutine, but that's now a small and isolated section of the code..."
| [reply] |
|
FWIW, all 255 Perl Best Practices (without the text from the PBP book) are available here.
There are a number of items related to heredocs in the Values and Expressions chapter, the most relevant being item 42:
Use a "theredoc" when a heredoc would compromise your indentation. This item offers two alternative ways to minimize compromising code indentation (which harms readability): i) factor out the heredoc into a predefined read-only constant at the file level; ii) factor out the heredoc inside a small subroutine (indentation is compromised but only in a small and isolated section of the code). Both methods do not indent the contents of the heredoc, so no error-prone tricks are required to adjust. Conway describes both methods as a "theredoc".
| [reply] |
|
The book "Perl Best Practices"
Unfortunately my copy of that book is sat on a shelf in my office...I was last in my office back in February before the Pesky Pandemic turned the world upside down.
Come to think of it, I filled up the biscuit tin the last time I was there!
| [reply] |
|
Speaking merely as a long time satisfied customer https://learning.oreilly.com/ (used to be called "Safari Books Online" back when I first subscribed) lets you get to electronic versions of all the ORA books as well as things from lots of other tech publishers as well as video courses. I've found it well worth what I pay them yearly that I don't spend on dead tree copies (then again I'm satisfied with reading things on my iPad).
Alternately keep an eye out as Humble Bundle periodically will have ORA pdfs in a collection (e.g. this current one; but nothing (directly) perl related in this one though).
The cake is a lie.
The cake is a lie.
The cake is a lie.
| [reply] |
Re: Here documents in blocks (updated)
by AnomalousMonk (Archbishop) on Dec 19, 2020 at 18:30 UTC
|
Win8 Strawberry 5.30.3.1 (64) Sat 12/19/2020 13:18:14
C:\@Work\Perl\monks
>perl -Mstrict -Mwarnings
use 5.014; # for s/// with /r modifier
print "Content-type: text/plain\n\n";
print "Test\n\n";
# sub undent { # works, but not as flexible
# return $_[0] =~ s/^\s+//gmr;
# }
sub undent {
my $text = shift;
$text =~ s{ \A [^\n]* \n (\s*) }{}xms;
my $dent = length $1;
return $text =~ s{ ^ \s{0,$dent} }{}xmsgr;
}
if (1) {
print undent "
Here is
some test text
that can
also be
ragged
with plenty of space
at the start\n"
}
^Z
Content-type: text/plain
Test
Here is
some test text
that can
also be
ragged
with plenty of space
at the start
However, this has the disadvantage that you have to manually stick a
newline at the end to get a nice block ending. But I suppose you
could tack that on automatically with a .= "\n" or some such.
(Update: I realized after posting that I only tested
with spaces as indentation characters, not tabs, which I never use
anyway. I think the code would work with pure tab
indents, but I haven't tested this. I doubt the code would work with
a mixture of spaces and tabs used as indentation.)
Update: Yes,
return $text =~ s{ ^ \s{0,$dent} }{}xmsgr . "\n";
seems to do it for the automatic newline text block end.
Give a man a fish: <%-{-{-{-<
| [reply] [d/l] [select] |
Re: Here documents in blocks
by tybalt89 (Monsignor) on Dec 19, 2020 at 19:58 UTC
|
#!/usr/bin/perl
use strict; # https://perlmonks.org/?node_id=11125451
use warnings;
sub indent {
my $text = shift;
$text =~ s/^\s//gm until $text =~ /^\S/m;
return $text;
}
if (1) {
print indent(<<"");
Here is
some test text
with plenty of space
and even an indented line
at the start
}
Outputs:
Here is
some test text
with plenty of space
and even an indented line
at the start
| [reply] [d/l] [select] |
|
| [reply] [d/l] |
|
It's just a tradeoff between danger and beauty :)
Personally I put the HERE-IS block at the left hand edge, and skip the whole "indent" thing.
(A what (indent) you see, is what you get.)
| [reply] |
|
|
|
Re: Here documents in blocks
by marto (Cardinal) on Dec 19, 2020 at 16:45 UTC
|
"Not very pretty and quite difficult to follow as it becomes more involved, especially as more and more HTML gets added over time. So a slight improvement..."
With respect it isn't 1995 anymore. Using classes and inline styles in HTML? Not using a templating system or modern framework. FWIW Mojolicious has an excellent support for this out of the box.
| [reply] |
|
| [reply] |
|
| [reply] |
|
|
|
|
|
Re: Here documents in blocks
by kcott (Archbishop) on Dec 20, 2020 at 03:31 UTC
|
G'day Bod,
I had a look through your post and came up with quite a few solutions;
although, as I read through the other posts, I found most had already been covered.
However, this one hasn't been addressed:
"... put every line in a separate print statement ..."
The print function takes a list.
You don't need a massive column of print statements:
sometimes you might need a few; for the HTML table code you showed, you really only need one.
I've reduced the HTML to bare bones text but the principle is the same.
I've included a conditional line just as your code had.
$ perl -e '
print
qq{line1\n},
qq{line2\n},
($ARGV[0] == 20 ? qq{line3\n} : ""),
qq{line4\n};
' 19
line1
line2
line4
$ perl -e '
print
qq{line1\n},
qq{line2\n},
($ARGV[0] == 20 ? qq{line3\n} : ""),
qq{line4\n};
' 20
line1
line2
line3
line4
I think you'll agree that code is a lot cleaner; easier to read; and easier to maintain.
I suppose you have your reasons for using 5.16 —
I'm stuck with that at $work too; but I use 5.32 at home.
Thankfully, I work at home normally (nothing to do with the plague) so I can build utilities in 5.32
to automate a large part of my work; unfortunately, I need to use 5.16 for all legacy code.
Anyway, the suggestions by others that I saw will work under 5.16 (templating systems, s///r, and so on).
| [reply] [d/l] [select] |
|
I think you'll agree that code is a lot cleaner; easier to read; and easier to maintain.
I certainly do agree!
Thanks Ken for this. Between this and other answers I think I can produce some much nicer code next time I am faced with this sort of problem.
I suppose you have your reasons for using 5.16
It's what is installed on the shared hosting...I have 5.32 on my laptop and even 5.28 on my mobile!
The webhost are doing an upgrade over night at the beginning of January. They have not said what is being upgraded but I'm hoping that they will installing a later version of Perl although I won't be holding my breath.
Like you, I normally work from home. My company doesn't have any offices so all my employees work remotely. We just have one small conference room for face to face meetings and I have an office next to that but unusually only visit about once a month and I have not been there since February due to the Pesky Pandemic which, here in the UK, seems to be getting worse rather than better - quite concerning as we are in the hospitality sector.
| [reply] |
Re: Here documents in blocks [chomp]
by kcott (Archbishop) on Dec 20, 2020 at 03:57 UTC
|
Here's another trick I've used occasionally that involves chomp.
The following code will leave a blank line at the end of <pre> blocks when the HTML is rendered:
$ perl -e '
my $insert = <<EOF;
line1
line2
line3
EOF
print "<pre>$insert</pre>";
'
<pre>line1
line2
line3
</pre>
chomp to the rescue:
$ perl -e '
chomp(my $insert = <<EOF);
line1
line2
line3
EOF
print "<pre>$insert</pre>";
'
<pre>line1
line2
line3</pre>
It can fix lots of annoying problems like that; not just <pre> blocks.
| [reply] [d/l] [select] |
Re: Here documents in blocks [s///r chaining]
by kcott (Archbishop) on Dec 20, 2020 at 17:00 UTC
|
Me again. I don't think I've ever written this many responses to a single OP. :-)
Use of s///r has been mentioned in more than one post.
I wondered if you knew that you could chain them.
You can also chain y///r and mix them up.
This type of extended construct is valid; although, I can't think of an immediate use for such a beast:
$str =~ s///r =~ y///r =~ s///r =~ tr///r
I saw where you'd written that you don't really have time to learn a completely new system.
The following may be useful in its own right;
however, it may get you halfway to writing a more formal template.
When you do get around to looking at templating systems
— and I do recommend you at least put that on your TODO list —
you'll probably notice the similarities between placeholders like __TOKEN__ here
and those used by templating systems, such as <% TOKEN %>.
In the following code, the main processing, including the s///r chaining, is all at the front;
the (messy) heredocs are written as theredocs and moved out of the way to the end of the code.
$ perl -E '
my @users = (
{ audience => "Management" },
{ audience => "Employee" },
{ audience => "Guest" },
);
generate_report($_) for @users;
sub generate_report {
my ($user) = @_;
say main_template()
=~ s/__AUDIENCE__/$user->{audience}/r
=~ s/__MNGT_REP__/mngt_rep($user)/er
=~ s/__EMP_REP__/emp_rep($user)/er
=~ s/__GUEST_REP__/guest_rep($user)/er;
}
# Theredocs (out of the way)
sub main_template {
<<EOF
<p>
Report for __AUDIENCE__.
</p>
__MNGT_REP____EMP_REP____GUEST_REP__
EOF
}
sub mngt_rep {
my ($viewer) = @_;
return "" unless $viewer->{audience} eq "Management";
return <<EOF
<div>
... Management Report ...
</div>
EOF
}
sub emp_rep {
my ($viewer) = @_;
return "" unless $viewer->{audience} eq "Employee";
return <<EOF
<div>
... Employee Report ...
</div>
EOF
}
sub guest_rep {
my ($viewer) = @_;
return "" unless $viewer->{audience} eq "Guest";
return <<EOF
<div>
... Guest Report ...
</div>
EOF
}
'
When run, that outputs:
<p>
Report for Management.
</p>
<div>
... Management Report ...
</div>
<p>
Report for Employee.
</p>
<div>
... Employee Report ...
</div>
<p>
Report for Guest.
</p>
<div>
... Guest Report ...
</div>
| [reply] [d/l] [select] |
Re: Here documents in blocks
by Anonymous Monk on Dec 20, 2020 at 22:04 UTC
|
I would strongly suggest that you consider using something like Template::Toolkit even though you might not be producing "a web page." These are very useful in creating a separation of concerns between what you want to include and exactly how you want the finished text to look. | [reply] |
|
| [reply] |