Skip to content

Commit bb06038

Browse files
committed
document functions, break template docs into smaller parts
1 parent b1e3355 commit bb06038

File tree

8 files changed

+325
-106
lines changed

8 files changed

+325
-106
lines changed

src/SUMMARY.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@
33
- [Introduction](./introduction.md)
44
- [Getting started](./getting-started.md)
55
- [Components](./components.md)
6-
%% - [User model](./templates/usermodel.md)
7-
%% - [Data Context](./templates/data-ctx.md)
86
- [State](./components/state.md)
97
- [Event handling](./components/events.md)
108
- [Messaging](./components/messages.md)
@@ -13,6 +11,11 @@
1311
- [Runtime](./runtime.md)
1412
- [Backend](./backend.md)
1513
- [Templates](./templates.md)
14+
- [Loops](./templates/loops.md)
15+
- [If / Else](./templates/if-else.md)
16+
- [Switch / Case](./templates/switch-case.md)
17+
- [Functions](./templates/functions.md)
18+
- [Custom functions](./templates/functions/custom.md)
1619
- [Elements](./templates/elements.md)
1720
- [text](./templates/elements/text.md)
1821
- [span](./templates/elements/span.md)

src/introduction.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ By separating the layout from the rest of the application, reducing the amount o
1111
code needed to express your design, and featuring hot reloading it becomes incredibly fast
1212
to iterate over the design.
1313

14+
Do note that AML is a markup language with some basic control flow and is not a
15+
reactive programming language.
16+
1417
## Why
1518

1619
* Templates can be shipped with the application, giving the end user the ability

src/templates.md

Lines changed: 34 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ Anathema has a template language to describe user interfaces.
44
This makes it possible to ship the template(s) together with the compiled binary so the
55
application can be customised without having to be recompiled.
66

7+
Do note that AML (Anathema Markup Language) is **not** a programming language,
8+
therefore control flow is limited.
9+
710
The element syntax looks as follows: `<element> <attributes> <value>`
811

912
```
@@ -81,128 +84,55 @@ border
8184
text "look, a border"
8285
```
8386

84-
## Loops
85-
86-
It's possible to loop over the elements of a collection.
87-
The syntax for loops are `for <element> in <collection>`.
88-
89-
Example: looping over static values
90-
```
91-
for value in [1, 2, "hello", 3]
92-
text value
93-
```
87+
* [Loops](./templates/loops.md)
88+
* [If / Else](./templates/if-else.md)
89+
* [Switch / Case](./templates/switch-case.md)
9490

95-
Elements generated by the loop can be thought of as belonging to the parent
96-
element as the loop it self is not a element.
97-
See example below.
9891

99-
Example: mixing loops and elements
100-
```
101-
vstack
102-
text "start"
103-
for val in [1, 2, 3]
104-
text "some value: " val "."
105-
text "end"
106-
```
107-
The above example would render:
108-
```
109-
start
110-
some value: 1.
111-
some value: 2.
112-
some value: 3.
113-
end
114-
```
92+
## Either
11593

116-
For-loops also expose a `loop` variable that is set to the current loop iteration.
94+
The `?` symbol can be used to have a fallback value.
11795

118-
Example: `loop` variable
11996
```
120-
vstack
121-
for val in ["a", "b", "c", "d"]
122-
text "#" loop ": " val
123-
```
124-
The above example would render:
125-
```
126-
#0: a
127-
#1: b
128-
#2: c
129-
#3: d
97+
text state.maybe_value ? attributes.maybe_this ? "there was no value"
13098
```
13199

132-
Note: For-loops do not work inside attributes, and can only produce
133-
elements.
100+
## Constants / Globals
134101

135-
## If / Else
102+
Constants are global and regardless of where in a template they are declared
103+
they will be hoisted to the top.
136104

137-
It's possible to use `if` and `else` to determine what to layout.
105+
### Example
138106

139-
Example:
140-
```
141-
if true
142-
text "It's true!"
143-
144-
if value > 10
145-
text "Larger than ten"
146-
else if value > 5
147-
text "Larger than five but less than ten"
148-
else
149-
text "It's a small value..."
107+
The following example will print `1`
150108
```
109+
text glob
151110
152-
### Conditional theming
153-
154-
Changing colors and style depending on a condition can be achieved by declaring
155-
a constant. All constants are global.
156-
111+
let glob = 1
157112
```
158-
let THEME = {
159-
enabled: { bg: "grey" },
160-
disabled: { bg: "reset" },
161-
}
162113

163-
text [background: THEME["disabled"].bg] "Hello, tea"
114+
The following example will print `1` then `2`, as the `inner` component will override the
115+
outer components global.
164116
```
117+
// main.aml
118+
let glob = 1
119+
vstack
120+
text glob
121+
@inner
165122
166-
Since boolean values can translate to numbers it's also possible to use
167-
them as index lookups.
168-
123+
// inner.aml
124+
let glob = 2
125+
text glob
169126
```
170-
let THEME = [
171-
// False
172-
{ bg: "grey" },
173-
// True
174-
{ bg: "reset" },
175-
]
176127

177-
text [background: THEME[state.some_bool].bg] "Hello, tea"
128+
The following example will print `2`, as the `inner` component will override the
129+
outer components global.
178130
```
131+
// main.aml
132+
let glob = glob
133+
@inner
179134
180-
### Operators
181-
182-
* Equality `==`
183-
* Greater than `>`
184-
* Greater than or equals `>=`
185-
* Less than `<`
186-
* Less than or equals `<=`
187-
* And `&&`
188-
* Or `||`
189-
* Addition `+`
190-
* Subtraction `-`
191-
* Multiplication `*`
192-
* Division `/`
193-
* Remainder (Modulo) `%`
194-
* Negation `!`
195-
* Either `?` (Uses the right value if the left value does not exist)
196-
197-
Note: just like for-loops it's not possible to use if / else with attributes.
198-
199-
To determine the value of an attribute depending on some condition this should
200-
be handled by the state.
201-
202-
## Either
203-
204-
The `?` symbol can be used to have a fallback value.
205-
206-
```
207-
text state.maybe_value ? attributes.maybe_this ? "there was no value"
135+
// inner.aml
136+
let glob = 2
137+
text glob
208138
```

src/templates/functions.md

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
# Functions
2+
3+
AML have a few functions built-in and it's possible to add custom functions.
4+
5+
A function can either be called as a member function: `"string".to_upper()` or a
6+
free function: `to_upper("string")`
7+
8+
Do note that calling a function as a member function on a collection
9+
10+
## `to_upper(string)`
11+
12+
Convert a string to upper case.
13+
14+
### Example
15+
16+
```
17+
text "It's teatime".to_upper()
18+
```
19+
20+
Will output: "IT'S TEATIME".
21+
22+
## `to_lower(string)`
23+
24+
Convert a string to lower case.
25+
26+
### Example
27+
28+
```
29+
text "It's teatime".to_lower()
30+
```
31+
32+
Will output: "it's teatime".
33+
34+
## `to_str(arg)`
35+
36+
Convert any value to a string representation.
37+
38+
### Example
39+
40+
```
41+
let greetings = {
42+
"1": "Hello",
43+
"2": "Hi",
44+
}
45+
46+
text greetings[to_str(2)]
47+
```
48+
49+
Will output: "Hi".
50+
51+
## `to_int(arg)`
52+
53+
Try to convert any value to an integer.
54+
55+
Boolean `true` will convert to `1`, and `false` will convert to `0`.
56+
57+
Floating point values will be truncated.
58+
`to_int(1.99999)` will be converted to `1`.
59+
60+
### Example
61+
62+
```
63+
let greetings = [
64+
"Hello",
65+
"Hi",
66+
]
67+
68+
text greetings[to_int(true)]
69+
```
70+
71+
Will output: "Hi".
72+
73+
## `round(number, decimal_count=0)`
74+
75+
Round a floating point value.
76+
Trying to round any other type will return null.
77+
78+
If no `decimal_count` is provided `0` is the default.
79+
80+
### Example
81+
82+
```
83+
vstack
84+
text round(1.1234, 2)
85+
text round(1.1234)
86+
```
87+
88+
Will output:
89+
```
90+
1.12
91+
1
92+
```
93+
94+
This function will pad with zeroes:
95+
```
96+
text round(1.12, 5)
97+
```
98+
99+
Will output: `1.12000`
100+
101+
## `contains(haystack, needle)`
102+
103+
Returns true if the haystack contains the needle.
104+
105+
### Example
106+
107+
```
108+
vstack
109+
text contains([1, 2, 3], 2)
110+
text "hello world".contains("lo")
111+
```
112+
113+
Will output:
114+
```
115+
true
116+
true
117+
```

src/templates/functions/custom.md

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# Adding custom functions
2+
3+
It's possible to add custom functions to the runtime.
4+
5+
All function have the same signature in Rust:
6+
7+
```rust, ignore
8+
fn contains<'a>(args: &[ValueKind<'a>]) -> ValueKind<'a> {
9+
...
10+
}
11+
```
12+
13+
## Example
14+
15+
A function that adds two values
16+
17+
```rust, ignore
18+
use anathema::resolver::ValueKind;
19+
20+
fn add<'a>(args: &[ValueKind<'a>]) -> ValueKind<'a> {
21+
if args.len() != 2 {
22+
return ValueKind::Null;
23+
}
24+
25+
let args = args[0].to_int().zip(args[1].to_int());
26+
match args {
27+
Some((lhs, rhs)) => ValueKind::Int(lhs + rhs),
28+
None => ValueKind::Null
29+
}
30+
}
31+
```
32+
33+
## Adding the function to the runtime
34+
35+
Use the `register_function` method on the runtime to add your custom function.
36+
37+
It is not possible to overwrite existing functions, and trying to do so will
38+
return an error.
39+
40+
### Example
41+
42+
```rust,ignore
43+
builder.register_function("add", add).unwrap();
44+
```
45+
In the template:
46+
```
47+
text add(1, 2)
48+
```

0 commit comments

Comments
 (0)