comparison lisp/textmodes/texnfo-upd.el @ 4028:3831300d2ecb

Fix typo re `texinfo-sequential-node-update.' Ensure that no commands depend on the value of case-fold-search. Rewrite messages. Avoid using `mark-whole-buffer'. (texinfo-start-menu-description): New function to insert title as description in a menu. (texinfo-make-menu-list): Remove automatic title insertion. (texinfo-master-menu): Error message if file contains too few nodes for a master menu. Handle the case where no master menu was inserted. (texinfo-insert-master-menu-list): Only attempt to insert detailed master menu if there is one. Insert a master menu only after `Top' node and before next node. (texinfo-check-for-node-name): Offer section title as prompt. (texinfo-copy-next-section-title): Copy title correctly. Handle failure to find @node. (texinfo-copy-menu): Error message if menu empty. (texinfo-pointer-name): Find only those section commands that are accompanied by `@node' lines. (texinfo-section-types-regexp): Look for subh and subs, not just sub. (texinfo-make-one-menu): Copy node-name correctly for message. (texinfo-copy-menu-title): Copy title as it should rather than node line. (texinfo-find-higher-level-node): Stop search at limit. Special handling for `top' and `chapter' levels. (texinfo-copy-menu-title): Rewrite to handle outer include files. (texinfo-multi-file-update): Update all nodes properly (and sooner); rewrite doc string and interactive. Copy title properly. (texinfo-all-menus-update): Fixed typo that caused the function to create a master menu when it shouldn't. Update pre-existing master menu, if there is one. (texinfo-incorporate-descriptions): Use a regexp search to look for both kinds of menu item. (texinfo-menu-indent-description): Likewise. (texinfo-incorporate-menu-entry-names): New function. (texinfo-insert-menu): Handle both kinds of menu item. (texinfo-multi-files-insert-main-menu): Likewise. (texinfo-update-node): Pass t as second arg to push-mark. (texinfo-sequential-node-update): Likewise. (texinfo-insert-node-lines): Bind `title' at a higher level. Don't find previous @node if it's close. Take region to process as arguments. (texinfo-multiple-files-update): Handle prefix arg better within `interactive'. Canonicalize the blank lines.
author Richard M. Stallman <rms@gnu.org>
date Wed, 07 Jul 1993 22:15:20 +0000
parents 507f64624555
children 8bf916902edc
comparison
equal deleted inserted replaced
4027:afa1ecd408e1 4028:3831300d2ecb
1 ;;; texnfo-upd.el --- a utility for updating nodes and menus in Texinfo files. 1 ;;; Texinfo mode utilities for updating nodes and menus in Texinfo files.
2 2 ;;; Copyright 1989, 1990, 1991, 1992 Free Software Foundation
3 ;;;; Copyright 1989, 1990, 1992 Free Software Foundation 3
4 4 ;; Author: Robert J. Chassell
5 ;; Author: Bob Chassell <bob@gnu.ai.mit.edu> 5 ;; Maintainer: bug-texinfo@prep.ai.mit.edu
6 ;; Version: 2.00
7 ;; Keywords: maint, tex, docs 6 ;; Keywords: maint, tex, docs
8 7
9 ;; This file is part of GNU Emacs. 8 ;; This file is part of GNU Emacs.
10 9
11 ;; GNU Emacs is free software; you can redistribute it and/or modify 10 ;; GNU Emacs is free software; you can redistribute it and/or modify
21 ;; You should have received a copy of the GNU General Public License 20 ;; 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 21 ;; along with GNU Emacs; see the file COPYING. If not, write to
23 ;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 22 ;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
24 23
25 ;;; Commentary: 24 ;;; Commentary:
26 25
27 ;;;; Summary 26 ;;; Known bug: update commands fail to ignore @ignore.
28 27
29 ; (Much of the following commentary ought eventually be incorporated 28 ;;; Summary: how to use the updating commands
30 ; into the Texinfo Manual.)
31 29
32 ; The node and menu updating functions automatically 30 ; The node and menu updating functions automatically
33 31
34 ; * insert missing `@node' lines, 32 ; * insert missing `@node' lines,
35 ; * insert the `Next', `Previous' and `Up' pointers of a node, 33 ; * insert the `Next', `Previous' and `Up' pointers of a node,
36 ; * insert or update the menu for a section, 34 ; * insert or update the menu for a section,
37 ; * create a master menu for a Texinfo source file. 35 ; * create a master menu for a Texinfo source file.
38 36 ;
39 ; Passed an argument, the `texinfo-update-node' and 37 ; Passed an argument, the `texinfo-update-node' and
40 ; `texinfo-make-menu' functions do their jobs in the region. 38 ; `texinfo-make-menu' functions do their jobs in the region.
41 39 ;
42 ; These functions replace doing these jobs by hand.
43 ; You may find them helpful.
44
45 ; In brief, the functions for creating or updating nodes and menus, are: 40 ; In brief, the functions for creating or updating nodes and menus, are:
46 ; 41 ;
47 ; texinfo-update-node (&optional region-p) 42 ; texinfo-update-node (&optional region-p)
48 ; texinfo-every-node-update () 43 ; texinfo-every-node-update ()
49 ; texinfo-sequential-node-update (&optional region-p) 44 ; texinfo-sequential-node-update (&optional region-p)
79 74
80 ; If the file has a `top' node, it must be called `top' or `Top' and 75 ; If the file has a `top' node, it must be called `top' or `Top' and
81 ; be the first node in the file. 76 ; be the first node in the file.
82 77
83 78
84 ;;;; The updating functions in detail 79 ;;; The update node functions described in detail
85 ; --------------------------------
86 80
87 ; The `texinfo-update-node' function without an argument inserts 81 ; The `texinfo-update-node' function without an argument inserts
88 ; the correct next, previous and up pointers for the node in which 82 ; the correct next, previous and up pointers for the node in which
89 ; point is located (i.e., for the node preceding point). 83 ; point is located (i.e., for the node preceding point).
90 84
96 ; `Next', `Previous', or `Up' pointers in it. They are removed. 90 ; `Next', `Previous', or `Up' pointers in it. They are removed.
97 91
98 ; The `texinfo-every-node-update' function runs `texinfo-update-node' 92 ; The `texinfo-every-node-update' function runs `texinfo-update-node'
99 ; on the whole buffer. 93 ; on the whole buffer.
100 94
101 ; The `texinfo-update-node' function inserts the immediately following 95 ; The `texinfo-sequential-node-update' function inserts the
102 ; and preceding node into the `Next' or `Previous' pointers regardless 96 ; immediately following and preceding node into the `Next' or
103 ; of their hierarchical level. This is only useful for certain kinds 97 ; `Previous' pointers regardless of their hierarchical level. This is
104 ; of text, like a novel, which you go through sequentially. 98 ; only useful for certain kinds of text, like a novel, which you go
99 ; through sequentially.
100
101
102 ;;; The menu making functions described in detail
105 103
106 ; The `texinfo-make-menu' function without an argument creates or 104 ; The `texinfo-make-menu' function without an argument creates or
107 ; updates a menu for the section encompassing the node that follows 105 ; updates a menu for the section encompassing the node that follows
108 ; point. With an argument, it makes or updates menus for the nodes 106 ; point. With an argument, it makes or updates menus for the nodes
109 ; within or part of the marked region. 107 ; within or part of the marked region.
144 ; as node names in pre-existing `@node' lines that lack names. 142 ; as node names in pre-existing `@node' lines that lack names.
145 ; 143 ;
146 ; Since node names should be more concise than section or chapter 144 ; Since node names should be more concise than section or chapter
147 ; titles, node names so inserted will need to be edited manually. 145 ; titles, node names so inserted will need to be edited manually.
148 146
147
149 ;;; Code: 148 ;;; Code:
150 149
151 ;;;; Menu Making Functions 150 ;;; The menu making functions
152 151
153 (defun texinfo-make-menu (&optional region-p) 152 (defun texinfo-make-menu (&optional region-p)
154 "Without any prefix argument, make or update a menu. 153 "Without any prefix argument, make or update a menu.
155 Make the menu for the section enclosing the node found following point. 154 Make the menu for the section enclosing the node found following point.
156 155
166 (if (not region-p) 165 (if (not region-p)
167 (let ((level (texinfo-hierarchic-level))) 166 (let ((level (texinfo-hierarchic-level)))
168 (texinfo-make-one-menu level) 167 (texinfo-make-one-menu level)
169 (message "Done...updated the menu. You may save the buffer.")) 168 (message "Done...updated the menu. You may save the buffer."))
170 ;; else 169 ;; else
171 (message "Making or updating menus... ") 170 (message "Making or updating menus in %s... " (buffer-name))
172 (let ((beginning (region-beginning)) 171 (let ((beginning (region-beginning))
173 (region-end (region-end)) 172 (region-end (region-end))
174 (level (progn ; find section type following point 173 (level (progn ; find section type following point
175 (goto-char (region-beginning)) 174 (goto-char (region-beginning))
176 (texinfo-hierarchic-level)))) 175 (texinfo-hierarchic-level))))
205 (point))) 204 (point)))
206 (end (texinfo-update-menu-region-end level)) 205 (end (texinfo-update-menu-region-end level))
207 (first (texinfo-menu-first-node beginning end)) 206 (first (texinfo-menu-first-node beginning end))
208 (node-name (progn 207 (node-name (progn
209 (goto-char beginning) 208 (goto-char beginning)
209 (beginning-of-line)
210 (texinfo-copy-node-name))) 210 (texinfo-copy-node-name)))
211 (new-menu-list (texinfo-make-menu-list beginning end level))) 211 (new-menu-list (texinfo-make-menu-list beginning end level)))
212 (if (texinfo-old-menu-p beginning first) 212 (if (texinfo-old-menu-p beginning first)
213 (progn 213 (progn
214 (texinfo-incorporate-descriptions new-menu-list) 214 (texinfo-incorporate-descriptions new-menu-list)
215 (texinfo-incorporate-menu-entry-names new-menu-list)
215 (texinfo-delete-old-menu beginning first))) 216 (texinfo-delete-old-menu beginning first)))
216 (texinfo-insert-menu new-menu-list node-name))) 217 (texinfo-insert-menu new-menu-list node-name)))
217 218
218 (defun texinfo-all-menus-update (&optional update-all-nodes-p) 219 (defun texinfo-all-menus-update (&optional update-all-nodes-p)
219 "Update every regular menu in a Texinfo file. 220 "Update every regular menu in a Texinfo file.
220 You must remove the detailed part of a pre-existing master menu before 221 Update pre-existing master menu, if there is one.
221 running this command, lest it be partly duplicated.
222 222
223 If called with a non-nil argument, this function first updates all the 223 If called with a non-nil argument, this function first updates all the
224 nodes in the buffer before updating the menus." 224 nodes in the buffer before updating the menus."
225 (interactive "P") 225 (interactive "P")
226 (save-excursion 226 (let ((case-fold-search t)
227 (mark-whole-buffer) 227 master-menu-p)
228 (message "Checking for a master menu... ")
229 (save-excursion 228 (save-excursion
230 (if (re-search-forward texinfo-master-menu-header nil t) 229 (push-mark (point-max) t)
231 (error 230 (goto-char (point-min))
232 "Please remove existing master menu, lest it be partly duplicated!"))) 231 (message "Checking for a master menu in %s ... "(buffer-name))
233 232 (save-excursion
234 (if update-all-nodes-p 233 (if (re-search-forward texinfo-master-menu-header nil t)
235 (progn 234 ;; Remove detailed master menu listing
236 (message "First updating all nodes... ") 235 (progn
237 (sleep-for 2) 236 (setq master-menu-p t)
238 (mark-whole-buffer) 237 (goto-char (match-beginning 0))
239 (texinfo-update-node t))) 238 (let ((end-of-detailed-menu-descriptions
240 239 (save-excursion ; beginning of end menu line
241 (message "Updating all menus... ") 240 (goto-char (texinfo-menu-end))
242 (sleep-for 2) 241 (beginning-of-line) (forward-char -1)
243 (texinfo-make-menu t) 242 (point))))
243 (delete-region (point) end-of-detailed-menu-descriptions)))))
244
245 (if update-all-nodes-p
246 (progn
247 (message "Updating all nodes in %s ... " (buffer-name))
248 (sleep-for 2)
249 (push-mark (point-max) t)
250 (goto-char (point-min))
251 (texinfo-update-node t)))
252
253 (message "Updating all menus in %s ... " (buffer-name))
254 (sleep-for 2)
255 (push-mark (point-max) t)
256 (goto-char (point-min))
257 (texinfo-make-menu t)
258
259 (if master-menu-p
260 (progn
261 (message "Updating the master menu in %s... " (buffer-name))
262 (sleep-for 2)
263 (texinfo-master-menu nil))))
264
244 (message "Done...updated all the menus. You may save the buffer."))) 265 (message "Done...updated all the menus. You may save the buffer.")))
245 266
246 (defun texinfo-find-lower-level-node (level region-end) 267 (defun texinfo-find-lower-level-node (level region-end)
247 "Search forward from point for node at any level lower than LEVEL. 268 "Search forward from point for node at any level lower than LEVEL.
248 Search is limited to the end of the marked region, REGION-END, 269 Search is limited to the end of the marked region, REGION-END,
249 and to the end of the menu region for the level. 270 and to the end of the menu region for the level.
250 271
251 Return t if the node is found, else nil. Leave point at the beginning 272 Return t if the node is found, else nil. Leave point at the beginning
252 of the node if one is found; else do not move point." 273 of the node if one is found; else do not move point."
253 274 (let ((case-fold-search t))
254 (if (and (< (point) region-end) 275 (if (and (< (point) region-end)
255 (re-search-forward 276 (re-search-forward
256 (concat 277 (concat
257 "\\(^@node\\).*\n" ; match node line 278 "\\(^@node\\).*\n" ; match node line
258 "\\(\\(\\(^@c\\).*\n\\)" ; match comment line, if any 279 "\\(\\(\\(^@c\\).*\n\\)" ; match comment line, if any
259 "\\|" ; or 280 "\\|" ; or
260 "\\(^@ifinfo[ ]*\n\\)\\)?" ; ifinfo line, if any 281 "\\(^@ifinfo[ ]*\n\\)\\)?" ; ifinfo line, if any
261 (eval (cdr (assoc level texinfo-update-menu-lower-regexps)))) 282 (eval (cdr (assoc level texinfo-update-menu-lower-regexps))))
262 ;; the next higher level node marks the end of this 283 ;; the next higher level node marks the end of this
263 ;; section, and no lower level node will be found beyond 284 ;; section, and no lower level node will be found beyond
264 ;; this position even if region-end is farther off 285 ;; this position even if region-end is farther off
265 (texinfo-update-menu-region-end level) 286 (texinfo-update-menu-region-end level)
266 t)) 287 t))
267 (goto-char (match-beginning 1)))) 288 (goto-char (match-beginning 1)))))
268 289
269 (defun texinfo-find-higher-level-node (level region-end) 290 (defun texinfo-find-higher-level-node (level region-end)
270 "Search forward from point for node at any higher level than argument LEVEL. 291 "Search forward from point for node at any higher level than argument LEVEL.
271 Search is limited to the end of the marked region, REGION-END. 292 Search is limited to the end of the marked region, REGION-END.
272 293
273 Return t if the node is found, else nil. Leave point at the beginning 294 Return t if the node is found, else nil. Leave point at the beginning
274 of the node if one is found; else do not move point." 295 of the node if one is found; else do not move point."
275 296 (let ((case-fold-search t))
276 (if (and (< (point) region-end) 297 (cond
277 (re-search-forward 298 ((or (string-equal "top" level) (string-equal "chapter" level))
278 (concat 299 (if (re-search-forward "^@node [ \t]*top[ \t]*\\(,\\|$\\)" region-end t)
279 "\\(^@node\\).*\n" ; match node line 300 (progn (beginning-of-line) t)))
280 "\\(\\(\\(^@c\\).*\n\\)" ; match comment line, if any 301 (t
281 "\\|" ; or 302 (if (re-search-forward
282 "\\(^@ifinfo[ ]*\n\\)\\)?" ; ifinfo line, if any 303 (concat
283 (eval ; (won't ever find a `top' node) 304 "\\(^@node\\).*\n" ; match node line
284 (cdr (assoc level texinfo-update-menu-higher-regexps)))) 305 "\\(\\(\\(^@c\\).*\n\\)" ; match comment line, if any
285 nil 306 "\\|" ; or
286 t)) 307 "\\(^@ifinfo[ ]*\n\\)\\)?" ; ifinfo line, if any
287 (goto-char (match-beginning 1)))) 308 (eval (cdr (assoc level texinfo-update-menu-higher-regexps))))
309 region-end t)
310 (progn (beginning-of-line) t))))))
288 311
289 312
290 ;;;; Making the list of new menu entries 313 ;;; Making the list of new menu entries
291 314
292 (defun texinfo-make-menu-list (beginning end level) 315 (defun texinfo-make-menu-list (beginning end level)
293 "Make a list of node names and their descriptions. 316 "Make a list of node names and their descriptions.
294 Point is left at the end of the menu region, but the menu is not inserted. 317 Point is left at the end of the menu region, but the menu is not inserted.
295 318
304 (let (new-menu-list) 327 (let (new-menu-list)
305 (while (texinfo-menu-locate-entry-p level end) 328 (while (texinfo-menu-locate-entry-p level end)
306 (setq new-menu-list 329 (setq new-menu-list
307 (cons (cons 330 (cons (cons
308 (texinfo-copy-node-name) 331 (texinfo-copy-node-name)
309 (texinfo-copy-section-title)) 332 (prog1 "" (forward-line 1)))
333 ;; Use following to insert section titles automatically.
334 ;; (texinfo-copy-section-title))
310 new-menu-list))) 335 new-menu-list)))
311 (reverse new-menu-list))) 336 (reverse new-menu-list)))
312 337
313 (defun texinfo-menu-locate-entry-p (level search-end) 338 (defun texinfo-menu-locate-entry-p (level search-end)
314 "Find a node that will be part of menu for this section. 339 "Find a node that will be part of menu for this section.
315 First argument is a string such as \"section\" specifying the general 340 First argument is a string such as \"section\" specifying the general
316 hierarchical level of the menu; second argument is a postion 341 hierarchical level of the menu; second argument is a position
317 specifying the end of the search. 342 specifying the end of the search.
318 343
319 The function returns t if the node is found, else nil. It searches 344 The function returns t if the node is found, else nil. It searches
320 forward from point, and leaves point at the beginning of the node. 345 forward from point, and leaves point at the beginning of the node.
321 346
322 The function finds entries of the same type. Thus `subsections' and 347 The function finds entries of the same type. Thus `subsections' and
323 `unnumberedsubsecs' will appear in the same menu." 348 `unnumberedsubsecs' will appear in the same menu."
324 (if (re-search-forward 349 (let ((case-fold-search t))
325 (concat 350 (if (re-search-forward
326 "\\(^@node\\).*\n" ; match node line 351 (concat
327 "\\(\\(\\(^@c\\).*\n\\)" ; match comment line, if any 352 "\\(^@node\\).*\n" ; match node line
328 "\\|" ; or 353 "\\(\\(\\(^@c\\).*\n\\)" ; match comment line, if any
329 "\\(^@ifinfo[ ]*\n\\)\\)?" ; ifinfo line, if any 354 "\\|" ; or
330 (eval 355 "\\(^@ifinfo[ ]*\n\\)\\)?" ; ifinfo line, if any
331 (cdr (assoc level texinfo-update-menu-same-level-regexps)))) 356 (eval
332 search-end 357 (cdr (assoc level texinfo-update-menu-same-level-regexps))))
333 t) 358 search-end
334 (goto-char (match-beginning 1)))) 359 t)
360 (goto-char (match-beginning 1)))))
335 361
336 (defun texinfo-copy-node-name () 362 (defun texinfo-copy-node-name ()
337 "Return the node name as a string. 363 "Return the node name as a string.
338 364
339 Start with point at the beginning of the node line; copy the text 365 Start with point at the beginning of the node line; copy the text
372 (skip-chars-forward " \t") ; and over spaces 398 (skip-chars-forward " \t") ; and over spaces
373 (point)) 399 (point))
374 (progn (end-of-line) (point)))) 400 (progn (end-of-line) (point))))
375 401
376 402
377 ;;;; Handling the old menu 403 ;;; Handling the old menu
378 404
379 (defun texinfo-old-menu-p (beginning first) 405 (defun texinfo-old-menu-p (beginning first)
380 "Move point to the beginning of the menu for this section, if any. 406 "Move point to the beginning of the menu for this section, if any.
381 Otherwise move point to the end of the first node of this section. 407 Otherwise move point to the end of the first node of this section.
382 Return t if a menu is found, nil otherwise. 408 Return t if a menu is found, nil otherwise.
395 (defun texinfo-incorporate-descriptions (new-menu-list) 421 (defun texinfo-incorporate-descriptions (new-menu-list)
396 "Copy the old menu line descriptions that exist to the new menu. 422 "Copy the old menu line descriptions that exist to the new menu.
397 423
398 Point must be at beginning of old menu. 424 Point must be at beginning of old menu.
399 425
400 If the node-name of the new menu entry cannot be found in the old 426 If the node-name of the new menu is found in the old menu, insert the
401 menu, use the new section title for the description, but if the 427 old description into the new entry.
402 node-name of the new menu is found in the old menu, replace the
403 section title with the old description, whatever it may be.
404 428
405 For this function, the new menu is a list made up of lists of dotted 429 For this function, the new menu is a list made up of lists of dotted
406 pairs in which the first element of the pair is the node name and the 430 pairs in which the first element of the pair is the node name and the
407 second element the description. The new menu is changed destructively. 431 second element the description. The new menu is changed destructively.
408 The old menu is the menu as it appears in the texinfo file." 432 The old menu is the menu as it appears in the texinfo file."
409 433
410 (let ((new-menu-list-pointer new-menu-list) 434 (let ((new-menu-list-pointer new-menu-list)
411 (end-of-menu (texinfo-menu-end))) 435 (end-of-menu (texinfo-menu-end)))
412 (while new-menu-list 436 (while new-menu-list
413 (save-excursion ; keep point at beginning of menu 437 (save-excursion ; keep point at beginning of menu
414 (if (search-forward 438 (if (re-search-forward
415 (concat "\* " ; so only menu entries are found 439 ;; Existing nodes can have the form
416 (car (car new-menu-list)) 440 ;; * NODE NAME:: DESCRIPTION
417 ":") ; so only complete entries are found 441 ;; or
442 ;; * MENU ITEM: NODE NAME. DESCRIPTION.
443 ;;
444 ;; Recognize both when looking for the description.
445 (concat "\\* \\(" ; so only menu entries are found
446 (car (car new-menu-list)) "::"
447 "\\|"
448 ".*: " (car (car new-menu-list)) "[.,\t\n]"
449 "\\)"
450 ) ; so only complete entries are found
418 end-of-menu 451 end-of-menu
419 t) 452 t)
420 (setcdr (car new-menu-list) 453 (setcdr (car new-menu-list)
421 (texinfo-menu-copy-old-description end-of-menu)))) 454 (texinfo-menu-copy-old-description end-of-menu))))
422 (setq new-menu-list (cdr new-menu-list))) 455 (setq new-menu-list (cdr new-menu-list)))
456 (setq new-menu-list new-menu-list-pointer)))
457
458 (defun texinfo-incorporate-menu-entry-names (new-menu-list)
459 "Copy any old menu entry names to the new menu.
460
461 Point must be at beginning of old menu.
462
463 If the node-name of the new menu entry cannot be found in the old
464 menu, do nothing.
465
466 For this function, the new menu is a list made up of lists of dotted
467 pairs in which the first element of the pair is the node name and the
468 second element is the description (or nil).
469
470 If we find an existing menu entry name, we change the first element of
471 the pair to be another dotted pair in which the car is the menu entry
472 name and the cdr is the node name.
473
474 NEW-MENU-LIST is changed destructively. The old menu is the menu as it
475 appears in the texinfo file."
476
477 (let ((new-menu-list-pointer new-menu-list)
478 (end-of-menu (texinfo-menu-end)))
479 (while new-menu-list
480 (save-excursion ; keep point at beginning of menu
481 (if (re-search-forward
482 ;; Existing nodes can have the form
483 ;; * NODE NAME:: DESCRIPTION
484 ;; or
485 ;; * MENU ITEM: NODE NAME. DESCRIPTION.
486 ;;
487 ;; We're interested in the second case.
488 (concat "\\* " ; so only menu entries are found
489 "\\(.*\\): " (car (car new-menu-list)) "[.,\t\n]")
490 end-of-menu
491 t)
492 (setcar
493 (car new-menu-list) ; replace the node name
494 (cons (buffer-substring (match-beginning 1) (match-end 1))
495 (car (car new-menu-list)))))
496 (setq new-menu-list (cdr new-menu-list))))
423 (setq new-menu-list new-menu-list-pointer))) 497 (setq new-menu-list new-menu-list-pointer)))
424 498
425 (defun texinfo-menu-copy-old-description (end-of-menu) 499 (defun texinfo-menu-copy-old-description (end-of-menu)
426 "Return description field of old menu line as string. 500 "Return description field of old menu line as string.
427 Point must be located just after the node name. Point left before description. 501 Point must be located just after the node name. Point left before description.
428 Single argument, END-OF-MENU, is position limiting search." 502 Single argument, END-OF-MENU, is position limiting search."
429 (skip-chars-forward "[:.,\t\n ]+") 503 (skip-chars-forward "[:.,\t\n ]+")
430 ;; don't copy a carriage return at line beginning with asterisk! 504 ;; don't copy a carriage return at line beginning with asterisk!
431 ;; do copy a description that begins with an `@'! 505 ;; do copy a description that begins with an `@'!
506 ;; !! Known bug: does not copy descriptions starting with ^|\{?* etc.
432 (if (and (looking-at "\\(\\w+\\|@\\)") 507 (if (and (looking-at "\\(\\w+\\|@\\)")
433 (not (looking-at "\\(^\\* \\|^@end menu\\)"))) 508 (not (looking-at "\\(^\\* \\|^@end menu\\)")))
434 (buffer-substring 509 (buffer-substring
435 (point) 510 (point)
436 (save-excursion 511 (save-excursion
459 (save-excursion 534 (save-excursion
460 (re-search-forward "^@end menu" first) 535 (re-search-forward "^@end menu" first)
461 (point)))) 536 (point))))
462 537
463 538
464 ;;;; Inserting new menu 539 ;;; Inserting new menu
465 540
466 ;; try 32, but perhaps 24 is better 541 ;; try 32, but perhaps 24 is better
467 (defvar texinfo-column-for-description 32 542 (defvar texinfo-column-for-description 32
468 "*Column at which descriptions start in a Texinfo menu.") 543 "*Column at which descriptions start in a Texinfo menu.")
469 544
473 texinfo-column-for-description. 548 texinfo-column-for-description.
474 549
475 MENU-LIST has form: 550 MENU-LIST has form:
476 551
477 \(\(\"node-name1\" . \"description\"\) 552 \(\(\"node-name1\" . \"description\"\)
478 \(\"node-name\" . \"description\"\) ... \) 553 \(\"node-name2\" . \"description\"\) ... \)
479 554
480 However, there does not need to be a description field." 555 However, the description field might be nil.
556
557 Also, the node-name field might itself be a dotted pair (call it P) of
558 strings instead of just a string. In that case, the car of P
559 is the menu entry name, and the cdr of P is the node name."
481 560
482 (insert "@menu\n") 561 (insert "@menu\n")
483 (while menu-list 562 (while menu-list
484 (if (cdr (car menu-list)) ; menu-list has description entry 563 ;; Every menu entry starts with a star and a space.
564 (insert "* ")
565
566 ;; Insert the node name (and menu entry name, if present).
567 (let ((node-part (car (car menu-list))))
568 (if (stringp node-part)
569 ;; "Double colon" entry line; menu entry and node name are the same,
570 (insert (format "%s::" node-part))
571 ;; "Single colon" entry line; menu entry and node name are different.
572 (insert (format "%s: %s." (car node-part) (cdr node-part)))))
573
574 ;; Insert the description, if present.
575 (if (cdr (car menu-list))
485 (progn 576 (progn
486 (insert 577 ;; Move to right place.
487 (format "* %s::" (car (car menu-list)))) ; node-name entry 578 (indent-to texinfo-column-for-description 2)
488 (indent-to texinfo-column-for-description 2) 579 ;; Insert description.
489 (insert 580 (insert (format "%s" (cdr (car menu-list))))))
490 (format "%s\n" (cdr (car menu-list))))) ; description entry 581
491 ;; else menu-list lacks description entry 582 (insert "\n") ; end this menu entry
492 (insert
493 (format "* %s::\n" (car (car menu-list))))) ; node-name entry
494 (setq menu-list (cdr menu-list))) 583 (setq menu-list (cdr menu-list)))
495 (insert "@end menu") 584 (insert "@end menu")
496 (message 585 (message
497 "Updated \"%s\" level menu following node: %s ... " 586 "Updated \"%s\" level menu following node: %s ... " level node-name))
498 level node-name))
499 587
500 588
501 ;;;; Handling description indentation 589 ;;; Starting menu descriptions by inserting titles
590
591 (defun texinfo-start-menu-description ()
592 "In this menu entry, insert the node's section title as a description.
593 Position point at beginning of description ready for editing.
594 Do not insert a title if the line contains an existing description.
595
596 You will need to edit the inserted text since a useful description
597 complements the node name rather than repeats it as a title does."
598
599 (interactive)
600 (let (beginning end node-name title)
601 (save-excursion
602 (beginning-of-line)
603 (if (search-forward "* " (save-excursion (end-of-line) (point)) t)
604 (progn (skip-chars-forward " \t")
605 (setq beginning (point)))
606 (error "This is not a line in a menu!"))
607
608 (cond
609 ;; "Double colon" entry line; menu entry and node name are the same,
610 ((search-forward "::" (save-excursion (end-of-line) (point)) t)
611 (if (looking-at "[ \t]*[^ \t\n]+")
612 (error "Descriptive text already exists."))
613 (skip-chars-backward ": \t")
614 (setq node-name (buffer-substring beginning (point))))
615
616 ;; "Single colon" entry line; menu entry and node name are different.
617 ((search-forward ":" (save-excursion (end-of-line) (point)) t)
618 (skip-chars-forward " \t")
619 (setq beginning (point))
620 ;; Menu entry line ends in a period, comma, or tab.
621 (if (re-search-forward "[.,\t]"
622 (save-excursion (forward-line 1) (point)) t)
623 (progn
624 (if (looking-at "[ \t]*[^ \t\n]+")
625 (error "Descriptive text already exists."))
626 (skip-chars-backward "., \t")
627 (setq node-name (buffer-substring beginning (point))))
628 ;; Menu entry line ends in a return.
629 (re-search-forward ".*\n"
630 (save-excursion (forward-line 1) (point)) t)
631 (skip-chars-backward " \t\n")
632 (setq node-name (buffer-substring beginning (point)))
633 (if (= 0 (length node-name))
634 (error "No node name on this line.")
635 (insert "."))))
636 (t (error "No node name on this line.")))
637 ;; Search for node that matches node name, and copy the section title.
638 (if (re-search-forward
639 (concat
640 "^@node[ \t]+"
641 node-name
642 ".*\n" ; match node line
643 "\\("
644 "\\(\\(^@c \\|^@comment\\).*\n\\)" ; match comment line, if any
645 "\\|" ; or
646 "\\(^@ifinfo[ ]*\n\\)" ; ifinfo line, if any
647 "\\)?")
648 nil t)
649 (progn
650 (setq title
651 (buffer-substring
652 ;; skip over section type
653 (progn (forward-word 1)
654 ;; and over spaces
655 (skip-chars-forward " \t")
656 (point))
657 (progn (end-of-line)
658 (skip-chars-backward " \t")
659 (point)))))
660 (error "Cannot find node to match node name in menu entry.")))
661 ;; Return point to the menu and insert the title.
662 (end-of-line)
663 (delete-region
664 (point)
665 (save-excursion (skip-chars-backward " \t") (point)))
666 (indent-to texinfo-column-for-description 2)
667 (save-excursion (insert title))))
668
669
670 ;;; Handling description indentation
502 671
503 ; Since the make-menu functions indent descriptions, these functions 672 ; Since the make-menu functions indent descriptions, these functions
504 ; are useful primarily for indenting a single menu specially. 673 ; are useful primarily for indenting a single menu specially.
505 674
506 (defun texinfo-indent-menu-description (column &optional region-p) 675 (defun texinfo-indent-menu-description (column &optional region-p)
538 (while (< beginning-of-next-line 707 (while (< beginning-of-next-line
539 (save-excursion ; beginning of end menu line 708 (save-excursion ; beginning of end menu line
540 (goto-char (texinfo-menu-end)) 709 (goto-char (texinfo-menu-end))
541 (beginning-of-line) 710 (beginning-of-line)
542 (point))) 711 (point)))
543 (if (search-forward "::" (texinfo-menu-end) t) 712
713 (if (re-search-forward "\\* \\(.*::\\|.*: [^.,\t\n]+[.,\t]\\)"
714 (texinfo-menu-end)
715 t)
544 (progn 716 (progn
545 (let ((beginning-white-space (point))) 717 (let ((beginning-white-space (point)))
546 (skip-chars-forward " \t") ; skip over spaces 718 (skip-chars-forward " \t") ; skip over spaces
547 (if (looking-at "\\(@\\|\\w\\)+") ; if there is text 719 (if (looking-at "\\(@\\|\\w\\)+") ; if there is text
548 (progn 720 (progn
552 ;; position point at beginning of next line 724 ;; position point at beginning of next line
553 (forward-line 1) 725 (forward-line 1)
554 (setq beginning-of-next-line (point))))) 726 (setq beginning-of-next-line (point)))))
555 727
556 728
557 ;;;; Making the master menu 729 ;;; Making the master menu
558 730
559 (defun texinfo-master-menu (update-all-nodes-menus-p) 731 (defun texinfo-master-menu (update-all-nodes-menus-p)
560 "Make a master menu for a whole Texinfo file. 732 "Make a master menu for a whole Texinfo file.
561 Non-nil argument (prefix, if interactive) means first update all 733 Non-nil argument (prefix, if interactive) means first update all
562 existing nodes and menus. Remove pre-existing master menu, if there is one. 734 existing nodes and menus. Remove pre-existing master menu, if there is one.
568 If called with a non-nil argument, this function first updates all the 740 If called with a non-nil argument, this function first updates all the
569 menus in the buffer (incorporating descriptions from pre-existing 741 menus in the buffer (incorporating descriptions from pre-existing
570 menus) before it constructs the master menu. 742 menus) before it constructs the master menu.
571 743
572 The function removes the detailed part of an already existing master 744 The function removes the detailed part of an already existing master
573 menu. This action depends on the pre-existing master menu using the 745 menu. This action depends on the pre-exisitng master menu using the
574 standard `texinfo-master-menu-header'. 746 standard `texinfo-master-menu-header'.
575 747
576 The master menu has the following format, which is adapted from the 748 The master menu has the following format, which is adapted from the
577 recommendation in the Texinfo Manual: 749 recommendation in the Texinfo Manual:
578 750
586 directly to a particular node if he or she is searching for 758 directly to a particular node if he or she is searching for
587 specific information. 759 specific information.
588 760
589 Each of the menus in the detailed node listing is introduced by the 761 Each of the menus in the detailed node listing is introduced by the
590 title of the section containing the menu." 762 title of the section containing the menu."
591 763
592 (interactive "P") 764 (interactive "P")
593 (widen) 765 (let ((case-fold-search t))
594 (goto-char (point-min)) 766 (widen)
595 767 (goto-char (point-min))
596 ;; Move point to location after `top'. 768
597 (if (not (re-search-forward "^@node [ \t]*top[ \t]*\\(,\\|$\\)" nil t)) 769 ;; Move point to location after `top'.
598 (error "This buffer needs a Top node!")) 770 (if (not (re-search-forward "^@node [ \t]*top[ \t]*\\(,\\|$\\)" nil t))
599 771 (error "This buffer needs a Top node!"))
600 (let ((first-chapter 772
601 (save-excursion (re-search-forward "^@node") (point)))) 773 (let ((first-chapter
602 (if (re-search-forward texinfo-master-menu-header first-chapter t) 774 (save-excursion
603 ;; Remove detailed master menu listing 775 (or (re-search-forward "^@node" nil t)
776 (error "Too few nodes for a master menu!"))
777 (point))))
778 (if (re-search-forward texinfo-master-menu-header first-chapter t)
779 ;; Remove detailed master menu listing
780 (progn
781 (goto-char (match-beginning 0))
782 (let ((end-of-detailed-menu-descriptions
783 (save-excursion ; beginning of end menu line
784 (goto-char (texinfo-menu-end))
785 (beginning-of-line) (forward-char -1)
786 (point))))
787 (delete-region (point) end-of-detailed-menu-descriptions)))))
788
789 (if update-all-nodes-menus-p
604 (progn 790 (progn
605 (goto-char (match-beginning 0)) 791 (message "Making a master menu in %s ...first updating all nodes... "
606 (let ((end-of-detailed-menu-descriptions 792 (buffer-name))
607 (save-excursion ; beginning of end menu line 793 (sleep-for 2)
608 (goto-char (texinfo-menu-end)) 794 (push-mark (point-max) t)
609 (beginning-of-line) (forward-char -1) 795 (goto-char (point-min))
610 (point)))) 796 (texinfo-update-node t)
611 (delete-region (point) end-of-detailed-menu-descriptions))))) 797
612 798 (message "Updating all menus in %s ... " (buffer-name))
613 (if update-all-nodes-menus-p 799 (sleep-for 2)
614 (progn 800 (push-mark (point-max) t)
615 (message "Making a master menu...first updating all nodes... ") 801 (goto-char (point-min))
616 (sleep-for 2) 802 (texinfo-make-menu t)))
617 (mark-whole-buffer) 803
618 (texinfo-update-node t) 804 (message "Now making the master menu in %s... " (buffer-name))
619 805 (sleep-for 2)
620 (message "Updating all menus... ")
621 (sleep-for 2)
622 (mark-whole-buffer)
623 (texinfo-make-menu t)))
624
625 (message "Now making the master menu... ")
626 (sleep-for 2)
627 (goto-char (point-min))
628 (texinfo-insert-master-menu-list
629 (texinfo-master-menu-list))
630
631 ;; Remove extra newlines that texinfo-insert-master-menu-list
632 ;; may have inserted.
633
634 (save-excursion
635 (goto-char (point-min)) 806 (goto-char (point-min))
636 807 (texinfo-insert-master-menu-list
637 (re-search-forward texinfo-master-menu-header) 808 (texinfo-master-menu-list))
638 (goto-char (match-beginning 0)) 809
639 (insert "\n") 810 ;; Remove extra newlines that texinfo-insert-master-menu-list
640 (delete-blank-lines) 811 ;; may have inserted.
641 812
642 (re-search-backward "^@menu") 813 (save-excursion
643 (forward-line -1) 814 (goto-char (point-min))
644 (delete-blank-lines) 815
645 816 (if (re-search-forward texinfo-master-menu-header nil t)
646 (re-search-forward "^@end menu") 817 (progn
647 (forward-line 1) 818 (goto-char (match-beginning 0))
648 (delete-blank-lines)) 819 (insert "\n")
649 820 (delete-blank-lines)
650 (message "Done...completed making master menu. You may save the buffer.")) 821 (goto-char (point-min))))
822
823 (re-search-forward "^@menu")
824 (forward-line -1)
825 (delete-blank-lines)
826
827 (re-search-forward "^@end menu")
828 (forward-line 1)
829 (delete-blank-lines))
830
831 (message
832 "Done...completed making master menu. You may save the buffer.")))
651 833
652 (defun texinfo-master-menu-list () 834 (defun texinfo-master-menu-list ()
653 "Return a list of menu entries and header lines for the master menu. 835 "Return a list of menu entries and header lines for the master menu.
654 836
655 Start with the menu for chapters and indices and then find each 837 Start with the menu for chapters and indices and then find each
673 (reverse master-menu-list))) 855 (reverse master-menu-list)))
674 856
675 (defun texinfo-insert-master-menu-list (master-menu-list) 857 (defun texinfo-insert-master-menu-list (master-menu-list)
676 "Format and insert the master menu in the current buffer." 858 "Format and insert the master menu in the current buffer."
677 (goto-char (point-min)) 859 (goto-char (point-min))
678 (re-search-forward "^@menu") 860 ;; Insert a master menu only after `Top' node and before next node
861 ;; \(or include file if there is no next node\).
862 (if (not (re-search-forward "^@node [ \t]*top[ \t]*\\(,\\|$\\)" nil t))
863 (error "This buffer needs a Top node!"))
864 (let ((first-chapter
865 (save-excursion (re-search-forward "^@node\\|^@include") (point))))
866 (if (not (re-search-forward "^@menu" first-chapter t))
867 (error
868 "Buffer lacks ordinary `Top' menu in which to insert master.")))
679 (beginning-of-line) 869 (beginning-of-line)
680 (delete-region (point) ; buffer must have ordinary top menu 870 (delete-region ; buffer must have ordinary top menu
681 (save-excursion 871 (point)
682 (re-search-forward "^@end menu") 872 (save-excursion (re-search-forward "^@end menu") (point)))
683 (point))) 873
684
685 (save-excursion ; leave point at beginning of menu 874 (save-excursion ; leave point at beginning of menu
686 ;; Handle top of menu 875 ;; Handle top of menu
687 (insert "\n@menu\n") 876 (insert "\n@menu\n")
688 ;; Insert chapter menu entries 877 ;; Insert chapter menu entries
689 (setq this-very-menu-list (reverse (car (car master-menu-list))))
690 ;;; Tell user what is going on.
691 (message "Inserting chapter menu entry: %s ... " this-very-menu-list)
692 (while this-very-menu-list
693 (insert "* " (car this-very-menu-list) "\n")
694 (setq this-very-menu-list (cdr this-very-menu-list)))
695
696 (setq master-menu-list (cdr master-menu-list))
697
698 (insert texinfo-master-menu-header)
699
700 ;; Now, insert all the other menus
701
702 ;; The menu master-menu-list has a form like this:
703 ;; ((("beta" "alpha") "title-A")
704 ;; (("delta" "gamma") "title-B"))
705
706 (while master-menu-list
707
708 (message
709 "Inserting menu for %s .... " (car (cdr (car master-menu-list))))
710 ;; insert title of menu section
711 (insert "\n" (car (cdr (car master-menu-list))) "\n\n")
712
713 ;; insert each menu entry
714 (setq this-very-menu-list (reverse (car (car master-menu-list)))) 878 (setq this-very-menu-list (reverse (car (car master-menu-list))))
879 ;; Tell user what is going on.
880 (message "Inserting chapter menu entry: %s ... " this-very-menu-list)
715 (while this-very-menu-list 881 (while this-very-menu-list
716 (insert "* " (car this-very-menu-list) "\n") 882 (insert "* " (car this-very-menu-list) "\n")
717 (setq this-very-menu-list (cdr this-very-menu-list))) 883 (setq this-very-menu-list (cdr this-very-menu-list)))
718 884
719 (setq master-menu-list (cdr master-menu-list))) 885 (setq master-menu-list (cdr master-menu-list))
720 886
721 ;; Finish menu 887 ;; Only insert detailed master menu if there is one....
722 (insert "@end menu\n\n"))) 888 (if (car (car master-menu-list))
889 (insert texinfo-master-menu-header))
890
891 ;; Now, insert all the other menus
892
893 ;; The menu master-menu-list has a form like this:
894 ;; ((("beta" "alpha") "title-A")
895 ;; (("delta" "gamma") "title-B"))
896
897 (while master-menu-list
898
899 (message
900 "Inserting menu for %s .... " (car (cdr (car master-menu-list))))
901 ;; insert title of menu section
902 (insert "\n" (car (cdr (car master-menu-list))) "\n\n")
903
904 ;; insert each menu entry
905 (setq this-very-menu-list (reverse (car (car master-menu-list))))
906 (while this-very-menu-list
907 (insert "* " (car this-very-menu-list) "\n")
908 (setq this-very-menu-list (cdr this-very-menu-list)))
909
910 (setq master-menu-list (cdr master-menu-list)))
911
912 ;; Finish menu
913 (insert "@end menu\n\n")))
723 914
724 (defvar texinfo-master-menu-header 915 (defvar texinfo-master-menu-header
725 "\n --- The Detailed Node Listing ---\n" 916 "\n --- The Detailed Node Listing ---\n"
726 "String inserted before lower level entries in Texinfo master menu. 917 "String inserted before lower level entries in Texinfo master menu.
727 It comes after the chapter-level menu entries.") 918 It comes after the chapter-level menu entries.")
734 925
735 (defun texinfo-copy-menu-title () 926 (defun texinfo-copy-menu-title ()
736 "Return the title of the section preceding the menu as a string. 927 "Return the title of the section preceding the menu as a string.
737 If such a title cannot be found, return an empty string. Do not move 928 If such a title cannot be found, return an empty string. Do not move
738 point." 929 point."
739 (save-excursion 930 (let ((case-fold-search t))
740 (if (re-search-backward 931 (save-excursion
741 (concat 932 (if (re-search-backward
742 "\\(^@node\\).*\n" ; match node line 933 (concat
743 "\\(\\(\\(^@c\\).*\n\\)" ; match comment line, if any 934 "\\(^@top"
744 "\\|" ; or 935 "\\|" ; or
745 "\\(^@ifinfo[ ]*\n\\)\\)?" ; ifinfo line, if any 936 texinfo-section-types-regexp ; all other section types
746 (eval 937 "\\)")
747 (cdr 938 nil
748 (assoc (texinfo-hierarchic-level) 939 t)
749 texinfo-update-menu-higher-regexps)))) 940 (progn
750 nil 941 (beginning-of-line)
751 t) 942 (forward-word 1) ; skip over section type
752 (texinfo-copy-section-title) 943 (skip-chars-forward " \t") ; and over spaces
753 " "))) 944 (buffer-substring
945 (point)
946 (progn (end-of-line) (point))))
947 ""))))
754 948
755 (defun texinfo-copy-menu () 949 (defun texinfo-copy-menu ()
756 "Return the entries of an existing menu as a list. 950 "Return the entries of an existing menu as a list.
757 Start with point just after the word `menu' in the `@menu' line 951 Start with point just after the word `menu' in the `@menu' line
758 and leave point on the line before the `@end menu' line." 952 and leave point on the line before the `@end menu' line."
759 (let* (this-menu-list 953 (let* (this-menu-list
760 (end-of-menu (texinfo-menu-end)) ; position of end of `@end menu' 954 (end-of-menu (texinfo-menu-end)) ; position of end of `@end menu'
761 (last-entry (save-excursion ; position of beginning of 955 (last-entry (save-excursion ; position of beginning of
762 ; last `* ' entry 956 ; last `* ' entry
763 (goto-char end-of-menu) 957 (goto-char end-of-menu)
764 (re-search-backward "^\* ") ; handle multi-line desc. 958 ;; handle multi-line description
959 (if (not (re-search-backward "^\* " nil t))
960 (error "No entries in menu."))
765 (point)))) 961 (point))))
766 (while (< (point) last-entry) 962 (while (< (point) last-entry)
767 (if (re-search-forward "^\* " end-of-menu t) 963 (if (re-search-forward "^\* " end-of-menu t)
768 (progn 964 (progn
769 (setq this-menu-list 965 (setq this-menu-list
776 (- (point) 3))) 972 (- (point) 3)))
777 this-menu-list))))) 973 this-menu-list)))))
778 this-menu-list)) 974 this-menu-list))
779 975
780 976
781 ;;;; Determining the hierarchical level in the texinfo file 977 ;;; Determining the hierarchical level in the texinfo file
782 978
783 (defun texinfo-specific-section-type () 979 (defun texinfo-specific-section-type ()
784 "Return the specific type of next section, as a string. 980 "Return the specific type of next section, as a string.
785 For example, \"unnumberedsubsec\". Return \"top\" for top node. 981 For example, \"unnumberedsubsec\". Return \"top\" for top node.
786 982
787 Searches forward for a section. Hence, point must be before the 983 Searches forward for a section. Hence, point must be before the
788 section whose type will be found. Does not move point. Signal an 984 section whose type will be found. Does not move point. Signal an
789 error if the node is not the top node and a section is not found." 985 error if the node is not the top node and a section is not found."
790 (save-excursion 986 (let ((case-fold-search t))
791 (cond 987 (save-excursion
792 ((re-search-forward "^@node [ \t]*top[ \t]*\\(,\\|$\\)" 988 (cond
793 (save-excursion 989 ((re-search-forward "^@node [ \t]*top[ \t]*\\(,\\|$\\)"
794 (end-of-line) 990 ;;; Following search limit by cph but causes a bug
795 (point)) 991 ;;; (save-excursion
796 t) 992 ;;; (end-of-line)
797 "top") 993 ;;; (point))
798 ((re-search-forward texinfo-section-types-regexp nil t) 994 nil
799 (buffer-substring (progn (beginning-of-line) ; copy its name 995 t)
800 (1+ (point))) 996 "top")
801 (progn (forward-word 1) 997 ((re-search-forward texinfo-section-types-regexp nil t)
802 (point)))) 998 (buffer-substring (progn (beginning-of-line) ; copy its name
803 (t 999 (1+ (point)))
804 (error 1000 (progn (forward-word 1)
805 "texinfo-specific-section-type: Chapter or section not found."))))) 1001 (point))))
1002 (t
1003 (error
1004 "texinfo-specific-section-type: Chapter or section not found."))))))
806 1005
807 (defun texinfo-hierarchic-level () 1006 (defun texinfo-hierarchic-level ()
808 "Return the general hierarchal level of the next node in a texinfo file. 1007 "Return the general hierarchal level of the next node in a texinfo file.
809 Thus, a subheading or appendixsubsec is of type subsection." 1008 Thus, a subheading or appendixsubsec is of type subsection."
810 (cdr (assoc 1009 (let ((case-fold-search t))
811 (texinfo-specific-section-type) 1010 (cdr (assoc
812 texinfo-section-to-generic-alist))) 1011 (texinfo-specific-section-type)
1012 texinfo-section-to-generic-alist))))
813 1013
814 1014
815 ;;;; Locating the major positions 1015 ;;; Locating the major positions
816 1016
817 (defun texinfo-update-menu-region-beginning (level) 1017 (defun texinfo-update-menu-region-beginning (level)
818 "Locate beginning of higher level section this section is within. 1018 "Locate beginning of higher level section this section is within.
819 Return position of the beginning of the node line; do not move point. 1019 Return position of the beginning of the node line; do not move point.
820 Thus, if this level is subsection, searches backwards for section node. 1020 Thus, if this level is subsection, searches backwards for section node.
821 Only argument is a string of the general type of section." 1021 Only argument is a string of the general type of section."
822 1022 (let ((case-fold-search t))
823 (cond 1023 ;; !! Known bug: if section immediately follows top node, this
824 ((or (string-equal "top" level) 1024 ;; returns the beginning of the buffer as the beginning of the
825 (string-equal "chapter" level)) 1025 ;; higher level section.
826 (save-excursion 1026 (cond
827 (goto-char (point-min)) 1027 ((or (string-equal "top" level)
828 (re-search-forward "^@node [ \t]*top[ \t]*\\(,\\|$\\)" nil t) 1028 (string-equal "chapter" level))
829 (beginning-of-line) 1029 (save-excursion
830 (point))) 1030 (goto-char (point-min))
831 (t 1031 (re-search-forward "^@node [ \t]*top[ \t]*\\(,\\|$\\)" nil t)
832 (save-excursion 1032 (beginning-of-line)
833 (re-search-backward 1033 (point)))
834 (concat 1034 (t
835 "\\(^@node\\).*\n" ; match node line 1035 (save-excursion
836 "\\(\\(\\(^@c\\).*\n\\)" ; match comment line, if any 1036 (re-search-backward
837 "\\|" ; or 1037 (concat
838 "\\(^@ifinfo[ ]*\n\\)\\)?" ; ifinfo line, if any 1038 "\\(^@node\\).*\n" ; match node line
839 (eval 1039 "\\(\\(\\(^@c\\).*\n\\)" ; match comment line, if any
840 (cdr (assoc level texinfo-update-menu-higher-regexps)))) 1040 "\\|" ; or
841 nil 1041 "\\(^@ifinfo[ ]*\n\\)\\)?" ; ifinfo line, if any
842 'goto-beginning) 1042 (eval
843 (point))))) 1043 (cdr (assoc level texinfo-update-menu-higher-regexps))))
1044 nil
1045 'goto-beginning)
1046 (point))))))
844 1047
845 (defun texinfo-update-menu-region-end (level) 1048 (defun texinfo-update-menu-region-end (level)
846 "Locate end of higher level section this section is within. 1049 "Locate end of higher level section this section is within.
847 Return position; do not move point. Thus, if this level is a 1050 Return position; do not move point. Thus, if this level is a
848 subsection, find the node for the section this subsection is within. 1051 subsection, find the node for the section this subsection is within.
849 If level is top or chapter, returns end of file. Only argument is a 1052 If level is top or chapter, returns end of file. Only argument is a
850 string of the general type of section." 1053 string of the general type of section."
851 1054 (let ((case-fold-search t))
852 (save-excursion 1055 (save-excursion
853 (if (re-search-forward 1056 (if (re-search-forward
854 (concat 1057 (concat
855 "\\(^@node\\).*\n" ; match node line 1058 "\\(^@node\\).*\n" ; match node line
856 "\\(\\(\\(^@c\\).*\n\\)" ; match comment line, if any 1059 "\\(\\(\\(^@c\\).*\n\\)" ; match comment line, if any
857 "\\|" ; or 1060 "\\|" ; or
858 "\\(^@ifinfo[ ]*\n\\)\\)?" ; ifinfo line, if any 1061 "\\(^@ifinfo[ ]*\n\\)\\)?" ; ifinfo line, if any
859 (eval 1062 (eval
860 (cdr (assoc level texinfo-update-menu-higher-regexps)))) 1063 ;; Never finds end of level above chapter so goes to end.
861 nil 1064 (cdr (assoc level texinfo-update-menu-higher-regexps))))
862 'goto-end) 1065 nil
863 (match-beginning 1) 1066 'goto-end)
864 (point-max)))) 1067 (match-beginning 1)
1068 (point-max)))))
865 1069
866 (defun texinfo-menu-first-node (beginning end) 1070 (defun texinfo-menu-first-node (beginning end)
867 "Locate first node of the section the menu will be placed in. 1071 "Locate first node of the section the menu will be placed in.
868 Return position; do not move point. 1072 Return position; do not move point.
869 The menu will be located just before this position. 1073 The menu will be located just before this position.
878 (re-search-forward "^@node" end t) 1082 (re-search-forward "^@node" end t)
879 (beginning-of-line) 1083 (beginning-of-line)
880 (point))) 1084 (point)))
881 1085
882 1086
883 ;;;; Alists and regular expressions for defining hierarchical levels 1087 ;;; Alists and regular expressions for defining hierarchical levels
884 1088
885 (defvar texinfo-section-to-generic-alist 1089 (defvar texinfo-section-to-generic-alist
886 '(("top" . "top") 1090 '(("top" . "top")
887 1091
888 ("chapter" . "chapter") 1092 ("chapter" . "chapter")
907 ("appendixsubsubsec" . "subsubsection")) 1111 ("appendixsubsubsec" . "subsubsection"))
908 "*An alist of specific and corresponding generic Texinfo section types. 1112 "*An alist of specific and corresponding generic Texinfo section types.
909 The keys are strings specifying specific types of section; the values 1113 The keys are strings specifying specific types of section; the values
910 are strings of their corresponding general types.") 1114 are strings of their corresponding general types.")
911 1115
1116 ;; We used to look for just sub, but that found @subtitle.
912 (defvar texinfo-section-types-regexp 1117 (defvar texinfo-section-types-regexp
913 "^@\\(chapter \\|sect\\|sub\\|unnum\\|major\\|chapheading \\|heading \\|appendix\\)" 1118 "^@\\(chapter \\|sect\\|subs\\|subh\\|unnum\\|major\\|chapheading \\|heading \\|appendix\\)"
914 "Regexp matching chapter, section, other headings (but not the top node).") 1119 "Regexp matching chapter, section, other headings (but not the top node).")
915 1120
916 (defvar texinfo-chapter-level-regexp 1121 (defvar texinfo-chapter-level-regexp
917 "chapter\\|unnumbered \\|appendix \\|majorheading\\|chapheading" 1122 "chapter\\|unnumbered \\|appendix \\|majorheading\\|chapheading"
918 "Regular expression matching just the Texinfo chapter level headings.") 1123 "Regular expression matching just the Texinfo chapter level headings.")
1008 "*Regexps for searching for lower level sections in a Texinfo file. 1213 "*Regexps for searching for lower level sections in a Texinfo file.
1009 The keys are strings specifying the general hierarchical level in the 1214 The keys are strings specifying the general hierarchical level in the
1010 document; the values are regular expressions.") 1215 document; the values are regular expressions.")
1011 1216
1012 1217
1013 ;;;; Updating a Node 1218 ;;; Updating a node
1014 1219
1015 (defun texinfo-update-node (&optional region-p) 1220 (defun texinfo-update-node (&optional region-p)
1016 "Without any prefix argument, update the node in which point is located. 1221 "Without any prefix argument, update the node in which point is located.
1017 Non-nil argument (prefix, if interactive) means update the nodes in the 1222 Non-nil argument (prefix, if interactive) means update the nodes in the
1018 marked region. 1223 marked region.
1029 texinfo-master-menu () 1234 texinfo-master-menu ()
1030 1235
1031 texinfo-indent-menu-description (column &optional region-p) 1236 texinfo-indent-menu-description (column &optional region-p)
1032 1237
1033 The `texinfo-column-for-description' variable specifies the column to 1238 The `texinfo-column-for-description' variable specifies the column to
1034 which menu descriptions are indented. Its default value is 24." 1239 which menu descriptions are indented. Its default value is 32."
1035 1240
1036 (interactive "P") 1241 (interactive "P")
1037 (if (not region-p) 1242 (if (not region-p)
1038 (let ((auto-fill-function nil)) ; update a single node 1243 (let ((auto-fill-function nil)) ; update a single node
1039 (if (not (re-search-backward "^@node" (point-min) t)) 1244 (if (not (re-search-backward "^@node" (point-min) t))
1047 (if (= end beginning) 1252 (if (= end beginning)
1048 (error "Please mark a region!")) 1253 (error "Please mark a region!"))
1049 (save-restriction 1254 (save-restriction
1050 (narrow-to-region beginning end) 1255 (narrow-to-region beginning end)
1051 (goto-char beginning) 1256 (goto-char beginning)
1052 (push-mark) 1257 (push-mark (point) t)
1053 (while (re-search-forward "^@node" (point-max) t) 1258 (while (re-search-forward "^@node" (point-max) t)
1054 (beginning-of-line) 1259 (beginning-of-line)
1055 (texinfo-update-the-node)) 1260 (texinfo-update-the-node))
1056 (message "Done...updated nodes in region. You may save the buffer."))))) 1261 (message "Done...updated nodes in region. You may save the buffer.")))))
1057 1262
1058 (defun texinfo-every-node-update () 1263 (defun texinfo-every-node-update ()
1059 "Update every node in a Texinfo file." 1264 "Update every node in a Texinfo file."
1060 (interactive) 1265 (interactive)
1061 (save-excursion 1266 (save-excursion
1062 (mark-whole-buffer) 1267 (push-mark (point-max) t)
1268 (goto-char (point-min))
1063 (texinfo-update-node t) 1269 (texinfo-update-node t)
1064 (message "Done...updated every node. You may save the buffer."))) 1270 (message "Done...updated every node. You may save the buffer.")))
1065 1271
1066 (defun texinfo-update-the-node () 1272 (defun texinfo-update-the-node ()
1067 "Update one node. Point must be at the beginning of node line. 1273 "Update one node. Point must be at the beginning of node line.
1109 1315
1110 (defun texinfo-check-for-node-name () 1316 (defun texinfo-check-for-node-name ()
1111 "Determine whether the node has a node name. Prompt for one if not. 1317 "Determine whether the node has a node name. Prompt for one if not.
1112 Point must be at beginning of node line. Does not move point." 1318 Point must be at beginning of node line. Does not move point."
1113 (save-excursion 1319 (save-excursion
1114 (forward-word 1) ; skip over node command 1320 (let ((initial (texinfo-copy-next-section-title)))
1115 (skip-chars-forward " \t") ; and over spaces 1321 ;; This is not clean. Use `interactive' to read the arg.
1116 (if (not (looking-at "[^,\t\n ]+")) ; regexp based on what info looks for 1322 (forward-word 1) ; skip over node command
1117 ; alternatively, use "[a-zA-Z]+" 1323 (skip-chars-forward " \t") ; and over spaces
1118 (let ((node-name (read-from-minibuffer "Node name: "))) 1324 (if (not (looking-at "[^,\t\n ]+")) ; regexp based on what Info looks for
1119 (insert " " node-name))))) 1325 ; alternatively, use "[a-zA-Z]+"
1326 (let ((node-name
1327 (read-from-minibuffer
1328 "Node name (use no @, commas, colons, or apostrophes): "
1329 initial)))
1330 (insert " " node-name))))))
1120 1331
1121 (defun texinfo-delete-existing-pointers () 1332 (defun texinfo-delete-existing-pointers ()
1122 "Delete `Next', `Previous', and `Up' pointers. 1333 "Delete `Next', `Previous', and `Up' pointers.
1123 Starts from the current position of the cursor, and searches forward 1334 Starts from the current position of the cursor, and searches forward
1124 on the line for a comma and if one is found, deletes the rest of the 1335 on the line for a comma and if one is found, deletes the rest of the
1142 the section found will be at the same or higher hierarchical level in 1353 the section found will be at the same or higher hierarchical level in
1143 the Texinfo file; when looking for the `Up' pointer, the section found 1354 the Texinfo file; when looking for the `Up' pointer, the section found
1144 will be at some level higher in the Texinfo file. The fourth argument 1355 will be at some level higher in the Texinfo file. The fourth argument
1145 \(one of 'next, 'previous, or 'up\) specifies whether to find the 1356 \(one of 'next, 'previous, or 'up\) specifies whether to find the
1146 `Next', `Previous', or `Up' pointer." 1357 `Next', `Previous', or `Up' pointer."
1147 1358 (let ((case-fold-search t))
1148 (cond ((eq direction 'next) 1359 (cond ((eq direction 'next)
1149 (forward-line 3) ; skip over current node 1360 (forward-line 3) ; skip over current node
1150 (if (re-search-forward 1361 ;; Search for section commands accompanied by node lines;
1151 (eval 1362 ;; ignore section commands in the middle of nodes.
1152 (cdr (assoc level texinfo-update-menu-same-level-regexps))) 1363 (if (re-search-forward
1153 end 1364 ;; A `Top' node is never a next pointer, so won't find it.
1154 t) 1365 (concat
1155 'normal 1366 ;; Match node line.
1156 'no-pointer)) 1367 "\\(^@node\\).*\n"
1157 ((eq direction 'previous) 1368 ;; Match comment or ifinfo line, if any
1158 (if (re-search-backward 1369 "\\(\\(\\(^@c\\).*\n\\)\\|\\(^@ifinfo[ ]*\n\\)\\)?"
1159 (concat 1370 (eval
1160 "\\(" 1371 (cdr (assoc level texinfo-update-menu-same-level-regexps))))
1161 (eval 1372 end
1162 (cdr (assoc level texinfo-update-menu-same-level-regexps))) 1373 t)
1163 "\\|" 1374 'normal
1164 (eval 1375 'no-pointer))
1165 (cdr (assoc level texinfo-update-menu-higher-regexps))) 1376 ((eq direction 'previous)
1166 "\\)") 1377 (if (re-search-backward
1167 beginning 1378 (concat
1168 t) 1379 "\\("
1169 'normal 1380 ;; Match node line.
1170 'no-pointer)) 1381 "\\(^@node\\).*\n"
1171 ((eq direction 'up) 1382 ;; Match comment or ifinfo line, if any
1172 (if (re-search-backward 1383 "\\(\\(\\(^@c\\).*\n\\)\\|\\(^@ifinfo[ ]*\n\\)\\)?"
1173 (eval (cdr (assoc level texinfo-update-menu-higher-regexps))) 1384 (eval
1174 (save-excursion 1385 (cdr (assoc level texinfo-update-menu-same-level-regexps)))
1175 (goto-char beginning) 1386 "\\|"
1176 (beginning-of-line) 1387 ;; Match node line.
1177 (point)) 1388 "\\(^@node\\).*\n"
1178 t) 1389 ;; Match comment or ifinfo line, if any
1179 'normal 1390 "\\(\\(\\(^@c\\).*\n\\)\\|\\(^@ifinfo[ ]*\n\\)\\)?"
1180 'no-pointer)) 1391 (eval
1181 (t 1392 (cdr (assoc level texinfo-update-menu-higher-regexps)))
1182 (error "texinfo-find-pointer: lack proper arguments")))) 1393 "\\|"
1394 ;; Handle `Top' node specially.
1395 "^@node [ \t]*top[ \t]*\\(,\\|$\\)"
1396 "\\)")
1397 beginning
1398 t)
1399 'normal
1400 'no-pointer))
1401 ((eq direction 'up)
1402 (if (re-search-backward
1403 (concat
1404 "\\("
1405 ;; Match node line.
1406 "\\(^@node\\).*\n"
1407 ;; Match comment or ifinfo line, if any
1408 "\\(\\(\\(^@c\\).*\n\\)\\|\\(^@ifinfo[ ]*\n\\)\\)?"
1409 (eval (cdr (assoc level texinfo-update-menu-higher-regexps)))
1410 "\\|"
1411 ;; Handle `Top' node specially.
1412 "^@node [ \t]*top[ \t]*\\(,\\|$\\)"
1413 "\\)")
1414 (save-excursion
1415 (goto-char beginning)
1416 (beginning-of-line)
1417 (point))
1418 t)
1419 'normal
1420 'no-pointer))
1421 (t
1422 (error "texinfo-find-pointer: lack proper arguments")))))
1183 1423
1184 (defun texinfo-pointer-name (kind) 1424 (defun texinfo-pointer-name (kind)
1185 "Return the node name preceding the section command. 1425 "Return the node name preceding the section command.
1186 The argument is the kind of section, either normal or no-pointer." 1426 The argument is the kind of section, either normal or no-pointer."
1187 (let (name) 1427 (let (name)
1219 (end-of-line) 1459 (end-of-line)
1220 (skip-chars-backward ", ") 1460 (skip-chars-backward ", ")
1221 (delete-region (point) (save-excursion (end-of-line) (point)))) 1461 (delete-region (point) (save-excursion (end-of-line) (point))))
1222 1462
1223 1463
1224 ;;;; Updating nodes sequentially 1464 ;;; Updating nodes sequentially
1225 ; These sequential update functions insert `Next' or `Previous' 1465 ; These sequential update functions insert `Next' or `Previous'
1226 ; pointers that point to the following or preceding nodes even if they 1466 ; pointers that point to the following or preceding nodes even if they
1227 ; are at higher or lower hierarchical levels. This means that if a 1467 ; are at higher or lower hierarchical levels. This means that if a
1228 ; section contains one or more subsections, the section's `Next' 1468 ; section contains one or more subsections, the section's `Next'
1229 ; pointer will point to the subsection and not the following section. 1469 ; pointer will point to the subsection and not the following section.
1262 (if (= end beginning) 1502 (if (= end beginning)
1263 (error "Please mark a region!")) 1503 (error "Please mark a region!"))
1264 (save-restriction 1504 (save-restriction
1265 (narrow-to-region beginning end) 1505 (narrow-to-region beginning end)
1266 (goto-char beginning) 1506 (goto-char beginning)
1267 (push-mark) 1507 (push-mark (point) t)
1268 (while (re-search-forward "^@node" (point-max) t) 1508 (while (re-search-forward "^@node" (point-max) t)
1269 (beginning-of-line) 1509 (beginning-of-line)
1270 (texinfo-sequentially-update-the-node)) 1510 (texinfo-sequentially-update-the-node))
1271 (message 1511 (message
1272 "Done...updated the nodes in sequence. You may save the buffer."))))) 1512 "Done...updated the nodes in sequence. You may save the buffer.")))))
1304 such as \"chapter\ or \"section\". The section found will be at the 1544 such as \"chapter\ or \"section\". The section found will be at the
1305 same hierarchical level in the Texinfo file, or, in the case of the up 1545 same hierarchical level in the Texinfo file, or, in the case of the up
1306 pointer, some level higher. The second argument (one of 'next, 1546 pointer, some level higher. The second argument (one of 'next,
1307 'previous, or 'up) specifies whether to find the `Next', `Previous', 1547 'previous, or 'up) specifies whether to find the `Next', `Previous',
1308 or `Up' pointer." 1548 or `Up' pointer."
1309 1549 (let ((case-fold-search t))
1310 (cond ((eq direction 'next) 1550 (cond ((eq direction 'next)
1311 (forward-line 3) ; skip over current node 1551 (forward-line 3) ; skip over current node
1312 (if (re-search-forward 1552 (if (re-search-forward
1313 texinfo-section-types-regexp 1553 texinfo-section-types-regexp
1314 (point-max) 1554 (point-max)
1315 t) 1555 t)
1316 'normal 1556 'normal
1317 'no-pointer)) 1557 'no-pointer))
1318 ((eq direction 'previous) 1558 ((eq direction 'previous)
1319 (if (re-search-backward 1559 (if (re-search-backward
1320 texinfo-section-types-regexp 1560 texinfo-section-types-regexp
1321 (point-min) 1561 (point-min)
1322 t) 1562 t)
1323 'normal 1563 'normal
1324 'no-pointer)) 1564 'no-pointer))
1325 ((eq direction 'up) 1565 ((eq direction 'up)
1326 (if (re-search-backward 1566 (if (re-search-backward
1327 (eval (cdr (assoc level texinfo-update-menu-higher-regexps))) 1567 (eval (cdr (assoc level texinfo-update-menu-higher-regexps)))
1328 beginning 1568 beginning
1329 t) 1569 t)
1330 'normal 1570 'normal
1331 'no-pointer)) 1571 'no-pointer))
1332 (t 1572 (t
1333 (error "texinfo-sequential-find-pointer: lack proper arguments")))) 1573 (error "texinfo-sequential-find-pointer: lack proper arguments")))))
1334 1574
1335 (defun texinfo-sequentially-insert-pointer (level direction) 1575 (defun texinfo-sequentially-insert-pointer (level direction)
1336 "Insert the `Next', `Previous' or `Up' node name at point. 1576 "Insert the `Next', `Previous' or `Up' node name at point.
1337 Move point forward. 1577 Move point forward.
1338 1578
1346 (save-excursion 1586 (save-excursion
1347 (texinfo-pointer-name 1587 (texinfo-pointer-name
1348 (texinfo-sequentially-find-pointer level direction))))) 1588 (texinfo-sequentially-find-pointer level direction)))))
1349 1589
1350 1590
1351 ;;;; Inserting `@node' lines 1591 ;;; Inserting `@node' lines
1352 ; The `texinfo-insert-node-lines' function inserts `@node' lines as needed 1592 ; The `texinfo-insert-node-lines' function inserts `@node' lines as needed
1353 ; before the `@chapter', `@section', and such like lines of a region 1593 ; before the `@chapter', `@section', and such like lines of a region
1354 ; in a Texinfo file. 1594 ; in a Texinfo file.
1355 1595
1356 (defun texinfo-insert-node-lines (&optional title-p) 1596 (defun texinfo-insert-node-lines (beginning end &optional title-p)
1357 "Insert missing `@node' lines in region of Texinfo file. 1597 "Insert missing `@node' lines in region of Texinfo file.
1358 Non-nil argument (prefix, if interactive) means also to insert the 1598 Non-nil argument (prefix, if interactive) means also to insert the
1359 section titles as node names; and also to insert the section titles as 1599 section titles as node names; and also to insert the section titles as
1360 node names in pre-existing @node lines that lack names." 1600 node names in pre-existing @node lines that lack names."
1361 (interactive "P") 1601 (interactive "r\nP")
1362 (save-excursion 1602
1363 (let ((begin-region (region-beginning)) 1603 ;; Use marker; after inserting node lines, leave point at end of
1364 (end-region (region-end))) 1604 ;; region and mark at beginning.
1365 (goto-char begin-region) 1605
1366 (while (< (point) end-region) 1606 (let (beginning-marker end-marker title last-section-position)
1367 (re-search-forward texinfo-section-types-regexp nil 'end) 1607
1368 ;; copy title, since most often, we will need it 1608 ;; Save current position on mark ring and set mark to end.
1369 (let ((title 1609 (push-mark end t)
1370 (progn 1610 (setq end-marker (mark-marker))
1371 (beginning-of-line) 1611
1372 (forward-word 1) 1612 (goto-char beginning)
1373 (skip-chars-forward " \t") 1613 (while (re-search-forward
1374 (buffer-substring 1614 texinfo-section-types-regexp
1375 (point) 1615 end-marker
1376 (save-excursion (end-of-line) (point)))))) 1616 'end)
1377 ;; insert a node if necessary 1617 ;; Copy title if desired.
1378 (if (re-search-backward 1618 (if title-p
1379 "^@node" 1619 (progn
1380 (save-excursion 1620 (beginning-of-line)
1381 (forward-line -3) 1621 (forward-word 1)
1382 (point)) 1622 (skip-chars-forward " \t")
1383 t) 1623 (setq title (buffer-substring
1384 ;; @node present, and point at beginning of that line 1624 (point)
1385 (forward-word 1) 1625 (save-excursion (end-of-line) (point))))))
1386 ;; else @node missing, insert one 1626 ;; Insert node line if necessary.
1387 (progn 1627 (if (re-search-backward
1388 (beginning-of-line) ; beginning of `@section' line 1628 "^@node"
1389 (insert "@node\n") 1629 ;; Avoid finding previous node line if node lines are close.
1390 (backward-char 1))) ; leave point just after `@node' 1630 (or last-section-position
1391 ;; insert a title if warranted 1631 (save-excursion (forward-line -2) (point))) t)
1392 (if title-p 1632 ;; @node is present, and point at beginning of that line
1393 (progn 1633 (forward-word 1) ; Leave point just after @node.
1394 (skip-chars-forward " \t") 1634 ;; Else @node missing; insert one.
1395 ;; use regexp based on what info looks for 1635 (beginning-of-line) ; Beginning of `@section' line.
1396 ;; (alternatively, use "[a-zA-Z]+") 1636 (insert "@node\n")
1397 (if (not (looking-at "[^,\t\n ]+")) 1637 (backward-char 1)) ; Leave point just after `@node'.
1398 (progn 1638 ;; Insert title if desired.
1399 (beginning-of-line) 1639 (if title-p
1400 (forward-word 1) 1640 (progn
1401 (insert " " title) 1641 (skip-chars-forward " \t")
1402 (message "Inserted title %s ... " title))))) 1642 ;; Use regexp based on what info looks for
1403 ;; in any case, go forward beyond current section title 1643 ;; (alternatively, use "[a-zA-Z]+");
1404 (forward-line 3))))) 1644 ;; this means we only insert a title if none exists.
1405 (if title-p 1645 (if (not (looking-at "[^,\t\n ]+"))
1646 (progn
1647 (beginning-of-line)
1648 (forward-word 1)
1649 (insert " " title)
1650 (message "Inserted title %s ... " title)))))
1651 ;; Go forward beyond current section title.
1652 (re-search-forward texinfo-section-types-regexp
1653 (save-excursion (forward-line 3) (point)) t)
1654 (setq last-section-position (point))
1655 (forward-line 1))
1656
1657 ;; Leave point at end of region, mark at beginning.
1658 (set-mark beginning)
1659
1660 (if title-p
1406 (message 1661 (message
1407 "Done inserting node lines and titles. You may save the buffer.") 1662 "Done inserting node lines and titles. You may save the buffer.")
1408 (message "Done inserting node lines. You may save the buffer."))) 1663 (message "Done inserting node lines. You may save the buffer."))))
1409 1664
1410 1665
1411 ;;;; Update and create menus for multi-file Texinfo sources 1666 ;;; Update and create menus for multi-file Texinfo sources
1412 1667
1413 ;; 1. M-x texinfo-multiple-files-update 1668 ;; 1. M-x texinfo-multiple-files-update
1414 ;; 1669 ;;
1415 ;; Read the include file list of an outer Texinfo file and 1670 ;; Read the include file list of an outer Texinfo file and
1416 ;; update all highest level nodes in the files listed and insert a 1671 ;; update all highest level nodes in the files listed and insert a
1435 ;;; * Do not save or delete any buffers. You may fill up your memory. 1690 ;;; * Do not save or delete any buffers. You may fill up your memory.
1436 ;;; * Do not handle any pre-existing nodes in outer file. 1691 ;;; * Do not handle any pre-existing nodes in outer file.
1437 ;;; Hence, you may need a file for indices. 1692 ;;; Hence, you may need a file for indices.
1438 1693
1439 1694
1440 ;;;; Auxiliary functions for multiple file updating 1695 ;;; Auxiliary functions for multiple file updating
1441 1696
1442 (defun texinfo-multi-file-included-list (outer-file) 1697 (defun texinfo-multi-file-included-list (outer-file)
1443 "Return a list of the included files in OUTER-FILE." 1698 "Return a list of the included files in OUTER-FILE."
1444 (let ((included-file-list (list outer-file)) 1699 (let ((included-file-list (list outer-file))
1445 start) 1700 start)
1463 Start with point at the beginning of the node line. Leave point at the 1718 Start with point at the beginning of the node line. Leave point at the
1464 same place. If there is no title, returns an empty string." 1719 same place. If there is no title, returns an empty string."
1465 1720
1466 (save-excursion 1721 (save-excursion
1467 (end-of-line) 1722 (end-of-line)
1468 (let ((section-end (or 1723 (let ((node-end (or
1469 (save-excursion 1724 (save-excursion
1470 (re-search-forward "\\(^@node\\)" nil t) 1725 (if (re-search-forward "\\(^@node\\)" nil t)
1471 (match-beginning 0)) 1726 (match-beginning 0)))
1472 (point-max)))) 1727 (point-max))))
1473 (if (re-search-forward texinfo-section-types-regexp section-end t) 1728 (if (re-search-forward texinfo-section-types-regexp node-end t)
1474 ;; copy title 1729 (progn
1475 (let ((title 1730 (beginning-of-line)
1476 (buffer-substring 1731 ;; copy title
1477 (progn (forward-word 1) ; skip over section type 1732 (let ((title
1478 (skip-chars-forward " \t") ; and over spaces 1733 (buffer-substring
1479 (point)) 1734 (progn (forward-word 1) ; skip over section type
1480 (progn (end-of-line) (point))))) 1735 (skip-chars-forward " \t") ; and over spaces
1481 title) 1736 (point))
1737 (progn (end-of-line) (point)))))
1738 title))
1482 "")))) 1739 ""))))
1483 1740
1484 (defun texinfo-multi-file-update (files &optional update-everything) 1741 (defun texinfo-multi-file-update (files &optional update-everything)
1485 "Update first node pointers in each file in FILES. 1742 "Update first node pointers in each file in FILES.
1486 Return a list of the node names and the title immediate following them. 1743 Return a list of the node names.
1487 1744
1488 The first file in the list is an outer file; the remaining are 1745 The first file in the list is an outer file; the remaining are
1489 files included in the outer file with `@include' commands. 1746 files included in the outer file with `@include' commands.
1490 1747
1491 If optional arg UPDATE-EVERYTHING non-nil, update every menu and 1748 If optional arg UPDATE-EVERYTHING non-nil, update every menu and
1500 hierarchical level node, 1757 hierarchical level node,
1501 * this node must be the first node in the included file, 1758 * this node must be the first node in the included file,
1502 * each highest hierarchical level node must be of the same type. 1759 * each highest hierarchical level node must be of the same type.
1503 1760
1504 Thus, normally, each included file contains one, and only one, 1761 Thus, normally, each included file contains one, and only one,
1505 chapter. 1762 chapter."
1506 1763
1507 The menu-list has the form: 1764 ; The menu-list has the form:
1508 1765 ;
1509 \(\(\"node-name1\" . \"title1\"\) 1766 ; \(\(\"node-name1\" . \"title1\"\)
1510 \(\"node-name2\" . \"title2\"\) ... \) 1767 ; \(\"node-name2\" . \"title2\"\) ... \)
1511 1768 ;
1512 However, there does not need to be a title field." 1769 ; However, there does not need to be a title field and this function
1770 ; does not fill it; however a comment tells you how to do so.
1771 ; You would use the title field if you wanted to insert titles in the
1772 ; description slot of a menu as a description.
1513 1773
1514 (let (menu-list) 1774 (let ((case-fold-search t)
1775 menu-list)
1515 1776
1516 ;; Find the name of the first node of the first included file. 1777 ;; Find the name of the first node of the first included file.
1517 (switch-to-buffer (find-file-noselect (car (cdr files)))) 1778 (switch-to-buffer (find-file-noselect (car (cdr files))))
1518 (widen) 1779 (widen)
1519 (goto-char (point-min)) 1780 (goto-char (point-min))
1524 (setq next-node-name (texinfo-copy-node-name)) 1785 (setq next-node-name (texinfo-copy-node-name))
1525 1786
1526 (setq menu-list 1787 (setq menu-list
1527 (cons (cons 1788 (cons (cons
1528 next-node-name 1789 next-node-name
1529 (texinfo-copy-next-section-title)) 1790 (prog1 "" (forward-line 1)))
1791 ;; Use following to insert section titles automatically.
1792 ;; (texinfo-copy-next-section-title)
1530 menu-list)) 1793 menu-list))
1531 1794
1532 ;; Go to outer file 1795 ;; Go to outer file
1533 (switch-to-buffer (find-file-noselect (car files))) 1796 (switch-to-buffer (find-file-noselect (car files)))
1534 (goto-char (point-min)) 1797 (goto-char (point-min))
1535 (if (not (re-search-forward "^@node [ \t]*top[ \t]*\\(,\\|$\\)" nil t)) 1798 (if (not (re-search-forward "^@node [ \t]*top[ \t]*\\(,\\|$\\)" nil t))
1536 (error "This buffer needs a Top node!")) 1799 (error "This buffer needs a Top node!"))
1558 (texinfo-check-for-node-name) 1821 (texinfo-check-for-node-name)
1559 (setq next-node-name (texinfo-copy-node-name)) 1822 (setq next-node-name (texinfo-copy-node-name))
1560 (setq menu-list 1823 (setq menu-list
1561 (cons (cons 1824 (cons (cons
1562 next-node-name 1825 next-node-name
1563 (texinfo-copy-next-section-title)) 1826 (prog1 "" (forward-line 1)))
1827 ;; Use following to insert section titles automatically.
1828 ;; (texinfo-copy-next-section-title)
1564 menu-list))) 1829 menu-list)))
1565 1830
1566 ;; Go to node to be updated. 1831 ;; Go to node to be updated.
1567 (switch-to-buffer (find-file-noselect (car files))) 1832 (switch-to-buffer (find-file-noselect (car files)))
1568 (goto-char (point-min)) 1833 (goto-char (point-min))
1569 (if (not (re-search-forward "^@node" nil t)) 1834 (if (not (re-search-forward "^@node" nil t))
1570 (error "No `@node' line found in %s !" (buffer-name))) 1835 (error "No `@node' line found in %s !" (buffer-name)))
1836 (beginning-of-line)
1837
1838 ;; Update other menus and nodes if requested.
1839 (if update-everything (texinfo-all-menus-update t))
1840
1571 (beginning-of-line) 1841 (beginning-of-line)
1572 (texinfo-delete-existing-pointers) 1842 (texinfo-delete-existing-pointers)
1573 (end-of-line) 1843 (end-of-line)
1574 (insert ", " next-node-name ", " previous-node-name ", " up-node-name) 1844 (insert ", " next-node-name ", " previous-node-name ", " up-node-name)
1575 1845
1576 (beginning-of-line) 1846 (beginning-of-line)
1577 (setq previous-node-name (texinfo-copy-node-name)) 1847 (setq previous-node-name (texinfo-copy-node-name))
1578 1848
1579 ;; Update other menus and nodes if requested.
1580 (if update-everything (texinfo-all-menus-update t))
1581
1582 (setq files (cdr files))) 1849 (setq files (cdr files)))
1583 (nreverse menu-list))) 1850 (nreverse menu-list)))
1584 1851
1585 (defun texinfo-multi-files-insert-main-menu (menu-list) 1852 (defun texinfo-multi-files-insert-main-menu (menu-list)
1586 "Insert formatted main menu at point. 1853 "Insert formatted main menu at point.
1587 Indents the first line of the description, if any, to the value of 1854 Indents the first line of the description, if any, to the value of
1588 texinfo-column-for-description." 1855 texinfo-column-for-description."
1589 1856
1590 (insert "@menu\n") 1857 (insert "@menu\n")
1591 (while menu-list 1858 (while menu-list
1592 (if (cdr (car menu-list)) ; menu-list has description entry 1859 ;; Every menu entry starts with a star and a space.
1860 (insert "* ")
1861
1862 ;; Insert the node name (and menu entry name, if present).
1863 (let ((node-part (car (car menu-list))))
1864 (if (stringp node-part)
1865 ;; "Double colon" entry line; menu entry and node name are the same,
1866 (insert (format "%s::" node-part))
1867 ;; "Single colon" entry line; menu entry and node name are different.
1868 (insert (format "%s: %s." (car node-part) (cdr node-part)))))
1869
1870 ;; Insert the description, if present.
1871 (if (cdr (car menu-list))
1593 (progn 1872 (progn
1594 (insert 1873 ;; Move to right place.
1595 (format "* %s::" (car (car menu-list)))) ; node-name entry 1874 (indent-to texinfo-column-for-description 2)
1596 (indent-to texinfo-column-for-description 2) 1875 ;; Insert description.
1597 (insert 1876 (insert (format "%s" (cdr (car menu-list))))))
1598 (format "%s\n" (cdr (car menu-list))))) ; description entry 1877
1599 ;; else menu-list lacks description entry 1878 (insert "\n") ; end this menu entry
1600 (insert
1601 (format "* %s::\n" (car (car menu-list))))) ; node-name entry
1602 (setq menu-list (cdr menu-list))) 1879 (setq menu-list (cdr menu-list)))
1603 (insert "@end menu")) 1880 (insert "@end menu"))
1604
1605 1881
1606 (defun texinfo-multi-file-master-menu-list (files-list) 1882 (defun texinfo-multi-file-master-menu-list (files-list)
1607 "Return master menu list from files in FILES-LIST. 1883 "Return master menu list from files in FILES-LIST.
1608 Menu entries in each file collected using `texinfo-master-menu-list'. 1884 Menu entries in each file collected using `texinfo-master-menu-list'.
1609 1885
1619 (append master-menu-list (texinfo-master-menu-list))) 1895 (append master-menu-list (texinfo-master-menu-list)))
1620 (setq files-list (cdr files-list))) 1896 (setq files-list (cdr files-list)))
1621 master-menu-list))) 1897 master-menu-list)))
1622 1898
1623 1899
1624 ;;;; The multiple-file update function 1900 ;;; The multiple-file update function
1625 1901
1626 (defun texinfo-multiple-files-update 1902 (defun texinfo-multiple-files-update
1627 (outer-file &optional update-everything make-master-menu) 1903 (outer-file &optional update-everything make-master-menu)
1628 "Update first node pointers in each file included in OUTER-FILE; 1904 "Update first node pointers in each file included in OUTER-FILE;
1629 create or update main menu in the outer file that refers to such nodes. 1905 create or update the `Top' level node pointers and the main menu in
1630 This does not create or update menus or pointers within the included files. 1906 the outer file that refers to such nodes. This does not create or
1907 update menus or pointers within the included files.
1631 1908
1632 With optional MAKE-MASTER-MENU argument (prefix arg, if interactive), 1909 With optional MAKE-MASTER-MENU argument (prefix arg, if interactive),
1633 insert a master menu in OUTER-FILE. This does not create or update 1910 insert a master menu in OUTER-FILE in addition to creating or updating
1634 menus or pointers within the included files. 1911 pointers in the first @node line in each included file and creating or
1912 updating the `Top' level node pointers of the outer file. This does
1913 not create or update other menus and pointers within the included
1914 files.
1635 1915
1636 With optional UPDATE-EVERYTHING argument (numeric prefix arg, if 1916 With optional UPDATE-EVERYTHING argument (numeric prefix arg, if
1637 interactive), update all the menus and all the `Next', `Previous', and 1917 interactive), update all the menus and all the `Next', `Previous', and
1638 `Up' pointers of all the files included in OUTER-FILE before inserting 1918 `Up' pointers of all the files included in OUTER-FILE before inserting
1639 a master menu in OUTER-FILE. 1919 a master menu in OUTER-FILE. Also, update the `Top' level node
1640 1920 pointers of OUTER-FILE.
1641 The command also updates the `Top' level node pointers of OUTER-FILE.
1642 1921
1643 Notes: 1922 Notes:
1644 1923
1645 * this command does NOT save any files--you must save the 1924 * this command does NOT save any files--you must save the
1646 outer file and any modified, included files. 1925 outer file and any modified, included files.
1656 * this highest node must be the first node in the included file, 1935 * this highest node must be the first node in the included file,
1657 * each highest hierarchical level node must be of the same type. 1936 * each highest hierarchical level node must be of the same type.
1658 1937
1659 Thus, normally, each included file contains one, and only one, 1938 Thus, normally, each included file contains one, and only one,
1660 chapter." 1939 chapter."
1661 1940
1662 (interactive "fName of outer `include' file: ") 1941 (interactive (cons
1663 1942 (read-string
1664 (cond (current-prefix-arg 1943 "Name of outer `include' file: "
1665 (setq make-master-menu (listp current-prefix-arg)) 1944 (buffer-file-name))
1666 (setq update-everything (numberp current-prefix-arg)))) 1945 (cond ((not current-prefix-arg)
1946 '(nil nil))
1947 ((listp current-prefix-arg)
1948 '(t nil)) ; make-master-menu
1949 ((numberp current-prefix-arg)
1950 '(t t)) ; update-everything
1951 )))
1667 1952
1668 (let* ((included-file-list (texinfo-multi-file-included-list outer-file)) 1953 (let* ((included-file-list (texinfo-multi-file-included-list outer-file))
1669 (files included-file-list) 1954 (files included-file-list)
1670 main-menu-list 1955 main-menu-list
1671 next-node-name 1956 next-node-name
1718 (point)))) 2003 (point))))
1719 (delete-region (point) end-of-detailed-menu-descriptions)))) 2004 (delete-region (point) end-of-detailed-menu-descriptions))))
1720 2005
1721 ;; Create a master menu and insert it 2006 ;; Create a master menu and insert it
1722 (texinfo-insert-master-menu-list 2007 (texinfo-insert-master-menu-list
1723 (texinfo-multi-file-master-menu-list 2008 (texinfo-multi-file-master-menu-list
1724 included-file-list))))) 2009 included-file-list)))))
2010
2011 ;; Remove unwanted extra lines.
2012 (save-excursion
2013 (goto-char (point-min))
2014
2015 (re-search-forward "^@menu")
2016 (forward-line -1)
2017 (insert "\n") ; Ensure at least one blank line.
2018 (delete-blank-lines)
2019
2020 (re-search-forward "^@end menu")
2021 (forward-line 1)
2022 (insert "\n") ; Ensure at least one blank line.
2023 (delete-blank-lines))
2024
1725 (message "Multiple files updated.")) 2025 (message "Multiple files updated."))
1726 2026
2027
2028 ;;; Place `provide' at end of file.
1727 (provide 'texnfo-upd) 2029 (provide 'texnfo-upd)
1728 2030
1729 ;;; texnfo-upd.el ends here 2031 ;;; texnfo-upd.el ends here