X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/d4717700cc0b7af6197c19e22bd912e3b1ed67ee..f23d76bdefbd4c06e14d69e99e50d35ce91c8226:/lisp/help-mode.el diff --git a/lisp/help-mode.el b/lisp/help-mode.el index 9462153515..bca0b5b65e 100644 --- a/lisp/help-mode.el +++ b/lisp/help-mode.el @@ -1,7 +1,7 @@ ;;; help-mode.el --- `help-mode' used by *Help* buffers ;; Copyright (C) 1985, 1986, 1993, 1994, 1998, 1999, 2000, 2001, 2002, -;; 2003, 2004, 2005, 2006 Free Software Foundation, Inc. +;; 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. ;; Maintainer: FSF ;; Keywords: help, internal @@ -10,7 +10,7 @@ ;; GNU Emacs is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2, or (at your option) +;; the Free Software Foundation; either version 3, or (at your option) ;; any later version. ;; GNU Emacs is distributed in the hope that it will be useful, @@ -40,6 +40,7 @@ (define-key help-mode-map [mouse-2] 'help-follow-mouse) (define-key help-mode-map "\C-c\C-b" 'help-go-back) +(define-key help-mode-map "\C-c\C-f" 'help-go-forward) (define-key help-mode-map "\C-c\C-c" 'help-follow-symbol) ;; Documentation only, since we use minor-mode-overriding-map-alist. (define-key help-mode-map "\r" 'help-follow) @@ -52,13 +53,28 @@ To use the element, do (apply FUNCTION ARGS) then goto the point.") (put 'help-xref-stack 'permanent-local t) (make-variable-buffer-local 'help-xref-stack) +(defvar help-xref-forward-stack nil + "The stack of used to navigate help forwards after using the back button. +Used by `help-follow' and `help-xref-go-forward'. +An element looks like (POSITION FUNCTION ARGS...). +To use the element, do (apply FUNCTION ARGS) then goto the point.") +(put 'help-xref-forward-stack 'permanent-local t) +(make-variable-buffer-local 'help-xref-forward-stack) + (defvar help-xref-stack-item nil "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) (make-variable-buffer-local 'help-xref-stack-item) +(defvar help-xref-stack-forward-item nil + "An item for `help-go-back' to push onto `help-xref-forward-stack'. +The format is (FUNCTION ARGS...).") +(put 'help-xref-stack-forward-item 'permanent-local t) +(make-variable-buffer-local 'help-xref-stack-forward-item) + (setq-default help-xref-stack nil help-xref-stack-item nil) +(setq-default help-xref-forward-stack nil help-xref-forward-stack-item nil) (defcustom help-mode-hook nil "Hook run by `help-mode'." @@ -123,6 +139,11 @@ The format is (FUNCTION ARGS...).") 'help-function #'help-xref-go-back 'help-echo (purecopy "mouse-2, RET: go back to previous help buffer")) +(define-button-type 'help-forward + :supertype 'help-xref + 'help-function #'help-xref-go-forward + 'help-echo (purecopy "mouse-2, RET: move forward to next help buffer")) + (define-button-type 'help-info :supertype 'help-xref 'help-function #'info @@ -157,7 +178,9 @@ The format is (FUNCTION ARGS...).") (let ((location (find-function-search-for-symbol fun nil file))) (pop-to-buffer (car location)) - (goto-char (cdr location)))) + (if (cdr location) + (goto-char (cdr location)) + (message "Unable to find location in file")))) 'help-echo (purecopy "mouse-2, RET: find function's definition")) (define-button-type 'help-variable-def @@ -167,8 +190,10 @@ The format is (FUNCTION ARGS...).") (setq file (help-C-file-name var 'var))) (let ((location (find-variable-noselect var file))) (pop-to-buffer (car location)) - (goto-char (cdr location)))) - 'help-echo (purecopy"mouse-2, RET: find variable's definition")) + (if (cdr location) + (goto-char (cdr location)) + (message "Unable to find location in file")))) + 'help-echo (purecopy "mouse-2, RET: find variable's definition")) (define-button-type 'help-face-def :supertype 'help-xref @@ -179,7 +204,9 @@ The format is (FUNCTION ARGS...).") (let ((location (find-function-search-for-symbol fun 'defface file))) (pop-to-buffer (car location)) - (goto-char (cdr location)))) + (if (cdr location) + (goto-char (cdr location)) + (message "Unable to find location in file")))) 'help-echo (purecopy "mouse-2, RET: find face's definition")) @@ -194,9 +221,22 @@ Commands: (use-local-map help-mode-map) (setq mode-name "Help") (setq major-mode 'help-mode) + (view-mode) - (make-local-variable 'view-no-disable-on-exit) - (setq view-no-disable-on-exit t) + (set (make-local-variable 'view-no-disable-on-exit) t) + ;; With Emacs 22 `view-exit-action' could delete the selected window + ;; disregarding whether the help buffer was shown in that window at + ;; all. Since `view-exit-action' is called with the help buffer as + ;; argument it seems more appropriate to have it work on the buffer + ;; only and leave it to `view-mode-exit' to delete any associated + ;; window(s). + (setq view-exit-action + (lambda (buffer) + ;; Use `with-current-buffer' to make sure that `bury-buffer' + ;; also removes BUFFER from the selected window. + (with-current-buffer buffer + (bury-buffer)))) + (run-mode-hooks 'help-mode-hook)) ;;;###autoload @@ -206,16 +246,23 @@ Commands: ;;;###autoload (defun help-mode-finish () - (let ((entry (assq (selected-window) view-return-to-alist))) - (if entry - ;; When entering Help mode from the Help window, - ;; such as by following a link, preserve the same - ;; meaning for the q command. - ;; (setcdr entry (cons (selected-window) help-return-method)) - nil - (setq view-return-to-alist - (cons (cons (selected-window) help-return-method) - view-return-to-alist)))) + (if (eq help-window t) + ;; If `help-window' is t, `view-return-to-alist' is handled by + ;; `with-help-window'. In this case set `help-window' to the + ;; selected window since now is the only moment where we can + ;; unambiguously identify it. + (setq help-window (selected-window)) + (let ((entry (assq (selected-window) view-return-to-alist))) + (if entry + ;; When entering Help mode from the Help window, + ;; such as by following a link, preserve the same + ;; meaning for the q command. + ;; (setcdr entry (cons (selected-window) help-return-method)) + nil + (setq view-return-to-alist + (cons (cons (selected-window) help-return-method) + view-return-to-alist))))) + (when (eq major-mode 'help-mode) ;; View mode's read-only status of existing *Help* buffer is lost ;; by with-output-to-temp-buffer. @@ -232,11 +279,14 @@ Commands: (defvar help-back-label (purecopy "[back]") "Label to use by `help-make-xrefs' for the go-back reference.") +(defvar help-forward-label (purecopy "[forward]") + "Label to use by `help-make-xrefs' for the go-forward reference.") + (defconst help-xref-symbol-regexp (purecopy (concat "\\(\\<\\(\\(variable\\|option\\)\\|" ; Link to var - "\\(function\\|command\\)\\|" ; Link to function - "\\(face\\)\\|" ; Link to face - "\\(symbol\\|program\\)\\|" ; Don't link + "\\(function\\|command\\)\\|" ; Link to function + "\\(face\\)\\|" ; Link to face + "\\(symbol\\|program\\|property\\)\\|" ; Don't link "\\(source \\(?:code \\)?\\(?:of\\|for\\)\\)\\)" "[ \t\n]+\\)?" ;; Note starting with word-syntax character: @@ -276,7 +326,8 @@ because we want to record the \"previous\" position of point so we can restore it properly when going back." (with-current-buffer (help-buffer) (when help-xref-stack-item - (push (cons (point) help-xref-stack-item) help-xref-stack)) + (push (cons (point) help-xref-stack-item) help-xref-stack) + (setq help-xref-forward-stack nil)) (when interactive-p (let ((tail (nthcdr 10 help-xref-stack))) ;; Truncate the stack. @@ -286,6 +337,7 @@ restore it properly when going back." (defvar help-xref-following nil "Non-nil when following a help cross-reference.") +;;;###autoload (defun help-buffer () (buffer-name ;for with-output-to-temp-buffer (if help-xref-following @@ -426,9 +478,11 @@ that." ;; An obvious case of a key substitution: (save-excursion (while (re-search-forward - ;; Assume command name is only word characters - ;; and dashes to get things like `use M-x foo.'. - "\\bar'. + ;; Command required to end with word constituent + ;; to avoid `.' at end of a sentence. + "\\= (current-column) col) - (looking-at "\\(\\sw\\|-\\)+$")) + (looking-at "\\(\\sw\\|\\s_\\)+$")) (let ((sym (intern-soft (match-string 0)))) (if (fboundp sym) (help-xref-button 0 'help-function sym)))) @@ -465,11 +519,19 @@ that." (while (and (not (bobp)) (bolp)) (delete-char -1)) (insert "\n") + (when (or help-xref-stack help-xref-forward-stack) + (insert "\n")) ;; Make a back-reference in this buffer if appropriate. (when help-xref-stack - (insert "\n") (help-insert-xref-button help-back-label 'help-back - (current-buffer)) + (current-buffer))) + ;; Make a forward-reference in this buffer if appropriate. + (when help-xref-forward-stack + (when help-xref-stack + (insert "\t")) + (help-insert-xref-button help-forward-label 'help-forward + (current-buffer))) + (when (or help-xref-stack help-xref-forward-stack) (insert "\n"))) ;; View mode steals RET from us. (set (make-local-variable 'minor-mode-overriding-map-alist) @@ -588,6 +650,7 @@ help buffer." "From BUFFER, go back to previous help buffer text using `help-xref-stack'." (let (item position method args) (with-current-buffer buffer + (push (cons (point) help-xref-stack-item) help-xref-forward-stack) (when help-xref-stack (setq item (pop help-xref-stack) ;; Clear the current item so that it won't get pushed @@ -603,6 +666,26 @@ help buffer." (set-window-point (get-buffer-window buffer) position) (goto-char position))))) +(defun help-xref-go-forward (buffer) + "From BUFFER, go forward to next help buffer." + (let (item position method args) + (with-current-buffer buffer + (push (cons (point) help-xref-stack-item) help-xref-stack) + (when help-xref-forward-stack + (setq item (pop help-xref-forward-stack) + ;; Clear the current item so that it won't get pushed + ;; by the function we're about to call. TODO: We could also + ;; push it onto a "forward" stack and add a `forw' button. + help-xref-stack-item nil + position (car item) + method (cadr item) + args (cddr item)))) + (apply method args) + (with-current-buffer buffer + (if (get-buffer-window buffer) + (set-window-point (get-buffer-window buffer) position) + (goto-char position))))) + (defun help-go-back () "Go back to previous topic in this help buffer." (interactive) @@ -610,6 +693,13 @@ help buffer." (help-xref-go-back (current-buffer)) (error "No previous help buffer"))) +(defun help-go-forward () + "Go back to next topic in this help buffer." + (interactive) + (if help-xref-forward-stack + (help-xref-go-forward (current-buffer)) + (error "No next help buffer"))) + (defun help-do-xref (pos function args) "Call the help cross-reference function FUNCTION with args ARGS. Things are set up properly so that the resulting help-buffer has