6

I am working with Emacs on Cygwin, which actually has 3 types of Emacsen:

  • Win32 Emacs, which is a graphical Emacs compiled to use native Windows GUI (so no X windows is required)
  • Terminal Emacs, which displays in the mintty terminal by default
  • X Windows Emacs (requires X, and not relevant to this question)

I am trying to bind the APPS key (the one with the little menu on it, usually to the right of the right-hand Windows key, I think it is properly known as the MENU key, https://en.wikipedia.org/wiki/Menu_key) to the "super" modifier (gotta love those short key sequences). In Win32 Emacs this is pretty easy:

(when (equal window-system 'w32)
    (setq w32-pass-apps-to-system nil
          w32-apps-modifier 'super))

This makes Emacs treat APPS as super and stops it passing it onto the OS. It then becomes trivial to make bindings such as

(define-key global-map (kbd "s-r") 'recentf-open-files)

Problem

How to make terminal mode Emacs also treat APPS as super? Firstly it was necessary to have mintty changed to pass through the APPS key to Emacs; this has been done already by the maintainer (see https://github.com/mintty/mintty/issues/494) and we can now configure mintty to send any escape sequence we want through to Emacs.

As I said in the issue, the initial suggestion of Key_Menu=29 (which results in ESC [ 2 9 ~ appearing in the view-lossage log), appears to be interpreted by Emacs as the "<print>" key, so that I can succesfully bind using

(global-set-key (kbd "<print> r") 'recentf-open-files)

The above, while it is a great advance, is not ideal because 2 sets of bindings would be required, one for terminal mode and one for graphical windowed mode.

Things that I don't know

  • How does Emacs translate a sequence of input characters into a logical key?
  • Why does terminal Emacs think the ESC 29 sequence is the print key?
  • Does terminal Emacs even know about the APPS key?

Question

  • How can I configure W32 Emacs and terminal Emacs so that they both treat APPS/MENU as the super modifier, thus enabling a single set of keybindings to be used in both cases?
  • 1
    Please edit the post so that it asks one clear question. If you have multiple questions, feel free to make multiple posts. – Dan Nov 20 '15 at 10:57
  • Interesting question! I don't have an answer, but if you're using mintty, this page may have part of your answer: code.google.com/p/mintty/wiki/Keycodes . – Sue D. Nymme Nov 20 '15 at 13:42
  • 1
    I found out why Emacs thinks it is the print key. There is a line in list\term\xterm.el.gz which maps that sequence to print: (define-key map "\e[29~" [print]) – Philip Daniels Nov 22 '15 at 11:22
  • Please consider accepting your own answer. This question still shows up on the unanswered list. Thx. – Drew Feb 11 at 17:55
4

I made quite a bit of progress on this. Reading up on key translation I found this Emacs manual page on Translation keymaps which has an interesting hyperify function

(defun hyperify (prompt)
  (let ((e (read-event)))
    (vector (if (numberp e)
                (logior (lsh 1 24) e)
              (if (memq 'hyper (event-modifiers e))
                  e
                (add-event-modifier "H-" e))))))

(defun add-event-modifier (string e)
  (let ((symbol (if (symbolp e) e (car e))))
    (setq symbol (intern (concat string
                                 (symbol-name symbol))))
    (if (symbolp e)
        symbol
      (cons symbol (cdr e)))))

(define-key local-function-key-map "\C-ch" 'hyperify)

An equivalent superify function can be written by replacing the lsh 1 24 with lsh 1 23 (see Emacs page on character modifier bits). However, googling hyperify resulted in a hit on the Emacs wiki called "StickyModifiers" which mentions a built in function to achieve this called event-apply-super-modifier. I guess the manual is a bit out of date or it was just for pedagogical purposes. In any case, this will make APPS/MENU into a super key in both terminal and W32 Emacs under mintty:

(if (equal system-type 'cygwin)
     (if (equal window-system 'w32)
         (setq w32-pass-apps-to-system nil
               w32-apps-modifier 'super)
       (define-key local-function-key-map (kbd "<print>") 'event-apply-super-modifier)))

 (define-key global-map (kbd "s-h") (lambda () (interactive) (message "hello from menu key via s- prefix")))

Problem It is not perfect however, because holding the APPS key down results in the string [29~ being repeatedly written into the buffer, so you have to be quick. Contrast this with the way that the Alt key works: you can hold it down for as long as you want.

Alternative Technique Over at ErgoEmacs I found an article talking about leader keys, which unfortunately I cannot post because reputation is no longer high enough having given it all to bounty. SIGH. Anyway, it is called "emacs_menu_app_keys". Using this technique:

(if (equal system-type 'cygwin)
     (if (equal window-system 'w32)
         (setq w32-pass-apps-to-system nil
               w32-apps-modifier nil)
       (progn ;; force all alternatives to <apps> so we can write one set of keybindings.
         (define-key key-translation-map (kbd "<print>") (kbd "<apps>"))
         (define-key key-translation-map (kbd "<menu>") (kbd "<apps>")))))

 (define-key global-map (kbd "<apps> h")
    (lambda () (interactive) (message "hello from menu key via <apps> leader key")))

This works great, you press and release APPS before pressing H. I think I prefer it to the first technique as it is easier to type and this prefix key will be reserved for mnemonic-style, one-shot function bindings anyway i.e. nothing that I need to press repeatedly like C-n.

Bounty If anybody can come up with something better, especially if they can get the first technique to work as perfectly as using the Alt or Ctrl keys I will still award the bounty to them.

  • Sadly, I don't have a menu/apps key, and I can't seem to reproduce the problem without it. – PythonNut Nov 26 '15 at 22:28

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.