Tutorial 2: Building a Config DSL¶
Use Capy to turn a small declarative source language into a JSON configuration file. Estimated time: 10 minutes.
Goal¶
Source:
Output (a package.json-ish file):
Step 1 — initial library¶
extension json
context
name ""
version ""
dependencies []
end
function set_name
arg capture n any
set context.name n
end
function set_version
arg capture v any
set context.version v
end
function depend
arg literal "depend"
arg literal "on"
arg capture pkg any
append context.dependencies pkg
end
file_template
write (toJSONIndent context)
end
Key concepts here:
contextdeclares the initial state. Maps to{}, lists to[].- No function calls
write— the body emits nothing; the entire output is the rendered context. set/appendmutate context.file_templateusestoJSONIndentto marshal context.depend onis a multi-literal pattern. The function namedependis NOT auto-prepended because the args list already contains literals.
Step 2 — add validation¶
Add a type for semantic versions:
And change set_version to use it:
Now set_version "1.2.0" is valid; set_version "not-a-version" fails
with a clear error.
Step 3 — script¶
Run:
Output:
Note that JSON object keys are alphabetised by the marshaller — if you want a specific order, render the file_template manually:
file_template
write `{
"name": ${toQuoted context.name},
"version": ${toQuoted context.version},
"dependencies": ${toJSON context.dependencies}
}
`
end
Try it¶
- Add a
script <name> = "<cmd>"function that accumulates a map (set context.scripts[name] cmd). - Add an enum-typed field, e.g.
set_licensewithoptions: ["MIT", "Apache-2.0", "GPL-3.0"]. - Add a
description "<text>"function.
Next¶
Tutorial 3: Transpiling to Python introduces block functions and indented bodies.