diff options
Diffstat (limited to 'lisp/info.el')
-rw-r--r-- | lisp/info.el | 209 |
1 files changed, 117 insertions, 92 deletions
diff --git a/lisp/info.el b/lisp/info.el index 739116cceac..db95574bf72 100644 --- a/lisp/info.el +++ b/lisp/info.el @@ -115,7 +115,9 @@ The Lisp code is executed when the node is selected.") (defface info-menu-star '((((class color)) :foreground "red1") (t :underline t)) - "Face for every third `*' in an Info menu.") + "Face used to emphasize `*' in an Info menu. +The face is assigned to the third, sixth, and ninth `*' for easier +orientation. See `Info-nth-menu-item'.") (defface info-xref '((t :inherit link)) @@ -159,59 +161,8 @@ A header-line does not scroll with the rest of the buffer." "Face used to highlight matches in an index entry." :version "24.4") -;; This is a defcustom largely so that we can get the benefit -;; of `custom-initialize-delay'. Perhaps it would work to make it a -;; `defvar' and explicitly give it a `standard-value' property, and -;; call `custom-initialize-delay' on it. -;; The value is initialized at startup time, when command-line calls -;; `custom-reevaluate-setting' on all the defcustoms in -;; `custom-delayed-init-variables'. This is somewhat sub-optimal, as ideally -;; this should be done when Info mode is first invoked. ;;;###autoload -(defcustom Info-default-directory-list - (let* ((config-dir - (file-name-as-directory - ;; Self-contained NS build with info/ in the app-bundle. - (or (and (featurep 'ns) - (let ((dir (expand-file-name "../info" data-directory))) - (if (file-directory-p dir) dir))) - configure-info-directory))) - (prefixes - ;; Directory trees in which to look for info subdirectories - (prune-directory-list '("/usr/local/" "/usr/" "/opt/"))) - (suffixes - ;; Subdirectories in each directory tree that may contain info - ;; directories. - '("share/" "")) - (standard-info-dirs - (apply #'nconc - (mapcar (lambda (pfx) - (let ((dirs - (mapcar (lambda (sfx) - (concat pfx sfx "info/")) - suffixes))) - (prune-directory-list dirs))) - prefixes))) - ;; If $(prefix)/share/info is not one of the standard info - ;; directories, they are probably installing an experimental - ;; version of Emacs, so make sure that experimental version's Info - ;; files override the ones in standard directories. - (dirs - (if (member config-dir standard-info-dirs) - ;; FIXME? What is the point of adding it again at the end - ;; when it is already present earlier in the list? - (nconc standard-info-dirs (list config-dir)) - (cons config-dir standard-info-dirs)))) - (if (not (eq system-type 'windows-nt)) - dirs - ;; Include the info directory near where Emacs executable was installed. - (let* ((instdir (file-name-directory invocation-directory)) - (dir1 (expand-file-name "../info/" instdir)) - (dir2 (expand-file-name "../../../info/" instdir))) - (cond ((file-exists-p dir1) (append dirs (list dir1))) - ((file-exists-p dir2) (append dirs (list dir2))) - (t dirs))))) - +(defcustom Info-default-directory-list nil "Default list of directories to search for Info documentation files. They are searched in the order they are given in the list. Therefore, the directory of Info files that come with Emacs @@ -222,15 +173,12 @@ first in this list. Once Info is started, the list of directories to search comes from the variable `Info-directory-list'. -This variable `Info-default-directory-list' is used as the default -for initializing `Info-directory-list' when Info is started, unless -the environment variable INFOPATH is set. - -Although this is a customizable variable, that is mainly for technical -reasons. Normally, you should either set INFOPATH or customize -`Info-additional-directory-list', rather than changing this variable." - :initialize #'custom-initialize-delay - :type '(repeat directory)) + +This variable is used as the default for initializing +`Info-directory-list' when Info is started, unless the +environment variable INFOPATH is set." + :type '(repeat directory) + :version "29.1") (defvar Info-directory-list nil "List of directories to search for Info documentation files. @@ -677,6 +625,51 @@ in `Info-file-supports-index-cookies-list'." (cdr (assoc file Info-file-supports-index-cookies-list))) +(defun Info--default-directory-list () + "Compute a directory list suitable for Info." + (let* ((config-dir + (file-name-as-directory + ;; Self-contained NS build with info/ in the app-bundle. + (or (and (featurep 'ns) + (let ((dir (expand-file-name "../info" data-directory))) + (if (file-directory-p dir) dir))) + configure-info-directory))) + (prefixes + ;; Directory trees in which to look for info subdirectories + (prune-directory-list '("/usr/local/" "/usr/" "/opt/"))) + (suffixes + ;; Subdirectories in each directory tree that may contain info + ;; directories. + '("share/" "")) + (standard-info-dirs + (apply #'nconc + (mapcar (lambda (pfx) + (let ((dirs + (mapcar (lambda (sfx) + (concat pfx sfx "info/")) + suffixes))) + (prune-directory-list dirs))) + prefixes))) + ;; If $(prefix)/share/info is not one of the standard info + ;; directories, they are probably installing an experimental + ;; version of Emacs, so make sure that experimental version's Info + ;; files override the ones in standard directories. + (dirs + (if (member config-dir standard-info-dirs) + ;; FIXME? What is the point of adding it again at the end + ;; when it is already present earlier in the list? + (nconc standard-info-dirs (list config-dir)) + (cons config-dir standard-info-dirs)))) + (if (not (eq system-type 'windows-nt)) + dirs + ;; Include the info directory near where Emacs executable was installed. + (let* ((instdir (file-name-directory invocation-directory)) + (dir1 (expand-file-name "../info/" instdir)) + (dir2 (expand-file-name "../../../info/" instdir))) + (cond ((file-exists-p dir1) (append dirs (list dir1))) + ((file-exists-p dir2) (append dirs (list dir2))) + (t dirs)))))) + (defun Info-default-dirs () (let ((source (expand-file-name "info/" source-directory)) (sibling (if installation-directory @@ -699,25 +692,11 @@ in `Info-file-supports-index-cookies-list'." sibling ;; Uninstalled, builddir == srcdir source)) - (if (or (member alternative Info-default-directory-list) - ;; On DOS/NT, we use movable executables always, - ;; and we must always find the Info dir at run time. - (if (memq system-type '(ms-dos windows-nt)) - nil - ;; Use invocation-directory for Info - ;; only if we used it for exec-directory also. - (not (string= exec-directory - (expand-file-name "lib-src/" - installation-directory)))) - (not (file-exists-p alternative))) - Info-default-directory-list - ;; `alternative' contains the Info files that came with this - ;; version, so we should look there first. `Info-insert-dir' - ;; currently expects to find `alternative' first on the list. - (cons alternative - ;; Don't drop the last part, it might contain non-Emacs stuff. - ;; (reverse (cdr (reverse - Info-default-directory-list)))) ;; ))) + ;; `alternative' contains the Info files that came with this + ;; version, so we should look there first. `Info-insert-dir' + ;; currently expects to find `alternative' first on the list. + (append (cons alternative Info-default-directory-list) + (Info--default-directory-list)))) (defun info-initialize () "Initialize `Info-directory-list', if that hasn't been done yet." @@ -1792,7 +1771,46 @@ of NODENAME; if none is found it then tries a case-insensitive match (if trim (setq nodename (substring nodename 0 trim)))) (if transient-mark-mode (deactivate-mark)) (Info-find-node (if (equal filename "") nil filename) - (if (equal nodename "") "Top" nodename) nil strict-case))) + (if (equal nodename "") "Top" nodename) nil strict-case))) + +(defun Info-goto-node-web (node) + "Use `browse-url' to go to the gnu.org web server's version of NODE. +By default, go to the current Info node." + (interactive (list (Info-read-node-name + "Go to node (default current page): " Info-current-node)) + Info-mode) + (browse-url-button-open-url + (Info-url-for-node (format "(%s)%s" (file-name-sans-extension + (file-name-nondirectory + Info-current-file)) + node)))) + +(defun Info-url-for-node (node) + "Return a URL for NODE, a node in the GNU Emacs or Elisp manual. +NODE should be a string on the form \"(manual)Node\". Only emacs +and elisp manuals are supported." + (unless (string-match "\\`(\\(.+\\))\\(.+\\)\\'" node) + (error "Invalid node name %s" node)) + (let ((manual (match-string 1 node)) + (node (match-string 2 node))) + (unless (member manual '("emacs" "elisp")) + (error "Only emacs/elisp manuals are supported")) + ;; Encode a bunch of characters the way that makeinfo does. + (setq node + (mapconcat (lambda (ch) + (if (or (< ch 32) ; ^@^A-^Z^[^\^]^^^- + (<= 33 ch 47) ; !"#$%&'()*+,-./ + (<= 58 ch 64) ; :;<=>?@ + (<= 91 ch 96) ; [\]_` + (<= 123 ch 127)) ; {|}~ DEL + (format "_00%x" ch) + (char-to-string ch))) + node + "")) + (concat "https://www.gnu.org/software/emacs/manual/html_node/" + manual "/" + (url-hexify-string (string-replace " " "-" node)) + ".html"))) (defvar Info-read-node-completion-table) @@ -1877,7 +1895,7 @@ See `completing-read' for a description of arguments and usage." code Info-read-node-completion-table string predicate)))) ;; Arrange to highlight the proper letters in the completion list buffer. -(defun Info-read-node-name (prompt) +(defun Info-read-node-name (prompt &optional default) "Read an Info node name with completion, prompting with PROMPT. A node name can have the form \"NODENAME\", referring to a node in the current Info file, or \"(FILENAME)NODENAME\", referring to @@ -1885,7 +1903,8 @@ a node in FILENAME. \"(FILENAME)\" is a short format to go to the Top node in FILENAME." (let* ((completion-ignore-case t) (Info-read-node-completion-table (Info-build-node-completions)) - (nodename (completing-read prompt #'Info-read-node-name-1 nil t))) + (nodename (completing-read prompt #'Info-read-node-name-1 nil t nil + 'Info-minibuf-history default))) (if (equal nodename "") (Info-read-node-name prompt) nodename))) @@ -2604,12 +2623,9 @@ new buffer." (if (eq (length completions) 1) (setq default (car completions))) (if completions - (let ((input (completing-read (if default - (concat - "Follow reference named (default " - default "): ") - "Follow reference named: ") - completions nil t))) + (let ((input (completing-read (format-prompt "Follow reference named" + default) + completions nil t))) (list (if (equal input "") default input) current-prefix-arg)) @@ -4049,6 +4065,7 @@ If FORK is non-nil, it is passed to `Info-goto-node'." (define-key map "e" 'end-of-buffer) (define-key map "f" 'Info-follow-reference) (define-key map "g" 'Info-goto-node) + (define-key map "G" 'Info-goto-node-web) (define-key map "h" 'Info-help) ;; This is for compatibility with standalone info (>~ version 5.2). ;; Though for some time, standalone info had H and h reversed. @@ -4653,7 +4670,7 @@ the variable `Info-file-list-for-emacs'." (defvar Info-link-keymap (let ((keymap (make-sparse-keymap))) (define-key keymap [header-line down-mouse-1] 'mouse-drag-header-line) - (define-key keymap [header-line mouse-1] 'mouse-select-window) + (define-key keymap [header-line mouse-1] 'Info-mouse-follow-link) (define-key keymap [header-line mouse-2] 'Info-mouse-follow-link) (define-key keymap [mouse-2] 'Info-mouse-follow-link) (define-key keymap [follow-link] 'mouse-face) @@ -4858,9 +4875,16 @@ first line or header line, and for breadcrumb links.") ;; an end of sentence (skip-syntax-backward " (")) (setq other-tag - (cond ((save-match-data (looking-back "\\(^\\| \\)see" + (cond ((save-match-data (looking-back "\\(^\\|[ (]\\)see" (- (point) 4))) "") + ;; We want "Also *note" to produce + ;; "Also see", but "See also *note" to produce + ;; "See also", so match case-sensitively. + ((save-match-data (let ((case-fold-search nil)) + (looking-back "\\(^\\| \\)also" + (- (point) 5)))) + "") ((save-match-data (looking-back "\\(^\\| \\)in" (- (point) 3))) "") @@ -5402,6 +5426,7 @@ type returned by `Info-bookmark-make-record', which see." (bookmark-default-handler `("" (buffer . ,buf) . ,(bookmark-get-bookmark-record bmk))))) +(put 'Info-bookmark-jump 'bookmark-handler-type "Info") ;;;###autoload (defun info-display-manual (manual) |