If you run (kbd "M-r") you'll get back the bit vector [134217842]. But what if I want to go the other way around: start with [134217842] and return M-r. How does one do that?

I Have looked at the edmacro-parse-keys function inside edmacro.el, and that describes how to go from the string to the bitvector. However this code is a bit tough to read, let alone figure out how to reverse.

For context, you'll see this in LAP disassembly, and I would like to provide the human-readable format instead, (although I suppose that's not strictly necessary).

One other slight complication: although understanding how to do this in Elisp would be great, the decompiler right now is in Python. So if it is easier to describe that way, this would be helpful.


2 Answers 2


In Emacs Lisp, key-description does this. For instance: (key-description [134217842]) gives you "M-r".

Its docstring says that kbd is an approximate inverse of it.

(Method of finding this out: Look at definition of describe-key (C-h k) which does this as part of its operations, go to help--analyze-key and finally help-key-description.)


Here is some Python3 code that accomplishes this to some extent. It may have bugs in it. If someone wants to convert this to Elisp and post that as an answer I'll accept that. In the meantime...

def emacs_key_translate(s):
    result = ''
    if s[0] == '"':
        result = '"'
        for c in s[1:]:
            if ord(c) < 31:
                result += '\C-%s' % chr(ord('a') + ord(c) - 1)
                result += c
        m = re.match("^\[(\w+(?: \w+)*)\]$", s)
        if m:
            for s in m.group(1).split():
                    i = int(s)
                    if i == 27:
                        result += ' ESC'
                    elif 134217728 <= i <= 134217759:
                        result += ' C-M-%s' % chr(95 - (134217759 - i)).lower()
                    elif 134217761 <= i <= 134217854:
                        result += ' M-%s' % chr(126 - (134217854 - i)).lower()
                except ValueError:
                    # FIXME: check that is something like "right" "up", etc.
                    # Also handle <C-M-down>
                    result += (' <%s>' % s)

    if result != s:
        return 'kbd("%s")' % result.lstrip(' ')
    return s

for seq in (
    print("'%s' -> '%s'" % (seq,  
emacs_key_translate(seq.strip().replace('|', ' '))))

The code lives in github here.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.