Download
(require 'help-mode)
(defvar help-forward-label)
(defvar help-xref-override-view-map)
(defun help-mode ()
"Major mode for viewing help text and navigating references in it.
Entry to this mode runs the normal hook `help-mode-hook'.
Commands:
\\{help-mode-map}"
(interactive)
(kill-all-local-variables)
(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)
(setq view-exit-action (lambda (buffer)
(or (window-minibuffer-p (selected-window))
(when (eq (window-buffer) (get-buffer "*Help*"))
(if (one-window-p t)
(delete-frame)
(delete-window))))))
(run-mode-hooks 'help-mode-hook))
(defun help-make-xrefs (&optional buffer)
"Parse and hyperlink documentation cross-references in the given BUFFER.
Find cross-reference information in a buffer and activate such cross
references for selection with `help-follow'. Cross-references have
the canonical form `...' and the type of reference may be
disambiguated by the preceding word(s) used in
`help-xref-symbol-regexp'. Faces only get cross-referenced if
preceded or followed by the word `face'. Variables without
variable documentation do not get cross-referenced, unless
preceded by the word `variable' or `option'.
If the variable `help-xref-mule-regexp' is non-nil, find also
cross-reference information related to multilingual environment
\(e.g., coding-systems). This variable is also used to disambiguate
the type of reference as the same way as `help-xref-symbol-regexp'.
A special reference `back' is made to return back through a stack of
help buffers. Variable `help-back-label' specifies the text for
that."
(interactive "b")
(with-current-buffer (or buffer (current-buffer))
(save-excursion
(goto-char (point-min))
(forward-paragraph)
(let ((old-modified (buffer-modified-p)))
(let ((stab (syntax-table))
(case-fold-search t)
(inhibit-read-only t))
(set-syntax-table emacs-lisp-mode-syntax-table)
(unwind-protect
(progn
(save-excursion
(while (re-search-forward help-xref-info-regexp nil t)
(let ((data (match-string 2)))
(save-match-data
(unless (string-match "^([^)]+)" data)
(setq data (concat "(emacs)" data)))
(setq data
(replace-regexp-in-string "[ \t\n]+" " " data t t)))
(help-xref-button 2 'help-info data))))
(save-excursion
(while (re-search-forward help-xref-url-regexp nil t)
(let ((data (match-string 1)))
(help-xref-button 1 'help-url data))))
(if help-xref-mule-regexp
(save-excursion
(while (re-search-forward help-xref-mule-regexp nil t)
(let* ((data (match-string 7))
(sym (intern-soft data)))
(cond
((match-string 3)
(and sym (coding-system-p sym)
(help-xref-button 6 'help-coding-system sym)))
((match-string 4)
(and (assoc data input-method-alist)
(help-xref-button 7 'help-input-method data)))
((or (match-string 5) (match-string 6))
(and sym (charsetp sym)
(help-xref-button 7 'help-character-set sym)))
((assoc data input-method-alist)
(help-xref-button 7 'help-character-set data))
((and sym (coding-system-p sym))
(help-xref-button 7 'help-coding-system sym))
((and sym (charsetp sym))
(help-xref-button 7 'help-character-set sym)))))))
(save-excursion
(while (re-search-forward help-xref-symbol-regexp nil t)
(let* ((data (match-string 8))
(sym (intern-soft data)))
(when sym
(cond
((or (and (or (boundp sym)
(get sym 'variable-documentation))
(fboundp sym))
(and (fboundp sym)
(facep sym))
(and (or (boundp sym)
(get sym 'variable-documentation))
(facep sym)))
(help-xref-button 8 'help-symbol sym))
((match-string 3)
(and (or (boundp sym)
(get sym 'variable-documentation))
(help-xref-button 8 'help-variable sym)))
((match-string 4)
(and (fboundp sym)
(help-xref-button 8 'help-function sym)))
((match-string 5)
(and (facep sym)
(help-xref-button 8 'help-face sym)))
((match-string 6))
((match-string 7)
(help-xref-button 8 'help-function-def sym))
((and
(facep sym)
(save-match-data (looking-at "[ \t\n]+face\\W")))
(help-xref-button 8 'help-face sym))
((and
(or (boundp sym)
(get sym 'variable-documentation))
(or
(documentation-property
sym 'variable-documentation)
(if (or (> emacs-major-version 24)
(and (= emacs-major-version 24)
(> emacs-minor-version 2)))
(documentation-property
(indirect-variable sym)
'variable-documentation)
(condition-case nil
(documentation-property
(indirect-variable sym)
'variable-documentation)
(cyclic-variable-indirection nil)))))
(help-xref-button 8 'help-variable sym))
((fboundp sym)
(help-xref-button 8 'help-function sym)))))))
(save-excursion
(while (re-search-forward
"\\<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)))))
(save-excursion
(goto-char (point-min))
(while (re-search-forward "^key +binding\n\\(-+ +\\)-+\n\n"
nil t)
(let ((col (- (match-end 1) (match-beginning 1))))
(while
(and (not (eobp))
(not (looking-at "\n\\s-*\n")))
(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))))))
(set-syntax-table stab))
(goto-char (point-max))
(while (and (not (bobp)) (bolp))
(delete-char -1))
(insert "\n")
(when (or help-xref-stack (and (boundp 'help-xref-forward-stack)
help-xref-forward-stack))
(insert "\n"))
(when help-xref-stack
(help-insert-xref-button help-back-label 'help-back
(current-buffer)))
(when (and (boundp 'help-xref-forward-stack) 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 (and (boundp 'help-xref-forward-stack)
help-xref-forward-stack))
(insert "\n")))
(when (< emacs-major-version 24)
(set (make-local-variable 'minor-mode-overriding-map-alist)
(list (cons 'view-mode help-xref-override-view-map))))
(when (or (> emacs-major-version 24)
(and (= emacs-major-version 24)
(> emacs-minor-version 2)))
(set-buffer-modified-p old-modified))))))
(defun help-xref-on-pp (from to)
"Add xrefs for symbols in `pp's output between FROM and TO."
(if (> (- to from) 5000) nil
(with-syntax-table emacs-lisp-mode-syntax-table
(save-excursion
(save-restriction
(narrow-to-region from to)
(goto-char (point-min))
(condition-case nil
(while (not (eobp))
(cond
((looking-at "\"") (forward-sexp 1))
((looking-at "#<") (search-forward ">" nil 'move))
((looking-at "\\(\\(\\sw\\|\\s_\\)+\\)")
(let* ((sym (intern-soft (match-string 1)))
(type (cond ((fboundp sym) 'help-function)
((or (memq sym '(t nil))
(keywordp sym))
nil)
((and sym (boundp sym))
'help-variable)
((and sym (locate-library (symbol-name sym)))
'help-library))))
(when type (help-xref-button 1 type sym)))
(goto-char (match-end 1)))
(t (forward-char 1))))
(error nil)))))))
(define-button-type 'help-library
:supertype 'help-xref
'help-function #'(lambda (x) (find-library (symbol-name x)))
'help-echo (purecopy "mouse-2, RET: find this library"))
(provide 'help-mode+)