comparison lisp/info.el @ 2561:1bd4cf98df68

(Info-find-node, Info-insert-subfile): Do the right thing if info files have been compressed or gzipped. This is saving me lots of disk space.
author Eric S. Raymond <esr@snark.thyrsus.com>
date Fri, 23 Apr 1993 02:20:55 +0000
parents dd9ab1e9467e
children fa1b6b4e8409
comparison
equal deleted inserted replaced
2560:50d7841854b3 2561:1bd4cf98df68
64 "Name of node that Info is now looking at, or nil.") 64 "Name of node that Info is now looking at, or nil.")
65 65
66 (defvar Info-tag-table-marker (make-marker) 66 (defvar Info-tag-table-marker (make-marker)
67 "Marker pointing at beginning of current Info file's tag table. 67 "Marker pointing at beginning of current Info file's tag table.
68 Marker points nowhere if file has no tag table.") 68 Marker points nowhere if file has no tag table.")
69
70 (defvar Info-index-alternatives nil
71 "List of possible matches for last Info-index command.")
72
73 (defvar Info-suffix-list '( ("" . nil)
74 (".info" . nil)
75 (".Z" . "uncompress")
76 (".Y" . "unyabba")
77 (".z" . "gunzip")
78 (".info.Z" . "uncompress")
79 (".info.Y" . "unyabba")
80 (".z" . "gunzip"))
81 "List of file name suffixes and associated decoding commands.
82 Each entry should be (SUFFIX . STRING); the file is given to
83 the command as standard input. If STRING is nil, no decoding is done.")
84
85 (defun info-insert-file-contents (filename &optional visit)
86 "Insert the contents of an info file in the current buffer.
87 Do the right thing if the file has been compressed or zipped."
88 (if (null (catch 'ok
89 (mapcar
90 (function
91 (lambda (x)
92 (let ((compressed (concat filename (car x))))
93 (if (file-exists-p compressed)
94 (progn
95 (insert-file-contents compressed visit)
96 (if (cdr x)
97 (let ((buffer-read-only nil))
98 (shell-command-on-region
99 (point-min) (point-max) (cdr x) t)))
100 (throw 'ok t))))))
101 Info-suffix-list)
102 nil))
103 (error "Can't find %s or any compressed version of it!" filename)))
69 104
70 ;;;###autoload 105 ;;;###autoload
71 (defun info (&optional file) 106 (defun info (&optional file)
72 "Enter Info, the documentation browser. 107 "Enter Info, the documentation browser.
73 Optional argument FILE specifies the file to examine; 108 Optional argument FILE specifies the file to examine;
116 (while (and dirs (not found)) 151 (while (and dirs (not found))
117 (setq temp (expand-file-name filename (car dirs))) 152 (setq temp (expand-file-name filename (car dirs)))
118 (setq temp-downcase 153 (setq temp-downcase
119 (expand-file-name (downcase filename) (car dirs))) 154 (expand-file-name (downcase filename) (car dirs)))
120 ;; Try several variants of specified name. 155 ;; Try several variants of specified name.
121 ;; Try downcasing, appending `.info', or both. 156 (catch 'foundit
122 (cond ((file-exists-p temp) 157 (mapcar
123 (setq found temp)) 158 (function
124 ((file-exists-p temp-downcase) 159 (lambda (x)
125 (setq found temp-downcase)) 160 (if (file-exists-p (concat temp (car x)))
126 ((file-exists-p (concat temp ".info")) 161 (progn
127 (setq found (concat temp ".info"))) 162 (setq found temp)
128 ((file-exists-p (concat temp-downcase ".info")) 163 (throw 'foundit nil)))
129 (setq found (concat temp-downcase ".info")))) 164 (if (file-exists-p (concat temp-downcase (car x)))
165 (progn
166 (setq found temp-downcase)
167 (throw 'foundit nil)))))
168 Info-suffix-list))
130 (setq dirs (cdr dirs))))) 169 (setq dirs (cdr dirs)))))
131 (if found 170 (if found
132 (setq filename found) 171 (setq filename found)
133 (error "Info file %s does not exist" filename)))) 172 (error "Info file %s does not exist" filename))))
134 ;; Record the node we are leaving. 173 ;; Record the node we are leaving.
149 (or (null filename) 188 (or (null filename)
150 (equal Info-current-file filename) 189 (equal Info-current-file filename)
151 (let ((buffer-read-only nil)) 190 (let ((buffer-read-only nil))
152 (setq Info-current-file nil 191 (setq Info-current-file nil
153 Info-current-subfile nil 192 Info-current-subfile nil
193 Info-index-alternatives nil
154 buffer-file-name nil) 194 buffer-file-name nil)
155 (erase-buffer) 195 (erase-buffer)
156 (if (eq filename t) 196 (if (eq filename t)
157 (Info-insert-dir) 197 (Info-insert-dir)
158 (insert-file-contents filename t) 198 (info-insert-file-contents filename t)
159 (setq default-directory (file-name-directory filename))) 199 (setq default-directory (file-name-directory filename)))
160 (set-buffer-modified-p nil) 200 (set-buffer-modified-p nil)
161 ;; See whether file has a tag table. Record the location if yes. 201 ;; See whether file has a tag table. Record the location if yes.
162 (set-marker Info-tag-table-marker nil) 202 (set-marker Info-tag-table-marker nil)
163 (goto-char (point-max)) 203 (goto-char (point-max))
379 (or (equal Info-current-subfile lastfilename) 419 (or (equal Info-current-subfile lastfilename)
380 (let ((buffer-read-only nil)) 420 (let ((buffer-read-only nil))
381 (setq buffer-file-name nil) 421 (setq buffer-file-name nil)
382 (widen) 422 (widen)
383 (erase-buffer) 423 (erase-buffer)
384 (insert-file-contents lastfilename) 424 (info-insert-file-contents lastfilename)
385 (set-buffer-modified-p nil) 425 (set-buffer-modified-p nil)
386 (setq Info-current-subfile lastfilename))) 426 (setq Info-current-subfile lastfilename)))
387 (goto-char (point-min)) 427 (goto-char (point-min))
388 (search-forward "\n\^_") 428 (search-forward "\n\^_")
389 (+ (- nodepos lastfilepos) (point)))) 429 (+ (- nodepos lastfilepos) (point))))
868 (if (pos-visible-in-window-p (point-min)) 908 (if (pos-visible-in-window-p (point-min))
869 (Info-last-preorder) 909 (Info-last-preorder)
870 (scroll-down)) 910 (scroll-down))
871 ) 911 )
872 912
913 (defun Info-index (topic)
914 "Look up a string in the index for this file.
915 The index is defined as the first node in the top-level menu whose
916 name contains the word \"Index\", plus any immediately following
917 nodes whose names also contain the word \"Index\".
918 If there are no exact matches to the specified topic, this chooses
919 the first match which is a case-insensitive substring of a topic.
920 Use the `,' command to see the other matches.
921 Give a blank topic name to go to the Index node itself."
922 (interactive "sIndex topic: ")
923 (let ((orignode Info-current-node)
924 (rnode nil)
925 (pattern (format "\n\\* \\([^\n:]*%s[^\n:]*\\):[ \t]*\\([^.\n]*\\)\\.[ t]*\\([0-9]*\\)"
926 (regexp-quote topic)))
927 node)
928 (Info-goto-node "Top")
929 (or (search-forward "\n* menu:" nil t)
930 (error "No index"))
931 (or (re-search-forward "\n\\* \\(.*\\<Index\\>\\)" nil t)
932 (error "No index"))
933 (goto-char (match-beginning 1))
934 (let ((Info-keeping-history nil))
935 (Info-goto-node (Info-extract-menu-node-name)))
936 (or (equal topic "")
937 (let ((matches nil)
938 (exact nil)
939 (Info-keeping-history nil)
940 found)
941 (while
942 (progn
943 (goto-char (point-min))
944 (while (re-search-forward pattern nil t)
945 (setq matches
946 (cons (list (buffer-substring (match-beginning 1)
947 (match-end 1))
948 (buffer-substring (match-beginning 2)
949 (match-end 2))
950 Info-current-node
951 (string-to-int (concat "0"
952 (buffer-substring
953 (match-beginning 3)
954 (match-end 3)))))
955 matches)))
956 (and (setq node (Info-extract-pointer "next" t))
957 (string-match "\\<Index\\>" node)))
958 (Info-goto-node node))
959 (or matches
960 (progn
961 (Info-last)
962 (error "No \"%s\" in index" topic)))
963 ;; Here it is a feature that assoc is case-sensitive.
964 (while (setq found (assoc topic matches))
965 (setq exact (cons found exact)
966 matches (delq found matches)))
967 (setq Info-index-alternatives (nconc exact (nreverse matches)))
968 (Info-index-next 0)))))
969
970 (defun Info-index-next (num)
971 "Go to the next matching index item from the last `i' command."
972 (interactive "p")
973 (or Info-index-alternatives
974 (error "No previous `i' command in this file"))
975 (while (< num 0)
976 (setq num (+ num (length Info-index-alternatives))))
977 (while (> num 0)
978 (setq Info-index-alternatives
979 (nconc (cdr Info-index-alternatives)
980 (list (car Info-index-alternatives)))
981 num (1- num)))
982 (Info-goto-node (nth 1 (car Info-index-alternatives)))
983 (if (> (nth 3 (car Info-index-alternatives)) 0)
984 (forward-line (nth 3 (car Info-index-alternatives)))
985 (forward-line 3) ; don't search in headers
986 (let ((name (car (car Info-index-alternatives))))
987 (if (or (re-search-forward (format
988 "\\(Function\\|Command\\): %s\\( \\|$\\)"
989 (regexp-quote name)) nil t)
990 (search-forward (format "`%s'" name) nil t)
991 (and (string-match "\\`.*\\( (.*)\\)\\'" name)
992 (search-forward
993 (format "`%s'" (substring name 0 (match-beginning 1)))
994 nil t))
995 (search-forward name nil t))
996 (beginning-of-line)
997 (goto-char (point-min)))))
998 (message "Found \"%s\" in %s. %s"
999 (car (car Info-index-alternatives))
1000 (nth 2 (car Info-index-alternatives))
1001 (if (cdr Info-index-alternatives)
1002 "(Press `,' for more)"
1003 "(Only match)")))
1004
873 (defun Info-undefined () 1005 (defun Info-undefined ()
874 "Make command be undefined in Info." 1006 "Make command be undefined in Info."
875 (interactive) 1007 (interactive)
876 (ding)) 1008 (ding))
877 1009
989 (define-key Info-mode-map "d" 'Info-directory) 1121 (define-key Info-mode-map "d" 'Info-directory)
990 (define-key Info-mode-map "e" 'Info-edit) 1122 (define-key Info-mode-map "e" 'Info-edit)
991 (define-key Info-mode-map "f" 'Info-follow-reference) 1123 (define-key Info-mode-map "f" 'Info-follow-reference)
992 (define-key Info-mode-map "g" 'Info-goto-node) 1124 (define-key Info-mode-map "g" 'Info-goto-node)
993 (define-key Info-mode-map "h" 'Info-help) 1125 (define-key Info-mode-map "h" 'Info-help)
1126 (define-key Info-mode-map "i" 'Info-index)
994 (define-key Info-mode-map "l" 'Info-last) 1127 (define-key Info-mode-map "l" 'Info-last)
995 (define-key Info-mode-map "m" 'Info-menu) 1128 (define-key Info-mode-map "m" 'Info-menu)
996 (define-key Info-mode-map "n" 'Info-next) 1129 (define-key Info-mode-map "n" 'Info-next)
997 (define-key Info-mode-map "p" 'Info-prev) 1130 (define-key Info-mode-map "p" 'Info-prev)
998 (define-key Info-mode-map "q" 'Info-exit) 1131 (define-key Info-mode-map "q" 'Info-exit)
999 (define-key Info-mode-map "s" 'Info-search) 1132 (define-key Info-mode-map "s" 'Info-search)
1133 (define-key Info-mode-map "t" 'Info-top)
1000 (define-key Info-mode-map "u" 'Info-up) 1134 (define-key Info-mode-map "u" 'Info-up)
1135 (define-key Info-mode-map "," 'Info-index-next)
1001 (define-key Info-mode-map "\177" 'Info-scroll-down) 1136 (define-key Info-mode-map "\177" 'Info-scroll-down)
1002 (define-key Info-mode-map [mouse-3] 'Info-follow-nearest-node) 1137 (define-key Info-mode-map [mouse-3] 'Info-follow-nearest-node)
1003 ) 1138 )
1004 1139
1005 ;; Info mode is suitable only for specially formatted data. 1140 ;; Info mode is suitable only for specially formatted data.
1021 \\[Info-menu] Pick menu item specified by name (or abbreviation). 1156 \\[Info-menu] Pick menu item specified by name (or abbreviation).
1022 Picking a menu item causes another node to be selected. 1157 Picking a menu item causes another node to be selected.
1023 \\[Info-directory] Go to the Info directory node. 1158 \\[Info-directory] Go to the Info directory node.
1024 \\[Info-follow-reference] Follow a cross reference. Reads name of reference. 1159 \\[Info-follow-reference] Follow a cross reference. Reads name of reference.
1025 \\[Info-last] Move to the last node you were at. 1160 \\[Info-last] Move to the last node you were at.
1161 \\[Info-index] Look up a topic in this file's Index and move to that node.
1162 \\[Info-index-next] (comma) Move to the next match from a previous `i' command.
1026 1163
1027 Moving within a node: 1164 Moving within a node:
1028 \\[scroll-up] Normally, scroll forward a full screen. If the end of the buffer is 1165 \\[scroll-up] Normally, scroll forward a full screen. If the end of the buffer is
1029 already visible, try to go to the next menu entry, or up if there is none. 1166 already visible, try to go to the next menu entry, or up if there is none.
1030 \\[scroll-down] Normally, scroll backward. If the beginning of the buffer is 1167 \\[scroll-down] Normally, scroll backward. If the beginning of the buffer is
1054 (make-local-variable 'Info-current-file) 1191 (make-local-variable 'Info-current-file)
1055 (make-local-variable 'Info-current-subfile) 1192 (make-local-variable 'Info-current-subfile)
1056 (make-local-variable 'Info-current-node) 1193 (make-local-variable 'Info-current-node)
1057 (make-local-variable 'Info-tag-table-marker) 1194 (make-local-variable 'Info-tag-table-marker)
1058 (make-local-variable 'Info-history) 1195 (make-local-variable 'Info-history)
1196 (make-local-variable 'Info-index-alternatives)
1059 (Info-set-mode-line) 1197 (Info-set-mode-line)
1060 (run-hooks 'Info-mode-hook)) 1198 (run-hooks 'Info-mode-hook))
1061 1199
1062 (defvar Info-edit-map nil 1200 (defvar Info-edit-map nil
1063 "Local keymap used within `e' command of Info.") 1201 "Local keymap used within `e' command of Info.")