0

The accepted answer of this question provides a way in terminal Emacs to get command(super) key bindings worked as M-*. The solution should work for every terminal.

How to get Command + Control + */Command + Option + */... like key bindings translate to C-M-*/C-S-*/... in terminal Emacs in Kitty on macOS then?

1 Answer 1

0
  1. Start kitty
  2. Do emacs -nw
  3. Copy the snippet to *scratch* buffer and then do M-x eval-buffer
(require 'dash)

(defvar kitty--char-and-shifted-char)
(setq kitty--char-and-shifted-char
      (mapcar (lambda (it)
                (cons (string-to-char (car it))
                      (string-to-char (cdr it))))
              (append
               (mapcar (lambda (c)
                         (cons (char-to-string c) (char-to-string (upcase c))))
                       (number-sequence ?a ?z))
               '(
                 ("`" . "~")
                 ("1" . "!")
                 ("2" . "@")
                 ("3" . "#")
                 ("4" . "$")
                 ("5" . "%")
                 ("6" . "^")
                 ("7" . "&")
                 ("8" . "*")
                 ("9" . "(")
                 ("0" . ")")
                 ("-" . "_")
                 ("=" . "+")
                 ("[" . "{")
                 ("]" . "}")
                 ("\\" . "|")
                 (";" . ":")
                 ("'" . "\"")
                 ("," . "<")
                 ("." . ">")
                 ("/" . "?")))))

(defun kitty--modifiers->value (modifiers)
  (cl-loop with modifiers->value = '(
                                     (shift . 1)
                                     (alt . 2)
                                     (ctrl . 4)
                                     (super . 8)
                                     (hyper . 16)
                                     (meta . 32)
                                     (caps_lock . 64)
                                     (num_lock . 128))
           for modifier in modifiers
           summing (alist-get modifier modifiers->value) into n
           finally return (1+ n)))

(defun kitty-modifiers->emacs-keys (keys)
  (apply #'concat
         (cl-loop with alist = `((shift . "S-")
                                 (super . "s-")
                                 (alt . "M-")
                                 (ctrl . "C-"))
                  for x in keys
                  collect (cond ((numberp x) (char-to-string x))
                                ((stringp x) x)
                                ((symbolp x) (alist-get x alist))))))

(defvar kitty--info)
(setq kitty--info
      (cl-loop for (base-char . shifted-char) in kitty--char-and-shifted-char
               ;; M-char1
               collect (list
                        base-char
                        nil
                        (list (char-to-string base-char)))
               ;; M-S-char1
               collect (list
                        base-char
                        (list 'shift)
                        (list (char-to-string shifted-char)))))

(defun kitty-configure--Command-key (CommandKey)
  (interactive
   (list
    ;; When we press `Command' key, what do we want to see `M-' or `s-'.
    ;;
    ;; Since `Option' key sends `M-', it is preferable to choose `s-'
    (let* ((choices '(("super" . super)
                      ("alt" . alt)))
           (option (completing-read "Treat Command key as " choices nil t)))
      (assoc-default option choices))))
  (cl-loop with format-spec = "%-32s\t%s"
           ;; When we press Command, Kitty sends a super modifier along with the
           ;; key
           with kitty--prefix = 'super
           with modifier-set = '(ctrl
                                 ;; hyper
                                 )
           initially (let* ((header (format format-spec
                                            "What Emacs Sees"
                                            "What Kitty Sends")))
                       (message "When you press `Command' key ....")
                       (message "%s" header)
                       (message "%s" (make-string (length header) ?-)))
           for new-modifiers in (-powerset modifier-set)
           do (cl-loop for (base-char modifiers emacs-keys) in kitty--info
                       for what-emacs-should-see = (kitty-modifiers->emacs-keys
                                                    (cons CommandKey (append new-modifiers emacs-keys)))
                       for what-kitty-sends = (format "M-[ %s ; %s u"
                                                      (key-description
                                                       (format "%s" base-char))
                                                      (key-description
                                                       (format "%s" (kitty--modifiers->value
                                                                     (cons kitty--prefix
                                                                           (append new-modifiers modifiers))))))
                       do (message format-spec what-emacs-should-see what-kitty-sends)
                       (define-key input-decode-map
                                   (kbd what-kitty-sends)
                                   (kbd what-emacs-should-see)))))


  1. Do M-x kitty-configure--Command-key
  2. You will be prompted for how you want the Command key to behave. Choose super or alt. I suggest you pick super. Since Option key can be configured to send M (or is it ESC?)
  3. You will see following *Messages*. They give an indication of what keys Emacs sees.

When you press ‘Command’ key ....
What Emacs Sees                     What Kitty Sends
-------------------------------------------------
s-C-a                               M-[ 9 7 ; 1 3 u
s-C-A                               M-[ 9 7 ; 1 4 u
s-C-b                               M-[ 9 8 ; 1 3 u
s-C-B                               M-[ 9 8 ; 1 4 u
s-C-c                               M-[ 9 9 ; 1 3 u
s-C-C                               M-[ 9 9 ; 1 4 u
s-C-d                               M-[ 1 0 0 ; 1 3 u
s-C-D                               M-[ 1 0 0 ; 1 4 u
s-C-e                               M-[ 1 0 1 ; 1 3 u
s-C-E                               M-[ 1 0 1 ; 1 4 u
....
s-a                                 M-[ 9 7 ; 9 u
s-A                                 M-[ 9 7 ; 1 0 u
s-b                                 M-[ 9 8 ; 9 u
s-B                                 M-[ 9 8 ; 1 0 u
s-c                                 M-[ 9 9 ; 9 u
s-C                                 M-[ 9 9 ; 1 0 u
s-d                                 M-[ 1 0 0 ; 9 u
s-D                                 M-[ 1 0 0 ; 1 0 u
s-e                                 M-[ 1 0 1 ; 9 u
s-E                                 M-[ 1 0 1 ; 1 0 u
  1. Do C-h k Command+x and see what sees
  2. Do Command+x and see what Emacs sees
  3. Do C-Command+% and see what Emacs sees.
  4. Do M-x kitty-configure--Command-key, and for a change pick alt and repeat the previous steps.

Above snippet doesn't handle any key not seen in *Messages* specifically it does NOT handle Functional key definition and any other .

Setting up of the keys that are NOT configured by this snippet, is left as an exercise to the reader.


FWIW, on Debian/Windows Keyboard,emacs running within kitty doesn't respond to LeftWinKey. (LeftWinKey is usually s- (=super) on GTK Emacs).

So, the snippet shared above not only can be used on Macs to configure the Command key, but also can be used to configure LeftWin on Debian/Windows machines.

I--the author of this snippet--use Debian/Windows laptop btw. This is a a en:us keyboard with qwerty layout.

~$ setxkbmap -print -verbose 10
Setting verbose level to 10
locale is C
Trying to load rules file ./rules/evdev...
Trying to load rules file /usr/share/X11/xkb/rules/evdev...
Success.
Applied rules from evdev:
rules:      evdev
model:      pc105
layout:     us,mn,us
variant:    ,,
options:    numpad:microsoft,keypad:pointerkeys,compose:menu,caps:shiftlock
Trying to build keymap using the following components:
keycodes:   evdev+aliases(qwerty)
types:      complete+numpad(microsoft)
compat:     complete+ledcaps(shift_lock)
symbols:    pc+us+mn:2+us:3+inet(evdev)+capslock(shiftlock)+compose(menu)+keypad(pointerkeys)
geometry:   pc(pc105)
xkb_keymap {
    xkb_keycodes  { include "evdev+aliases(qwerty)" };
    xkb_types     { include "complete+numpad(microsoft)"    };
    xkb_compat    { include "complete+ledcaps(shift_lock)"  };
    xkb_symbols   { include "pc+us+mn:2+us:3+inet(evdev)+capslock(shiftlock)+compose(menu)+keypad(pointerkeys)" };
    xkb_geometry  { include "pc(pc105)" };
};



1

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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