Skip to content

feat(builtins): add template command (non-standard, Mustache/Handlebars-lite) #569

@chaliy

Description

@chaliy

Summary

A non-standard builtin for lightweight template rendering. envsubst (#551) handles simple $VAR substitution, but real config generation needs conditionals, loops, and defaults. This fills the gap between envsubst and a full template engine.

Proposed Syntax

template [OPTIONS] [template-file] [< stdin]

Variables come from environment + shell variables. Additional vars via -v key=value.

Supported Template Syntax (Mustache-lite)

Syntax Description
{{VAR}} Variable substitution (HTML-safe by default)
{{{VAR}}} Raw substitution (no escaping)
{{VAR|default}} Default value if unset
{{#items}}...{{/items}} Section (loop over array or truthy check)
{{^items}}...{{/items}} Inverted section (render if falsy/empty)
{{! comment }} Comment (stripped from output)

Use Cases

# Simple config generation
export HOST=localhost PORT=8080
template < nginx.tmpl > nginx.conf

# With extra variables
template -v env=production -v replicas=3 < k8s.tmpl

# Inline template
echo 'Hello {{USER}}, you are in {{PWD}}' | template

# Conditional sections
cat <<'TMPL' | ENABLE_SSL=true template
server {
    listen {{PORT|80}};
    {{#ENABLE_SSL}}
    ssl_certificate /etc/ssl/cert.pem;
    {{/ENABLE_SSL}}
}
TMPL

# Loop over space-separated values
export SERVICES="web api worker"
cat <<'TMPL' | template
{{#SERVICES}}
- {{.}}
{{/SERVICES}}
TMPL

llm_hint()

Some("template: Mustache-lite templates. `echo '{{VAR|default}}' | template`. Supports sections {{#X}}...{{/X}}, defaults {{V|d}}, comments {{! }}.")

Implementation Notes

  • Variables sourced from interpreter env + shell variables
  • Arrays (space-separated strings) iterable via {{#VAR}}...{{/VAR}}
  • {{VAR|default}} syntax for defaults is critical — most templates need it
  • NOT Mustache-spec compliant (no partials, no lambdas) — intentionally simple
  • Exit 1 if template has syntax errors, 0 otherwise (undefined vars → empty string)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions