#ifndef CST_KEYMAP_H #define CST_KEYMAP_H #include #ifdef __cplusplus extern "C" { #endif /* Key codes: a Unicode code point (control characters included: ctrl+a = 1), * a CST_K_* special key, optionally OR'ed with CST_KEY_ALT. */ #define CST_KEY_SPECIAL 0x110000 #define CST_KEY_ALT 0x400000 enum { CST_K_UP = CST_KEY_SPECIAL, CST_K_DOWN, CST_K_LEFT, CST_K_RIGHT, CST_K_HOME, CST_K_END, CST_K_PGUP, CST_K_PGDN, CST_K_BTAB, /* shift+tab */ CST_K_DEL, CST_K_INS, CST_K_CTRL_HOME, CST_K_CTRL_END, CST_K_CTRL_UP, CST_K_CTRL_DOWN, CST_K_ALT_UP, CST_K_ALT_DOWN, CST_K_F1, /* CST_K_F1 + n - 1 for f1..f12 */ CST_K_LAST = CST_K_F1 + 11 }; typedef enum { CST_KA_NONE = 0, /* general */ CST_KA_PALETTE, CST_KA_KEYS, CST_KA_MODE, CST_KA_APPROVAL, CST_KA_NEWLINE, CST_KA_REDRAW, CST_KA_QUIT, /* view */ CST_KA_TOGGLE_TOOL, CST_KA_TOGGLE_THOUGHT, CST_KA_THINKING_ALL, CST_KA_DETAILS, CST_KA_TODO, CST_KA_SIDEBAR, CST_KA_SCROLL_UP, CST_KA_SCROLL_DOWN, CST_KA_LINE_UP, CST_KA_LINE_DOWN, CST_KA_TOP, CST_KA_BOTTOM, /* session */ CST_KA_NEW_SESSION, CST_KA_SESSIONS, CST_KA_UNDO, CST_KA_RETRY, CST_KA_COMPACT, CST_KA_COPY, CST_KA_EXPORT, /* model */ CST_KA_MODEL, CST_KA_PROVIDER, CST_KA_EFFORT, /* extensions */ CST_KA_AGENTS, CST_KA_SKILLS, CST_KA_PLUGINS, CST_KA_COUNT } cst_key_action_t; typedef struct { const char *name; /* keybinds.json key, e.g. "new_session" */ const char *group; /* "General", "View", ... */ const char *desc; const char *slash; /* equivalent slash command, or NULL */ } cst_key_action_info_t; const cst_key_action_info_t *cst_key_action_info(int action); int cst_key_action_find(const char *name); /* CST_KA_NONE when unknown */ /* "ctrl+p", "shift+tab", "alt+enter", "f1", "pgup", "x" → code; -1 if bad. */ int cst_key_parse(const char *s); /* code → canonical name ("ctrl+x", "tab", "alt+up", ...). */ const char *cst_key_name(int code, char *buf, size_t n); #define CST_KEYMAP_MAX 128 typedef struct { int action; int keys[2]; int nkeys; int user; /* from keybinds.json */ } cst_binding_t; typedef struct { int leader; cst_binding_t b[CST_KEYMAP_MAX]; int n; } cst_keymap_t; void cst_keymap_defaults(cst_keymap_t *km); /* Apply keybinds.json text over the defaults: * {"leader":"ctrl+x", "palette":"ctrl+p", "new_session":[" n","f2"], * "todo":"none"} * Returns 0, or -1 with a message (bad entries are skipped, the rest apply). */ int cst_keymap_apply_json(cst_keymap_t *km, const char *json, char *err, size_t err_sz); /* Defaults + /keybinds.json when present. */ int cst_keymap_load(cst_keymap_t *km, char *err, size_t err_sz); #define CST_KM_NONE 0 #define CST_KM_MATCH 1 #define CST_KM_PREFIX 2 /* seq of 1 or 2 keys → CST_KM_*; *action set on a match. */ int cst_keymap_lookup(const cst_keymap_t *km, const int *seq, int n, int *action); /* "ctrl+x n, f2" (or "" when unbound). */ void cst_keymap_describe(const cst_keymap_t *km, int action, char *buf, size_t n); /* One line per conflict ("ctrl+o: toggle_tool, toggle_thought"); returns the * number of conflicts. */ int cst_keymap_conflicts(const cst_keymap_t *km, char *buf, size_t n); #ifdef __cplusplus } #endif #endif