📄 info.el
字号:
;;; info.el --- info package for Emacs.;; Copyright (C) 1985, 86, 92, 93, 94, 95, 96, 97 Free Software;; Foundation, Inc.;; Maintainer: FSF;; Keywords: help;; This file is part of GNU Emacs.;; GNU Emacs is free software; you can redistribute it and/or modify;; it under the terms of the GNU General Public License as published by;; the Free Software Foundation; either version 2, or (at your option);; any later version.;; GNU Emacs is distributed in the hope that it will be useful,;; but WITHOUT ANY WARRANTY; without even the implied warranty of;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the;; GNU General Public License for more details.;; You should have received a copy of the GNU General Public License;; along with GNU Emacs; see the file COPYING. If not, write to the;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,;; Boston, MA 02111-1307, USA.;;; Commentary:;; Note that nowadays we expect info files to be made using makeinfo.;;; Code:(defgroup info nil "Info subsystem" :group 'help :group 'docs)(defvar Info-history nil "List of info nodes user has visited.Each element of list is a list (FILENAME NODENAME BUFFERPOS).")(defcustom Info-enable-edit nil "*Non-nil means the \\<Info-mode-map>\\[Info-edit] command in Info can edit the current node.This is convenient if you want to write info files by hand.However, we recommend that you not do this.It is better to write a Texinfo file and generate the Info file from that,because that gives you a printed manual as well." :type 'boolean :group 'info)(defvar Info-enable-active-nodes nil "Non-nil allows Info to execute Lisp code associated with nodes.The Lisp code is executed when the node is selected.")(put 'Info-enable-active-nodes 'risky-local-variable t)(defcustom Info-fontify t "*Non-nil enables highlighting and fonts in Info nodes." :type 'boolean :group 'info)(defcustom Info-fontify-maximum-menu-size 30000 "*Maximum size of menu to fontify if `Info-fontify' is non-nil." :type 'integer :group 'info)(defvar Info-directory-list (let ((path (getenv "INFOPATH")) ;; This is for older Emacs versions ;; which might get this info.el from the Texinfo distribution. (path-separator (if (boundp 'path-separator) path-separator (if (eq system-type 'ms-dos) ";" ":"))) (source (expand-file-name "info/" source-directory)) (sibling (if installation-directory (expand-file-name "info/" installation-directory))) alternative) (if path (let ((list nil) idx) (while (> (length path) 0) (setq idx (or (string-match path-separator path) (length path)) list (cons (substring path 0 idx) list) path (substring path (min (1+ idx) (length path))))) (nreverse list)) (if (and sibling (file-exists-p sibling)) (setq alternative sibling) (setq alternative source)) (if (or (member alternative Info-default-directory-list) (not (file-exists-p alternative)) ;; On DOS/NT, we use movable executables always, ;; and we must always find the Info dir at run time. (if (or (eq system-type 'ms-dos) (eq system-type '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))))) Info-default-directory-list (reverse (cons alternative (cdr (reverse Info-default-directory-list))))))) "List of directories to search for Info documentation files.nil means not yet initialized. In this case, Info uses the environmentvariable INFOPATH to initialize it, or `Info-default-directory-list'if there is no INFOPATH variable in the environment.The last element of `Info-default-directory-list' is the directorywhere Emacs installs the Info files that come with it.If you run the Emacs executable from the `src' directory in the Emacssource tree, the `info' directory in the source tree is used as the lastelement, in place of the installation Info directory. This is usefulwhen you run a version of Emacs without installing it.")(defcustom Info-additional-directory-list nil "List of additional directories to search for Info documentation files.These directories are not searched for merging the `dir' file." :type '(repeat directory) :group 'info)(defvar Info-current-file nil "Info file that Info is now looking at, or nil.This is the name that was specified in Info, not the actual file name.It doesn't contain directory names or file name extensions added by Info.")(defvar Info-current-subfile nil "Info subfile that is actually in the *info* buffer now,or nil if current info file is not split into subfiles.")(defvar Info-current-node nil "Name of node that Info is now looking at, or nil.")(defvar Info-tag-table-marker nil "Marker pointing at beginning of current Info file's tag table.Marker points nowhere if file has no tag table.")(defvar Info-tag-table-buffer nil "Buffer used for indirect tag tables.")(defvar Info-current-file-completions nil "Cached completion list for current Info file.")(defvar Info-index-alternatives nil "List of possible matches for last Info-index command.")(defvar Info-standalone nil "Non-nil if Emacs was started solely as an Info browser.")(defvar Info-suffix-list (if (eq system-type 'ms-dos) '( (".gz" . "gunzip") (".z" . "gunzip") (".inf" . nil) ("" . nil)) '( (".info.Z". "uncompress") (".info.Y". "unyabba") (".info.gz". "gunzip") (".info.z". "gunzip") (".info". nil) ("-info.Z". "uncompress") ("-info.Y". "unyabba") ("-info.gz". "gunzip") ("-info.z". "gunzip") ("-info". nil) ("/index.Z". "uncompress") ("/index.Y". "unyabba") ("/index.gz". "gunzip") ("/index.z". "gunzip") ("/index". nil) (".Z". "uncompress") (".Y". "unyabba") (".gz". "gunzip") (".z". "gunzip") ("". nil))) "List of file name suffixes and associated decoding commands.Each entry should be (SUFFIX . STRING); the file is given tothe command as standard input. If STRING is nil, no decoding is done.Because the SUFFIXes are tried in order, the empty string shouldbe last in the list.");; Concatenate SUFFIX onto FILENAME. SUFFIX should start with a dot.;; First, on ms-dos, delete some of the extension in FILENAME;; to make room.(defun info-insert-file-contents-1 (filename suffix) (if (not (eq system-type 'ms-dos)) (concat filename suffix) (let* ((sans-exts (file-name-sans-extension filename)) ;; How long is the extension in FILENAME (not counting the dot). (ext-len (max 0 (- (length filename) (length sans-exts) 1))) ext-left) ;; SUFFIX starts with a dot. If FILENAME already has one, ;; get rid of the one in SUFFIX (unless suffix is empty). (or (and (<= ext-len 0) (not (eq (aref filename (1- (length filename))) ?.))) (= (length suffix) 0) (setq suffix (substring suffix 1))) ;; How many chars of that extension should we keep? (setq ext-left (min ext-len (max 0 (- 3 (length suffix))))) ;; Get rid of the rest of the extension, and add SUFFIX. (concat (substring filename 0 (- (length filename) (- ext-len ext-left))) suffix))))(defun info-insert-file-contents (filename &optional visit) "Insert the contents of an info file in the current buffer.Do the right thing if the file has been compressed or zipped." (let ((tail Info-suffix-list) fullname decoder) (if (file-exists-p filename) ;; FILENAME exists--see if that name contains a suffix. ;; If so, set DECODE accordingly. (progn (while (and tail (not (string-match (concat (regexp-quote (car (car tail))) "$") filename))) (setq tail (cdr tail))) (setq fullname filename decoder (cdr (car tail)))) ;; Try adding suffixes to FILENAME and see if we can find something. (while (and tail (not (file-exists-p (info-insert-file-contents-1 filename (car (car tail)))))) (setq tail (cdr tail))) ;; If we found a file with a suffix, set DECODER according to the suffix ;; and set FULLNAME to the file's actual name. (setq fullname (info-insert-file-contents-1 filename (car (car tail))) decoder (cdr (car tail))) (or tail (error "Can't find %s or any compressed version of it" filename))) ;; check for conflict with jka-compr (if (and (featurep 'jka-compr) (jka-compr-installed-p) (jka-compr-get-compression-info fullname)) (setq decoder nil)) (insert-file-contents fullname visit) (if decoder (let ((buffer-read-only nil) (default-directory (or (file-name-directory fullname) default-directory))) (call-process-region (point-min) (point-max) decoder t t)))));;;###autoload (add-hook 'same-window-buffer-names "*info*");;;###autoload(defun info (&optional file) "Enter Info, the documentation browser.Optional argument FILE specifies the file to examine;the default is the top-level directory of Info.In interactive use, a prefix argument directs this commandto read a file name from the minibuffer.The search path for Info files is in the variable `Info-directory-list'.The top-level Info directory is made by combining all the files named `dir' in all the directories in that path." (interactive (if current-prefix-arg (list (read-file-name "Info file name: " nil nil t)))) (if file (Info-goto-node (concat "(" file ")")) (if (get-buffer "*info*") (pop-to-buffer "*info*") (Info-directory))));;;###autoload(defun info-standalone () "Run Emacs as a standalone Info reader.Usage: emacs -f info-standalone [filename]In standalone mode, \\<Info-mode-map>\\[Info-exit] exits Emacs itself." (setq Info-standalone t) (if (and command-line-args-left (not (string-match "^-" (car command-line-args-left)))) (condition-case err (progn (info (car command-line-args-left)) (setq command-line-args-left (cdr command-line-args-left))) (error (send-string-to-terminal (format "%s\n" (if (eq (car-safe err) 'error) (nth 1 err) err))) (save-buffers-kill-emacs))) (info)));; Go to an info node specified as separate filename and nodename.;; no-going-back is non-nil if recovering from an error in this function;;; it says do not attempt further (recursive) error recovery.(defun Info-find-node (filename nodename &optional no-going-back) ;; Convert filename to lower case if not found as specified. ;; Expand it. (if filename (let (temp temp-downcase found) (setq filename (substitute-in-file-name filename)) (if (string= (downcase filename) "dir") (setq found t) (let ((dirs (if (string-match "^\\./" filename) ;; If specified name starts with `./' ;; then just try current directory. '("./") (if (file-name-absolute-p filename) ;; No point in searching for an ;; absolute file name '(nil) (if Info-additional-directory-list (append Info-directory-list Info-additional-directory-list) Info-directory-list))))) ;; Search the directory list for file FILENAME. (while (and dirs (not found)) (setq temp (expand-file-name filename (car dirs))) (setq temp-downcase (expand-file-name (downcase filename) (car dirs))) ;; Try several variants of specified name. (let ((suffix-list Info-suffix-list)) (while (and suffix-list (not found)) (cond ((file-exists-p (info-insert-file-contents-1 temp (car (car suffix-list)))) (setq found temp)) ((file-exists-p (info-insert-file-contents-1 temp-downcase (car (car suffix-list)))) (setq found temp-downcase))) (setq suffix-list (cdr suffix-list)))) (setq dirs (cdr dirs))))) (if found (setq filename found) (error "Info file %s does not exist" filename)))) ;; Record the node we are leaving. (if (and Info-current-file (not no-going-back)) (setq Info-history (cons (list Info-current-file Info-current-node (point)) Info-history))) ;; Go into info buffer. (or (eq major-mode 'Info-mode) (pop-to-buffer "*info*")) (buffer-disable-undo (current-buffer)) (or (eq major-mode 'Info-mode) (Info-mode)) (widen) (setq Info-current-node nil) (unwind-protect (progn ;; Switch files if necessary (or (null filename) (equal Info-current-file filename) (let ((buffer-read-only nil)) (setq Info-current-file nil Info-current-subfile nil Info-current-file-completions nil buffer-file-name nil) (erase-buffer) (if (eq filename t) (Info-insert-dir) (info-insert-file-contents filename t) (setq default-directory (file-name-directory filename))) (set-buffer-modified-p nil) ;; See whether file has a tag table. Record the location if yes. (goto-char (point-max)) (forward-line -8) ;; Use string-equal, not equal, to ignore text props. (if (not (or (string-equal nodename "*") (not (search-forward "\^_\nEnd tag table\n" nil t)))) (let (pos) ;; We have a tag table. Find its beginning. ;; Is this an indirect file? (search-backward "\nTag table:\n") (setq pos (point)) (if (save-excursion
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -