-;;; info-look.el --- major-mode-sensitive Info index lookup facility
+;;; info-look.el --- major-mode-sensitive Info index lookup facility -*- lexical-binding: t -*-
;; An older version of this was known as libc.el.
-;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2001, 2002, 2003,
-;; 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
+;; Copyright (C) 1995-1999, 2001-2016 Free Software Foundation, Inc.
;; Author: Ralph Schleicher <rs@nunatak.allgaeu.org>
;; (did not show signs of life (Nov 2001) -stef)
;; Really cool code to lookup info indexes.
;; Try especially info-lookup-symbol (aka C-h S).
+;; Some additional sources of (Tex)info files for non-GNU packages:
+;;
+;; Scheme: <URL:http://groups.csail.mit.edu/mac/ftpdir/scm/r5rs.info.tar.gz>
+;; LaTeX:
+;; <URL:ftp://ctan.tug.org/tex-archive/info/latex2e-help-texinfo/latex2e.texi>
+;; (or CTAN mirrors)
+;; Perl: <URL:ftp://ftp.cpan.org/pub/CPAN/doc/manual/texinfo/> (or CPAN mirrors)
+
+;; Traditionally, makeinfo quoted `like this', but version 5 and later
+;; quotes 'like this' or ‘like this’. Doc specs with patterns
+;; therefore match open and close quotes with ['`‘] and ['’],
+;; respectively.
+
;;; Code:
(require 'info)
(defun info-lookup-add-help (&rest arg)
"Add or update a help specification.
-Function arguments are one or more options of the form
+Function arguments are specified as keyword/argument pairs:
- KEYWORD ARGUMENT
+ (KEYWORD . ARGUMENT)
KEYWORD is either `:topic', `:mode', `:regexp', `:ignore-case',
`:doc-spec', `:parse-rule', or `:other-modes'.
value into the minibuffer so you can edit it. The default symbol is the
one found at point.
-With prefix arg a query for the symbol help mode is offered."
+With prefix arg MODE a query for the symbol help mode is offered."
(interactive
(info-lookup-interactive-arguments 'symbol current-prefix-arg))
(info-lookup 'symbol symbol mode))
into the minibuffer so you can edit it.
The default file name is the one found at point.
-With prefix arg a query for the file help mode is offered."
+With prefix arg MODE a query for the file help mode is offered."
(interactive
(info-lookup-interactive-arguments 'file current-prefix-arg))
(info-lookup 'file file mode))
(when (string-match (caar file-name-alist) file-name)
(setq info-lookup-mode (cdar file-name-alist)))
(setq file-name-alist (cdr file-name-alist)))))
+
+ ;; If major-mode has no setups in info-lookup-alist, under any topic, then
+ ;; search up through derived-mode-parent to find a parent mode which does
+ ;; have some setups. This means that a `define-derived-mode' with no
+ ;; setups of its own will select its parent mode for lookups, if one of
+ ;; its parents has some setups. Good for example on `makefile-gmake-mode'
+ ;; and similar derivatives of `makefile-mode'.
+ ;;
+ (let ((mode major-mode)) ;; Look for `mode' with some setups.
+ (while (and mode (not info-lookup-mode))
+ (dolist (topic-cell info-lookup-alist) ;; Usually only two topics here.
+ (if (info-lookup->mode-value (car topic-cell) mode)
+ (setq info-lookup-mode mode)))
+ (setq mode (get mode 'derived-mode-parent))))
+
(or info-lookup-mode (setq info-lookup-mode major-mode)))
(defun info-lookup-change-mode (topic)
(setq node (nth 0 (car doc-spec))
prefix (nth 2 (car doc-spec))
suffix (nth 3 (car doc-spec)))
- (when (condition-case error-data
+ (when (condition-case nil
(progn
;; Don't need Index menu fontifications here, and
;; they slow down the lookup.
(t (nth 1 (car doc-spec)))))
(with-current-buffer buffer
(message "Processing Info node `%s'..." node)
- (when (condition-case error-data
+ (when (condition-case nil
(progn
(Info-goto-node node)
(setq doc-found t))
(condition-case nil
(save-excursion
(let ((case-fold-search t)
- (ignored-chars "][()`',:.\" \t\n")
- (significant-chars "^][()`',:.\" \t\n")
+ (ignored-chars "][()`'‘’,:.\" \t\n")
+ (significant-chars "^][()`'‘’,:.\" \t\n")
beg end)
(cond
((and (memq (get-char-property (point) 'face)
(setq end (point))
(> end beg))
(and (looking-at "[ \t\n]")
- (looking-back (concat "[" significant-chars "]"))
+ (looking-back (concat "[" significant-chars "]")
+ (1- (point)))
(setq end (point))
(skip-chars-backward significant-chars)
(setq beg (point))
info-lookup-mode
(info-lookup-change-mode 'file)))))
+(defun info-lookup-completions-at-point (topic mode)
+ "Try to complete a help item."
+ (or mode (setq mode (info-lookup-select-mode)))
+ (when (info-lookup->mode-value topic mode)
+ (let ((modes (info-lookup-quick-all-modes topic mode))
+ (start (point))
+ try)
+ (while (and (not try) modes)
+ (setq mode (car modes)
+ modes (cdr modes)
+ try (info-lookup-guess-default* topic mode))
+ (goto-char start))
+ (when try
+ (let ((completions (info-lookup->completions topic mode)))
+ (when completions
+ (when (info-lookup->ignore-case topic mode)
+ (setq completions
+ (lambda (string pred action)
+ (let ((completion-ignore-case t))
+ (complete-with-action
+ action completions string pred)))))
+ (save-excursion
+ ;; Find the original symbol and zap it.
+ (end-of-line)
+ (while (and (search-backward try nil t)
+ (< start (point))))
+ (list (match-beginning 0) (match-end 0) completions
+ :exclusive 'no))))))))
+
(defun info-complete (topic mode)
"Try to complete a help item."
(barf-if-buffer-read-only)
- (or mode (setq mode (info-lookup-select-mode)))
- (or (info-lookup->mode-value topic mode)
- (error "No %s completion available for `%s'" topic mode))
- (let ((modes (info-lookup-quick-all-modes topic mode))
- (start (point))
- try)
- (while (and (not try) modes)
- (setq mode (car modes)
- modes (cdr modes)
- try (info-lookup-guess-default* topic mode))
- (goto-char start))
- (and (not try)
- (error "Found no %S to complete" topic))
- (let ((completions (info-lookup->completions topic mode))
- (completion-ignore-case (info-lookup->ignore-case topic mode))
- completion)
- (setq completion (try-completion try completions))
- (cond ((not completion)
- (ding)
- (message "No match"))
- ((stringp completion)
- (or (assoc completion completions)
- (setq completion (completing-read
- (format "Complete %S: " topic)
- completions nil t completion
- info-lookup-history)))
- ;; Find the original symbol and zap it.
- (end-of-line)
- (while (and (search-backward try nil t)
- (< start (point))))
- (replace-match "")
- (insert completion))
- (t
- (message "%s is complete"
- (capitalize (prin1-to-string topic))))))))
+ (let ((data (info-lookup-completions-at-point topic mode)))
+ (if (null data)
+ (error "No %s completion available for `%s' at point" topic mode)
+ (completion-in-region (nth 0 data) (nth 1 data) (nth 2 data)))))
\f
;;; Initialize some common modes.
;; suffix "\\>" is not used because that sends DBL_MAX to
;; DBL_MAX_EXP ("_" is a non-word char)
("(libc)Variable Index" nil
- "^\\([ \t]+-+ \\(Variable\\|Macro\\): .*\\<\\|`\\)"
- "\\( \\|'?$\\)")
+ "^\\([ \t]+-+ \\(Variable\\|Macro\\): .*\\<\\|['`‘]\\)"
+ "\\( \\|['’]?$\\)")
("(libc)Type Index" nil
"^[ \t]+-+ Data Type: \\<" "\\>")
("(termcap)Var Index" nil
- "^[ \t]*`" "'"))
+ "^[ \t]*['`‘]" "['’]"))
:parse-rule 'info-lookup-guess-c-symbol)
(info-lookup-maybe-add-help
:mode 'bison-mode
:regexp "[:;|]\\|%\\([%{}]\\|[_a-z]+\\)\\|YY[_A-Z]+\\|yy[_a-z]+"
:doc-spec '(("(bison)Index" nil
- "`" "'"))
+ "['`‘]" "['’]"))
:parse-rule "[:;|]\\|%\\([%{}]\\|[_a-zA-Z][_a-zA-Z0-9]*\\)"
:other-modes '(c-mode))
:mode 'makefile-mode
:regexp "\\$[^({]\\|\\.[_A-Z]*\\|[_a-zA-Z][_a-zA-Z0-9-]*"
:doc-spec '(("(make)Name Index" nil
- "^[ \t]*`" "'")
- ("(automake)Macro and Variable Index" nil
- "^[ \t]*`" "'"))
- :parse-rule "\\$[^({]\\|\\.[_A-Z]*\\|[_a-zA-Z0-9-]+"
- :other-modes '(automake-mode))
+ "^[ \t]*['`‘]" "['’]"))
+ :parse-rule "\\$[^({]\\|\\.[_A-Z]*\\|[_a-zA-Z0-9-]+")
+
+(info-lookup-maybe-add-help
+ :topic 'symbol
+ :mode 'makefile-automake-mode
+ ;; similar regexp/parse-rule as makefile-mode, but also the following
+ ;; (which have index entries),
+ ;; "##" special automake comment
+ ;; "+=" append operator, separate from the GNU make one
+ :regexp "\\$[^({]\\|\\.[_A-Z]*\\|[_a-zA-Z][_a-zA-Z0-9-]*\\|##\\|\\+="
+ :parse-rule "\\$[^({]\\|\\.[_A-Z]*\\|[_a-zA-Z0-9-]+\\|##\\|\\+="
+ :doc-spec '(
+ ;; "(automake)Macro Index" is autoconf macros used in
+ ;; configure.ac, not Makefile.am, so don't have that here.
+ ("(automake)Variable Index" nil "^[ \t]*['`‘]" "['’]")
+ ;; In automake 1.4 macros and variables were a combined node.
+ ("(automake)Macro and Variable Index" nil "^[ \t]*['`‘]"
+ "['’]")
+ ;; Directives like "if" are in the "General Index".
+ ;; Prefix "`" since the text for say `+=' isn't always an
+ ;; @item etc and so not always at the start of a line.
+ ("(automake)General Index" nil "['`‘]" "['’]")
+ ;; In automake 1.3 there was just a single "Index" node.
+ ("(automake)Index" nil "['`‘]" "['’]"))
+ :other-modes '(makefile-mode))
(info-lookup-maybe-add-help
:mode 'texinfo-mode
(lambda (item)
(if (string-match "^\\([a-zA-Z]+\\|[^a-zA-Z]\\)\\( .*\\)?$" item)
(concat "@" (match-string 1 item))))
- "`" "[' ]")))
+ "['`‘]" "['’ ]")))
(info-lookup-maybe-add-help
:mode 'm4-mode
;; macros (eg. AC_PROG_CC). Ensure this is after the autoconf
;; index, so as to prefer the autoconf docs.
("(automake)Macro and Variable Index" nil
- "^[ \t]*`" "'"))
+ "^[ \t]*['`‘]" "['’]"))
;; Autoconf symbols are M4 macros. Thus use M4's parser.
:parse-rule 'ignore
:other-modes '(m4-mode))
;; Built-in functions (matches to many entries).
((string-match "^[a-z]+$" item)
item))))
- "`" "\\([ \t]*([^)]*)\\)?'")))
+ "['`‘]" "\\([ \t]*([^)]*)\\)?['’]")))
(info-lookup-maybe-add-help
:mode 'perl-mode
(info-lookup-maybe-add-help
:mode 'latex-mode
:regexp "\\\\\\([a-zA-Z]+\\|[^a-zA-Z]\\)"
- :doc-spec '(("(latex)Command Index" nil
- "`" "\\({[^}]*}\\)?'")))
+ :doc-spec `((,(if (Info-find-file "latex2e" t)
+ ;; From http://home.gna.org/latexrefman
+ "(latex2e)Command Index"
+ "(latex)Command Index")
+ ;; \frac{NUM}{DEN} etc can have more than one {xx} argument.
+ ;; \sqrt[ROOT]{num} and others can have square brackets.
+ nil "[`'‘]" "\\({[^}]*}|\\[[^]]*\\]\\)*['’]")))
+
(info-lookup-maybe-add-help
:mode 'emacs-lisp-mode
- :regexp "[^][()`',\" \t\n]+"
+ :regexp "[^][()`'‘’,\" \t\n]+"
:doc-spec '(;; Commands with key sequences appear in nodes as `foo' and
;; those without as `M-x foo'.
- ("(emacs)Command Index" nil "`\\(M-x[ \t\n]+\\)?" "'")
+ ("(emacs)Command Index" nil "['`‘]\\(M-x[ \t\n]+\\)?" "['’]")
;; Variables normally appear in nodes as just `foo'.
- ("(emacs)Variable Index" nil "`" "'")
+ ("(emacs)Variable Index" nil "['`‘]" "['’]")
;; Almost all functions, variables, etc appear in nodes as
;; " -- Function: foo" etc. A small number of aliases and
;; symbols appear only as `foo', and will miss out on exact
;; for things that should go to Function: etc, and those latter
;; are much more important. Perhaps this could change if some
;; sort of fallback match scheme existed.
- ("(elisp)Index" nil "^ -+ .*: " "\\( \\|$\\)")))
+ ("(elisp)Index" nil "^ -+ .*: " "\\( \\|$\\)")
+ ("(cl)Function Index" nil "^ -+ .*: " "\\( \\|$\\)")
+ ("(cl)Variable Index" nil "^ -+ .*: " "\\( \\|$\\)")))
;; docstrings talk about elisp, so have apropos-mode follow emacs-lisp-mode
(info-lookup-maybe-add-help
:mode 'apropos-mode
- :regexp "[^][()`',\" \t\n]+" ;; same as emacs-lisp-mode above
+ :regexp "[^][()`'‘’,\" \t\n]+" ;; same as emacs-lisp-mode above
:other-modes '(emacs-lisp-mode))
(info-lookup-maybe-add-help
:mode 'lisp-interaction-mode
- :regexp "[^][()`',\" \t\n]+"
+ :regexp "[^][()`'‘’,\" \t\n]+"
:parse-rule 'ignore
:other-modes '(emacs-lisp-mode))
(info-lookup-maybe-add-help
:mode 'lisp-mode
- :regexp "[^()`',\" \t\n]+"
+ :regexp "[^()`'‘’,\" \t\n]+"
:parse-rule 'ignore
:other-modes '(emacs-lisp-mode))
(info-lookup-maybe-add-help
:mode 'scheme-mode
- :regexp "[^()`',\" \t\n]+"
+ :regexp "[^()`'‘’,\" \t\n]+"
:ignore-case t
;; Aubrey Jaffer's rendition from <URL:ftp://ftp-swiss.ai.mit.edu/pub/scm>
:doc-spec '(("(r5rs)Index" nil
;; bash has "." and ":" in its index, but those chars will probably never
;; work in info, so don't bother matching them in the regexp.
:regexp "\\([a-zA-Z0-9_-]+\\|[!{}@*#?$]\\|\\[\\[?\\|]]?\\)"
- :doc-spec '(("(bash)Builtin Index" nil "^`" "[ .']")
- ("(bash)Reserved Word Index" nil "^`" "[ .']")
- ("(bash)Variable Index" nil "^`" "[ .']")
+ :doc-spec '(("(bash)Builtin Index" nil "^['`‘]" "[ .'’]")
+ ("(bash)Reserved Word Index" nil "^['`‘]" "[ .'’]")
+ ("(bash)Variable Index" nil "^['`‘]" "[ .'’]")
;; coreutils (version 4.5.10) doesn't have a separate program
;; index, so exclude extraneous stuff (most of it) by demanding
item))
;; This gets functions in evaluated classes. Other
;; possible patterns don't seem to work too well.
- "`" "(")))
+ "['`‘]" "(")))
(info-lookup-maybe-add-help
:mode 'Custom-mode
:ignore-case t
- :regexp "[^][()`',:\" \t\n]+"
+ :regexp "[^][()`'‘’,:\" \t\n]+"
:parse-rule 'info-lookup-guess-custom-symbol
:other-modes '(emacs-lisp-mode))
(info-lookup-maybe-add-help
:mode 'help-mode
- :regexp "[^][()`',:\" \t\n]+"
+ :regexp "[^][()`'‘’,:\" \t\n]+"
:other-modes '(emacs-lisp-mode))
\f
(provide 'info-look)
-;; arch-tag: 0f1e3ea3-32a2-4461-bbab-3cff93539a74
;;; info-look.el ends here