Skip to content

Commit db98725

Browse files
committed
Document UIDL, 1. step.
1 parent c3bb72f commit db98725

File tree

2 files changed

+258
-0
lines changed

2 files changed

+258
-0
lines changed

UIDL.md

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
# UIDL - User Interface Description Language
2+
3+
UIDL is a small and simple language for describing user interfaces.
4+
`fdialog` is the reference implementation.
5+
6+
The main element in UIDL is the command.
7+
A command is a keyword followed by a name, any number of attributes in parentheses and
8+
an optional block with more commands.
9+
So a typical command looks like this:
10+
11+
```uidl
12+
keyword name(attr1=123.456, attr2="value2", continue=false) {
13+
....
14+
}
15+
```
16+
17+
So the UIDL commands form a tree structure quite like HTML elements.
18+
As every command has to have a name, these names form a name path that can be
19+
used to reference a command anywhere in a UIDL file: `name1.name2.name3`
20+
21+
The attributes of a command can have the following data types:
22+
23+
| Data Type | Examples |
24+
|----------:|:---------------------------|
25+
| integer | `1`, `-3`, `+2` |
26+
| float | `-1.3`, `+3.8e4` `7E82` |
27+
| boolean | `true`, `false` |
28+
| string | `"ab\ncd"`, ` raw string ` |
29+
| list | `[123, "abc", true]` |
30+
31+
A UIDL list can contain a mix of different data types but lists of lists are not supported.
32+
33+
The full UIDL grammar with all exact definitions can be found in:
34+
[grammar/UIDL.g4](https://./grammar/UIDL.g4)
35+
36+
The optional string attributes `id` and `group` are allowed for any keyword.
37+
Each of them contains an identifier as value.
38+
`id` is a short cut for it's full name path and can be used for references.
39+
`group` marks the command as part of a group of commands.
40+
This is used for storing input data from the user together as a group and writing it
41+
all together to the output (as JSON object(s)).
42+
43+
The keyword decides together with the special string attribute `type` what the command is
44+
and what attributes are allowed.
45+
46+
## Predefined Commands
47+
48+
The following commands are currently defined:
49+
50+
### Keyword: `window`
51+
* Keyword: `window`
52+
* Type: n/a
53+
* Function: display a window with title bar
54+
* Children: optional, content of the window
55+
###### Attributes:
56+
* `title`: displayed in the title bar
57+
(optional, string type, minimum length: 1)
58+
* `width`: width of the window
59+
(optional, float type, minimum value: 50.0)
60+
* `height`: height of the window
61+
(optional, float type, minimum value: 80.0)
62+
* `appId`: (only main window) ID for loading preferences, etc.
63+
(optional, string type, minimum length: 1)
64+
* `exitCode`: (only main window) exit code of the app when it ends unexpectedly
65+
(optional, integer type, values: 0 to 125)
66+
67+
### Keyword: `link`
68+
* Keyword: `link`
69+
* Type: n/a
70+
* Function: link to another keyword in the UI description by using its full name path
71+
* Children: none
72+
###### Attributes:
73+
* `destination`: destination keyword of the link; can be nested with dots (e.g.: main.confirm.dismiss)
74+
(required, string type, minimum length: 1, regex: `^[\pL\pN_]+(?:[.][\pL\pN_]+)*$`)
75+
76+
### Keyword: `action`, Type: `exit`
77+
* Keyword: `action`
78+
* Type: `exit`
79+
* Function: ends the app and returns a exit code to the calling program
80+
* Children: none
81+
###### Attributes:
82+
* `code`: exit code of the app
83+
(optional, integer type, values: 0 to 125)
84+
85+
### Keyword: `action`, Type: `close`
86+
* Keyword: `action`
87+
* Type: `close`
88+
* Function: closes a dialog without doing anything else
89+
* Children: none
90+
###### Attributes:
91+
None.
92+
93+
### Keyword: `action`, Type: `group`
94+
* Keyword: `action`
95+
* Type: `group`
96+
* Function: executes a multiple child commands
97+
* Children: at least one command
98+
###### Attributes:
99+
None.
100+
101+
### Keyword: `action`, Type: `write`
102+
* Keyword: `action`
103+
* Type: `write`
104+
* Function: writes data (in JSON format) to standard output
105+
* Children: none
106+
###### Attributes:
107+
* `outputKey`: key of a single data value written
108+
(optional, string type, valid identifier)
109+
* `fullName`: full name path of the value to write
110+
(optional, string type, valid identifiers separated by dots (`.`))
111+
* `id`: ID of the value to write
112+
(optional, string type, valid identifier)
113+
* `group`: group of values to write
114+
(optional, string type, valid identifier)
115+
116+
All attributes are optional but either `group` or `outputKey` and one of
117+
`id` and `fullName` mut be given.
118+
119+
### Keyword: `form`
120+
* Keyword: `form`
121+
* Type: n/a
122+
* Function: display a form with submit and cancel buttons
123+
* Children: a `submit` child, a `cancel` child and at least one more child for the
124+
content of the form are required.
125+
###### Attributes:
126+
* `submitText`: text of the submit button
127+
(optional, string type, minimum length: 1)
128+
* `cancelText`: text of the cancel button
129+
(optional, string type, minimum length: 1)

grammar/UIDL.g4

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
grammar UIDL;
2+
3+
options {
4+
language=Go;
5+
}
6+
7+
@parser::header {
8+
import "strings"
9+
}
10+
11+
uidl
12+
: WhiteSpace? version commandSeparator commands WhiteSpace? EOF
13+
;
14+
15+
version
16+
: 'uidl' WhiteSpace Natural
17+
;
18+
19+
commands
20+
: command (commandSeparator command)* commandSeparator?
21+
;
22+
23+
command
24+
: Identifier WhiteSpace Identifier WhiteSpace? attributes WhiteSpace? commandBody?
25+
;
26+
27+
commandSeparator
28+
: Semicolon
29+
| ws=WhiteSpace {strings.ContainsRune($ws.text, '\n')}?<fail='expected semicolon or new line'>
30+
;
31+
32+
commandBody
33+
: '{' WhiteSpace? commands '}'
34+
;
35+
36+
attributes
37+
: '(' WhiteSpace? (attribute (Comma attribute)* Comma? )? ')'
38+
;
39+
40+
attribute
41+
: Identifier WhiteSpace? '=' WhiteSpace? value WhiteSpace?
42+
;
43+
44+
value
45+
: simpleValue
46+
| listValue
47+
;
48+
49+
listValue
50+
: '[' WhiteSpace? (simpleValue (Comma simpleValue)* Comma? )? ']'
51+
;
52+
53+
simpleValue
54+
: DoubleQuotedString
55+
| BackQuotedString
56+
| Float
57+
| (Natural | Int)
58+
| Bool
59+
;
60+
61+
Bool
62+
: ('true' | 'false')
63+
;
64+
65+
DoubleQuotedString
66+
: '"' (EscapedChar | SafeCodepoint)* '"'
67+
;
68+
69+
BackQuotedString
70+
: '`' ~[`]* '`'
71+
;
72+
73+
fragment EscapedChar
74+
: '\\' (["\\bfnrt] | UnicodeChar)
75+
;
76+
77+
fragment UnicodeChar
78+
: 'u' HexDigit HexDigit HexDigit HexDigit
79+
;
80+
81+
fragment HexDigit
82+
: [0-9a-fA-F]
83+
;
84+
85+
fragment SafeCodepoint
86+
: ~["\\\u0000-\u001F]
87+
;
88+
89+
Identifier
90+
: [\p{Alpha}_] [\p{Alnum}_]*
91+
;
92+
93+
Natural
94+
// integer part forbids leading 0s (e.g. `01`)
95+
: [1-9] [0-9]*
96+
;
97+
98+
Float
99+
: Int '.' [0-9]+ Exponent?
100+
;
101+
102+
Int
103+
: ('+' | '-')? ('0' | Natural)
104+
;
105+
106+
fragment Exponent
107+
// exponent number permits leading 0s (e.g. `1e01`)
108+
: [Ee] [+-]? [0-9]+
109+
;
110+
111+
Semicolon
112+
: WhiteSpace? ';' WhiteSpace?
113+
;
114+
115+
Comma
116+
: WhiteSpace? ',' WhiteSpace?
117+
;
118+
119+
WhiteSpace
120+
: (Space | Comment)+
121+
;
122+
123+
fragment Space
124+
: [\p{White_Space}]+
125+
;
126+
127+
fragment Comment
128+
: '#' ~[\n]* ('\n' | EOF)
129+
;

0 commit comments

Comments
 (0)