Skip to main content

Context

Context is the heart of an archetype script: a smart map that holds template variables and provides every prompt method. Values placed in a Context become the variables your templates render against.

local context = Context.new()
context:prompt_text("Project Name:", "project-name", { cases = Cases.programming() })
directory.render("contents", context)

Constructor

Context.new()

local context = Context.new()

Creates a new Context. Answers pre-supplied to this invocation — from -a key=value, an answer file, or a parent archetype — are loaded into it immediately, which is how prompts get auto-answered.

Returns: Context

Core methods

MethodReturnsDescription
ctx:get(key)anyThe stored value, or nil if absent
ctx:has(key)booleanWhether the key exists
ctx:contains(key, value)booleanWhether the array at key contains value
ctx:set(key, value, opts?)Store a value directly (with optional case expansion)
ctx:merge(other)Deep-merge another Context or table into this one
tostring(ctx)stringYAML of the context's data (a valid answer file)

ctx:get(key)

local name = context:get("project_name")

Returns the value stored under key, or nil when the key is not present. This is how you read case-expanded variants produced by cases options — prompt methods return only the raw value.

ctx:has(key)

if context:has("project-suffix") then ... end

Returns true when the key exists in the context.

ctx:contains(key, value)

if context:contains("features", "GitHub Actions") then ... end

Returns true when the value stored at key is an array containing value (string comparison). Returns false when the key is missing or is not an array. Handy for checking prompt_multiselect results.

ctx:set(key, value, opts)

context:set("author", "Jane Doe")
context:set("service-name", "order api", { cases = Cases.programming() })
ParameterTypeDescription
keystringKey to store under
valueanyString, integer, boolean, table (map or array), or nil
opts.casesCaseSpec | CaseSpec[]Case expansion — applies to string values only

Notes:

  • Setting nil stores a Nil sentinel — it does not remove the key. There is no context:remove(); avoid setting nil if you need the key to be absent.
  • When opts.cases is supplied, the original key is written alongside the case variants. Use a canonical key form (kebab or snake) so the input key doesn't collide with a derived variant.

ctx:merge(other)

context:merge(catalog.render("components/xtask", context))
context:merge(format.from_yaml(file.read("defaults.yaml")))

Deep-merges another Context or a map-shaped Lua table into this one. Map-into-map merges recursively; scalar and array values are overwritten by the incoming value. Merging nil is a no-op; merging an array-shaped table is an error.

This is the standard way to absorb a child archetype's contributions — see catalog.

tostring(ctx)

log.debug(tostring(context))

Serializes the context's data as YAML — equivalent to format.to_yaml(ctx). The output round-trips as a valid answer file, so dumping a context doubles as "what answers would reproduce this render". See format, log & output.

Prompt methods

All seven prompt methods follow the same contract:

  1. Answer lookup first. If an answer already exists in the context (from -a, an answer file, or a parent), the prompt is skipped and the answer is used.
  2. Defaults in headless / --use-defaults modes. When running headless, or when the key is covered by use_defaults / use_defaults_all, the default option is used without prompting. If there is no default and the prompt is not optional, the render fails with an error.
  3. Storage. The result is stored in the context under key (with case expansion where supported).
  4. Return value is the raw user value. Each method returns exactly what the user entered — nil when an optional prompt is skipped. Case-expanded variants are stored in the context only; read them with ctx:get.
-- Returns the raw input; case variants are context side effects.
local raw = context:prompt_text("Project Name:", "project-name", {
cases = Cases.programming(),
})
-- raw == "My Project"
-- context:get("project-name") == "My Project"
-- context:get("project_name") == "my_project"
-- context:get("ProjectName") == "MyProject"

Common options

OptionTypeApplies toDescription
defaultvariesall except prompt_listValue used when the user accepts the default, and in headless/use-defaults modes
helpstringallHelp text shown alongside the prompt
placeholderstringallPlaceholder text in the input field
optionalbooleanall except prompt_editorAllow skipping; a skipped prompt returns nil and stores nothing
casesCaseSpec | CaseSpec[]prompt_text, prompt_selectCase expansion — see Casing
answer_keystringallPre-answer lookup alias (see below)

answer_key semantics

answer_key is a lookup alias only. When checking for a pre-supplied answer, the prompt looks under answer_key instead of the prompt's own key. The result is always stored under the prompt's own key regardless. Use it when the CLI or a parent archetype supplies a value under a different name than your storage key:

-- `archetect render -a artifact_id=widget ...` answers this prompt,
-- but the value is stored (and case-expanded) under "project-name".
context:prompt_text("Project Name:", "project-name", {
answer_key = "artifact_id",
cases = Cases.programming(),
})

prompt_text

context:prompt_text(message, key, opts?) --> string | nil
OptionTypeDescription
defaultstringDefault value
helpstringHelp text
placeholderstringPlaceholder text
minintegerMinimum input length
maxintegerMaximum input length
optionalbooleanWhether the prompt can be skipped
casesCaseSpec | CaseSpec[]Case expansion rules
answer_keystringPre-answer lookup alias
local desc = context:prompt_text("Description:", "description", {
default = "A new project",
min = 3,
max = 80,
})

prompt_int

context:prompt_int(message, key, opts?) --> integer | nil
OptionTypeDescription
defaultintegerDefault value
helpstringHelp text
placeholderstringPlaceholder text
minintegerMinimum value
maxintegerMaximum value
optionalbooleanWhether the prompt can be skipped
answer_keystringPre-answer lookup alias
local port = context:prompt_int("Service Port:", "port", {
default = 8080,
min = 1024,
max = 65535,
})

prompt_confirm

context:prompt_confirm(message, key, opts?) --> boolean | nil
OptionTypeDescription
defaultbooleanDefault value
helpstringHelp text
placeholderstringPlaceholder text
optionalbooleanWhether the prompt can be skipped
answer_keystringPre-answer lookup alias
if context:prompt_confirm("Initialize a git repository?", "git-init", { default = true }) then
local git = require("archetect.git")
git.init()
end

prompt_select

context:prompt_select(message, key, options, opts?) --> string | nil
ParameterTypeDescription
optionsstring[]The choices presented to the user
OptionTypeDescription
defaultstringDefault selection (may be an off-list value when allow_other = true)
helpstringHelp text
placeholderstringPlaceholder text
optionalbooleanWhether the prompt can be skipped
allow_otherbooleanAppend an "Other..." entry that opens a free-text prompt
other_labelstringLabel for the "other" entry (default: "Other...")
casesCaseSpec | CaseSpec[]Case expansion rules
answer_keystringPre-answer lookup alias
local lang = context:prompt_select("Language:", "language",
{ "Rust", "Java", "Python" },
{ default = "Rust", allow_other = true })

prompt_multiselect

context:prompt_multiselect(message, key, options, opts?) --> string[] | nil
ParameterTypeDescription
optionsstring[]The choices presented to the user
OptionTypeDescription
defaultstring[]Default selections
helpstringHelp text
placeholderstringPlaceholder text
minintegerMinimum number of selections
maxintegerMaximum number of selections
optionalbooleanWhether the prompt can be skipped
answer_keystringPre-answer lookup alias
context:prompt_multiselect("Features:", "features",
{ "Dockerfile", "GitHub Actions", "Helm Chart" },
{ default = { "Dockerfile" } })

if context:contains("features", "Helm Chart") then
directory.render("contents/helm", context)
end

A pre-supplied answer may be an array or a comma-separated string (-a features="Dockerfile, Helm Chart"); a string is split on commas and stored as an array.

:::caution Deprecated alias prompt_multi_select is a deprecated alias of prompt_multiselect. It behaves identically but logs a deprecation warning; migrate to prompt_multiselect. :::

prompt_list

context:prompt_list(message, key, opts?) --> string[] | nil

Prompts for a free-form list of strings (the user enters items one at a time).

OptionTypeDescription
defaultstring[]Default items (used in headless / use-defaults modes)
helpstringHelp text
placeholderstringPlaceholder text
minintegerMinimum number of items
maxintegerMaximum number of items
optionalbooleanWhether the prompt can be skipped
answer_keystringPre-answer lookup alias
local modules = context:prompt_list("Module names:", "modules", { min = 1 })

As with prompt_multiselect, a pre-supplied string answer is split on commas into an array.

prompt_editor

context:prompt_editor(message, key, opts?) --> string | nil

Opens the user's editor to capture multi-line text.

OptionTypeDescription
defaultstringInitial text in the editor
helpstringHelp text
placeholderstringPlaceholder text
answer_keystringPre-answer lookup alias
local body = context:prompt_editor("Long description:", "long-description", {
default = "# " .. context:get("project-name"),
})

See also