Documentation
¶
Overview ¶
Package cmd defines the pure-data model for MUGEN/Ikemen GO input command (.cmd) files: CommandFile, CommandDefaults, and Command.
This is the read-path surface — the stable vocabulary a library consumer (editor, engine) works with. It carries no INI parsing, file I/O, or write-only (format-preservation) logic; per CLAUDE.md's read/write separation constraint, that lives elsewhere so importing this data model alone never pulls in write-only dependencies.
A .cmd file has two structurally distinct parts: button remapping/command definitions unique to this format ("[Remap]", "[Defaults]", "Command" sections), and an "always" state ("[Statedef -1]" plus its "[State ...]" controllers) that links a recognized command to a state change — byte-for- byte the same syntax .cns already parses. CommandFile.States is that second part, parsed via the cns package rather than reimplemented here; see .vibe/decisions/025-cmd-package-reuses-cns-for-state-triggering-block.md. The link itself needs no dedicated modeling: it already flows through cns.Controller's existing unevaluated Triggers strings (e.g. `command = "holdback"`), the same "read-path model can't hold everything yet" pattern this repo applies throughout.
Parse turns MUGEN/Ikemen GO .cmd text into a CommandFile — the read-path entry point for this package.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Serialize ¶
func Serialize(w io.Writer, file CommandFile) error
Serialize writes file to w as MUGEN/Ikemen GO .cmd text: a "[Remap]" section (if file.Remap is non-empty), a "[Defaults]" section (if file.Defaults is not the zero value), one "Command" block per file.Commands entry in order, and finally the linked "always" state (file.States) via cns.Serialize — see .vibe/decisions/025-cmd-package-reuses-cns-for-state-triggering-block.md.
This is a first-pass write path: it does not attempt a byte-exact round-trip of any original file's formatting, comments, or unrecognized sections (a separate, format-preserving concern — see Document) — it only guarantees valid, readable output that Parse reads back into an equivalent CommandFile. Remap is written sorted by key for deterministic output, since Go map order carries no meaning Parse relies on. A Command's Time/BufferTime is only written when non-zero: zero means "not set, use CommandFile.Defaults" (see Command's own doc comment), so writing an explicit zero would round-trip into a real override instead of staying unset.
Types ¶
type Command ¶
type Command struct {
// Name identifies this command (.cmd "name"), referenced by a linked
// state controller's trigger (e.g. `command = "holdback"`).
Name string `json:"name"`
// Input is the raw, unevaluated MUGEN/Ikemen input-sequence expression
// (.cmd "command", e.g. "~D, DF, F, a") that must be entered to trigger
// this command. Stored verbatim rather than decomposed into individual
// steps: this repo has no input-sequence grammar to evaluate it against,
// mirroring cns.Controller's own unevaluated Triggers/Parameters.
Input string `json:"input"`
// Time is this command's own input-recognition buffer window override
// (.cmd "command.time" scoped to this [Command] block); zero means "not
// set", in which case CommandFile.Defaults.Time applies instead.
Time int `json:"time"`
// BufferTime is this command's own recognized-command duration override
// (.cmd "command.buffer.time" scoped to this [Command] block); zero
// means "not set", in which case CommandFile.Defaults.BufferTime applies
// instead.
BufferTime int `json:"bufferTime"`
}
Command is a single .cmd "Command" section: a named input sequence a player can perform.
type CommandDefaults ¶
type CommandDefaults struct {
// Time is the default input-recognition buffer window, in game ticks
// (.cmd "command.time").
Time int `json:"time"`
// BufferTime is the default duration a completed command stays
// recognized before being discarded, in game ticks (.cmd
// "command.buffer.time").
BufferTime int `json:"bufferTime"`
}
CommandDefaults is a .cmd file's "[Defaults]" section: the command-recognition window a Command falls back to when it doesn't set its own Time/BufferTime.
type CommandFile ¶
type CommandFile struct {
// Remap maps a physical button ("a", "b", "c", "x", "y", "z", "s", ...)
// to the button it is remapped to (.cmd "[Remap]" section). A nil or
// empty Remap means no remapping is defined — an Ikemen GO extension not
// present in every MUGEN 1.0/1.1 .cmd file.
Remap map[string]string `json:"remap"`
// Defaults are the file-level command-recognition defaults (.cmd
// "[Defaults]" section) a Command falls back to when it doesn't set its
// own Time/BufferTime.
Defaults CommandDefaults `json:"defaults"`
// Commands are the input command definitions (.cmd "[Command]"
// sections), in file order.
Commands []Command `json:"commands"`
// States are the linked "always" state ("[Statedef -1]" and its
// "[State ...]" controllers) that react to a recognized command, parsed
// via the cns package — see the package doc comment.
States []cns.StateDef `json:"states"`
}
CommandFile is a MUGEN/Ikemen GO input command (.cmd) file: optional button remapping, file-level command-recognition defaults, the input command definitions themselves, and the linked "always" state that reacts to them.
func Parse ¶
func Parse(r io.Reader) (CommandFile, error)
Parse reads MUGEN/Ikemen GO .cmd input-command text from r and returns the CommandFile it describes.
The "[Remap]", "[Defaults]", and "Command" sections (matched case-insensitively) populate CommandFile.Remap/Defaults/Commands; any other section, including "[Statedef -1]" and its "[State ...]" controllers, is skipped by this pass without validation — those are parsed separately via cns.Parse (run against the same source) into CommandFile.States, since they share .cns's syntax byte-for-byte. See the package doc comment and .vibe/decisions/025-cmd-package-reuses-cns-for-state-triggering-block.md.
Within "[Defaults]"/"Command", "command.time"/"time" and "command.buffer.time"/"buffer.time" (matched case-insensitively, with or without the "command." prefix) set the numeric Time/BufferTime fields; a value that doesn't parse as a literal integer is ignored, leaving the field at zero, since this package has no expression grammar for these fields (unlike cns.StateDef's HeaderExprs escape hatch — real .cmd files don't appear to need one for these two fields). "name"/"command" set a Command's Name/Input; Input is stored verbatim and unevaluated, including any MUGEN/Ikemen input-sequence modifiers ("~", "$", "/", "+"). Every "[Remap]" key/value pair becomes a lowercase-keyed Remap entry.
A bracket line missing its closing "]" that looks like an attempt at this package's own "[Remap]"/"[Defaults]"/"Command" header returns a descriptive, line-numbered error; any other bracket line missing "]" (including a "[State ...]" header — a real-world .cmd authoring typo, see backlog item 042's .cns equivalent) is left for cns.Parse's own recovery and is not treated as an error here. A content line inside a known section that isn't a valid "key=value" pair is ignored rather than erroring, the same tolerance def.Parse/cns.Parse already apply. Comment lines (';', whole-line or trailing) are ignored. An empty input returns a zero-value CommandFile and a nil error.
type Document ¶
type Document struct {
File CommandFile
// contains filtered or unexported fields
}
Document is the write-path counterpart to Parse/Serialize: it exists so a .cmd file can be round-tripped — parsed, then serialized back out — without losing the comments, section ordering, and unrecognized sections that the pure-data CommandFile model deliberately does not carry.
Document.File is decoded the same way Parse's return value is, for convenient structured access to what was parsed — but Serialize does not read it back. As long as Document.File is left untouched, ParseDocument followed by Serialize reproduces the original source byte-for-byte, comments and all. Mutating File has no effect on Serialize's output: regenerating text from an edited CommandFile while still preserving unrelated comments/sections/ordering around the edit is a heavier per-line reconciliation this type does not attempt, mirroring def.Document/air.Document.
func ParseDocument ¶
ParseDocument reads MUGEN/Ikemen GO .cmd input-command text from r, decoding it the same way Parse does while also retaining the exact source bytes needed for a faithful round trip through Serialize.
Directories
¶
| Path | Synopsis |
|---|---|
|
Command wasm is the WASM entrypoint for the character library: thin syscall/js glue exposing character.LoadBytes to a browser (or any JS host) as a single global function, so a consumer can load a MUGEN/Ikemen character without a Go toolchain of its own.
|
Command wasm is the WASM entrypoint for the character library: thin syscall/js glue exposing character.LoadBytes to a browser (or any JS host) as a single global function, so a consumer can load a MUGEN/Ikemen character without a Go toolchain of its own. |