(define-key help-map "F" 'view-emacs-FAQ)
(define-key help-map "i" 'info)
+(define-key help-map "4i" 'info-other-window)
(define-key help-map "\C-f" 'Info-goto-emacs-command-node)
(define-key help-map "\C-k" 'Info-goto-emacs-key-command-node)
(define-key help-map "\C-i" 'info-lookup-symbol)
(defvar help-xref-stack nil
"A stack of ways by which to return to help buffers after following xrefs.
-Used by `help-follow' and `help-xref-go-back'.")
+Used by `help-follow' and `help-xref-go-back'.
+An element looks like (POSITION FUNCTION ARGS...).
+To use the element, do (apply FUNCTION ARGS) then (goto-char POSITION).")
(put 'help-xref-stack 'permanent-local t)
(defvar help-xref-stack-item nil
- "An item for `help-follow' in this buffer to push onto `help-xref-stack'.")
+ "An item for `help-follow' in this buffer to push onto `help-xref-stack'.
+The format is (FUNCTION ARGS...).")
(put 'help-xref-stack-item 'permanent-local t)
(setq-default help-xref-stack nil help-xref-stack-item nil)
"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."
(interactive "kDescribe key briefly: \nP")
- ;; If this key seq ends with a down event, discard the
- ;; following click or drag event. Otherwise that would
- ;; erase the message.
- (let ((type (aref key (1- (length key)))))
- (if (listp type) (setq type (car type)))
- (and (symbolp type)
- (memq 'down (event-modifiers type))
- (read-event)))
(save-excursion
(let ((modifiers (event-modifiers (aref key 0)))
(standard-output (if insert (current-buffer) t))
(defun describe-key (key)
"Display documentation of the function invoked by KEY. KEY is a string."
(interactive "kDescribe key: ")
- ;; If this key seq ends with a down event, discard the
- ;; following click or drag event. Otherwise that would
- ;; erase the message.
- (let ((type (aref key (1- (length key)))))
- (if (listp type) (setq type (car type)))
- (and (symbolp type)
- (memq 'down (event-modifiers type))
- (read-event)))
(save-excursion
(let ((modifiers (event-modifiers (aref key 0)))
window position)
(princ mode-name)
(princ " mode:\n")
(princ (documentation major-mode))
- (help-setup-xref (cons #'help-xref-mode (current-buffer)) (interactive-p))
+ (help-setup-xref (list #'help-xref-mode (current-buffer)) (interactive-p))
(print-help-return-message)))
;; So keyboard macro definitions are documented correctly
((byte-code-function-p def)
(concat beg "compiled Lisp function"))
((symbolp def)
+ (while (symbolp (symbol-function def))
+ (setq def (symbol-function def)))
(format "alias for `%s'" def))
((eq (car-safe def) 'lambda)
(concat beg "Lisp function"))
(help-xref-button 1 #'(lambda (arg)
(let ((location
(find-function-noselect arg)))
- (display-buffer (nth 0 location))
- (goto-char (nth 1 location))))
+ (pop-to-buffer (car location))
+ (goto-char (cdr location))))
function)))))
(if need-close (princ ")"))
(princ ".")
(terpri)
- (let* ((inner-function (if (and (listp def) 'macro)
- (cdr def)
- def))
- (arglist (cond ((byte-code-function-p inner-function)
- (car (append inner-function nil)))
- ((eq (car-safe inner-function) 'lambda)
- (nth 1 inner-function))
- (t t))))
+ ;; Handle symbols aliased to other symbols.
+ (setq def (indirect-function def))
+ ;; If definition is a macro, find the function inside it.
+ (if (eq (car-safe def) 'macro)
+ (setq def (cdr def)))
+ (let ((arglist (cond ((byte-code-function-p def)
+ (car (append def nil)))
+ ((eq (car-safe def) 'lambda)
+ (nth 1 def))
+ (t t))))
(if (listp arglist)
(progn
(princ (cons function
(if doc
(progn (terpri)
(princ doc)
- (help-setup-xref (cons #'describe-function function) (interactive-p)))
+ (help-setup-xref (list #'describe-function function) (interactive-p)))
(princ "not documented")))))
;; We return 0 if we can't find a variable to return.
(terpri)
(let ((doc (documentation-property variable 'variable-documentation)))
(princ (or doc "not documented as a variable.")))
- (help-setup-xref (cons #'describe-variable variable) (interactive-p))
+ (help-setup-xref (list #'describe-variable variable) (interactive-p))
;; Make a link to customize if this variable can be customized.
- (if (or (get variable 'custom-type)
- (user-variable-p variable))
+ ;; Note, it is not reliable to test for a custom-type property
+ ;; because those are only present after the var's definition
+ ;; has been loaded.
+ (if (user-variable-p variable)
(let ((customize-label "customize"))
(terpri)
(terpri)
(buffer-string))))
(message "You did not specify a variable")))
-(defun describe-bindings (&optional prefix)
+(defun describe-bindings (&optional prefix buffer)
"Show a list of all defined keys, and their definitions.
We put that list in a buffer, and display the buffer.
The optional argument PREFIX, if non-nil, should be a key sequence;
-then we display only bindings that start with that prefix."
+then we display only bindings that start with that prefix.
+The optional argument BUFFER specifies which buffer's bindings
+to display (default, the current buffer)."
(interactive "P")
- (describe-bindings-internal nil prefix)
+ (or buffer (setq buffer (current-buffer)))
+ (with-current-buffer buffer
+ (describe-bindings-internal nil prefix))
(with-current-buffer "*Help*"
- (setq help-xref-stack nil
- help-xref-stack-item nil)))
+ (help-setup-xref (list #'describe-bindings prefix buffer)
+ (interactive-p))))
(defun where-is (definition &optional insert)
"Print message listing key sequences that invoke specified command.
(defun help-setup-xref (item interactive-p)
"Invoked from commands using the \"*Help*\" buffer to install some xref info.
-ITEM is a (function . args) pair appropriate for recreating the help
+ITEM is a (FUNCTION . ARGS) pair appropriate for recreating the help
buffer after following a reference. INTERACTIVE-P is non-nil if the
calling command was invoked interactively. In this case the stack of
items for help buffer \"back\" buttons is cleared."
(help-xref-button 1 #'describe-function sym)))))
;; Look for commands in whole keymap substitutions:
(save-excursion
+ ;; Make sure to find the first keymap.
+ (goto-char (point-min))
;; Find a header and the column at which the command
;; name will be found.
(while (re-search-forward "^key +binding\n\\(-+ +\\)-+\n\n"
(goto-char (point-max))
(insert "\n\n" fdoc))
(goto-char (point-min))
- (help-setup-xref (cons #'help-xref-interned symbol) nil))
+ (help-setup-xref (list #'help-xref-interned symbol) nil))
(defun help-xref-mode (buffer)
"Do a `describe-mode' for the specified BUFFER."
(defun help-follow-mouse (click)
"Follow the cross-reference that you click on."
(interactive "e")
- (save-excursion
- (let* ((start (event-start click))
- (window (car start))
- (pos (car (cdr start))))
- (set-buffer (window-buffer window))
+ (let* ((start (event-start click))
+ (window (car start))
+ (pos (car (cdr start))))
+ (with-current-buffer (window-buffer window)
(help-follow pos))))
(defun help-xref-go-back (buffer)
"Go back to the previous help buffer text using info on `help-xref-stack'."
(interactive)
- (let (item method args)
+ (let (item position method args)
(with-current-buffer buffer
(when help-xref-stack
(setq help-xref-stack (cdr help-xref-stack)) ; due to help-follow
(setq item (car help-xref-stack)
- method (car item)
- args (cdr item))
+ position (car item)
+ method (cadr item)
+ args (cddr item))
(setq help-xref-stack (cdr help-xref-stack))))
- (if (listp args)
- (apply method args)
- (funcall method args))))
+ (apply method args)
+ (goto-char position)))
(defun help-go-back ()
(interactive)
For the cross-reference format, see `help-make-xrefs'."
(interactive "d")
- (let* ((help-data (get-text-property pos 'help-xref))
+ (let* ((help-data (or (and (not (= pos (point-max)))
+ (get-text-property pos 'help-xref))
+ (and (not (= pos (point-min)))
+ (get-text-property (1- pos) 'help-xref))))
(method (car help-data))
(args (cdr help-data)))
- (setq help-xref-stack (cons help-xref-stack-item help-xref-stack))
+ (setq help-xref-stack (cons (cons (point) help-xref-stack-item)
+ help-xref-stack))
(setq help-xref-stack-item nil)
(when help-data
;; There is a reference at point. Follow it.