diff options
Diffstat (limited to 'lisp/info-look.el')
-rw-r--r-- | lisp/info-look.el | 114 |
1 files changed, 106 insertions, 8 deletions
diff --git a/lisp/info-look.el b/lisp/info-look.el index cc6a806f56f..48120359193 100644 --- a/lisp/info-look.el +++ b/lisp/info-look.el @@ -43,6 +43,7 @@ (require 'info) (eval-when-compile (require 'subr-x)) +(eval-when-compile (require 'cl-lib)) (defgroup info-lookup nil "Major mode sensitive help agent." @@ -123,6 +124,14 @@ OTHER-MODES is a list of cross references to other help modes.") (defsubst info-lookup->mode-value (topic mode) (assoc mode (info-lookup->topic-value topic))) +(defun info-lookup--expand-info (info) + ;; We have a dynamic doc-spec function. + (when (and (null (nth 3 info)) + (nth 6 info)) + (setf (nth 3 info) (funcall (nth 6 info)) + (nth 6 info) nil)) + info) + (defsubst info-lookup->regexp (topic mode) (nth 1 (info-lookup->mode-value topic mode))) @@ -145,7 +154,11 @@ Function arguments are specified as keyword/argument pairs: (KEYWORD . ARGUMENT) KEYWORD is either `:topic', `:mode', `:regexp', `:ignore-case', - `:doc-spec', `:parse-rule', or `:other-modes'. + `:doc-spec', `:parse-rule', `:other-modes' or `:doc-spec-function'. + `:doc-spec-function' is used to compute a `:doc-spec', but instead of + doing so at load time, this is done when the user asks for info on + the mode in question. + ARGUMENT has a value as explained in the documentation of the variable `info-lookup-alist'. @@ -161,7 +174,8 @@ for more details." (defun info-lookup-add-help* (maybe &rest arg) (let (topic mode regexp ignore-case doc-spec - parse-rule other-modes keyword value) + parse-rule other-modes keyword value + doc-spec-function) (setq topic 'symbol mode major-mode regexp "\\w+") @@ -184,6 +198,8 @@ for more details." (setq ignore-case value)) ((eq keyword :doc-spec) (setq doc-spec value)) + ((eq keyword :doc-spec-function) + (setq doc-spec-function value)) ((eq keyword :parse-rule) (setq parse-rule value)) ((eq keyword :other-modes) @@ -191,7 +207,8 @@ for more details." (t (error "Unknown keyword \"%S\"" keyword)))) (or (and maybe (info-lookup->mode-value topic mode)) - (let* ((data (list regexp ignore-case doc-spec parse-rule other-modes)) + (let* ((data (list regexp ignore-case doc-spec parse-rule other-modes + doc-spec-function)) (topic-cell (or (assoc topic info-lookup-alist) (car (setq info-lookup-alist (cons (cons topic nil) @@ -341,11 +358,22 @@ If optional argument QUERY is non-nil, query for the help mode." (error "No %s help available for `%s'" topic mode)) (setq info-lookup-mode mode))) +(defun info-lookup--item-to-mode (item mode) + (let ((spec (cons mode (car (split-string (if (stringp item) + item + (symbol-name item)) + "-"))))) + (if (assoc spec (cdr (assq 'symbol info-lookup-alist))) + spec + mode))) + (defun info-lookup (topic item mode) "Display the documentation of a help item." (or mode (setq mode (info-lookup-select-mode))) - (or (info-lookup->mode-value topic mode) - (error "No %s help available for `%s'" topic mode)) + (setq mode (info-lookup--item-to-mode item mode)) + (if-let ((info (info-lookup->mode-value topic mode))) + (info-lookup--expand-info info) + (error "No %s help available for `%s'" topic mode)) (let* ((completions (info-lookup->completions topic mode)) (ignore-case (info-lookup->ignore-case topic mode)) (entry (or (assoc (if ignore-case (downcase item) item) completions) @@ -724,6 +752,8 @@ Return nil if there is nothing appropriate in the buffer near point." (defun info-complete (topic mode) "Try to complete a help item." (barf-if-buffer-read-only) + (when-let ((info (info-lookup->mode-value topic mode))) + (info-lookup--expand-info info)) (let ((data (info-lookup-completions-at-point topic mode))) (if (null data) (error "No %s completion available for `%s' at point" topic mode) @@ -904,9 +934,16 @@ Return nil if there is nothing appropriate in the buffer near point." (info-lookup-maybe-add-help :mode 'python-mode - :doc-spec `((,(if (Info-find-file "python3.9" t) - "(python3.9)Index" - "(python)Index")))) + ;; Debian includes Python info files, but they're version-named + ;; instead of having a symlink. + :doc-spec-function (lambda () + (list + (list + (cl-loop for version from 20 downto 7 + for name = (format "python3.%d" version) + if (Info-find-file name t) + return (format "(%s)Index" name) + finally return "(python)Index"))))) (info-lookup-maybe-add-help :mode 'cperl-mode @@ -944,6 +981,67 @@ Return nil if there is nothing appropriate in the buffer near point." ("(cl)Function Index" nil "^ -+ .*: " "\\( \\|$\\)") ("(cl)Variable Index" nil "^ -+ .*: " "\\( \\|$\\)"))) +(mapc + (lambda (elem) + (let* ((prefix (car elem))) + (info-lookup-add-help + :mode (cons 'emacs-lisp-mode prefix) + :regexp (concat "\\b" prefix "-[^][()`'‘’,\" \t\n]+") + :doc-spec (cl-loop for node in (cdr elem) + collect + (list (if (string-match-p "^(" node) + node + (format "(%s)%s" prefix node)) + nil "^ -+ .*: " "\\( \\|$\\)"))))) + ;; Below we have a list of prefixes (used to match on symbols in + ;; `emacs-lisp-mode') and the nodes where the function/variable + ;; indices live. If the prefix is different than the name of the + ;; manual, then the full "(manual)Node" name has to be used. + '(("auth" "Function Index" "Variable Index") + ("autotype" "Command Index" "Variable Index") + ("calc" "Lisp Function Index" "Variable Index") + ;;("cc-mode" "Variable Index" "Command and Function Index") + ("dbus" "Index") + ("ediff" "Index") + ("eieio" "Function Index") + ("gnutls" "(emacs-gnutls)Variable Index" "(emacs-gnutls)Function Index") + ("mm" "(emacs-mime)Index") + ("epa" "Variable Index" "Function Index") + ("ert" "Index") + ("eshell" "Function and Variable Index") + ("eudc" "Index") + ("eww" "Variable Index" "Lisp Function Index") + ("flymake" "Index") + ("forms" "Index") + ("gnus" "Index") + ("htmlfontify" "Functions" "Variables & Customization") + ("idlwave" "Index") + ("ido" "Variable Index" "Function Index") + ("info" "Index") + ("mairix" "(mairix-el)Variable Index" "(mairix-el)Function Index") + ("message" "Index") + ("mh" "(mh-e)Option Index" "(mh-e)Command Index") + ("newsticker" "Index") + ("octave" "(octave-mode)Variable Index" "(octave-mode)Lisp Function Index") + ("org" "Variable Index" "Command and Function Index") + ("pgg" "Variable Index" "Function Index") + ("rcirc" "Variable Index" "Index") + ("reftex" "Index") + ("sasl" "Variable Index" "Function Index") + ("sc" "Variable Index") + ("semantic" "Index") + ("ses" "Index") + ("sieve" "Index") + ("smtpmail" "Function and Variable Index") + ("srecode" "Index") + ("tramp" "Variable Index" "Function Index") + ("url" "Variable Index" "Function Index") + ("vhdl" "(vhdl-mode)Variable Index" "(vhdl-mode)Command Index") + ("viper" "Variable Index" "Function Index") + ("widget" "Index") + ("wisent" "Index") + ("woman" "Variable Index" "Command Index"))) + ;; docstrings talk about elisp, so have apropos-mode follow emacs-lisp-mode (info-lookup-maybe-add-help :mode 'apropos-mode |