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 swap the command (super) and option (meta) then?

Saddle Point
  • 486
  • 8
  • 24

2 Answers2

1

No need to swap/use the modifier keys.

When working with Emacs in Terminal, you can use a built-in feature to implement the behavior specific for the modifier keys Super, Hyper, and Alt.

This feature can be started by: C-x @ followed by one of the characters s or h or a corresponding to the modifier mode and followed by the rest of the desired command. For instance, C-x @ s v (for s-v') or C-s @ h C-a (for 'Hyper-Control-a').

You don't need to write any code line, and, interesting, works also in GUI mode, so developing a habit to use it in terminal does not harm when in GUI.

Ian
  • 1,463
  • 11
  • 13
0

How to swap super and meta in terminal Emacs on macOS?

Before trying on kitty try the below suggestion on GUI Emacs first.

  1. Install the following snippet
(require 'dash)

;; (defvar modmap--bare-keys ;; (cl-loop with case-fold-search = nil ;; for ascii-num in (number-sequence 0 255) ;; for key-desc = (key-description (char-to-string ascii-num)) ;; unless (string-match-p (rx (or "M-" "C-")) key-desc) ;; collect key-desc))

(defvar modmap--bare-keys '("TAB" "RET" "ESC" "SPC" "!" "&quot;" "#" "$" "%" "&" "'" "(" ")" "*" "+" "," "-" "." "/" "0" "1" "2" "3" "4" "5" "6" "7" "8" "9" ":" ";" "<" "=" ">" "?" "@" "A" "B" "C" "D" "E" "F" "G" "H" "I" "J" "K" "L" "M" "N" "O" "P" "Q" "R" "S" "T" "U" "V" "W" "X" "Y" "Z" "[" "\" "]" "^" "_" "`" "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" "p" "q" "r" "s" "t" "u" "v" "w" "x" "y" "z" "{" "|" "}" "~" "DEL"))

;; (defvar modmap--fn-keys ;; (mapcar (lambda (s) ;; (intern (format "<%s>" s))) ;; `( ;; ;; Cursor arrow keys. ;; left up right down ;; ;; Other cursor repositioning keys. ;; begin end home next prior ;; ;; Miscellaneous function keys. ;; select print execute backtab insert undo redo clearline ;; insertline deleteline insertchar deletechar ;; ;; Numbered function keys (across the top of the keyboard). ;; ,@(mapcar (lambda (n) ;; (format "f%s" n)) ;; (number-sequence 1 35)) ;; ;; Keypad keys (to the right of the regular keyboard) ;; ;; with names or ;; ;; punctuation. ;; kp-add kp-subtract kp-multiply kp-divide kp-backtab ;; kp-space kp-tab kp-enter kp-separator kp-decimal kp-equal ;; kp-prior kp-next kp-end kp-home kp-left kp-up kp-right kp-down ;; kp-insert kp-delete ;; ;; Keypad keys with digits. ;; ,@(mapcar (lambda (n) ;; (format "kp%s" n)) ;; (number-sequence 0 9)) ;; ;; Keypad PF keys. ;; ,@(mapcar (lambda (n) ;; (format "kp-f%s" n)) ;; (number-sequence 1 4)))))

(defvar modmap--fn-keys '(<left> <up> <right> <down> <begin> <end> <home> <next> <prior> <select> <print> <execute> <backtab> <insert> <undo> <redo> <clearline> <insertline> <deleteline> <insertchar> <deletechar> <f1> <f2> <f3> <f4> <f5> <f6> <f7> <f8> <f9> <f10> <f11> <f12> <f13> <f14> <f15> <f16> <f17> <f18> <f19> <f20> <f21> <f22> <f23> <f24> <f25> <f26> <f27> <f28> <f29> <f30> <f31> <f32> <f33> <f34> <f35> <kp-add> <kp-subtract> <kp-multiply> <kp-divide> <kp-backtab> <kp-space> <kp-tab> <kp-enter> <kp-separator> <kp-decimal> <kp-equal> <kp-prior> <kp-next> <kp-end> <kp-home> <kp-left> <kp-up> <kp-right> <kp-down> <kp-insert> <kp-delete> <kp0> <kp1> <kp2> <kp3> <kp4> <kp5> <kp6> <kp7> <kp8> <kp9> <kp-f1> <kp-f2> <kp-f3> <kp-f4>))

(defvar modmap--all-keys (append modmap--bare-keys (mapcar #'symbol-name modmap--fn-keys)))

(defvar modmap--modifiers->string `( (alt . "M-") (ctrl . "C-") ;; (hyper . "H-") ;; (shift . "S-") (super . "s-") ))

(defvar modmap--all-modifiers (mapcar #'car modmap--modifiers->string))

(defvar modmap--from->to `((super . alt) (alt . super)))

(defun modmap--print-keys (keys) (apply #'concat (cl-loop with alist = modmap--modifiers->string for x in keys collect (cond ((numberp x) (char-to-string x)) ((stringp x) x) ((symbolp x) (alist-get x alist)) (t (error "This shouldn't happen"))))))

(defun modmap--replace (keys &optional modifier-translations) (cl-loop for key in keys collect (or (alist-get key (or modifier-translations modmap--from->to)) key)))

(defun modmap--do (&optional install) (interactive "P") (cl-loop with format-spec = "\n%-30s\t%s" with case-fold-search = nil for modifiers in (-powerset modmap--all-modifiers) do (cl-loop for keys in modmap--all-keys for from = (append modifiers (list keys)) for to = (modmap--replace from modmap--from->to) for from-keys = (modmap--print-keys from) for to-keys = (modmap--print-keys to) unless (string= from-keys to-keys) do (princ (format format-spec from-keys to-keys)) (when install (with-demoted-errors "Error :%S" (define-key input-decode-map (kbd from-keys) (kbd to-keys)))))))

(defgroup modmap-mode nil "Options for Modmap Mode." :tag "Modmap Mode" :group 'my)

(defvar modmap--input-decode-map)

(define-minor-mode modmap-mode "Modmap Mode." :lighter " Modmap Mode." :group 'modmap-mode :global t (cond (modmap-mode (setq modmap--input-decode-map (copy-tree input-decode-map t)) (with-output-to-temp-buffer (get-buffer-create "modmap") (let* ((format-spec "\n%-30s\t%s") (header "")) (princ (format "\n%s" "You have requested the following translation ...")) (setq header (format format-spec "From" "To")) (princ (format "\n\n%s" header)) (princ (format "\n%s" (make-string (length header) ?-))) (cl-loop for (from . to) in modmap--from->to do (princ (format format-spec (modmap--print-keys (list from)) (modmap--print-keys (list to))))) (princ (format "\n\n%s" "Installing following translation in input-decode-map'&quot;)) ;; Isinput-decode-map' may not be the right translation map in ;; to which the modifier translations can be installed? I am not ;; sure. This is a prototype code ... and for now this works. ;; ;; According to ;; ;; (info "(elisp) Translation Keymaps") ;; ;; When the ‘read-key-sequence’ function reads a key sequence ;; (*note Key Sequence Input::), it uses “translation keymaps” to ;; translate certain event sequences into others. ;; ;; The translation keymaps are ‘input-decode-map’, ;; ‘local-function-key-map’, and ‘key-translation-map’ (in order ;; of priority). (setq header (format format-spec "\nWhen you type this" "Emacs translates it to")) (princ (format "\n%s" header)) (princ (format "\n%s" (make-string (length header) ?-))) (modmap--do 1)))) (t (when (boundp 'modmap--input-decode-map) (setq input-decode-map modmap--input-decode-map)))))

  1. Install also the following snippet. Which puts commands on the s key.
;; Install some bindings on `super` keys for demo purposes.

;; M-x is `execute-extended-command' ;; s-x prints "Hello s-x" (global-set-key (kbd "s-x") (defun hello-world-a () (interactive) (message "%s" "Emacs says &quot;Hello s-x&quot;")))

;; C-M-% is normally `query-replace-regexp' ;; C-s-% prints "Hello C-M-%" (global-set-key (kbd "C-s-%") (defun hello-world-b () (interactive) (message "%s" "Emacs says &quot;Hello &quot;C-M-%&quot;")))

  1. Now do M-x modmap-mode. You will see the following buffer popup, and it tells what the command just did.

M-x modmap-mode

  1. Try M-x, C-M-%. See what happens.
  2. Try s-x, C-s-%. See what happens.
  3. Try C-h k on above keys. See what Emacs reports.

M-x modmap-mode in action (1)

M-x modemap-mode in action (2)

  1. Do s-x modmap-mode, and try the above steps once more. See what happens.

The M-x modmap-mode essentially "swaps" M- and s- keys.