Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
/.vscode
/target

# rendered code fragments
/*.pdf
# rendering artifacts
*.pdf
.*.typ

# documentation symlinks
/doc/references
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "technique"
version = "0.5.1"
version = "0.5.2"
edition = "2021"
description = "A domain specific language for procedures."
authors = [ "Andrew Cowie" ]
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ The _technique_ program has three subcommands:
syntax highlighting if run in a terminal.

- _render_ \
Render the Technique document into a printable PDF. This use the Typst
Render the Technique document into a printable PDF. This uses the Typst
typestting language and so requires the _typst_ compiler be installed and on
`PATH`.

Expand Down
4 changes: 2 additions & 2 deletions examples/prototype/GovernmentForm.tq
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ drivers_license_application :
{
[
"Name" = "Kowalski"
"Species" = "Emperor Pengin"
"Species" = "Emperor Penguin"
"Age" = 4.2 winters
"Unique Pengiun Identifier" = uuid()
"Unique Penguin Identifier" = uuid()
"Occupation" = "Operational Planning Specialist"
"Permanent Address" = "Central Park Zoo, New York, NY, 10021, United States"
]
Expand Down
4 changes: 2 additions & 2 deletions src/domain/checklist/adapter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
//! role assignments are inherited by sub steps, and SectionChunks are
//! rendered as headings with their sub-procedures' steps as children.

use crate::language;
use crate::domain::Adapter;
use crate::language;

use super::types::{Document, Response, Section, Step};

Expand Down Expand Up @@ -209,8 +209,8 @@ fn step_from_scope(scope: &language::Scope, inherited_role: Option<&str>) -> Ste
mod check {
use std::path::Path;

use crate::parsing;
use crate::domain::Adapter;
use crate::parsing;

use super::ChecklistAdapter;

Expand Down
1 change: 1 addition & 0 deletions src/domain/checklist/mod.rs
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
pub mod adapter;
pub mod types;
mod typst;
42 changes: 0 additions & 42 deletions src/domain/checklist/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@
//! A checklist is moderately structured and relatively flat: sections with
//! headings, steps with checkboxes, response options, and limited nesting.

use crate::domain::typst::{Data, Render};

/// A checklist is a document of sections containing steps.
pub struct Document {
pub sections: Vec<Section>,
Expand All @@ -18,31 +16,13 @@ impl Document {
}
}

impl Render for Document {
fn render(&self, data: &mut Data) {
data.open();
data.list("sections", &self.sections);
data.close();
}
}

/// A section within a checklist.
pub struct Section {
pub ordinal: Option<String>,
pub heading: Option<String>,
pub steps: Vec<Step>,
}

impl Render for Section {
fn render(&self, data: &mut Data) {
data.open();
data.field("ordinal", &self.ordinal);
data.field("heading", &self.heading);
data.list("steps", &self.steps);
data.close();
}
}

/// A step within a checklist section.
pub struct Step {
#[allow(dead_code)]
Expand All @@ -55,30 +35,8 @@ pub struct Step {
pub children: Vec<Step>,
}

impl Render for Step {
fn render(&self, data: &mut Data) {
data.open();
data.field("ordinal", &self.ordinal);
data.field("title", &self.title);
data.list("body", &self.body);
data.field("role", &self.role);
data.list("responses", &self.responses);
data.list("children", &self.children);
data.close();
}
}

/// A response option with an optional condition.
pub struct Response {
pub value: String,
pub condition: Option<String>,
}

impl Render for Response {
fn render(&self, data: &mut Data) {
data.open();
data.field("value", &self.value);
data.field("condition", &self.condition);
data.close();
}
}
72 changes: 72 additions & 0 deletions src/domain/checklist/typst.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
//! Typst serialization for checklist domain types.

use crate::domain::serialize::{Markup, Render};

use super::types::{Document, Response, Section, Step};

impl Render for Document {
fn render(&self, out: &mut Markup) {
for section in &self.sections {
section.render(out);
}
}
}

impl Render for Section {
fn render(&self, out: &mut Markup) {
out.call("render-section");
out.param_opt("ordinal", &self.ordinal);
out.param_opt("heading", &self.heading);
if !self
.steps
.is_empty()
{
out.content_open("children");
for step in &self.steps {
step.render(out);
}
out.content_close();
}
out.close();
}
}

impl Render for Step {
fn render(&self, out: &mut Markup) {
out.call("render-step");
out.param_opt("ordinal", &self.ordinal);
out.param_opt("title", &self.title);
out.param_list("body", &self.body);
out.param_opt("role", &self.role);
if !self
.responses
.is_empty()
{
out.content_open("responses");
for r in &self.responses {
r.render(out);
}
out.content_close();
}
if !self
.children
.is_empty()
{
out.content_open("children");
for child in &self.children {
child.render(out);
}
out.content_close();
}
out.close();
}
}

impl Render for Response {
fn render(&self, out: &mut Markup) {
out.call("render-response");
out.param("value", &self.value);
out.param_opt("condition", &self.condition);
out.close();
}
}
2 changes: 1 addition & 1 deletion src/domain/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ mod adapter;
pub mod checklist;
pub mod engine;
pub mod procedure;
pub(crate) mod serialize;
pub mod source;
pub mod typst;

pub use adapter::Adapter;
4 changes: 2 additions & 2 deletions src/domain/procedure/adapter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
//! any SectionChunks within) become the body. Remaining top-level procedures
//! are appended as Procedure nodes.

use crate::language;
use crate::domain::Adapter;
use crate::language;

use super::types::{Document, Node, Response};

Expand Down Expand Up @@ -192,8 +192,8 @@ fn node_from_step(scope: &language::Scope) -> Node {
mod check {
use std::path::Path;

use crate::parsing;
use crate::domain::Adapter;
use crate::parsing;

use super::super::types::Node;
use super::ProcedureAdapter;
Expand Down
1 change: 1 addition & 0 deletions src/domain/procedure/mod.rs
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
pub mod adapter;
pub mod types;
mod typst;
73 changes: 0 additions & 73 deletions src/domain/procedure/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@
//! source Technique document. Sections, procedures, steps, role groups —
//! whatever the author wrote, the domain model preserves.

use crate::domain::typst::{Data, Render};

/// A procedure document: title and description from the first procedure,
/// then a tree of nodes representing the body.
pub struct Document {
Expand All @@ -24,16 +22,6 @@ impl Document {
}
}

impl Render for Document {
fn render(&self, data: &mut Data) {
data.open();
data.field("title", &self.title);
data.list("description", &self.description);
data.list("body", &self.body);
data.close();
}
}

/// A node in the procedure tree.
pub enum Node {
Section {
Expand Down Expand Up @@ -68,69 +56,8 @@ pub enum Node {
},
}

impl Render for Node {
fn render(&self, data: &mut Data) {
match self {
Node::Section { ordinal, heading, children } => {
data.open();
data.tag("section");
data.field("ordinal", ordinal);
data.field("heading", heading);
data.list("children", children);
data.close();
}
Node::Procedure { name, title, description, children } => {
data.open();
data.tag("procedure");
data.field("name", name);
data.field("title", title);
data.list("description", description);
data.list("children", children);
data.close();
}
Node::Sequential { ordinal, title, body, invocations, responses, children } => {
data.open();
data.tag("sequential");
data.field("ordinal", ordinal);
data.field("title", title);
data.list("body", body);
data.list("invocations", invocations);
data.list("responses", responses);
data.list("children", children);
data.close();
}
Node::Parallel { title, body, invocations, responses, children } => {
data.open();
data.tag("parallel");
data.field("title", title);
data.list("body", body);
data.list("invocations", invocations);
data.list("responses", responses);
data.list("children", children);
data.close();
}
Node::Attribute { name, children } => {
data.open();
data.tag("attribute");
data.field("name", name);
data.list("children", children);
data.close();
}
}
}
}

/// A response option with an optional condition.
pub struct Response {
pub value: String,
pub condition: Option<String>,
}

impl Render for Response {
fn render(&self, data: &mut Data) {
data.open();
data.field("value", &self.value);
data.field("condition", &self.condition);
data.close();
}
}
Loading
Loading