aboutsummaryrefslogtreecommitdiffstats
path: root/lisp/help.el
diff options
context:
space:
mode:
Diffstat (limited to 'lisp/help.el')
-rw-r--r--lisp/help.el257
1 files changed, 109 insertions, 148 deletions
diff --git a/lisp/help.el b/lisp/help.el
index 361ab2a01ee..0fb1c2dab77 100644
--- a/lisp/help.el
+++ b/lisp/help.el
@@ -593,6 +593,39 @@ If INSERT (the prefix arg) is non-nil, insert the message in the buffer."
593 string 593 string
594 (format "%s (translated from %s)" string otherstring)))))) 594 (format "%s (translated from %s)" string otherstring))))))
595 595
596(defun help--analyze-key (key untranslated)
597 "Get information about KEY its corresponding UNTRANSLATED events.
598Returns a list of the form (BRIEF-DESC DEFN EVENT MOUSE-MSG)."
599 (if (numberp untranslated)
600 (setq untranslated (this-single-command-raw-keys)))
601 (let* ((event (aref key (if (and (symbolp (aref key 0))
602 (> (length key) 1)
603 (consp (aref key 1)))
604 1
605 0)))
606 (modifiers (event-modifiers event))
607 (mouse-msg (if (or (memq 'click modifiers) (memq 'down modifiers)
608 (memq 'drag modifiers)) " at that spot" ""))
609 (defn (key-binding key t)))
610 ;; Handle the case where we faked an entry in "Select and Paste" menu.
611 (when (and (eq defn nil)
612 (stringp (aref key (1- (length key))))
613 (eq (key-binding (substring key 0 -1)) 'yank-menu))
614 (setq defn 'menu-bar-select-yank))
615 ;; Don't bother user with strings from (e.g.) the select-paste menu.
616 (when (stringp (aref key (1- (length key))))
617 (aset key (1- (length key)) "(any string)"))
618 (when (and untranslated
619 (stringp (aref untranslated (1- (length untranslated)))))
620 (aset untranslated (1- (length untranslated)) "(any string)"))
621 (list
622 ;; Now describe the key, perhaps as changed.
623 (let ((key-desc (help-key-description key untranslated)))
624 (if (or (null defn) (integerp defn) (equal defn 'undefined))
625 (format "%s%s is undefined" key-desc mouse-msg)
626 (format "%s%s runs the command %S" key-desc mouse-msg defn)))
627 defn event mouse-msg)))
628
596(defun describe-key-briefly (&optional key insert untranslated) 629(defun describe-key-briefly (&optional key insert untranslated)
597 "Print the name of the function KEY invokes. KEY is a string. 630 "Print the name of the function KEY invokes. KEY is a string.
598If INSERT (the prefix arg) is non-nil, insert the message in the buffer. 631If INSERT (the prefix arg) is non-nil, insert the message in the buffer.
@@ -603,73 +636,12 @@ the last key hit are used.
603If KEY is a menu item or a tool-bar button that is disabled, this command 636If KEY is a menu item or a tool-bar button that is disabled, this command
604temporarily enables it to allow getting help on disabled items and buttons." 637temporarily enables it to allow getting help on disabled items and buttons."
605 (interactive 638 (interactive
606 (let ((enable-disabled-menus-and-buttons t) 639 ;; Ignore mouse movement events because it's too easy to miss the
607 (cursor-in-echo-area t) 640 ;; message while moving the mouse.
608 saved-yank-menu) 641 (pcase-let ((`(,key ,_up-event) (help-read-key-sequence 'no-mouse-movement)))
609 (unwind-protect 642 `(,key ,current-prefix-arg 1)))
610 (let (key) 643 (princ (car (help--analyze-key key untranslated))
611 ;; If yank-menu is empty, populate it temporarily, so that 644 (if insert (current-buffer) standard-output)))
612 ;; "Select and Paste" menu can generate a complete event.
613 (when (null (cdr yank-menu))
614 (setq saved-yank-menu (copy-sequence yank-menu))
615 (menu-bar-update-yank-menu "(any string)" nil))
616 (while
617 (progn
618 (setq key (read-key-sequence "Describe the following key, mouse click, or menu item: "))
619 (and (vectorp key)
620 (consp (aref key 0))
621 (symbolp (car (aref key 0)))
622 (string-match "\\(mouse\\|down\\|click\\|drag\\)"
623 (symbol-name (car (aref key 0))))
624 (not (sit-for (/ double-click-time 1000.0) t)))))
625 ;; Clear the echo area message (Bug#7014).
626 (message nil)
627 ;; If KEY is a down-event, read and discard the
628 ;; corresponding up-event. Note that there are also
629 ;; down-events on scroll bars and mode lines: the actual
630 ;; event then is in the second element of the vector.
631 (and (vectorp key)
632 (let ((last-idx (1- (length key))))
633 (and (eventp (aref key last-idx))
634 (memq 'down (event-modifiers (aref key last-idx)))))
635 (read-event))
636 (list
637 key
638 (if current-prefix-arg (prefix-numeric-value current-prefix-arg))
639 1))
640 ;; Put yank-menu back as it was, if we changed it.
641 (when saved-yank-menu
642 (setq yank-menu (copy-sequence saved-yank-menu))
643 (fset 'yank-menu (cons 'keymap yank-menu))))))
644 (if (numberp untranslated)
645 (setq untranslated (this-single-command-raw-keys)))
646 (let* ((event (if (and (symbolp (aref key 0))
647 (> (length key) 1)
648 (consp (aref key 1)))
649 (aref key 1)
650 (aref key 0)))
651 (modifiers (event-modifiers event))
652 (standard-output (if insert (current-buffer) standard-output))
653 (mouse-msg (if (or (memq 'click modifiers) (memq 'down modifiers)
654 (memq 'drag modifiers)) " at that spot" ""))
655 (defn (key-binding key t))
656 key-desc)
657 ;; Handle the case where we faked an entry in "Select and Paste" menu.
658 (if (and (eq defn nil)
659 (stringp (aref key (1- (length key))))
660 (eq (key-binding (substring key 0 -1)) 'yank-menu))
661 (setq defn 'menu-bar-select-yank))
662 ;; Don't bother user with strings from (e.g.) the select-paste menu.
663 (if (stringp (aref key (1- (length key))))
664 (aset key (1- (length key)) "(any string)"))
665 (if (and (> (length untranslated) 0)
666 (stringp (aref untranslated (1- (length untranslated)))))
667 (aset untranslated (1- (length untranslated)) "(any string)"))
668 ;; Now describe the key, perhaps as changed.
669 (setq key-desc (help-key-description key untranslated))
670 (if (or (null defn) (integerp defn) (equal defn 'undefined))
671 (princ (format "%s%s is undefined" key-desc mouse-msg))
672 (princ (format "%s%s runs the command %S" key-desc mouse-msg defn)))))
673 645
674(defun help--key-binding-keymap (key &optional accept-default no-remap position) 646(defun help--key-binding-keymap (key &optional accept-default no-remap position)
675 "Return a keymap holding a binding for KEY within current keymaps. 647 "Return a keymap holding a binding for KEY within current keymaps.
@@ -734,6 +706,59 @@ function `key-binding'."
734 (throw 'found x)))) 706 (throw 'found x))))
735 nil))))) 707 nil)))))
736 708
709(defun help-read-key-sequence (&optional no-mouse-movement)
710 "Reads a key sequence from the user.
711Returns a list of the form (KEY UP-EVENT), where KEY is the key
712sequence, and UP-EVENT is the up-event that was discarded by
713reading KEY, or nil.
714If NO-MOUSE-MOVEMENT is non-nil, ignore key sequences starting
715with `mouse-movement' events."
716 (let ((enable-disabled-menus-and-buttons t)
717 (cursor-in-echo-area t)
718 saved-yank-menu)
719 (unwind-protect
720 (let (key)
721 ;; If yank-menu is empty, populate it temporarily, so that
722 ;; "Select and Paste" menu can generate a complete event.
723 (when (null (cdr yank-menu))
724 (setq saved-yank-menu (copy-sequence yank-menu))
725 (menu-bar-update-yank-menu "(any string)" nil))
726 (while
727 (pcase (setq key (read-key-sequence "\
728Describe the following key, mouse click, or menu item: "))
729 ((and (pred vectorp) (let `(,key0 . ,_) (aref key 0))
730 (guard (symbolp key0)) (let keyname (symbol-name key0)))
731 (if no-mouse-movement
732 (string-match "mouse-movement" keyname)
733 (and (string-match "\\(mouse\\|down\\|click\\|drag\\)"
734 keyname)
735 (not (sit-for (/ double-click-time 1000.0) t)))))))
736 (list
737 key
738 ;; If KEY is a down-event, read and include the
739 ;; corresponding up-event. Note that there are also
740 ;; down-events on scroll bars and mode lines: the actual
741 ;; event then is in the second element of the vector.
742 (and (vectorp key)
743 (let ((last-idx (1- (length key))))
744 (and (eventp (aref key last-idx))
745 (memq 'down (event-modifiers (aref key last-idx)))))
746 (or (and (eventp (aref key 0))
747 (memq 'down (event-modifiers (aref key 0)))
748 ;; However, for the C-down-mouse-2 popup
749 ;; menu, there is no subsequent up-event. In
750 ;; this case, the up-event is the next
751 ;; element in the supplied vector.
752 (= (length key) 1))
753 (and (> (length key) 1)
754 (eventp (aref key 1))
755 (memq 'down (event-modifiers (aref key 1)))))
756 (read-event))))
757 ;; Put yank-menu back as it was, if we changed it.
758 (when saved-yank-menu
759 (setq yank-menu (copy-sequence saved-yank-menu))
760 (fset 'yank-menu (cons 'keymap yank-menu))))))
761
737(defun describe-key (&optional key untranslated up-event) 762(defun describe-key (&optional key untranslated up-event)
738 "Display documentation of the function invoked by KEY. 763 "Display documentation of the function invoked by KEY.
739KEY can be any kind of a key sequence; it can include keyboard events, 764KEY can be any kind of a key sequence; it can include keyboard events,
@@ -748,83 +773,20 @@ UP-EVENT is the up-event that was discarded by reading KEY, or nil.
748If KEY is a menu item or a tool-bar button that is disabled, this command 773If KEY is a menu item or a tool-bar button that is disabled, this command
749temporarily enables it to allow getting help on disabled items and buttons." 774temporarily enables it to allow getting help on disabled items and buttons."
750 (interactive 775 (interactive
751 (let ((enable-disabled-menus-and-buttons t) 776 (pcase-let ((`(,key ,up-event) (help-read-key-sequence)))
752 (cursor-in-echo-area t) 777 `(,key ,(prefix-numeric-value current-prefix-arg) ,up-event)))
753 saved-yank-menu) 778 (pcase-let ((`(,brief-desc ,defn ,event ,mouse-msg)
754 (unwind-protect 779 (help--analyze-key key untranslated))
755 (let (key) 780 (defn-up nil) (defn-up-tricky nil)
756 ;; If yank-menu is empty, populate it temporarily, so that 781 (key-locus-up nil) (key-locus-up-tricky nil)
757 ;; "Select and Paste" menu can generate a complete event. 782 (mouse-1-remapped nil) (mouse-1-tricky nil)
758 (when (null (cdr yank-menu)) 783 (ev-type nil))
759 (setq saved-yank-menu (copy-sequence yank-menu)) 784 (if (or (null defn)
760 (menu-bar-update-yank-menu "(any string)" nil)) 785 (integerp defn)
761 (while 786 (equal defn 'undefined))
762 (progn 787 (message "%s" brief-desc)
763 (setq key (read-key-sequence "Describe the following key, mouse click, or menu item: "))
764 (and (vectorp key)
765 (consp (aref key 0))
766 (symbolp (car (aref key 0)))
767 (string-match "\\(mouse\\|down\\|click\\|drag\\)"
768 (symbol-name (car (aref key 0))))
769 (not (sit-for (/ double-click-time 1000.0) t)))))
770 (list
771 key
772 (prefix-numeric-value current-prefix-arg)
773 ;; If KEY is a down-event, read and include the
774 ;; corresponding up-event. Note that there are also
775 ;; down-events on scroll bars and mode lines: the actual
776 ;; event then is in the second element of the vector.
777 (and (vectorp key)
778 (let ((last-idx (1- (length key))))
779 (and (eventp (aref key last-idx))
780 (memq 'down (event-modifiers (aref key last-idx)))))
781 (or (and (eventp (aref key 0))
782 (memq 'down (event-modifiers (aref key 0)))
783 ;; However, for the C-down-mouse-2 popup
784 ;; menu, there is no subsequent up-event. In
785 ;; this case, the up-event is the next
786 ;; element in the supplied vector.
787 (= (length key) 1))
788 (and (> (length key) 1)
789 (eventp (aref key 1))
790 (memq 'down (event-modifiers (aref key 1)))))
791 (read-event))))
792 ;; Put yank-menu back as it was, if we changed it.
793 (when saved-yank-menu
794 (setq yank-menu (copy-sequence saved-yank-menu))
795 (fset 'yank-menu (cons 'keymap yank-menu))))))
796 (if (numberp untranslated)
797 (setq untranslated (this-single-command-raw-keys)))
798 (let* ((event (aref key (if (and (symbolp (aref key 0))
799 (> (length key) 1)
800 (consp (aref key 1)))
801 1
802 0)))
803 (modifiers (event-modifiers event))
804 (mouse-msg (if (or (memq 'click modifiers) (memq 'down modifiers)
805 (memq 'drag modifiers)) " at that spot" ""))
806 (defn (key-binding key t))
807 key-locus key-locus-up key-locus-up-tricky
808 defn-up defn-up-tricky ev-type
809 mouse-1-remapped mouse-1-tricky)
810
811 ;; Handle the case where we faked an entry in "Select and Paste" menu.
812 (when (and (eq defn nil)
813 (stringp (aref key (1- (length key))))
814 (eq (key-binding (substring key 0 -1)) 'yank-menu))
815 (setq defn 'menu-bar-select-yank))
816 (if (or (null defn) (integerp defn) (equal defn 'undefined))
817 (message "%s%s is undefined"
818 (help-key-description key untranslated) mouse-msg)
819 (help-setup-xref (list #'describe-function defn) 788 (help-setup-xref (list #'describe-function defn)
820 (called-interactively-p 'interactive)) 789 (called-interactively-p 'interactive))
821 ;; Don't bother user with strings from (e.g.) the select-paste menu.
822 (when (stringp (aref key (1- (length key))))
823 (aset key (1- (length key)) "(any string)"))
824 (when (and untranslated
825 (stringp (aref untranslated (1- (length untranslated)))))
826 (aset untranslated (1- (length untranslated))
827 "(any string)"))
828 ;; Need to do this before erasing *Help* buffer in case event 790 ;; Need to do this before erasing *Help* buffer in case event
829 ;; is a mouse click in an existing *Help* buffer. 791 ;; is a mouse click in an existing *Help* buffer.
830 (when up-event 792 (when up-event
@@ -849,13 +811,12 @@ temporarily enables it to allow getting help on disabled items and buttons."
849 (aset sequence 0 'mouse-1) 811 (aset sequence 0 'mouse-1)
850 (setq defn-up-tricky (key-binding sequence nil nil (event-start up-event))) 812 (setq defn-up-tricky (key-binding sequence nil nil (event-start up-event)))
851 (setq key-locus-up-tricky (help--binding-locus sequence (event-start up-event)))))) 813 (setq key-locus-up-tricky (help--binding-locus sequence (event-start up-event))))))
852 (setq key-locus (help--binding-locus key (event-start event)))
853 (with-help-window (help-buffer) 814 (with-help-window (help-buffer)
854 (princ (help-key-description key untranslated)) 815 (princ brief-desc)
855 (princ (format "%s runs the command %S%s, which is " 816 (let ((key-locus (help--binding-locus key (event-start event))))
856 mouse-msg defn (if key-locus 817 (when key-locus
857 (format " (found in %s)" key-locus) 818 (princ (format " (found in %s)" key-locus))))
858 ""))) 819 (princ ", which is ")
859 (describe-function-1 defn) 820 (describe-function-1 defn)
860 (when up-event 821 (when up-event
861 (unless (or (null defn-up) 822 (unless (or (null defn-up)