Axel Meyer 8f4128ee34 docs: migrate README to API-Doc-Convention (S2 Phase 3)
Restructured per spec section 3.2: Abstract + Badges-Table + Topology-Block
+ 7 H3-API-Subsections + Conventions + Consumer pattern + Migration +
CHANGELOG + References. Topology-Block auto-populated via
Sporel.exe --lint --fix. Pre-commit hook installed via --install-hooks.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-16 14:17:44 +02:00

lib-core.input

P.0 action-mapping lib. Decouples physical keys from logical actions. Polling-based (is_action_down) + edge-based (was_action_pressed, was_action_released). Direction-vector helper composes 4 actions into {x, y} in {-1, 0, +1}^2.

Field Value
Version 0.4.0
Lib-ID lib-core.input
Requires (none)
Tags input, action-mapping
graph LR
  this["lib-core.input"]
  engine["engine.*"]
  this --> engine

API

input.bind(action_name, keys)

Syntax: input.bind(action_name: string, keys: string[]) -> void

Example:

input.bind("move_left", { "a", "left" })

Description: Bindet einen logischen Action-Namen an ein Array von Key-Names. Atomic: wenn ein Key invalid ist, fehlt der gesamte Bind ohne partial state. Lua error(...) für bind() misuse (caller-bug fast-fail).

input.unbind(action_name)

Syntax: input.unbind(action_name: string) -> void

Example:

input.unbind("move_left")

Description: Entfernt eine Action-Binding. No-op wenn Action nicht gebunden.

input.is_action_down(action) -> bool

Syntax: input.is_action_down(action: string) -> bool

Example:

if input.is_action_down("move_left") then ... end

Description: Returns true wenn irgendein gebundener Key der Action gerade gedrückt ist. Silent-false für undefined actions.

input.was_action_pressed(action) -> bool

Syntax: input.was_action_pressed(action: string) -> bool

Example:

if input.was_action_pressed("quit") then engine.exit(0) end

Description: Press-Edge — true für genau einen Frame pro Key-Down-Event. Triggers einmal pro Press-Release-Cycle.

input.was_action_released(action) -> bool

Syntax: input.was_action_released(action: string) -> bool

Example:

if input.was_action_released("attack") then finish_swing() end

Description: Release-Edge — true für genau einen Frame pro Key-Up-Event. v0.4.0+. Triggers einmal pro Press-Release-Cycle.

input.direction(left, right, up, down)

Syntax: input.direction(left: string, right: string, up: string, down: string) -> {x: int, y: int}

Example:

local d = input.direction("move_left", "move_right", "move_up", "move_down")
-- d.x, d.y in {-1, 0, +1}

Description: Komponiert 4 Actions in einen Direction-Vector. Y-down-positive per ADR-0031.

input.action_count() -> number

Syntax: input.action_count() -> number

Description: Returns Anzahl der gebundenen Actions. Debug-friendly.

Key-Names

Strict-lowercase. Engine-internal engine.input.KEY_* integer-args are rejected.

Category Names
Letters a, b, ..., z
Numbers 0, 1, ..., 9
Arrows left, right, up, down
Whitespace + control space, tab, enter, backspace, escape
Modifiers (left-side) shift (= lshift), ctrl (= lctrl), alt (= lalt)
Console-toggle ^ (DE: Zirkumflex / US: backtick)
Mouse mouse_left, mouse_right, mouse_middle (v0.3.0+)

Right-modifier-aliases (rshift, rctrl, ralt) + function-keys (f1..f12) + special-keys (delete, insert, ...) are forthcoming.

Unknown key-names raise a Lua-error with hint to this README.

Conventions

  • Y-down-positive per Sporel pixel-convention (ADR-0031).
  • Multi-key per action (e.g., {"a", "left"} for both A and Left-Arrow).
  • Silent-false for undefined actions (debug-friendly).
  • Lua error(...) for bind() misuse (caller-bug fast-fail). Atomic.

Consumer pattern

local input = require("lib-core.input")
input.bind("quit",       { "escape" })
input.bind("move_left",  { "a", "left" })
input.bind("move_right", { "d", "right" })
input.bind("move_up",    { "w", "up" })
input.bind("move_down",  { "s", "down" })

function update(ctx, dt)
    if input.was_action_pressed("quit") then engine.exit(0) end
    local d = input.direction("move_left", "move_right", "move_up", "move_down")
    -- d.x, d.y in {-1, 0, +1}
end

Migration v0.1.0 -> v0.2.0

bind() switched from integer engine.input.KEY_* arguments to lowercase string-keys (per P.2.6). Reason: stop leaking engine-internal namespace into modules.

v0.1.0 v0.2.0
bind("quit", { engine.input.KEY_ESCAPE }) bind("quit", { "escape" })

CHANGELOG

v0.4.0 (P.3.10, 2026-05-15)

  • Added was_action_released(action_name) — release-edge detection per action.

v0.3.0 (P.3.3, 2026-05-12)

  • bind() now accepts unified key+mouse strings via BIND_MAP with kind-tagged entries.

v0.2.0 (P.2.6, 2026-05-11)

  • bind() accepts string-key-names only.

v0.1.0 (P.0)

  • Initial release.

References

  • Spec v0.4.0 (P.3.10): meta/docs/superpowers/specs/2026-05-15-p3-housekeeping-design.md
  • Spec v0.3.0 (P.3.3): meta/docs/superpowers/specs/2026-05-12-p3-3-mouse-input-design.md
  • Spec v0.2.0 (P.2.6): meta/docs/superpowers/specs/2026-05-11-engine-input-symbolic-keys-design.md
  • Spec v0.1.0 (P.0): meta/docs/superpowers/specs/2026-05-09-p0-lib-input-design.md
  • ADR-0001 (engine knows verbs, libs bring nouns)
  • ADR-0031 (pixel-convention: Y-down-positive)
  • ADR-0038 (API-Doc-Convention)
Description
P.0.lib.input � action-mapping + direction-vector helper
Readme 50 KiB
Languages
Lua 94.9%
Shell 5.1%