-
Notifications
You must be signed in to change notification settings - Fork 0
Templates and Aliases
The wire language has two ways to stop repeating yourself. Both are declared in the same request as the objects that use them, and both live for the life of the connection.
-
template— a named type with properties and children built in. -
alias— a short name for a property name.
Neither adds a runtime concept. A template expands at instantiation into the builtin type it is built on, so the display service ends up with exactly the objects you would have written by hand.
template FormRow=panel layout=hbox spacing=8
new FormRow children={ new label caption="Name:"; new textinput stretch=1 }
new FormRow children={ new label caption="Email:"; new textinput stretch=1 }
template Name=base props… declares it. The base is a builtin type, or
another template. Everything after the base is applied to each instance
before that instance's own properties.
template MyBtn=button align=right caption="Click Me" visible
new MyBtn caption="Other" !visible
The object receives align=right, caption="Click Me", visible, and then
caption="Other", !visible. Later wins, so the instance's caption and its
un-set of visible are what survive. This is ordinary property ordering, not
a special merge rule.
A template's base may be another template, to any depth:
template Plain=button caption="OK"
template Danger=Plain fg=bright_red
new Danger
Danger is a button with both properties. The chain is accumulated base-most
first, so the more specific template wins where they disagree. A cycle is
refused rather than followed.
template LabeledInput=panel layout=hbox children={
lbl=new label caption="?"
input=new textinput
}
Template children come first; an instance's children are appended to them, not substituted for them:
template LabeledInput=panel layout=hbox children={
lbl=new label caption="?"
input=new textinput
}
row=new LabeledInput children={ new label caption="extra" }
builds a panel with three children — the template's label, the template's text input, then the instance's label.
Keys written inside a template body are namespaced under the instance's key,
and you surface the ones you want with key=path:
template LabeledInput=panel layout=hbox children={
lbl=new label caption="?"
input=new textinput
}
row=new LabeledInput
field=row.input
cap=row.lbl
The reply carries row, field and cap — the panel, the text input, and
the label. Keys you do not surface stay internal to the instance and are not
returned, so a template can have as much private structure as it likes
without every instance handing back a pile of ids.
A property that indexes children has to come after them (see ListView). Within one statement that ordering is the author's to get right. A template applies its children before any instance's properties, so the ordering holds at every use:
template Sizes=listview children={
new item caption="Small"
new item caption="Medium"
new item caption="Large"
}
lv=new Sizes selected=2
selects the third row. The same ordering applies inside the template —
template Bad=listview selected=2 children={new item caption="A"; new item caption="B"}
— and that fails as silently as it does anywhere else, so keep a template's own arguments in order too.
alias C="caption" V="visible"
new button C="Aliased" !V
alias Name="target" is a lexical macro for a property name, and nothing
else. The target is a quoted string, and substitution happens where a
property name is expected.
An alias is not a value, a type, or an object. It cannot stand in for a
children block, a type name, or a property's value — which is what a
template is for.
Both obey the same rule: user-declared names begin with an uppercase letter, builtin type and property names are lowercase. That is what makes substitution unambiguous — a lowercase word is always the protocol's, an uppercase one is always yours.
The rule is enforced, and the errors say so:
| Written | Result |
|---|---|
template lowercase=button |
rejected — templates must begin uppercase |
alias c="caption" |
rejected — aliases must begin uppercase |
alias C=caption |
rejected — an alias target must be a quoted string |
new button X="boom" |
rejected — X is not a declared alias |
template Orphan=Missing |
rejected — unknown base template |
new Undeclared |
rejected — unknown template |
A correlation key does not apply to either verb: k=template … is an error,
because a declaration creates no object to correlate.
Templates and aliases belong to the connection, and last as long as it does. They are not global, so two applications — or two connections from one application — cannot collide on a name.
Declare them in the same request that uses them, or in an earlier one on the same connection; both work, since the session remembers.
Object Model — the new / set / destroy verbs ·
Properties and Values ·
Panel · ListView
KittyTK — image/tty Trinket Kit · MIT licensed · alpha, 0.1.x
Repository · Issues · Support on ko-fi
Sibling projects: PurfecTerm (terminal emulator) · mew (text editor) · PawScript (language)
Getting Started
Installation Building from Source Running a Display Host Your First Application Examples
Protocol
Protocol Overview Object Model Properties and Values Events Templates and Aliases Common Properties Introspection Transports and Security
Clients
Go Client Python Client C Client
Application Objects
Application · MenuBar · Window · MessageBox
Output Trinkets
Label · ProgressBar · StatusBar
Input Trinkets
TextInput · Editor · Terminal
Button · CheckBox · RadioButton
ListView · ComboBox · TreeView
Layout Trinkets
TabTrinket · Panel
ScrollArea · MDIPane
Separator · Spacer · Splitter
Other Trinkets
Layout Helpers