1
0
mirror of https://git.savannah.gnu.org/git/emacs.git synced 2024-12-02 08:22:22 +00:00

Refactor key describing commands

* lisp/help.el (help-read-key-sequence, help--analyze-key): New
functions, extracted from `describe-key' and `describe-key-briefly'.
(describe-key, describe-key-briefly): Use them.
This commit is contained in:
Noam Postavsky 2017-06-17 20:33:56 -04:00
parent 0ad5fd4b6c
commit 2bd32ede1c

View File

@ -593,6 +593,39 @@ If INSERT (the prefix arg) is non-nil, insert the message in the buffer."
string
(format "%s (translated from %s)" string otherstring))))))
(defun help--analyze-key (key untranslated)
"Get information about KEY its corresponding UNTRANSLATED events.
Returns a list of the form (BRIEF-DESC DEFN EVENT MOUSE-MSG)."
(if (numberp untranslated)
(setq untranslated (this-single-command-raw-keys)))
(let* ((event (aref key (if (and (symbolp (aref key 0))
(> (length key) 1)
(consp (aref key 1)))
1
0)))
(modifiers (event-modifiers event))
(mouse-msg (if (or (memq 'click modifiers) (memq 'down modifiers)
(memq 'drag modifiers)) " at that spot" ""))
(defn (key-binding key t)))
;; Handle the case where we faked an entry in "Select and Paste" menu.
(when (and (eq defn nil)
(stringp (aref key (1- (length key))))
(eq (key-binding (substring key 0 -1)) 'yank-menu))
(setq defn 'menu-bar-select-yank))
;; Don't bother user with strings from (e.g.) the select-paste menu.
(when (stringp (aref key (1- (length key))))
(aset key (1- (length key)) "(any string)"))
(when (and untranslated
(stringp (aref untranslated (1- (length untranslated)))))
(aset untranslated (1- (length untranslated)) "(any string)"))
(list
;; Now describe the key, perhaps as changed.
(let ((key-desc (help-key-description key untranslated)))
(if (or (null defn) (integerp defn) (equal defn 'undefined))
(format "%s%s is undefined" key-desc mouse-msg)
(format "%s%s runs the command %S" key-desc mouse-msg defn)))
defn event mouse-msg)))
(defun describe-key-briefly (&optional key insert untranslated)
"Print the name of the function KEY invokes. KEY is a string.
If INSERT (the prefix arg) is non-nil, insert the message in the buffer.
@ -603,73 +636,10 @@ the last key hit are used.
If KEY is a menu item or a tool-bar button that is disabled, this command
temporarily enables it to allow getting help on disabled items and buttons."
(interactive
(let ((enable-disabled-menus-and-buttons t)
(cursor-in-echo-area t)
saved-yank-menu)
(unwind-protect
(let (key)
;; If yank-menu is empty, populate it temporarily, so that
;; "Select and Paste" menu can generate a complete event.
(when (null (cdr yank-menu))
(setq saved-yank-menu (copy-sequence yank-menu))
(menu-bar-update-yank-menu "(any string)" nil))
(while
(progn
(setq key (read-key-sequence "Describe the following key, mouse click, or menu item: "))
(and (vectorp key)
(consp (aref key 0))
(symbolp (car (aref key 0)))
(string-match "\\(mouse\\|down\\|click\\|drag\\)"
(symbol-name (car (aref key 0))))
(not (sit-for (/ double-click-time 1000.0) t)))))
;; Clear the echo area message (Bug#7014).
(message nil)
;; If KEY is a down-event, read and discard the
;; corresponding up-event. Note that there are also
;; down-events on scroll bars and mode lines: the actual
;; event then is in the second element of the vector.
(and (vectorp key)
(let ((last-idx (1- (length key))))
(and (eventp (aref key last-idx))
(memq 'down (event-modifiers (aref key last-idx)))))
(read-event))
(list
key
(if current-prefix-arg (prefix-numeric-value current-prefix-arg))
1))
;; Put yank-menu back as it was, if we changed it.
(when saved-yank-menu
(setq yank-menu (copy-sequence saved-yank-menu))
(fset 'yank-menu (cons 'keymap yank-menu))))))
(if (numberp untranslated)
(setq untranslated (this-single-command-raw-keys)))
(let* ((event (if (and (symbolp (aref key 0))
(> (length key) 1)
(consp (aref key 1)))
(aref key 1)
(aref key 0)))
(modifiers (event-modifiers event))
(standard-output (if insert (current-buffer) standard-output))
(mouse-msg (if (or (memq 'click modifiers) (memq 'down modifiers)
(memq 'drag modifiers)) " at that spot" ""))
(defn (key-binding key t))
key-desc)
;; Handle the case where we faked an entry in "Select and Paste" menu.
(if (and (eq defn nil)
(stringp (aref key (1- (length key))))
(eq (key-binding (substring key 0 -1)) 'yank-menu))
(setq defn 'menu-bar-select-yank))
;; Don't bother user with strings from (e.g.) the select-paste menu.
(if (stringp (aref key (1- (length key))))
(aset key (1- (length key)) "(any string)"))
(if (and (> (length untranslated) 0)
(stringp (aref untranslated (1- (length untranslated)))))
(aset untranslated (1- (length untranslated)) "(any string)"))
;; Now describe the key, perhaps as changed.
(setq key-desc (help-key-description key untranslated))
(if (or (null defn) (integerp defn) (equal defn 'undefined))
(princ (format "%s%s is undefined" key-desc mouse-msg))
(princ (format "%s%s runs the command %S" key-desc mouse-msg defn)))))
(pcase-let ((`(,key ,_up-event) (help-read-key-sequence)))
`(,key ,current-prefix-arg 1)))
(princ (car (help--analyze-key key untranslated))
(if insert (current-buffer) standard-output)))
(defun help--key-binding-keymap (key &optional accept-default no-remap position)
"Return a keymap holding a binding for KEY within current keymaps.
@ -734,6 +704,55 @@ function `key-binding'."
(throw 'found x))))
nil)))))
(defun help-read-key-sequence ()
"Reads a key sequence from the user.
Returns a list of the form (KEY UP-EVENT), where KEY is the key
sequence, and UP-EVENT is the up-event that was discarded by
reading KEY, or nil."
(let ((enable-disabled-menus-and-buttons t)
(cursor-in-echo-area t)
saved-yank-menu)
(unwind-protect
(let (key)
;; If yank-menu is empty, populate it temporarily, so that
;; "Select and Paste" menu can generate a complete event.
(when (null (cdr yank-menu))
(setq saved-yank-menu (copy-sequence yank-menu))
(menu-bar-update-yank-menu "(any string)" nil))
(while
(pcase (setq key (read-key-sequence "\
Describe the following key, mouse click, or menu item: "))
((and (pred vectorp) (let `(,key0 . ,_) (aref key 0))
(guard (symbolp key0)) (let keyname (symbol-name key0)))
(and (string-match "\\(mouse\\|down\\|click\\|drag\\)"
keyname)
(not (sit-for (/ double-click-time 1000.0) t))))))
(list
key
;; If KEY is a down-event, read and include the
;; corresponding up-event. Note that there are also
;; down-events on scroll bars and mode lines: the actual
;; event then is in the second element of the vector.
(and (vectorp key)
(let ((last-idx (1- (length key))))
(and (eventp (aref key last-idx))
(memq 'down (event-modifiers (aref key last-idx)))))
(or (and (eventp (aref key 0))
(memq 'down (event-modifiers (aref key 0)))
;; However, for the C-down-mouse-2 popup
;; menu, there is no subsequent up-event. In
;; this case, the up-event is the next
;; element in the supplied vector.
(= (length key) 1))
(and (> (length key) 1)
(eventp (aref key 1))
(memq 'down (event-modifiers (aref key 1)))))
(read-event))))
;; Put yank-menu back as it was, if we changed it.
(when saved-yank-menu
(setq yank-menu (copy-sequence saved-yank-menu))
(fset 'yank-menu (cons 'keymap yank-menu))))))
(defun describe-key (&optional key untranslated up-event)
"Display documentation of the function invoked by KEY.
KEY can be any kind of a key sequence; it can include keyboard events,
@ -748,83 +767,20 @@ UP-EVENT is the up-event that was discarded by reading KEY, or nil.
If KEY is a menu item or a tool-bar button that is disabled, this command
temporarily enables it to allow getting help on disabled items and buttons."
(interactive
(let ((enable-disabled-menus-and-buttons t)
(cursor-in-echo-area t)
saved-yank-menu)
(unwind-protect
(let (key)
;; If yank-menu is empty, populate it temporarily, so that
;; "Select and Paste" menu can generate a complete event.
(when (null (cdr yank-menu))
(setq saved-yank-menu (copy-sequence yank-menu))
(menu-bar-update-yank-menu "(any string)" nil))
(while
(progn
(setq key (read-key-sequence "Describe the following key, mouse click, or menu item: "))
(and (vectorp key)
(consp (aref key 0))
(symbolp (car (aref key 0)))
(string-match "\\(mouse\\|down\\|click\\|drag\\)"
(symbol-name (car (aref key 0))))
(not (sit-for (/ double-click-time 1000.0) t)))))
(list
key
(prefix-numeric-value current-prefix-arg)
;; If KEY is a down-event, read and include the
;; corresponding up-event. Note that there are also
;; down-events on scroll bars and mode lines: the actual
;; event then is in the second element of the vector.
(and (vectorp key)
(let ((last-idx (1- (length key))))
(and (eventp (aref key last-idx))
(memq 'down (event-modifiers (aref key last-idx)))))
(or (and (eventp (aref key 0))
(memq 'down (event-modifiers (aref key 0)))
;; However, for the C-down-mouse-2 popup
;; menu, there is no subsequent up-event. In
;; this case, the up-event is the next
;; element in the supplied vector.
(= (length key) 1))
(and (> (length key) 1)
(eventp (aref key 1))
(memq 'down (event-modifiers (aref key 1)))))
(read-event))))
;; Put yank-menu back as it was, if we changed it.
(when saved-yank-menu
(setq yank-menu (copy-sequence saved-yank-menu))
(fset 'yank-menu (cons 'keymap yank-menu))))))
(if (numberp untranslated)
(setq untranslated (this-single-command-raw-keys)))
(let* ((event (aref key (if (and (symbolp (aref key 0))
(> (length key) 1)
(consp (aref key 1)))
1
0)))
(modifiers (event-modifiers event))
(mouse-msg (if (or (memq 'click modifiers) (memq 'down modifiers)
(memq 'drag modifiers)) " at that spot" ""))
(defn (key-binding key t))
key-locus key-locus-up key-locus-up-tricky
defn-up defn-up-tricky ev-type
mouse-1-remapped mouse-1-tricky)
;; Handle the case where we faked an entry in "Select and Paste" menu.
(when (and (eq defn nil)
(stringp (aref key (1- (length key))))
(eq (key-binding (substring key 0 -1)) 'yank-menu))
(setq defn 'menu-bar-select-yank))
(if (or (null defn) (integerp defn) (equal defn 'undefined))
(message "%s%s is undefined"
(help-key-description key untranslated) mouse-msg)
(pcase-let ((`(,key ,up-event) (help-read-key-sequence)))
`(,key ,(prefix-numeric-value current-prefix-arg) ,up-event)))
(pcase-let ((`(,brief-desc ,defn ,event ,mouse-msg)
(help--analyze-key key untranslated))
(defn-up nil) (defn-up-tricky nil)
(key-locus-up nil) (key-locus-up-tricky nil)
(mouse-1-remapped nil) (mouse-1-tricky nil)
(ev-type nil))
(if (or (null defn)
(integerp defn)
(equal defn 'undefined))
(message "%s" brief-desc)
(help-setup-xref (list #'describe-function defn)
(called-interactively-p 'interactive))
;; Don't bother user with strings from (e.g.) the select-paste menu.
(when (stringp (aref key (1- (length key))))
(aset key (1- (length key)) "(any string)"))
(when (and untranslated
(stringp (aref untranslated (1- (length untranslated)))))
(aset untranslated (1- (length untranslated))
"(any string)"))
;; Need to do this before erasing *Help* buffer in case event
;; is a mouse click in an existing *Help* buffer.
(when up-event
@ -849,13 +805,12 @@ temporarily enables it to allow getting help on disabled items and buttons."
(aset sequence 0 'mouse-1)
(setq defn-up-tricky (key-binding sequence nil nil (event-start up-event)))
(setq key-locus-up-tricky (help--binding-locus sequence (event-start up-event))))))
(setq key-locus (help--binding-locus key (event-start event)))
(with-help-window (help-buffer)
(princ (help-key-description key untranslated))
(princ (format "%s runs the command %S%s, which is "
mouse-msg defn (if key-locus
(format " (found in %s)" key-locus)
"")))
(princ brief-desc)
(let ((key-locus (help--binding-locus key (event-start event))))
(when key-locus
(princ (format " (found in %s)" key-locus))))
(princ ", which is ")
(describe-function-1 defn)
(when up-event
(unless (or (null defn-up)