Function: key-description
key-description is a function defined in keymap.c.
Signature
(key-description KEYS &optional PREFIX)
Documentation
Return a pretty description of key-sequence KEYS.
Optional arg PREFIX is the sequence of keys leading up to KEYS. For example, [?\C-x ?l] is converted into the string "C-x l".
For an approximate inverse of this, see kbd.
Source Code
// Defined in /usr/src/emacs/src/keymap.c
{
ptrdiff_t len = 0;
Lisp_Object *args;
EMACS_INT nkeys = XFIXNUM (Flength (keys));
EMACS_INT nprefix = XFIXNUM (Flength (prefix));
Lisp_Object sep = build_string (" ");
bool add_meta = false;
USE_SAFE_ALLOCA;
/* This has one extra element at the end that we don't pass to Fconcat. */
ptrdiff_t size4;
if (INT_MULTIPLY_WRAPV (nkeys + nprefix, 4, &size4))
memory_full (SIZE_MAX);
SAFE_ALLOCA_LISP (args, size4);
/* In effect, this computes
(mapconcat 'single-key-description keys " ")
but we shouldn't use mapconcat because it can do GC. */
Lisp_Object lists[2] = { prefix, keys };
ptrdiff_t listlens[2] = { nprefix, nkeys };
for (int li = 0; li < ARRAYELTS (lists); li++)
{
Lisp_Object list = lists[li];
ptrdiff_t listlen = listlens[li], i_byte = 0;
if (! (NILP (list) || STRINGP (list) || VECTORP (list) || CONSP (list)))
wrong_type_argument (Qarrayp, list);
for (ptrdiff_t i = 0; i < listlen; )
{
Lisp_Object key;
if (STRINGP (list))
{
int c = fetch_string_char_advance (list, &i, &i_byte);
if (SINGLE_BYTE_CHAR_P (c) && (c & 0200))
c ^= 0200 | meta_modifier;
key = make_fixnum (c);
}
else if (VECTORP (list))
{
key = AREF (list, i);
i++;
}
else
{
key = XCAR (list);
list = XCDR (list);
i++;
}
if (add_meta)
{
if (!FIXNUMP (key)
|| EQ (key, meta_prefix_char)
|| (XFIXNUM (key) & meta_modifier))
{
args[len++] = Fsingle_key_description (meta_prefix_char,
Qnil);
args[len++] = sep;
if (EQ (key, meta_prefix_char))
continue;
}
else
key = make_fixnum (XFIXNUM (key) | meta_modifier);
add_meta = false;
}
else if (EQ (key, meta_prefix_char))
{
add_meta = true;
continue;
}
args[len++] = Fsingle_key_description (key, Qnil);
args[len++] = sep;
}
}
Lisp_Object result;
if (add_meta)
{
args[len] = Fsingle_key_description (meta_prefix_char, Qnil);
result = Fconcat (len + 1, args);
}
else if (len == 0)
result = empty_unibyte_string;
else
result = Fconcat (len - 1, args);
SAFE_FREE ();
return result;
}