Immediate-mode keybindings with auto-generated help page in Jai
- YT :: https://www.youtube.com/watch?v=0toGj487cpA
- Original title :: Immediate Mode Shortcuts System
Tsoding adds a centralized but still immediate-mode keybinding system to Sowon2, his Jai + raylib music player/timer that is driven almost entirely by shortcuts. Each shortcut check also logs itself with a description and source location, so the app can show an F1 help page listing exactly the shortcuts available in the current context, and later flag collisions - without refactoring every existing IsKeyPressed call site.
The problem
- Keyboard-only UI keeps the GUI trivial (no buttons), but there are now too many shortcuts to remember.
- A README would rot. A classic centralized keymap is not "immediate modable": every
IsKeyPressedcheck scattered through the frame would have to be rewritten.
Design
- Global
Key_Bindingsstate persisting across frames, bracketed per frame bykey_bindings_begin(*kb)/key_bindings_end(*kb). - =key_bindings_pressed(*kb, modifiers, key, description, loc=#caller_location)= behaves like
IsKeyPressedbut appends aKey_Stroke(modifiers, key, description, source location) to a per-frame log. beginclears the log; by the end of the frame the log holds every shortcut the current context checked.- Modifiers are a Jai
enum_flags(Ctrl, Shift, Alt) - a bitmask; chat compares it to Pascal sets. Modifiers not in the mask must be up, so Ctrl+Z and Ctrl+Shift+Z are distinct flat bindings instead of nested ifs. - Collisions: initially logged on detection, then moved to the help page (duplicates shown in red, ideally clickable to jump to source via emacsclient) to avoid a log line per frame. A compile-time check via Jai metaprogramming - BFS over the function's control flow graph, the same algorithm used to type-check Porth - is floated as a future idea.
- Both APIs coexist: unmigrated raw key checks keep working, they just don't appear in help.
Help page
- F1 sets "switch to help mode on next frame": the log is only complete at frame end, and the help page has its own keys, so
key_bindings_snapshotfreezes the previous frame's log before switching. - F1 has to be bound per mode, otherwise opening help from help recursively snapshots the help page's own keys.
- Rendering: modifiers joined with
+via a temp-allocated string builder, key names formatted, rounded background and frame around each key stroke, aligned description column; Escape returns to the previous mode.
Ideas parked for later
- Grouping bindings, hidden (debug) bindings, search in help, popup instead of a full page, region-scoped uniqueness, modifier-only chords (Shift+Alt).