Annotation of 43BSD/contrib/emacs/lisp/info.el, revision 1.1.1.1

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")))

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.