From 39cd91751cd2b7c2eac63f556d6d3dea6b8ab655 Mon Sep 17 00:00:00 2001 From: Gregory Heytings Date: Sat, 16 Oct 2021 16:47:47 +0000 Subject: [PATCH] Make it possible to use the kbd key binding syntax in more places. * src/keymap.c (is_kbd_key, maybe_convert_kbd_key): New functions. (Fdefine_key, Flookup_key, Fkey_binding, Fminor_mode_key_binding): Use the new functions, and document the change. (syms_of_keymap): Add symbol. --- src/keymap.c | 94 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) diff --git a/src/keymap.c b/src/keymap.c index be45d2be1e..4b1054079b 100644 --- a/src/keymap.c +++ b/src/keymap.c @@ -1026,6 +1026,86 @@ DEFUN ("copy-keymap", Fcopy_keymap, Scopy_keymap, 1, 1, 0, /* GC is possible in this function if it autoloads a keymap. */ +static bool +is_kbd_key (char *key) +{ + bool mod[6]; + bool space = false; + if (strlen (key) < 2) + return false; + while (*key) + { + if (space && *key != ' ') + return false; + if (*key == ' ') + { + if (!space || !*(key + 1)) + return false; + space = false; + key++; + continue; + } + mod[0] = mod[1] = mod[2] = mod[3] = mod[4] = mod[5] = false; + while (((*key == 'A' && !mod[0] && (mod[0] = true)) || + (*key == 'C' && !mod[1] && (mod[1] = true)) || + (*key == 'H' && !mod[2] && (mod[2] = true)) || + (*key == 'M' && !mod[3] && (mod[3] = true)) || + (*key == 's' && !mod[4] && (mod[4] = true)) || + (*key == 'S' && !mod[5] && (mod[5] = true))) && + *(key + 1) == '-') + key += 2; + if (!strncmp (key, "NUL", 3) || !strncmp (key, "RET", 3) || + !strncmp (key, "LFD", 3) || !strncmp (key, "TAB", 3) || + !strncmp (key, "ESC", 3) || !strncmp (key, "SPC", 3) || + !strncmp (key, "DEL", 3)) + { + space = true; + key += 3; + continue; + } + if (*key == '<' && + ((*(key + 1) >= 'a' && *(key + 1) <= 'z') || + (*(key + 1) >= 'A' && *(key + 1) <= 'Z'))) + { + key++; + while (*key && *key != '>') + { + if (!((*key >= 'a' && *key <= 'z') || + (*key >= 'A' && *key <= 'Z') || + (*key >= '0' && *key <= '9') || + *key == '-' || *key == '_')) + return false; + key++; + } + if (*key != '>') + return false; + space = true; + key++; + continue; + } + if (*key >= '!' && *key <= '~') + { + space = true; + key++; + continue; + } + return false; + } + return true; +} + +static Lisp_Object +maybe_convert_kbd_key (Lisp_Object key) +{ + Lisp_Object kbd_key; + if (STRINGP (key) && + is_kbd_key (SSDATA (key)) && + !NILP (Ffboundp (Qkbd)) && + !NILP ((kbd_key = safe_call1 (Qkbd, key)))) + key = kbd_key; + return key; +} + DEFUN ("define-key", Fdefine_key, Sdefine_key, 3, 3, 0, doc: /* In KEYMAP, define key sequence KEY as DEF. KEYMAP is a keymap. @@ -1037,6 +1117,8 @@ DEFUN ("define-key", Fdefine_key, Sdefine_key, 3, 3, 0, [remap COMMAND] remaps any key binding for COMMAND. [t] creates a default definition, which applies to any event with no other definition in KEYMAP. +When KEY is a string in the format returned by commands such as `C-h k' +\(`describe-key'), it is first processed by `kbd', which see. DEF is anything that can be a key's definition: nil (means key is undefined in this keymap), @@ -1059,6 +1141,8 @@ DEFUN ("define-key", Fdefine_key, Sdefine_key, 3, 3, 0, { bool metized = false; + key = maybe_convert_kbd_key (key); + keymap = get_keymap (keymap, 1, 1); ptrdiff_t length = CHECK_VECTOR_OR_STRING (key); @@ -1204,6 +1288,8 @@ DEFUN ("lookup-key", Flookup_key, Slookup_key, 2, 3, 0, { bool t_ok = !NILP (accept_default); + key = maybe_convert_kbd_key (key); + if (!CONSP (keymap) && !NILP (keymap)) keymap = get_keymap (keymap, true, true); @@ -1577,6 +1663,8 @@ DEFUN ("current-active-maps", Fcurrent_active_maps, Scurrent_active_maps, DEFUN ("key-binding", Fkey_binding, Skey_binding, 1, 4, 0, doc: /* Return the binding for command KEY in current keymaps. KEY is a string or vector, a sequence of keystrokes. +When KEY is a string in the format returned by commands such as `C-h k' +\(`describe-key'), it is first processed by `kbd', which see. The binding is probably a symbol with a function definition. Normally, `key-binding' ignores bindings for t, which act as default @@ -1602,6 +1690,8 @@ DEFUN ("key-binding", Fkey_binding, Skey_binding, 1, 4, 0, */) (Lisp_Object key, Lisp_Object accept_default, Lisp_Object no_remap, Lisp_Object position) { + key = maybe_convert_kbd_key (key); + if (NILP (position) && VECTORP (key)) { if (ASIZE (key) == 0) @@ -1661,6 +1751,8 @@ DEFUN ("minor-mode-key-binding", Fminor_mode_key_binding, Sminor_mode_key_bindin int nmaps = current_minor_maps (&modes, &maps); Lisp_Object binding = Qnil; + key = maybe_convert_kbd_key (key); + int j; for (int i = j = 0; i < nmaps; i++) if (!NILP (maps[i]) @@ -3261,4 +3353,6 @@ syms_of_keymap (void) defsubr (&Stext_char_description); defsubr (&Swhere_is_internal); defsubr (&Sdescribe_buffer_bindings); + + DEFSYM (Qkbd, "kbd"); } -- 2.33.0