Search code examples
perltemplatescommand-linetemplate-toolkit

template-toolkit: passing array variables into tpage from command line?


I have this template working correctly:

$ cat matrix.tt 
[% DEFAULT
    ncols = 3
    elems = [1,2,3,4,5,6,7,8,9]
%]
\left[\begin{matrix}
[% WHILE elems.size %]
    [% elems.splice(0,ncols).join(' & ') %]
    [% IF elems.size %]\\[% END %]
[% END %]
\end{matrix}\right]
$ tpage --pre_chomp --post_chomp matrix.tt 
\left[\begin{matrix}1 & 2 & 3\\4 & 5 & 6\\7 & 8 & 9\end{matrix}\right]

But this does not work:

$ tpage --define ncols=2 --define elems=[1,2,3,4] matrix.tt 
undef error - WHILE loop terminated (> 1000 iterations) 

I found using the following code that it is not trivial to pass arrays using the --define option to tpage.

$ cat pk.tt 
[% DEFAULT 
    ho = [1,2]
-%]
ho is [% ho %]
po is [% po %]
$ tpage --define po=[1,3] pk.tt #I want po to be interpreted as an array
ho is ARRAY(0x1a3fd00)
po is [1,3]

The output shows that po is a scalar. I want to pass arrays from command line is there any way to do that?


Solution

  • Here is a way to pass any data into tpage from command line without having to tweak tpage source or the template.

    $ cat matrix.tt 
    [% DEFAULT
        ncols = 3
        elems = [1,2,3,4,5,6,7,8,9,10,11,12]
    %]
    \left[\begin{matrix}
    [% WHILE elems.size %]
        [% elems.splice(0,ncols).join(' & ') %]
        [% IF elems.size %]\\[% END %]
    [% END %]
    \end{matrix}\right]
    $ cat <(echo '[% elems=["x","y","z",1,2,3] %]') matrix.tt |tpage --pre_chomp --post_chomp
    \left[\begin{matrix}x & y & z\\1 & 2 & 3\end{matrix}\right]
    $ 
    

    or if you wish, you can type in a directive to set variables and press ^D:

    $ rlwrap cat - matrix.tt |tpage --pre_chomp --post_chomp
    [%
      ncols=4
      elems=[4,5,6,7,"x","y","z","t"]
    %]
    \left[\begin{matrix}4 & 5 & 6 & 7\\x & y & z & t\end{matrix}\right]
    $
    

    rlwrap saves the lines you type in, and makes them available later by pressing the up key. You can remove rlwrap if you do not need this.

    The method works with any program that can process stdin given the shell supports this kind of redirection. I hope it is pretty portable.