diff options
Diffstat (limited to 'lisp/help-mode.el')
-rw-r--r-- | lisp/help-mode.el | 224 |
1 files changed, 138 insertions, 86 deletions
diff --git a/lisp/help-mode.el b/lisp/help-mode.el index ee68d253cb8..8b5e48edad1 100644 --- a/lisp/help-mode.el +++ b/lisp/help-mode.el @@ -31,22 +31,23 @@ (require 'cl-lib) -(defvar help-mode-map - (let ((map (make-sparse-keymap))) - (set-keymap-parent map (make-composed-keymap button-buffer-map - special-mode-map)) - (define-key map "l" 'help-go-back) - (define-key map "r" 'help-go-forward) - (define-key map "\C-c\C-b" 'help-go-back) - (define-key map "\C-c\C-f" 'help-go-forward) - (define-key map [XF86Back] 'help-go-back) - (define-key map [XF86Forward] 'help-go-forward) - (define-key map "\C-c\C-c" 'help-follow-symbol) - (define-key map "s" 'help-view-source) - (define-key map "i" 'help-goto-info) - (define-key map "c" 'help-customize) - map) - "Keymap for Help mode.") +(defvar-keymap help-mode-map + :doc "Keymap for Help mode." + :parent (make-composed-keymap button-buffer-map + special-mode-map) + "n" #'help-goto-next-page + "p" #'help-goto-previous-page + "l" #'help-go-back + "r" #'help-go-forward + "C-c C-b" #'help-go-back + "C-c C-f" #'help-go-forward + "<XF86Back>" #'help-go-back + "<XF86Forward>" #'help-go-forward + "C-c C-c" #'help-follow-symbol + "s" #'help-view-source + "I" #'help-goto-lispref-info + "i" #'help-goto-info + "c" #'help-customize) (easy-menu-define help-mode-menu help-mode-map "Menu for Help mode." @@ -265,7 +266,9 @@ The format is (FUNCTION ARGS...).") (let* ((location (find-function-search-for-symbol fun type file)) (position (cdr location))) - (pop-to-buffer (car location)) + (if help-window-keep-selected + (pop-to-buffer-same-window (car location)) + (pop-to-buffer (car location))) (run-hooks 'find-function-after-hook) (if position (progn @@ -273,6 +276,10 @@ The format is (FUNCTION ARGS...).") (when (or (< position (point-min)) (> position (point-max))) (widen)) + ;; Save mark for the old location, unless the point is not + ;; actually going to move. + (unless (= (point) position) + (push-mark nil t)) (goto-char position)) (message "Unable to find location in file"))))) @@ -287,7 +294,10 @@ The format is (FUNCTION ARGS...).") (setq file (locate-library file t)) (if (and file (file-readable-p file)) (progn - (pop-to-buffer (find-file-noselect file)) + (if help-window-keep-selected + (pop-to-buffer-same-window + (find-file-noselect file)) + (pop-to-buffer (find-file-noselect file))) (widen) (goto-char (point-min)) (if (re-search-forward @@ -306,7 +316,9 @@ The format is (FUNCTION ARGS...).") (setq file (help-C-file-name var 'var))) (let* ((location (find-variable-noselect var file)) (position (cdr location))) - (pop-to-buffer (car location)) + (if help-window-keep-selected + (pop-to-buffer-same-window (car location)) + (pop-to-buffer (car location))) (run-hooks 'find-function-after-hook) (if position (progn @@ -327,7 +339,9 @@ The format is (FUNCTION ARGS...).") (let* ((location (find-function-search-for-symbol fun 'defface file)) (position (cdr location))) - (pop-to-buffer (car location)) + (if help-window-keep-selected + (pop-to-buffer-same-window (car location)) + (pop-to-buffer (car location))) (if position (progn ;; Widen the buffer if necessary to go to this position. @@ -369,9 +383,18 @@ The format is (FUNCTION ARGS...).") :supertype 'help-xref 'help-function (lambda (file pos) - (view-buffer-other-window (find-file-noselect file)) + (if help-window-keep-selected + (view-buffer (find-file-noselect file)) + (view-buffer-other-window (find-file-noselect file))) (goto-char pos)) 'help-echo (purecopy "mouse-2, RET: show corresponding NEWS announcement")) + +;;;###autoload +(defun help-mode--add-function-link (str fun) + (make-text-button (copy-sequence str) nil + 'type 'help-function + 'help-args (list fun))) + (defvar bookmark-make-record-function) (defvar help-mode--current-data nil) @@ -379,7 +402,8 @@ The format is (FUNCTION ARGS...).") ;;;###autoload (define-derived-mode help-mode special-mode "Help" "Major mode for viewing help text and navigating references in it. -Entry to this mode runs the normal hook `help-mode-hook'. +Also see the `help-enable-variable-value-editing' variable. + Commands: \\{help-mode-map}" (setq-local revert-buffer-function @@ -389,17 +413,21 @@ Commands: help-mode-tool-bar-map) (setq-local help-mode--current-data nil) (setq-local bookmark-make-record-function - #'help-bookmark-make-record)) + #'help-bookmark-make-record) + (unless search-default-mode + (isearch-fold-quotes-mode))) ;;;###autoload (defun help-mode-setup () "Enter Help mode in the current buffer." + (declare (obsolete nil "29.1")) (help-mode) (setq buffer-read-only nil)) ;;;###autoload (defun help-mode-finish () "Finalize Help mode setup in current buffer." + (declare (obsolete nil "29.1")) (when (derived-mode-p 'help-mode) (setq buffer-read-only t) (help-make-xrefs (current-buffer)))) @@ -424,6 +452,7 @@ Commands: "\\(symbol\\|program\\|property\\)\\|" ; Don't link "\\(source \\(?:code \\)?\\(?:of\\|for\\)\\)\\)" "[ \t\n]+\\)?" + "\\(\\\\\\+\\)?" "['`‘]\\(\\(?:\\sw\\|\\s_\\)+\\|`\\)['’]")) "Regexp matching doc string references to symbols. @@ -484,17 +513,16 @@ restore it properly when going back." ;;;###autoload (defun help-buffer () "Return the name of a buffer for inserting help. -If `help-xref-following' is non-nil, this is the name of the -current buffer. Signal an error if this buffer is not derived -from `help-mode'. +If `help-xref-following' is non-nil and the current buffer is +derived from `help-mode', this is the name of the current buffer. + Otherwise, return \"*Help*\", creating a buffer with that name if it does not already exist." - (buffer-name ;for with-output-to-temp-buffer - (if (not help-xref-following) - (get-buffer-create "*Help*") - (unless (derived-mode-p 'help-mode) - (error "Current buffer is not in Help mode")) - (current-buffer)))) + (buffer-name ;for with-output-to-temp-buffer + (if (and help-xref-following + (derived-mode-p 'help-mode)) + (current-buffer) + (get-buffer-create "*Help*")))) (defvar describe-symbol-backends `((nil ,#'fboundp ,(lambda (s _b _f) (describe-function s))) @@ -513,6 +541,12 @@ Each element has the form (NAME TESTFUN DESCFUN) where: and a frame), inserts the description of that symbol in the current buffer and returns that text as well.") +(defcustom help-clean-buttons nil + "If non-nil, remove quotes around link buttons." + :version "29.1" + :type 'boolean + :group 'help) + ;;;###autoload (defun help-make-xrefs (&optional buffer) "Parse and hyperlink documentation cross-references in the given BUFFER. @@ -600,27 +634,28 @@ that." ;; Quoted symbols (save-excursion (while (re-search-forward help-xref-symbol-regexp nil t) - (let* ((data (match-string 8)) - (sym (intern-soft data))) - (if sym - (cond - ((match-string 3) ; `variable' &c - (and (or (boundp sym) ; `variable' doesn't ensure + (when-let ((sym (intern-soft (match-string 9)))) + (if (match-string 8) + (delete-region (match-beginning 8) + (match-end 8)) + (cond + ((match-string 3) ; `variable' &c + (and (or (boundp sym) ; `variable' doesn't ensure ; it's actually bound - (get sym 'variable-documentation)) - (help-xref-button 8 'help-variable sym))) - ((match-string 4) ; `function' &c - (and (fboundp sym) ; similarly - (help-xref-button 8 'help-function sym))) - ((match-string 5) ; `face' - (and (facep sym) - (help-xref-button 8 'help-face sym))) - ((match-string 6)) ; nothing for `symbol' - ((match-string 7) - (help-xref-button 8 'help-function-def sym)) - ((cl-some (lambda (x) (funcall (nth 1 x) sym)) - describe-symbol-backends) - (help-xref-button 8 'help-symbol sym))))))) + (get sym 'variable-documentation)) + (help-xref-button 9 'help-variable sym))) + ((match-string 4) ; `function' &c + (and (fboundp sym) ; similarly + (help-xref-button 9 'help-function sym))) + ((match-string 5) ; `face' + (and (facep sym) + (help-xref-button 9 'help-face sym))) + ((match-string 6)) ; nothing for `symbol' + ((match-string 7) + (help-xref-button 9 'help-function-def sym)) + ((cl-some (lambda (x) (funcall (nth 1 x) sym)) + describe-symbol-backends) + (help-xref-button 9 'help-symbol sym))))))) ;; An obvious case of a key substitution: (save-excursion (while (re-search-forward @@ -631,34 +666,7 @@ that." "\\<M-x\\s-+\\(\\sw\\(\\sw\\|\\s_\\)*\\sw\\)" nil t) (let ((sym (intern-soft (match-string 1)))) (if (fboundp sym) - (help-xref-button 1 'help-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. - - ;; If the keymap substitution isn't the last thing in - ;; the doc string, and if there is anything on the same - ;; line after it, this code won't recognize the end of it. - (while (re-search-forward "^key +binding\n\\(-+ +\\)-+\n\n" - nil t) - (let ((col (- (match-end 1) (match-beginning 1)))) - (while - (and (not (eobp)) - ;; Stop at a pair of blank lines. - (not (looking-at-p "\n\\s-*\n"))) - ;; Skip a single blank line. - (and (eolp) (forward-line)) - (end-of-line) - (skip-chars-backward "^ \t\n") - (if (and (>= (current-column) col) - (looking-at "\\(\\sw\\|\\s_\\)+$")) - (let ((sym (intern-soft (match-string 0)))) - (if (fboundp sym) - (help-xref-button 0 'help-function sym)))) - (forward-line)))))) + (help-xref-button 1 'help-function sym)))))) (set-syntax-table stab)) ;; Delete extraneous newlines at the end of the docstring (goto-char (point-max)) @@ -687,12 +695,26 @@ that." MATCH-NUMBER is the subexpression of interest in the last matched regexp. TYPE is the type of button to use. Any remaining arguments are passed to the button's help-function when it is invoked. -See `help-make-xrefs'." +See `help-make-xrefs'. + +This function removes quotes surrounding the match if the +variable `help-clean-buttons' is non-nil." ;; Don't mung properties we've added specially in some instances. - (unless (button-at (match-beginning match-number)) - (make-text-button (match-beginning match-number) - (match-end match-number) - 'type type 'help-args args))) + (let ((beg (match-beginning match-number)) + (end (match-end match-number))) + (unless (button-at beg) + (make-text-button beg end 'type type 'help-args args) + (when (and help-clean-buttons + (> beg (point-min)) + (save-excursion + (goto-char (1- beg)) + (looking-at "['`‘]")) + (< end (point-max)) + (save-excursion + (goto-char end) + (looking-at "['’]"))) + (delete-region end (1+ end)) + (delete-region (1- beg) beg))))) ;;;###autoload (defun help-insert-xref-button (string type &rest args) @@ -795,6 +817,26 @@ See `help-make-xrefs'." (help-xref-go-forward (current-buffer)) (user-error "No next help buffer"))) +(defun help-goto-next-page () + "Go to the next page (if any) in the current buffer. +The help buffers are divided into \"pages\" by the ^L character." + (interactive nil help-mode) + (push-mark) + (forward-page) + (unless (eobp) + (forward-line 1))) + +(defun help-goto-previous-page () + "Go to the previous page (if any) in the current buffer. +(If not at the start of a page, go to the start of the current page.) + +The help buffers are divided into \"pages\" by the ^L character." + (interactive nil help-mode) + (push-mark) + (backward-page (if (looking-back "\f\n" (- (point) 5)) 2 1)) + (unless (bobp) + (forward-line 1))) + (defun help-view-source () "View the source of the current help item." (interactive nil help-mode) @@ -811,7 +853,16 @@ See `help-make-xrefs'." (unless help-mode--current-data (error "No symbol to look up in the current buffer")) (info-lookup-symbol (plist-get help-mode--current-data :symbol) - 'emacs-lisp-mode)) + 'emacs-lisp-mode + help-window-keep-selected)) + +(defun help-goto-lispref-info () + "View the Emacs Lisp manual *info* node of the current help item." + (interactive nil help-mode) + (unless help-mode--current-data + (error "No symbol to look up in the current buffer")) + (info-lookup-symbol (plist-get help-mode--current-data :symbol) + 'emacs-lisp-only)) (defun help-customize () "Customize variable or face whose doc string is shown in the current buffer." @@ -921,6 +972,7 @@ BOOKMARK is a bookmark name or a bookmark record." (pop-to-buffer "*Help*") (goto-char position))) +(put 'help-bookmark-jump 'bookmark-handler-type "Help") (provide 'help-mode) |