template-toolkit: передача переменных массива в tpage из командной строки?
У меня этот шаблон работает правильно:
$ 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]
Но это не работает
$ tpage --define ncols=2 --define elems=[1,2,3,4] matrix.tt
undef error - WHILE loop terminated (> 1000 iterations)
Используя следующий код, я обнаружил, что нетривиально передавать массивы с помощью --define
возможность 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]
Выходные данные показывают, что po является скаляром. Я хочу передать массивы из командной строки, есть ли способ сделать это?
3 ответа
Вот способ передать любые данные в tpage
из командной строки без необходимости настраивать tpage
источник или шаблон.
$ 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]
$
или, если хотите, вы можете ввести директиву для установки переменных и нажать ^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
сохраняет введенные вами строки и делает их доступными позже, нажав up
ключ. Вы можете удалить rlwrap
если тебе это не нужно
Метод работает с любой программой, которая может обрабатывать stdin
данная оболочка поддерживает этот вид перенаправления. Я надеюсь, что это довольно портативно.
В зависимости от того, насколько сложными являются значения в вашем массиве, вы можете получить что-то вроде:
[%- el = elems.split(',') -%]
\left[\begin{matrix}
[% WHILE el.size %]
[% el.splice(0,ncols).join(' & ') %]
... #etc
$ tpage --define ncols=2 --define elems="1,2,3,4" matrix.tt
Но если конечно elems
не контролируется или имеет встроенные метасимволы или запятые, которые могут привести к боли. Но в противном случае достаточно просто преобразовать скаляр в массив, используя .split()
VMethod.
Аргументы командной строки для tpage
не оцениваются как Perl-код, поэтому вы можете получить только строковые значения. Если вы хотите поддержать произвольный код Perl, вам нужно взломать tpage
источник.
Найдите следующую строку в источнике:
my %ttopts = $config->varlist('^template_(?!directive_)', 1);
На следующей строке добавьте следующий код:
foreach my $var (keys %{ $ttopts{variables} }) {
$ttopts{variables}{$var} = eval $ttopts{variables}{$var};
die $@ if $@;
}
Это перебирает все аргументы --define
и звонки eval
на них, преобразовывая их из строк в код Perl.
Когда вы запустите это, не забудьте процитировать ваши аргументы, чтобы защитить их от расширения оболочкой:
$ ./tpage --define 'array=["foo","bar"]' --define 'hash={baz=>"qux"}' foo.tt
$VAR1 = [
'foo',
'bar'
];
$VAR1 = {
'baz' => 'qux'
};
$ cat foo.tt
[% USE Dumper %]
[% Dumper.dump(array) %]
[% Dumper.dump(hash) %]
Чтобы передать буквальную строку, вы должны заключить ее в кавычки q{}
или же qq{}
потому что AppConfig удаляет обычные кавычки (tpage
негласно использует AppConfig для чтения аргументов командной строки). Например:
$ ./tpage --define 'string=q{foo}' foo.tt
$VAR1 = 'foo';
$ cat foo.tt
[% USE Dumper %]
[% Dumper.dump(string) %]
Обратите внимание, что хотя Template Toolkit поддерживает переменные практически любого типа Perl, моя модифицированная версия tpage
не делает. Числа, строки, массивы и хэши должны все работать; подпрограммы нет.