Getting Started¶
The smallest working document¶
A document is a part def specializing DocumentQueries::Document with a
literal title and content blocks as nested parts. This is the whole of the
smallest one:
package Hello {
private import DocumentQueries::*;
private import ScalarValues::*;
part def HelloReport :> Document {
attribute redefines title = "Hello, Documents";
part greeting : Paragraph {
attribute redefines text = "This document was generated from a SysML v2 model.";
}
}
}
Save it as hello.sysml and render it:
$ sysml hello.sysml -render-document Hello::HelloReport
✓ package Hello
# Hello, Documents
This document was generated from a SysML v2 model.
The status line goes to stderr; the Markdown goes to stdout, or to a file with
-o hello.md.
Three things to note:
DocumentQueriesis bundled with the binary — no extra files to import.titleis required and must be a literal string; a document without one is a planning error, not an empty heading.- Content renders in declaration order.
Adding model data¶
A document earns its keep when its content comes from the model. That takes a
query — a calc def specializing DocumentQueries::Query — and a block
that invokes it:
package Hello {
private import DocumentQueries::*;
private import KerML::Root::Element;
private import ScalarValues::*;
part rover {
part chassis;
part arm;
part mast;
}
calc def PartNames :> Query {
in root : Element;
Project(
source = OrderBy(
source = OwnedElements(source = root),
property = "name",
direction = "ascending",
missing = "last",
multiple = "error"
),
properties = ("name")
)
}
part def RoverReport :> Document {
attribute redefines title = "Rover Parts";
part intro : Paragraph {
attribute redefines text = "The rover's top-level parts, from the model:";
}
part partsTable : Table {
attribute redefines caption = "Top-level parts";
calc rows : PartNames {
in root = rover;
}
}
}
}
The query reads inside-out: OwnedElements collects rover's children,
OrderBy sorts them by name, and Project turns each element into a row with
one name column. The in root : Element; parameter makes the query
reusable; the table's calc rows : PartNames { in root = rover; } binds it to
a concrete element.
$ sysml rover.sysml -render-document Hello::RoverReport
✓ package Hello
# Rover Parts
The rover's top-level parts, from the model:
*Top-level parts*
| name |
| --- |
| arm |
| chassis |
| mast |
Add a part to rover and rerun — the table updates. That is the entire
workflow.
Running a query on its own¶
While writing a query it is faster to run it directly than to render a
document around it. -run-query takes the query's qualified name and its
bindings:
$ sysml rover.sysml -run-query "Hello::PartNames root=Hello::rover"
✓ package Hello
✓ Query Hello::PartNames returned 3 rows
Columns: name
Row 1: Hello::rover::arm
name = "arm"
...
The same commands exist in the REPL as %render-document and %run-query,
over gRPC, and in the VS Code extension — see Interfaces.
Where to go from here¶
- The query cookbook covers every query operation with a runnable recipe.
- Document authoring covers every content block, including inline runs, cross-references, grouped tables and diagrams.
- The worked example puts it all together in one report.