{"id":17799425,"url":"https://github.com/polettix/teepee","last_synced_at":"2025-03-17T05:32:39.714Z","repository":{"id":34729078,"uuid":"38707012","full_name":"polettix/teepee","owner":"polettix","description":"extract data from structures","archived":false,"fork":false,"pushed_at":"2022-05-06T14:56:58.000Z","size":1324,"stargazers_count":6,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-02-27T21:29:07.813Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Perl","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/polettix.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-07-07T18:31:18.000Z","updated_at":"2022-05-06T14:57:02.000Z","dependencies_parsed_at":"2022-09-14T18:41:17.210Z","dependency_job_id":null,"html_url":"https://github.com/polettix/teepee","commit_stats":null,"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/polettix%2Fteepee","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/polettix%2Fteepee/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/polettix%2Fteepee/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/polettix%2Fteepee/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/polettix","download_url":"https://codeload.github.com/polettix/teepee/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243852484,"owners_count":20358271,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-27T12:07:15.965Z","updated_at":"2025-03-17T05:32:39.003Z","avatar_url":"https://github.com/polettix.png","language":"Perl","readme":"# NAME\n\nteepee - extract data from structures\n\n# HURRY UP!\n\nGet the bundled version like this:\n\n    curl -LO https://github.com/polettix/teepee/raw/master/bundle/teepee\n\nor this\n\n    wget https://github.com/polettix/teepee/raw/master/bundle/teepee\n\nor just click here:\n[https://github.com/polettix/teepee/raw/master/bundle/teepee](https://github.com/polettix/teepee/raw/master/bundle/teepee).\n\nFor way more than you want to know about `teepee` visit also\n[http://github.polettix.it/teepee/](http://github.polettix.it/teepee/).\n\n# USAGE\n\n    teepee [--usage] [--help] [--man] [--version]\n\n    teepee [-A|--auto-key]\n           [-P|--auto-key-prefix string]\n           [-S|--auto-key-suffix string]\n           [-b|--binmode setting]\n           [-K|--default-key string]\n           [-d|--define key=value]\n           [-f|--format input-format]\n           [-F|--function spec]\n           [-I|--immediate text]\n           [-i|--input filename]\n           [-j|--jsn|--json filename]\n           [-J|--json-s text]\n           [-l|--lib|--include dirname]\n           [-M|--module module-spec]\n           [-n|--newline|--no-newline]\n           [-N|--no-input]\n           [-o|--output filename]\n           [-t|--template filename]\n           [-T|--text string]\n           [-v|--variable string]\n           [-y|--yml|--yaml filename]\n           [   --yaml-1 filename]\n           [-Y|--yaml-s text]\n           [   --yaml-s1 text]\n\n# EXAMPLES\n\n    # suppose to start from this data structure in JSON inside data.json,\n    # YAML works much in the same way.\n    {\n       \"name\": \"Flavio\",\n       \"surname\": \"Poletti\",\n       \"cpan\": {\n          \"metacpan\": \"https://metacpan.org/author/POLETTIX\",\n          \"latest\": [\n             \"Data::Crumbr\",\n             \"Template::Perlish\",\n             \"Graphics::Potrace\",\n             \"Log::Log4perl::Tiny\"\n          ],\n          \"favorites\": {\n             \"JSON\":   { \"id\": \"MAKAMAKA\" },\n             \"Dancer\": { \"id\": \"YANICK\"   },\n             \"Moo\":    { \"id\": \"HAARG\"    }\n          },\n          \"using\": {\n             \"JSON\": { \"id\": \"https://metacpan.org/release/JSON\" }\n          },\n          \"id\": \"POLETTIX\"\n       }\n    }\n\n    # get a few variables:\n    # -n prints a newline at theend\n    # -i indicates the input file to use\n    # -v indicates the \"path\" into the data structure, can include\n    #    indexes in arrays\n    $ teepee -ni data.json -v name\n    Flavio\n    $ teepee -ni data.json -v cpan.favoritex.JSON.id\n    MAKAMAKA\n    $ teepee -ni data.json -v cpan.using.JSON.id\n    https://metacpan.org/release/JSON\n    $ teepee -ni data.json -v cpan.latest.1\n    Template::Perlish\n\n    # pretty-print in JSON or YAML, output to /dev/null (useful, uh?)\n    $ teepee -i data.json -FJSON -o /dev/null\n    $ teepee -i data.json -FYAML -o /dev/null\n\n    # input might be available directly on the command line, just use\n    # the uppercase variant\n    $ data=$(\u003c data.json)\n    $ teepee -nI \"$data\" -v cpan.id\n    POLETTIX\n\n    # you can format your output using templates, e.g. from command line\n    $ teepee -nI \"$data\" -T 'Hello, [% name %] [% surname %]!'\n    Hello, Flavio Poletti!\n\n    # templates can be read from files. Lowercase option means file\n    $ teepee -nI \"$data\" -t template.txt -o /dev/null\n\n    # To see how you can write templates, please look at the\n    # documentation for Template::Perlish at\n    # https://metacpan.org/pod/Template::Perlish\n\n    # you can set some values in the data structure from the command\n    # line, just use option -d\n    $ teepee -nI \"$data\" -d name=FLAVIO\n       \\ -T 'Hello, [% name %] [% surname %]!'\n    Hello, FLAVIO Poletti!\n\n    # no need for the key/index to already exist when using -d\n    $ teepee -nI \"$data\" -d github.id=polettix \\\n       -T '[% cpan.id %]@CPAN is [% github.id %]@GitHub'\n    POLETTIX@CPAN is polettix@GitHub\n\n    # there is actually no need to read any data structure at all\n    # but this has to be indicated using -N\n    $ teepee -nN -d github.id=polettix -d cpan.id=POLETTIX \\\n       -T '[% cpan.id %]@CPAN is [% github.id %]@GitHub'\n    POLETTIX@CPAN is polettix@GitHub\n\n# DESCRIPTION\n\n`teepee` allows you to generate data according to a template. Data is\nextracted from data structures available in JSON or YAML format, read\nfrom files or from standard input. This should make it easy to extract\nthe needed data e.g. out of the output from some tool that provides you\nstructured JSON or YAML text in output.\n\n## Options Overview\n\nInput data structures can be provided via option [-i ](https://metacpan.org/pod/\u0026#x20;--input). You\ncan provide more than one input; in this case, they will be read in\norder and merged together. Merging in this case means that whatever is\npresent in a file provided later in the command line supersedes\nwhatevever was previously available. If you set the input filename as\n`-`, the input will be read from standard input.\n\nYou can provide input definitions from the command line too, via option\n[\"--define\"](#define). In this case, you can provide the \"path\" into the\ndata structure separating items with a dot `.`. Any key part that\nresembles an integer index starting from 0 will be interpreted as an\narray index, otherwise it will be considered a hash key. Definitions\nwith this options always supersede those read from input files.\n\nThe input format can be either specified explicitly via option\n[\"--format\"](#format) or deduced implicitly. The heuristic will first check the\nfile name, then the contents. Suggestion is to specify it if you happen\nto know, expecially for programmatic usage.\n\nThe template to be expanded can be provided either from a file (via\noption [\"--template\"](#template)) or from the command-line directly (via option\n[\"--text\"](#text)). Templates can be written according to what\n[Template::Perlish](https://metacpan.org/pod/Template::Perlish) provides. As quick, specialized alternatives to\n[\"--text\"](#text), you can also use [\"--function\"](#function) and [\"--variable\"](#variable).\n\nAll files are supposed to be UTF-8 encoded. When the template is\nprovided from the command line, module [I18N::Langinfo](https://metacpan.org/pod/I18N::Langinfo) is used to\nauto-detect the terminal setting and try to do the right things. If in\ndoubt, just use a UTF-8 encoded file for your template.\n\nOutput is sent to either standard output (by default or if you set the\nfilename to `-`) or to the filename specified via option `/--output`.\nOutput will be printed assuming that the receiving end is UTF-8 capable.\n\nAs of version `0.7.0`, it is possible to also pre-load modules in the\n_right_ package where the templates are expanded, with a simple syntax\nthat leverages on options [\"-M\"](#m)/[\"--module\"](#module) (for importing modules) and\n[\"-l\"](#l)/[\"--lib\"](#lib)/[\"--include\"](#include) (for adding directories to the module search\npath).\n\n## Reading Inputs\n\nIt's worth noting that input data might come into three forms,\nindependently of the input format: _hash_ (i.e. _object_ in JSON),\n_array_ or _scalar_. Whatever the input, a big _hash_/_object_ is\nbuilt and eventually consumed by the templates; every time the top-level\nelement in the input is not a _hash_, the following applies:\n\n- a (hopefully) unique key is generated joining [\"--auto-key-prefix\"](#auto-key-prefix), an\nincreasing integer number starting from `0`, and [--auto-key-suffix](https://metacpan.org/pod/--auto-key-suffix).\nThe value is associated to this key in the top level hash.\n- the last value read in this way is always associated to key\n[\"--default-key\"](#default-key).\n\nBy default, the three options are set to the string `_` (one single\nunderscore).\n\nFor example, if you have two input files with two arrays inside:\n\n    # first input, JSON format\n    [ \"one\", \"two\", \"three\" ]\n\n    # second input, JSON format\n    [ 1, 2, 3 ]\n\nthe resulting overall hash read will be the following when the two\ninputs are read in the order above:\n\n    {\n       _0_ =\u003e [ 'one', 'two', 'three' ],\n       _1_ =\u003e [ 1, 2, 3 ],\n       _   =\u003e [ 1, 2, 3 ],\n    }\n\nYou can change the different options to be able to mix the input arrays\nwith hashes and preserve key uniqueness.\n\nIf you specify input option [--auto-key](https://metacpan.org/pod/--auto-key), the above algorithm will\nalways be applied, also for hash inputs. This allows you get input from\nmultiple sources without the risk of having keys trump on each other\n(which might be or not what you want).\n\n## Writing Templates\n\nTemplates for extracting data are written according to what\nTemplate::Perlish provides. You should take a look at its documentation\nat [https://metacpan.org/pod/Template::Perlish](https://metacpan.org/pod/Template::Perlish). Only a few tricks will\nbe reported here, just to get your feet wet.\n\nWe will suppose to have the following data, represented as YAML:\n\n    ---\n    key1: value1\n    key2: value2\n    array:\n       - first\n       - second\n       - third\n       -\n          k1: v1\n          k2: v2\n    hash:\n       one: two\n       three: four\n       five:\n          - a\n          - b\n          - 'see...'\n       'complex key': whatever\n\nValues that are neither hashes/objects nor arrays will be called\n_scalars_.\n\nSo, we have a hash at the top level, with four keys (`key1`, `key2`,\n`array` and `hash`), two of which are scalars, one is an array and one\nis a hash. The array contains four items, the last of which is a hash\nwith two keys (`k1` and `k2`). The hash contains three keys, the first\ntwo (`one` and `three`) associated to a scalar value, the last one\nbeing an array with three strings inside.\n\nIf you want to just access scalar variable pointed by key `three`\ninside `hash`, it is sufficient to provide the _path_ to that value as\na sequence of keys starting from the top level and separated by a dot,\nlike this:\n\n    [% hash.three %]\n\nIf you want to access an array's element, the trick is similar but you\nwill have to use the index (starting from 0) instead of the key. So, for\nexample, the `b` in the second array would be accessed like this:\n\n    [% hash.five.1 %]\n\nand the `v1` like this:\n\n    [% array.3.k1 %]\n\nPlease note that, by default, the keys that you can concatenate can only\ncontain alphanumeric values, plus the underscore. What if you want to\naccess `whatever` then? You can insert non-alphanumeric characters\nusing quotes, like this:\n\n    [% hash.'complex key' %]\n\nAs you can imagine, there are ways to also cope with keys that have\nquotes inside, so refer to Template::Perlish if you need to know more.\n\nBesides just accessing scalar values, you might want to add some logic\nto your templates. You can do this by simply writing Perl code, because\nwhatever is not recognised as a valid _path of keys_ is considered Perl\ncode and evaluated accordingly:\n\n    current time: [% print scalar localtime() %]\n\nThere is even a shortcut to just print the output of an expression, so\nthe above example can be written like this:\n\n    current time: [%= scalar localtime() %]\n\n(note that there is an equal sign just after the template opening).\n\nWhen you are writing Perl code, you can access the data structure\nthrough the hash variable `%variables`, so the following are\nequivalent:\n\n    [% hash.'complex key' %]\n    [%= $variables{hash}{'complex key'} %]\n\nbut of course you can do fancier things with the second one, like this:\n\n    uppercase: [%= uc $variables{hash}{'complex key'} %]\n\nAccessing variables like this can be boring if you have a deeply nested\ndata structure, because it's a lot of typing and a lot of curly\nbrackets. To save typing and time, you can use the shortcut function\n`V`, so the following are equivalent:\n\n    [%  hash.'complex key' %]\n    [%= $variables{hash}{'complex key'} %]\n    [%= V(\"hash.'complex key'\") %]\n\nAs you are probably guessing, `V` uses the same algorithm as just\nputting a plain sequence of path elements, including its restrictions on\nnon-alphanumeric characters. This is considered a feature, because it\nadds consistency.\n\nJust like you can access any variable with `V`, you also have a few\nadditional functions at your disposal for some common tasks. For\nexample, sometimes you will want to iterate over an array and find just\nthose elements that have some characteristics, e.g. restricting only to\nelements that are hashes containing the `k1` key. The long version is\nthis, of course:\n\n    [%\n       for my $item (@{$variables{array}}) {\n          next unless ref($item) eq 'HASH';\n          next unless exists $item-\u003e{k1};\n          print $item-\u003e{k1};\n          last;\n       }\n    %]\n\nYou can use the `V` shortcut, of course:\n\n    [%\n       for my $item (@{V('array')}) {\n          next unless ref($item) eq 'HASH';\n          next unless exists $item-\u003e{k1};\n          print $item-\u003e{k1};\n          last;\n       }\n    %]\n\nalthough in this case you would probably use `A` instead:\n\n    [%\n       for my $item (A 'array') {\n          next unless ref($item) eq 'HASH';\n          next unless exists $item-\u003e{k1};\n          print $item-\u003e{k1};\n          last;\n       }\n    %]\n\nThis takes the element at path `array` from `%variables`, expands it\nas an array and... well, what you do with it is completely up to you, of\ncourse.\n\n## Pretty Printing\n\nSometimes, especially in an interactive session, you might just want to\ntake a look at the data structure you have to traverse; this is where\n_pretty-printing_ comes handy.\n\nYAML is already quite readable by its own, so chances are that you might\nwant to have some pretty-printing when your data is represented in\ncampact JSON format.\n\nThere are two functions for pretty-printing: [\"YAML\"](#yaml) and [\"JSON\"](#json). As\nyou might have guessed, they print out the input data structure\nrespectively as YAML and JSON (so they can also be used to transform one\ninto the other, of course). It suffices to use the `/-F` option to get\ntheir services:\n\n    # pretty-print JSON as JSON\n    $ teepee -FJSON \u003cinput.json\n\n    # just dump as YAML\n    $ teepee -FYAML \u003cinput.whatever\n\nNote that if your input is not an hash, or you are using [\"--auto-key\"](#auto-key),\nyour data structure will contain multiple references to the same\nobjects, which by default is considered a _circular data reference_.\n`teepee` solves this problem by eliminating the [\"--default-key\"](#default-key) from\nthe input hash before doing the pretty-printing.\n\nThis will anyway give you something that is different from the real\ninput data, because of the embedding into the top-level hash.  If you\njust want the original data, you can do as follows (this will work only\nfor the last read input data of course):\n\n    # pretty-print JSON as JSON\n    $ teepee -F'JSON(V(\"_\"))' \u003cinput.json\n\n    # just dump as YAML\n    $ teepee -F'YAML(V(\"_\"))' \u003cinput.whatever\n\nThis isolates the last read input with an auto-generated key (with\n`V(\"_\")`) and pretty-prints that (passing to the relevant function,\ni.e. either `JSON` or `YAML`).\n\n## Feeling Better With `grep`?\n\nIf you're not very comfortable with Perl... you should. There are a lot\nof very good resources out there to learn it, the most outstanding\nand readily available example is probably Modern Perl\n([http://onyxneon.com/books/modern\\_perl/index.html](http://onyxneon.com/books/modern_perl/index.html), look for both the\nprinted and online version).\n\nAnyway, if you're in a hurry and you prefer to use `grep`/`sed` and\nall other classical Unix tools, you can turn on _crumbr_ mode and play\nwith its output.\n\nTo understand what crumbr does, let's start from an example, i.e. let's\nsee what this does when applied to the example data structure described\nin [\"Writing Templates\"](#writing-templates). The template is quite straightforward in this\ncase:\n\n    $ teepee -T '[%= crumbr(); %]' -i data.yml\n\nand the output is the following:\n\n    array/0 \"first\"\n    array/1 \"second\"\n    array/2 \"third\"\n    array/3/k1 \"v1\"\n    array/3/k2 \"v2\"\n    hash/complex%20key \"whatever\"\n    hash/five/0 \"a\"\n    hash/five/1 \"b\"\n    hash/five/2 \"see...\"\n    hash/one \"two\"\n    hash/three \"four\"\n    key1 \"value1\"\n    key2 \"value2\"\n\nEvery leaf node is represented on a single line of its own. Each line\ncontains a URI-shaped path, a space, and a JSON-encoded representation\nof the value. Hash keys are sorted lexicographically, array keys are\nsorted numerically.\n\nSo, are we still looking at the values pointed by key `k1` inside any\nhash under the top-level array? This is how you do it:\n\n    $ teepee -T '[%= crumbr(); %]' -i data.yml \\\n      | grep '^array/[0-9][0-9]*/k1 '\n\nYou get the idea. Typing (or even remembering) that template might be\ncumbersome, which is why there is a shorthand option [\"-F\"](#f) that lets\nyou just write this instead:\n\n    $ teepee -Fcrumbr -i data.yml | grep '^array/[0-9][0-9]*/k1'\n\nSee [\"--function\"](#function)/[\"-F\"](#f) for the available functions in addition to\n`crumbr`. We will use this short form from now on.\n\nWhy the JSON encoding in the output? Aren't those double quotes\nannoying? The answer is probably yes, but they are also needed. In fact,\nthere are a few cases where you will _not_ see them, namely:\n\n- **empty arrays**\n\n    are represented as `[]`, without quotes\n\n- **empty hashes**\n\n    are represented as `{}`, without quotes\n\n- **null/undefined values**\n\n    are represented as _null_, without quotes (as opposed to\n    the string _\"null\"_, that has the quotes).\n\nExample:\n\n    $ cat sample.yaml\n    ---\n    'plain-value': ciao\n    'null-value': ~\n    'empty-array': []\n    'empty-hash': {}\n\n    $ teepee -Fcrumbr \u003csample.yaml\n    empty-array []\n    empty-hash {}\n    null-value null\n    plain-value \"ciao\"\n\nYou have probably noticed that this does not allow you to clearly\ndistinguish between hash/object keys and array indexes. Hopefully this\ndoes not concern you because you have a sane input data structure, but\nin case you want to remove any space for misunderstanding, you can use\n`exact_crumbr` instead:\n\n    $ teepee -Fexact_crumbr -i data.yml\n    {\"array\"}[0]:\"first\"\n    {\"array\"}[1]:\"second\"\n    {\"array\"}[2]:\"third\"\n    {\"array\"}[3]{\"k1\"}:\"v1\"\n    {\"array\"}[3]{\"k2\"}:\"v2\"\n    {\"hash\"}{\"complex key\"}:\"whatever\"\n    {\"hash\"}{\"five\"}[0]:\"a\"\n    {\"hash\"}{\"five\"}[1]:\"b\"\n    {\"hash\"}{\"five\"}[2]:\"see...\"\n    {\"hash\"}{\"one\"}:\"two\"\n    {\"hash\"}{\"three\"}:\"four\"\n    {\"key1\"}:\"value1\"\n    {\"key2\"}:\"value2\"\n\nIf you like, or need, to play with _JSON subsets_ instead, you might\nfind `json_crumbr` interesting:\n\n    $ teepee -Fjson_crumbr -i data.yml\n    {\"array\":[\"first\"]}\n    {\"array\":[\"second\"]}\n    {\"array\":[\"third\"]}\n    {\"array\":[{\"k1\":\"v1\"}]}\n    {\"array\":[{\"k2\":\"v2\"}]}\n    {\"hash\":{\"complex key\":\"whatever\"}}\n    {\"hash\":{\"five\":[\"a\"]}}\n    {\"hash\":{\"five\":[\"b\"]}}\n    {\"hash\":{\"five\":[\"see...\"]}}\n    {\"hash\":{\"one\":\"two\"}}\n    {\"hash\":{\"three\":\"four\"}}\n    {\"key1\":\"value1\"}\n    {\"key2\":\"value2\"}\n\nIn this case, each line is a valid JSON data structure with one single\nleaf value only.\n\n# OPTIONS\n\n- -A\n- --auto-key\n- --no-auto-key\n\n        -A\n        --auto-key\n        --no-auto-key\n\n    When set (first two options), every input is put into its own sub-value\n    inside the top-level hash. See [\"--auto-key-prefix\"](#auto-key-prefix),\n    [--auto-key-suffix](https://metacpan.org/pod/--auto-key-suffix) and [\"default-key\"](#default-key) for options related to\n    automatic keys generation.\n\n    Defaults to a false value, i.e. hashes will be merged together in the\n    top level hash, and only array/scalar values will get an automatically\n    generated key.\n\n- -P\n- --auto-key-prefix\n\n        -P ITEM-\n        --auto-key-prefix ITEM-\n\n    Prefix to be applied when auto-generating a key for inserting an input\n    into the top-level hash. This applies to input top-level arrays/scalars,\n    unless when `--auto-key` is set in which case it applies to all\n    top-level inputs.\n\n    Defaults to the single underscore character `_`.\n\n- -S\n- --auto-key-suffix\n\n        -S _mine\n        --auto-key-suffix _mine\n\n    Suffix to be applied when auto-generating a key for inserting an input\n    into the top-level hash. This applies to input top-level arrays/scalars,\n    unless when `--auto-key` is set in which case it applies to all\n    top-level inputs.\n\n    Defaults to the single underscore character `_`.\n\n- -b\n- --binmode\n\n        -b setting\n        --binmode setting\n\n    set the output encoding using the same rules as Perl's `binmode`\n    function. Defaults to `:encoding(UTF-8)`. When left empty, it is\n    considered equivalent to `:raw`.\n\n- -K\n- --default-key\n\n        -K mykey\n        --default-key mykey\n\n    Key associated to the last top-level input that needs key\n    auto-generation (depends on [\"--auto-key\"](#auto-key)).\n\n    Defaults to the single underscore character `_`.\n\n- -d\n- --define\n\n        -d key=value\n        --define key=value\n\n    add the definition of an element in the input data. The following\n    algorithm applies:\n\n    - input definition `key=value` is split at the first `=` sign found.\n    This means that the `key` cannot contain `=` signs, while the value\n    can;\n    - the `key` part is divided into sub-keys splitting using the `.` dot\n    character. This means that sub-keys cannot contain dots.\n    - each sub-key is used to traverse the input data, with auto-vivification\n    when necessary.\n    - sub-keys that are non-negative integers (i.e. either 0 or any positive\n    integer) are regarded as array indexes. Otherwise, the sub-key is\n    regarded as a hash key.\n    - the `value` part is assigned as the element _pointed_ by the last\n    sub-key.\n\n- -f\n- --format\n\n        -f \u003cyaml|yml|json|jsn\u003e\n        --format \u003cyaml|yml|json|jsn\u003e\n\n    set the (default) format for input data files. It can be one of `yml`,\n    `yaml`, `json` or `jsn` in whatever case. You can also set the format\n    in a fine-grained way using either [\"--json\"](#json) or [\"--yaml\"](#yaml) options.\n\n- -F\n- --function\n\n        -F spec\n        --function spec\n\n    set template to a function. This is equivalent to specifying:\n\n        -T '[%= spec %]'\n\n    except that it is more concise. You can of course put whatever in\n    `spec`, so you are not constrained on using a single function.\n\n    Currently available functions are:\n\n    - `base64`\n\n        encode the argument with RFC 2045 base64 algorithm, use it like this:\n\n            base64('text') # \"dGV4dA==\"\n\n    - `indent`\n\n        indent the argument, 4 blanks by default. Use it like this:\n\n            indent('whatever')  #  \"    whatever\"\n            indent('xxx', 7)    #  \"       xxx\"\n            indent('X', '  ')   #  \"  X\"\n\n    - `slurp`\n\n        read a whole file, optionally setting the encoding via `binmode` (defaults\n        to `:raw`, i.e. no reading tricks applied). Use it like this:\n\n            slurp('/path/to/filen.ame');\n\n    - `urlenc`\n\n        encode a string in a form suitable for inclusion in a URL. All characters\n        that are not in ` a-z A-Z 0-9 - ~ _ . ` are transformed into their\n        percent-encoded counterparts.\n\n    - `xmlenc`\n\n        encode a string in a form suitable for use as XML text. Characters\n        `\u003c \u003e \u0026 ' \"` are transformed (in numeric form).\n\n    - `xmltxt`\n\n        encode a string in a form suitable for use as XML text. Only characters\n        `\u003c \u0026` are transformed (in numeric form).\n\n    - `crumbr_as(type)`\n\n        where `type` can be `URI`, `Default` or `JSON`;\n\n    - `crumbr`\n\n        alias to `uri_crumbr`\n\n    - `uri_crumbr`\n\n        use crumbr with the `URI` alternative\n\n    - `exact_crumbr`\n\n        use crumbr with the _exact_ `Default` alternative\n\n    - `json_crumbr`\n\n        use crumbr with the `JSON` alternative\n\n    - `JSON`\n\n        dumps the input as pretty-printed JSON (so this is more readable)\n\n    - `YAML`\n\n        dumps the input as YAML (so this is more readable)\n\n    The functions above work, by default, on the overall input data, unless\n    indicated otherwise. You can pass an optional (additional) parameter with\n    the data structure you want it to work upon, e.g. if you just want to\n    pretty-print an item you can do this:\n\n        $ teepee -i input.json -F'YAML(V(\"some.inner.hash\"))'\n\n    Note that you can use `slurp`, `base64` and `indent` to read in any\n    file, encode it and possibly put it as content inside a YAML file. E.g.\n    you might do this to pass a generic file via cloud-init:\n\n        #cloud-config\n        write_files:\n        - encoding: base64\n          path: /etc/whatever\n          owner: root:root\n          permissions: '0644'\n          content: |\n        [%= indent(base64(slurp(V 'filename')), 5) %]\n\n- --help\n\n    print a somewhat more verbose help, showing usage, this description of\n    the options and some examples from the synopsis.\n\n- -I\n- --immediate\n\n        -I '{\"ciao\":\"a tutti\"}'\n        --immediate '{\"hey\":\"joe\"}'\n\n    immediate input, whose content is directly in the command line\n    parameter. Does auto-detection and complies with [\"--format\"](#format) as\n    [\"--input\"](#input).\n\n- -i\n- --input\n\n        -i filename\n        --input filename\n\n    an input file carrying data for expansion. This option can be set\n    multiple times, which will trigger (shallow) merging of the data\n    structures.\n\n    If set as `-`, standard input will be read.\n\n    Note: only allowed data structures are hashes at the top level.\n\n- -j\n- --jsn\n- --json\n\n        -j input.json\n        --jsn some.json\n        --json other.json\n\n    add an input file indicating that its format is JSON.\n\n- -J\n- --json-s\n\n        -J '{\"ciao\":\"a tutti\"}'\n        --json-s '{\"hey\":\"joe\"}'\n\n    immediate input, whose content is directly in the command line\n    parameter, read as JSON.\n\n    Note that the case of the lowercase option is uppercase.\n\n    This can come handy when you have read your data structure in a shell\n    variable, and don't want to do tricks with redirections.\n\n- -l\n- --lib\n- --include\n\n        -l lib\n        --lib /path/to/local/lib\n        --include /from/other/perl/lib\n\n    add a path to the array `@INC` where modules are looked for. This\n    actually applies only to items loaded via [\"-M\"](#m)/[\"--module\"](#module) below,\n    because the inclusion of the directories happens at runtime.\n\n- --man\n\n    print out the full documentation for the script.\n\n- -M\n- --module\n\n        -M Digest::MD5=md5_hex\n        --module 'Log::Log4perl::Tiny qw\u003c :easy \u003e'\n\n    import a module and its functions. The first flavor has a\n    specification where you can put `Module::Name=func1,func2,...`,\n    otherwise you can specify a line that will `eval`ed like\n    `use $your_line;`.\n\n- -n\n- --newline\n- --no-newline\n\n    the first two forms set `teepee` to always print a newline at the end.\n    This should make it easier to use in the command line, especially for\n    casually printing variables on the shell.\n\n    The last form is the negation, i.e. newline printing is disabled. This\n    can come handy when you set the environment variable [\"TEEPEE\\_NEWLINE\"](#teepee_newline)\n    to a non-false value, but you want to disable the newline printing in\n    one call.\n\n- -N\n- --no-input\n\n        -N\n        --no-input\n\n    boolean option to signal that there is no input at all. This is handy if\n    you just want to expand a template based on a few variables set directly\n    on the command line, for example:\n\n        # both \"n\" for newline and \"N\" for no-input, then multiple defines\n        $ teepee -nN -d a=b -d c=d -T '[% a %] -\u003e [% c %]'\n        b -\u003e d\n\n- -o \n- --output\n\n        -o filename\n        --output filename\n\n    set the output channel where data will be sent. By default it is set to\n    `-`, which means standard output.\n\n    Data will be printed assuming the channel is UTF-8 capable.\n\n- -t \n- --template\n\n        -t filename\n        --template filename\n\n    set the input template filename. The input file is assumed to be UTF-8\n    encoded.\n\n    Templates are assumed to be valid [Template::Perlish](https://metacpan.org/pod/Template::Perlish) template files,\n    see that module's documentation for additional help. The default opener\n    and closer are assumed.\n\n- -T \n- --text\n\n    set the template to expand directly on the command line.\n\n- --usage\n\n    print a concise usage line and exit.\n\n- -v string\n- --variable string\n\n        -v some.data.inside\n        --variable some.data.inside\n\n    expand a variable directly. This is equivalent to specifying:\n\n        -T '[% some.data.inside %]'\n\n    but more concise.\n\n- --version\n\n    print the version of the script.\n\n- -y\n- --yml\n- --yaml\n\n        -y input.yaml\n        --yml some.yaml\n        --yaml other.yaml\n\n    add an input file indicating that its format is YAML.\n\n- --yaml-1\n\n        --yaml-1 file-with-yaml-frontmatter.md\n\n    add an input file which has an initial header that is formatted in YAML.\n    This is useful for reading the _front matter_ from a Markdown file, if\n    present, like in the following example:\n\n        ---\n        title: My shiny post\n        type: post\n        date: 2022-05-06 07:00:00 +0200\n        ---\n\n        # Post title\n\n        This is a post about...\n\n- -Y\n- --yaml-s\n\n        -Y '\"ciao\": \"a tutti\"'\n        --yaml-s '\"hi\": \"there\"'\n\n    immediate input, whose content is provided directly in the command line\n    parameter, read as YAML.\n\n    Note that the case of the short option is uppercase.\n\n    This can come handy when you have read your data structure in a shell\n    variable, and don't want to do tricks with redirections.\n\n- --yaml-s1\n\n        --yaml-s1 \"$string_with_yaml_frontmatter\"\n\n    immediate input, whose content is provided directly in the command line\n    parameter, which starts with valid YAML.\n\n    This can be handy to parse the YAML _front matter_ from a string that\n    contains a whole Markdown document that contains one. See [\"--yaml-1\"](#yaml-1)\n    for an example.\n\n# DIAGNOSTICS\n\n- `output open('%s'): %s`\n\n    errors while opening the output channel, second placeholder carries the\n    error from the operating system.\n\n- `undefined input format`\n\n    auto-detection of input format failed. You can use option [\"--format\"](#format)\n    to specify the input format.\n\n- `cannot read input format %s`\n\n    the provided input format is not recognised, see [\"--format\"](#format) for the\n    allowed values.\n\n- `undefined filename`\n\n    the filename provided for input reading is not defined. This applies\n    both to data and template inputs.\n\n- `input open('%s'): %s`\n\n    errors while opening an input file, second placeholder carries the\n    error from the operating system.\n\n- `cannot infer format for file '%s'`\n\n    heuristic to infer the format of the file failed. You can specify the\n    format to be used using [\"--format\"](#format)\n\n# CONFIGURATION AND ENVIRONMENT\n\nteepee requires no configuration files.\n\nThe following environment variables are supported:\n\n- **TEEPEE\\_NEWLINE**\n\n    when set to a true value, it has the same effect of option\n    [\"--newline\"](#newline). Anyway, the command line always overrides the environment\n    variable, so if option [\"--no-newline\"](#no-newline) is set, the newline printig will\n    be disabled anyway.\n\n# DEPENDENCIES\n\n- [Data::Crumbr](https://metacpan.org/pod/Data::Crumbr) (and sons)\n- [JSON::PP](https://metacpan.org/pod/JSON::PP) (with [JSON::PP::Boolean](https://metacpan.org/pod/JSON::PP::Boolean))\n- [Mo](https://metacpan.org/pod/Mo) (with [Mo::default](https://metacpan.org/pod/Mo::default) and [Mo::coerce](https://metacpan.org/pod/Mo::coerce))\n- [Template::Perlish](https://metacpan.org/pod/Template::Perlish)\n- [YAML::Tiny](https://metacpan.org/pod/YAML::Tiny)\n\nThe bundled version contains all the needed modules, without\ndocumentation. The following licensing terms apply to the included\nmodules:\n\n- [Data::Crumbr](https://metacpan.org/pod/Data::Crumbr)\n\n    Copyright (C) 2015 by Flavio Poletti \u003cpolettix@cpan.org\u003e\n\n    This module is free software. You can redistribute it and/or modify it\n    under the terms of the Artistic License 2.0.\n\n    This program is distributed in the hope that it will be useful, but\n    without any warranty; without even the implied warranty of\n    merchantability or fitness for a particular purpose.\n\n- [JSON::PP](https://metacpan.org/pod/JSON::PP)\n\n    Copyright 2007-2014 by Makamaka Hannyaharamitu\n\n    This library is free software; you can redistribute it and/or modify it\n    under the same terms as Perl itself.\n\n- [Mo](https://metacpan.org/pod/Mo)\n\n    Copyright (c) 2011-2013. Ingy döt Net.\n\n    This program is free software; you can redistribute it and/or modify it\n    under the same terms as Perl itself.\n\n    See http://www.perl.com/perl/misc/Artistic.html\n\n- [Template::Perlish](https://metacpan.org/pod/Template::Perlish)\n\n    Copyright (c) 2008-2015 by Flavio Poletti polettix@cpan.org.\n\n    This module is free software. You can redistribute it and/or modify it\n    under the terms of the Artistic License 2.0.\n\n    This program is distributed in the hope that it will be useful, but\n    without any warranty; without even the implied warranty of\n    merchantability or fitness for a particular purpose.\n\n- [YAML::Tiny](https://metacpan.org/pod/YAML::Tiny)\n\n    Copyright 2006 - 2013 Adam Kennedy.\n\n    This program is free software; you can redistribute it and/or modify it\n    under the same terms as Perl itself.\n\n    The full text of the license can be found in the LICENSE file available\n    at https://metacpan.org/source/ETHER/YAML-Tiny-1.69/LICENSE.\n\n# BUGS AND LIMITATIONS\n\nNo bugs have been reported. Auto-detection of locale should probably\nextend to output encoding when printing to standard output, as opposed\nto assuming UTF-8 is fine.\n\nPlease report any bugs or feature requests through http://rt.cpan.org/\n\n# AUTHOR\n\nFlavio Poletti `polettix@cpan.org`\n\n# LICENCE AND COPYRIGHT\n\nCopyright (c) 2015, 2017 Flavio Poletti `polettix@cpan.org`.\n\nThis module is free software.  You can redistribute it and/or\nmodify it under the terms of the Artistic License 2.0.\n\nThis program is distributed in the hope that it will be useful,\nbut without any warranty; without even the implied warranty of\nmerchantability or fitness for a particular purpose.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpolettix%2Fteepee","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpolettix%2Fteepee","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpolettix%2Fteepee/lists"}