Doing Some Funky HTML Sh*t with Raku

Came across some pretty funky PHP/HTML the other day. No, I did not write it! (btw using echo is considered bad practice)

function html_form_code() {
    echo '<form action="' . esc_url( $_SERVER['REQUEST_URI'] ) . '" method="post">';
    echo '<p>';
    echo 'Your Name (required) <br />';
    echo '<input type="text" name="cf-name" pattern="[a-zA-Z0-9 ]+" 
                    value="' . ( isset( $_POST["cf-name"] ) ? esc_attr( $_POST["cf-name"] ) : '' ) . '" size="40" />';
    echo '</p>';
    echo '<p>';
    echo 'Your Email (required) <br />';
    echo '<input type="email" name="cf-email" value="' . ( isset( $_POST["cf-email"] ) ? esc_attr( $_POST["cf-email"] ) : '' ) . '" size="40" />';
    echo '</p>';
    echo '<p>';
    echo 'Subject (required) <br />';
    echo '<input type="text" name="cf-subject" pattern="[a-zA-Z ]+" 
                     value="' . ( isset( $_POST["cf-subject"] ) ? esc_attr( $_POST["cf-subject"] ) : '' ) . '" size="40" />';
    echo '</p>';
    echo '<p>';
    echo 'Your Message (required) <br />';
    echo '<textarea rows="10" cols="35" name="cf-message">' . ( isset( $_POST["cf-message"] ) ? esc_attr( $_POST["cf-message"] ) : '' ) . '</textarea>';
    echo '</p>';
    echo '<p><input type="submit" name="cf-submitted" value="Send"/></p>';
    echo '</form>';

By coincidence, three HTML-ish Raku ideas have recently popped into my inbox courtesy of the Raku Weekly rag:

So this all got me wondering what my funky PHP/HTML sample would look like in a fully fledged Cro / Raku style… in the spirit of keeping this post briefish, I will skip the Cro Templates and CSS parsing for now and hope to cover them in subsequent missives…

First, here is gfldex’s code copied to my source file:

constant term:<␣> = ' ';
constant term:<¶> = $?NL;

constant term:<§> = class :: does Associative {
    sub qh($s) {
        $s.trans([ '<'   , '>'   , '&' ] =>
                 [ '&lt;', '&gt;', '&amp;' ])

    role NON-QUOTE {}

    method AT-KEY($key) {
        when $key ~~ /^ '&' / { 
            $key does NON-QUOTE
        when $key ~~ /\w+/ {
            sub (*@a, *%_) {
                ##dd @a; 
                ('<' ~ $key ~ (+%_ ?? ␣ !! '') 
                ~{ .key ~ '="' ~ .value ~ '"'  }).join(' ') ~ '>' 
                ~{ $^e ~~ NON-QUOTE ?? $^e !! $^e.&qh }).join('')
                ~ '</' ~ $key ~ '>') does NON-QUOTE

Sharp eyed viewers will notice that I have made one change … replacing the constant ‘html’ with term: < § > … this is called the section symbol and lurks towards the top left of your keyboard. I find this greatly improves the readability of my embedded html.

So, here’s how my PHP example looks in modern Raku stylee:

my $action = '';
my $cf-name = 'p6steve';
my $cf-email = '';
my $cf-subject = 'Raku does HTML';
my $cf-message = 'Describe your feelings about this...';

my $size = <40>;
my $pattern = <[a-zA-Z0-9 ]+>;

put '<!DOCTYPE html>';
§<html>( ¶,  
    §<body>( ¶,
        §<form>(:$action, :method<post>, ¶,       
            §<p>('Your Name (required)'), ¶,
            §<input>(:type<text>, :required, :name<cf-name>, 
                                  :value($cf-name), :$size, :$pattern,), ¶,

            §<p>('Your Email (required)'), ¶,     #email type validates input
            §<input>(:type<email>, :required, :name<cf-email>, 
                                   :value($cf-email), :$size), ¶,  

            §<p>('Your Subject (required)'), ¶,
            §<input>(:type<text>, :required, :name<cf-subject>, 
                                  :value($cf-subject), :$size, :$pattern,), ¶,

            §<p>('Your Message (required)'), ¶,
            §<p>(§<textarea>(:rows<10>, :cols<35>, :required, 
                             :name<cf-message>, $cf-message, ),), ¶,

            §<input>(:type<submit>, :name<cf-submitted>, :value<Send>,), ¶,

Thoughtfully glfdex includes a para character ¶ term, to make line breaks in the output html source to keep it human friendly. And here is the html output:

<DOCTYPE html>
<form action="" method="post">
<p>Your Name (required)</p>
<input pattern="[a-zA-Z0-9 ]+" type="text" name="cf-name" size="40" required="True" value="p6steve"></input>
<p>Your Email (required)</p>
<input size="40" value="" type="email" required="True" name="cf-email"></input>
<p>Your Subject (required)</p>
<input name="cf-subject" pattern="[a-zA-Z0-9 ]+" type="text" size="40" value="Raku does HTML" required="True"></input>
<p>Your Message (required)</p>
<p><textarea required="True" cols="35" rows="10" name="cf-message">Describe your feelings about this...</textarea></p>
<input name="cf-submitted" value="Send" type="submit"></input>

Personally I love to write (and read) html when done in this kind of programmatic style. Not least it has cut 19 lines of embedded code to 10 lines (and that means I can squish more code into my screen and into my brain). No longer do I have to dance my right pinkie around the < / > keys or worry about leaving out the closing end tags!! Another neat helper is the Raku pair syntax, so if I define a scalar with the same name as the attribute name, I can avoid repetitive typing and the consequent opportunity to make a mistake… e.g. the :$action attribute in the form tag.

Hopefully in the next instalment, I will be able to combine the power of Cro::Web::Template to apply the substitution and escape pieces…

Please do leave any thoughts and comments below.



  1. gfldex says:

    Maybe a sub called pretty-print-html(Str $html –> Str) is in order.


    1. p6steve says:

      I have taken the liberty of making a gist here … with a couple of tweaks to handle Bool attires e.g. :required, some css and a very basic pretty-print-html sub…


  2. p6steve says:

    neat idea … I am thinking that (i) adding CSS quoting, (ii) somehow escaping/mixin for using this to generate Cro::Web::Templates and (iii) then round trip through Raku CSS/(X)HTML parsers would be cool.


Leave a Comment

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s