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