cmd

package
v0.7.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 10, 2026 License: MIT Imports: 9 Imported by: 0

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

func ParseDocument(r io.Reader) (*Document, error)

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.

func (*Document) Serialize

func (d *Document) Serialize(w io.Writer) error

Serialize writes the Document's retained source back out to w verbatim, reproducing the exact text ParseDocument read — including comments, section ordering, unrecognized sections, and original line endings.

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.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL