1;;; texnfo-upd.el --- utilities for updating nodes and menus in Texinfo files 2 3;; Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc. 4 5;; Author: Robert J. Chassell 6;; Maintainer: bug-texinfo@prep.ai.mit.edu 7;; Keywords: maint, tex, docs 8 9;; This file is part of GNU Emacs. 10 11;; GNU Emacs is free software; you can redistribute it and/or modify 12;; it under the terms of the GNU General Public License as published by 13;; the Free Software Foundation; either version 2, or (at your option) 14;; any later version. 15 16;; GNU Emacs is distributed in the hope that it will be useful, 17;; but WITHOUT ANY WARRANTY; without even the implied warranty of 18;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19;; GNU General Public License for more details. 20 21;; You should have received a copy of the GNU General Public License 22;; along with GNU Emacs; see the file COPYING. If not, write to the 23;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, 24;; Boston, MA 02111-1307, USA. 25 26;;; Commentary: 27 28;; Known bug: update commands fail to ignore @ignore. 29 30;; Summary: how to use the updating commands 31 32;; The node and menu updating functions automatically 33 34;; * insert missing `@node' lines, 35;; * insert the `Next', `Previous' and `Up' pointers of a node, 36;; * insert or update the menu for a section, 37;; * create a master menu for a Texinfo source file. 38;; 39;; With a prefix argument, the `texinfo-update-node' and 40;; `texinfo-make-menu' functions do their jobs in the region. 41;; 42;; In brief, the functions for creating or updating nodes and menus, are: 43;; 44;; texinfo-update-node (&optional beginning end) 45;; texinfo-every-node-update () 46;; texinfo-sequential-node-update (&optional region-p) 47;; 48;; texinfo-make-menu (&optional beginning end) 49;; texinfo-all-menus-update () 50;; texinfo-master-menu () 51;; 52;; texinfo-insert-node-lines (&optional title-p) 53;; 54;; texinfo-indent-menu-description (column &optional region-p) 55 56;; The `texinfo-column-for-description' variable specifies the column to 57;; which menu descriptions are indented. 58 59;; Texinfo file structure 60;; ---------------------- 61 62;; To use the updating commands, you must structure your Texinfo file 63;; hierarchically. Each `@node' line, with the exception of the top 64;; node, must be accompanied by some kind of section line, such as an 65;; `@chapter' or `@section' line. Each node-line/section-line 66;; combination must look like this: 67 68;; @node Lists and Tables, Cross References, Structuring, Top 69;; @comment node-name, next, previous, up 70;; @chapter Making Lists and Tables 71 72;; or like this (without the `@comment' line): 73 74;; @node Lists and Tables, Cross References, Structuring, Top 75;; @chapter Making Lists and Tables 76 77;; If the file has a `top' node, it must be called `top' or `Top' and 78;; be the first node in the file. 79 80 81;;; The update node functions described in detail 82 83;; The `texinfo-update-node' command with no prefix argument inserts 84;; the correct next, previous and up pointers for the node in which 85;; point is located (i.e., for the node preceding point). 86 87;; With prefix argument, the `texinfo-update-node' function inserts the 88;; correct next, previous and up pointers for the nodes inside the 89;; region. 90 91;; It does not matter whether the `@node' line has pre-existing 92;; `Next', `Previous', or `Up' pointers in it. They are removed. 93 94;; The `texinfo-every-node-update' function runs `texinfo-update-node' 95;; on the whole buffer. 96 97;; The `texinfo-sequential-node-update' function inserts the 98;; immediately following and preceding node into the `Next' or 99;; `Previous' pointers regardless of their hierarchical level. This is 100;; only useful for certain kinds of text, like a novel, which you go 101;; through sequentially. 102 103 104;;; The menu making functions described in detail 105 106;; The `texinfo-make-menu' function without an argument creates or 107;; updates a menu for the section encompassing the node that follows 108;; point. With an argument, it makes or updates menus for the nodes 109;; within or part of the marked region. 110 111;; Whenever an existing menu is updated, the descriptions from 112;; that menu are incorporated into the new menu. This is done by copying 113;; descriptions from the existing menu to the entries in the new menu 114;; that have the same node names. If the node names are different, the 115;; descriptions are not copied to the new menu. 116 117;; Menu entries that refer to other Info files are removed since they 118;; are not a node within current buffer. This is a deficiency. 119 120;; The `texinfo-all-menus-update' function runs `texinfo-make-menu' 121;; on the whole buffer. 122 123;; The `texinfo-master-menu' function creates an extended menu located 124;; after the top node. (The file must have a top node.) The function 125;; first updates all the regular menus in the buffer (incorporating the 126;; descriptions from pre-existing menus), and then constructs a master 127;; menu that includes every entry from every other menu. (However, the 128;; function cannot update an already existing master menu; if one 129;; exists, it must be removed before calling the function.) 130 131;; The `texinfo-indent-menu-description' function indents every 132;; description in the menu following point, to the specified column. 133;; Non-nil argument (prefix, if interactive) means indent every 134;; description in every menu in the region. This function does not 135;; indent second and subsequent lines of a multi-line description. 136 137;; The `texinfo-insert-node-lines' function inserts `@node' before the 138;; `@chapter', `@section', and such like lines of a region in a Texinfo 139;; file where the `@node' lines are missing. 140;; 141;; With a non-nil argument (prefix, if interactive), the function not 142;; only inserts `@node' lines but also inserts the chapter or section 143;; titles as the names of the corresponding nodes; and inserts titles 144;; as node names in pre-existing `@node' lines that lack names. 145;; 146;; Since node names should be more concise than section or chapter 147;; titles, node names so inserted will need to be edited manually. 148 149 150;;; Code: 151 152(defvar texinfo-master-menu-header 153 " --- The Detailed Node Listing ---\n" 154 "String inserted before lower level entries in Texinfo master menu. 155It comes after the chapter-level menu entries.") 156 157(defun texinfo-make-menu (&optional beginning end) 158 "Without any prefix argument, make or update a menu. 159Make the menu for the section enclosing the node found following point. 160 161A prefix argument means make or update menus 162for nodes within or part of the marked region. 163 164Whenever a menu exists, and is being updated, the descriptions that 165are associated with node names in the pre-existing menu are 166incorporated into the new menu. Otherwise, the nodes' section titles 167are inserted as descriptions." 168 169 (interactive 170 (if prefix-arg 171 (list (point) (mark)))) 172 (if (null beginning) 173 (let ((level (texinfo-hierarchic-level))) 174 (texinfo-make-one-menu level) 175 (message "Menu updated")) 176 ;; else 177 (message "Making or updating menus in %s... " (buffer-name)) 178 (save-excursion 179 (goto-char (min beginning end)) 180 ;; find section type following point 181 (let ((level (texinfo-hierarchic-level)) 182 (region-end (max beginning end))) 183 (save-restriction 184 (widen) 185 186 (while (texinfo-find-lower-level-node level region-end) 187 (setq level (texinfo-hierarchic-level)) ; new, lower level 188 (texinfo-make-one-menu level)) 189 190 (while (and (< (point) region-end) 191 (texinfo-find-higher-level-node level region-end)) 192 (setq level (texinfo-hierarchic-level)) 193 (while (texinfo-find-lower-level-node level region-end) 194 (setq level (texinfo-hierarchic-level)) ; new, lower level 195 (texinfo-make-one-menu level)))))) 196 (message "Making or updating menus in %s...done" (buffer-name)))) 197 198(defun texinfo-make-one-menu (level) 199 "Make a menu of all the appropriate nodes in this section. 200`Appropriate nodes' are those associated with sections that are 201at the level specified by LEVEL. Point is left at the end of menu." 202 (let* 203 ((case-fold-search t) 204 (beginning 205 (save-excursion 206 (goto-char (texinfo-update-menu-region-beginning level)) 207 (end-of-line) 208 (point))) 209 (end (texinfo-update-menu-region-end level)) 210 (first (texinfo-menu-first-node beginning end)) 211 (node-name (progn 212 (goto-char beginning) 213 (beginning-of-line) 214 (texinfo-copy-node-name))) 215 (new-menu-list (texinfo-make-menu-list beginning end level))) 216 (if (texinfo-old-menu-p beginning first) 217 (progn 218 (texinfo-incorporate-descriptions new-menu-list) 219 (texinfo-incorporate-menu-entry-names new-menu-list) 220 (texinfo-delete-old-menu beginning first))) 221 (texinfo-insert-menu new-menu-list node-name))) 222 223(defun texinfo-all-menus-update (&optional update-all-nodes-p) 224 "Update every regular menu in a Texinfo file. 225Update pre-existing master menu, if there is one. 226 227If called with a non-nil argument, this function first updates all the 228nodes in the buffer before updating the menus." 229 (interactive "P") 230 (let ((case-fold-search t) 231 master-menu-p) 232 (save-excursion 233 (push-mark (point-max) t) 234 (goto-char (point-min)) 235 (message "Checking for a master menu in %s ... "(buffer-name)) 236 (save-excursion 237 (if (search-forward texinfo-master-menu-header nil t) 238 (progn 239 ;; Check if @detailmenu kludge is used; 240 ;; if so, leave point before @detailmenu. 241 (search-backward "\n@detailmenu" 242 (save-excursion (forward-line -3) (point)) 243 t) 244 ;; Remove detailed master menu listing 245 (setq master-menu-p t) 246 (goto-char (match-beginning 0)) 247 (let ((end-of-detailed-menu-descriptions 248 (save-excursion ; beginning of end menu line 249 (goto-char (texinfo-menu-end)) 250 (beginning-of-line) (forward-char -1) 251 (point)))) 252 (delete-region (point) end-of-detailed-menu-descriptions))))) 253 254 (if update-all-nodes-p 255 (progn 256 (message "Updating all nodes in %s ... " (buffer-name)) 257 (sleep-for 2) 258 (texinfo-update-node (point-min) (point-max)))) 259 260 (message "Updating all menus in %s ... " (buffer-name)) 261 (sleep-for 2) 262 (texinfo-make-menu (point-max) (point-min)) 263 264 (if master-menu-p 265 (progn 266 (message "Updating the master menu in %s... " (buffer-name)) 267 (sleep-for 2) 268 (texinfo-master-menu nil)))) 269 270 (message "Done...updated all the menus. You may save the buffer."))) 271 272(defun texinfo-find-lower-level-node (level region-end) 273 "Search forward from point for node at any level lower than LEVEL. 274Search is limited to the end of the marked region, REGION-END, 275and to the end of the menu region for the level. 276 277Return t if the node is found, else nil. Leave point at the beginning 278of the node if one is found; else do not move point." 279 (let ((case-fold-search t)) 280 (if (and (< (point) region-end) 281 (re-search-forward 282 (concat 283 "\\(^@node\\).*\n" ; match node line 284 "\\(\\(\\(^@c\\).*\n\\)" ; match comment line, if any 285 "\\|" ; or 286 "\\(^@ifinfo[ ]*\n\\)\\)?" ; ifinfo line, if any 287 (eval (cdr (assoc level texinfo-update-menu-lower-regexps)))) 288 ;; the next higher level node marks the end of this 289 ;; section, and no lower level node will be found beyond 290 ;; this position even if region-end is farther off 291 (texinfo-update-menu-region-end level) 292 t)) 293 (goto-char (match-beginning 1))))) 294 295(defun texinfo-find-higher-level-node (level region-end) 296 "Search forward from point for node at any higher level than argument LEVEL. 297Search is limited to the end of the marked region, REGION-END. 298 299Return t if the node is found, else nil. Leave point at the beginning 300of the node if one is found; else do not move point." 301 (let ((case-fold-search t)) 302 (cond 303 ((or (string-equal "top" level) (string-equal "chapter" level)) 304 (if (re-search-forward "^@node [ \t]*top[ \t]*\\(,\\|$\\)" region-end t) 305 (progn (beginning-of-line) t))) 306 (t 307 (if (re-search-forward 308 (concat 309 "\\(^@node\\).*\n" ; match node line 310 "\\(\\(\\(^@c\\).*\n\\)" ; match comment line, if any 311 "\\|" ; or 312 "\\(^@ifinfo[ ]*\n\\)\\)?" ; ifinfo line, if any 313 (eval (cdr (assoc level texinfo-update-menu-higher-regexps)))) 314 region-end t) 315 (progn (beginning-of-line) t)))))) 316 317 318;;; Making the list of new menu entries 319 320(defun texinfo-make-menu-list (beginning end level) 321 "Make a list of node names and their descriptions. 322Point is left at the end of the menu region, but the menu is not inserted. 323 324First argument is position from which to start making menu list; 325second argument is end of region in which to try to locate entries; 326third argument is the level of the nodes that are the entries. 327 328Node names and descriptions are dotted pairs of strings. Each pair is 329an element of the list. If the description does not exist, the 330element consists only of the node name." 331 (goto-char beginning) 332 (let (new-menu-list) 333 (while (texinfo-menu-locate-entry-p level end) 334 (setq new-menu-list 335 (cons (cons 336 (texinfo-copy-node-name) 337 (prog1 "" (forward-line 1))) 338 ;; Use following to insert section titles automatically. 339 ;; (texinfo-copy-section-title)) 340 new-menu-list))) 341 (reverse new-menu-list))) 342 343(defun texinfo-menu-locate-entry-p (level search-end) 344 "Find a node that will be part of menu for this section. 345First argument is a string such as \"section\" specifying the general 346hierarchical level of the menu; second argument is a position 347specifying the end of the search. 348 349The function returns t if the node is found, else nil. It searches 350forward from point, and leaves point at the beginning of the node. 351 352The function finds entries of the same type. Thus `subsections' and 353`unnumberedsubsecs' will appear in the same menu." 354 (let ((case-fold-search t)) 355 (if (re-search-forward 356 (concat 357 "\\(^@node\\).*\n" ; match node line 358 "\\(\\(\\(^@c\\).*\n\\)" ; match comment line, if any 359 "\\|" ; or 360 "\\(^@ifinfo[ ]*\n\\)\\)?" ; ifinfo line, if any 361 (eval 362 (cdr (assoc level texinfo-update-menu-same-level-regexps)))) 363 search-end 364 t) 365 (goto-char (match-beginning 1))))) 366 367(defun texinfo-copy-node-name () 368 "Return the node name as a string. 369 370Start with point at the beginning of the node line; copy the text 371after the node command up to the first comma on the line, if any, and 372return the text as a string. Leaves point at the beginning of the 373line. If there is no node name, returns an empty string." 374 375 (save-excursion 376 (buffer-substring 377 (progn (forward-word 1) ; skip over node command 378 (skip-chars-forward " \t") ; and over spaces 379 (point)) 380 (if (search-forward 381 "," 382 (save-excursion (end-of-line) (point)) t) ; bound search 383 (1- (point)) 384 (end-of-line) (point))))) 385 386(defun texinfo-copy-section-title () 387 "Return the title of the section as a string. 388The title is used as a description line in the menu when one does not 389already exist. 390 391Move point to the beginning of the appropriate section line by going 392to the start of the text matched by last regexp searched for, which 393must have been done by `texinfo-menu-locate-entry-p'." 394 395 ;; could use the same re-search as in `texinfo-menu-locate-entry-p' 396 ;; instead of using `match-beginning'; such a variation would be 397 ;; more general, but would waste information already collected 398 399 (goto-char (match-beginning 7)) ; match section name 400 401 (buffer-substring 402 (progn (forward-word 1) ; skip over section type 403 (skip-chars-forward " \t") ; and over spaces 404 (point)) 405 (progn (end-of-line) (point)))) 406 407 408;;; Handling the old menu 409 410(defun texinfo-old-menu-p (beginning first) 411 "Move point to the beginning of the menu for this section, if any. 412Otherwise move point to the end of the first node of this section. 413Return t if a menu is found, nil otherwise. 414 415First argument is the position of the beginning of the section in which 416the menu will be located; second argument is the position of the first 417node within the section. 418 419If no menu is found, the function inserts two newlines just before the 420end of the section, and leaves point there where a menu ought to be." 421 (goto-char beginning) 422 (if (not (re-search-forward "^@menu" first 'goto-end)) 423 (progn (insert "\n\n") (forward-line -2) nil) 424 t)) 425 426(defun texinfo-incorporate-descriptions (new-menu-list) 427 "Copy the old menu line descriptions that exist to the new menu. 428 429Point must be at beginning of old menu. 430 431If the node-name of the new menu is found in the old menu, insert the 432old description into the new entry. 433 434For this function, the new menu is a list made up of lists of dotted 435pairs in which the first element of the pair is the node name and the 436second element the description. The new menu is changed destructively. 437The old menu is the menu as it appears in the Texinfo file." 438 439 (let ((new-menu-list-pointer new-menu-list) 440 (end-of-menu (texinfo-menu-end))) 441 (while new-menu-list 442 (save-excursion ; keep point at beginning of menu 443 (if (re-search-forward 444 ;; Existing nodes can have the form 445 ;; * NODE NAME:: DESCRIPTION 446 ;; or 447 ;; * MENU ITEM: NODE NAME. DESCRIPTION. 448 ;; 449 ;; Recognize both when looking for the description. 450 (concat "\\* \\(" ; so only menu entries are found 451 (regexp-quote (car (car new-menu-list))) "::" 452 "\\|" 453 ".*: " (regexp-quote (car (car new-menu-list))) "[.,\t\n]" 454 "\\)" 455 ) ; so only complete entries are found 456 end-of-menu 457 t) 458 (setcdr (car new-menu-list) 459 (texinfo-menu-copy-old-description end-of-menu)))) 460 (setq new-menu-list (cdr new-menu-list))) 461 (setq new-menu-list new-menu-list-pointer))) 462 463(defun texinfo-incorporate-menu-entry-names (new-menu-list) 464 "Copy any old menu entry names to the new menu. 465 466Point must be at beginning of old menu. 467 468If the node-name of the new menu entry cannot be found in the old 469menu, do nothing. 470 471For this function, the new menu is a list made up of lists of dotted 472pairs in which the first element of the pair is the node name and the 473second element is the description (or nil). 474 475If we find an existing menu entry name, we change the first element of 476the pair to be another dotted pair in which the car is the menu entry 477name and the cdr is the node name. 478 479NEW-MENU-LIST is changed destructively. The old menu is the menu as it 480appears in the texinfo file." 481 482 (let ((new-menu-list-pointer new-menu-list) 483 (end-of-menu (texinfo-menu-end))) 484 (while new-menu-list 485 (save-excursion ; keep point at beginning of menu 486 (if (re-search-forward 487 ;; Existing nodes can have the form 488 ;; * NODE NAME:: DESCRIPTION 489 ;; or 490 ;; * MENU ITEM: NODE NAME. DESCRIPTION. 491 ;; 492 ;; We're interested in the second case. 493 (concat "\\* " ; so only menu entries are found 494 "\\(.*\\): " (car (car new-menu-list)) "[.,\t\n]") 495 end-of-menu 496 t) 497 (setcar 498 (car new-menu-list) ; replace the node name 499 (cons (buffer-substring (match-beginning 1) (match-end 1)) 500 (car (car new-menu-list))))) 501 (setq new-menu-list (cdr new-menu-list)))) 502 (setq new-menu-list new-menu-list-pointer))) 503 504(defun texinfo-menu-copy-old-description (end-of-menu) 505 "Return description field of old menu line as string. 506Point must be located just after the node name. Point left before description. 507Single argument, END-OF-MENU, is position limiting search." 508 (skip-chars-forward "[:.,\t\n ]+") 509 ;; don't copy a carriage return at line beginning with asterisk! 510 ;; do copy a description that begins with an `@'! 511 ;; !! Known bug: does not copy descriptions starting with ^|\{?* etc. 512 (if (and (looking-at "\\(\\w+\\|@\\)") 513 (not (looking-at "\\(^\\* \\|^@end menu\\)"))) 514 (buffer-substring 515 (point) 516 (save-excursion 517 (re-search-forward "\\(^\\* \\|^@end menu\\)" end-of-menu t) 518 (forward-line -1) 519 (end-of-line) ; go to end of last description line 520 (point))) 521 "")) 522 523(defun texinfo-menu-end () 524 "Return position of end of menu, but don't move point. 525Signal an error if not end of menu." 526 (save-excursion 527 (if (re-search-forward "^@end menu" nil t) 528 (point) 529 (error "Menu does not have an end.")))) 530 531(defun texinfo-delete-old-menu (beginning first) 532 "Delete the old menu. Point must be in or after menu. 533First argument is position of the beginning of the section in which 534the menu will be located; second argument is the position of the first 535node within the section." 536 ;; No third arg to search, so error if search fails. 537 (re-search-backward "^@menu" beginning) 538 (delete-region (point) 539 (save-excursion 540 (re-search-forward "^@end menu" first) 541 (point)))) 542 543 544;;; Inserting new menu 545 546;; try 32, but perhaps 24 is better 547(defvar texinfo-column-for-description 32 548 "*Column at which descriptions start in a Texinfo menu.") 549 550(defun texinfo-insert-menu (menu-list node-name) 551 "Insert formatted menu at point. 552Indents the first line of the description, if any, to the value of 553texinfo-column-for-description. 554 555MENU-LIST has form: 556 557 \(\(\"node-name1\" . \"description\"\) 558 \(\"node-name2\" . \"description\"\) ... \) 559 560However, the description field might be nil. 561 562Also, the node-name field might itself be a dotted pair (call it P) of 563strings instead of just a string. In that case, the car of P 564is the menu entry name, and the cdr of P is the node name." 565 566 (insert "@menu\n") 567 (while menu-list 568 ;; Every menu entry starts with a star and a space. 569 (insert "* ") 570 571 ;; Insert the node name (and menu entry name, if present). 572 (let ((node-part (car (car menu-list)))) 573 (if (stringp node-part) 574 ;; "Double colon" entry line; menu entry and node name are the same, 575 (insert (format "%s::" node-part)) 576 ;; "Single colon" entry line; menu entry and node name are different. 577 (insert (format "%s: %s." (car node-part) (cdr node-part))))) 578 579 ;; Insert the description, if present. 580 (if (cdr (car menu-list)) 581 (progn 582 ;; Move to right place. 583 (indent-to texinfo-column-for-description 2) 584 ;; Insert description. 585 (insert (format "%s" (cdr (car menu-list)))))) 586 587 (insert "\n") ; end this menu entry 588 (setq menu-list (cdr menu-list))) 589 (insert "@end menu") 590 (message 591 "Updated \"%s\" level menu following node: %s ... " level node-name)) 592 593 594;;; Starting menu descriptions by inserting titles 595 596(defun texinfo-start-menu-description () 597 "In this menu entry, insert the node's section title as a description. 598Position point at beginning of description ready for editing. 599Do not insert a title if the line contains an existing description. 600 601You will need to edit the inserted text since a useful description 602complements the node name rather than repeats it as a title does." 603 604 (interactive) 605 (let (beginning end node-name title) 606 (save-excursion 607 (beginning-of-line) 608 (if (search-forward "* " (save-excursion (end-of-line) (point)) t) 609 (progn (skip-chars-forward " \t") 610 (setq beginning (point))) 611 (error "This is not a line in a menu!")) 612 613 (cond 614 ;; "Double colon" entry line; menu entry and node name are the same, 615 ((search-forward "::" (save-excursion (end-of-line) (point)) t) 616 (if (looking-at "[ \t]*[^ \t\n]+") 617 (error "Descriptive text already exists.")) 618 (skip-chars-backward ": \t") 619 (setq node-name (buffer-substring beginning (point)))) 620 621 ;; "Single colon" entry line; menu entry and node name are different. 622 ((search-forward ":" (save-excursion (end-of-line) (point)) t) 623 (skip-chars-forward " \t") 624 (setq beginning (point)) 625 ;; Menu entry line ends in a period, comma, or tab. 626 (if (re-search-forward "[.,\t]" 627 (save-excursion (forward-line 1) (point)) t) 628 (progn 629 (if (looking-at "[ \t]*[^ \t\n]+") 630 (error "Descriptive text already exists.")) 631 (skip-chars-backward "., \t") 632 (setq node-name (buffer-substring beginning (point)))) 633 ;; Menu entry line ends in a return. 634 (re-search-forward ".*\n" 635 (save-excursion (forward-line 1) (point)) t) 636 (skip-chars-backward " \t\n") 637 (setq node-name (buffer-substring beginning (point))) 638 (if (= 0 (length node-name)) 639 (error "No node name on this line.") 640 (insert ".")))) 641 (t (error "No node name on this line."))) 642 ;; Search for node that matches node name, and copy the section title. 643 (if (re-search-forward 644 (concat 645 "^@node[ \t]+" 646 node-name 647 ".*\n" ; match node line 648 "\\(" 649 "\\(\\(^@c \\|^@comment\\).*\n\\)" ; match comment line, if any 650 "\\|" ; or 651 "\\(^@ifinfo[ ]*\n\\)" ; ifinfo line, if any 652 "\\)?") 653 nil t) 654 (progn 655 (setq title 656 (buffer-substring 657 ;; skip over section type 658 (progn (forward-word 1) 659 ;; and over spaces 660 (skip-chars-forward " \t") 661 (point)) 662 (progn (end-of-line) 663 (skip-chars-backward " \t") 664 (point))))) 665 (error "Cannot find node to match node name in menu entry."))) 666 ;; Return point to the menu and insert the title. 667 (end-of-line) 668 (delete-region 669 (point) 670 (save-excursion (skip-chars-backward " \t") (point))) 671 (indent-to texinfo-column-for-description 2) 672 (save-excursion (insert title)))) 673 674 675;;; Handling description indentation 676 677;; Since the make-menu functions indent descriptions, these functions 678;; are useful primarily for indenting a single menu specially. 679 680(defun texinfo-indent-menu-description (column &optional region-p) 681 "Indent every description in menu following point to COLUMN. 682Non-nil argument (prefix, if interactive) means indent every 683description in every menu in the region. Does not indent second and 684subsequent lines of a multi-line description." 685 686 (interactive 687 "nIndent menu descriptions to (column number): \nP") 688 (save-excursion 689 (save-restriction 690 (widen) 691 (if (not region-p) 692 (progn 693 (re-search-forward "^@menu") 694 (texinfo-menu-indent-description column) 695 (message 696 "Indented descriptions in menu. You may save the buffer.")) 697 ;;else 698 (message "Indenting every menu description in region... ") 699 (goto-char (region-beginning)) 700 (while (and (< (point) (region-end)) 701 (texinfo-locate-menu-p)) 702 (forward-line 1) 703 (texinfo-menu-indent-description column)) 704 (message "Indenting done. You may save the buffer."))))) 705 706(defun texinfo-menu-indent-description (to-column-number) 707 "Indent the Texinfo file menu description to TO-COLUMN-NUMBER. 708Start with point just after the word `menu' in the `@menu' line and 709leave point on the line before the `@end menu' line. Does not indent 710second and subsequent lines of a multi-line description." 711 (let* ((beginning-of-next-line (point))) 712 (while (< beginning-of-next-line 713 (save-excursion ; beginning of end menu line 714 (goto-char (texinfo-menu-end)) 715 (beginning-of-line) 716 (point))) 717 718 (if (re-search-forward "\\* \\(.*::\\|.*: [^.,\t\n]+[.,\t]\\)" 719 (texinfo-menu-end) 720 t) 721 (progn 722 (let ((beginning-white-space (point))) 723 (skip-chars-forward " \t") ; skip over spaces 724 (if (looking-at "\\(@\\|\\w\\)+") ; if there is text 725 (progn 726 ;; remove pre-existing indentation 727 (delete-region beginning-white-space (point)) 728 (indent-to-column to-column-number)))))) 729 ;; position point at beginning of next line 730 (forward-line 1) 731 (setq beginning-of-next-line (point))))) 732 733 734;;; Making the master menu 735 736(defun texinfo-master-menu (update-all-nodes-menus-p) 737 "Make a master menu for a whole Texinfo file. 738Non-nil argument (prefix, if interactive) means first update all 739existing nodes and menus. Remove pre-existing master menu, if there is one. 740 741This function creates a master menu that follows the top node. The 742master menu includes every entry from all the other menus. It 743replaces any existing ordinary menu that follows the top node. 744 745If called with a non-nil argument, this function first updates all the 746menus in the buffer (incorporating descriptions from pre-existing 747menus) before it constructs the master menu. 748 749The function removes the detailed part of an already existing master 750menu. This action depends on the pre-existing master menu using the 751standard `texinfo-master-menu-header'. 752 753The master menu has the following format, which is adapted from the 754recommendation in the Texinfo Manual: 755 756 * The first part contains the major nodes in the Texinfo file: the 757 nodes for the chapters, chapter-like sections, and the major 758 appendices. This includes the indices, so long as they are in 759 chapter-like sections, such as unnumbered sections. 760 761 * The second and subsequent parts contain a listing of the other, 762 lower level menus, in order. This way, an inquirer can go 763 directly to a particular node if he or she is searching for 764 specific information. 765 766Each of the menus in the detailed node listing is introduced by the 767title of the section containing the menu." 768 769 (interactive "P") 770 (let ((case-fold-search t)) 771 (widen) 772 (goto-char (point-min)) 773 774 ;; Move point to location after `top'. 775 (if (not (re-search-forward "^@node [ \t]*top[ \t]*\\(,\\|$\\)" nil t)) 776 (error "This buffer needs a Top node!")) 777 778 (let ((first-chapter 779 (save-excursion 780 (or (re-search-forward "^@node" nil t) 781 (error "Too few nodes for a master menu!")) 782 (point)))) 783 (if (search-forward texinfo-master-menu-header first-chapter t) 784 (progn 785 ;; Check if @detailmenu kludge is used; 786 ;; if so, leave point before @detailmenu. 787 (search-backward "\n@detailmenu" 788 (save-excursion (forward-line -3) (point)) 789 t) 790 ;; Remove detailed master menu listing 791 (goto-char (match-beginning 0)) 792 (let ((end-of-detailed-menu-descriptions 793 (save-excursion ; beginning of end menu line 794 (goto-char (texinfo-menu-end)) 795 (beginning-of-line) (forward-char -1) 796 (point)))) 797 (delete-region (point) end-of-detailed-menu-descriptions))))) 798 799 (if update-all-nodes-menus-p 800 (progn 801 (message "Making a master menu in %s ...first updating all nodes... " 802 (buffer-name)) 803 (sleep-for 2) 804 (texinfo-update-node (point-min) (point-max)) 805 806 (message "Updating all menus in %s ... " (buffer-name)) 807 (sleep-for 2) 808 (texinfo-make-menu (point-min) (point-max)))) 809 810 (message "Now making the master menu in %s... " (buffer-name)) 811 (sleep-for 2) 812 (goto-char (point-min)) 813 (texinfo-insert-master-menu-list 814 (texinfo-master-menu-list)) 815 816 ;; Remove extra newlines that texinfo-insert-master-menu-list 817 ;; may have inserted. 818 819 (save-excursion 820 (goto-char (point-min)) 821 822 (if (search-forward texinfo-master-menu-header nil t) 823 (progn 824 (goto-char (match-beginning 0)) 825 ;; Check if @detailmenu kludge is used; 826 ;; if so, leave point before @detailmenu. 827 (search-backward "\n@detailmenu" 828 (save-excursion (forward-line -3) (point)) 829 t) 830 (insert "\n") 831 (delete-blank-lines) 832 (goto-char (point-min)))) 833 834 (re-search-forward "^@menu") 835 (forward-line -1) 836 (delete-blank-lines) 837 838 (re-search-forward "^@end menu") 839 (forward-line 1) 840 (delete-blank-lines)) 841 842 (message 843 "Done...completed making master menu. You may save the buffer."))) 844 845(defun texinfo-master-menu-list () 846 "Return a list of menu entries and header lines for the master menu. 847 848Start with the menu for chapters and indices and then find each 849following menu and the title of the node preceding that menu. 850 851The master menu list has this form: 852 853 \(\(\(... \"entry-1-2\" \"entry-1\"\) \"title-1\"\) 854 \(\(... \"entry-2-2\" \"entry-2-1\"\) \"title-2\"\) 855 ...\) 856 857However, there does not need to be a title field." 858 859 (let (master-menu-list) 860 (while (texinfo-locate-menu-p) 861 (setq master-menu-list 862 (cons (list 863 (texinfo-copy-menu) 864 (texinfo-copy-menu-title)) 865 master-menu-list))) 866 (reverse master-menu-list))) 867 868(defun texinfo-insert-master-menu-list (master-menu-list) 869 "Format and insert the master menu in the current buffer." 870 (goto-char (point-min)) 871 ;; Insert a master menu only after `Top' node and before next node 872 ;; \(or include file if there is no next node\). 873 (if (not (re-search-forward "^@node [ \t]*top[ \t]*\\(,\\|$\\)" nil t)) 874 (error "This buffer needs a Top node!")) 875 (let ((first-chapter 876 (save-excursion (re-search-forward "^@node\\|^@include") (point)))) 877 (if (not (re-search-forward "^@menu" first-chapter t)) 878 (error 879 "Buffer lacks ordinary `Top' menu in which to insert master."))) 880 (beginning-of-line) 881 (delete-region ; buffer must have ordinary top menu 882 (point) 883 (save-excursion (re-search-forward "^@end menu") (point))) 884 885 (save-excursion 886 ;; `master-menu-inserted-p' is a kludge to tell 887 ;; whether to insert @end detailmenu (see bleow) 888 (let (master-menu-inserted-p) 889 ;; Handle top of menu 890 (insert "\n@menu\n") 891 ;; Insert chapter menu entries 892 (setq this-very-menu-list (reverse (car (car master-menu-list)))) 893 ;; Tell user what is going on. 894 (message "Inserting chapter menu entry: %s ... " this-very-menu-list) 895 (while this-very-menu-list 896 (insert "* " (car this-very-menu-list) "\n") 897 (setq this-very-menu-list (cdr this-very-menu-list))) 898 899 (setq master-menu-list (cdr master-menu-list)) 900 901 ;; Only insert detailed master menu if there is one.... 902 (if (car (car master-menu-list)) 903 (progn (setq master-menu-inserted-p t) 904 (insert (concat "\n@detailmenu" texinfo-master-menu-header)))) 905 906 ;; @detailmenu added 5 Sept 1996 to `texinfo-master-menu-header' 907 ;; at Karl Berry's request to avert a bug in `makeinfo'; 908 ;; all agree this is a bad kludge and should eventually be removed. 909 ;; @detailmenu ... @end detailmenu is a noop in `texinfmt.el'. 910 ;; See @end detailmenu below; 911 ;; also see `texinfo-all-menus-update' above, `texinfo-master-menu', 912 ;; `texinfo-multiple-files-update'. 913 914 ;; Now, insert all the other menus 915 916 ;; The menu master-menu-list has a form like this: 917 ;; ((("beta" "alpha") "title-A") 918 ;; (("delta" "gamma") "title-B")) 919 920 (while master-menu-list 921 922 (message 923 "Inserting menu for %s .... " (car (cdr (car master-menu-list)))) 924 ;; insert title of menu section 925 (insert "\n" (car (cdr (car master-menu-list))) "\n\n") 926 927 ;; insert each menu entry 928 (setq this-very-menu-list (reverse (car (car master-menu-list)))) 929 (while this-very-menu-list 930 (insert "* " (car this-very-menu-list) "\n") 931 (setq this-very-menu-list (cdr this-very-menu-list))) 932 933 (setq master-menu-list (cdr master-menu-list))) 934 935 ;; Finish menu 936 937 ;; @detailmenu (see note above) 938 ;; Only insert @end detailmenu if a master menu was inserted. 939 (if master-menu-inserted-p 940 (insert "\n@end detailmenu")) 941 (insert "\n@end menu\n\n")))) 942 943(defun texinfo-locate-menu-p () 944 "Find the next menu in the texinfo file. 945If found, leave point after word `menu' on the `@menu' line, and return t. 946If a menu is not found, do not move point and return nil." 947 (re-search-forward "\\(^@menu\\)" nil t)) 948 949(defun texinfo-copy-menu-title () 950 "Return the title of the section preceding the menu as a string. 951If such a title cannot be found, return an empty string. Do not move 952point." 953 (let ((case-fold-search t)) 954 (save-excursion 955 (if (re-search-backward 956 (concat 957 "\\(^@top" 958 "\\|" ; or 959 texinfo-section-types-regexp ; all other section types 960 "\\)") 961 nil 962 t) 963 (progn 964 (beginning-of-line) 965 (forward-word 1) ; skip over section type 966 (skip-chars-forward " \t") ; and over spaces 967 (buffer-substring 968 (point) 969 (progn (end-of-line) (point)))) 970 "")))) 971 972(defun texinfo-copy-menu () 973 "Return the entries of an existing menu as a list. 974Start with point just after the word `menu' in the `@menu' line 975and leave point on the line before the `@end menu' line." 976 (let* (this-menu-list 977 (end-of-menu (texinfo-menu-end)) ; position of end of `@end menu' 978 (last-entry (save-excursion ; position of beginning of 979 ; last `* ' entry 980 (goto-char end-of-menu) 981 ;; handle multi-line description 982 (if (not (re-search-backward "^\\* " nil t)) 983 (error "No entries in menu.")) 984 (point)))) 985 (while (< (point) last-entry) 986 (if (re-search-forward "^\\* " end-of-menu t) 987 (progn 988 (setq this-menu-list 989 (cons 990 (buffer-substring 991 (point) 992 ;; copy multi-line descriptions 993 (save-excursion 994 (re-search-forward "\\(^\\* \\|^@e\\)" nil t) 995 (- (point) 3))) 996 this-menu-list))))) 997 this-menu-list)) 998 999 1000;;; Determining the hierarchical level in the texinfo file 1001 1002(defun texinfo-specific-section-type () 1003 "Return the specific type of next section, as a string. 1004For example, \"unnumberedsubsec\". Return \"top\" for top node. 1005 1006Searches forward for a section. Hence, point must be before the 1007section whose type will be found. Does not move point. Signal an 1008error if the node is not the top node and a section is not found." 1009 (let ((case-fold-search t)) 1010 (save-excursion 1011 (cond 1012 ((re-search-forward "^@node [ \t]*top[ \t]*\\(,\\|$\\)" 1013;;; Following search limit by cph but causes a bug 1014;;; (save-excursion 1015;;; (end-of-line) 1016;;; (point)) 1017 nil 1018 t) 1019 "top") 1020 ((re-search-forward texinfo-section-types-regexp nil t) 1021 (buffer-substring-no-properties 1022 (progn (beginning-of-line) ; copy its name 1023 (1+ (point))) 1024 (progn (forward-word 1) 1025 (point)))) 1026 (t 1027 (error 1028 "texinfo-specific-section-type: Chapter or section not found.")))))) 1029 1030(defun texinfo-hierarchic-level () 1031 "Return the general hierarchal level of the next node in a texinfo file. 1032Thus, a subheading or appendixsubsec is of type subsection." 1033 (let ((case-fold-search t)) 1034 (cdr (assoc 1035 (texinfo-specific-section-type) 1036 texinfo-section-to-generic-alist)))) 1037 1038 1039;;; Locating the major positions 1040 1041(defun texinfo-update-menu-region-beginning (level) 1042 "Locate beginning of higher level section this section is within. 1043Return position of the beginning of the node line; do not move point. 1044Thus, if this level is subsection, searches backwards for section node. 1045Only argument is a string of the general type of section." 1046 (let ((case-fold-search t)) 1047 ;; !! Known bug: if section immediately follows top node, this 1048 ;; returns the beginning of the buffer as the beginning of the 1049 ;; higher level section. 1050 (cond 1051 ((or (string-equal "top" level) 1052 (string-equal "chapter" level)) 1053 (save-excursion 1054 (goto-char (point-min)) 1055 (re-search-forward "^@node [ \t]*top[ \t]*\\(,\\|$\\)" nil t) 1056 (beginning-of-line) 1057 (point))) 1058 (t 1059 (save-excursion 1060 (re-search-backward 1061 (concat 1062 "\\(^@node\\).*\n" ; match node line 1063 "\\(\\(\\(^@c\\).*\n\\)" ; match comment line, if any 1064 "\\|" ; or 1065 "\\(^@ifinfo[ ]*\n\\)\\)?" ; ifinfo line, if any 1066 (eval 1067 (cdr (assoc level texinfo-update-menu-higher-regexps)))) 1068 nil 1069 'goto-beginning) 1070 (point)))))) 1071 1072(defun texinfo-update-menu-region-end (level) 1073 "Locate end of higher level section this section is within. 1074Return position; do not move point. Thus, if this level is a 1075subsection, find the node for the section this subsection is within. 1076If level is top or chapter, returns end of file. Only argument is a 1077string of the general type of section." 1078 (let ((case-fold-search t)) 1079 (save-excursion 1080 (if (re-search-forward 1081 (concat 1082 "\\(^@node\\).*\n" ; match node line 1083 "\\(\\(\\(^@c\\).*\n\\)" ; match comment line, if any 1084 "\\|" ; or 1085 "\\(^@ifinfo[ ]*\n\\)\\)?" ; ifinfo line, if any 1086 (eval 1087 ;; Never finds end of level above chapter so goes to end. 1088 (cdr (assoc level texinfo-update-menu-higher-regexps)))) 1089 nil 1090 'goto-end) 1091 (match-beginning 1) 1092 (point-max))))) 1093 1094(defun texinfo-menu-first-node (beginning end) 1095 "Locate first node of the section the menu will be placed in. 1096Return position; do not move point. 1097The menu will be located just before this position. 1098 1099First argument is the position of the beginning of the section in 1100which the menu will be located; second argument is the position of the 1101end of that region; it limits the search." 1102 1103 (save-excursion 1104 (goto-char beginning) 1105 (forward-line 1) 1106 (re-search-forward "^@node" end t) 1107 (beginning-of-line) 1108 (point))) 1109 1110 1111;;; Alists and regular expressions for defining hierarchical levels 1112 1113(defvar texinfo-section-to-generic-alist 1114 '(("top" . "top") 1115 1116 ("chapter" . "chapter") 1117 ("unnumbered" . "chapter") 1118 ("majorheading" . "chapter") 1119 ("chapheading" . "chapter") 1120 ("appendix" . "chapter") 1121 1122 ("section" . "section") 1123 ("unnumberedsec" . "section") 1124 ("heading" . "section") 1125 ("appendixsec" . "section") 1126 1127 ("subsection" . "subsection") 1128 ("unnumberedsubsec" . "subsection") 1129 ("subheading" . "subsection") 1130 ("appendixsubsec" . "subsection") 1131 1132 ("subsubsection" . "subsubsection") 1133 ("unnumberedsubsubsec" . "subsubsection") 1134 ("subsubheading" . "subsubsection") 1135 ("appendixsubsubsec" . "subsubsection")) 1136 "*An alist of specific and corresponding generic Texinfo section types. 1137The keys are strings specifying specific types of section; the values 1138are strings of their corresponding general types.") 1139 1140;; We used to look for just sub, but that found @subtitle. 1141(defvar texinfo-section-types-regexp 1142 "^@\\(chapter \\|sect\\|subs\\|subh\\|unnum\\|major\\|chapheading \\|heading \\|appendix\\)" 1143 "Regexp matching chapter, section, other headings (but not the top node).") 1144 1145(defvar texinfo-chapter-level-regexp 1146 "chapter\\|unnumbered \\|appendix \\|majorheading\\|chapheading" 1147 "Regular expression matching just the Texinfo chapter level headings.") 1148 1149(defvar texinfo-section-level-regexp 1150 "section\\|unnumberedsec\\|heading \\|appendixsec" 1151 "Regular expression matching just the Texinfo section level headings.") 1152 1153(defvar texinfo-subsection-level-regexp 1154 "subsection\\|unnumberedsubsec\\|subheading\\|appendixsubsec" 1155 "Regular expression matching just the Texinfo subsection level headings.") 1156 1157(defvar texinfo-subsubsection-level-regexp 1158 "subsubsection\\|unnumberedsubsubsec\\|subsubheading\\|appendixsubsubsec" 1159 "Regular expression matching just the Texinfo subsubsection level headings.") 1160 1161(defvar texinfo-update-menu-same-level-regexps 1162 '(("top" . "top[ \t]+") 1163 ("chapter" . 1164 (concat "\\(^@\\)\\(" texinfo-chapter-level-regexp "\\)[ \t]*")) 1165 ("section" . 1166 (concat "\\(^@\\)\\(" texinfo-section-level-regexp "\\)[ \t]*")) 1167 ("subsection" . 1168 (concat "\\(^@\\)\\(" texinfo-subsection-level-regexp "\\)[ \t]+")) 1169 ("subsubsection" . 1170 (concat "\\(^@\\)\\(" texinfo-subsubsection-level-regexp "\\)[ \t]+"))) 1171 "*Regexps for searching for same level sections in a Texinfo file. 1172The keys are strings specifying the general hierarchical level in the 1173document; the values are regular expressions.") 1174 1175(defvar texinfo-update-menu-higher-regexps 1176 '(("top" . "^@node [ \t]*DIR") 1177 ("chapter" . "^@node [ \t]*top[ \t]*\\(,\\|$\\)") 1178 ("section" . 1179 (concat 1180 "\\(^@\\(" 1181 texinfo-chapter-level-regexp 1182 "\\)[ \t]*\\)")) 1183 ("subsection" . 1184 (concat 1185 "\\(^@\\(" 1186 texinfo-section-level-regexp 1187 "\\|" 1188 texinfo-chapter-level-regexp 1189 "\\)[ \t]*\\)")) 1190 ("subsubsection" . 1191 (concat 1192 "\\(^@\\(" 1193 texinfo-subsection-level-regexp 1194 "\\|" 1195 texinfo-section-level-regexp 1196 "\\|" 1197 texinfo-chapter-level-regexp 1198 "\\)[ \t]*\\)"))) 1199 "*Regexps for searching for higher level sections in a Texinfo file. 1200The keys are strings specifying the general hierarchical level in the 1201document; the values are regular expressions.") 1202 1203(defvar texinfo-update-menu-lower-regexps 1204 '(("top" . 1205 (concat 1206 "\\(^@\\(" 1207 texinfo-chapter-level-regexp 1208 "\\|" 1209 texinfo-section-level-regexp 1210 "\\|" 1211 texinfo-subsection-level-regexp 1212 "\\|" 1213 texinfo-subsubsection-level-regexp 1214 "\\)[ \t]*\\)")) 1215 ("chapter" . 1216 (concat 1217 "\\(^@\\(" 1218 texinfo-section-level-regexp 1219 "\\|" 1220 texinfo-subsection-level-regexp 1221 "\\|" 1222 texinfo-subsubsection-level-regexp 1223 "\\)[ \t]*\\)")) 1224 ("section" . 1225 (concat 1226 "\\(^@\\(" 1227 texinfo-subsection-level-regexp 1228 "\\|" 1229 texinfo-subsubsection-level-regexp 1230 "\\)[ \t]+\\)")) 1231 ("subsection" . 1232 (concat 1233 "\\(^@\\(" 1234 texinfo-subsubsection-level-regexp 1235 "\\)[ \t]+\\)")) 1236 ("subsubsection" . "nothing lower")) 1237 "*Regexps for searching for lower level sections in a Texinfo file. 1238The keys are strings specifying the general hierarchical level in the 1239document; the values are regular expressions.") 1240 1241 1242;;; Updating a node 1243 1244;;;###autoload 1245(defun texinfo-update-node (&optional beginning end) 1246 "Without any prefix argument, update the node in which point is located. 1247Interactively, a prefix argument means to operate on the region. 1248 1249The functions for creating or updating nodes and menus, and their 1250keybindings, are: 1251 1252 texinfo-update-node (&optional beginning end) \\[texinfo-update-node] 1253 texinfo-every-node-update () \\[texinfo-every-node-update] 1254 texinfo-sequential-node-update (&optional region-p) 1255 1256 texinfo-make-menu (&optional region-p) \\[texinfo-make-menu] 1257 texinfo-all-menus-update () \\[texinfo-all-menus-update] 1258 texinfo-master-menu () 1259 1260 texinfo-indent-menu-description (column &optional region-p) 1261 1262The `texinfo-column-for-description' variable specifies the column to 1263which menu descriptions are indented. Its default value is 32." 1264 1265 (interactive 1266 (if prefix-arg 1267 (list (point) (mark)))) 1268 (if (null beginning) 1269 ;; Update a single node. 1270 (let ((auto-fill-function nil) (auto-fill-hook nil)) 1271 (if (not (re-search-backward "^@node" (point-min) t)) 1272 (error "Node line not found before this position")) 1273 (texinfo-update-the-node) 1274 (message "Done...updated the node. You may save the buffer.")) 1275 ;; else 1276 (let ((auto-fill-function nil) 1277 (auto-fill-hook nil)) 1278 (save-excursion 1279 (save-restriction 1280 (narrow-to-region beginning end) 1281 (goto-char (point-min)) 1282 (while (re-search-forward "^@node" (point-max) t) 1283 (beginning-of-line) 1284 (texinfo-update-the-node)) 1285 (goto-char (point-max)) 1286 (message "Done...nodes updated in region. You may save the buffer.")))))) 1287 1288;;;###autoload 1289(defun texinfo-every-node-update () 1290 "Update every node in a Texinfo file." 1291 (interactive) 1292 (save-excursion 1293 (texinfo-update-node (point-min) (point-max)) 1294 (message "Done...updated every node. You may save the buffer."))) 1295 1296(defun texinfo-update-the-node () 1297 "Update one node. Point must be at the beginning of node line. 1298Leave point at the end of the node line." 1299 (texinfo-check-for-node-name) 1300 (texinfo-delete-existing-pointers) 1301 (message "Updating node: %s ... " (texinfo-copy-node-name)) 1302 (save-restriction 1303 (widen) 1304 (let* 1305 ((case-fold-search t) 1306 (level (texinfo-hierarchic-level)) 1307 (beginning (texinfo-update-menu-region-beginning level)) 1308 (end (texinfo-update-menu-region-end level))) 1309 (if (string-equal level "top") 1310 (texinfo-top-pointer-case) 1311 ;; else 1312 (texinfo-insert-pointer beginning end level 'next) 1313 (texinfo-insert-pointer beginning end level 'previous) 1314 (texinfo-insert-pointer beginning end level 'up) 1315 (texinfo-clean-up-node-line))))) 1316 1317(defun texinfo-top-pointer-case () 1318 "Insert pointers in the Top node. This is a special case. 1319 1320The `Next' pointer is a pointer to a chapter or section at a lower 1321hierarchical level in the file. The `Previous' and `Up' pointers are 1322to `(dir)'. Point must be at the beginning of the node line, and is 1323left at the end of the node line." 1324 1325 (texinfo-clean-up-node-line) 1326 (insert ", " 1327 (save-excursion 1328 ;; There may be an @chapter or other such command between 1329 ;; the top node line and the next node line, as a title 1330 ;; for an `ifinfo' section. This @chapter command must 1331 ;; must be skipped. So the procedure is to search for 1332 ;; the next `@node' line, and then copy its name. 1333 (if (re-search-forward "^@node" nil t) 1334 (progn 1335 (beginning-of-line) 1336 (texinfo-copy-node-name)) 1337 " ")) 1338 ", (dir), (dir)")) 1339 1340(defun texinfo-check-for-node-name () 1341 "Determine whether the node has a node name. Prompt for one if not. 1342Point must be at beginning of node line. Does not move point." 1343 (save-excursion 1344 (let ((initial (texinfo-copy-next-section-title))) 1345 ;; This is not clean. Use `interactive' to read the arg. 1346 (forward-word 1) ; skip over node command 1347 (skip-chars-forward " \t") ; and over spaces 1348 (if (not (looking-at "[^,\t\n ]+")) ; regexp based on what Info looks for 1349 ; alternatively, use "[a-zA-Z]+" 1350 (let ((node-name 1351 (read-from-minibuffer 1352 "Node name (use no @, commas, colons, or apostrophes): " 1353 initial))) 1354 (insert " " node-name)))))) 1355 1356(defun texinfo-delete-existing-pointers () 1357 "Delete `Next', `Previous', and `Up' pointers. 1358Starts from the current position of the cursor, and searches forward 1359on the line for a comma and if one is found, deletes the rest of the 1360line, including the comma. Leaves point at beginning of line." 1361 (let ((eol-point (save-excursion (end-of-line) (point)))) 1362 (if (search-forward "," eol-point t) 1363 (delete-region (1- (point)) eol-point))) 1364 (beginning-of-line)) 1365 1366(defun texinfo-find-pointer (beginning end level direction) 1367 "Move point to section associated with next, previous, or up pointer. 1368Return type of pointer (either `normal' or `no-pointer'). 1369 1370The first and second arguments bound the search for a pointer to the 1371beginning and end, respectively, of the enclosing higher level 1372section. The third argument is a string specifying the general kind 1373of section such as \"chapter\" or \"section\". When looking for the 1374`Next' pointer, the section found will be at the same hierarchical 1375level in the Texinfo file; when looking for the `Previous' pointer, 1376the section found will be at the same or higher hierarchical level in 1377the Texinfo file; when looking for the `Up' pointer, the section found 1378will be at some level higher in the Texinfo file. The fourth argument 1379\(one of 'next, 'previous, or 'up\) specifies whether to find the 1380`Next', `Previous', or `Up' pointer." 1381 (let ((case-fold-search t)) 1382 (cond ((eq direction 'next) 1383 (forward-line 3) ; skip over current node 1384 ;; Search for section commands accompanied by node lines; 1385 ;; ignore section commands in the middle of nodes. 1386 (if (re-search-forward 1387 ;; A `Top' node is never a next pointer, so won't find it. 1388 (concat 1389 ;; Match node line. 1390 "\\(^@node\\).*\n" 1391 ;; Match comment or ifinfo line, if any 1392 "\\(\\(\\(^@c\\).*\n\\)\\|\\(^@ifinfo[ ]*\n\\)\\)?" 1393 (eval 1394 (cdr (assoc level texinfo-update-menu-same-level-regexps)))) 1395 end 1396 t) 1397 'normal 1398 'no-pointer)) 1399 ((eq direction 'previous) 1400 (if (re-search-backward 1401 (concat 1402 "\\(" 1403 ;; Match node line. 1404 "\\(^@node\\).*\n" 1405 ;; Match comment or ifinfo line, if any 1406 "\\(\\(\\(^@c\\).*\n\\)\\|\\(^@ifinfo[ ]*\n\\)\\)?" 1407 (eval 1408 (cdr (assoc level texinfo-update-menu-same-level-regexps))) 1409 "\\|" 1410 ;; Match node line. 1411 "\\(^@node\\).*\n" 1412 ;; Match comment or ifinfo line, if any 1413 "\\(\\(\\(^@c\\).*\n\\)\\|\\(^@ifinfo[ ]*\n\\)\\)?" 1414 (eval 1415 (cdr (assoc level texinfo-update-menu-higher-regexps))) 1416 "\\|" 1417 ;; Handle `Top' node specially. 1418 "^@node [ \t]*top[ \t]*\\(,\\|$\\)" 1419 "\\)") 1420 beginning 1421 t) 1422 'normal 1423 'no-pointer)) 1424 ((eq direction 'up) 1425 (if (re-search-backward 1426 (concat 1427 "\\(" 1428 ;; Match node line. 1429 "\\(^@node\\).*\n" 1430 ;; Match comment or ifinfo line, if any 1431 "\\(\\(\\(^@c\\).*\n\\)\\|\\(^@ifinfo[ ]*\n\\)\\)?" 1432 (eval (cdr (assoc level texinfo-update-menu-higher-regexps))) 1433 "\\|" 1434 ;; Handle `Top' node specially. 1435 "^@node [ \t]*top[ \t]*\\(,\\|$\\)" 1436 "\\)") 1437 (save-excursion 1438 (goto-char beginning) 1439 (beginning-of-line) 1440 (point)) 1441 t) 1442 'normal 1443 'no-pointer)) 1444 (t 1445 (error "texinfo-find-pointer: lack proper arguments"))))) 1446 1447(defun texinfo-pointer-name (kind) 1448 "Return the node name preceding the section command. 1449The argument is the kind of section, either `normal' or `no-pointer'." 1450 (let (name) 1451 (cond ((eq kind 'normal) 1452 (end-of-line) ; this handles prev node top case 1453 (re-search-backward ; when point is already 1454 "^@node" ; at the beginning of @node line 1455 (save-excursion (forward-line -3)) 1456 t) 1457 (setq name (texinfo-copy-node-name))) 1458 ((eq kind 'no-pointer) 1459 ;; Don't need to put a blank in the pointer slot, 1460 ;; since insert "' " always has a space 1461 (setq name " "))) ; put a blank in the pointer slot 1462 name)) 1463 1464(defun texinfo-insert-pointer (beginning end level direction) 1465 "Insert the `Next', `Previous' or `Up' node name at point. 1466Move point forward. 1467 1468The first and second arguments bound the search for a pointer to the 1469beginning and end, respectively, of the enclosing higher level 1470section. The third argument is the hierarchical level of the Texinfo 1471file, a string such as \"section\". The fourth argument is direction 1472towards which the pointer is directed, one of `next', `previous', or `up'." 1473 1474 (end-of-line) 1475 (insert 1476 ", " 1477 (save-excursion 1478 (texinfo-pointer-name 1479 (texinfo-find-pointer beginning end level direction))))) 1480 1481(defun texinfo-clean-up-node-line () 1482 "Remove extra commas, if any, at end of node line." 1483 (end-of-line) 1484 (skip-chars-backward ", ") 1485 (delete-region (point) (save-excursion (end-of-line) (point)))) 1486 1487 1488;;; Updating nodes sequentially 1489;; These sequential update functions insert `Next' or `Previous' 1490;; pointers that point to the following or preceding nodes even if they 1491;; are at higher or lower hierarchical levels. This means that if a 1492;; section contains one or more subsections, the section's `Next' 1493;; pointer will point to the subsection and not the following section. 1494;; (The subsection to which `Next' points will most likely be the first 1495;; item on the section's menu.) 1496 1497;;;###autoload 1498(defun texinfo-sequential-node-update (&optional region-p) 1499 "Update one node (or many) in a Texinfo file with sequential pointers. 1500 1501This function causes the `Next' or `Previous' pointer to point to the 1502immediately preceding or following node, even if it is at a higher or 1503lower hierarchical level in the document. Continually pressing `n' or 1504`p' takes you straight through the file. 1505 1506Without any prefix argument, update the node in which point is located. 1507Non-nil argument (prefix, if interactive) means update the nodes in the 1508marked region. 1509 1510This command makes it awkward to navigate among sections and 1511subsections; it should be used only for those documents that are meant 1512to be read like a novel rather than a reference, and for which the 1513Info `g*' command is inadequate." 1514 1515 (interactive "P") 1516 (if (not region-p) 1517 ;; update a single node 1518 (let ((auto-fill-function nil) (auto-fill-hook nil)) 1519 (if (not (re-search-backward "^@node" (point-min) t)) 1520 (error "Node line not found before this position.")) 1521 (texinfo-sequentially-update-the-node) 1522 (message 1523 "Done...sequentially updated the node . You may save the buffer.")) 1524 ;; else 1525 (let ((auto-fill-function nil) 1526 (auto-fill-hook nil) 1527 (beginning (region-beginning)) 1528 (end (region-end))) 1529 (if (= end beginning) 1530 (error "Please mark a region!")) 1531 (save-restriction 1532 (narrow-to-region beginning end) 1533 (goto-char beginning) 1534 (push-mark (point) t) 1535 (while (re-search-forward "^@node" (point-max) t) 1536 (beginning-of-line) 1537 (texinfo-sequentially-update-the-node)) 1538 (message 1539 "Done...updated the nodes in sequence. You may save the buffer."))))) 1540 1541(defun texinfo-sequentially-update-the-node () 1542 "Update one node such that the pointers are sequential. 1543A `Next' or `Previous' pointer points to any preceding or following node, 1544regardless of its hierarchical level." 1545 1546 (texinfo-check-for-node-name) 1547 (texinfo-delete-existing-pointers) 1548 (message 1549 "Sequentially updating node: %s ... " (texinfo-copy-node-name)) 1550 (save-restriction 1551 (widen) 1552 (let* 1553 ((case-fold-search t) 1554 (level (texinfo-hierarchic-level))) 1555 (if (string-equal level "top") 1556 (texinfo-top-pointer-case) 1557 ;; else 1558 (texinfo-sequentially-insert-pointer level 'next) 1559 (texinfo-sequentially-insert-pointer level 'previous) 1560 (texinfo-sequentially-insert-pointer level 'up) 1561 (texinfo-clean-up-node-line))))) 1562 1563(defun texinfo-sequentially-find-pointer (level direction) 1564 "Find next or previous pointer sequentially in Texinfo file, or up pointer. 1565Move point to section associated with the pointer. Find point even if 1566it is in a different section. 1567 1568Return type of pointer (either `normal' or `no-pointer'). 1569 1570The first argument is a string specifying the general kind of section 1571such as \"chapter\" or \"section\". The section found will be at the 1572same hierarchical level in the Texinfo file, or, in the case of the up 1573pointer, some level higher. The second argument (one of `next', 1574`previous', or `up') specifies whether to find the `Next', `Previous', 1575or `Up' pointer." 1576 (let ((case-fold-search t)) 1577 (cond ((eq direction 'next) 1578 (forward-line 3) ; skip over current node 1579 (if (re-search-forward 1580 texinfo-section-types-regexp 1581 (point-max) 1582 t) 1583 'normal 1584 'no-pointer)) 1585 ((eq direction 'previous) 1586 (if (re-search-backward 1587 texinfo-section-types-regexp 1588 (point-min) 1589 t) 1590 'normal 1591 'no-pointer)) 1592 ((eq direction 'up) 1593 (if (re-search-backward 1594 (eval (cdr (assoc level texinfo-update-menu-higher-regexps))) 1595 beginning 1596 t) 1597 'normal 1598 'no-pointer)) 1599 (t 1600 (error "texinfo-sequential-find-pointer: lack proper arguments"))))) 1601 1602(defun texinfo-sequentially-insert-pointer (level direction) 1603 "Insert the `Next', `Previous' or `Up' node name at point. 1604Move point forward. 1605 1606The first argument is the hierarchical level of the Texinfo file, a 1607string such as \"section\". The second argument is direction, one of 1608`next', `previous', or `up'." 1609 1610 (end-of-line) 1611 (insert 1612 ", " 1613 (save-excursion 1614 (texinfo-pointer-name 1615 (texinfo-sequentially-find-pointer level direction))))) 1616 1617 1618;;; Inserting `@node' lines 1619;; The `texinfo-insert-node-lines' function inserts `@node' lines as needed 1620;; before the `@chapter', `@section', and such like lines of a region 1621;; in a Texinfo file. 1622 1623(defun texinfo-insert-node-lines (beginning end &optional title-p) 1624 "Insert missing `@node' lines in region of Texinfo file. 1625Non-nil argument (prefix, if interactive) means also to insert the 1626section titles as node names; and also to insert the section titles as 1627node names in pre-existing `@node' lines that lack names." 1628 (interactive "r\nP") 1629 1630 ;; Use marker; after inserting node lines, leave point at end of 1631 ;; region and mark at beginning. 1632 1633 (let (beginning-marker end-marker title last-section-position) 1634 1635 ;; Save current position on mark ring and set mark to end. 1636 (push-mark end t) 1637 (setq end-marker (mark-marker)) 1638 1639 (goto-char beginning) 1640 (while (re-search-forward 1641 texinfo-section-types-regexp 1642 end-marker 1643 'end) 1644 ;; Copy title if desired. 1645 (if title-p 1646 (progn 1647 (beginning-of-line) 1648 (forward-word 1) 1649 (skip-chars-forward " \t") 1650 (setq title (buffer-substring 1651 (point) 1652 (save-excursion (end-of-line) (point)))))) 1653 ;; Insert node line if necessary. 1654 (if (re-search-backward 1655 "^@node" 1656 ;; Avoid finding previous node line if node lines are close. 1657 (or last-section-position 1658 (save-excursion (forward-line -2) (point))) t) 1659 ;; @node is present, and point at beginning of that line 1660 (forward-word 1) ; Leave point just after @node. 1661 ;; Else @node missing; insert one. 1662 (beginning-of-line) ; Beginning of `@section' line. 1663 (insert "@node\n") 1664 (backward-char 1)) ; Leave point just after `@node'. 1665 ;; Insert title if desired. 1666 (if title-p 1667 (progn 1668 (skip-chars-forward " \t") 1669 ;; Use regexp based on what info looks for 1670 ;; (alternatively, use "[a-zA-Z]+"); 1671 ;; this means we only insert a title if none exists. 1672 (if (not (looking-at "[^,\t\n ]+")) 1673 (progn 1674 (beginning-of-line) 1675 (forward-word 1) 1676 (insert " " title) 1677 (message "Inserted title %s ... " title))))) 1678 ;; Go forward beyond current section title. 1679 (re-search-forward texinfo-section-types-regexp 1680 (save-excursion (forward-line 3) (point)) t) 1681 (setq last-section-position (point)) 1682 (forward-line 1)) 1683 1684 ;; Leave point at end of region, mark at beginning. 1685 (set-mark beginning) 1686 1687 (if title-p 1688 (message 1689 "Done inserting node lines and titles. You may save the buffer.") 1690 (message "Done inserting node lines. You may save the buffer.")))) 1691 1692 1693;;; Update and create menus for multi-file Texinfo sources 1694 1695;; 1. M-x texinfo-multiple-files-update 1696;; 1697;; Read the include file list of an outer Texinfo file and 1698;; update all highest level nodes in the files listed and insert a 1699;; main menu in the outer file after its top node. 1700 1701;; 2. C-u M-x texinfo-multiple-files-update 1702;; 1703;; Same as 1, but insert a master menu. (Saves reupdating lower 1704;; level menus and nodes.) This command simply reads every menu, 1705;; so if the menus are wrong, the master menu will be wrong. 1706;; Similarly, if the lower level node pointers are wrong, they 1707;; will stay wrong. 1708 1709;; 3. C-u 2 M-x texinfo-multiple-files-update 1710;; 1711;; Read the include file list of an outer Texinfo file and 1712;; update all nodes and menus in the files listed and insert a 1713;; master menu in the outer file after its top node. 1714 1715;;; Note: these functions: 1716;;; 1717;;; * Do not save or delete any buffers. You may fill up your memory. 1718;;; * Do not handle any pre-existing nodes in outer file. 1719;;; Hence, you may need a file for indices. 1720 1721 1722;;; Auxiliary functions for multiple file updating 1723 1724(defun texinfo-multi-file-included-list (outer-file) 1725 "Return a list of the included files in OUTER-FILE." 1726 (let ((included-file-list (list outer-file)) 1727 start) 1728 (save-excursion 1729 (switch-to-buffer (find-file-noselect outer-file)) 1730 (widen) 1731 (goto-char (point-min)) 1732 (while (re-search-forward "^@include" nil t) 1733 (skip-chars-forward " \t") 1734 (setq start (point)) 1735 (end-of-line) 1736 (skip-chars-backward " \t") 1737 (setq included-file-list 1738 (cons (buffer-substring start (point)) 1739 included-file-list))) 1740 (nreverse included-file-list)))) 1741 1742(defun texinfo-copy-next-section-title () 1743 "Return the name of the immediately following section as a string. 1744 1745Start with point at the beginning of the node line. Leave point at the 1746same place. If there is no title, returns an empty string." 1747 1748 (save-excursion 1749 (end-of-line) 1750 (let ((node-end (or 1751 (save-excursion 1752 (if (re-search-forward "\\(^@node\\)" nil t) 1753 (match-beginning 0))) 1754 (point-max)))) 1755 (if (re-search-forward texinfo-section-types-regexp node-end t) 1756 (progn 1757 (beginning-of-line) 1758 ;; copy title 1759 (let ((title 1760 (buffer-substring 1761 (progn (forward-word 1) ; skip over section type 1762 (skip-chars-forward " \t") ; and over spaces 1763 (point)) 1764 (progn (end-of-line) (point))))) 1765 title)) 1766 "")))) 1767 1768(defun texinfo-multi-file-update (files &optional update-everything) 1769 "Update first node pointers in each file in FILES. 1770Return a list of the node names. 1771 1772The first file in the list is an outer file; the remaining are 1773files included in the outer file with `@include' commands. 1774 1775If optional arg UPDATE-EVERYTHING non-nil, update every menu and 1776pointer in each of the included files. 1777 1778Also update the `Top' level node pointers of the outer file. 1779 1780Requirements: 1781 1782 * the first file in the FILES list must be the outer file, 1783 * each of the included files must contain exactly one highest 1784 hierarchical level node, 1785 * this node must be the first node in the included file, 1786 * each highest hierarchical level node must be of the same type. 1787 1788Thus, normally, each included file contains one, and only one, chapter." 1789 1790;; The menu-list has the form: 1791;; 1792;; \(\(\"node-name1\" . \"title1\"\) 1793;; \(\"node-name2\" . \"title2\"\) ... \) 1794;; 1795;; However, there does not need to be a title field and this function 1796;; does not fill it; however a comment tells you how to do so. 1797;; You would use the title field if you wanted to insert titles in the 1798;; description slot of a menu as a description. 1799 1800 (let ((case-fold-search t) 1801 menu-list) 1802 1803 ;; Find the name of the first node of the first included file. 1804 (switch-to-buffer (find-file-noselect (car (cdr files)))) 1805 (widen) 1806 (goto-char (point-min)) 1807 (if (not (re-search-forward "^@node" nil t)) 1808 (error "No `@node' line found in %s !" (buffer-name))) 1809 (beginning-of-line) 1810 (texinfo-check-for-node-name) 1811 (setq next-node-name (texinfo-copy-node-name)) 1812 1813 (setq menu-list 1814 (cons (cons 1815 next-node-name 1816 (prog1 "" (forward-line 1))) 1817 ;; Use following to insert section titles automatically. 1818 ;; (texinfo-copy-next-section-title) 1819 menu-list)) 1820 1821 ;; Go to outer file 1822 (switch-to-buffer (find-file-noselect (car files))) 1823 (goto-char (point-min)) 1824 (if (not (re-search-forward "^@node [ \t]*top[ \t]*\\(,\\|$\\)" nil t)) 1825 (error "This buffer needs a Top node!")) 1826 (beginning-of-line) 1827 (texinfo-delete-existing-pointers) 1828 (end-of-line) 1829 (insert ", " next-node-name ", (dir), (dir)") 1830 (beginning-of-line) 1831 (setq previous-node-name "Top") 1832 (setq files (cdr files)) 1833 1834 (while files 1835 1836 (if (not (cdr files)) 1837 ;; No next file 1838 (setq next-node-name "") 1839 ;; Else, 1840 ;; find the name of the first node in the next file. 1841 (switch-to-buffer (find-file-noselect (car (cdr files)))) 1842 (widen) 1843 (goto-char (point-min)) 1844 (if (not (re-search-forward "^@node" nil t)) 1845 (error "No `@node' line found in %s !" (buffer-name))) 1846 (beginning-of-line) 1847 (texinfo-check-for-node-name) 1848 (setq next-node-name (texinfo-copy-node-name)) 1849 (setq menu-list 1850 (cons (cons 1851 next-node-name 1852 (prog1 "" (forward-line 1))) 1853 ;; Use following to insert section titles automatically. 1854 ;; (texinfo-copy-next-section-title) 1855 menu-list))) 1856 1857 ;; Go to node to be updated. 1858 (switch-to-buffer (find-file-noselect (car files))) 1859 (goto-char (point-min)) 1860 (if (not (re-search-forward "^@node" nil t)) 1861 (error "No `@node' line found in %s !" (buffer-name))) 1862 (beginning-of-line) 1863 1864 ;; Update other menus and nodes if requested. 1865 (if update-everything (texinfo-all-menus-update t)) 1866 1867 (beginning-of-line) 1868 (texinfo-delete-existing-pointers) 1869 (end-of-line) 1870 (insert ", " next-node-name ", " previous-node-name ", " up-node-name) 1871 1872 (beginning-of-line) 1873 (setq previous-node-name (texinfo-copy-node-name)) 1874 1875 (setq files (cdr files))) 1876 (nreverse menu-list))) 1877 1878(defun texinfo-multi-files-insert-main-menu (menu-list) 1879 "Insert formatted main menu at point. 1880Indents the first line of the description, if any, to the value of 1881`texinfo-column-for-description'." 1882 1883 (insert "@menu\n") 1884 (while menu-list 1885 ;; Every menu entry starts with a star and a space. 1886 (insert "* ") 1887 1888 ;; Insert the node name (and menu entry name, if present). 1889 (let ((node-part (car (car menu-list)))) 1890 (if (stringp node-part) 1891 ;; "Double colon" entry line; menu entry and node name are the same, 1892 (insert (format "%s::" node-part)) 1893 ;; "Single colon" entry line; menu entry and node name are different. 1894 (insert (format "%s: %s." (car node-part) (cdr node-part))))) 1895 1896 ;; Insert the description, if present. 1897 (if (cdr (car menu-list)) 1898 (progn 1899 ;; Move to right place. 1900 (indent-to texinfo-column-for-description 2) 1901 ;; Insert description. 1902 (insert (format "%s" (cdr (car menu-list)))))) 1903 1904 (insert "\n") ; end this menu entry 1905 (setq menu-list (cdr menu-list))) 1906 (insert "@end menu")) 1907 1908(defun texinfo-multi-file-master-menu-list (files-list) 1909 "Return master menu list from files in FILES-LIST. 1910Menu entries in each file collected using `texinfo-master-menu-list'. 1911 1912The first file in FILES-LIST must be the outer file; the others must 1913be the files included within it. A main menu must already exist." 1914 (save-excursion 1915 (let (master-menu-list) 1916 (while files-list 1917 (switch-to-buffer (find-file-noselect (car files-list))) 1918 (message "Working on: %s " (current-buffer)) 1919 (goto-char (point-min)) 1920 (setq master-menu-list 1921 (append master-menu-list (texinfo-master-menu-list))) 1922 (setq files-list (cdr files-list))) 1923 master-menu-list))) 1924 1925 1926;;; The multiple-file update function 1927 1928(defun texinfo-multiple-files-update 1929 (outer-file &optional update-everything make-master-menu) 1930 "Update first node pointers in each file included in OUTER-FILE; 1931create or update the `Top' level node pointers and the main menu in 1932the outer file that refers to such nodes. This does not create or 1933update menus or pointers within the included files. 1934 1935With optional MAKE-MASTER-MENU argument (prefix arg, if interactive), 1936insert a master menu in OUTER-FILE in addition to creating or updating 1937pointers in the first @node line in each included file and creating or 1938updating the `Top' level node pointers of the outer file. This does 1939not create or update other menus and pointers within the included 1940files. 1941 1942With optional UPDATE-EVERYTHING argument (numeric prefix arg, if 1943interactive), update all the menus and all the `Next', `Previous', and 1944`Up' pointers of all the files included in OUTER-FILE before inserting 1945a master menu in OUTER-FILE. Also, update the `Top' level node 1946pointers of OUTER-FILE. 1947 1948Notes: 1949 1950 * this command does NOT save any files--you must save the 1951 outer file and any modified, included files. 1952 1953 * except for the `Top' node, this command does NOT handle any 1954 pre-existing nodes in the outer file; hence, indices must be 1955 enclosed in an included file. 1956 1957Requirements: 1958 1959 * each of the included files must contain exactly one highest 1960 hierarchical level node, 1961 * this highest node must be the first node in the included file, 1962 * each highest hierarchical level node must be of the same type. 1963 1964Thus, normally, each included file contains one, and only one, 1965chapter." 1966 1967 (interactive (cons 1968 (read-string 1969 "Name of outer `include' file: " 1970 (buffer-file-name)) 1971 (cond ((not current-prefix-arg) 1972 '(nil nil)) 1973 ((listp current-prefix-arg) 1974 '(t nil)) ; make-master-menu 1975 ((numberp current-prefix-arg) 1976 '(t t)) ; update-everything 1977 ))) 1978 1979 (let* ((included-file-list (texinfo-multi-file-included-list outer-file)) 1980 (files included-file-list) 1981 main-menu-list 1982 next-node-name 1983 previous-node-name 1984 (up-node-name "Top")) 1985 1986;;; Update the pointers 1987;;; and collect the names of the nodes and titles 1988 (setq main-menu-list (texinfo-multi-file-update files update-everything)) 1989 1990;;; Insert main menu 1991 1992 ;; Go to outer file 1993 (switch-to-buffer (find-file-noselect (car included-file-list))) 1994 (if (texinfo-old-menu-p 1995 (point-min) 1996 (save-excursion 1997 (re-search-forward "^@include") 1998 (beginning-of-line) 1999 (point))) 2000 2001 ;; If found, leave point after word `menu' on the `@menu' line. 2002 (progn 2003 (texinfo-incorporate-descriptions main-menu-list) 2004 ;; Delete existing menu. 2005 (beginning-of-line) 2006 (delete-region 2007 (point) 2008 (save-excursion (re-search-forward "^@end menu") (point))) 2009 ;; Insert main menu 2010 (texinfo-multi-files-insert-main-menu main-menu-list)) 2011 2012 ;; Else no current menu; insert it before `@include' 2013 (texinfo-multi-files-insert-main-menu main-menu-list)) 2014 2015;;; Insert master menu 2016 2017 (if make-master-menu 2018 (progn 2019 ;; First, removing detailed part of any pre-existing master menu 2020 (goto-char (point-min)) 2021 (if (search-forward texinfo-master-menu-header nil t) 2022 (progn 2023 (goto-char (match-beginning 0)) 2024 ;; Check if @detailmenu kludge is used; 2025 ;; if so, leave point before @detailmenu. 2026 (search-backward "\n@detailmenu" 2027 (save-excursion (forward-line -3) (point)) 2028 t) 2029 ;; Remove detailed master menu listing 2030 (let ((end-of-detailed-menu-descriptions 2031 (save-excursion ; beginning of end menu line 2032 (goto-char (texinfo-menu-end)) 2033 (beginning-of-line) (forward-char -1) 2034 (point)))) 2035 (delete-region (point) end-of-detailed-menu-descriptions)))) 2036 2037 ;; Create a master menu and insert it 2038 (texinfo-insert-master-menu-list 2039 (texinfo-multi-file-master-menu-list 2040 included-file-list))))) 2041 2042 ;; Remove unwanted extra lines. 2043 (save-excursion 2044 (goto-char (point-min)) 2045 2046 (re-search-forward "^@menu") 2047 (forward-line -1) 2048 (insert "\n") ; Ensure at least one blank line. 2049 (delete-blank-lines) 2050 2051 (re-search-forward "^@end menu") 2052 (forward-line 1) 2053 (insert "\n") ; Ensure at least one blank line. 2054 (delete-blank-lines)) 2055 2056 (message "Multiple files updated.")) 2057 2058 2059;;; Place `provide' at end of file. 2060(provide 'texnfo-upd) 2061 2062;;; texnfo-upd.el ends here 2063