(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'.
-An element looks like (POSITION FUNCTION ARGS...).
-To use the element, do (apply FUNCTION ARGS) then (goto-char POSITION).")
+An element looks like (POSITION FUNCTION ARGS...), where POSITION is
+`(POINT . BUFFER-NAME)'.
+To use the element, do (apply FUNCTION ARGS) then goto the point in
+the named buffer.")
(put 'help-xref-stack 'permanent-local t)
(defvar help-xref-stack-item nil
(funcall (or function 'message)
(concat
(if first-message
- (substitute-command-keys first-message)
- "")
- (if first-message " " "")
+ (substitute-command-keys first-message))
+ (if first-message " ")
;; If the help buffer will go in a separate frame,
;; it's no use mentioning a command to scroll, so don't.
(if (special-display-p (buffer-name standard-output))
;; Document a minor mode if it is listed in minor-mode-alist,
;; bound locally in this buffer, non-nil, and has a function
;; definition.
- (if (and (symbol-value minor-mode)
+ (if (and (boundp minor-mode)
+ (symbol-value minor-mode)
(fboundp minor-mode))
(let ((pretty-minor-mode minor-mode))
(if (string-match "-mode$" (symbol-name minor-mode))
"Display the Emacs Frequently Asked Questions (FAQ) file."
(interactive)
;;; (find-file-read-only (expand-file-name "FAQ" data-directory))
- (info "(emacs-faq)"))
+ (info "(efaq)"))
(defun view-emacs-problems ()
"Display info on known problems with Emacs and possible workarounds."
(vectorp def))
"a keyboard macro")
((subrp def)
- (concat beg "built-in function"))
+ (if (eq 'unevalled (cdr (subr-arity def)))
+ (concat beg "special form")
+ (concat beg "built-in function")))
((byte-code-function-p def)
(concat beg "compiled Lisp function"))
((symbolp def)
(if doc
(progn (terpri)
(princ doc)
- (with-current-buffer standard-output
- (beginning-of-line)
- ;; Builtins get the calling sequence at the end of
- ;; the doc string. Move it to the same place as
- ;; for other functions.
- (when (looking-at (format "(%S[ )]" function))
- (let ((start (point-marker)))
- (goto-char (point-min))
- (forward-paragraph)
- (insert-buffer-substring (current-buffer) start)
- (insert ?\n)
- (delete-region (1- start) (point-max))
- (goto-char (point-max)))))
+ (if (subrp (symbol-function function))
+ (with-current-buffer standard-output
+ (beginning-of-line)
+ ;; Builtins get the calling sequence at the end of
+ ;; the doc string. Move it to the same place as
+ ;; for other functions.
+
+ ;; In cases where `function' has been fset to a
+ ;; subr we can't search for function's name in
+ ;; the doc string. Kluge round that using the
+ ;; printed representation. The arg list then
+ ;; shows the wrong function name, but that
+ ;; might be a useful hint.
+ (let* ((rep (prin1-to-string def))
+ (name (progn
+ (string-match " \\([^ ]+\\)>$" rep)
+ (match-string 1 rep))))
+ (if (looking-at (format "(%s[ )]" name))
+ (let ((start (point-marker)))
+ (goto-char (point-min))
+ (forward-paragraph)
+ (insert-buffer-substring (current-buffer) start)
+ (insert ?\n)
+ (delete-region (1- start) (point-max)))
+ (goto-char (point-min))
+ (forward-paragraph)
+ (insert
+ "[Missing arglist. Please make a bug report.]\n")))
+ (goto-char (point-max))))
(help-setup-xref (list #'describe-function function)
interactive-p))
(princ "not documented")))))
((looking-at "#<") (search-forward ">" nil 'move))
((looking-at "\\(\\(\\sw\\|\\s_\\)+\\)")
(let* ((sym (intern-soft
- (buffer-substring (match-beginning 1) (match-end 1))))
+ (buffer-substring (match-beginning 1)
+ (match-end 1))))
(fn (cond ((fboundp sym) #'describe-function)
- ((and sym (boundp sym)) #'describe-variable))))
+ ((or (memq sym '(t nil))
+ (keywordp sym))
+ nil)
+ ((and sym (boundp sym))
+ #'describe-variable))))
(when fn (help-xref-button 1 fn sym)))
(goto-char (match-end 1)))
(t (forward-char 1))))))
(enable-recursive-minibuffers t)
val)
(setq val (completing-read (if (symbolp v)
- (format "Describe variable (default %s): " v)
+ (format
+ "Describe variable (default %s): " v)
"Describe variable: ")
obarray 'boundp t nil nil
(if (symbolp v) (symbol-name v))))
(set-buffer standard-output)
(if (> (count-lines (point-min) (point-max)) 10)
(progn
+ ;; Note that setting the syntax table like below
+ ;; makes forward-sexp move over a `'s' at the end
+ ;; of a symbol.
(set-syntax-table emacs-lisp-mode-syntax-table)
(goto-char (point-min))
(if valvoid
(forward-line 1)
(forward-sexp 1)
(delete-region (point) (progn (end-of-line) (point)))
- (insert "'s value is shown below.\n\n")
+ (insert " value is shown below.\n\n")
(save-excursion
(insert "\n\nValue:"))))))
(princ "Documentation:")
(save-excursion
(re-search-backward
(concat "\\(" customize-label "\\)") nil t)
- (help-xref-button 1 #'(lambda (v)
- (customize-variable v))
+ (help-xref-button 1 (lambda (v)
+ (if help-xref-stack
+ (pop help-xref-stack))
+ (customize-variable v))
variable
- "mouse-2, RET: customize variable")
- ))))
+ "mouse-2, RET: customize variable")))))
;; Make a hyperlink to the library if appropriate. (Don't
;; change the format of the buffer's initial line in case
;; anything expects the current format.)
t))
(let (result)
(catch 'answer
- (mapcar
+ (mapc
(lambda (dir)
- (mapcar
+ (mapc
(lambda (suf)
(let ((try (expand-file-name (concat library suf) dir)))
(and (file-readable-p try)
(defconst help-xref-symbol-regexp
(purecopy (concat "\\(\\<\\(\\(variable\\|option\\)\\|"
"\\(function\\|command\\)\\|"
+ "\\(face\\)\\|"
"\\(symbol\\)\\)\\s-+\\)?"
;; Note starting with word-syntax character:
"`\\(\\sw\\(\\sw\\|\\s_\\)+\\)'"))
(setq help-xref-stack nil))
(setq help-xref-stack-item item))
+(defvar help-xref-following nil
+ "Non-nil when following a help cross-reference.")
+
(defun help-make-xrefs (&optional buffer)
"Parse and hyperlink documentation cross-references in the given BUFFER.
;; Quoted symbols
(save-excursion
(while (re-search-forward help-xref-symbol-regexp nil t)
- (let* ((data (match-string 6))
+ (let* ((data (match-string 7))
(sym (intern-soft data)))
(if sym
(cond
(and (boundp sym) ; `variable' doesn't ensure
; it's actually bound
(help-xref-button
- 6 #'describe-variable sym
+ 7 #'describe-variable sym
"mouse-2, RET: describe this variable")))
((match-string 4) ; `function' &c
(and (fboundp sym) ; similarly
(help-xref-button
- 6 #'describe-function sym
+ 7 #'describe-function sym
"mouse-2, RET: describe this function")))
- ((match-string 5)) ; nothing for symbol
+ ((match-string 5) ; `face'
+ (and (facep sym)
+ (help-xref-button 7 #'describe-face sym
+ "mouse-2, RET: describe this face")))
+ ((match-string 6)) ; nothing for symbol
((and (boundp sym) (fboundp sym))
;; We can't intuit whether to use the
;; variable or function doc -- supply both.
(help-xref-button
- 6 #'help-xref-interned sym
+ 7 #'help-xref-interned sym
"mouse-2, RET: describe this symbol"))
((boundp sym)
(help-xref-button
- 6 #'describe-variable sym
+ 7 #'describe-variable sym
"mouse-2, RET: describe this variable"))
((fboundp sym)
(help-xref-button
- 6 #'describe-function sym
- "mouse-2, RET: describe this function")))))))
+ 7 #'describe-function sym
+ "mouse-2, RET: describe this function"))
+ ((facep sym)
+ (help-xref-button
+ 7 #'describe-face sym)))))))
;; An obvious case of a key substitution:
(save-excursion
(while (re-search-forward
(zerop (forward-line)))))))))
(set-syntax-table stab))
;; Make a back-reference in this buffer if appropriate.
- (when help-xref-stack
+ (when (and help-xref-following help-xref-stack)
(goto-char (point-max))
(save-excursion
(insert "\n\n" help-back-label))
Both variable and function documentation are extracted into a single
help buffer."
- (let ((fdoc (when (fboundp symbol) (describe-function symbol))))
+ (let ((fdoc (when (fboundp symbol) (describe-function symbol)))
+ (facedoc (when (facep symbol) (describe-face symbol))))
(when (or (boundp symbol) (not fdoc))
(describe-variable symbol)
;; We now have a help buffer on the variable. Insert the function
;; text before it.
- (when fdoc
+ (when (or fdoc facedoc)
(with-current-buffer "*Help*"
(goto-char (point-min))
(let ((inhibit-read-only t))
- (insert fdoc "\n\n" (symbol-name symbol) " is also a variable.\n\n"))
+ (when fdoc
+ (insert fdoc "\n\n"))
+ (when facedoc
+ (insert (make-string 30 ?-) "\n\n" (symbol-name symbol)
+ " is also a " "face." "\n\n" facedoc "\n\n"))
+ (insert (make-string 30 ?-) "\n\n" (symbol-name symbol)
+ " is also a " "variable." "\n\n"))
(help-setup-xref (list #'help-xref-interned symbol) nil))))))
(defun help-xref-mode (buffer)
(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)
+ (setq item (pop help-xref-stack)
position (car item)
method (cadr item)
- args (cddr item))
- (setq help-xref-stack (cdr help-xref-stack))))
+ args (cddr item))))
(apply method args)
- ;; We're not in the right buffer to do this, and we don't actually
- ;; know which we should be in.
- ;;(goto-char position)
- ))
+ ;; We assume that the buffer we just recreated has the saved name,
+ ;; which might not always be true.
+ (when (get-buffer (cdr position))
+ (with-current-buffer (cdr position)
+ (goto-char (car position))))))
(defun help-go-back ()
"Invoke the [back] button (if any) in the Help mode buffer."
(method (car help-data))
(args (cdr help-data)))
(when help-data
- (setq help-xref-stack (cons (cons (point) help-xref-stack-item)
+ (setq help-xref-stack (cons (cons (cons pos (buffer-name))
+ help-xref-stack-item)
help-xref-stack))
(setq help-xref-stack-item nil)
;; There is a reference at point. Follow it.
- (apply method args))))
+ (let ((help-xref-following t))
+ (apply method args)))))
;; For tabbing through buffer.
(defun help-next-ref ()
(make-byte-code . "(make-byte-code &rest ELEMENTS)")
(call-process
. "(call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS)")
+ (call-process-region
+ . "(call-process-region START END PROGRAM &optional DELETE BUFFER DISPLAY &rest ARGS)")
(string . "(string &rest CHARACTERS)")
(+ . "(+ &rest NUMBERS-OR-MARKERS)")
(- . "(- &optional NUMBER-OR-MARKER &rest MORE-NUMBERS-OR-MARKERS)")
(catch . "(catch TAG BODY...)")
(unwind-protect . "(unwind-protect BODYFORM UNWINDFORMS...)")
(condition-case . "(condition-case VAR BODYFORM HANDLERS...)")
- (track-mouse . "(track-mouse BOFY ...)")
+ (track-mouse . "(track-mouse BODY ...)")
(ml-if . "(ml-if COND THEN ELSE...)")
(ml-provide-prefix-argument . "(ml-provide-prefix-argument ARG1 ARG2)")
(with-output-to-temp-buffer