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