Different variable syntaxes

Currently Wharf’s variable syntax looks like this: ${myVariable}, and is escaped like this: ${%myVariable%}

This is a weird syntax, and except the escaping part, it actually collides too heavily with variable syntaxes from other systems such as bash, PowerShell, Dockerfile, et.al.

Inspiration

Here’s some different syntaxes that can be found out in the wild:

Used inUsageEscaped
Bash, PowerShell, Dockerfile, CircleCI env var$myVariable\$myVariable
Bash, PowerShell, Dockerfile env var${myVariable}\${myVariable}
Batch (.bat)%myVariable%%%myVariable%%
CircleCI parameter<<parameters.myVariable>>unknown
Mustache templates (ex: Helm){{myVariable}}{{`{{myVariable}}`}}
A.P. value expr1$(myVariable)unknown
A.P. runtime expr1$[myVariable]unknown
A.P. compile-time expr1, GitHub Actions${{parameters.myVariable}}unknown
XML/HTML<!--myVariable-->&lt;!--myVariable--&gt;

CircleCI boolean parameters

If a parameter is of type boolean in CircleCI, then you can have a slighly varied syntax that can omit some text based on that boolean value.2

<<# myBoolVar >>conditionally outputted<</ myBoolVar >>

Example:

inputs:
  - name: forcePush
    type: boolean
    default: false

myStage:
  myStep:
    container:
      image: ubuntu:20.04
      cmds:
        - git push <<# forcePush >>--force<</ forcePush >>

Other ideas

UsageEscaped
#{myVariable}
{|myVariable|}
<|myVariable|>
#:myVariable:#
@@myVariable@@
::myVariable::

The winning qualities of a good variable substitution syntax is:

  • low collision with already used syntaxes (counterexample: ${myVariable})

  • easy to see (counterexample: __myVariable__)

  • easy to write (counterexample: $*^myVariable^*$)

  • small overhead (counterexample: $$WHARF-VAR-BEGIN: myVariable :WHARF-VAR-END$$)

  • usable in YAML, i.e. YAML should not try to parse it as anything else than a string (counterexample: {myVariable})

    • starting with { could be interpreted as map
    • starting with [ could be interpreted as sequence
    • starting with % could be interpreted as YAML/tag directive (ex: %YAML 1.3)
    • starting with ? could be interpreted as map key (ex: ? key)
    • starting with : could be interpreted as map value (ex: : value)
    • including # could be interpreted as a comment
    • including : could be interpreted as property key-value (ex: key: value)
    • including ! could be interpreted as tags (ex: !yaml!str)
    • including & could be interpreted as anchor definition (ex: &A)
    • including * could be interpreted as anchor reference (ex: *A)