From 7f4867ecbd971e1d13868e99f3aea5d9fa4b07c3 Mon Sep 17 00:00:00 2001 From: Hugo Heagren Date: Sun, 4 Aug 2024 12:54:27 +0100 Subject: [PATCH] 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'. --- etc/NEWS | 5 +++++ lisp/keymap.el | 58 +++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 62 insertions(+), 1 deletion(-) diff --git a/etc/NEWS b/etc/NEWS index f10f9ae4d65..3149b99db66 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -32,6 +32,11 @@ applies, and please also update docstrings as needed. * 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. * Changes in Specialized Modes and Packages in Emacs 31.1 diff --git a/lisp/keymap.el b/lisp/keymap.el index 861d6724c9e..b65f34f96bf 100644 --- a/lisp/keymap.el +++ b/lisp/keymap.el @@ -392,9 +392,16 @@ key-translate 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)) @@ -417,6 +424,55 @@ key-translate (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'. -- 2.20.1