|
|
1.1 root 1: ;; Info package for Emacs -- could use a "create node" feature.
2: ;; Copyright (C) 1985 Richard M. Stallman.
3:
4: ;; This file is part of GNU Emacs.
5:
6: ;; GNU Emacs is distributed in the hope that it will be useful,
7: ;; but WITHOUT ANY WARRANTY. No author or distributor
8: ;; accepts responsibility to anyone for the consequences of using it
9: ;; or for whether it serves any particular purpose or works at all,
10: ;; unless he says so in writing. Refer to the GNU Emacs General Public
11: ;; License for full details.
12:
13: ;; Everyone is granted permission to copy, modify and redistribute
14: ;; GNU Emacs, but only under the conditions described in the
15: ;; GNU Emacs General Public License. A copy of this license is
16: ;; supposed to have been given to you along with GNU Emacs so you
17: ;; can know your rights and responsibilities. It should be in a
18: ;; file named COPYING. Among other things, the copyright notice
19: ;; and this notice must be preserved on all copies.
20:
21:
22: (defvar Info-history nil
23: "List of info nodes user has visited.
24: Each element of list is a list (FILENAME NODENAME BUFFERPOS).")
25:
26: (defvar Info-enable-edit nil
27: "Non-nil means the \\[Info-edit] command in Info can edit the current node.")
28:
29: (defvar Info-enable-active-nodes t
30: "Non-nil allows Info to execute Lisp code associated with nodes.
31: The Lisp code is executed when the node is selected.")
32:
33: (defvar Info-directory nil
34: "Default directory for Info documentation files.")
35:
36: (defvar Info-current-file nil
37: "Info file that Info is now looking at, or nil.")
38:
39: (defvar Info-current-node nil
40: "Name of node that Info is now looking at, or nil.")
41:
42: (defvar Info-tag-table-marker (make-marker)
43: "Marker pointing at beginning of current Info file's tag table.
44: Marker points nowhere if file has no tag table.")
45:
46: (defun info ()
47: "Create a buffer for Info, the documentation browser program."
48: (interactive)
49: (if (get-buffer "*info*")
50: (switch-to-buffer "*info*")
51: (Info-directory)))
52:
53: ;; Go to an info node specified as separate filename and nodename.
54: ;; no-going-back is non-nil if recovering from an error in this function;
55: ;; it says do not attempt further (recursive) error recovery.
56: (defun Info-find-node (filename nodename &optional no-going-back)
57: ;; Convert filename to lower case if not found as specified.
58: ;; Expand it.
59: (if filename
60: (let (temp)
61: (setq filename (substitute-in-file-name filename))
62: (setq temp (expand-file-name filename Info-directory))
63: (if (file-exists-p temp)
64: (setq filename temp)
65: (setq temp (expand-file-name (downcase filename) Info-directory))
66: (if (file-exists-p temp)
67: (setq filename temp)
68: (error "Info file %s does not exist"
69: (expand-file-name filename Info-directory))))))
70: ;; Record the node we are leaving.
71: (if (and Info-current-file (not no-going-back))
72: (setq Info-history
73: (cons (list Info-current-file Info-current-node (point))
74: Info-history)))
75: ;; Go into info buffer.
76: (switch-to-buffer "*info*")
77: (Info-mode)
78: (widen)
79: (setq Info-current-file nil Info-current-node nil)
80: (unwind-protect
81: (progn
82: ;; Switch files if necessary
83: (or (null filename)
84: (equal buffer-file-name filename)
85: (let ((buffer-read-only nil))
86: (erase-buffer)
87: (insert-file-contents filename t)
88: ;; See whether file has a tag table. Record the location if yes.
89: (move-marker Info-tag-table-marker nil)
90: (goto-char (point-max))
91: (forward-line -8)
92: (if (search-forward "\^_\nEnd tag table\n" nil t)
93: (progn
94: (search-backward "\nTag table:\n")
95: (move-marker Info-tag-table-marker (match-end 0))))))
96: (if (equal nodename "*")
97: (progn (setq Info-current-file buffer-file-name
98: Info-current-node nodename)
99: (Info-set-mode-line))
100: ;; Search file for a suitable node.
101: ;; First get advice from tag table if file has one.
102: (if (marker-position Info-tag-table-marker)
103: (progn
104: (goto-char Info-tag-table-marker)
105: (if (search-forward (concat "Node: " nodename "\177") nil t)
106: (goto-char (max (point-min) (- (read (current-buffer)) 1000)))
107: (error "No such node: %s" nodename)))
108: (goto-char (point-min)))
109: (let ((regexp (concat "Node: *" (regexp-quote nodename) " *[,\t\n]")))
110: (catch 'foo
111: (while (search-forward "\n\^_" nil t)
112: (forward-line 1)
113: (let ((beg (point)))
114: (forward-line 1)
115: (if (re-search-backward regexp beg t)
116: (throw 'foo t))))
117: (error "No such node: %s" nodename)))
118: (Info-select-node)))
119: ;; If we did not finish finding the specified node,
120: ;; go back to the previous one.
121: (or Info-current-node no-going-back
122: (let ((hist (car Info-history)))
123: (setq Info-history (cdr Info-history))
124: (Info-find-node (nth 0 hist) (nth 1 hist) t)
125: (goto-char (nth 2 hist)))))
126: (goto-char (point-min)))
127:
128: ;; Select the info node that point is in.
129: (defun Info-select-node ()
130: (save-excursion
131: ;; Find beginning of node.
132: (search-backward "\n\^_")
133: (forward-line 2)
134: ;; Get nodename spelled as it is in the node.
135: (re-search-forward "Node:[ \t]*")
136: (setq Info-current-node
137: (buffer-substring (point)
138: (progn
139: (skip-chars-forward "^,\t\n")
140: (point))))
141: (setq Info-current-file buffer-file-name)
142: (Info-set-mode-line)
143: ;; Find the end of it, and narrow.
144: (beginning-of-line)
145: (let (active-expression)
146: (narrow-to-region (point)
147: (if (re-search-forward "\n[\^_\f]" nil t)
148: (prog1
149: (1- (point))
150: (if (looking-at "[\n\^_\f]*execute: ")
151: (progn
152: (goto-char (match-end 0))
153: (setq active-expression
154: (read (current-buffer))))))
155: (point-max)))
156: (if Info-enable-active-nodes (eval active-expression)))))
157:
158: (defun Info-set-mode-line ()
159: (setq mode-line-format
160: (concat
161: "--%1*%1*-Info: ("
162: (if buffer-file-name
163: (file-name-nondirectory buffer-file-name)
164: "")
165: ")"
166: (or Info-current-node "")
167: " %M %[(%m)%]----%3p-%-")))
168:
169: ;; Go to an info node specified with a filename-and-nodename string
170: ;; of the sort that is found in pointers in nodes.
171:
172: (defun Info-goto-node (nodename)
173: "Go to info node named NAME. Give just NODENAME or (FILENAME)NODENAME."
174: (interactive "sGoto node: ")
175: (let (filename)
176: (string-match "\\s *\\((\\s *\\([^\t)]*\\)\\s *)\\s *\\|\\)\\(.*\\)"
177: nodename)
178: (setq filename (substring nodename (match-beginning 2) (match-end 2))
179: nodename (substring nodename (match-beginning 3) (match-end 3)))
180: (let ((trim (string-match "\\s *\\'" filename)))
181: (if trim (setq filename (substring filename 0 trim))))
182: (let ((trim (string-match "\\s *\\'" nodename)))
183: (if trim (setq nodename (substring nodename 0 trim))))
184: (Info-find-node (if (equal filename "") nil filename)
185: (if (equal nodename "") "Top" nodename))))
186:
187: (defun Info-tagify ()
188: "Create or update tag table of current info file."
189: (interactive)
190: ;; Save and restore point and restrictions.
191: ;; save-restrictions would not work
192: ;; because it records the old max relative to the end.
193: ;; We record it relative to the beginning.
194: (let ((omin (point-min))
195: (omax (point-max))
196: (opoint (point)))
197: (unwind-protect
198: (progn
199: (widen)
200: (goto-char (point-min))
201: (let ((regexp "Node:[ \t]*\\([^,\n\t]\\)*[,\t\n]")
202: (case-fold-search t)
203: list)
204: (while (search-forward "\n\^_" nil t)
205: (forward-line 1)
206: (let ((beg (point)))
207: (forward-line 1)
208: (if (re-search-backward regexp beg t)
209: (setq list
210: (cons (list (buffer-substring
211: (match-beginning 1)
212: (match-end 1))
213: beg)
214: list)))))
215: (goto-char (point-max))
216: (forward-line -8)
217: (let ((buffer-read-only nil))
218: (if (search-forward "\^_\nEnd tag table\n" nil t)
219: (let ((end (point)))
220: (search-backward "\nTag table:\n")
221: (beginning-of-line)
222: (delete-region (point) end)))
223: (goto-char (point-max))
224: (insert "\^_\f\nTag table:\n")
225: (move-marker Info-tag-table-marker (point))
226: (setq list (nreverse list))
227: (while list
228: (insert "Node: " (car (car list)) ?\177)
229: (princ (car (cdr (car list))) (current-buffer))
230: (insert ?\n)
231: (setq list (cdr list)))
232: (insert "\^_\nEnd tag table\n"))))
233: (goto-char opoint)
234: (narrow-to-region omin (min omax (point-max))))))
235:
236: (defun Info-validate ()
237: "Check that every node pointer points to an existing node."
238: (interactive)
239: (save-excursion
240: (save-restriction
241: (widen)
242: (goto-char (point-min))
243: (let ((allnodes '(("*")))
244: (regexp "Node:[ \t]*\\([^,\n\t]*\\)[,\t\n]")
245: (case-fold-search t)
246: (tags-losing nil)
247: (lossages ()))
248: (while (search-forward "\n\^_" nil t)
249: (forward-line 1)
250: (let ((beg (point)))
251: (forward-line 1)
252: (if (re-search-backward regexp beg t)
253: (setq allnodes
254: (cons (list (downcase
255: (buffer-substring
256: (match-beginning 1)
257: (progn
258: (goto-char (match-end 1))
259: (skip-chars-backward " \t")
260: (point))))
261: (progn
262: (end-of-line)
263: (and (re-search-backward "prev[ious]*:"
264: beg t)
265: (progn
266: (goto-char (match-end 0))
267: (downcase
268: (Info-following-node-name)))))
269: (point))
270: allnodes)))))
271: (goto-char (point-min))
272: (while (search-forward "\n\^_" nil t)
273: (forward-line 1)
274: (let ((beg (point))
275: thisnode next)
276: (forward-line 1)
277: (if (re-search-backward regexp beg t)
278: (save-restriction
279: (search-forward "\n\^_" nil 'move)
280: (narrow-to-region beg (point))
281: (setq thisnode (downcase
282: (buffer-substring
283: (match-beginning 1)
284: (progn
285: (goto-char (match-end 1))
286: (skip-chars-backward " \t")
287: (point)))))
288: (end-of-line)
289: (and (search-backward "next:" nil t)
290: (setq next (Info-validate-node-name "Next"))
291: (if (equal (car (cdr (assoc next allnodes)))
292: thisnode)
293: ;; allow multiple `next' pointers to one node
294: (let ((tem lossages))
295: (while tem
296: (if (and (equal (car (cdr (car tem)))
297: "Previous-pointer in Next")
298: (equal (car (cdr (cdr (car tem))))
299: next))
300: (setq lossages (delq (car tem) lossages)))
301: (setq tem (cdr tem))))
302: (setq lossages
303: (cons (list thisnode
304: "Previous-pointer in Next"
305: next)
306: lossages))))
307: (end-of-line)
308: (if (search-backward "prev[ious]*:" nil t)
309: (Info-validate-node-name "Previous"))
310: (end-of-line)
311: (if (search-backward "up:" nil t)
312: (Info-validate-node-name "Up"))
313: (if (search-forward "\n* Menu:" nil t)
314: (while (search-forward "\n* " nil t)
315: (Info-validate-node-name
316: (concat "menu item "
317: (buffer-substring (point)
318: (save-excursion
319: (skip-chars-forward "^:")
320: (point))))
321: (Info-extract-menu-node-name))))
322: (goto-char (point-min))
323: (while (re-search-forward "\\*note[ \n]*[^:\t]*:" nil t)
324: (goto-char (+ (match-beginning 0) 5))
325: (skip-chars-forward " \n")
326: (Info-validate-node-name
327: (concat "reference "
328: (buffer-substring (point)
329: (save-excursion
330: (skip-chars-forward "^:")
331: (point))))
332: (Info-extract-menu-node-name "Bad format cross-reference")))))))
333: (setq tags-losing (not (Info-validate-tags-table)))
334: (if (or lossages tags-losing)
335: (with-output-to-temp-buffer " *problems in info file*"
336: (while lossages
337: (princ "In node \"")
338: (princ (car (car lossages)))
339: (princ "\", invalid ")
340: (let ((tem (nth 1 (car lossages))))
341: (cond ((string-match "\n" tem)
342: (princ (substring tem 0 (match-beginning 0)))
343: (princ "..."))
344: (t
345: (princ tem))))
346: (princ ": ")
347: (let ((tem (nth 2 (car lossages))))
348: (cond ((string-match "\n" tem)
349: (princ (substring tem 0 (match-beginning 0)))
350: (princ "..."))
351: (t
352: (princ tem))))
353: (terpri)
354: (setq lossages (cdr lossages)))
355: (if tags-losing (princ "\nTags table must be recomputed\n")))
356: (message "File appears valid"))))))
357:
358: (defun Info-validate-node-name (kind &optional name)
359: (if name
360: nil
361: (goto-char (match-end 0))
362: (skip-chars-forward " \t")
363: (if (= (following-char) ?\()
364: nil
365: (setq name
366: (buffer-substring
367: (point)
368: (progn
369: (skip-chars-forward "^,\t\n")
370: (skip-chars-backward " ")
371: (point))))))
372: (if (null name)
373: nil
374: (setq name (downcase name))
375: (or (and (> (length name) 0) (= (aref name 0) ?\())
376: (assoc name allnodes)
377: (setq lossages
378: (cons (list thisnode kind name) lossages))))
379: name)
380:
381: (defun Info-validate-tags-table ()
382: (goto-char (point-min))
383: (if (not (search-forward "\^_\nEnd tag table\n" nil t))
384: t
385: (not (catch 'losing
386: (let* ((end (match-beginning 0))
387: (start (progn (search-backward "\nTag table:\n")
388: (1- (match-end 0))))
389: tem)
390: (setq tem allnodes)
391: (while tem
392: (goto-char start)
393: (or (equal (car (car tem)) "*")
394: (search-forward (concat "Node: "
395: (car (car tem))
396: "\177")
397: end t)
398: (throw 'losing 'x))
399: (setq tem (cdr tem)))
400: (goto-char (1+ start))
401: (while (looking-at ".*Node: \\(.*\\)\177\\([0-9]+\\)$")
402: (setq tem (assoc (buffer-substring
403: (match-beginning 1)
404: (match-end 1))
405: allnodes))
406: (if (or (not tem)
407: (< 1000 (progn
408: (goto-char (match-beginning 2))
409: (setq tem (- (car (cdr (cdr tem)))
410: (read (current-buffer))))
411: (if (> tem 0) tem (- tem)))))
412: (throw 'losing 'y)))
413: (forward-line 1))
414: (or (looking-at "End tag table\n")
415: (throw 'losing 'z))
416: nil))))
417:
418: (defvar Info-last-search nil
419: "Default regexp for Info S command to search for.")
420:
421: (defun Info-search (regexp)
422: "Search for REGEXP, starting from point, and select node it's found in."
423: (interactive "sSearch (regexp): ")
424: (if (equal regexp "")
425: (setq regexp Info-last-search)
426: (setq Info-last-search regexp))
427: (let (found)
428: (save-excursion
429: (save-restriction
430: (widen)
431: (re-search-forward regexp)
432: (setq found (point))))
433: (if found
434: (progn
435: (widen)
436: (goto-char found)
437: (Info-select-node)))))
438:
439: (defun Info-extract-pointer (name &optional errorname)
440: (save-excursion
441: (goto-char (point-min))
442: (forward-line 1)
443: (if (re-search-backward (concat name ":") nil t)
444: nil
445: (error (concat "Node has no " (capitalize (or errorname name)))))
446: (goto-char (match-end 0))
447: (Info-following-node-name)))
448:
449: (defun Info-following-node-name (&optional allowedchars)
450: (skip-chars-forward " \t")
451: (buffer-substring
452: (point)
453: (progn
454: (skip-chars-forward (or allowedchars "^,\t\n"))
455: (skip-chars-backward " ")
456: (point))))
457:
458: (defun Info-next ()
459: "Go to the next node of this node."
460: (interactive)
461: (Info-goto-node (Info-extract-pointer "next")))
462:
463: (defun Info-prev ()
464: "Go to the previous node of this node."
465: (interactive)
466: (Info-goto-node (Info-extract-pointer "prev[ious]*" "previous")))
467:
468: (defun Info-up ()
469: "Go to the superior node of this node."
470: (interactive)
471: (Info-goto-node (Info-extract-pointer "up")))
472:
473: (defun Info-last ()
474: "Go back to the last node visited."
475: (interactive)
476: (or Info-history
477: (error "This is the first Info node you looked at"))
478: (let (filename nodename opoint)
479: (setq filename (car (car Info-history)))
480: (setq nodename (car (cdr (car Info-history))))
481: (setq opoint (car (cdr (cdr (car Info-history)))))
482: (setq Info-history (cdr Info-history))
483: (Info-find-node filename nodename)
484: (setq Info-history (cdr Info-history))
485: (goto-char opoint)))
486:
487: (defun Info-directory ()
488: "Go to the Info directory node."
489: (interactive)
490: (Info-find-node "dir" "top"))
491:
492: (defun Info-follow-reference (footnotename)
493: "Follow cross reference named NAME to the node it refers to.
494: NAME may be an abbreviation of the reference name."
495: (interactive
496: (let ((completion-ignore-case t)
497: completions str i)
498: (save-excursion
499: (goto-char (point-min))
500: (while (re-search-forward "\\*note[ \n]*[^:\t]*:" nil t)
501: (setq str (buffer-substring
502: (+ (match-beginning 0) 6)
503: (1- (point))))
504: (setq i 0)
505: (while (setq i (string-match "\n" str i))
506: (aset str i ?\ ))
507: (setq completions
508: (cons (cons str nil)
509: completions))))
510: (if completions
511: (list (completing-read "Follow reference named: " completions nil t))
512: (error "No cross-references in this node"))))
513: (let (target beg i (str (concat "\\*note " footnotename)))
514: (while (setq i (string-match " " str i))
515: (setq str (concat (substring str 0 i) "[ \n]*" (substring str (1+ i))))
516: (setq i (+ i 5)))
517: (save-excursion
518: (goto-char (point-min))
519: (or (re-search-forward str nil t)
520: (error "No cross-reference named %s" footnotename))
521: (goto-char (+ (match-beginning 0) 5))
522: (setq target (Info-extract-menu-node-name "Bad format cross reference")))
523: (Info-goto-node target)))
524:
525: (defun Info-extract-menu-node-name (&optional errmessage)
526: (skip-chars-forward " \t\n")
527: (let ((beg (point))
528: str i)
529: (skip-chars-forward "^:")
530: (forward-char 1)
531: (setq str
532: (if (looking-at ":")
533: (buffer-substring beg (1- (point)))
534: (Info-following-node-name "^.,\t\n")))
535: (while (setq i (string-match "\n" str i))
536: (aset str i ?\ ))
537: str))
538:
539: (defun Info-menu-item-sequence (list)
540: (while list
541: (Info-menu-item (car list))
542: (setq list (cdr list))))
543:
544: (defun Info-menu (menu-item)
545: "Go to node for menu item named (or abbreviated) NAME."
546: (interactive
547: (let (completions
548: (completion-ignore-case t))
549: (save-excursion
550: (goto-char (point-min))
551: (if (not (search-forward "\n* menu:" nil t))
552: (error "No menu in this node"))
553: (while (re-search-forward
554: "\n\\* \\([^:\t\n]*\\):" nil t)
555: (setq completions
556: (cons (cons (buffer-substring
557: (match-beginning 1)
558: (match-end 1))
559: (match-beginning 1))
560: completions))))
561: (list (completing-read "Menu item: " completions nil t))))
562: (Info-goto-node (Info-extract-menu-item menu-item)))
563:
564: (defun Info-extract-menu-item (menu-item)
565: (save-excursion
566: (goto-char (point-min))
567: (or (search-forward "\n* menu:" nil t)
568: (error "No menu in this node"))
569: (or (search-forward (concat "\n* " menu-item) nil t)
570: (error "No such item in menu"))
571: (beginning-of-line)
572: (forward-char 2)
573: (Info-extract-menu-node-name)))
574:
575: (defun Info-extract-menu-counting (count)
576: (save-excursion
577: (goto-char (point-min))
578: (or (search-forward "\n* menu:" nil t)
579: (error "No menu in this node"))
580: (or (search-forward "\n* " nil t count)
581: (error "Too few items in menu"))
582: (Info-extract-menu-node-name)))
583:
584: (defun Info-first-menu-item ()
585: "Go to the node of the first menu item."
586: (interactive)
587: (Info-goto-node (Info-extract-menu-counting 1)))
588:
589: (defun Info-second-menu-item ()
590: "Go to the node of the second menu item."
591: (interactive)
592: (Info-goto-node (Info-extract-menu-counting 2)))
593:
594: (defun Info-third-menu-item ()
595: "Go to the node of the third menu item."
596: (interactive)
597: (Info-goto-node (Info-extract-menu-counting 3)))
598:
599: (defun Info-fourth-menu-item ()
600: "Go to the node of the fourth menu item."
601: (interactive)
602: (Info-goto-node (Info-extract-menu-counting 4)))
603:
604: (defun Info-fifth-menu-item ()
605: "Go to the node of the fifth menu item."
606: (interactive)
607: (Info-goto-node (Info-extract-menu-counting 5)))
608:
609: (defun Info-exit ()
610: "Exit Info by selecting some other buffer."
611: (interactive)
612: (switch-to-buffer (prog1 (other-buffer (current-buffer))
613: (bury-buffer (current-buffer)))))
614:
615: (defun Info-undefined ()
616: "Make command be undefined in Info."
617: (interactive)
618: (ding))
619:
620: (defun Info-help ()
621: "Enter the Info tutorial."
622: (interactive)
623: (Info-find-node "info"
624: (if (< (window-height) 23)
625: "Help-Small-Screen"
626: "Help")))
627:
628: (defun Info-summary ()
629: "Display a brief summary of all Info commands."
630: (interactive)
631: (save-window-excursion
632: (switch-to-buffer "*Help*")
633: (erase-buffer)
634: (insert (documentation 'Info-mode))
635: (goto-char (point-min))
636: (let (ch flag)
637: (while (progn (setq flag (not (pos-visible-in-window-p (point-max))))
638: (message (if flag "Type Space to see more"
639: "Type Space to return to Info"))
640: (if (/= ?\ (setq ch (read-char)))
641: (progn (setq unread-command-char ch) nil)
642: flag))
643: (scroll-up)))))
644:
645: (defvar Info-mode-map nil
646: "Keymap containing Info commands.")
647: (if Info-mode-map
648: nil
649: (setq Info-mode-map (make-keymap))
650: (suppress-keymap Info-mode-map)
651: (define-key Info-mode-map "." 'beginning-of-buffer)
652: (define-key Info-mode-map " " 'scroll-up)
653: (define-key Info-mode-map "1" 'Info-first-menu-item)
654: (define-key Info-mode-map "2" 'Info-second-menu-item)
655: (define-key Info-mode-map "3" 'Info-third-menu-item)
656: (define-key Info-mode-map "4" 'Info-fourth-menu-item)
657: (define-key Info-mode-map "5" 'Info-fifth-menu-item)
658: (define-key Info-mode-map "6" 'undefined)
659: (define-key Info-mode-map "7" 'undefined)
660: (define-key Info-mode-map "8" 'undefined)
661: (define-key Info-mode-map "9" 'undefined)
662: (define-key Info-mode-map "0" 'undefined)
663: (define-key Info-mode-map "?" 'Info-summary)
664: (define-key Info-mode-map "b" 'beginning-of-buffer)
665: (define-key Info-mode-map "d" 'Info-directory)
666: (define-key Info-mode-map "e" 'Info-edit)
667: (define-key Info-mode-map "f" 'Info-follow-reference)
668: (define-key Info-mode-map "g" 'Info-goto-node)
669: (define-key Info-mode-map "h" 'Info-help)
670: (define-key Info-mode-map "l" 'Info-last)
671: (define-key Info-mode-map "m" 'Info-menu)
672: (define-key Info-mode-map "n" 'Info-next)
673: (define-key Info-mode-map "p" 'Info-prev)
674: (define-key Info-mode-map "q" 'Info-exit)
675: (define-key Info-mode-map "s" 'Info-search)
676: (define-key Info-mode-map "u" 'Info-up)
677: (define-key Info-mode-map "\177" 'scroll-down))
678:
679: (defun Info-mode ()
680: "Info mode provides commands for browsing through the Info documentation tree.
681: Documentation in Info is divided into \"nodes\", each of which
682: discusses one topic and contains references to other nodes
683: which discuss related topics. Info has commands to follow
684: the references and show you other nodes.
685:
686: h Invoke the Info tutorial.
687:
688: Selecting other nodes:
689: n Move to the \"next\" node of this node.
690: p Move to the \"previous\" node of this node.
691: u Move \"up\" from this node.
692: m Pick menu item specified by name (or abbreviation).
693: Picking a menu item causes another node to be selected.
694: f Follow a cross reference. Reads name of reference.
695: l Move to the last node you were at.
696:
697: Moving within a node:
698: Space scroll forward a page. DEL scroll backward.
699: b Go to beginning of node.
700:
701: Advanced commands:
702: q Quit Info: reselect previously selected buffer.
703: e Edit contents of selected node.
704: 1 Pick first item in node's menu.
705: 2, 3, 4, 5 Pick second ... fifth item in node's menu.
706: g Move to node specified by name.
707: You may include a filename as well, as (FILENAME)NODENAME.
708: s Search through this Info file for specified regexp,
709: and select the node in which the next occurrence is found."
710: (kill-all-local-variables)
711: (setq major-mode 'Info-mode)
712: (setq mode-name "Info")
713: (use-local-map Info-mode-map)
714: (set-syntax-table text-mode-syntax-table)
715: (setq local-abbrev-table text-mode-abbrev-table)
716: (setq case-fold-search t)
717: (setq buffer-read-only t)
718: (Info-set-mode-line))
719:
720: (defvar Info-edit-map nil
721: "Local keymap used within `e' command of Info.")
722: (if Info-edit-map
723: nil
724: (setq Info-edit-map (copy-alist text-mode-map))
725: (define-key Info-edit-map "\C-c\C-c" 'Info-cease-edit))
726:
727: (defun Info-edit-mode ()
728: "Major mode for editing the contents of an Info node.
729: Like text mode with the addition of Info-cease-edit
730: which returns to Info mode for browsing.
731: \\{Info-edit-map}"
732: )
733:
734: (defun Info-edit ()
735: "Edit the contents of this Info node.
736: Allowed only if variable Info-enable-edit is non-nil."
737: (interactive)
738: (or Info-enable-edit
739: (error "Editing info nodes is not enabled"))
740: (use-local-map Info-edit-map)
741: (setq major-mode 'Info-edit-mode)
742: (setq mode-name "Info Edit")
743: (setq mode-line-format default-mode-line-format)
744: (setq buffer-read-only nil)
745: ;; Make mode line update.
746: (set-buffer-modified-p (buffer-modified-p))
747: (message (substitute-command-keys
748: "Editing: Type \\[Info-cease-edit] to return to info")))
749:
750: (defun Info-cease-edit ()
751: "Finish editing Info node; switch back to Info proper."
752: (interactive)
753: ;; Do this first, so nothing has changed if user C-g's at query.
754: (and (buffer-modified-p)
755: (y-or-n-p "Save the file? ")
756: (save-buffer))
757: (use-local-map Info-mode-map)
758: (setq major-mode 'Info-mode)
759: (setq mode-name "Info")
760: (Info-set-mode-line)
761: (setq buffer-read-only t)
762: ;; Make mode line update.
763: (set-buffer-modified-p (buffer-modified-p))
764: (and (marker-position Info-tag-table-marker)
765: (buffer-modified-p)
766: (message "Tags may have changed. Use Info-tagify if necessary")))
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.