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'.
This commit is contained in:
Hugo Heagren 2024-08-04 12:54:27 +01:00 committed by Stefan Monnier
parent 042eee61ee
commit 3139ce7ad4
2 changed files with 62 additions and 1 deletions

View file

@ -123,6 +123,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

View file

@ -392,9 +392,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))
@ -417,6 +424,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'.