I would like to show how I am creating printer-ready documents using LaTeX templates from within Perl with LaTeX::Easy::Templates which I have recently published. I will illustrate this introduction with preparing pdf (envelope) labels since a question (Printing Labels) about this was asked earlier.
Latex offers to the People easy access to professional typography producing aesthetically superb documents. And to the hacker the means to do the same programmatically and automatically, with zero mouse-clicking and menu selecting. Remember, once Latex was the best (OK IMO) alternative to the evil, closed-standard, M$'s pitiful attempts to writing software. Gosh that ugly font!
Perl users have often inlined latex in their scripts, embeded with data and then shelling out (or using LaTeX::Driver) in order to call latex to produce the final typeset. The same way HTML was produced back in the cavas [sic]! :)
Latex templates, similar to HTML templates, achieve separation of Model, View & Controller. Additionally, the particular package LaTeX::Easy::Templates handles all the typesetting (via LaTeX::Driver) and makes it easy to typeset your data for publishing. With in-memory latex templates it means you can readily typeset data from a string template with a standalone perl script.
For the problem at hand: printing (envelope) labels, posted by Bod, I will use the "labels" latex package (documentation) and two simple latex templates label.tex.tx and labels.tex.tx. The latter is the entry point and includes the former for each label in the input. Of course, a single template could be used instead, but the spirit is to be modular.
Currently the only template engine supported by LaTeX::Easy::Templates is Text::Xslate which performs really fast and has some nifty features which allow for powerful expressions. Including recursion and access to any Perl module. As a consolation to TT fans, it offers a TT-like syntax, called TTerse.
Here is the entry point latex template: ./templates/labels/labels.tex.tx:
% I am ./templates/labels/labels.tex.tx \documentclass[12pt]{letter} \usepackage{graphicx} \usepackage{labels} \begin{document} : for $data -> $label { : include 'label.tex.tx' { label => $label }; : } \end{document}
The template responsible for rendering a single label is the following. Notice how it is included in the above in a loop over each label:
% I am ./templates/labels/label.tex.tx \genericlabel{ \begin{tabular}{|c|} \hline : if $label.sender.logo { \includegraphics[width=1cm,angle=0]{<: $label.sender.logo :>}\\ : } \hline <: $label.recipient.fullname :>\\ \hline : for $label.recipient.addresslines -> $addressline { <: $addressline :> : } \\ <: $label.recipient.postcode :>\\ \hline \end{tabular} }
Save these two files under a directory called ./templates/labels, optionally create a logo image here ./templates/images/logo.png. You can create as complex a directory hierarchy as it suits you but you should adjust the file paths in the script.
And here is the script to harness the beast:
use LaTeX::Easy::Templates; use FindBin; my $curdir = $FindBin::Bin; # the templates can be placed anywhere as long these # paths are adjusted. As it is now, they # must both be placed in ./templates/labels # the main entry is ./templates/labels/labels.tex.tx # which calls/includes ./templates/labels/label.tex.tx my $template_filename = File::Spec->catfile($curdir, 'templates', 'lab +els', 'labels.tex.tx'); # optionally specify a logo image my $logo_filename = File::Spec->catfile($curdir, 'templates', 'images' +, 'logo.png'); if( ! -e $logo_filename ){ $logo_filename = undef } my $output_filename = 'labels.pdf'; # see LaTeX::Driver's doc for other formats, e.g. pdf(xelatex) my $latex_driver_and_format = 'pdf(pdflatex)'; # debug settings: my $verbosity = 1; # keep intermediate latex file for inspection my $cleanup = 1; my $sender = { fullname => 'Gigi Comp', addresslines => [ 'Apt 5', '25, Jen Way', 'Balac' ], postcode => '1An34', # this assumes that ./templates/images/logo.png exists, else comment + it out: logo => $logo_filename, }; my @labels_data = map { { recipient => { fullname => "Teli Bingo ($_)", addresslines => [ 'Apt 5', '25, Jen Way', 'Balac' ], postcode => '1An34', }, sender => $sender, } } (1..42); # create many labels yummy my $latter = LaTeX::Easy::Templates->new({ 'debug' => { 'verbosity' => $verbosity, 'cleanup' => $cleanup }, 'processors' => { 'custom-labels' => { 'template' => { 'filepath' => $template_filename, }, 'latex' => { 'filepath' => 'xyz.tex', 'latex-driver-parameters' => { 'format' => $latex_driver_and_format, } } }, } }); die "failed to instantiate 'LaTeX::Easy::Templates'" unless defined $l +atter; my $ret = $latter->format({ 'template-data' => \@labels_data, 'output' => { 'filepath' => $output_filename, }, 'processor' => 'custom-labels', }); die "failed to format the document, most likely latex command has fail +ed." unless defined $ret; print "$0 : done, output in '$output_filename'.\n";
edit: check the output here: https://metacpan.org/pod/LaTeX%3A%3AEasy%3A%3ATemplates#EXAMPLE:-PRINTING-STICKY-LABELS
edit: example of other labels. Cute? In general https://www.overleaf.com allows you to browse typeset documents and show you the source for using them as a basis.
edit: I have set the "untemplated" latex file to be saved to 'xyz.tex' for inspection. Ideally that file can be rendered with latex using: pdflatex xyz.tex . Its only dependency is the logo image (if any) and the labels, graphicx latex packages. In production you omit specifying a filename and all is written in temp files to be erased at the end.
edit: make sure you have latest version of LaTeX::Easy::Templates.
OnT but OtT: LaTeX has for many years been powering the scientific publishing industry (and what an industry that is!). As free and open-source software so that they can charge $$ for the People to access free literature produced by scientists paid by their taxes.
bw, bliako
|
---|