From: Hugo Heagren Date: Sun, 4 Aug 2024 11:54:27 +0000 (+0100) Subject: Add commands to interactively set/unset keyboard translations X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=9c0b5d8ce8e07c4f91dc915a4f9008a974b0f35e;p=emacs.git Add commands to interactively set/unset keyboard translations * lisp/keymap.el (key-translate): Add an interactive form, prompting for keys to translate, and update docstring to reflect this. (key-translate-selection-function): New custom option. (key-select-translation): New function, default value of above option. (key-translate-remove): New command, for removing entries from `keyboard-translate-table'. (cherry picked from commit 3139ce7ad42ab883eee5189d6cb19612f525f491) --- diff --git a/etc/NEWS b/etc/NEWS index 151469dc094..6ad0bd7c2f5 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -96,6 +96,11 @@ It is equivalent to running ‘project-any-command’ with ‘find-file’. * Editing Changes in Emacs 31.1 +** Commands for keyboard translation +`key-translate' is now interactive. It prompts for a key to translate +from, and another to translate to, and sets `keyboard-translate-table'. +The new command `key-translate-remove' prompts for a key/translation +pair with completing-read, and removes it from the translation table. ** Internationalization diff --git a/lisp/keymap.el b/lisp/keymap.el index 39442146f01..d53ed702527 100644 --- a/lisp/keymap.el +++ b/lisp/keymap.el @@ -384,9 +384,16 @@ This function creates a `keyboard-translate-table' if necessary and then modifies one entry in it. Both FROM and TO should be specified by strings that satisfy `key-valid-p'. -If TO is nil, remove any existing translation for FROM." +If TO is nil, remove any existing translation for FROM. + +Interactively, prompt for FROM and TO with `read-char'." (declare (compiler-macro (lambda (form) (keymap--compile-check from to) form))) + ;; Using `key-description' is a necessary evil here, so that the + ;; values can be passed to keymap-* functions, even though those + ;; functions immediately undo it with `key-parse'. + (interactive `(,(key-description `[,(read-char "From: ")]) + ,(key-description `[,(read-char "To: ")]))) (keymap--check from) (when to (keymap--check to)) @@ -409,6 +416,55 @@ If TO is nil, remove any existing translation for FROM." (aref from-key 0) (and to (aref to-key 0))))) +(defun key-select-translation () + "Prompt for a current keyboard translation pair with `completing-read'. + +Each pair is formatted as \"FROM -> TO\". + +Return the \"FROM\" as a key string." + (let* ((formatted-trans-alist nil) + ;; Alignment helpers + (pad 0) + (key-code-func + (lambda (kc trans) + (let* ((desc (key-description `[,kc])) + (len (length desc))) + (when (> len pad) + (setq pad len)) + (push + `(,desc . ,(key-description `[,trans])) + formatted-trans-alist)))) + (format-func + (lambda (pair) ;; (key . value) + (format + "%s -> %s" + (string-pad (key-description `[,(car pair)]) pad) + (key-description `[,(cdr pair)]))))) + ;; Set `pad' and `formatted-trans-alist' + (map-char-table + (lambda (chr trans) + (if (characterp chr) + (funcall key-code-func chr trans) + (require 'range) + (range-map + (lambda (kc) (funcall key-code-func kc trans)) + chr))) + keyboard-translate-table) + (car + (split-string + (completing-read + "Key Translation: " + (mapcar format-func formatted-trans-alist) + nil t))))) + +(defun key-translate-remove (from) + "Remove translation of FROM from `keyboard-translate-table'. + +FROM must satisfy `key-valid-p'. If FROM has no entry in +`keyboard-translate-table', this has no effect." + (interactive (list (key-select-translation))) + (key-translate from nil)) + (defun keymap-lookup (keymap key &optional accept-default no-remap position) "Return the binding for command KEY in KEYMAP. KEY is a string that satisfies `key-valid-p'.