Basics · Events
Key events
Element events cover clicks and form controls, but a keyboard app also
wants the raw key stream. Declare a function named handleKey taking a
sumi.Event and it becomes the component’s raw handler. The wiring is by
name — only handleKey is picked up. The onkey="handleKey" attribute on
the root documents that intent; it is not what does the wiring.
The event carries Kind (EventKey, EventSpecial, EventSignal, …),
Rune for a printable key, and Special for the named keys. Printable
keys arrive as EventKey with Rune set; arrows and the like arrive as
EventSpecial — match them by value against sumi.KeyUp, sumi.KeyDown,
and the other re-exported constants.
You do not have to wire quitting. Ctrl+C already ends the app — it is the
default exit chord (ExitOn). What doesn’t stop on its own is an OS
signal: a SIGINT/SIGTERM arrives as an EventSignal and is ignored
unless you handle it, which is why every handler starts with the same line.
Your turn
Move the selection with j/k and the arrow keys. The % keeps the index
inside the list:
func handleKey(evt sumi.Event) {
if evt.Kind == sumi.EventSignal { sumi.Quit(); return }
n := len(todos.Get())
if n == 0 { return }
if evt.Rune == 'j' || evt.Special == sumi.KeyDown {
selected.Set((selected.Get() + 1) % n)
}
if evt.Rune == 'k' || evt.Special == sumi.KeyUp {
selected.Set((selected.Get() + n - 1) % n)
}
}
Press Run, click into the terminal, and move the > marker with the
keyboard.