Annotation of GNUtools/emacs/lisp/informat.el, revision 1.1.1.1

1.1       root        1: ;; Info support functions package for Emacs
                      2: ;; Copyright (C) 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: (require 'info)
                     21: 
                     22: (defun Info-tagify ()
                     23:   "Create or update Info-file tag table in current buffer."
                     24:   (interactive)
                     25:   ;; Save and restore point and restrictions.
                     26:   ;; save-restrictions would not work
                     27:   ;; because it records the old max relative to the end.
                     28:   ;; We record it relative to the beginning.
                     29:   (let ((omin (point-min))
                     30:        (omax (point-max))
                     31:        (nomax (= (point-max) (1+ (buffer-size))))
                     32:        (opoint (point)))
                     33:     (unwind-protect
                     34:        (progn
                     35:          (widen)
                     36:          (goto-char (point-min))
                     37:          (if (search-forward "\^_\nIndirect:\n" nil t)
                     38:              (message "Cannot tagify split info file")
                     39:            (let ((regexp "Node:[ \t]*\\([^,\n\t]\\)*[,\t\n]")
                     40:                  (case-fold-search t)
                     41:                  list)
                     42:              (while (search-forward "\n\^_" nil t)
                     43:                (forward-line 1)
                     44:                (let ((beg (point)))
                     45:                  (forward-line 1)
                     46:                  (if (re-search-backward regexp beg t)
                     47:                      (setq list
                     48:                            (cons (list (buffer-substring
                     49:                                          (match-beginning 1)
                     50:                                          (match-end 1))
                     51:                                        beg)
                     52:                                  list)))))
                     53:              (goto-char (point-max))
                     54:              (forward-line -8)
                     55:              (let ((buffer-read-only nil))
                     56:                (if (search-forward "\^_\nEnd tag table\n" nil t)
                     57:                    (let ((end (point)))
                     58:                      (search-backward "\nTag table:\n")
                     59:                      (beginning-of-line)
                     60:                      (delete-region (point) end)))
                     61:                (goto-char (point-max))
                     62:                (insert "\^_\f\nTag table:\n")
                     63:                (move-marker Info-tag-table-marker (point))
                     64:                (setq list (nreverse list))
                     65:                (while list
                     66:                  (insert "Node: " (car (car list)) ?\177)
                     67:                  (princ (car (cdr (car list))) (current-buffer))
                     68:                  (insert ?\n)
                     69:                  (setq list (cdr list)))
                     70:                (insert "\^_\nEnd tag table\n")))))
                     71:       (goto-char opoint)
                     72:       (narrow-to-region omin (if nomax (1+ (buffer-size))
                     73:                               (min omax (point-max)))))))
                     74: 
                     75: (defun Info-split ()
                     76:   "Split an info file into an indirect file plus bounded-size subfiles.
                     77: Each subfile will be up to 50000 characters plus one node.
                     78: 
                     79: To use this command, first visit a large Info file that has a tag table.
                     80: The buffer is modified into a (small) indirect info file
                     81: which should be saved in place of the original visited file.
                     82: 
                     83: The subfiles are written in the same directory the original file is in,
                     84: with names generated by appending `-' and a number to the original file name.
                     85: 
                     86: The indirect file still functions as an Info file, but it contains
                     87: just the tag table and a directory of subfiles."
                     88:   (interactive)
                     89:   (if (< (buffer-size) 70000)
                     90:       (error "This is too small to be worth splitting"))
                     91:   (goto-char (point-min))
                     92:   (search-forward "\^_")
                     93:   (forward-char -1)
                     94:   (let ((start (point))
                     95:        (chars-deleted 0)
                     96:        subfiles
                     97:        (subfile-number 1)
                     98:        (case-fold-search t)
                     99:        (filename (file-name-sans-versions buffer-file-name)))
                    100:     (goto-char (point-max))
                    101:     (forward-line -8)
                    102:     (setq buffer-read-only nil)
                    103:     (or (search-forward "\^_\nEnd tag table\n" nil t)
                    104:        (error "Tag table required; use M-x Info-tagify"))
                    105:     (search-backward "\nTag table:\n")
                    106:     (if (looking-at "\nTag table:\n\^_")
                    107:        (error "Tag table is just a skeleton; use M-x Info-tagify"))
                    108:     (beginning-of-line)
                    109:     (forward-char 1)
                    110:     (save-restriction
                    111:       (narrow-to-region (point-min) (point))
                    112:       (goto-char (point-min))
                    113:       (while (< (1+ (point)) (point-max))
                    114:        (goto-char (min (+ (point) 50000) (point-max)))
                    115:        (search-forward "\^_" nil 'move)
                    116:        (setq subfiles
                    117:              (cons (list (+ start chars-deleted)
                    118:                          (concat (file-name-nondirectory filename)
                    119:                                  (format "-%d" subfile-number)))
                    120:                    subfiles))
                    121:        ;; Put a newline at end of split file, to make Unix happier.
                    122:        (insert "\n")
                    123:        (write-region (point-min) (point)
                    124:                      (concat filename (format "-%d" subfile-number)))
                    125:        (delete-region (1- (point)) (point))
                    126:        ;; Back up over the final ^_.
                    127:        (forward-char -1)
                    128:        (setq chars-deleted (+ chars-deleted (- (point) start)))
                    129:        (delete-region start (point))
                    130:        (setq subfile-number (1+ subfile-number))))
                    131:     (while subfiles
                    132:       (goto-char start)
                    133:       (insert (nth 1 (car subfiles))
                    134:              (format ": %d" (car (car subfiles)))
                    135:              "\n")
                    136:       (setq subfiles (cdr subfiles)))
                    137:     (goto-char start)
                    138:     (insert "\^_\nIndirect:\n")
                    139:     (search-forward "\nTag Table:\n")
                    140:     (insert "(Indirect)\n")))
                    141: 
                    142: (defun Info-validate ()
                    143:   "Check current buffer for validity as an Info file.
                    144: Check that every node pointer points to an existing node."
                    145:   (interactive)
                    146:   (save-excursion
                    147:     (save-restriction
                    148:       (widen)
                    149:       (goto-char (point-min))
                    150:       (if (search-forward "\nTag table:\n(Indirect)\n" nil t)
                    151:          (error "Don't yet know how to validate indirect info files: \"%s\""
                    152:                 (buffer-name (current-buffer))))
                    153:       (goto-char (point-min))
                    154:       (let ((allnodes '(("*")))
                    155:            (regexp "Node:[ \t]*\\([^,\n\t]*\\)[,\t\n]")
                    156:            (case-fold-search t)
                    157:            (tags-losing nil)
                    158:            (lossages ()))
                    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:                (let ((name (downcase
                    165:                              (buffer-substring
                    166:                                (match-beginning 1)
                    167:                                (progn
                    168:                                  (goto-char (match-end 1))
                    169:                                  (skip-chars-backward " \t")
                    170:                                  (point))))))
                    171:                  (if (assoc name allnodes)
                    172:                      (setq lossages
                    173:                            (cons (list name "Duplicate node-name" nil)
                    174:                                  lossages))
                    175:                      (setq allnodes
                    176:                            (cons (list name
                    177:                                        (progn
                    178:                                          (end-of-line)
                    179:                                          (and (re-search-backward
                    180:                                                "prev[ious]*:" beg t)
                    181:                                               (progn
                    182:                                                 (goto-char (match-end 0))
                    183:                                                 (downcase
                    184:                                                   (Info-following-node-name)))))
                    185:                                        beg)
                    186:                                  allnodes)))))))
                    187:        (goto-char (point-min))
                    188:        (while (search-forward "\n\^_" nil t)
                    189:          (forward-line 1)
                    190:          (let ((beg (point))
                    191:                thisnode next)
                    192:            (forward-line 1)
                    193:            (if (re-search-backward regexp beg t)
                    194:                (save-restriction
                    195:                  (search-forward "\n\^_" nil 'move)
                    196:                  (narrow-to-region beg (point))
                    197:                  (setq thisnode (downcase
                    198:                                   (buffer-substring
                    199:                                     (match-beginning 1)
                    200:                                     (progn
                    201:                                       (goto-char (match-end 1))
                    202:                                       (skip-chars-backward " \t")
                    203:                                       (point)))))
                    204:                  (end-of-line)
                    205:                  (and (search-backward "next:" nil t)
                    206:                       (setq next (Info-validate-node-name "invalid Next"))
                    207:                       (assoc next allnodes)
                    208:                       (if (equal (car (cdr (assoc next allnodes)))
                    209:                                  thisnode)
                    210:                           ;; allow multiple `next' pointers to one node
                    211:                           (let ((tem lossages))
                    212:                             (while tem
                    213:                               (if (and (equal (car (cdr (car tem)))
                    214:                                               "should have Previous")
                    215:                                        (equal (car (car tem))
                    216:                                               next))
                    217:                                   (setq lossages (delq (car tem) lossages)))
                    218:                               (setq tem (cdr tem))))
                    219:                         (setq lossages
                    220:                               (cons (list next
                    221:                                           "should have Previous"
                    222:                                           thisnode)
                    223:                                     lossages))))
                    224:                  (end-of-line)
                    225:                  (if (re-search-backward "prev[ious]*:" nil t)
                    226:                      (Info-validate-node-name "invalid Previous"))
                    227:                  (end-of-line)
                    228:                  (if (search-backward "up:" nil t)
                    229:                      (Info-validate-node-name "invalid Up"))
                    230:                  (if (re-search-forward "\n* Menu:" nil t)
                    231:                      (while (re-search-forward "\n\\* " nil t)
                    232:                        (Info-validate-node-name
                    233:                          (concat "invalid menu item "
                    234:                                  (buffer-substring (point)
                    235:                                                    (save-excursion
                    236:                                                      (skip-chars-forward "^:")
                    237:                                                      (point))))
                    238:                          (Info-extract-menu-node-name))))
                    239:                  (goto-char (point-min))
                    240:                  (while (re-search-forward "\\*note[ \n]*[^:\t]*:" nil t)
                    241:                    (goto-char (+ (match-beginning 0) 5))
                    242:                    (skip-chars-forward " \n")
                    243:                    (Info-validate-node-name
                    244:                     (concat "invalid reference "
                    245:                             (buffer-substring (point)
                    246:                                               (save-excursion
                    247:                                                 (skip-chars-forward "^:")
                    248:                                                 (point))))
                    249:                     (Info-extract-menu-node-name "Bad format cross-reference")))))))
                    250:        (setq tags-losing (not (Info-validate-tags-table)))
                    251:        (if (or lossages tags-losing)
                    252:            (with-output-to-temp-buffer " *problems in info file*"
                    253:              (while lossages
                    254:                (princ "In node \"")
                    255:                (princ (car (car lossages)))
                    256:                (princ "\", ")
                    257:                (let ((tem (nth 1 (car lossages))))
                    258:                  (cond ((string-match "\n" tem)
                    259:                         (princ (substring tem 0 (match-beginning 0)))
                    260:                         (princ "..."))
                    261:                        (t
                    262:                         (princ tem))))
                    263:                (if (nth 2 (car lossages))
                    264:                    (progn
                    265:                      (princ ": ")
                    266:                      (let ((tem (nth 2 (car lossages))))
                    267:                        (cond ((string-match "\n" tem)
                    268:                               (princ (substring tem 0 (match-beginning 0)))
                    269:                               (princ "..."))
                    270:                              (t
                    271:                               (princ tem))))))
                    272:                (terpri)
                    273:                (setq lossages (cdr lossages)))
                    274:              (if tags-losing (princ "\nTags table must be recomputed\n")))
                    275:          ;; Here if info file is valid.
                    276:          ;; If we already made a list of problems, clear it out.
                    277:          (save-excursion
                    278:            (if (get-buffer " *problems in info file*")
                    279:                (progn
                    280:                  (set-buffer " *problems in info file*")
                    281:                  (kill-buffer (current-buffer)))))
                    282:          (message "File appears valid"))))))
                    283: 
                    284: (defun Info-validate-node-name (kind &optional name)
                    285:   (if name
                    286:       nil
                    287:     (goto-char (match-end 0))
                    288:     (skip-chars-forward " \t")
                    289:     (if (= (following-char) ?\()
                    290:        nil
                    291:       (setq name
                    292:            (buffer-substring
                    293:             (point)
                    294:             (progn
                    295:              (skip-chars-forward "^,\t\n")
                    296:              (skip-chars-backward " ")
                    297:              (point))))))
                    298:   (if (null name)
                    299:       nil
                    300:     (setq name (downcase name))
                    301:     (or (and (> (length name) 0) (= (aref name 0) ?\())
                    302:        (assoc name allnodes)
                    303:        (setq lossages
                    304:              (cons (list thisnode kind name) lossages))))
                    305:   name)
                    306: 
                    307: (defun Info-validate-tags-table ()
                    308:   (goto-char (point-min))
                    309:   (if (not (search-forward "\^_\nEnd tag table\n" nil t))
                    310:       t
                    311:     (not (catch 'losing
                    312:           (let* ((end (match-beginning 0))
                    313:                  (start (progn (search-backward "\nTag table:\n")
                    314:                                (1- (match-end 0))))
                    315:                  tem)
                    316:             (setq tem allnodes)
                    317:             (while tem
                    318:               (goto-char start)
                    319:               (or (equal (car (car tem)) "*")
                    320:                   (search-forward (concat "Node: "
                    321:                                           (car (car tem))
                    322:                                           "\177")
                    323:                                   end t)
                    324:                   (throw 'losing 'x))
                    325:               (setq tem (cdr tem)))
                    326:             (goto-char (1+ start))
                    327:             (while (looking-at ".*Node: \\(.*\\)\177\\([0-9]+\\)$")
                    328:               (setq tem (downcase (buffer-substring
                    329:                                     (match-beginning 1)
                    330:                                     (match-end 1))))
                    331:               (setq tem (assoc tem allnodes))
                    332:               (if (or (not tem)
                    333:                       (< 1000 (progn
                    334:                                 (goto-char (match-beginning 2))
                    335:                                 (setq tem (- (car (cdr (cdr tem)))
                    336:                                              (read (current-buffer))))
                    337:                                 (if (> tem 0) tem (- tem)))))
                    338:                   (throw 'losing 'y)))
                    339:             (forward-line 1))
                    340:           (or (looking-at "End tag table\n")
                    341:               (throw 'losing 'z))
                    342:           nil))))
                    343: 
                    344: (defun batch-info-validate ()
                    345:   "Runs  Info-validate  on the files remaining on the command line.
                    346: Must be used only with -batch, and kills emacs on completion.
                    347: Each file will be processed even if an error occurred previously.
                    348: For example, invoke \"emacs -batch -f batch-info-validate $info/ ~/*.info\""
                    349:   (if (not noninteractive)
                    350:       (error "batch-info-validate may only be used -batch."))
                    351:   (let ((version-control t)
                    352:        (auto-save-default nil)
                    353:        (find-file-run-dired nil)
                    354:        (kept-old-versions 259259)
                    355:        (kept-new-versions 259259))
                    356:     (let ((error 0)
                    357:          file
                    358:          (files ()))
                    359:       (while command-line-args-left
                    360:        (setq file (expand-file-name (car command-line-args-left)))
                    361:        (cond ((not (file-exists-p file))
                    362:               (message ">> %s does not exist!" file)
                    363:               (setq error 1
                    364:                     command-line-args-left (cdr command-line-args-left))) 
                    365:              ((file-directory-p file)
                    366:               (setq command-line-args-left (nconc (directory-files file)
                    367:                                              (cdr command-line-args-left))))
                    368:              (t
                    369:               (setq files (cons file files)
                    370:                     command-line-args-left (cdr command-line-args-left)))))
                    371:       (while files
                    372:        (setq file (car files)
                    373:              files (cdr files))
                    374:        (let ((lose nil))
                    375:          (condition-case err
                    376:              (progn
                    377:                (if buffer-file-name (kill-buffer (current-buffer)))
                    378:                (find-file file)
                    379:                (buffer-flush-undo (current-buffer))
                    380:                (set-buffer-modified-p nil)
                    381:                (fundamental-mode)
                    382:                (let ((case-fold-search nil))
                    383:                  (goto-char (point-max))
                    384:                  (cond ((search-backward "\n\^_\^L\nTag table:\n" nil t)
                    385:                         (message "%s already tagified" file))
                    386:                        ((< (point-max) 30000)
                    387:                         (message "%s too small to bother tagifying" file))
                    388:                        (t
                    389:                         (message "Tagifying %s..." file)
                    390:                         (Info-tagify)
                    391:                         (message "Tagifying %s...done" file))))
                    392:                (let ((loss-name " *problems in info file*"))
                    393:                  (message "Checking validity of info file %s..." file)
                    394:                  (if (get-buffer loss-name)
                    395:                      (kill-buffer loss-name))
                    396:                  (Info-validate)
                    397:                  (if (not (get-buffer loss-name))
                    398:                      nil ;(message "Checking validity of info file %s... OK" file)
                    399:                    (message "----------------------------------------------------------------------")
                    400:                    (message ">> PROBLEMS IN INFO FILE %s" file)
                    401:                    (save-excursion
                    402:                      (set-buffer loss-name)
                    403:                      (princ (buffer-substring (point-min) (point-max))))
                    404:                    (message "----------------------------------------------------------------------")
                    405:                    (setq error 1 lose t)))
                    406:                (if (and (buffer-modified-p)
                    407:                         (not lose))
                    408:                    (progn (message "Saving modified %s" file)
                    409:                           (save-buffer))))
                    410:            (error (message ">> Error: %s" (prin1-to-string err))))))
                    411:       (kill-emacs error))))

unix.superglobalmegacorp.com

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