19. Complete examples
Contents of ATD 0.1
(informative)
Beside this document, each a complete description that checks without findings:
| File | Shows |
|---|---|
mindmap.atd, mindmap.notation.atd |
a diagram split over a root and a part, with script functions, constraints, operations, a capability and an xml binding |
reading-list.atd |
a designer with a table surface and a yaml binding |
notes.atd |
an editor with a text surface and a bullets binding |
binding-json.atd, binding-lines.atd, binding-blocks.atd |
a binding of the json, lines and blocks families |
binding-grammar.atd |
a binding of the grammar family, for Turtle, with its grammar inline (section 11.9) |
binding-capability.atd |
a binding whose family is a capability |
And the worked examples of section 2: fixtures/mindmap/basic/, mindmap.trace.json with mindmap.md, and capabilities/*/contract.json.
The tool descriptions under definitions/ are examples too, and atd-grammar.py --probe reads them with those beside this document: definitions/designers/hierarchical-requirement.atd, with its part hierarchical-requirement.markdown.atd, is a designer with a hierarchy surface, the widths of its columns, move with a place, binding types the type map maps as the document and as unreadable, and rule names with hyphens. The five editors under definitions/editors/ (plain-text.atd, markdown.atd, json.atd, xml.atd, yaml.atd) are editors with a text surface: files, token classes, checks and completion from sources the editor names, an outline of a model read by a capability, and a preview.
Three of them follow in full, the shortest of each kind that shows a binding. Each is a copy of the file beside this document. The guide for tool engineers explains how such a file is written, step by step, with the mind map, the Hierarchical Requirement Designer and the Markdown editor.
A diagram, binding-lines.atd:
atd 0.1
/// Variables and the links between them, one statement per line: the `lines` family, as the causal loop diagram's
/// `.cld` files are read (FBL's `causal-loop-diagram.fbl`, trimmed).
diagram example/influence version "0.1.0" {
label "Influence diagram"
model {
element Variable {
attribute name: string required
attribute label: string
labelAttribute: name
}
element Link {
attribute from: Variable required
attribute to: Variable required
}
relation Influence from Variable to Variable {
derived: (diagram.nodes.filter(n, n.type == "Link").map(l, {'source': l.from, 'target': l.to}))
}
}
notation {
node Variable { shape ellipse label @name }
edge Influence { line { routing: bezier } marker target arrow }
}
binding cld family lines {
label "Influence diagram"
claims files "*.cld"
text { newline: crlf, finalNewline: true }
comment: r"^\s*#"
unmatched: report
element Variable as variable line r"^\s*variable\s+(?<name>[^\s]+)(?:\s+(?<label>\x22[^\x22]*\x22))?\s*$" {
attribute name from group "name" { empty: refuse }
attribute label from group "label" { empty: remove }
insert { place: after-last, emit: "variable {name}[ \"{label}\"]" }
remove { cascade: [link] }
}
element Link as link line r"^\s*link\s+(?<from>[^\s]+)\s+->\s+(?<to>[^\s]+)\s*$" {
attribute from from group "from" { references variable by name }
attribute to from group "to" { references variable by name }
insert { place: after-last, emit: "link {from} -> {to}" }
remove {}
}
}
}
A designer, reading-list.atd:
atd 0.1
/// A reading list, one row per book, with text and number fields and one view: DESL's smallest example
/// (`minimal-table.des` and `minimal-table.fbl`) as a designer in ATD.
designer example/reading-list version "0.1.0" {
label "Reading list"
model {
element Field {
attribute name: string required
attribute valueType: ValueType required
labelAttribute: name
}
element View {
attribute name: string required
labelAttribute: name
}
element Book {
contains Value ordered
contains Value as values
}
element Value {
attribute field: Field required
attribute text: text
attribute number: number
}
enum ValueType {
text { label: "Text" }
number { label: "Number" }
}
}
persistence {
ids: { strategy: "uuid-v4", encoding: base36, types: { Value: { strategy: derived, expression: (self.parent.id + "/" + self.field.id) } } }
}
constraint uniqueFieldNames for Field {
rule document.elementsOfType("Field").filter(f, f.name == self.name).size() == 1
severity error
message "Two fields have this name."
code: "reading-list.duplicate-field-name"
}
surface table {
columns Field { name: name, valueType: valueType }
rows Book
cells Value { column: field }
views View { name: name }
valueType text "Text" {
key: text
editor: text
comparisons: [is, contains]
sort: text
convert number parse
}
valueType number "Number" {
key: number
editor: number
comparisons: [equals, greater-than, less-than]
sort: number
convert text written-form
}
}
operation addBook "New book" for document {
create Book
}
binding yaml family yaml {
label "Reading list"
claims { extensions: [".yaml", ".yml"], shared: true, marker: { rootKey: designer, value: "example/reading-list" }, origins: ["example/reading-list"] }
text { newline: lf, indent: 2 }
header { key: ded, value: "0.1", required: true }
element Field as field at "/fields/*" {
id from key "id"
attribute name from key "name" { empty: refuse }
attribute valueType from key "type" { empty: refuse }
insert { place: after-last, container: "/fields", keys: [id, name, type] }
remove { cascade: [value] }
}
element View as view at "/views/*" {
id from key "id"
attribute name from key "name" { empty: refuse }
insert { place: after-last, container: "/views", keys: [id, name] }
remove {}
}
element Book as book at "/books/*" {
id from key "id"
insert { place: after-last, container: "/books", create: { at: { under: "/" } }, keys: [id] }
remove {}
}
element Value as value at "/books/*/values/*" {
parent book slot values
attribute field from key "field" {
empty: refuse
references field by id
}
attribute text from key "text" { empty: remove }
attribute number from key "number" { empty: remove, number: shortest }
insert { place: after-last, container: "values", create: { at: { after: id } }, keys: [field, text, number] }
remove { container: remove-when-empty }
}
registration { createOnFirstPlacement: false }
template """ded: "0.1"
designer: example/reading-list
fields:
- id: {newid:field}
name: Title
type: text
views:
- id: {newid:view}
name: All books
"""
}
}
An editor, notes.atd:
atd 0.1
/// Notes kept as a Markdown list: an editor whose text is the document, with an outline of the notes, folding by
/// note, a preview, and a `bullets` binding that reads the notes under the heading `Notes` as a tree.
editor example/notes version "0.1.0" {
label "Notes"
requires capability render.markdown@^1
model {
element Note {
attribute title: string required
attribute done: bool default false
attribute detail: text
contains Note ordered
labelAttribute: title
}
}
constraint titled for Note {
rule self.title.trim() != ""
severity warning
message "A note needs a title."
code: "notes.untitled"
}
surface text {
files "*.notes.md"
tokens markdown
outline Note by title
fold Note
preview capability render.markdown { side: right }
fix closeNote "Mark as done" {
when !self.done
set self.done = true
}
}
binding notes family bullets {
label "Notes"
claims files "*.notes.md"
header { line: r"^# ", required: false }
section notes "Notes" { caseInsensitive: true }
element Note as note line r"^\[(?<done>[ x])\] (?<title>.+)$" {
within notes
parent note
attribute title from group "title" { empty: refuse }
attribute done from group "done" { map: { "x": "true", " ": "false" } }
attribute detail from continuation
insert { place: after-last, emit: "- \\[{done}\\] {title}" }
remove {}
}
}
}
walk/walk.json ($defs/Walk) is the walk of 30 edits and requests over the examples that every language server meets alike (SC-005): completion in a binding rule's attribute position, a rename across a description's files, typing on after a syntax error, formatting twice, and a description with a part.
refused/ holds descriptions a checker refuses, each with the findings it must give (refused/README.md). atd check --corpus refused compares every one of them with its findings.
An agent writing a description is given grammar/atd.flat.lark, with which a model service constrains its output, two examples, and the findings of atd check --json, which it reads as data. Section 10 of the guide says how.