A few (more) hints on how to use teepee.
Assumptions
We will assume to have the following filename.json JSON file lying around:
{
"name": "Flavio",
"surname": "Poletti",
"cpan": {
"metacpan": "https://metacpan.org/author/POLETTIX",
"latest": [
"Data::Crumbr",
"Template::Perlish",
"Graphics::Potrace",
"Log::Log4perl::Tiny"
],
"favorites": {
"JSON": { "id": "MAKAMAKA" },
"Dancer": { "id": "YANICK" },
"Moo": { "id": "HAARG" }
},
"using": {
"JSON": { "id": "https://metacpan.org/release/JSON" }
},
"id": "POLETTIX"
}
}and the corresponding filename.yaml too.
Input
Input from File or Standard Input
Reading from a file while auto-detecting the format:
$ teepee -i filename.json ...
$ teepee -i filename.yaml ...Force reading as JSON:
$ teepee -j filename.json ...
$ teepee -j filename.json -f json ...Force reading as YAML:
$ teepee -y filename.yaml ...
$ teepee -y filename.yaml -f yaml ...Input comes from standard input by default, no need to specify anything
in this case (although you can be explicit and use filename -):
# auto-detect
$ cat filename.json | teepee ...
$ cat filename.json | teepee -i - ...
# force reading as JSON
$ cat filename.json | teepee -f json ...
$ cat filename.json | teepee -j - ...
# force reading as YAML
$ cat filename.yaml | teepee -f yaml ...
$ cat filename.yaml | teepee -y - ...Input from Text on Command Line
You can specify input text with a shell trick (using <<<) and what
explained before, or using the following options directly:
$ teepee -I '{"some":"json"}' ...
$ some_json=$(< filename.json)
$ teepee -J "$some_json" ...
$ some_yaml=$(< filename.yaml)
$ teepee -Y "$some_yaml" ...No Input
Sometimes you don’t need to read an input data structure (e.g. when you
define variable’s values using -d/--define):
$ teepee -N ...Output
Output is sent to standard output by default. You can either
redirect/pipe it, or use option -o to save to a file:
$ teepee -o output-file ...Many options/tricks specify how the output is generated, so read on! One
option is described here, though: if you want to add a newline at the
very end of the input, pass option -n:
$ teepee -n ...Templates Handling
Templates are generally written using rules of Template::Perlish:
- plain text is rendered as-is
- whatever is enclosed between a pair of
[%and%]is considered special- if the pair contains a path in the data, the chunk is expanded with the value of the variable at the specific position in the input data
- if the opening is immediately followed by an equal sign
=(with no spaces), the chunk is interpreted as Perl code and the last value is substituted for the chunk - otherwise, the chunk is considered Perl code but nothing is printed by default
- whatever is printed to standard output in the Perl code inside the chunks is expanded in place of the chunk.
A path in the data is something like path.to.1.variable. This
is split upon the the dots, and each section is used to traverse the
input data structure. So, if we had a reference $V to the data
structure, the example path would be resolved to
$V->{path}{to}[1]{variable} (assuming of course that there are hashes
and arrays at the right places).
Text Templates
Templates can be taken from a file, for example file1.tmpl:
Hello [% cpan.id %] ([% name %] [% surname %])Use option -t to load them:
$ teepee -j filename.json -t file1.tmpl
Hello POLETTIX (Flavio Poletti)… or from a string on the command line:
$ teepee -nj filename.json -T 'Hello [% cpan.id %]!'
Hello POLETTIX!We used option -n to add a newline to the output!
Variables
Getting a single variable only has its own shortcut, i.e. the following are equivalent:
$ teepee -nj filename.json -T '[% cpan.latest.1 %]'
Template::Perlish
$ teepee -nj filename.json -v cpan.latest.1
Template::PerlishFunctions
Getting the output of a function only has its own shortcut, i.e. the following are equivalent:
$ teepee -nj filename.json -T '[%= 2+2 %]'
4
$ teepee -nj filename.json -F 2+2
4This comes handy for calling a few pre-defined functions as explained below.
Pretty-Printing
Pretty-printing (or converting!) in JSON:
$ teepee -y filename.yaml -FJSON
{
"name" : "Flavio",
"surname" : "Poletti",
"cpan" : {
"favorites" : {
"Dancer" : {
"id" : "YANICK"
},
"Moo" : {
"id" : "HAARG"
},
"JSON" : {
"id" : "MAKAMAKA"
}
},
"metacpan" : "https://metacpan.org/author/POLETTIX",
"latest" : [
"Data::Crumbr",
"Template::Perlish",
"Graphics::Potrace",
"Log::Log4perl::Tiny"
],
"using" : {
"JSON" : {
"id" : "https://metacpan.org/release/JSON"
}
},
"id" : "POLETTIX"
}
}Pretty-printing (or converting!) in YAML:
$ teepee -j filename.json -FYAML
---
cpan:
favorites:
Dancer:
id: YANICK
JSON:
id: MAKAMAKA
Moo:
id: HAARG
id: POLETTIX
latest:
- Data::Crumbr
- Template::Perlish
- Graphics::Potrace
- Log::Log4perl::Tiny
metacpan: https://metacpan.org/author/POLETTIX
using:
JSON:
id: https://metacpan.org/release/JSON
name: Flavio
surname: PolettiGenerating HTML/XML
Functions urlenc, xmlenc and xmltxt can come handy when generating
HTML/XML - they encode the argument to a representation that is safe for
inclusion in URL or text, respectively. This is urlenc in action:
$ ./teepee -nNT 'http://example.com/[%= urlenc("&a <- \"b\"") %]'
http://example.com/%26a%20%3C-%20%22b%22xmlenc encodes the five reserved characters < > ' " &:
$ ./teepee -nNT '<hey>[%= xmlenc("&a <- \"b\"") %]</hey>'
<hey>&a <- "b"</hey>xmltxt is like xmlenc, but it encodes only < and & (which should be
fine in all cases anyway):
$ ./teepee -nNT '<hey>[%= xmltxt("&a <- \"b\"") %]</hey>'
<hey>&a <- "b"</hey>Crumbr Mode
Crumbr mode allows you to expand the whole input data structure with one
line per leaf, so that you should be able to easily use grep and
sed.
$ teepee -j filename.json -Fcrumbr
cpan/favorites/Dancer/id "YANICK"
cpan/favorites/JSON/id "MAKAMAKA"
cpan/favorites/Moo/id "HAARG"
cpan/id "POLETTIX"
cpan/latest/0 "Data::Crumbr"
cpan/latest/1 "Template::Perlish"
cpan/latest/2 "Graphics::Potrace"
cpan/latest/3 "Log::Log4perl::Tiny"
cpan/metacpan "https:\/\/metacpan.org\/author\/POLETTIX"
cpan/using/JSON/id "https:\/\/metacpan.org\/release\/JSON"
name "Flavio"
surname "Poletti"You can be exact in distinguishing between hash keys and array indexes:
$ teepee -j filename.json -Fexact_crumbr
{"cpan"}{"favorites"}{"Dancer"}{"id"}:"YANICK"
{"cpan"}{"favorites"}{"JSON"}{"id"}:"MAKAMAKA"
{"cpan"}{"favorites"}{"Moo"}{"id"}:"HAARG"
{"cpan"}{"id"}:"POLETTIX"
{"cpan"}{"latest"}[0]:"Data::Crumbr"
{"cpan"}{"latest"}[1]:"Template::Perlish"
{"cpan"}{"latest"}[2]:"Graphics::Potrace"
{"cpan"}{"latest"}[3]:"Log::Log4perl::Tiny"
{"cpan"}{"metacpan"}:"https:\/\/metacpan.org\/author\/POLETTIX"
{"cpan"}{"using"}{"JSON"}{"id"}:"https:\/\/metacpan.org\/release\/JSON"
{"name"}:"Flavio"
{"surname"}:"Poletti"You might want to get a JSON-compliant representation of each line:
$ teepee -j filename.json -Fjson_crumbr
{"cpan":{"favorites":{"Dancer":{"id":"YANICK"}}}}
{"cpan":{"favorites":{"JSON":{"id":"MAKAMAKA"}}}}
{"cpan":{"favorites":{"Moo":{"id":"HAARG"}}}}
{"cpan":{"id":"POLETTIX"}}
{"cpan":{"latest":["Data::Crumbr"]}}
{"cpan":{"latest":["Template::Perlish"]}}
{"cpan":{"latest":["Graphics::Potrace"]}}
{"cpan":{"latest":["Log::Log4perl::Tiny"]}}
{"cpan":{"metacpan":"https:\/\/metacpan.org\/author\/POLETTIX"}}
{"cpan":{"using":{"JSON":{"id":"https:\/\/metacpan.org\/release\/JSON"}}}}
{"name":"Flavio"}
{"surname":"Poletti"}Variables Accessors
Variables accessors are shortcut functions that allow expanding a variable according to the (expected) type.
Scalar variables can be accessed via V (for Variable, not for
Scalar!):
# another alternative for -v...
$ teepee -nj filename.json -F 'V "cpan.favorites.Moo.id"'
HAARG
$ teepee -nj filename.json -F '"*" x length V "cpan.favorites.Moo.id"'
*****Array references are de-referenced using A:
$ teepee -nj filename.json -F 'A "cpan.latest"'
4
$ teepee -j filename.json -F 'print "- $_\n" for A "cpan.latest"'
- Data::Crumbr
- Template::Perlish
- Graphics::Potrace
- Log::Log4perl::TinyHashes can be dereferenced in three ways: directly with H, only keys
with HK, only values with HV:
$ teepee -nj filename.json -F 'my %favs = H "cpan.favorites"; $favs{JSON}{id}'
MAKAMAKA
$ teepee -j filename.json -F 'print "- $_\n" for HK "cpan.favorites"'
- Moo
- Dancer
- JSON
$ teepee -j filename.json -F 'print "- $_->{id}\n" for HV "cpan.favorites"'
- MAKAMAKA
- HAARG
- YANICKLoading Functions
If you want to load Perl functions from modules, as of version 0.7.0
you can with options -M and -l.
The former (-M, alias --module) allows you to load modules and
functions from the command line, and consume those functions from inside
the template:
$ teepee -nj filename.json -M Digest::MD5=md5_hex -F 'md5_hex(V "name")'
e6a25ad746bb0923f593e94f5128d13dYou can import multiple functions separating their names with a comma:
$ teepee -nj filename.json -M Digest::MD5=md5_hex,md5_base64 \
-F 'md5_hex(V "name") . " " . md5_base64(V "name")'
e6a25ad746bb0923f593e94f5128d13d 5qJa10a7CSP1k+lPUSjRPQAlternatively, you can just specify a line that will be used:
$ teepee -nj filename.json -M 'Digest::MD5 qw< md5_hex md5_base64 >' \
-F 'md5_hex(V "name") . " " . md5_base64(V "name")'
e6a25ad746bb0923f593e94f5128d13d 5qJa10a7CSP1k+lPUSjRPQIn particular, whatever you pass as parameter will be evaled like
follows:
# -M 'Digest::MD5 qw< md5_hex md5_base64 >'
use Digest::MD5 qw< md5_hex md5_base64 >;If you want to load modules/functions that don’t lie around in places
perl would normally look into, you can add places to the directory
search list using option -l (alias --lib, alias --include).
Suppose you have module Foo::Bar inside lib/Foo/Bar.pm:
$ teepee -nj filename.json -M 'Foo::Bar' -l lib -F 'foo(V "name")'
...
teepee