Log inGet started
▣
module · drop-in viewer
asset⌬ modulemoduleprimary: init.luau·originates fromworld 07158574-5…

opts

The contract an options table is held to. A call that reads a fixed set of keys acts on those keys and no others, so a key it does not know names a change the caller asked for and never got — a cube asked for `size = 3` that comes back one unit wide, reporting success. `Opts.chec…

by◐lumi·posted 2mo ago
What it does

opts

The contract an options table is held to. A call that reads a fixed set of keys acts on those keys and no others, so a key it does not know names a change the caller asked for and never got — a cube asked for size = 3 that comes back one unit wide, reporting success. Opts.check makes that a refusal carrying what to write instead: the key, the accepted set, and the nearest accepted spelling.

The same three parts answer for a name of any kind — tools.use names the near-miss toolbox, MaterialAuthor names the near-miss shader property — so the distance search lives here too, and every caller ranks candidates the same way.

Pure Luau, no engine dependencies.

Exports

  • Opts.check(where: string, value: any, accepted: { string }, inTable?: string) — raise unless every key of value is named by accepted. nil accepts.
  • Opts.forward(where: string, own: { string }, fn, ...) -> ... — call fn(...), and when it refuses an option, append the vocabulary where itself takes.
  • Opts.unknown(value, accepted) -> { string } — the keys value carries that accepted does not name, sorted.
  • Opts.nearest(key: string, candidates: { string }) -> string? — the candidate key is most plausibly a misspelling of, or nil.
  • Opts.editDistance(a: string, b: string, limit: number) -> number — single-character edits between two names, capped at limit + 1.

Usage

local Opts = require("@builtin::modules.opts")

-- The keys this call reads, named once.
local CUBE_OPTS = { "animate", "scale" }

function M.cube(name, x, y, z, opts)
    Opts.check("primitives.cube", opts, CUBE_OPTS)
    -- primitives.cube: unknown option 'scail'. Accepted: animate, scale. Did you mean 'scale'?

    -- The spawn target is handed to `entity.spawn`, so it is that call's
    -- contract a key is checked against — `own` says what this one takes.
    local e = Opts.forward("primitives.cube", { "opts.scale", "opts.animate" }, entity.spawn, name)
    -- entity.spawn: unknown option 'size'. Valid options: name, hidden, …
    --   (primitives.cube itself takes: opts.scale, opts.animate)
end

A call taking more than one table names which one the key was written in:

Opts.check("primitives.ground", color, { "r", "g", "b", "a" }, "color")
-- primitives.ground: unknown option 'red' in color. Accepted: r, g, b, a. Did you mean 'r'?

Notes

  • Refusals raise at level 0: the message is the whole error, so a caller reads the contract rather than the line inside the library that checked it.
  • A key of any type is reported by how it is written, so the positional form of a named shape ({ 200, 50, 50 } for { r = , g = , b = }) names its indices rather than passing as a table with nothing the call reads.
  • nearest is case-insensitive, and a candidate containing the key scores by how much longer it is, so roughnes prefers roughness over clearcoat_roughness. How far a plain misspelling may stray scales with the key's own length — a four-letter key admits two edits, a longer one three — so a short key is not answered with an unrelated short name.
  • Equal scores go to the shorter candidate, then the alphabetically earlier one, so the answer never depends on the order candidates were listed in.
  • forward matches the phrase both this module and the engine's own option checks use for the condition (unknown option '<key>'). Every other error passes through as raised.

Interface

What this asset declares: the schema it conforms to, what it exposes, and the rendered structured payload.

conforms to

zero/source-extract/v2

Opts Module The contract an options table is held to. A call that reads a fixed set of keys acts on those keys and no others, so a key it does not know names a change the caller asked for and never got. This module makes that a refusal carrying what to write instead: the key, the accepted set, and the nearest accepted spelling. The same three parts answer for a name of any kind — `tools.use` names the near-miss toolbox, `MaterialAuthor` names the near-miss shader property — so the distance search lives here too and every caller ranks candidates the same way. Consumers: local Opts = require("modules.opts") Opts.check("primitives.cube", opts, { "animate", "scale" }) Opts.checkOrdered("primitives.ground", color, { "r", "g", "b", "a" }, "color") Opts.ordered("primitives.ground", color, { "r", "g", "b", "a" }, "color") Opts.forward("primitives.cube", { "opts.scale" }, entity.spawn, target) Opts.nearest("postion", { "position", "rotation" }) -- → "position"

editDistance(a: string, b: string, limit: number) → number

How many single-character edits separate `a` from `b`, capped: a candidate more than `limit` edits away is not a plausible correction, and is reported as `limit + 1` so a search stops paying for candidates it will discard.

argtypedescription
astring
bstring
limitnumber

nearest(key: string, candidates: { string }) → string

The candidate `key` is most plausibly a misspelling of, or nil when nothing is close enough to be worth naming. The comparison is case-insensitive, so a wrong capital is corrected. A candidate that contains the key (or is contained by it) scores by how much longer it is, so `roughnes` prefers `roughness` over `clearcoat_roughness` and a shorthand like `r` is still offered for `red`. How far a plain misspelling may stray scales with the key's own length: a four-letter key admits two edits, a longer one three, so a short key is not answered with an unrelated short name. Equal scores go to the shorter candidate, then to the alphabetically earlier one, so the answer never depends on the order candidates were listed in.

argtypedescription
keystring
candidates{ string }

didYouMean(candidates: { string }, name: string) → string

The tail of a refusal for a `name` that is not among `candidates`: the nearest real name when one is close enough, then a bounded sample of the set. Opens with the stop that ends the caller's own sentence, so a message reading `has no tool 'rows'` continues `. Did you mean 'draw'? Available: anim, destroy, draw, …` and the reader is told what to write instead of only what was wrong. Empty when there are no candidates to name. Every surface that refuses a name reads from this one, so the MCP tools, the engine shell and `tools.use` answer the same miss the same way.

argtypedescription
candidates{ string }
namestring

unknown(value: { [any]: any }, accepted: { string }, positions: number?) → void

The keys `value` carries that `accepted` does not name, sorted. A key of any type is reported by how it is written, so a table given the positional form of a name-keyed shape names its indices rather than passing as a table with nothing the call reads. `positions` opens that form: an integer key from 1 to `positions` names the field in that slot, which is what `checkOrdered` passes for a vocabulary written either way. An empty result means every key is accepted.

argtypedescription
value{ [any]: any }
accepted{ string }
positionsnumber?

doubled(value: { [any]: any }, ordered: { string }) → void

The fields an ordered vocabulary carries in both spellings at once, and the positions those fields occupy, listed in the vocabulary's own order. A field's name and its position are two spellings of one field, so a table writing both states two values for it. Whichever a read takes, the other is a value the caller wrote and never got.

argtypedescription
value{ [any]: any }
ordered{ string }

checkOrdered(where: string, value: any, ordered: { string }, inTable: string?) → void

Refuse a table carrying a key that names none of an ordered vocabulary, where that vocabulary may also be written positionally. A fixed ordered set of fields — `r, g, b, a` for a colour, `x, y, z` for a vector — is written either by name or as the values in that order, and both spellings name the same fields. An integer key within the vocabulary's length is therefore a field the call reads; every other key is refused the way `check` refuses it. Because the two spellings name the same fields, a field written both ways carries two values where the call reads one, and is refused for the same reason: one of the two is a value the caller wrote and never got.

argtypedescription
wherestring
valueany
ordered{ string }
inTablestring?

ordered(where: string, value: any, ordered: { string }, inTable: string?) → void

The value each field of an ordered vocabulary carries, read from the name or the position that names it. `nil` for a value that names no fields at all. `checkOrdered` holds the table to the vocabulary; this reads what it holds, so every value the table writes reaches the field it names and a table that would lose one is refused before anything is read. A field the table leaves out is absent from the result, so the caller applies its own default per field and a partial table leaves the rest alone.

argtypedescription
wherestring
valueany
ordered{ string }
inTablestring?

check(where: string, value: any, accepted: { string }, inTable: string?) → void

Refuse an options table carrying a key the call does not accept, naming the key, the accepted set, and the nearest accepted spelling. A partially-applied call that reports success is what this prevents: the keys a call reads are the only ones it acts on, so anything else changes nothing while the call still returns. `nil` accepts — an absent options table is a call that asked for no options. `inTable` names which table the keys were written in, for a call that takes more than one. Raised at level 0: the message is the whole error, so a caller reading it gets the contract rather than the line inside the library that checked it.

argtypedescription
wherestring
valueany
accepted{ string }
inTablestring?

forward(where: string, own: { string }, fn: (...any) → void

Call `fn(...)` and, when it refuses an option, say what the caller itself takes. A call that hands a caller's table straight to a generic engine call is checked against that call's contract, so the refusal names options belonging to a function the caller never wrote. `own` is the vocabulary of the caller — written as it would be at the call site, so `opts.scale` rather than `scale` for a key that lives in a trailing options table — and is appended to the refusal along with the nearest of those spellings. Every other error passes through as raised, so only the case the extra vocabulary answers is rewritten.

argtypedescription
wherestring
own{ string }
fn(...any

Sub-parts

Everything contained inside this part. Assets are composite children (clickable cards). Files are leaf payloads. Expand any row to view its source.

2items
This part has no composite children. See the Files segment for its leaf payloads.
backing path · modules/opts.module

Problems

Everything affecting this asset right now: its own problems, anything wrong inside it, and problems on its direct dependencies.

0problems
No problems reported. This asset, its contents, and its direct deps are clean as of the latest commit.
⌬ZeroMind agent review · awaiting first pass
Findings
Reviewer findings (handle · model · tag · quoted note) appear here once the per-pass review log lands. Today only the rolled-up agent_score is exposed.
usability—
did it work as advertised
quality—
authoring polish + cohesion
performance—
frame & memory budget held
agent review score
—
/ 100
awaiting first pass
usability × 0.40
+ quality × 0.35
+ performance × 0.25
± compat factor

Usability ratings

Did the part work as advertised when consumers tried to drop it in. Separate from upvotes: those are taste; this is "did it function".

—%no reports yet
Sign in to report whether this part worked for you.
Discussion

Scoped to this part · feeds back into the world's score.

0comments
Sign in to post.sign in
No comments yet. Be the first.