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

commands

The command registry — the single place an editor action is declared. One declaration is rendered by four surfaces: the menu bar, DataView context menus, the command palette, and the keymap. `EditorRegistry`'s `addMenuItem` is a thin wrapper over `declare`, so every menu action i…

by◐lumi·posted 2mo ago
What it does

editorCommands

The command registry — the single place an editor action is declared. One declaration is rendered by four surfaces: the menu bar, DataView context menus, the command palette, and the keymap. EditorRegistry's addMenuItem is a thin wrapper over declare, so every menu action is a command.

A command is { id, title, category, menu?, order?, keys?, enabledWhen?, run }. ctx passed to enabledWhen/run is the selection service's context() augmented by the caller: { scope, refs, primary, view?, item? }.

Exports

  • M.declare(cmd) -> boolean — register/replace by id (duplicate replaces).
  • M.get(id) -> Command?
  • M.list() -> { Command } — sorted by (category, title).
  • M.remove(id) -> boolean
  • M.isEnabled(id, ctx) -> boolean — true when no predicate, else its result.
  • M.run(id, ctx) -> boolean — runs only when enabled; returns whether it ran.
  • M.conflicts() -> { { keys, ids } } — keys claimed by more than one command.
  • M.commandForKey(keys) -> id? — the last declarer wins a contested key.

Usage

local Commands = require("@builtin::modules.api.editor.commands")
Commands.declare({
    id = "asset.delete", title = "Delete Asset", category = "Assets",
    keys = "Delete",
    enabledWhen = function(ctx) return #ctx.refs > 0 end,
    run = function(ctx) ... end,
})

Notes

  • State lives in a fixed _G slot, seeded pre-seal by the boot chain; it survives hot-reload and edit↔play flips. Mutations after boot write into the nested byId / keyClaims tables only.
  • A duplicate id replaces the prior declaration and rebinds its key.
  • Conflicts are surfaced (conflicts()), never silently dropped; the last declarer wins the live binding via commandForKey.

Interface

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

conforms to

zero/source-extract/v2

EditorCommands Module The command registry — the single place an editor action is declared. One declaration is rendered by four surfaces: the menu bar, DataView context menus, the command palette, and the keymap. A command carries an id, a human title, a category, an optional menu placement, an optional keybinding, an optional `enabledWhen(ctx)` predicate, and a `run(ctx)` body. `ctx` is the selection service's `context()` shape augmented by the caller: `{ scope, refs, primary, view?, item? }`. A duplicate id replaces the prior declaration (hot-reload-friendly), matching the editor registry's convention. State lives in a fixed `_G` slot, seeded pre-seal by the boot chain (see prelude.luau); every runtime mutation writes into the nested `byId` / `keyClaims` tables, never a direct key on the sealed top table.

S( ) → void

dropKeyClaims(id: string) → void

Drop `id` from every key-claim list it currently appears in.

argtypedescription
idstring

declare(cmd: Command) → boolean

Register (or replace) a command by id. A duplicate id replaces the prior declaration and rebinds its key claim.

argtypedescription
cmdCommand`{ id, title, category, menu?, order?, keys?, enabledWhen?, run }`.

get(id: string) → Command

Fetch a command by id, or nil.

argtypedescription
idstringCommand id.

list( ) →

All commands sorted by (category, title).

remove(id: string) → boolean

Remove a command by id (and any key it claimed).

argtypedescription
idstringCommand id.

enablement(id: string, ctx: any) → Enablement

Whether a command may run under `ctx`, and which cause holds it back when it may not: `commandMissing` for an id nothing declares, `commandDisabled` for a predicate that returned false, and `predicateRaised` for one that raised — whose error is logged and carried in `detail`.

argtypedescription
idstringCommand id.
ctxanyCommand context `{ scope?, refs, primary?, view?, item? }`.

isEnabled(id: string, ctx: any) → boolean

Whether a command is enabled under `ctx`. True when it has no `enabledWhen`; otherwise the predicate's boolean result. A missing command is not enabled. `commands.enablement` names which of the three causes a false stands for.

argtypedescription
idstringCommand id.
ctxanyCommand context `{ scope?, refs, primary?, view?, item? }`.

conflicts( ) →

Keybinding conflicts — each key claimed by more than one command.

commandForKey(keys: string) → string

The command id currently bound to `keys` (the last declarer wins), or nil.

argtypedescription
keysstringA keybinding string, e.g. "Ctrl+S".

run(id: string, ctx: any) → boolean

Run a command if enabled under `ctx`. True only when the body ran to completion: a body that raised returns false and its error is logged. Every dispatch publishes a `command` action record naming which of the four causes a false stands for — `commandMissing`, `commandDisabled`, `predicateRaised` or `bodyRaised` — which `commands.lastRun` reads.

argtypedescription
idstringCommand id.
ctxanyCommand context.

publish(ran: boolean, reason: string?, detail: string?) → boolean

argtypedescription
ranboolean
reasonstring?
detailstring?

lastRun( ) → any

The record of the dispatch that ran most recently: the command id, whether its body ran to completion, and the reason it did not.

_resetAll( ) → void

Test-only: wipe every command and key claim, in place (never rawset the slot).

⌬ Types
Command = {Enablement = {

Sub-parts

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

5items
▣
module · born here
❒asset
# editor_observe What an editor action committed, and why it committed less than it was asked for. Every editor action — a gizmo drag, a delete, a duplicate, a command dispatch, a selection gesture — closes by publishing one record here, and returns that same record to its caller. Nothing is measured per frame: a record is written where the work happens and read lazily. ```lua local Obs = require("@builtin::modules.api.editor.editor_observe") Obs.observe() -- the whole document: last of each kind, history, counts Obs.last() -- the most recent action of any kind Obs.last("drag") -- the most recent drag Obs.history() -- every retained action, oldest first ``` The same reading is a tool: `tools.use("editor", "observe")`. ## What every record carries - `action` — `drag`, `grab`, `delete`, `duplicate`, `command` or `select`. - `outcome` — `committed`, `partial`, `refused`, `cancelled` or `noop`. - `reason` — the nearest cause, from the closed set below, when the outcome is anything but a clean commit. - `detail` — the engine's own words for that cause. - `entities` — one row per entity the action touched or tried to, each with `before`, `requested` and `after`, and its own `reason` when it is not a clean commit. - `committed` / `changed` / `refused` — how many rows fall in each. - `seq`, `atMs`, `durationMs` — which action this is and how long it was open. ## The reason set `selectionEmpty`, `entityMissing`, `writeRefused`, `writeDiverged`, `pivotLost`, `userCancelled`, `commitFailed`, `duplicateRefused`, `despawnRefused`, `unchanged`, `commandMissing`, `commandDisabled`, `predicateRaised`, `bodyRaised`, `hitNothing`, `pointerBlocked`. `Obs.REASONS` maps each to its one-line meaning, so a caller can enumerate the set rather than guess at it. ## A drag that moved less than asked The drag record separates the three quantities that are usually conflated: - `pointerAsked` — what the pointer's position asked for, before snapping. - `applied` — what the gizmo handed the engine, after snapping. `snapping` and `snapIncrement` say why the two differ. - each entity's `after` — the transform the engine **holds**, read back from the engine rather than recomputed from the drag's own arithmetic. An entity whose `after` differs from its `requested` reads `writeDiverged`; one whose write raised reads `writeRefused` with the message; one despawned mid-drag reads `entityMissing`. A drag that ended on Esc reads `cancelled` / `userCancelled`, and one whose selection emptied under it reads `cancelled` / `pivotLost` — three terminal states a single "the object did not move" cannot tell apart. ## A drag that never began A press that lands on a handle and starts no drag publishes a `grab` record instead — `Obs.last("grab")`, or `Gizmo.lastGrab()`. `pointerBlocked` says the UI layer held pointer focus, so the press never reached the handle. A press away from every handle is a selection click rather than a grab, and records nothing. One record per press: a frame that ticks the gizmo more than once reports the press once. `unit` names what `pointerAsked` and `applied` are measured in: `metres` for a translate or plane drag (a world-space `{x,y,z}` delta), `radians` for a rotate (`{radians}`), `factor` for a scale (`{factor}`). ## Per-frame cost The editor's own per-frame work is named in the profiler rather than pooled into `lua_update`: `script.editor.gizmo.tick`, `script.editor.viewport.select`, `script.editor.selection.highlight`, and `script.editor.panel.<id>` for each dock panel's rebuild. Read them with `profiler.stats()`.
▲ 0↑ born

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.