From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: "H. Dieter Wilhelm" Newsgroups: gmane.emacs.bugs Subject: bug#60587: Patch for adding links to symbols' help documentation Date: Wed, 25 Jan 2023 22:29:31 +0100 Message-ID: <86wn5anw04.fsf@duenenhof-wilhelm.de> References: <86y1qgr1bf.fsf@duenenhof-wilhelm.de> <86tu13qydg.fsf@duenenhof-wilhelm.de> <83h6x2u74b.fsf@gnu.org> <863588rfos.fsf@duenenhof-wilhelm.de> <83o7qw0yjy.fsf@gnu.org> <864jskx6a8.fsf@duenenhof-wilhelm.de> <831qnomh6l.fsf@gnu.org> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="11972"; mail-complaints-to="usenet@ciao.gmane.io" User-Agent: Gnus/5.13 (Gnus v5.13) Cc: 60587@debbugs.gnu.org, monnier@iro.umontreal.ca To: Eli Zaretskii Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Wed Jan 25 22:31:23 2023 Return-path: Envelope-to: geb-bug-gnu-emacs@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1pKnMZ-0002wi-0N for geb-bug-gnu-emacs@m.gmane-mx.org; Wed, 25 Jan 2023 22:31:23 +0100 Original-Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1pKnML-0003bR-MA; Wed, 25 Jan 2023 16:31:09 -0500 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1pKnMF-0003b8-DE for bug-gnu-emacs@gnu.org; Wed, 25 Jan 2023 16:31:05 -0500 Original-Received: from debbugs.gnu.org ([209.51.188.43]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1pKnMF-0002nJ-17 for bug-gnu-emacs@gnu.org; Wed, 25 Jan 2023 16:31:03 -0500 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1pKnME-0006PO-HD for bug-gnu-emacs@gnu.org; Wed, 25 Jan 2023 16:31:02 -0500 X-Loop: help-debbugs@gnu.org Resent-From: "H. Dieter Wilhelm" Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Wed, 25 Jan 2023 21:31:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 60587 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: patch Original-Received: via spool by 60587-submit@debbugs.gnu.org id=B60587.167468221424576 (code B ref 60587); Wed, 25 Jan 2023 21:31:02 +0000 Original-Received: (at 60587) by debbugs.gnu.org; 25 Jan 2023 21:30:14 +0000 Original-Received: from localhost ([127.0.0.1]:60106 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1pKnLR-0006OH-HV for submit@debbugs.gnu.org; Wed, 25 Jan 2023 16:30:14 -0500 Original-Received: from mout.kundenserver.de ([212.227.126.135]:38723) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1pKnLN-0006Mw-JY for 60587@debbugs.gnu.org; Wed, 25 Jan 2023 16:30:11 -0500 Original-Received: from ping ([109.250.147.186]) by mrelayeu.kundenserver.de (mreue009 [212.227.15.167]) with ESMTPSA (Nemesis) id 1MkpjD-1oxquB0uBb-00mOVy; Wed, 25 Jan 2023 22:29:32 +0100 In-Reply-To: <831qnomh6l.fsf@gnu.org> (Eli Zaretskii's message of "Sat, 21 Jan 2023 10:21:22 +0200") X-Provags-ID: V03:K1:oEv3R7dutNh1F71+OL789ZfwiXKqHp9iqD3lLKNleWs64tncMkb wxmGyK1X4jpdqa/iJyMXidWA+9g+E/AIzqIUSqjOYY0+zgVLu4SpVS9SUafnRQADX/ynW3q x3FWDT/Y/Cej2ATuf7T5fiYmEdIG3FQU4cQmxqvXQFYQ+6Jzms9vQgJ5l2reRGPtbLxRO/F kbW0lqFSJwVaWcC16oyXw== UI-OutboundReport: notjunk:1;M01:P0:H3yz6p87gb0=;Ctl+B8pEEWN7tt/J7F+Qt654UVa /WdLos08A7jyEILPV/OCx5yrNdRp897HJs87vPolUYte7RqyCzp5YmqjZW2QJP0vesam3K9tI hjyf3Ba8GEcqVl9sZKuwM9vUtoWuR3rKK2Qw4rU9kiWhF6SQoJ4BiLBXo0yF6TjKNQhsa/Y2d QQGKLBZHFFGFGwtje8VBa0IIEHFK9feDdCjh1FKpf8okiaD3UNUBDgEbNU3DqLm7HcfBvRwr1 Pau7BCEYsdFARbl8m8xBniM+vWPAS7r3+tDSVLrYT3Zfy4KY54xjMFG9Wm5dCF6GZ77mwpyky ZyY8M81AbRVAArqdbaB5bvW42JBgGJtWCE9zcYVhbmyOjEgNw2nKOwsO2MI/3GhWfq73jbNue uUMrvX9mws9PdwlO6Tp6Hl2fB2sk1IwEnzGiw/h7NsroiHd+rItHp2wG3C5l3fwD0TQAV9gph pQchVNc6c7W7VMkpfk+9TJ7a0UVsY7TQx0hEonVlUIAtNZD0mkwqb7JQIiVpvQiUIL691F4Dl SUjzK63+6/auWyK5CFDh3emuk71f2I7EQG3cQeLqIbIY+5ggD0TCB4nYljFOOIuItiOaHPCvk IGGNOsI2ZVn6JzHUrOYTg+93YcAP6PFC8rmvJ9DRnptjqPYHHi+Ckzya9dDBw7iTp5jzye7qg dMOQTHIs8wN2PtaPeJgi7niAPcs642k+ewH23W5ccA== X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-BeenThere: bug-gnu-emacs@gnu.org List-Id: "Bug reports for GNU Emacs, the Swiss army knife of text editors" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Original-Sender: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Xref: news.gmane.io gmane.emacs.bugs:254156 Archived-At: --=-=-= Content-Type: text/plain Eli Zaretskii writes: >> Unfortunately I also need to investigate the code anew. Yesterday I >> realised a regression starting with Emacs-29! `Tab' and `S-Tab' aren't >> working any longer for Info references. (E.g. the `Tab' keybinding is >> switched from `Info-next-reference' to `forward-button'..) > > So I guess you will be submitting a new patch soon? Below it is (based on a recent master commit). > I think the first sentence should be rewritten as describing a > separate feature, not "the same as" something else. Just say that > symbols are converted into buttons that lead to their doc strings. > > Also, the option which controls this should be mentioned and indexed. Please have a look at a further documentation patch. --=-=-= Content-Type: text/x-diff Content-Disposition: inline; filename=0001-Documentation-of-Info-providing-buttons-on-quoted-sy.patch >From 2e1f604c0923d39bbbc9314903622b92b3118830 Mon Sep 17 00:00:00 2001 From: Dieter Wilhelm Date: Mon, 23 Jan 2023 21:13:54 +0100 Subject: [PATCH] Documentation of Info providing buttons on quoted symbols (bug#60587) *etc/NEWS: Mention implementation *doc/emacs/help.texi: Describe implementation and how to switch off button creation --- doc/emacs/help.texi | 13 +++++++++++++ etc/NEWS | 11 +++++++++++ 2 files changed, 24 insertions(+) diff --git a/doc/emacs/help.texi b/doc/emacs/help.texi index 2513e6be271..02b8962c360 100644 --- a/doc/emacs/help.texi +++ b/doc/emacs/help.texi @@ -653,6 +653,19 @@ Misc Help K @var{key}}, described above, enter Info and go straight to the documentation of @var{function} or @var{key}. + In Info buffers quoted symbol names are made into buttons which show +the symbols' help documentation when typing @key{RET} or clicking +@kbd{mouse-2} or @kbd{mouse-1} on it. For example, the quoted name +@code{info-other-window} is made into a button which shows the +function's documentation string in another window, in the +@file{*Help*} buffer. Such quoted symbols (variables, functions and +face names) are highlighted by a distinct face and can be reached, as +the Info manual references, with @key{TAB} and @kbd{S-Tab}. + +@vindex info-make-xref-flag + If you want to prohibit the button creation for Info buffers, you +can set @code{info-make-xref-flag} to @code{nil}. + @kindex C-h S @findex info-lookup-symbol When editing a program, if you have an Info version of the manual diff --git a/etc/NEWS b/etc/NEWS index 5b8ab06086c..c55d39baf0c 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -195,6 +195,17 @@ This command adds a docstring comment to the current defun. If a comment already exists, point is only moved to the comment. It is bound to 'C-c C-d' in 'go-ts-mode'. +** Info + ++++ +*** Info-mode provides buttons on symbols showing their documentation string. +Quoted `symbols', like names of variables, functions or face names, +are made into buttons which can display the respective documentation +strings. These strings are presented in *Help* buffers in another +window. Such buttons are working independently of the regular Info +cross references and can be disabled with setting +`info-make-xref-flag' to nil. + * New Modes and Packages in Emacs 30.1 -- 2.34.1 --=-=-= Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename=0001-Info-providing-buttons-on-quoted-symbols-bug-60587.patch Content-Transfer-Encoding: quoted-printable >From f0d2f389d8b1967a2b14e297069aedad06e1c7e8 Mon Sep 17 00:00:00 2001 From: Dieter Wilhelm Date: Wed, 25 Jan 2023 22:00:57 +0100 Subject: [PATCH] Info providing buttons on quoted symbols (bug#60587) *lisp/info.el --- lisp/info.el | 397 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 397 insertions(+) diff --git a/lisp/info.el b/lisp/info.el index 035dff66e75..48ce78ac1e2 100644 --- a/lisp/info.el +++ b/lisp/info.el @@ -5510,6 +5510,403 @@ info--manual-names Info-directory-list (mapcar #'car Info-suffix-list)))))))) =20 + +;;; Commentary: + +;; The code below provides links of symbols (functions, variables, and +;; faces) within Emacs' Info viewer to their builtin help +;; documentation. This linking is done when symbol names in texinfo +;; documentation (like the Emacs- and Elisp manual) are: + +;; 1. Quoted symbol names like `quoted-symbol' or: + +;; 2. Function names which are prefixed by M-x, for example M-x +;; function-name or are quoted and prefixed, like `M-x function-name'. + +;; 3. Function names appearing behind the following forms, which +;; occur, for example, in the Elisp manual: + +;; -- Special Form: function-name +;; -- Command: ... +;; -- Function: ... +;; -- Macro: ... + +;; 4. And variables names behind the following text: + +;; -- User Option: variable-name +;; -- Variable: ... + +;; In any case all symbol names must be known to Emacs, which means it +;; is either a built-in, or its Lisp package is loaded for the current +;; Emacs session, or the symbol is auto-loaded. + +;; You can follow the additional links with the usual Info +;; keybindings. The customisation variable +;; `mouse-1-click-follows-link' is influencing the clicking behavior +;; (and tooltips) of the links, the variable's default is 450 (milli +;; seconds) setting it to nil means only clicking with mouse-2 is +;; following the link (hint: Drew Adams). + +;; The link color of symbols - referencing their builtin documentation +;; - is distinct from links which are referencing further Info +;; documentation. + +;; Below code is checking if Info documents are relevant Elisp and +;; Emacs related files to avoid false positives. Please see the +;; customization variable `info-none-emacs-or-elisp-documents'. + +;; The code uses mostly mechanisms from Emacs' lisp/help-mode.el file. + + +;;; Code: + +(require 'button) +(require 'cl-lib) +(require 'help-mode) +(require 'cl-seq) +(require 'subr-x) + +(defcustom info-make-xref-flag t + "Non-nil means Emacs creates symbol links in info buffers. +Please see the function `info-make-xrefs' for further +information." + :type '(choice (const :tag "Create links" t) + (const :tag "Do not link" nil)) + :version "30.1" + :group 'info) + +;; Toggle on or off the linking to help documents +(when info-make-xref-flag + (add-hook 'Info-selection-hook 'info-make-xrefs)) + +(defvar info-emacs-info-dir-content nil + "List of file names in Emacs' info directories. +It is used to check if the current info file `Info-current-file' +belongs to the Emacs and Elisp context. This variable will be +initialised when opening the first info file.") + +;; Turn better into a regexp list? Hint: Stefan Monier or switch to +;; alists with an explanation of file name? +(defcustom info-none-emacs-or-elisp-documents + '("aarm2012" ; Stefan: Ada manual, Elpa archive + "arm2012" ; Stefan: Ada manual + "sicp" ; T.V: Structure and Interpretation of Computer Programs, + ; Melpa archive + ) + "List of (known) documentation which is not related to GNU Emacs or Elis= p. +As well as documents which should not be searched for linking to +help documentation, for more details please see +`info-check-docu-p'. The list must contain only the base name of +files, without the file extension \".info\"." + :type '(repeat string) + :version "30.1" + :group 'info) + +(defun info-check-docu-p () + "Check if the current info file is relevant to Emacs or Elisp. +That means `Info-current-file' is either found in Emacs' info/ +directory or in `package-user-dir' and is not included in the +`info-none-emacs-or-elisp-documents' list." + (unless info-emacs-info-dir-content + (info-compile-emacs-info-dir-content)) + (let* ((ifile Info-current-file) + (ifi (when ifile + (file-name-sans-extension + (file-name-nondirectory ifile)))) + (pdir (when (boundp 'package-user-dir) + (expand-file-name + package-user-dir))) + ;; Check if checking pdir is redundant because Package adds + ;; info package folders to Info-directory-list anyway? + (ifiles info-emacs-info-dir-content) + (ndocu info-none-emacs-or-elisp-documents) + (is-info (and ifile + (or (assoc-string (concat ifi ".info") ifiles) + ;; the top info "dir" file + (assoc-string (concat ifi ".info.gz") ifiles) + ;; info files might be archived! + (when pdir (string-match pdir ifile))) + (not (assoc-string ifi ndocu))))) + (unless is-info + (message "No Emacs related info file: %s." ifile)) + is-info)) + +(defvar describe-symbol-backends) ;from help-mode.el +(defvar help-xref-following) ;dito + +;; customisation candidate +(defface info-color + '((t (:inherit font-lock-doc-face + ;; font-lock-preprocessor-face ; similar to link face (de= fault) + ;; font-lock-builtin-face ; similar (default Emacs) + ;; font-lock-function-name-face ; similar (default) + ;; info-face + ))) + "Face for all `symbol' references in `Info' nodes." + :group 'info-colors) + +(defvar-keymap info-button-map + :doc "Keymap used by buttons in Info buffers." + "RET" #'push-button + "" #'push-button + "" 'mouse-face + ;; FIXME: You'd think that for keymaps coming from text-properties on the + ;; mode-line or header-line, the `mode-line' or `header-line' prefix + ;; shouldn't be necessary! + " " #'push-button + " " #'push-button) + +;; Button types +(define-button-type 'info + 'link t + 'follow-link t + 'face 'info-color + 'keymap info-button-map + 'action #'info-button-action) + +(define-button-type 'info-function + :supertype 'info + 'info-function 'describe-function + 'help-echo (purecopy "mouse-2, RET: describe this function")) + +(define-button-type 'info-variable + :supertype 'info + 'info-function 'describe-variable + 'help-echo (purecopy "mouse-2, RET: describe this variable")) + +(define-button-type 'info-face + :supertype 'info + 'info-function 'describe-face + 'help-echo (purecopy "mouse-2, RET: describe this face")) + +(define-button-type 'info-symbol + :supertype 'info + 'info-function #'describe-symbol + 'help-echo (purecopy "mouse-2, RET: describe this symbol")) + +(define-button-type 'info-function-def + :supertype 'info + 'info-function (lambda (fun &optional file type) + (or file + (setq file (find-lisp-object-file-name fun type))) + (if (not file) + (message "Unable to find defining file") + (require 'find-func) + (when (eq file 'C-source) + (setq file + (help-C-file-name (indirect-function fun) 'fu= n))) + ;; Don't use find-function-noselect because it follows + ;; aliases (which fails for built-in functions). + (let ((location + (find-function-search-for-symbol fun type file= ))) + (pop-to-buffer (car location)) + (run-hooks 'find-function-after-hook) + (if (cdr location) + (goto-char (cdr location)) + (message "Unable to find location in file"))))) + 'help-echo (purecopy "mouse-2, RET: find function's definition")) + +;; Functions + +(defun info-compile-emacs-info-dir-content () + "Build a list of file names from Emacs' info directories. +This function fills `info-emacs-info-dir-content' with files from +`Info-directory-list'." + (setq info-emacs-info-dir-content + (mapcar 'file-name-nondirectory ;'file-name-sans-extension + (directory-files + (car + ;; search for the main Emacs' info/ directory, when this + ;; function is called Info-directory-list is already + ;; initialised + (cl-member "[^.]emacs" Info-directory-list :test + 'string-match-p)) + ;; don't list "." and ".." + t "[^.]$")))) + +(defun info-button-action (button) + "Call BUTTON's help function." + (info-do-xref nil + (button-get button 'info-function) + (button-get button 'info-args))) + +(defun info-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 +a proper [back] button." + ;; There is a reference at point. Follow it. + (let ((help-xref-following nil)) + (apply + function (if (eq function 'info) + (append args (list (generate-new-buffer-name "*info*")))= args)))) + +(defun info-button (match-number type &rest args) + "Make a hyperlink for cross-reference text previously matched. +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 info-function when it is invoked. +See `info-make-xrefs' Don't forget ARGS." + ;; Don't munge properties we've added, especially in some instances. + (unless (button-at (match-beginning match-number)) + ;; (message "Creating button: %s." args) + (make-text-button (match-beginning match-number) + (match-end match-number) + 'type type 'info-args args))) + +(defvar info-symbol-context + '(( variable . "variable\\|option") + ( function . "function\\|command\\|call") + ( face . "face") + ( ignore . "symbol\\|program\\|property") + ;; ignore symbols following this context type + ( definition . "source \\(?:code \\)?\\(?:of\\|for\\)")) + ;; function definitions in files + "This list helps to distinguish symbol types. +Words in info documentation preceding a (quoted) symbol are used +to distinguish variables, functions, faces and symbols. The +context information can also be used to ignore symbols because +there is no help documentation for them. The strings of the the +list are becoming part of `info-symbol-regexp'.") + +(defvar info-symbol-regexp + ;; use purecopy? + (concat + "\\(" ; Context start + "\\<\\(" ; Contex type definition + (string-remove-suffix + "\\|" + (mapconcat + (lambda (x) (concat "\\(" (cdr x) "\\)\\|")) + info-symbol-context "")) + "\\)" ; Context type definition end + "[ \t\n]+" ; Separators to quoted symbols + "\\)?" ; End of context + ;; quoted symbol + "['`=E2=80=98]" ; opening quotes + ;; Note: Symbol starting with word-syntax character: + "\\(\\sw\\(\\sw\\|\\s_\\)+\\|`\\)" ; The symbol itself + "['=E2=80=99]" ; End quotes + ) + "The regular expression for matching symbols to their help documentation. +It is comprised of the symbol's context and the (quoted) symbol +name. The various groups of context regular expressions are +matched in `info-make-xrefs' to distinct info buttons.") + +(defun info-check-type( type) + "Check if TYPE corresponds to the current search result. +The function is used in `info-make-xrefs'." + (let* ((isc info-symbol-context) + (n 3) ;embedded within 2 groups + (l (+ 3 (length isc)))) + (while (and (not (eq type (caar isc) ) ) (< n l) ) + (setq n (1+ n)) + (setq isc (cdr isc))) + (match-string n))) + + +;;;###autoload +(defun info-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'. The current +buffer is processed if the BUFFER argument is omitted. + + Cross-references have the canonical (quoted) form `symbol-name' +and the type of reference may be disambiguated by the preceding +word(s) as compiled in `info-symbol-regexp'. For example: Symbol +names are receiving distinct variable buttons when preceeded by +the words \"variable\" or \"option\". + +Variables are also detected when their names follow below form: + + -- User Option: variable-name + -- Variable: ... + +Function names are also detected when prefixed by `M-x`, for +example `M-x function-name` or are quoted and prefixed like `M-x +function-name`. + +Function names are detected, as well, when appearing behind the +following forms, which occur - for example - in the Elisp manual: + + -- Special Form: function-name + -- Command: ... + -- Function: ... + -- Macro: ... + +The linking is similar to mechanisms from lisp/help.el." + (interactive "b") + (when (info-check-docu-p) + (with-current-buffer (or buffer (current-buffer)) + (save-excursion + (goto-char (point-min)) + (with-silent-modifications ;hint from Stefan + (let ((case-fold-search t) + (inhibit-read-only t)) + (with-syntax-table emacs-lisp-mode-syntax-table + ;; Quoted symbols + (save-excursion + (while (re-search-forward info-symbol-regexp nil t) + (let* ((sym-group (+ 3 (length info-symbol-context))) + (data (match-string sym-group)) + (sym (intern-soft data))) + (if sym + (cond + ((info-check-type 'variable) + (and (or (boundp sym) + (get sym 'variable-documentation)) + (info-button sym-group 'info-variable sym))) + ((info-check-type 'function) + (and (fboundp sym) + (info-button sym-group 'info-function sym))) + ((info-check-type 'face) + (and (facep sym) + (info-button sym-group 'info-face sym))) + ((info-check-type 'ignore)) + ((info-check-type 'definition) + (info-button sym-group 'info-function-def sym)) + ;; symbols + ((cl-some (lambda (x) (funcall (nth 1 x) sym)) + describe-symbol-backends) + (info-button sym-group 'info-symbol sym))))))) + ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; (info "(elisp) Eval") + ;; Elisp manual -- Special Form: + ;; -- Command: + ;; -- Function: function-name function + ;; -- Macro: + (save-excursion + (while (re-search-forward + "-- \\(Special Form:\\|Command:\\|Function:\\|Macr= o:\\) " + nil t) + (looking-at "\\(\\sw\\|\\s_\\)+") + (let ((sym (intern-soft (match-string 0)))) + (if (fboundp sym) + (info-button 0 'info-function sym))))) + ;; -- User Option: + ;; -- Variable: variable-name + (save-excursion + (while (re-search-forward + "-- \\(User Option:\\|Variable:\\) " + nil t) + (looking-at "\\(\\sw\\|\\s_\\)+") + (let ((sym (intern-soft (match-string 0)))) + (if (boundp sym) + (info-button 0 'info-variable sym))))) + ;; M-x prefixed functions + (save-excursion + (while (re-search-forward + ;; Assume command name is only word and symbol + ;; characters to get things like `use M-x foo->bar= '. + ;; Command required to end with word constituent + ;; to avoid `.' at end of a sentence. + ;; "\\