Change release version from 21.4 to 22.1 throughout.
[bpt/emacs.git] / lisp / allout.el
CommitLineData
6a05d05f 1;;; allout.el --- extensive outline mode for use alone and with other modes
19b84ba3 2
e126900f 3;; Copyright (C) 1992, 93, 94, 2001, 02, 2004 Free Software Foundation, Inc.
1977b8f6 4
42d03dd0
JB
5;; Author: Ken Manheimer <klm@zope.com>
6;; Maintainer: Ken Manheimer <klm@zope.com>
c567ac01 7;; Created: Dec 1991 - first release to usenet
660a1df5 8;; Keywords: outlines mode wp languages
1977b8f6
RS
9
10;; This file is part of GNU Emacs.
11
59243403
RS
12;; GNU Emacs is free software; you can redistribute it and/or modify
13;; it under the terms of the GNU General Public License as published by
14;; the Free Software Foundation; either version 2, or (at your option)
15;; any later version.
16
1977b8f6 17;; GNU Emacs is distributed in the hope that it will be useful,
59243403
RS
18;; but WITHOUT ANY WARRANTY; without even the implied warranty of
19;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20;; GNU General Public License for more details.
21
22;; You should have received a copy of the GNU General Public License
b578f267
EN
23;; along with GNU Emacs; see the file COPYING. If not, write to the
24;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
25;; Boston, MA 02111-1307, USA.
1977b8f6 26
6a05d05f 27;;; Commentary:
19b84ba3
RS
28
29;; Allout outline mode provides extensive outline formatting and
9179616f
DL
30;; and manipulation beyond standard emacs outline mode. It provides
31;; for structured editing of outlines, as well as navigation and
32;; exposure. It also provides for syntax-sensitive text like
33;; programming languages. (For an example, see the allout code
34;; itself, which is organized in ;; an outline framework.)
71296446 35;;
9179616f 36;; In addition to outline navigation and exposure, allout includes:
71296446 37;;
9179616f
DL
38;; - topic-oriented repositioning, cut, and paste
39;; - integral outline exposure-layout
40;; - incremental search with dynamic exposure and reconcealment of hidden text
41;; - automatic topic-number maintenance
42;; - "Hot-spot" operation, for single-keystroke maneuvering and
fd5359c6 43;; exposure control. (See the `allout-mode' docstring.)
71296446 44;;
9179616f 45;; and many other features.
71296446 46;;
9179616f 47;; The outline menubar additions provide quick reference to many of
aad94676 48;; the features, and see the docstring of the function `allout-init'
e126900f 49;; for instructions on priming your Emacs session for automatic
fd5359c6 50;; activation of `allout-mode'.
71296446 51;;
fd5359c6
MR
52;; See the docstring of the variables `allout-layout' and
53;; `allout-auto-activation' for details on automatic activation of
54;; allout `allout-mode' as a minor mode. (It has changed since allout
19b84ba3 55;; 3.x, for those of you that depend on the old method.)
c567ac01 56;;
353e2ef2
KH
57;; Note - the lines beginning with `;;;_' are outline topic headers.
58;; Just `ESC-x eval-current-buffer' to give it a whirl.
19b84ba3 59
42d03dd0 60;; Ken Manheimer klm@zope.com
c567ac01 61
6a05d05f
PJ
62;;; Code:
63
19b84ba3 64;;;_* Provide
19b84ba3
RS
65(provide 'allout)
66
67;;;_* USER CUSTOMIZATION VARIABLES:
4bef9110
SE
68(defgroup allout nil
69 "Extensive outline mode for use alone and with other modes."
fd5359c6 70 :prefix "allout-"
65970d64 71 :group 'editing
bf247b6e 72 :version "22.1")
19b84ba3
RS
73
74;;;_ + Layout, Mode, and Topic Header Configuration
75
fd5359c6
MR
76;;;_ = allout-auto-activation
77(defcustom allout-auto-activation nil
78 "*Regulates auto-activation modality of allout outlines - see `allout-init'.
19b84ba3 79
fd5359c6 80Setq-default by `allout-init' to regulate whether or not allout
19b84ba3 81outline mode is automatically activated when the buffer-specific
fd5359c6
MR
82variable `allout-layout' is non-nil, and whether or not the layout
83dictated by `allout-layout' should be imposed on mode activation.
19b84ba3 84
24190da5 85With value t, auto-mode-activation and auto-layout are enabled.
aad94676 86\(This also depends on `allout-find-file-hook' being installed in
95c12694 87`find-file-hook', which is also done by `allout-init'.)
19b84ba3
RS
88
89With value `ask', auto-mode-activation is enabled, and endorsement for
90performing auto-layout is asked of the user each time.
91
71296446 92With value `activate', only auto-mode-activation is enabled,
353e2ef2 93auto-layout is not.
19b84ba3 94
24190da5 95With value nil, neither auto-mode-activation nor auto-layout are
19b84ba3
RS
96enabled.
97
fd5359c6 98See the docstring for `allout-init' for the proper interface to
9179616f
DL
99this variable."
100 :type '(choice (const :tag "On" t)
101 (const :tag "Ask about layout" "ask")
102 (const :tag "Mode only" "activate")
103 (const :tag "Off" nil))
104 :group 'allout)
fd5359c6
MR
105;;;_ = allout-layout
106(defvar allout-layout nil
19b84ba3 107 "*Layout specification and provisional mode trigger for allout outlines.
1977b8f6 108
19b84ba3
RS
109Buffer-specific.
110
111A list value specifies a default layout for the current buffer, to be
aad94676
MR
112applied upon activation of `allout-mode'. Any non-nil value will
113automatically trigger `allout-mode', provided `allout-init'
353e2ef2 114has been called to enable it.
19b84ba3 115
fd5359c6
MR
116See the docstring for `allout-init' for details on setting up for
117auto-mode-activation, and for `allout-expose-topic' for the format of
19b84ba3
RS
118the layout specification.
119
120You can associate a particular outline layout with a file by setting
121this var via the file's local variables. For example, the following
41e798a9 122lines at the bottom of an Emacs Lisp file:
19b84ba3
RS
123
124;;;Local variables:
fd5359c6 125;;;allout-layout: \(0 : -1 -1 0)
19b84ba3
RS
126;;;End:
127
128will, modulo the above-mentioned conditions, cause the mode to be
129activated when the file is visited, followed by the equivalent of
fd5359c6 130`\(allout-expose-topic 0 : -1 -1 0)'. \(This is the layout used for
19b84ba3
RS
131the allout.el, itself.)
132
353e2ef2
KH
133Also, allout's mode-specific provisions will make topic prefixes default
134to the comment-start string, if any, of the language of the file. This
fd5359c6
MR
135is modulo the setting of `allout-use-mode-specific-leader', which see.")
136(make-variable-buffer-local 'allout-layout)
137;;;_ = allout-show-bodies
138(defcustom allout-show-bodies nil
9179616f
DL
139 "*If non-nil, show entire body when exposing a topic, rather than
140just the header."
141 :type 'boolean
142 :group 'allout)
fd5359c6 143(make-variable-buffer-local 'allout-show-bodies)
1977b8f6 144
fd5359c6
MR
145;;;_ = allout-header-prefix
146(defcustom allout-header-prefix "."
19b84ba3
RS
147 "*Leading string which helps distinguish topic headers.
148
149Outline topic header lines are identified by a leading topic
c567ac01
RS
150header prefix, which mostly have the value of this var at their front.
151\(Level 1 topics are exceptions. They consist of only a single
2265e017 152character, which is typically set to the `allout-primary-bullet'. Many
4bef9110
SE
153outlines start at level 2 to avoid this discrepancy."
154 :type 'string
155 :group 'allout)
fd5359c6
MR
156(make-variable-buffer-local 'allout-header-prefix)
157;;;_ = allout-primary-bullet
158(defcustom allout-primary-bullet "*"
19b84ba3
RS
159 "Bullet used for top-level outline topics.
160
161Outline topic header lines are identified by a leading topic header
c567ac01 162prefix, which is concluded by bullets that includes the value of this
fd5359c6 163var and the respective allout-*-bullets-string vars.
c567ac01 164
353e2ef2 165The value of an asterisk (`*') provides for backwards compatibility
e126900f 166with the original Emacs outline mode. See `allout-plain-bullets-string'
2265e017 167and `allout-distinctive-bullets-string' for the range of available
4bef9110
SE
168bullets."
169 :type 'string
170 :group 'allout)
fd5359c6
MR
171(make-variable-buffer-local 'allout-primary-bullet)
172;;;_ = allout-plain-bullets-string
173(defcustom allout-plain-bullets-string ".:,;"
19b84ba3
RS
174 "*The bullets normally used in outline topic prefixes.
175
fd5359c6 176See `allout-distinctive-bullets-string' for the other kind of
c567ac01 177bullets.
1977b8f6 178
353e2ef2 179DO NOT include the close-square-bracket, `]', as a bullet.
1977b8f6 180
c567ac01 181Outline mode has to be reactivated in order for changes to the value
4bef9110
SE
182of this var to take effect."
183 :type 'string
184 :group 'allout)
fd5359c6
MR
185(make-variable-buffer-local 'allout-plain-bullets-string)
186;;;_ = allout-distinctive-bullets-string
187(defcustom allout-distinctive-bullets-string "*+-=>([{}&!?#%\"X@$~_\\"
19b84ba3 188 "*Persistent outline header bullets used to distinguish special topics.
1977b8f6 189
9179616f
DL
190These bullets are used to distinguish topics from the run-of-the-mill
191ones. They are not used in the standard topic headers created by
71296446 192the topic-opening, shifting, and rebulleting \(eg, on topic shift,
9179616f
DL
193topic paste, blanket rebulleting) routines, but are offered among the
194choices for rebulleting. They are not altered by the above automatic
195rebulleting, so they can be used to characterize topics, eg:
196
197 `?' question topics
198 `\(' parenthetic comment \(with a matching close paren inside)
199 `[' meta-note \(with a matching close ] inside)
200 `\"' a quote
201 `=' value settings
202 `~' \"more or less\"
203
204... just for example. (`#' typically has a special meaning to the
fd5359c6 205software, according to the value of `allout-numbered-bullet'.)
9179616f 206
fd5359c6 207See `allout-plain-bullets-string' for the selection of
9179616f 208alternating bullets.
1977b8f6 209
fd5359c6 210You must run `set-allout-regexp' in order for outline mode to
9179616f 211reconcile to changes of this value.
19b84ba3 212
353e2ef2 213DO NOT include the close-square-bracket, `]', on either of the bullet
4bef9110
SE
214strings."
215 :type 'string
216 :group 'allout)
fd5359c6 217(make-variable-buffer-local 'allout-distinctive-bullets-string)
1977b8f6 218
fd5359c6
MR
219;;;_ = allout-use-mode-specific-leader
220(defcustom allout-use-mode-specific-leader t
19b84ba3
RS
221 "*When non-nil, use mode-specific topic-header prefixes.
222
fd5359c6 223Allout outline mode will use the mode-specific `allout-mode-leaders'
19b84ba3 224and/or comment-start string, if any, to lead the topic prefix string,
353e2ef2 225so topic headers look like comments in the programming language.
19b84ba3
RS
226
227String values are used as they stand.
228
24190da5 229Value t means to first check for assoc value in `allout-mode-leaders'
19b84ba3 230alist, then use comment-start string, if any, then use default \(`.').
9179616f 231\(See note about use of comment-start strings, below.)
19b84ba3 232
fd5359c6 233Set to the symbol for either of `allout-mode-leaders' or
19b84ba3
RS
234`comment-start' to use only one of them, respectively.
235
24190da5 236Value nil means to always use the default \(`.').
19b84ba3
RS
237
238comment-start strings that do not end in spaces are tripled, and an
353e2ef2 239`_' underscore is tacked on the end, to distinguish them from regular
19b84ba3 240comment strings. comment-start strings that do end in spaces are not
9179616f 241tripled, but an underscore is substituted for the space. [This
19b84ba3 242presumes that the space is for appearance, not comment syntax. You
fd5359c6 243can use `allout-mode-leaders' to override this behavior, when
4bef9110 244incorrect.]"
71296446 245 :type '(choice (const t) (const nil) string
fd5359c6 246 (const allout-mode-leaders)
4bef9110
SE
247 (const comment-start))
248 :group 'allout)
fd5359c6
MR
249;;;_ = allout-mode-leaders
250(defvar allout-mode-leaders '()
251 "Specific allout-prefix leading strings per major modes.
19b84ba3 252
9179616f 253Entries will be used instead or in lieu of mode-specific
fd5359c6 254comment-start strings. See also `allout-use-mode-specific-leader'.
19b84ba3
RS
255
256If you're constructing a string that will comment-out outline
257structuring so it can be included in program code, append an extra
258character, like an \"_\" underscore, to distinguish the lead string
259from regular comments that start at bol.")
260
fd5359c6
MR
261;;;_ = allout-old-style-prefixes
262(defcustom allout-old-style-prefixes nil
aad94676 263 "*When non-nil, use only old-and-crusty `outline-mode' `*' topic prefixes.
19b84ba3
RS
264
265Non-nil restricts the topic creation and modification
c567ac01 266functions to asterix-padded prefixes, so they look exactly
e126900f 267like the original Emacs-outline style prefixes.
1977b8f6 268
c567ac01 269Whatever the setting of this variable, both old and new style prefixes
4bef9110
SE
270are always respected by the topic maneuvering functions."
271 :type 'boolean
272 :group 'allout)
fd5359c6
MR
273(make-variable-buffer-local 'allout-old-style-prefixes)
274;;;_ = allout-stylish-prefixes - alternating bullets
275(defcustom allout-stylish-prefixes t
19b84ba3 276 "*Do fancy stuff with topic prefix bullets according to level, etc.
c567ac01 277
19b84ba3
RS
278Non-nil enables topic creation, modification, and repositioning
279functions to vary the topic bullet char (the char that marks the topic
280depth) just preceding the start of the topic text) according to level.
353e2ef2 281Otherwise, only asterisks (`*') and distinctive bullets are used.
19b84ba3
RS
282
283This is how an outline can look (but sans indentation) with stylish
284prefixes:
c567ac01
RS
285
286 * Top level
287 .* A topic
288 . + One level 3 subtopic
289 . . One level 4 subtopic
19b84ba3 290 . . A second 4 subtopic
c567ac01 291 . + Another level 3 subtopic
19b84ba3
RS
292 . #1 A numbered level 4 subtopic
293 . #2 Another
294 . ! Another level 4 subtopic with a different distinctive bullet
295 . #4 And another numbered level 4 subtopic
c567ac01 296
19b84ba3
RS
297This would be an outline with stylish prefixes inhibited (but the
298numbered and other distinctive bullets retained):
c567ac01
RS
299
300 * Top level
301 .* A topic
19b84ba3
RS
302 . * One level 3 subtopic
303 . * One level 4 subtopic
304 . * A second 4 subtopic
305 . * Another level 3 subtopic
306 . #1 A numbered level 4 subtopic
307 . #2 Another
308 . ! Another level 4 subtopic with a different distinctive bullet
309 . #4 And another numbered level 4 subtopic
c567ac01
RS
310
311Stylish and constant prefixes (as well as old-style prefixes) are
312always respected by the topic maneuvering functions, regardless of
313this variable setting.
314
2265e017 315The setting of this var is not relevant when `allout-old-style-prefixes'
4bef9110
SE
316is non-nil."
317 :type 'boolean
318 :group 'allout)
fd5359c6 319(make-variable-buffer-local 'allout-stylish-prefixes)
1977b8f6 320
fd5359c6
MR
321;;;_ = allout-numbered-bullet
322(defcustom allout-numbered-bullet "#"
19b84ba3
RS
323 "*String designating bullet of topics that have auto-numbering; nil for none.
324
a0776d6b 325Topics having this bullet have automatic maintenance of a sibling
19b84ba3 326sequence-number tacked on, just after the bullet. Conventionally set
c567ac01 327to \"#\", you can set it to a bullet of your choice. A nil value
4bef9110
SE
328disables numbering maintenance."
329 :type '(choice (const nil) string)
330 :group 'allout)
fd5359c6
MR
331(make-variable-buffer-local 'allout-numbered-bullet)
332;;;_ = allout-file-xref-bullet
333(defcustom allout-file-xref-bullet "@"
334 "*Bullet signifying file cross-references, for `allout-resolve-xref'.
19b84ba3 335
9179616f 336Set this var to the bullet you want to use for file cross-references."
4bef9110
SE
337 :type '(choice (const nil) string)
338 :group 'allout)
c567ac01 339
fd5359c6
MR
340;;;_ = allout-presentation-padding
341(defcustom allout-presentation-padding 2
9179616f
DL
342 "*Presentation-format white-space padding factor, for greater indent."
343 :type 'integer
344 :group 'allout)
345
fd5359c6 346(make-variable-buffer-local 'allout-presentation-padding)
9179616f 347
fd5359c6
MR
348;;;_ = allout-abbreviate-flattened-numbering
349(defcustom allout-abbreviate-flattened-numbering nil
350 "*If non-nil, `allout-flatten-exposed-to-buffer' abbreviates topic
9179616f
DL
351numbers to minimal amount with some context. Otherwise, entire
352numbers are always used."
353 :type 'boolean
354 :group 'allout)
355
c567ac01 356;;;_ + LaTeX formatting
fd5359c6
MR
357;;;_ - allout-number-pages
358(defcustom allout-number-pages nil
4bef9110
SE
359 "*Non-nil turns on page numbering for LaTeX formatting of an outline."
360 :type 'boolean
361 :group 'allout)
fd5359c6
MR
362;;;_ - allout-label-style
363(defcustom allout-label-style "\\large\\bf"
4bef9110
SE
364 "*Font and size of labels for LaTeX formatting of an outline."
365 :type 'string
366 :group 'allout)
fd5359c6
MR
367;;;_ - allout-head-line-style
368(defcustom allout-head-line-style "\\large\\sl "
4bef9110
SE
369 "*Font and size of entries for LaTeX formatting of an outline."
370 :type 'string
371 :group 'allout)
fd5359c6
MR
372;;;_ - allout-body-line-style
373(defcustom allout-body-line-style " "
4bef9110
SE
374 "*Font and size of entries for LaTeX formatting of an outline."
375 :type 'string
376 :group 'allout)
fd5359c6
MR
377;;;_ - allout-title-style
378(defcustom allout-title-style "\\Large\\bf"
4bef9110
SE
379 "*Font and size of titles for LaTeX formatting of an outline."
380 :type 'string
381 :group 'allout)
fd5359c6
MR
382;;;_ - allout-title
383(defcustom allout-title '(or buffer-file-name (current-buffer-name))
c567ac01 384 "*Expression to be evaluated to determine the title for LaTeX
4bef9110
SE
385formatted copy."
386 :type 'sexp
387 :group 'allout)
fd5359c6
MR
388;;;_ - allout-line-skip
389(defcustom allout-line-skip ".05cm"
4bef9110
SE
390 "*Space between lines for LaTeX formatting of an outline."
391 :type 'string
392 :group 'allout)
fd5359c6
MR
393;;;_ - allout-indent
394(defcustom allout-indent ".3cm"
4bef9110
SE
395 "*LaTeX formatted depth-indent spacing."
396 :type 'string
397 :group 'allout)
c567ac01
RS
398
399;;;_ + Miscellaneous customization
400
fd5359c6
MR
401;;;_ = allout-command-prefix
402(defcustom allout-command-prefix "\C-c"
9179616f
DL
403 "*Key sequence to be used as prefix for outline mode command key bindings."
404 :type 'string
405 :group 'allout)
406
fd5359c6
MR
407;;;_ = allout-keybindings-list
408;;; You have to reactivate allout-mode - `(allout-mode t)' - to
c567ac01 409;;; institute changes to this var.
fd5359c6 410(defvar allout-keybindings-list ()
2265e017 411 "*List of `allout-mode' key / function bindings, for `allout-mode-map'.
19b84ba3 412
2265e017 413String or vector key will be prefaced with `allout-command-prefix',
9179616f 414unless optional third, non-nil element is present.")
fd5359c6 415(setq allout-keybindings-list
1977b8f6
RS
416 '(
417 ; Motion commands:
fd5359c6
MR
418 ("\C-n" allout-next-visible-heading)
419 ("\C-p" allout-previous-visible-heading)
420 ("\C-u" allout-up-current-level)
421 ("\C-f" allout-forward-current-level)
422 ("\C-b" allout-backward-current-level)
423 ("\C-a" allout-beginning-of-current-entry)
424 ("\C-e" allout-end-of-current-entry)
1977b8f6 425 ; Exposure commands:
fd5359c6
MR
426 ("\C-i" allout-show-children)
427 ("\C-s" allout-show-current-subtree)
428 ("\C-h" allout-hide-current-subtree)
429 ("\C-o" allout-show-current-entry)
430 ("!" allout-show-all)
1977b8f6 431 ; Alteration commands:
fd5359c6
MR
432 (" " allout-open-sibtopic)
433 ("." allout-open-subtopic)
434 ("," allout-open-supertopic)
435 ("'" allout-shift-in)
436 (">" allout-shift-in)
437 ("<" allout-shift-out)
438 ("\C-m" allout-rebullet-topic)
439 ("*" allout-rebullet-current-heading)
440 ("#" allout-number-siblings)
441 ("\C-k" allout-kill-line t)
442 ("\C-y" allout-yank t)
443 ("\M-y" allout-yank-pop t)
444 ("\C-k" allout-kill-topic)
1977b8f6 445 ; Miscellaneous commands:
fd5359c6
MR
446 ;([?\C-\ ] allout-mark-topic)
447 ("@" allout-resolve-xref)
448 ("=c" allout-copy-exposed-to-buffer)
449 ("=i" allout-indented-exposed-to-buffer)
450 ("=t" allout-latexify-exposed)
451 ("=p" allout-flatten-exposed-to-buffer)))
452
453;;;_ = allout-isearch-dynamic-expose
454(defcustom allout-isearch-dynamic-expose t
9179616f
DL
455 "*Non-nil enable dynamic exposure of hidden incremental-search
456targets as they're encountered."
4bef9110
SE
457 :type 'boolean
458 :group 'allout)
fd5359c6 459(make-variable-buffer-local 'allout-isearch-dynamic-expose)
c567ac01 460
fd5359c6
MR
461;;;_ = allout-use-hanging-indents
462(defcustom allout-use-hanging-indents t
19b84ba3
RS
463 "*If non-nil, topic body text auto-indent defaults to indent of the header.
464Ie, it is indented to be just past the header prefix. This is
465relevant mostly for use with indented-text-mode, or other situations
466where auto-fill occurs.
c567ac01 467
353e2ef2 468\[This feature no longer depends in any way on the `filladapt.el'
4bef9110
SE
469lisp-archive package.\]"
470 :type 'boolean
471 :group 'allout)
fd5359c6 472(make-variable-buffer-local 'allout-use-hanging-indents)
c567ac01 473
fd5359c6
MR
474;;;_ = allout-reindent-bodies
475(defcustom allout-reindent-bodies (if allout-use-hanging-indents
8d118843 476 'text)
19b84ba3 477 "*Non-nil enables auto-adjust of topic body hanging indent with depth shifts.
1977b8f6 478
8d118843
RS
479When active, topic body lines that are indented even with or beyond
480their topic header are reindented to correspond with depth shifts of
481the header.
482
24190da5 483A value of t enables reindent in non-programming-code buffers, ie
8d118843 484those that do not have the variable `comment-start' set. A value of
4bef9110
SE
485`force' enables reindent whether or not `comment-start' is set."
486 :type '(choice (const nil) (const t) (const text) (const force))
487 :group 'allout)
8d118843 488
fd5359c6 489(make-variable-buffer-local 'allout-reindent-bodies)
c567ac01 490
fd5359c6
MR
491;;;_ = allout-inhibit-protection
492(defcustom allout-inhibit-protection nil
19b84ba3
RS
493 "*Non-nil disables warnings and confirmation-checks for concealed-text edits.
494
e126900f 495Outline mode uses Emacs change-triggered functions to detect unruly
19b84ba3
RS
496changes to concealed regions. Set this var non-nil to disable the
497protection, potentially increasing text-entry responsiveness a bit.
c567ac01 498
2265e017 499This var takes effect at `allout-mode' activation, so you may have to
19b84ba3 500deactivate and then reactivate the mode if you want to toggle the
4bef9110
SE
501behavior."
502 :type 'boolean
503 :group 'allout)
c567ac01 504
19b84ba3 505;;;_* CODE - no user customizations below.
c567ac01 506
9179616f
DL
507;;;_ #1 Internal Outline Formatting and Configuration
508;;;_ : Version
fd5359c6
MR
509;;;_ = allout-version
510(defvar allout-version
65970d64 511 (let ((rcs-rev "$Revision$"))
19b84ba3
RS
512 (condition-case err
513 (save-match-data
8d118843 514 (string-match "Revision: \\([0-9]+\\.[0-9]+\\)" rcs-rev)
19b84ba3 515 (substring rcs-rev (match-beginning 1) (match-end 1)))
9179616f 516 ('error rcs-rev)))
8d118843 517 "Revision number of currently loaded outline package. \(allout.el)")
fd5359c6
MR
518;;;_ > allout-version
519(defun allout-version (&optional here)
19b84ba3
RS
520 "Return string describing the loaded outline version."
521 (interactive "P")
fd5359c6 522 (let ((msg (concat "Allout Outline Mode v " allout-version)))
eac9cf5f 523 (if here (insert msg))
19b84ba3
RS
524 (message "%s" msg)
525 msg))
9179616f 526;;;_ : Topic header format
fd5359c6
MR
527;;;_ = allout-regexp
528(defvar allout-regexp ""
c567ac01 529 "*Regular expression to match the beginning of a heading line.
19b84ba3 530
c567ac01
RS
531Any line whose beginning matches this regexp is considered a
532heading. This var is set according to the user configuration vars
2265e017 533by `set-allout-regexp'.")
fd5359c6
MR
534(make-variable-buffer-local 'allout-regexp)
535;;;_ = allout-bullets-string
536(defvar allout-bullets-string ""
19b84ba3
RS
537 "A string dictating the valid set of outline topic bullets.
538
fd5359c6
MR
539This var should *not* be set by the user - it is set by `set-allout-regexp',
540and is produced from the elements of `allout-plain-bullets-string'
541and `allout-distinctive-bullets-string'.")
542(make-variable-buffer-local 'allout-bullets-string)
543;;;_ = allout-bullets-string-len
544(defvar allout-bullets-string-len 0
2265e017 545 "Length of current buffers' `allout-plain-bullets-string'.")
fd5359c6
MR
546(make-variable-buffer-local 'allout-bullets-string-len)
547;;;_ = allout-line-boundary-regexp
548(defvar allout-line-boundary-regexp ()
aad94676 549 "`allout-regexp' with outline style beginning-of-line anchor.
19b84ba3 550
a4e104bf 551\(Ie, C-j, *or* C-m, for prefixes of hidden topics). This is properly
2265e017 552set when `allout-regexp' is produced by `set-allout-regexp', so
c567ac01 553that (match-beginning 2) and (match-end 2) delimit the prefix.")
fd5359c6
MR
554(make-variable-buffer-local 'allout-line-boundary-regexp)
555;;;_ = allout-bob-regexp
556(defvar allout-bob-regexp ()
2265e017 557 "Like `allout-line-boundary-regexp', for headers at beginning of buffer.
9179616f 558\(match-beginning 2) and \(match-end 2) delimit the prefix.")
fd5359c6
MR
559(make-variable-buffer-local 'allout-bob-regexp)
560;;;_ = allout-header-subtraction
561(defvar allout-header-subtraction (1- (length allout-header-prefix))
562 "Allout-header prefix length to subtract when computing topic depth.")
563(make-variable-buffer-local 'allout-header-subtraction)
564;;;_ = allout-plain-bullets-string-len
565(defvar allout-plain-bullets-string-len (length allout-plain-bullets-string)
2265e017 566 "Length of `allout-plain-bullets-string', updated by `set-allout-regexp'.")
fd5359c6
MR
567(make-variable-buffer-local 'allout-plain-bullets-string-len)
568
569
570;;;_ X allout-reset-header-lead (header-lead)
571(defun allout-reset-header-lead (header-lead)
c567ac01 572 "*Reset the leading string used to identify topic headers."
1977b8f6 573 (interactive "sNew lead string: ")
fd5359c6
MR
574 (setq allout-header-prefix header-lead)
575 (setq allout-header-subtraction (1- (length allout-header-prefix)))
576 (set-allout-regexp))
577;;;_ X allout-lead-with-comment-string (header-lead)
578(defun allout-lead-with-comment-string (&optional header-lead)
19b84ba3
RS
579 "*Set the topic-header leading string to specified string.
580
581Useful when for encapsulating outline structure in programming
582language comments. Returns the leading string."
1977b8f6
RS
583
584 (interactive "P")
585 (if (not (stringp header-lead))
586 (setq header-lead (read-string
587 "String prefix for topic headers: ")))
fd5359c6
MR
588 (setq allout-reindent-bodies nil)
589 (allout-reset-header-lead header-lead)
1977b8f6 590 header-lead)
fd5359c6
MR
591;;;_ > allout-infer-header-lead ()
592(defun allout-infer-header-lead ()
593 "Determine appropriate `allout-header-prefix'.
19b84ba3
RS
594
595Works according to settings of:
596
8d118843 597 `comment-start'
fd5359c6
MR
598 `allout-header-prefix' (default)
599 `allout-use-mode-specific-leader'
600and `allout-mode-leaders'.
19b84ba3 601
fd5359c6 602Apply this via \(re)activation of `allout-mode', rather than
8d118843 603invoking it directly."
fd5359c6
MR
604 (let* ((use-leader (and (boundp 'allout-use-mode-specific-leader)
605 (if (or (stringp allout-use-mode-specific-leader)
606 (memq allout-use-mode-specific-leader
607 '(allout-mode-leaders
19b84ba3
RS
608 comment-start
609 t)))
fd5359c6 610 allout-use-mode-specific-leader
19b84ba3
RS
611 ;; Oops - garbled value, equate with effect of 't:
612 t)))
613 (leader
614 (cond
615 ((not use-leader) nil)
616 ;; Use the explicitly designated leader:
617 ((stringp use-leader) use-leader)
fd5359c6 618 (t (or (and (memq use-leader '(t allout-mode-leaders))
19b84ba3 619 ;; Get it from outline mode leaders?
fd5359c6
MR
620 (cdr (assq major-mode allout-mode-leaders)))
621 ;; ... didn't get from allout-mode-leaders...
19b84ba3
RS
622 (and (memq use-leader '(t comment-start))
623 comment-start
624 ;; Use comment-start, maybe tripled, and with
353e2ef2 625 ;; underscore:
19b84ba3
RS
626 (concat
627 (if (string= " "
628 (substring comment-start
629 (1- (length comment-start))))
630 ;; Use comment-start, sans trailing space:
631 (substring comment-start 0 -1)
632 (concat comment-start comment-start comment-start))
633 ;; ... and append underscore, whichever:
634 "_")))))))
635 (if (not leader)
636 nil
fd5359c6 637 (if (string= leader allout-header-prefix)
19b84ba3 638 nil ; no change, nothing to do.
fd5359c6
MR
639 (setq allout-header-prefix leader)
640 allout-header-prefix))))
641;;;_ > allout-infer-body-reindent ()
642(defun allout-infer-body-reindent ()
643 "Determine proper setting for `allout-reindent-bodies'.
8d118843 644
fd5359c6 645Depends on default setting of `allout-reindent-bodies' \(which see)
8d118843
RS
646and presence of setting for `comment-start', to tell whether the
647file is programming code."
fd5359c6 648 (if (and allout-reindent-bodies
8d118843 649 comment-start
fd5359c6
MR
650 (not (eq 'force allout-reindent-bodies)))
651 (setq allout-reindent-bodies nil)))
652;;;_ > set-allout-regexp ()
653(defun set-allout-regexp ()
19b84ba3
RS
654 "Generate proper topic-header regexp form for outline functions.
655
fd5359c6
MR
656Works with respect to `allout-plain-bullets-string' and
657`allout-distinctive-bullets-string'."
1977b8f6
RS
658
659 (interactive)
fd5359c6
MR
660 ;; Derive allout-bullets-string from user configured components:
661 (setq allout-bullets-string "")
662 (let ((strings (list 'allout-plain-bullets-string
663 'allout-distinctive-bullets-string
664 'allout-primary-bullet))
1977b8f6
RS
665 cur-string
666 cur-len
c567ac01 667 cur-char
1977b8f6
RS
668 cur-char-string
669 index
670 new-string)
671 (while strings
672 (setq new-string "") (setq index 0)
673 (setq cur-len (length (setq cur-string (symbol-value (car strings)))))
674 (while (< index cur-len)
675 (setq cur-char (aref cur-string index))
fd5359c6
MR
676 (setq allout-bullets-string
677 (concat allout-bullets-string
1977b8f6
RS
678 (cond
679 ; Single dash would denote a
680 ; sequence, repeated denotes
681 ; a dash:
682 ((eq cur-char ?-) "--")
683 ; literal close-square-bracket
684 ; doesn't work right in the
685 ; expr, exclude it:
686 ((eq cur-char ?\]) "")
687 (t (regexp-quote (char-to-string cur-char))))))
688 (setq index (1+ index)))
689 (setq strings (cdr strings)))
690 )
fd5359c6
MR
691 ;; Derive next for repeated use in allout-pending-bullet:
692 (setq allout-plain-bullets-string-len (length allout-plain-bullets-string))
693 (setq allout-header-subtraction (1- (length allout-header-prefix)))
694 ;; Produce the new allout-regexp:
695 (setq allout-regexp (concat "\\(\\"
696 allout-header-prefix
1977b8f6 697 "[ \t]*["
fd5359c6 698 allout-bullets-string
1977b8f6 699 "]\\)\\|\\"
fd5359c6 700 allout-primary-bullet
1977b8f6 701 "+\\|\^l"))
fd5359c6
MR
702 (setq allout-line-boundary-regexp
703 (concat "\\([\n\r]\\)\\(" allout-regexp "\\)"))
704 (setq allout-bob-regexp
705 (concat "\\(\\`\\)\\(" allout-regexp "\\)"))
1977b8f6 706 )
9179616f 707;;;_ : Key bindings
fd5359c6
MR
708;;;_ = allout-mode-map
709(defvar allout-mode-map nil "Keybindings for (allout) outline minor mode.")
710;;;_ > produce-allout-mode-map (keymap-alist &optional base-map)
711(defun produce-allout-mode-map (keymap-list &optional base-map)
e126900f 712 "Produce keymap for use as allout-mode-map, from KEYMAP-LIST.
19b84ba3
RS
713
714Built on top of optional BASE-MAP, or empty sparse map if none specified.
fd5359c6 715See doc string for allout-keybindings-list for format of binding list."
9179616f 716 (let ((map (or base-map (make-sparse-keymap)))
fd5359c6 717 (pref (list allout-command-prefix)))
9179616f
DL
718 (mapcar (function
719 (lambda (cell)
720 (let ((add-pref (null (cdr (cdr cell))))
721 (key-suff (list (car cell))))
722 (apply 'define-key
723 (list map
724 (apply 'concat (if add-pref
725 (append pref key-suff)
726 key-suff))
727 (car (cdr cell)))))))
19b84ba3
RS
728 keymap-list)
729 map))
95c12694 730
9179616f 731;;;_ : Menu bar
95c12694
RS
732(defvar allout-mode-exposure-menu)
733(defvar allout-mode-editing-menu)
734(defvar allout-mode-navigation-menu)
735(defvar allout-mode-misc-menu)
fd5359c6 736(defun produce-allout-mode-menubar-entries ()
9179616f 737 (require 'easymenu)
fd5359c6
MR
738 (easy-menu-define allout-mode-exposure-menu
739 allout-mode-map
9179616f
DL
740 "Allout outline exposure menu."
741 '("Exposure"
fd5359c6
MR
742 ["Show Entry" allout-show-current-entry t]
743 ["Show Children" allout-show-children t]
744 ["Show Subtree" allout-show-current-subtree t]
745 ["Hide Subtree" allout-hide-current-subtree t]
746 ["Hide Leaves" allout-hide-current-leaves t]
9179616f 747 "----"
fd5359c6
MR
748 ["Show All" allout-show-all t]))
749 (easy-menu-define allout-mode-editing-menu
750 allout-mode-map
9179616f
DL
751 "Allout outline editing menu."
752 '("Headings"
fd5359c6
MR
753 ["Open Sibling" allout-open-sibtopic t]
754 ["Open Subtopic" allout-open-subtopic t]
755 ["Open Supertopic" allout-open-supertopic t]
9179616f 756 "----"
fd5359c6
MR
757 ["Shift Topic In" allout-shift-in t]
758 ["Shift Topic Out" allout-shift-out t]
759 ["Rebullet Topic" allout-rebullet-topic t]
760 ["Rebullet Heading" allout-rebullet-current-heading t]
761 ["Number Siblings" allout-number-siblings t]))
762 (easy-menu-define allout-mode-navigation-menu
763 allout-mode-map
9179616f
DL
764 "Allout outline navigation menu."
765 '("Navigation"
fd5359c6 766 ["Next Visible Heading" allout-next-visible-heading t]
9179616f 767 ["Previous Visible Heading"
fd5359c6 768 allout-previous-visible-heading t]
9179616f 769 "----"
fd5359c6
MR
770 ["Up Level" allout-up-current-level t]
771 ["Forward Current Level" allout-forward-current-level t]
9179616f 772 ["Backward Current Level"
fd5359c6 773 allout-backward-current-level t]
9179616f
DL
774 "----"
775 ["Beginning of Entry"
fd5359c6
MR
776 allout-beginning-of-current-entry t]
777 ["End of Entry" allout-end-of-current-entry t]
778 ["End of Subtree" allout-end-of-current-subtree t]))
779 (easy-menu-define allout-mode-misc-menu
780 allout-mode-map
9179616f
DL
781 "Allout outlines miscellaneous bindings."
782 '("Misc"
fd5359c6 783 ["Version" allout-version t]
9179616f 784 "----"
fd5359c6 785 ["Duplicate Exposed" allout-copy-exposed-to-buffer t]
9179616f 786 ["Duplicate Exposed, numbered"
71296446 787 allout-flatten-exposed-to-buffer t]
9179616f 788 ["Duplicate Exposed, indented"
71296446 789 allout-indented-exposed-to-buffer t]
9179616f 790 "----"
fd5359c6
MR
791 ["Set Header Lead" allout-reset-header-lead t]
792 ["Set New Exposure" allout-expose-topic t])))
9179616f 793;;;_ : Mode-Specific Variable Maintenance Utilities
fd5359c6
MR
794;;;_ = allout-mode-prior-settings
795(defvar allout-mode-prior-settings nil
aad94676 796 "Internal `allout-mode' use; settings to be resumed on mode deactivation.")
fd5359c6
MR
797(make-variable-buffer-local 'allout-mode-prior-settings)
798;;;_ > allout-resumptions (name &optional value)
799(defun allout-resumptions (name &optional value)
1977b8f6 800
2265e017 801 "Registers or resumes settings over `allout-mode' activation/deactivation.
19b84ba3
RS
802
803First arg is NAME of variable affected. Optional second arg is list
fd5359c6 804containing allout-mode-specific VALUE to be imposed on named
19b84ba3
RS
805variable, and to be registered. (It's a list so you can specify
806registrations of null values.) If no value is specified, the
807registered value is returned (encapsulated in the list, so the caller
808can distinguish nil vs no value), and the registration is popped
c567ac01 809from the list."
1977b8f6 810
fd5359c6 811 (let ((on-list (assq name allout-mode-prior-settings))
353e2ef2 812 prior-capsule ; By `capsule' i mean a list
1977b8f6
RS
813 ; containing a value, so we can
814 ; distinguish nil from no value.
815 )
816
817 (if value
818
819 ;; Registering:
820 (progn
821 (if on-list
822 nil ; Already preserved prior value - don't mess with it.
823 ;; Register the old value, or nil if previously unbound:
fd5359c6 824 (setq allout-mode-prior-settings
1977b8f6
RS
825 (cons (list name
826 (if (boundp name) (list (symbol-value name))))
fd5359c6 827 allout-mode-prior-settings)))
c567ac01
RS
828 ; And impose the new value, locally:
829 (progn (make-local-variable name)
830 (set name (car value))))
1977b8f6
RS
831
832 ;; Relinquishing:
833 (if (not on-list)
834
835 ;; Oops, not registered - leave it be:
836 nil
837
838 ;; Some registration:
839 ; reestablish it:
840 (setq prior-capsule (car (cdr on-list)))
841 (if prior-capsule
842 (set name (car prior-capsule)) ; Some prior value - reestablish it.
843 (makunbound name)) ; Previously unbound - demolish var.
844 ; Remove registration:
845 (let (rebuild)
fd5359c6
MR
846 (while allout-mode-prior-settings
847 (if (not (eq (car allout-mode-prior-settings)
1977b8f6
RS
848 on-list))
849 (setq rebuild
fd5359c6 850 (cons (car allout-mode-prior-settings)
1977b8f6 851 rebuild)))
fd5359c6
MR
852 (setq allout-mode-prior-settings
853 (cdr allout-mode-prior-settings)))
854 (setq allout-mode-prior-settings rebuild)))))
1977b8f6 855 )
9179616f 856;;;_ : Mode-specific incidentals
fd5359c6
MR
857;;;_ = allout-during-write-cue nil
858(defvar allout-during-write-cue nil
19b84ba3 859 "Used to inhibit outline change-protection during file write.
c567ac01 860
fd5359c6
MR
861See also `allout-post-command-business', `allout-write-file-hook',
862`allout-before-change-protect', and `allout-post-command-business'
19b84ba3 863functions.")
fd5359c6
MR
864;;;_ = allout-pre-was-isearching nil
865(defvar allout-pre-was-isearching nil
9179616f 866 "Cue for isearch-dynamic-exposure mechanism, implemented in
fd5359c6
MR
867allout-pre- and -post-command-hooks.")
868(make-variable-buffer-local 'allout-pre-was-isearching)
869;;;_ = allout-isearch-prior-pos nil
870(defvar allout-isearch-prior-pos nil
871 "Cue for isearch-dynamic-exposure tracking, used by allout-isearch-expose.")
872(make-variable-buffer-local 'allout-isearch-prior-pos)
873;;;_ = allout-isearch-did-quit
874(defvar allout-isearch-did-quit nil
9179616f
DL
875 "Distinguishes isearch conclusion and cancellation.
876
2265e017
MR
877Maintained by `allout-isearch-abort' \(which is wrapped around the real
878isearch-abort), and monitored by `allout-isearch-expose' for action.")
fd5359c6
MR
879(make-variable-buffer-local 'allout-isearch-did-quit)
880;;;_ = allout-override-protect nil
881(defvar allout-override-protect nil
2265e017 882 "Used in `allout-mode' for regulate of concealed-text protection mechanism.
19b84ba3
RS
883
884Allout outline mode regulates alteration of concealed text to protect
a0776d6b 885against inadvertent, unnoticed changes. This is for use by specific,
19b84ba3
RS
886native outline functions to temporarily override that protection.
887It's automatically reset to nil after every buffer modification.")
fd5359c6
MR
888(make-variable-buffer-local 'allout-override-protect)
889;;;_ > allout-unprotected (expr)
890(defmacro allout-unprotected (expr)
24190da5 891 "Evaluate EXPRESSION with `allout-override-protect' let-bound t."
fd5359c6 892 `(let ((allout-override-protect t))
9179616f 893 ,expr))
fd5359c6
MR
894;;;_ = allout-undo-aggregation
895(defvar allout-undo-aggregation 30
c567ac01 896 "Amount of successive self-insert actions to bunch together per undo.
19b84ba3 897
c567ac01 898This is purely a kludge variable, regulating the compensation for a bug in
9179616f 899the way that before-change-functions and undo interact.")
fd5359c6 900(make-variable-buffer-local 'allout-undo-aggregation)
19b84ba3 901;;;_ = file-var-bug hack
fd5359c6 902(defvar allout-v18/19-file-var-hack nil
c567ac01 903 "Horrible hack used to prevent invalid multiple triggering of outline
2265e017 904mode from prop-line file-var activation. Used by `allout-mode' function
c567ac01 905to track repeats.")
fd5359c6
MR
906;;;_ > allout-write-file-hook ()
907(defun allout-write-file-hook ()
95c12694 908 "In `allout-mode', run as a `write-contents-functions' activity.
19b84ba3 909
aad94676 910Currently just sets `allout-during-write-cue', so outline change-protection
353e2ef2 911knows to keep inactive during file write."
fd5359c6 912 (setq allout-during-write-cue t)
19b84ba3
RS
913 nil)
914
915;;;_ #2 Mode activation
fd5359c6
MR
916;;;_ = allout-mode
917(defvar allout-mode () "Allout outline mode minor-mode flag.")
918(make-variable-buffer-local 'allout-mode)
919;;;_ > allout-mode-p ()
920(defmacro allout-mode-p ()
2265e017 921 "Return t if `allout-mode' is active in current buffer."
fd5359c6
MR
922 'allout-mode)
923;;;_ = allout-explicitly-deactivated
924(defvar allout-explicitly-deactivated nil
aad94676 925 "Non-nil if `allout-mode' was last deliberately deactivated.
2265e017 926So `allout-post-command-business' should not reactivate it...")
fd5359c6
MR
927(make-variable-buffer-local 'allout-explicitly-deactivated)
928;;;_ > allout-init (&optional mode)
aad94676 929;;;###autoload
fd5359c6 930(defun allout-init (&optional mode)
2265e017 931 "Prime `allout-mode' to enable/disable auto-activation, wrt `allout-layout'.
19b84ba3 932
8d118843 933MODE is one of the following symbols:
19b84ba3 934
353e2ef2
KH
935 - nil \(or no argument) deactivate auto-activation/layout;
936 - `activate', enable auto-activation only;
937 - `ask', enable auto-activation, and enable auto-layout but with
a0776d6b 938 confirmation for layout operation solicited from user each time;
353e2ef2 939 - `report', just report and return the current auto-activation state;
8d118843
RS
940 - anything else \(eg, t) for auto-activation and auto-layout, without
941 any confirmation check.
19b84ba3 942
e126900f 943Use this function to setup your Emacs session for automatic activation
19b84ba3 944of allout outline mode, contingent to the buffer-specific setting of
fd5359c6
MR
945the `allout-layout' variable. (See `allout-layout' and
946`allout-expose-topic' docstrings for more details on auto layout).
19b84ba3 947
aad94676 948`allout-init' works by setting up (or removing)
95c12694 949`allout-find-file-hook' in `find-file-hook', and giving
aad94676 950`allout-auto-activation' a suitable setting.
19b84ba3 951
e126900f
JB
952To prime your Emacs session for full auto-outline operation, include
953the following two lines in your Emacs init file:
19b84ba3
RS
954
955\(require 'allout)
fd5359c6 956\(allout-init t)"
19b84ba3 957
65970d64
RS
958 (interactive
959 (let ((m (completing-read
960 (concat "Select outline auto setup mode "
961 "(empty for report, ? for options) ")
962 '(("nil")("full")("activate")("deactivate")
963 ("ask") ("report") (""))
964 nil
965 t)))
966 (if (string= m "") 'report
967 (intern-soft m))))
8d118843
RS
968 (let
969 ;; convenience aliases, for consistent ref to respective vars:
fd5359c6
MR
970 ((hook 'allout-find-file-hook)
971 (curr-mode 'allout-auto-activation))
353e2ef2 972
8d118843 973 (cond ((not mode)
95c12694 974 (setq find-file-hook (delq hook find-file-hook))
8d118843
RS
975 (if (interactive-p)
976 (message "Allout outline mode auto-activation inhibited.")))
977 ((eq mode 'report)
95c12694 978 (if (memq hook find-file-hook)
9471aeec
MR
979 ;; Just punt and use the reports from each of the modes:
980 (allout-init (symbol-value curr-mode))
981 (allout-init nil)
982 (message "Allout outline mode auto-activation inhibited.")))
95c12694 983 (t (add-hook 'find-file-hook hook)
353e2ef2 984 (set curr-mode ; `set', not `setq'!
8d118843
RS
985 (cond ((eq mode 'activate)
986 (message
987 "Outline mode auto-activation enabled.")
988 'activate)
989 ((eq mode 'report)
990 ;; Return the current mode setting:
fd5359c6 991 (allout-init mode))
8d118843
RS
992 ((eq mode 'ask)
993 (message
994 (concat "Outline mode auto-activation and "
995 "-layout \(upon confirmation) enabled."))
996 'ask)
997 ((message
998 "Outline mode auto-activation and -layout enabled.")
999 'full)))))))
71296446 1000
fd5359c6
MR
1001;;;_ > allout-setup-menubar ()
1002(defun allout-setup-menubar ()
aad94676 1003 "Populate the current buffer's menubar with `allout-mode' stuff."
fd5359c6
MR
1004 (let ((menus (list allout-mode-exposure-menu
1005 allout-mode-editing-menu
1006 allout-mode-navigation-menu
1007 allout-mode-misc-menu))
9179616f
DL
1008 cur)
1009 (while menus
1010 (setq cur (car menus)
1011 menus (cdr menus))
1012 (easy-menu-add cur))))
fd5359c6 1013;;;_ > allout-mode (&optional toggle)
19b84ba3 1014;;;_ : Defun:
fd5359c6 1015(defun allout-mode (&optional toggle)
c567ac01 1016;;;_ . Doc string:
19b84ba3
RS
1017 "Toggle minor mode for controlling exposure and editing of text outlines.
1018
9179616f
DL
1019Optional arg forces mode to re-initialize iff arg is positive num or
1020symbol. Allout outline mode always runs as a minor mode.
19b84ba3 1021
aad94676 1022Allout outline mode provides extensive outline oriented formatting and
9179616f
DL
1023manipulation. It enables structural editing of outlines, as well as
1024navigation and exposure. It also is specifically aimed at
1025accommodating syntax-sensitive text like programming languages. \(For
1026an example, see the allout code itself, which is organized as an allout
1027outline.)
19b84ba3 1028
9179616f 1029In addition to outline navigation and exposure, allout includes:
19b84ba3 1030
9179616f
DL
1031 - topic-oriented repositioning, cut, and paste
1032 - integral outline exposure-layout
1033 - incremental search with dynamic exposure and reconcealment of hidden text
1034 - automatic topic-number maintenance
1035 - \"Hot-spot\" operation, for single-keystroke maneuvering and
fd5359c6 1036 exposure control. \(See the allout-mode docstring.)
9179616f
DL
1037
1038and many other features.
19b84ba3
RS
1039
1040Below is a description of the bindings, and then explanation of
2265e017 1041special `allout-mode' features and terminology. See also the outline
9179616f 1042menubar additions for quick reference to many of the features, and see
f134d28b 1043the docstring of the function `allout-init' for instructions on
e126900f 1044priming your Emacs session for automatic activation of `allout-mode'.
9179616f 1045
19b84ba3 1046
fd5359c6
MR
1047The bindings are dictated by the `allout-keybindings-list' and
1048`allout-command-prefix' variables.
19b84ba3
RS
1049
1050 Navigation: Exposure Control:
1051 ---------- ----------------
fd5359c6
MR
1052C-c C-n allout-next-visible-heading | C-c C-h allout-hide-current-subtree
1053C-c C-p allout-previous-visible-heading | C-c C-i allout-show-children
1054C-c C-u allout-up-current-level | C-c C-s allout-show-current-subtree
1055C-c C-f allout-forward-current-level | C-c C-o allout-show-current-entry
1056C-c C-b allout-backward-current-level | ^U C-c C-s allout-show-all
1057C-c C-e allout-end-of-current-entry | allout-hide-current-leaves
1058C-c C-a allout-beginning-of-current-entry, alternately, goes to hot-spot
19b84ba3
RS
1059
1060 Topic Header Production:
1061 -----------------------
fd5359c6
MR
1062C-c<SP> allout-open-sibtopic Create a new sibling after current topic.
1063C-c . allout-open-subtopic ... an offspring of current topic.
1064C-c , allout-open-supertopic ... a sibling of the current topic's parent.
19b84ba3
RS
1065
1066 Topic Level and Prefix Adjustment:
1067 ---------------------------------
fd5359c6
MR
1068C-c > allout-shift-in Shift current topic and all offspring deeper.
1069C-c < allout-shift-out ... less deep.
1070C-c<CR> allout-rebullet-topic Reconcile bullets of topic and its offspring
19b84ba3
RS
1071 - distinctive bullets are not changed, others
1072 alternated according to nesting depth.
b5ea1dfd 1073C-c * allout-rebullet-current-heading Prompt for alternate bullet for
19b84ba3 1074 current topic.
fd5359c6 1075C-c # allout-number-siblings Number bullets of topic and siblings - the
1977b8f6
RS
1076 offspring are not affected. With repeat
1077 count, revoke numbering.
1078
19b84ba3
RS
1079 Topic-oriented Killing and Yanking:
1080 ----------------------------------
fd5359c6
MR
1081C-c C-k allout-kill-topic Kill current topic, including offspring.
1082C-k allout-kill-line Like kill-line, but reconciles numbering, etc.
1083C-y allout-yank Yank, adjusting depth of yanked topic to
1977b8f6 1084 depth of heading if yanking into bare topic
19b84ba3 1085 heading (ie, prefix sans text).
fd5359c6 1086M-y allout-yank-pop Is to allout-yank as yank-pop is to yank
1977b8f6 1087
19b84ba3
RS
1088 Misc commands:
1089 -------------
19b84ba3
RS
1090M-x outlineify-sticky Activate outline mode for current buffer,
1091 and establish a default file-var setting
fd5359c6
MR
1092 for `allout-layout'.
1093C-c C-SPC allout-mark-topic
1094C-c = c allout-copy-exposed-to-buffer
9179616f
DL
1095 Duplicate outline, sans concealed text, to
1096 buffer with name derived from derived from
1097 that of current buffer - \"*XXX exposed*\".
fd5359c6 1098C-c = p allout-flatten-exposed-to-buffer
9179616f
DL
1099 Like above 'copy-exposed', but convert topic
1100 prefixes to section.subsection... numeric
1101 format.
e126900f 1102ESC ESC (allout-init t) Setup Emacs session for outline mode
19b84ba3 1103 auto-activation.
1977b8f6 1104
19b84ba3 1105 HOT-SPOT Operation
c567ac01 1106
19b84ba3
RS
1107Hot-spot operation provides a means for easy, single-keystroke outline
1108navigation and exposure control.
c567ac01 1109
fd5359c6 1110\\<allout-mode-map>
19b84ba3
RS
1111When the text cursor is positioned directly on the bullet character of
1112a topic, regular characters (a to z) invoke the commands of the
fd5359c6 1113corresponding allout-mode keymap control chars. For example, \"f\"
19b84ba3 1114would invoke the command typically bound to \"C-c C-f\"
fd5359c6 1115\(\\[allout-forward-current-level] `allout-forward-current-level').
19b84ba3
RS
1116
1117Thus, by positioning the cursor on a topic bullet, you can execute
c567ac01 1118the outline navigation and manipulation commands with a single
19b84ba3
RS
1119keystroke. Non-literal chars never get this special translation, so
1120you can use them to get away from the hot-spot, and back to normal
1121operation.
c567ac01 1122
fd5359c6 1123Note that the command `allout-beginning-of-current-entry' \(\\[allout-beginning-of-current-entry]\)
c567ac01 1124will move to the hot-spot when the cursor is already located at the
fd5359c6 1125beginning of the current entry, so you can simply hit \\[allout-beginning-of-current-entry]
c567ac01 1126twice in a row to get to the hot-spot.
1977b8f6 1127
19b84ba3 1128 Terminology
1977b8f6 1129
c567ac01
RS
1130Topic hierarchy constituents - TOPICS and SUBTOPICS:
1131
e126900f 1132TOPIC: A basic, coherent component of an Emacs outline. It can
c567ac01
RS
1133 contain other topics, and it can be subsumed by other topics,
1134CURRENT topic:
1135 The visible topic most immediately containing the cursor.
19b84ba3
RS
1136DEPTH: The degree of nesting of a topic; it increases with
1137 containment. Also called the:
c567ac01
RS
1138LEVEL: The same as DEPTH.
1139
1140ANCESTORS:
1141 The topics that contain a topic.
1142PARENT: A topic's immediate ancestor. It has a depth one less than
1143 the topic.
1144OFFSPRING:
19b84ba3
RS
1145 The topics contained by a topic;
1146SUBTOPIC:
1147 An immediate offspring of a topic;
c567ac01
RS
1148CHILDREN:
1149 The immediate offspring of a topic.
1150SIBLINGS:
19b84ba3 1151 Topics having the same parent and depth.
353e2ef2 1152
c567ac01
RS
1153Topic text constituents:
1154
1155HEADER: The first line of a topic, include the topic PREFIX and header
353e2ef2 1156 text.
c567ac01
RS
1157PREFIX: The leading text of a topic which which distinguishes it from
1158 normal text. It has a strict form, which consists of a
1159 prefix-lead string, padding, and a bullet. The bullet may be
1160 followed by a number, indicating the ordinal number of the
1161 topic among its siblings, a space, and then the header text.
1162
1163 The relative length of the PREFIX determines the nesting depth
1164 of the topic.
1165PREFIX-LEAD:
353e2ef2 1166 The string at the beginning of a topic prefix, normally a `.'.
c567ac01 1167 It can be customized by changing the setting of
2265e017 1168 `allout-header-prefix' and then reinitializing `allout-mode'.
c567ac01
RS
1169
1170 By setting the prefix-lead to the comment-string of a
aad94676 1171 programming language, you can embed outline structuring in
c567ac01 1172 program code without interfering with the language processing
fd5359c6 1173 of that code. See `allout-use-mode-specific-leader'
19b84ba3 1174 docstring for more detail.
c567ac01
RS
1175PREFIX-PADDING:
1176 Spaces or asterisks which separate the prefix-lead and the
1177 bullet, according to the depth of the topic.
1178BULLET: A character at the end of the topic prefix, it must be one of
fd5359c6
MR
1179 the characters listed on `allout-plain-bullets-string' or
1180 `allout-distinctive-bullets-string'. (See the documentation
c567ac01
RS
1181 for these variables for more details.) The default choice of
1182 bullet when generating varies in a cycle with the depth of the
1183 topic.
1184ENTRY: The text contained in a topic before any offspring.
1185BODY: Same as ENTRY.
1186
1187
1188EXPOSURE:
1189 The state of a topic which determines the on-screen visibility
353e2ef2 1190 of its offspring and contained text.
c567ac01
RS
1191CONCEALED:
1192 Topics and entry text whose display is inhibited. Contiguous
353e2ef2
KH
1193 units of concealed text is represented by `...' ellipses.
1194 (Ref the `selective-display' var.)
c567ac01
RS
1195
1196 Concealed topics are effectively collapsed within an ancestor.
1197CLOSED: A topic whose immediate offspring and body-text is concealed.
353e2ef2 1198OPEN: A topic that is not closed, though its offspring or body may be."
c567ac01 1199;;;_ . Code
1977b8f6
RS
1200 (interactive "P")
1201
c567ac01 1202 (let* ((active (and (not (equal major-mode 'outline))
fd5359c6 1203 (allout-mode-p)))
353e2ef2 1204 ; Massage universal-arg `toggle' val:
c567ac01 1205 (toggle (and toggle
19b84ba3
RS
1206 (or (and (listp toggle)(car toggle))
1207 toggle)))
a0776d6b 1208 ; Activation specifically demanded?
c567ac01 1209 (explicit-activation (or
19b84ba3
RS
1210 ;;
1211 (and toggle
1212 (or (symbolp toggle)
1213 (and (natnump toggle)
1214 (not (zerop toggle)))))))
fd5359c6
MR
1215 ;; allout-mode already called once during this complex command?
1216 (same-complex-command (eq allout-v18/19-file-var-hack
19b84ba3
RS
1217 (car command-history)))
1218 do-layout
1219 )
c567ac01 1220
19b84ba3 1221 ; See comments below re v19.18,.19 bug.
fd5359c6 1222 (setq allout-v18/19-file-var-hack (car command-history))
c567ac01 1223
1977b8f6
RS
1224 (cond
1225
19b84ba3 1226 ;; Provision for v19.18, 19.19 bug -
c567ac01
RS
1227 ;; Emacs v 19.18, 19.19 file-var code invokes prop-line-designated
1228 ;; modes twice when file is visited. We have to avoid toggling mode
1229 ;; off on second invocation, so we detect it as best we can, and
1230 ;; skip everything.
1231 ((and same-complex-command ; Still in same complex command
aad94676 1232 ; as last time `allout-mode' invoked.
19b84ba3
RS
1233 active ; Already activated.
1234 (not explicit-activation) ; Prop-line file-vars don't have args.
1235 (string-match "^19.1[89]" ; Bug only known to be in v19.18 and
1236 emacs-version)); 19.19.
c567ac01 1237 t)
353e2ef2 1238
19b84ba3 1239 ;; Deactivation:
c567ac01 1240 ((and (not explicit-activation)
19b84ba3
RS
1241 (or active toggle))
1242 ; Activation not explicitly
1243 ; requested, and either in
1244 ; active state or *de*activation
1245 ; specifically requested:
fd5359c6 1246 (setq allout-explicitly-deactivated t)
c567ac01 1247
fd5359c6 1248 (if allout-old-style-prefixes
c567ac01 1249 (progn
fd5359c6
MR
1250 (allout-resumptions 'allout-primary-bullet)
1251 (allout-resumptions 'allout-old-style-prefixes)))
1252 (allout-resumptions 'selective-display)
9179616f 1253 (if (and (boundp 'before-change-functions) before-change-functions)
fd5359c6 1254 (allout-resumptions 'before-change-functions))
95c12694
RS
1255 (setq write-contents-functions
1256 (delq 'allout-write-file-hook
1257 write-contents-functions))
fd5359c6
MR
1258 (allout-resumptions 'paragraph-start)
1259 (allout-resumptions 'paragraph-separate)
1260 (allout-resumptions (if (string-match "^18" emacs-version)
19b84ba3
RS
1261 'auto-fill-hook
1262 'auto-fill-function))
fd5359c6
MR
1263 (allout-resumptions 'allout-former-auto-filler)
1264 (setq allout-mode nil))
1977b8f6 1265
19b84ba3 1266 ;; Activation:
1977b8f6 1267 ((not active)
fd5359c6
MR
1268 (setq allout-explicitly-deactivated nil)
1269 (if allout-old-style-prefixes
c567ac01 1270 (progn ; Inhibit all the fancy formatting:
fd5359c6
MR
1271 (allout-resumptions 'allout-primary-bullet '("*"))
1272 (allout-resumptions 'allout-old-style-prefixes '(()))))
19b84ba3 1273
fd5359c6
MR
1274 (allout-infer-header-lead)
1275 (allout-infer-body-reindent)
19b84ba3 1276
fd5359c6 1277 (set-allout-regexp)
19b84ba3
RS
1278
1279 ; Produce map from current version
fd5359c6 1280 ; of allout-keybindings-list:
c567ac01
RS
1281 (if (boundp 'minor-mode-map-alist)
1282
1283 (progn ; V19, and maybe lucid and
19b84ba3 1284 ; epoch, minor-mode key bindings:
fd5359c6
MR
1285 (setq allout-mode-map
1286 (produce-allout-mode-map allout-keybindings-list))
1287 (produce-allout-mode-menubar-entries)
1288 (fset 'allout-mode-map allout-mode-map)
19b84ba3
RS
1289 ; Include on minor-mode-map-alist,
1290 ; if not already there:
fd5359c6 1291 (if (not (member '(allout-mode . allout-mode-map)
19b84ba3
RS
1292 minor-mode-map-alist))
1293 (setq minor-mode-map-alist
fd5359c6 1294 (cons '(allout-mode . allout-mode-map)
19b84ba3
RS
1295 minor-mode-map-alist))))
1296
19b84ba3 1297 ; and add them:
fd5359c6 1298 (use-local-map (produce-allout-mode-map allout-keybindings-list
19b84ba3 1299 (current-local-map)))
c567ac01 1300 )
353e2ef2 1301
19b84ba3 1302 ; selective-display is the
e126900f 1303 ; Emacs conditional exposure
19b84ba3 1304 ; mechanism:
fd5359c6
MR
1305 (allout-resumptions 'selective-display '(t))
1306 (if allout-inhibit-protection
c567ac01 1307 t
fd5359c6
MR
1308 (allout-resumptions 'before-change-functions
1309 '(allout-before-change-protect)))
1310 (add-hook 'pre-command-hook 'allout-pre-command-business)
1311 (add-hook 'post-command-hook 'allout-post-command-business)
19b84ba3
RS
1312 ; Temporarily set by any outline
1313 ; functions that can be trusted to
1314 ; deal properly with concealed text.
95c12694 1315 (add-hook 'write-contents-functions 'allout-write-file-hook)
19b84ba3
RS
1316 ; Custom auto-fill func, to support
1317 ; respect for topic headline,
1318 ; hanging-indents, etc:
c567ac01 1319 (let* ((fill-func-var (if (string-match "^18" emacs-version)
19b84ba3
RS
1320 'auto-fill-hook
1321 'auto-fill-function))
1322 (fill-func (symbol-value fill-func-var)))
fd5359c6
MR
1323 ;; Register prevailing fill func for use by allout-auto-fill:
1324 (allout-resumptions 'allout-former-auto-filler (list fill-func))
1325 ;; Register allout-auto-fill to be used if filling is active:
1326 (allout-resumptions fill-func-var '(allout-auto-fill)))
c567ac01 1327 ;; Paragraphs are broken by topic headlines.
1977b8f6 1328 (make-local-variable 'paragraph-start)
fd5359c6 1329 (allout-resumptions 'paragraph-start
9179616f 1330 (list (concat paragraph-start "\\|^\\("
fd5359c6 1331 allout-regexp "\\)")))
1977b8f6 1332 (make-local-variable 'paragraph-separate)
fd5359c6 1333 (allout-resumptions 'paragraph-separate
9179616f 1334 (list (concat paragraph-separate "\\|^\\("
fd5359c6 1335 allout-regexp "\\)")))
c567ac01 1336
fd5359c6 1337 (or (assq 'allout-mode minor-mode-alist)
c567ac01 1338 (setq minor-mode-alist
aad94676 1339 (cons '(allout-mode " Allout") minor-mode-alist)))
19b84ba3 1340
fd5359c6 1341 (allout-setup-menubar)
9179616f 1342
fd5359c6 1343 (if allout-layout
19b84ba3 1344 (setq do-layout t))
1977b8f6 1345
fd5359c6
MR
1346 (if (and allout-isearch-dynamic-expose
1347 (not (fboundp 'allout-real-isearch-abort)))
1348 (allout-enwrap-isearch))
19b84ba3 1349
fd5359c6
MR
1350 (run-hooks 'allout-mode-hook)
1351 (setq allout-mode t))
19b84ba3
RS
1352
1353 ;; Reactivation:
8d118843 1354 ((setq do-layout t)
fd5359c6 1355 (allout-infer-body-reindent))
c567ac01 1356 ) ; cond
19b84ba3
RS
1357
1358 (if (and do-layout
fd5359c6
MR
1359 allout-auto-activation
1360 (listp allout-layout)
1361 (and (not (eq allout-auto-activation 'activate))
1362 (if (eq allout-auto-activation 'ask)
19b84ba3
RS
1363 (if (y-or-n-p (format "Expose %s with layout '%s'? "
1364 (buffer-name)
fd5359c6 1365 allout-layout))
19b84ba3 1366 t
8d118843 1367 (message "Skipped %s layout." (buffer-name))
19b84ba3
RS
1368 nil)
1369 t)))
1370 (save-excursion
1371 (message "Adjusting '%s' exposure..." (buffer-name))
1372 (goto-char 0)
fd5359c6 1373 (allout-this-or-next-heading)
8d118843 1374 (condition-case err
353e2ef2 1375 (progn
fd5359c6 1376 (apply 'allout-expose-topic (list allout-layout))
8d118843
RS
1377 (message "Adjusting '%s' exposure... done." (buffer-name)))
1378 ;; Problem applying exposure - notify user, but don't
1379 ;; interrupt, eg, file visit:
1380 (error (message "%s" (car (cdr err)))
1381 (sit-for 1)))))
fd5359c6 1382 allout-mode
c567ac01 1383 ) ; let*
19b84ba3 1384 ) ; defun
fd5359c6 1385;;;_ > allout-minor-mode
9179616f 1386;;; XXX released verion doesn't do this?
fd5359c6 1387(defalias 'allout-minor-mode 'allout-mode)
1977b8f6 1388
fd5359c6 1389;;;_ #3 Internal Position State-Tracking - "allout-recent-*" funcs
19b84ba3 1390;;; All the basic outline functions that directly do string matches to
1977b8f6 1391;;; evaluate heading prefix location set the variables
fd5359c6
MR
1392;;; `allout-recent-prefix-beginning' and `allout-recent-prefix-end'
1393;;; when successful. Functions starting with `allout-recent-' all
19b84ba3
RS
1394;;; use this state, providing the means to avoid redundant searches
1395;;; for just-established data. This optimization can provide
1396;;; significant speed improvement, but it must be employed carefully.
fd5359c6
MR
1397;;;_ = allout-recent-prefix-beginning
1398(defvar allout-recent-prefix-beginning 0
c567ac01 1399 "Buffer point of the start of the last topic prefix encountered.")
fd5359c6
MR
1400(make-variable-buffer-local 'allout-recent-prefix-beginning)
1401;;;_ = allout-recent-prefix-end
1402(defvar allout-recent-prefix-end 0
c567ac01 1403 "Buffer point of the end of the last topic prefix encountered.")
fd5359c6
MR
1404(make-variable-buffer-local 'allout-recent-prefix-end)
1405;;;_ = allout-recent-end-of-subtree
1406(defvar allout-recent-end-of-subtree 0
2265e017 1407 "Buffer point last returned by `allout-end-of-current-subtree'.")
fd5359c6
MR
1408(make-variable-buffer-local 'allout-recent-end-of-subtree)
1409;;;_ > allout-prefix-data (beg end)
1410(defmacro allout-prefix-data (beg end)
1411 "Register allout-prefix state data - BEGINNING and END of prefix.
1412
1413For reference by `allout-recent' funcs. Returns BEGINNING."
1414 `(setq allout-recent-prefix-end ,end
1415 allout-recent-prefix-beginning ,beg))
1416;;;_ > allout-recent-depth ()
1417(defmacro allout-recent-depth ()
19b84ba3 1418 "Return depth of last heading encountered by an outline maneuvering function.
c567ac01
RS
1419
1420All outline functions which directly do string matches to assess
2265e017
MR
1421headings set the variables `allout-recent-prefix-beginning' and
1422`allout-recent-prefix-end' if successful. This function uses those settings
c567ac01
RS
1423to return the current depth."
1424
fd5359c6
MR
1425 '(max 1 (- allout-recent-prefix-end
1426 allout-recent-prefix-beginning
1427 allout-header-subtraction)))
1428;;;_ > allout-recent-prefix ()
1429(defmacro allout-recent-prefix ()
2265e017 1430 "Like `allout-recent-depth', but returns text of last encountered prefix.
c567ac01
RS
1431
1432All outline functions which directly do string matches to assess
2265e017
MR
1433headings set the variables `allout-recent-prefix-beginning' and
1434`allout-recent-prefix-end' if successful. This function uses those settings
c567ac01 1435to return the current depth."
fd5359c6
MR
1436 '(buffer-substring allout-recent-prefix-beginning
1437 allout-recent-prefix-end))
1438;;;_ > allout-recent-bullet ()
1439(defmacro allout-recent-bullet ()
1440 "Like allout-recent-prefix, but returns bullet of last encountered prefix.
c567ac01
RS
1441
1442All outline functions which directly do string matches to assess
2265e017
MR
1443headings set the variables `allout-recent-prefix-beginning' and
1444`allout-recent-prefix-end' if successful. This function uses those settings
c567ac01 1445to return the current depth of the most recently matched topic."
fd5359c6
MR
1446 '(buffer-substring (1- allout-recent-prefix-end)
1447 allout-recent-prefix-end))
c567ac01 1448
19b84ba3 1449;;;_ #4 Navigation
c567ac01
RS
1450
1451;;;_ - Position Assessment
1452;;;_ : Location Predicates
fd5359c6
MR
1453;;;_ > allout-on-current-heading-p ()
1454(defun allout-on-current-heading-p ()
19b84ba3
RS
1455 "Return non-nil if point is on current visible topics' header line.
1456
1457Actually, returns prefix beginning point."
1977b8f6
RS
1458 (save-excursion
1459 (beginning-of-line)
fd5359c6
MR
1460 (and (looking-at allout-regexp)
1461 (allout-prefix-data (match-beginning 0) (match-end 0)))))
1462;;;_ > allout-on-heading-p ()
1463(defalias 'allout-on-heading-p 'allout-on-current-heading-p)
1464;;;_ > allout-e-o-prefix-p ()
1465(defun allout-e-o-prefix-p ()
19b84ba3 1466 "True if point is located where current topic prefix ends, heading begins."
c567ac01 1467 (and (save-excursion (beginning-of-line)
fd5359c6
MR
1468 (looking-at allout-regexp))
1469 (= (point)(save-excursion (allout-end-of-prefix)(point)))))
1470;;;_ > allout-hidden-p ()
1471(defmacro allout-hidden-p ()
1977b8f6 1472 "True if point is in hidden text."
c567ac01
RS
1473 '(save-excursion
1474 (and (re-search-backward "[\n\r]" () t)
1475 (= ?\r (following-char)))))
fd5359c6
MR
1476;;;_ > allout-visible-p ()
1477(defmacro allout-visible-p ()
c567ac01 1478 "True if point is not in hidden text."
1977b8f6 1479 (interactive)
fd5359c6 1480 '(not (allout-hidden-p)))
c567ac01 1481;;;_ : Location attributes
fd5359c6
MR
1482;;;_ > allout-depth ()
1483(defsubst allout-depth ()
2265e017 1484 "Like `allout-current-depth', but respects hidden as well as visible topics."
9179616f 1485 (save-excursion
fd5359c6
MR
1486 (if (allout-goto-prefix)
1487 (allout-recent-depth)
9179616f
DL
1488 (progn
1489 ;; Oops, no prefix, zero prefix data:
fd5359c6 1490 (allout-prefix-data (point)(point))
9179616f
DL
1491 ;; ... and return 0:
1492 0))))
fd5359c6
MR
1493;;;_ > allout-current-depth ()
1494(defmacro allout-current-depth ()
19b84ba3 1495 "Return nesting depth of visible topic most immediately containing point."
c567ac01 1496 '(save-excursion
fd5359c6 1497 (if (allout-back-to-current-heading)
c567ac01 1498 (max 1
fd5359c6
MR
1499 (- allout-recent-prefix-end
1500 allout-recent-prefix-beginning
1501 allout-header-subtraction))
c567ac01 1502 0)))
fd5359c6
MR
1503;;;_ > allout-get-current-prefix ()
1504(defun allout-get-current-prefix ()
c567ac01 1505 "Topic prefix of the current topic."
1977b8f6 1506 (save-excursion
fd5359c6
MR
1507 (if (allout-goto-prefix)
1508 (allout-recent-prefix))))
1509;;;_ > allout-get-bullet ()
1510(defun allout-get-bullet ()
c567ac01 1511 "Return bullet of containing topic (visible or not)."
1977b8f6 1512 (save-excursion
fd5359c6
MR
1513 (and (allout-goto-prefix)
1514 (allout-recent-bullet))))
1515;;;_ > allout-current-bullet ()
1516(defun allout-current-bullet ()
c567ac01 1517 "Return bullet of current (visible) topic heading, or none if none found."
1977b8f6
RS
1518 (condition-case err
1519 (save-excursion
fd5359c6
MR
1520 (allout-back-to-current-heading)
1521 (buffer-substring (- allout-recent-prefix-end 1)
1522 allout-recent-prefix-end))
1977b8f6 1523 ;; Quick and dirty provision, ostensibly for missing bullet:
9179616f 1524 ('args-out-of-range nil))
1977b8f6 1525 )
fd5359c6
MR
1526;;;_ > allout-get-prefix-bullet (prefix)
1527(defun allout-get-prefix-bullet (prefix)
c567ac01 1528 "Return the bullet of the header prefix string PREFIX."
1977b8f6
RS
1529 ;; Doesn't make sense if we're old-style prefixes, but this just
1530 ;; oughtn't be called then, so forget about it...
fd5359c6 1531 (if (string-match allout-regexp prefix)
1977b8f6 1532 (substring prefix (1- (match-end 0)) (match-end 0))))
fd5359c6
MR
1533;;;_ > allout-sibling-index (&optional depth)
1534(defun allout-sibling-index (&optional depth)
9179616f
DL
1535 "Item number of this prospective topic among its siblings.
1536
e126900f 1537If optional arg DEPTH is greater than current depth, then we're
9179616f
DL
1538opening a new level, and return 0.
1539
1540If less than this depth, ascend to that depth and count..."
1541
1542 (save-excursion
1543 (cond ((and depth (<= depth 0) 0))
fd5359c6 1544 ((or (not depth) (= depth (allout-depth)))
9179616f 1545 (let ((index 1))
fd5359c6 1546 (while (allout-previous-sibling (allout-recent-depth) nil)
9179616f
DL
1547 (setq index (1+ index)))
1548 index))
fd5359c6
MR
1549 ((< depth (allout-recent-depth))
1550 (allout-ascend-to-depth depth)
1551 (allout-sibling-index))
9179616f 1552 (0))))
fd5359c6
MR
1553;;;_ > allout-topic-flat-index ()
1554(defun allout-topic-flat-index ()
9179616f
DL
1555 "Return a list indicating point's numeric section.subsect.subsubsect...
1556Outermost is first."
fd5359c6
MR
1557 (let* ((depth (allout-depth))
1558 (next-index (allout-sibling-index depth))
9179616f
DL
1559 (rev-sibls nil))
1560 (while (> next-index 0)
1561 (setq rev-sibls (cons next-index rev-sibls))
1562 (setq depth (1- depth))
fd5359c6 1563 (setq next-index (allout-sibling-index depth)))
9179616f
DL
1564 rev-sibls)
1565 )
1977b8f6 1566
c567ac01 1567;;;_ - Navigation macros
fd5359c6
MR
1568;;;_ > allout-next-heading ()
1569(defsubst allout-next-heading ()
c567ac01
RS
1570 "Move to the heading for the topic \(possibly invisible) before this one.
1571
1572Returns the location of the heading, or nil if none found."
1573
9179616f 1574 (if (and (bobp) (not (eobp)))
c567ac01
RS
1575 (forward-char 1))
1576
fd5359c6
MR
1577 (if (re-search-forward allout-line-boundary-regexp nil 0)
1578 (allout-prefix-data ; Got valid location state - set vars:
9179616f 1579 (goto-char (or (match-beginning 2)
fd5359c6
MR
1580 allout-recent-prefix-beginning))
1581 (or (match-end 2) allout-recent-prefix-end))))
1582;;;_ : allout-this-or-next-heading
1583(defun allout-this-or-next-heading ()
8d118843 1584 "Position cursor on current or next heading."
fd5359c6
MR
1585 ;; A throwaway non-macro that is defined after allout-next-heading
1586 ;; and usable by allout-mode.
1587 (if (not (allout-goto-prefix)) (allout-next-heading)))
1588;;;_ > allout-previous-heading ()
1589(defmacro allout-previous-heading ()
19b84ba3 1590 "Move to the prior \(possibly invisible) heading line.
c567ac01
RS
1591
1592Return the location of the beginning of the heading, or nil if not found."
1593
1594 '(if (bobp)
1595 nil
fd5359c6 1596 (allout-goto-prefix)
c567ac01
RS
1597 (if
1598 ;; searches are unbounded and return nil if failed:
fd5359c6
MR
1599 (or (re-search-backward allout-line-boundary-regexp nil 0)
1600 (looking-at allout-bob-regexp))
19b84ba3 1601 (progn ; Got valid location state - set vars:
fd5359c6 1602 (allout-prefix-data
c567ac01 1603 (goto-char (or (match-beginning 2)
fd5359c6
MR
1604 allout-recent-prefix-beginning))
1605 (or (match-end 2) allout-recent-prefix-end))))))
c567ac01
RS
1606
1607;;;_ - Subtree Charting
1608;;;_ " These routines either produce or assess charts, which are
1609;;; nested lists of the locations of topics within a subtree.
1610;;;
1611;;; Use of charts enables efficient navigation of subtrees, by
1612;;; requiring only a single regexp-search based traversal, to scope
1613;;; out the subtopic locations. The chart then serves as the basis
9179616f
DL
1614;;; for assessment or adjustment of the subtree, without redundant
1615;;; traversal of the structure.
c567ac01 1616
fd5359c6
MR
1617;;;_ > allout-chart-subtree (&optional levels orig-depth prev-depth)
1618(defun allout-chart-subtree (&optional levels orig-depth prev-depth)
19b84ba3
RS
1619 "Produce a location \"chart\" of subtopics of the containing topic.
1620
a0776d6b 1621Optional argument LEVELS specifies the depth \(relative to start
e126900f 1622depth) for the chart.
19b84ba3 1623
aad94676 1624Charts are used to capture outline structure, so that outline altering
19b84ba3
RS
1625routines need assess the structure only once, and then use the chart
1626for their elaborate manipulations.
1627
1628Topics are entered in the chart so the last one is at the car.
1629The entry for each topic consists of an integer indicating the point
1630at the beginning of the topic. Charts for offspring consists of a
1631list containing, recursively, the charts for the respective subtopics.
1632The chart for a topics' offspring precedes the entry for the topic
1633itself.
1634
e126900f
JB
1635\(fn &optional levels)"
1636
1637 ;; The other function parameters are for internal recursion, and should
1638 ;; not be specified by external callers. ORIG-DEPTH is depth of topic at
1639 ;; starting point, and PREV-DEPTH is depth of prior topic."
19b84ba3 1640
353e2ef2 1641 (let ((original (not orig-depth)) ; `orig-depth' set only in recursion.
19b84ba3
RS
1642 chart curr-depth)
1643
1644 (if original ; Just starting?
1645 ; Register initial settings and
1646 ; position to first offspring:
fd5359c6 1647 (progn (setq orig-depth (allout-depth))
19b84ba3 1648 (or prev-depth (setq prev-depth (1+ orig-depth)))
fd5359c6 1649 (allout-next-heading)))
c567ac01 1650
19b84ba3
RS
1651 ;; Loop over the current levels' siblings. Besides being more
1652 ;; efficient than tail-recursing over a level, it avoids exceeding
e126900f 1653 ;; the typically quite constrained Emacs max-lisp-eval-depth.
9179616f 1654 ;;
19b84ba3
RS
1655 ;; Probably would speed things up to implement loop-based stack
1656 ;; operation rather than recursing for lower levels. Bah.
9179616f 1657
c567ac01 1658 (while (and (not (eobp))
19b84ba3 1659 ; Still within original topic?
fd5359c6 1660 (< orig-depth (setq curr-depth (allout-recent-depth)))
19b84ba3
RS
1661 (cond ((= prev-depth curr-depth)
1662 ;; Register this one and move on:
1663 (setq chart (cons (point) chart))
1664 (if (and levels (<= levels 1))
1665 ;; At depth limit - skip sublevels:
fd5359c6 1666 (or (allout-next-sibling curr-depth)
19b84ba3
RS
1667 ;; or no more siblings - proceed to
1668 ;; next heading at lesser depth:
e6a9aec7 1669 (while (and (<= curr-depth
fd5359c6
MR
1670 (allout-recent-depth))
1671 (allout-next-heading))))
1672 (allout-next-heading)))
19b84ba3
RS
1673
1674 ((and (< prev-depth curr-depth)
1675 (or (not levels)
1676 (> levels 0)))
1677 ;; Recurse on deeper level of curr topic:
1678 (setq chart
fd5359c6 1679 (cons (allout-chart-subtree (and levels
19b84ba3
RS
1680 (1- levels))
1681 orig-depth
1682 curr-depth)
1683 chart))
1684 ;; ... then continue with this one.
1685 )
1686
1687 ;; ... else nil if we've ascended back to prev-depth.
1688
1689 )))
1690
1691 (if original ; We're at the last sibling on
1692 ; the original level. Position
1693 ; to the end of it:
c567ac01 1694 (progn (and (not (eobp)) (forward-char -1))
9179616f 1695 (and (memq (preceding-char) '(?\n ?\r))
c567ac01
RS
1696 (memq (aref (buffer-substring (max 1 (- (point) 3))
1697 (point))
1698 1)
9179616f 1699 '(?\n ?\r))
19b84ba3 1700 (forward-char -1))
fd5359c6 1701 (setq allout-recent-end-of-subtree (point))))
353e2ef2 1702
c567ac01
RS
1703 chart ; (nreverse chart) not necessary,
1704 ; and maybe not preferable.
1705 ))
fd5359c6
MR
1706;;;_ > allout-chart-siblings (&optional start end)
1707(defun allout-chart-siblings (&optional start end)
c567ac01 1708 "Produce a list of locations of this and succeeding sibling topics.
fd5359c6 1709Effectively a top-level chart of siblings. See `allout-chart-subtree'
c567ac01
RS
1710for an explanation of charts."
1711 (save-excursion
fd5359c6 1712 (if (allout-goto-prefix)
c567ac01 1713 (let ((chart (list (point))))
fd5359c6 1714 (while (allout-next-sibling)
c567ac01 1715 (setq chart (cons (point) chart)))
19b84ba3 1716 (if chart (setq chart (nreverse chart)))))))
fd5359c6
MR
1717;;;_ > allout-chart-to-reveal (chart depth)
1718(defun allout-chart-to-reveal (chart depth)
c567ac01 1719
19b84ba3 1720 "Return a flat list of hidden points in subtree CHART, up to DEPTH.
c567ac01 1721
19b84ba3 1722Note that point can be left at any of the points on chart, or at the
c567ac01
RS
1723start point."
1724
1725 (let (result here)
1726 (while (and (or (eq depth t) (> depth 0))
1727 chart)
1728 (setq here (car chart))
1729 (if (listp here)
fd5359c6 1730 (let ((further (allout-chart-to-reveal here (or (eq depth t)
c567ac01
RS
1731 (1- depth)))))
1732 ;; We're on the start of a subtree - recurse with it, if there's
1733 ;; more depth to go:
1734 (if further (setq result (append further result)))
1735 (setq chart (cdr chart)))
1736 (goto-char here)
1737 (if (= (preceding-char) ?\r)
1738 (setq result (cons here result)))
1739 (setq chart (cdr chart))))
1740 result))
fd5359c6 1741;;;_ X allout-chart-spec (chart spec &optional exposing)
e126900f
JB
1742;; (defun allout-chart-spec (chart spec &optional exposing)
1743;; "Not yet \(if ever) implemented.
1744
1745;; Produce exposure directives given topic/subtree CHART and an exposure SPEC.
1746
1747;; Exposure spec indicates the locations to be exposed and the prescribed
1748;; exposure status. Optional arg EXPOSING is an integer, with 0
1749;; indicating pending concealment, anything higher indicating depth to
1750;; which subtopic headers should be exposed, and negative numbers
1751;; indicating (negative of) the depth to which subtopic headers and
1752;; bodies should be exposed.
1753
1754;; The produced list can have two types of entries. Bare numbers
1755;; indicate points in the buffer where topic headers that should be
1756;; exposed reside.
1757
1758;; - bare negative numbers indicates that the topic starting at the
1759;; point which is the negative of the number should be opened,
1760;; including their entries.
1761;; - bare positive values indicate that this topic header should be
1762;; opened.
1763;; - Lists signify the beginning and end points of regions that should
1764;; be flagged, and the flag to employ. (For concealment: `\(\?r\)', and
1765;; exposure:"
1766;; (while spec
1767;; (cond ((listp spec)
1768;; )
1769;; )
1770;; (setq spec (cdr spec)))
1771;; )
c567ac01
RS
1772
1773;;;_ - Within Topic
fd5359c6
MR
1774;;;_ > allout-goto-prefix ()
1775(defun allout-goto-prefix ()
9179616f 1776 "Put point at beginning of immediately containing outline topic.
19b84ba3 1777
9179616f 1778Goes to most immediate subsequent topic if none immediately containing.
19b84ba3
RS
1779
1780Not sensitive to topic visibility.
c567ac01 1781
d27081f5 1782Returns the point at the beginning of the prefix, or nil if none."
c567ac01 1783
19b84ba3
RS
1784 (let (done)
1785 (while (and (not done)
1786 (re-search-backward "[\n\r]" nil 1))
1787 (forward-char 1)
fd5359c6
MR
1788 (if (looking-at allout-regexp)
1789 (setq done (allout-prefix-data (match-beginning 0)
19b84ba3
RS
1790 (match-end 0)))
1791 (forward-char -1)))
1792 (if (bobp)
fd5359c6
MR
1793 (cond ((looking-at allout-regexp)
1794 (allout-prefix-data (match-beginning 0)(match-end 0)))
1795 ((allout-next-heading))
19b84ba3
RS
1796 (done))
1797 done)))
fd5359c6
MR
1798;;;_ > allout-end-of-prefix ()
1799(defun allout-end-of-prefix (&optional ignore-decorations)
19b84ba3
RS
1800 "Position cursor at beginning of header text.
1801
1802If optional IGNORE-DECORATIONS is non-nil, put just after bullet,
1803otherwise skip white space between bullet and ensuing text."
c567ac01 1804
fd5359c6 1805 (if (not (allout-goto-prefix))
1977b8f6
RS
1806 nil
1807 (let ((match-data (match-data)))
1808 (goto-char (match-end 0))
c567ac01
RS
1809 (if ignore-decorations
1810 t
1811 (while (looking-at "[0-9]") (forward-char 1))
1812 (if (and (not (eolp)) (looking-at "\\s-")) (forward-char 1)))
9179616f 1813 (store-match-data match-data))
1977b8f6 1814 ;; Reestablish where we are:
fd5359c6
MR
1815 (allout-current-depth)))
1816;;;_ > allout-current-bullet-pos ()
1817(defun allout-current-bullet-pos ()
c567ac01
RS
1818 "Return position of current \(visible) topic's bullet."
1819
fd5359c6 1820 (if (not (allout-current-depth))
c567ac01
RS
1821 nil
1822 (1- (match-end 0))))
fd5359c6
MR
1823;;;_ > allout-back-to-current-heading ()
1824(defun allout-back-to-current-heading ()
19b84ba3
RS
1825 "Move to heading line of current topic, or beginning if already on the line."
1826
1977b8f6 1827 (beginning-of-line)
fd5359c6
MR
1828 (prog1 (or (allout-on-current-heading-p)
1829 (and (re-search-backward (concat "^\\(" allout-regexp "\\)")
1977b8f6
RS
1830 nil
1831 'move)
fd5359c6
MR
1832 (allout-prefix-data (match-beginning 1)(match-end 1))))
1833 (if (interactive-p) (allout-end-of-prefix))))
1834;;;_ > allout-back-to-heading ()
1835(defalias 'allout-back-to-heading 'allout-back-to-current-heading)
1836;;;_ > allout-pre-next-preface ()
1837(defun allout-pre-next-preface ()
1977b8f6
RS
1838 "Skip forward to just before the next heading line.
1839
c567ac01 1840Returns that character position."
1977b8f6 1841
fd5359c6 1842 (if (re-search-forward allout-line-boundary-regexp nil 'move)
c567ac01 1843 (prog1 (goto-char (match-beginning 0))
fd5359c6
MR
1844 (allout-prefix-data (match-beginning 2)(match-end 2)))))
1845;;;_ > allout-end-of-current-subtree ()
1846(defun allout-end-of-current-subtree ()
c567ac01 1847 "Put point at the end of the last leaf in the currently visible topic."
1977b8f6 1848 (interactive)
fd5359c6
MR
1849 (allout-back-to-current-heading)
1850 (let ((level (allout-recent-depth)))
1851 (allout-next-heading)
1977b8f6 1852 (while (and (not (eobp))
fd5359c6
MR
1853 (> (allout-recent-depth) level))
1854 (allout-next-heading))
c567ac01 1855 (and (not (eobp)) (forward-char -1))
9179616f 1856 (and (memq (preceding-char) '(?\n ?\r))
c567ac01 1857 (memq (aref (buffer-substring (max 1 (- (point) 3)) (point)) 1)
9179616f 1858 '(?\n ?\r))
c567ac01 1859 (forward-char -1))
fd5359c6
MR
1860 (setq allout-recent-end-of-subtree (point))))
1861;;;_ > allout-beginning-of-current-entry ()
1862(defun allout-beginning-of-current-entry ()
19b84ba3 1863 "When not already there, position point at beginning of current topic's body.
c567ac01
RS
1864
1865If already there, move cursor to bullet for hot-spot operation.
2265e017 1866\(See `allout-mode' doc string for details on hot-spot operation.)"
1977b8f6 1867 (interactive)
c567ac01 1868 (let ((start-point (point)))
fd5359c6 1869 (allout-end-of-prefix)
c567ac01
RS
1870 (if (and (interactive-p)
1871 (= (point) start-point))
fd5359c6
MR
1872 (goto-char (allout-current-bullet-pos)))))
1873;;;_ > allout-end-of-current-entry ()
1874(defun allout-end-of-current-entry ()
c567ac01 1875 "Position the point at the end of the current topics' entry."
1977b8f6 1876 (interactive)
fd5359c6
MR
1877 (allout-show-entry)
1878 (prog1 (allout-pre-next-preface)
1977b8f6 1879 (if (and (not (bobp))(looking-at "^$"))
19b84ba3 1880 (forward-char -1))))
fd5359c6
MR
1881;;;_ > allout-end-of-current-heading ()
1882(defun allout-end-of-current-heading ()
9179616f 1883 (interactive)
fd5359c6 1884 (allout-beginning-of-current-entry)
9179616f
DL
1885 (forward-line -1)
1886 (end-of-line))
fd5359c6 1887(defalias 'allout-end-of-heading 'allout-end-of-current-heading)
1977b8f6 1888
c567ac01 1889;;;_ - Depth-wise
fd5359c6
MR
1890;;;_ > allout-ascend-to-depth (depth)
1891(defun allout-ascend-to-depth (depth)
c567ac01 1892 "Ascend to depth DEPTH, returning depth if successful, nil if not."
fd5359c6 1893 (if (and (> depth 0)(<= depth (allout-depth)))
1977b8f6 1894 (let ((last-good (point)))
fd5359c6 1895 (while (and (< depth (allout-depth))
1977b8f6 1896 (setq last-good (point))
fd5359c6
MR
1897 (allout-beginning-of-level)
1898 (allout-previous-heading)))
1899 (if (= (allout-recent-depth) depth)
1900 (progn (goto-char allout-recent-prefix-beginning)
1977b8f6 1901 depth)
65970d64 1902 (goto-char last-good)))))
fd5359c6
MR
1903;;;_ > allout-ascend ()
1904(defun allout-ascend ()
9179616f 1905 "Ascend one level, returning t if successful, nil if not."
65970d64
RS
1906 (if (allout-beginning-of-level)
1907 (allout-previous-heading)))
fd5359c6
MR
1908;;;_ > allout-descend-to-depth (depth)
1909(defun allout-descend-to-depth (depth)
19b84ba3
RS
1910 "Descend to depth DEPTH within current topic.
1911
1912Returning depth if successful, nil if not."
1977b8f6 1913 (let ((start-point (point))
fd5359c6 1914 (start-depth (allout-depth)))
1977b8f6 1915 (while
fd5359c6
MR
1916 (and (> (allout-depth) 0)
1917 (not (= depth (allout-recent-depth))) ; ... not there yet
1918 (allout-next-heading) ; ... go further
1919 (< start-depth (allout-recent-depth)))) ; ... still in topic
1920 (if (and (> (allout-depth) 0)
1921 (= (allout-recent-depth) depth))
1977b8f6
RS
1922 depth
1923 (goto-char start-point)
1924 nil))
1925 )
fd5359c6 1926;;;_ > allout-up-current-level (arg &optional dont-complain)
65970d64 1927(defun allout-up-current-level (arg &optional dont-complain interactive)
19b84ba3
RS
1928 "Move out ARG levels from current visible topic.
1929
1930Positions on heading line of containing topic. Error if unable to
1931ascend that far, or nil if unable to ascend but optional arg
1932DONT-COMPLAIN is non-nil."
65970d64 1933 (interactive "p\np")
fd5359c6
MR
1934 (allout-back-to-current-heading)
1935 (let ((present-level (allout-recent-depth))
19b84ba3
RS
1936 (last-good (point))
1937 failed
1938 return)
1977b8f6 1939 ;; Loop for iterating arg:
fd5359c6 1940 (while (and (> (allout-recent-depth) 1)
1977b8f6 1941 (> arg 0)
19b84ba3
RS
1942 (not (bobp))
1943 (not failed))
1944 (setq last-good (point))
1977b8f6 1945 ;; Loop for going back over current or greater depth:
fd5359c6
MR
1946 (while (and (not (< (allout-recent-depth) present-level))
1947 (or (allout-previous-visible-heading 1)
19b84ba3 1948 (not (setq failed present-level)))))
fd5359c6 1949 (setq present-level (allout-current-depth))
1977b8f6 1950 (setq arg (- arg 1)))
19b84ba3
RS
1951 (if (or failed
1952 (> arg 0))
1953 (progn (goto-char last-good)
65970d64 1954 (if interactive (allout-end-of-prefix))
19b84ba3 1955 (if (not dont-complain)
6a05d05f 1956 (error "Can't ascend past outermost level")
65970d64 1957 (if interactive (allout-end-of-prefix))
19b84ba3 1958 nil))
65970d64 1959 (if interactive (allout-end-of-prefix))
fd5359c6 1960 allout-recent-prefix-beginning)))
1977b8f6 1961
c567ac01 1962;;;_ - Linear
fd5359c6
MR
1963;;;_ > allout-next-sibling (&optional depth backward)
1964(defun allout-next-sibling (&optional depth backward)
2265e017 1965 "Like `allout-forward-current-level', but respects invisible topics.
1977b8f6 1966
c567ac01 1967Traverse at optional DEPTH, or current depth if none specified.
1977b8f6 1968
c567ac01 1969Go backward if optional arg BACKWARD is non-nil.
1977b8f6 1970
c567ac01 1971Return depth if successful, nil otherwise."
1977b8f6
RS
1972
1973 (if (and backward (bobp))
1974 nil
fd5359c6 1975 (let ((start-depth (or depth (allout-depth)))
1977b8f6 1976 (start-point (point))
c567ac01 1977 last-depth)
1977b8f6 1978 (while (and (not (if backward (bobp) (eobp)))
fd5359c6
MR
1979 (if backward (allout-previous-heading)
1980 (allout-next-heading))
1981 (> (setq last-depth (allout-recent-depth)) start-depth)))
1977b8f6 1982 (if (and (not (eobp))
fd5359c6
MR
1983 (and (> (or last-depth (allout-depth)) 0)
1984 (= (allout-recent-depth) start-depth)))
1985 allout-recent-prefix-beginning
1977b8f6 1986 (goto-char start-point)
fd5359c6 1987 (if depth (allout-depth) start-depth)
c567ac01 1988 nil))))
fd5359c6
MR
1989;;;_ > allout-previous-sibling (&optional depth backward)
1990(defun allout-previous-sibling (&optional depth backward)
aad94676 1991 "Like `allout-forward-current-level', but backwards & respect invisible topics.
1977b8f6 1992
c567ac01 1993Optional DEPTH specifies depth to traverse, default current depth.
1977b8f6 1994
c567ac01 1995Optional BACKWARD reverses direction.
1977b8f6 1996
c567ac01 1997Return depth if successful, nil otherwise."
fd5359c6 1998 (allout-next-sibling depth (not backward))
1977b8f6 1999 )
fd5359c6
MR
2000;;;_ > allout-snug-back ()
2001(defun allout-snug-back ()
19b84ba3
RS
2002 "Position cursor at end of previous topic
2003
2004Presumes point is at the start of a topic prefix."
c567ac01
RS
2005 (if (or (bobp) (eobp))
2006 nil
2007 (forward-char -1))
9179616f 2008 (if (or (bobp) (not (memq (preceding-char) '(?\n ?\r))))
c567ac01
RS
2009 nil
2010 (forward-char -1)
9179616f 2011 (if (or (bobp) (not (memq (preceding-char) '(?\n ?\r))))
c567ac01
RS
2012 (forward-char -1)))
2013 (point))
fd5359c6
MR
2014;;;_ > allout-beginning-of-level ()
2015(defun allout-beginning-of-level ()
c567ac01 2016 "Go back to the first sibling at this level, visible or not."
fd5359c6
MR
2017 (allout-end-of-level 'backward))
2018;;;_ > allout-end-of-level (&optional backward)
2019(defun allout-end-of-level (&optional backward)
c567ac01 2020 "Go to the last sibling at this level, visible or not."
1977b8f6 2021
fd5359c6
MR
2022 (let ((depth (allout-depth)))
2023 (while (allout-previous-sibling depth nil))
2024 (prog1 (allout-recent-depth)
65970d64 2025 (allout-end-of-prefix))))
fd5359c6
MR
2026;;;_ > allout-next-visible-heading (arg)
2027(defun allout-next-visible-heading (arg)
19b84ba3 2028 "Move to the next ARG'th visible heading line, backward if arg is negative.
c567ac01 2029
19b84ba3 2030Move as far as possible in indicated direction \(beginning or end of
9179616f 2031buffer) if headings are exhausted."
1977b8f6 2032
1977b8f6 2033 (interactive "p")
c567ac01
RS
2034 (let* ((backward (if (< arg 0) (setq arg (* -1 arg))))
2035 (step (if backward -1 1))
19b84ba3 2036 (start-point (point))
c567ac01
RS
2037 prev got)
2038
2039 (while (> arg 0) ; limit condition
2040 (while (and (not (if backward (bobp)(eobp))) ; boundary condition
19b84ba3
RS
2041 ;; Move, skipping over all those concealed lines:
2042 (< -1 (forward-line step))
fd5359c6 2043 (not (setq got (looking-at allout-regexp)))))
c567ac01
RS
2044 ;; Register this got, it may be the last:
2045 (if got (setq prev got))
2046 (setq arg (1- arg)))
2047 (cond (got ; Last move was to a prefix:
fd5359c6
MR
2048 (allout-prefix-data (match-beginning 0) (match-end 0))
2049 (allout-end-of-prefix))
c567ac01 2050 (prev ; Last move wasn't, but prev was:
fd5359c6 2051 (allout-prefix-data (match-beginning 0) (match-end 0)))
c567ac01 2052 ((not backward) (end-of-line) nil))))
fd5359c6
MR
2053;;;_ > allout-previous-visible-heading (arg)
2054(defun allout-previous-visible-heading (arg)
c567ac01 2055 "Move to the previous heading line.
1977b8f6 2056
c567ac01 2057With argument, repeats or can move forward if negative.
2265e017 2058A heading line is one that starts with a `*' (or that `allout-regexp'
c567ac01 2059matches)."
1977b8f6 2060 (interactive "p")
fd5359c6
MR
2061 (allout-next-visible-heading (- arg)))
2062;;;_ > allout-forward-current-level (arg)
65970d64 2063(defun allout-forward-current-level (arg &optional interactive)
19b84ba3 2064 "Position point at the next heading of the same level.
1977b8f6 2065
19b84ba3 2066Takes optional repeat-count, goes backward if count is negative.
1977b8f6 2067
19b84ba3 2068Returns resulting position, else nil if none found."
65970d64 2069 (interactive "p\np")
fd5359c6 2070 (let ((start-depth (allout-current-depth))
19b84ba3
RS
2071 (start-point (point))
2072 (start-arg arg)
2073 (backward (> 0 arg))
2074 last-depth
2075 (last-good (point))
2076 at-boundary)
2077 (if (= 0 start-depth)
2078 (error "No siblings, not in a topic..."))
2079 (if backward (setq arg (* -1 arg)))
2080 (while (not (or (zerop arg)
2081 at-boundary))
2082 (while (and (not (if backward (bobp) (eobp)))
fd5359c6
MR
2083 (if backward (allout-previous-visible-heading 1)
2084 (allout-next-visible-heading 1))
2085 (> (setq last-depth (allout-recent-depth)) start-depth)))
19b84ba3
RS
2086 (if (and last-depth (= last-depth start-depth)
2087 (not (if backward (bobp) (eobp))))
2088 (setq last-good (point)
2089 arg (1- arg))
2090 (setq at-boundary t)))
2091 (if (and (not (eobp))
2092 (= arg 0)
fd5359c6
MR
2093 (and (> (or last-depth (allout-depth)) 0)
2094 (= (allout-recent-depth) start-depth)))
2095 allout-recent-prefix-beginning
19b84ba3 2096 (goto-char last-good)
65970d64 2097 (if (not interactive)
19b84ba3 2098 nil
fd5359c6 2099 (allout-end-of-prefix)
6a05d05f 2100 (error "Hit %s level %d topic, traversed %d of %d requested"
19b84ba3 2101 (if backward "first" "last")
fd5359c6 2102 (allout-recent-depth)
19b84ba3
RS
2103 (- (abs start-arg) arg)
2104 (abs start-arg))))))
fd5359c6 2105;;;_ > allout-backward-current-level (arg)
65970d64 2106(defun allout-backward-current-level (arg &optional interactive)
fd5359c6 2107 "Inverse of `allout-forward-current-level'."
65970d64
RS
2108 (interactive "p\np")
2109 (if interactive
19b84ba3 2110 (let ((current-prefix-arg (* -1 arg)))
fd5359c6
MR
2111 (call-interactively 'allout-forward-current-level))
2112 (allout-forward-current-level (* -1 arg))))
c567ac01 2113
19b84ba3 2114;;;_ #5 Alteration
c567ac01
RS
2115
2116;;;_ - Fundamental
fd5359c6
MR
2117;;;_ > allout-before-change-protect (beg end)
2118(defun allout-before-change-protect (beg end)
19b84ba3
RS
2119 "Outline before-change hook, regulates changes to concealed text.
2120
2121Reveal concealed text that would be changed by current command, and
c567ac01
RS
2122offer user choice to commit or forego the change. Unchanged text is
2123reconcealed. User has option to have changed text reconcealed.
2124
2125Undo commands are specially treated - the user is not prompted for
2126choice, the undoes are always committed (based on presumption that the
2127things being undone were already subject to this regulation routine),
2128and undoes always leave the changed stuff exposed.
2129
2130Changes to concealed regions are ignored while file is being written.
2131\(This is for the sake of functions that do change the file during
2132writes, like crypt and zip modes.)
2133
9179616f 2134Locally bound in outline buffers to `before-change-functions', which
e126900f 2135in Emacs 19 is run before any change to the buffer.
c567ac01 2136
353e2ef2 2137Any functions which set [`this-command' to `undo', or which set]
fd5359c6 2138`allout-override-protect' non-nil (as does, eg, allout-flag-chars)
c567ac01 2139are exempt from this restriction."
fd5359c6
MR
2140 (if (and (allout-mode-p)
2141 ; allout-override-protect
c567ac01
RS
2142 ; set by functions that know what
2143 ; they're doing, eg outline internals:
fd5359c6
MR
2144 (not allout-override-protect)
2145 (not allout-during-write-cue)
c567ac01
RS
2146 (save-match-data ; Preserve operation position state.
2147 ; Both beginning and end chars must
2148 ; be exposed:
2149 (save-excursion (if (memq this-command '(newline open-line))
e126900f 2150 ;; Compensate for stupid Emacs {new,
c567ac01
RS
2151 ;; open-}line display optimization:
2152 (setq beg (1+ beg)
2153 end (1+ end)))
2154 (goto-char beg)
fd5359c6 2155 (or (allout-hidden-p)
c567ac01
RS
2156 (and (not (= beg end))
2157 (goto-char end)
fd5359c6 2158 (allout-hidden-p))))))
c567ac01
RS
2159 (save-match-data
2160 (if (equal this-command 'undo)
2161 ;; Allow undo without inhibition.
e126900f 2162 ;; - Undoing new and open-line hits stupid Emacs redisplay
c567ac01
RS
2163 ;; optimization (em 19 cmds.c, ~ line 200).
2164 ;; - Presumably, undoing what was properly protected when
2165 ;; done.
2166 ;; - Undo may be users' only recourse in protection faults.
2167 ;; So, expose what getting changed:
2168 (progn (message "Undo! - exposing concealed target...")
fd5359c6
MR
2169 (if (allout-hidden-p)
2170 (allout-show-children))
19b84ba3 2171 (message "Undo!"))
c567ac01 2172 (let (response
fd5359c6
MR
2173 (rehide-completely (save-excursion (allout-goto-prefix)
2174 (allout-hidden-p)))
c567ac01 2175 rehide-place)
353e2ef2 2176
c567ac01
RS
2177 (save-excursion
2178 (if (condition-case err
2179 ;; Condition case to catch keyboard quits during reads.
2180 (progn
2181 ; Give them a peek where
2182 (save-excursion
2183 (if (eolp) (setq rehide-place
fd5359c6
MR
2184 (allout-goto-prefix)))
2185 (allout-show-entry))
c567ac01
RS
2186 ; Present the message, but...
2187 ; leave the cursor at the location
2188 ; until they respond:
2189 ; Then interpret the response:
2190 (while
353e2ef2 2191 (progn
c567ac01
RS
2192 (message (concat "Change inside concealed"
2193 " region - do it? "
2194 "(n or 'y'/'r'eclose)"))
2195 (setq response (read-char))
2196 (not
2197 (cond ((memq response '(?r ?R))
2198 (setq response 'reclose))
2199 ((memq response '(?y ?Y ? ))
2200 (setq response t))
2201 ((memq response '(?n ?N 127))
2202 (setq response nil)
2203 t)
2204 ((eq response ??)
2205 (message
353e2ef2 2206 "`r' means `yes, then reclose'")
c567ac01
RS
2207 nil)
2208 (t (message "Please answer y, n, or r")
2209 (sit-for 1)
2210 nil)))))
2211 response)
9179616f 2212 ('quit nil))
c567ac01
RS
2213 ; Continue:
2214 (if (eq response 'reclose)
2215 (save-excursion
2216 (if rehide-place (goto-char rehide-place))
2217 (if rehide-completely
fd5359c6
MR
2218 (allout-hide-current-entry-completely)
2219 (allout-hide-current-entry)))
2220 (if (allout-ascend-to-depth (1- (allout-recent-depth)))
2221 (allout-show-children)
2222 (allout-show-to-offshoot)))
c567ac01
RS
2223 ; Prevent:
2224 (if rehide-completely
2225 (save-excursion
2226 (if rehide-place (goto-char rehide-place))
fd5359c6
MR
2227 (allout-hide-current-entry-completely))
2228 (allout-hide-current-entry))
c567ac01
RS
2229 (error (concat
2230 "Change within concealed region prevented.")))))))
2231 ) ; if
2232 ) ; defun
fd5359c6
MR
2233;;;_ = allout-post-goto-bullet
2234(defvar allout-post-goto-bullet nil
2235 "Outline internal var, for `allout-pre-command-business' hot-spot operation.
19b84ba3
RS
2236
2237When set, tells post-processing to reposition on topic bullet, and
2265e017 2238then unset it. Set by `allout-pre-command-business' when implementing
19b84ba3
RS
2239hot-spot operation, where literal characters typed over a topic bullet
2240are mapped to the command of the corresponding control-key on the
2265e017 2241`allout-mode-map'.")
fd5359c6
MR
2242(make-variable-buffer-local 'allout-post-goto-bullet)
2243;;;_ > allout-post-command-business ()
2244(defun allout-post-command-business ()
2265e017 2245 "Outline `post-command-hook' function.
c567ac01 2246
2265e017 2247- Null `allout-override-protect', so it's not left open.
c567ac01 2248
2265e017 2249- Implement (and clear) `allout-post-goto-bullet', for hot-spot
c567ac01
RS
2250 outline commands.
2251
2252- Massages buffer-undo-list so successive, standard character self-inserts are
2253 aggregated. This kludge compensates for lack of undo bunching when
2265e017 2254 `before-change-functions' is used."
c567ac01
RS
2255
2256 ; Apply any external change func:
fd5359c6 2257 (if (not (allout-mode-p)) ; In allout-mode.
19b84ba3 2258 nil
fd5359c6
MR
2259 (setq allout-override-protect nil)
2260 (if allout-isearch-dynamic-expose
2261 (allout-isearch-rectification))
2262 (if allout-during-write-cue
2263 ;; Was used by allout-before-change-protect, done with it now:
2264 (setq allout-during-write-cue nil))
19b84ba3
RS
2265 ;; Undo bunching business:
2266 (if (and (listp buffer-undo-list) ; Undo history being kept.
2267 (equal this-command 'self-insert-command)
2268 (equal last-command 'self-insert-command))
2269 (let* ((prev-stuff (cdr buffer-undo-list))
2270 (before-prev-stuff (cdr (cdr prev-stuff)))
2271 cur-cell cur-from cur-to
2272 prev-cell prev-from prev-to)
2273 (if (and before-prev-stuff ; Goes back far enough to bother,
2274 (not (car prev-stuff)) ; and break before current,
2275 (not (car before-prev-stuff)) ; !and break before prev!
2276 (setq prev-cell (car (cdr prev-stuff))) ; contents now,
2277 (setq cur-cell (car buffer-undo-list)) ; contents prev.
2278
2279 ;; cur contents denote a single char insertion:
2280 (numberp (setq cur-from (car cur-cell)))
2281 (numberp (setq cur-to (cdr cur-cell)))
2282 (= 1 (- cur-to cur-from))
2283
2284 ;; prev contents denote fewer than aggregate-limit
2285 ;; insertions:
2286 (numberp (setq prev-from (car prev-cell)))
2287 (numberp (setq prev-to (cdr prev-cell)))
c567ac01 2288 ; Below threshold:
fd5359c6 2289 (> allout-undo-aggregation (- prev-to prev-from)))
19b84ba3
RS
2290 (setq buffer-undo-list
2291 (cons (cons prev-from cur-to)
2292 (cdr (cdr (cdr buffer-undo-list))))))))
2293 ;; Implement -post-goto-bullet, if set: (must be after undo business)
fd5359c6
MR
2294 (if (and allout-post-goto-bullet
2295 (allout-current-bullet-pos))
2296 (progn (goto-char (allout-current-bullet-pos))
2297 (setq allout-post-goto-bullet nil)))
19b84ba3 2298 ))
fd5359c6
MR
2299;;;_ > allout-pre-command-business ()
2300(defun allout-pre-command-business ()
2265e017 2301 "Outline `pre-command-hook' function for outline buffers.
58edceeb 2302Implements special behavior when cursor is on bullet character.
c567ac01 2303
58edceeb
JB
2304When the cursor is on the bullet character, self-insert characters are
2305reinterpreted as the corresponding control-character in the
2306`allout-mode-map'. The `allout-mode' `post-command-hook' insures that
2307the cursor which has moved as a result of such reinterpretation is
2308positioned on the bullet character of the destination topic.
c567ac01 2309
9179616f
DL
2310The upshot is that you can get easy, single (ie, unmodified) key
2311outline maneuvering operations by positioning the cursor on the bullet
58edceeb
JB
2312char. When in this mode you can use regular cursor-positioning
2313command/keystrokes to relocate the cursor off of a bullet character to
2314return to regular interpretation of self-insert characters."
fd5359c6
MR
2315 (if (not (allout-mode-p))
2316 ;; Shouldn't be invoked if not in allout allout-mode, but just in case:
9179616f
DL
2317 nil
2318 ;; Register isearch status:
2319 (if (and (boundp 'isearch-mode) isearch-mode)
fd5359c6
MR
2320 (setq allout-pre-was-isearching t)
2321 (setq allout-pre-was-isearching nil))
9179616f
DL
2322 ;; Hot-spot navigation provisions:
2323 (if (and (eq this-command 'self-insert-command)
fd5359c6 2324 (eq (point)(allout-current-bullet-pos)))
9179616f
DL
2325 (let* ((this-key-num (cond
2326 ((numberp last-command-char)
2327 last-command-char)
e126900f 2328 ;; XXX Only XEmacs has characterp.
9179616f
DL
2329 ((and (fboundp 'characterp)
2330 (characterp last-command-char))
2331 (char-to-int last-command-char))
2332 (t 0)))
2333 mapped-binding)
2334 (if (zerop this-key-num)
2335 nil
c567ac01
RS
2336 ; Map upper-register literals
2337 ; to lower register:
9179616f
DL
2338 (if (<= 96 this-key-num)
2339 (setq this-key-num (- this-key-num 32)))
c567ac01 2340 ; Check if we have a literal:
9179616f
DL
2341 (if (and (<= 64 this-key-num)
2342 (>= 96 this-key-num))
2343 (setq mapped-binding
fd5359c6
MR
2344 (lookup-key 'allout-mode-map
2345 (concat allout-command-prefix
9179616f
DL
2346 (char-to-string (- this-key-num
2347 64))))))
2348 (if mapped-binding
fd5359c6 2349 (setq allout-post-goto-bullet t
9179616f 2350 this-command mapped-binding)))))))
fd5359c6
MR
2351;;;_ > allout-find-file-hook ()
2352(defun allout-find-file-hook ()
2265e017 2353 "Activate `allout-mode' when `allout-auto-activation' & `allout-layout' are non-nil.
fd5359c6
MR
2354
2355See `allout-init' for setup instructions."
2356 (if (and allout-auto-activation
2357 (not (allout-mode-p))
2358 allout-layout)
2359 (allout-mode t)))
2360;;;_ > allout-isearch-rectification
2361(defun allout-isearch-rectification ()
9179616f
DL
2362 "Rectify outline exposure before, during, or after isearch.
2363
2265e017 2364Called as part of `allout-post-command-business'."
9179616f
DL
2365
2366 (let ((isearching (and (boundp 'isearch-mode) isearch-mode)))
fd5359c6
MR
2367 (cond ((and isearching (not allout-pre-was-isearching))
2368 (allout-isearch-expose 'start))
2369 ((and isearching allout-pre-was-isearching)
2370 (allout-isearch-expose 'continue))
2371 ((and (not isearching) allout-pre-was-isearching)
2372 (allout-isearch-expose 'final))
9179616f 2373 ;; Not and wasn't isearching:
fd5359c6
MR
2374 (t (setq allout-isearch-prior-pos nil)
2375 (setq allout-isearch-did-quit nil)))))
2376;;;_ = allout-isearch-was-font-lock
2377(defvar allout-isearch-was-font-lock
9179616f 2378 (and (boundp 'font-lock-mode) font-lock-mode))
12435002 2379
fd5359c6
MR
2380;;;_ > allout-flag-region (from to flag)
2381(defmacro allout-flag-region (from to flag)
e126900f 2382 "Hide or show lines from FROM to TO, via Emacs selective-display FLAG char.
12435002
GM
2383Ie, text following flag C-m \(carriage-return) is hidden until the
2384next C-j (newline) char.
2385
2386Returns the endpoint of the region."
2387 `(let ((buffer-read-only nil)
fd5359c6 2388 (allout-override-protect t))
12435002
GM
2389 (subst-char-in-region ,from ,to
2390 (if (= ,flag ?\n) ?\r ?\n)
2391 ,flag t)))
2392
fd5359c6
MR
2393;;;_ > allout-isearch-expose (mode)
2394(defun allout-isearch-expose (mode)
e126900f 2395 "MODE is either 'clear, 'start, 'continue, or 'final."
fd5359c6 2396 ;; allout-isearch-prior-pos encodes exposure status of prior pos:
9179616f
DL
2397 ;; (pos was-vis header-pos end-pos)
2398 ;; pos - point of concern
2399 ;; was-vis - t, else 'topic if entire topic was exposed, 'entry otherwise
2400 ;; Do reclosure or prior pos, as necessary:
2401 (if (eq mode 'start)
fd5359c6 2402 (setq allout-isearch-was-font-lock (and (boundp 'font-lock-mode)
9179616f
DL
2403 font-lock-mode)
2404 font-lock-mode nil)
2405 (if (eq mode 'final)
fd5359c6
MR
2406 (setq font-lock-mode allout-isearch-was-font-lock))
2407 (if (and allout-isearch-prior-pos
2408 (listp allout-isearch-prior-pos))
9179616f 2409 ;; Conceal prior peek:
fd5359c6
MR
2410 (allout-flag-region (car (cdr allout-isearch-prior-pos))
2411 (car (cdr (cdr allout-isearch-prior-pos)))
9179616f 2412 ?\r)))
fd5359c6
MR
2413 (if (allout-visible-p)
2414 (setq allout-isearch-prior-pos nil)
9179616f 2415 (if (not (eq mode 'final))
fd5359c6
MR
2416 (setq allout-isearch-prior-pos (cons (point) (allout-show-entry)))
2417 (if allout-isearch-did-quit
9179616f 2418 nil
fd5359c6
MR
2419 (setq allout-isearch-prior-pos nil)
2420 (allout-show-children))))
2421 (setq allout-isearch-did-quit nil))
2422;;;_ > allout-enwrap-isearch ()
2423(defun allout-enwrap-isearch ()
2265e017 2424 "Impose `allout-mode' isearch-abort wrapper for dynamic exposure in isearch.
9179616f
DL
2425
2426The function checks to ensure that the rebinding is done only once."
2427
fd5359c6
MR
2428 (add-hook 'isearch-mode-end-hook 'allout-isearch-rectification)
2429 (if (fboundp 'allout-real-isearch-abort)
71296446 2430 ;;
9179616f
DL
2431 nil
2432 ; Ensure load of isearch-mode:
2433 (if (or (and (fboundp 'isearch-mode)
2434 (fboundp 'isearch-abort))
71296446 2435 (condition-case error
9179616f
DL
2436 (load-library "isearch-mode")
2437 ('file-error (message
2438 "Skipping isearch-mode provisions - %s '%s'"
2439 (car (cdr error))
2440 (car (cdr (cdr error))))
2441 (sit-for 1)
2442 ;; Inhibit subsequent tries and return nil:
fd5359c6 2443 (setq allout-isearch-dynamic-expose nil))))
9179616f
DL
2444 ;; Isearch-mode loaded, encapsulate specific entry points for
2445 ;; outline dynamic-exposure business:
71296446 2446 (progn
9179616f
DL
2447 ;; stash crucial isearch-mode funcs under known, private
2448 ;; names, then register wrapper functions under the old
2449 ;; names, in their stead:
fd5359c6
MR
2450 (fset 'allout-real-isearch-abort (symbol-function 'isearch-abort))
2451 (fset 'isearch-abort 'allout-isearch-abort)))))
2452;;;_ > allout-isearch-abort ()
2453(defun allout-isearch-abort ()
2265e017 2454 "Wrapper for `allout-real-isearch-abort' \(which see), to register
9179616f
DL
2455actual quits."
2456 (interactive)
fd5359c6 2457 (setq allout-isearch-did-quit nil)
9179616f 2458 (condition-case what
fd5359c6
MR
2459 (allout-real-isearch-abort)
2460 ('quit (setq allout-isearch-did-quit t)
9179616f
DL
2461 (signal 'quit nil))))
2462
2463;;; Prevent unnecessary font-lock while isearching!
2464(defvar isearch-was-font-locking nil)
2465(defun isearch-inhibit-font-lock ()
aad94676 2466 "Inhibit `font-lock-mode' while isearching - for use on `isearch-mode-hook'."
fd5359c6 2467 (if (and (allout-mode-p) (boundp 'font-lock-mode) font-lock-mode)
9179616f
DL
2468 (setq isearch-was-font-locking t
2469 font-lock-mode nil)))
2470(add-hook 'isearch-mode-hook 'isearch-inhibit-font-lock)
2471(defun isearch-reenable-font-lock ()
2472 "Reenable font-lock after isearching - for use on isearch-mode-end-hook."
2473 (if (and (boundp 'font-lock-mode) font-lock-mode)
fd5359c6 2474 (if (and (allout-mode-p) isearch-was-font-locking)
9179616f
DL
2475 (setq isearch-was-font-locking nil
2476 font-lock-mode t))))
2477(add-hook 'isearch-mode-end-hook 'isearch-reenable-font-lock)
c567ac01
RS
2478
2479;;;_ - Topic Format Assessment
fd5359c6
MR
2480;;;_ > allout-solicit-alternate-bullet (depth &optional current-bullet)
2481(defun allout-solicit-alternate-bullet (depth &optional current-bullet)
1977b8f6 2482
19b84ba3
RS
2483 "Prompt for and return a bullet char as an alternative to the current one.
2484
2485Offer one suitable for current depth DEPTH as default."
1977b8f6 2486
9179616f 2487 (let* ((default-bullet (or (and (stringp current-bullet) current-bullet)
fd5359c6
MR
2488 (allout-bullet-for-depth depth)))
2489 (sans-escapes (regexp-sans-escapes allout-bullets-string))
9179616f
DL
2490 choice)
2491 (save-excursion
fd5359c6 2492 (goto-char (allout-current-bullet-pos))
9179616f
DL
2493 (setq choice (solicit-char-in-string
2494 (format "Select bullet: %s ('%s' default): "
2495 sans-escapes
2496 default-bullet)
2497 sans-escapes
2498 t)))
2499 (message "")
1977b8f6
RS
2500 (if (string= choice "") default-bullet choice))
2501 )
fd5359c6
MR
2502;;;_ > allout-distinctive-bullet (bullet)
2503(defun allout-distinctive-bullet (bullet)
e126900f 2504 "True if BULLET is one of those on `allout-distinctive-bullets-string'."
fd5359c6
MR
2505 (string-match (regexp-quote bullet) allout-distinctive-bullets-string))
2506;;;_ > allout-numbered-type-prefix (&optional prefix)
2507(defun allout-numbered-type-prefix (&optional prefix)
c567ac01 2508 "True if current header prefix bullet is numbered bullet."
fd5359c6
MR
2509 (and allout-numbered-bullet
2510 (string= allout-numbered-bullet
1977b8f6 2511 (if prefix
fd5359c6
MR
2512 (allout-get-prefix-bullet prefix)
2513 (allout-get-bullet)))))
2514;;;_ > allout-bullet-for-depth (&optional depth)
2515(defun allout-bullet-for-depth (&optional depth)
19b84ba3 2516 "Return outline topic bullet suited to optional DEPTH, or current depth."
1977b8f6 2517 ;; Find bullet in plain-bullets-string modulo DEPTH.
fd5359c6
MR
2518 (if allout-stylish-prefixes
2519 (char-to-string (aref allout-plain-bullets-string
1977b8f6 2520 (% (max 0 (- depth 2))
fd5359c6
MR
2521 allout-plain-bullets-string-len)))
2522 allout-primary-bullet)
1977b8f6
RS
2523 )
2524
c567ac01 2525;;;_ - Topic Production
fd5359c6
MR
2526;;;_ > allout-make-topic-prefix (&optional prior-bullet
2527(defun allout-make-topic-prefix (&optional prior-bullet
1977b8f6
RS
2528 new
2529 depth
2530 solicit
2531 number-control
2532 index)
2533 ;; Depth null means use current depth, non-null means we're either
2534 ;; opening a new topic after current topic, lower or higher, or we're
2535 ;; changing level of current topic.
2536 ;; Solicit dominates specified bullet-char.
c567ac01 2537;;;_ . Doc string:
19b84ba3 2538 "Generate a topic prefix suitable for optional arg DEPTH, or current depth.
c567ac01
RS
2539
2540All the arguments are optional.
2541
2542PRIOR-BULLET indicates the bullet of the prefix being changed, or
2543nil if none. This bullet may be preserved (other options
2265e017 2544notwithstanding) if it is on the `allout-distinctive-bullets-string',
c567ac01
RS
2545for instance.
2546
2547Second arg NEW indicates that a new topic is being opened after the
2548topic at point, if non-nil. Default bullet for new topics, eg, may
2549be set (contingent to other args) to numbered bullets if previous
2550sibling is one. The implication otherwise is that the current topic
2551is being adjusted - shifted or rebulleted - and we don't consider
2552bullet or previous sibling.
2553
2554Third arg DEPTH forces the topic prefix to that depth, regardless of
2555the current topics' depth.
2556
9179616f
DL
2557If SOLICIT is non-nil, then the choice of bullet is solicited from
2558user. If it's a character, then that character is offered as the
2559default, otherwise the one suited to the context \(according to
2560distinction or depth) is offered. \(This overrides other options,
2561including, eg, a distinctive PRIOR-BULLET.) If non-nil, then the
2562context-specific bullet is used.
c567ac01 2563
fd5359c6 2564Fifth arg, NUMBER-CONTROL, matters only if `allout-numbered-bullet'
c567ac01
RS
2565is non-nil *and* soliciting was not explicitly invoked. Then
2566NUMBER-CONTROL non-nil forces prefix to either numbered or
2567denumbered format, depending on the value of the sixth arg, INDEX.
2568
2569\(Note that NUMBER-CONTROL does *not* apply to level 1 topics. Sorry...)
2570
2571If NUMBER-CONTROL is non-nil and sixth arg INDEX is non-nil then
2572the prefix of the topic is forced to be numbered. Non-nil
2573NUMBER-CONTROL and nil INDEX forces non-numbered format on the
2574bullet. Non-nil NUMBER-CONTROL and non-nil, non-number INDEX means
2575that the index for the numbered prefix will be derived, by counting
2576siblings back to start of level. If INDEX is a number, then that
2577number is used as the index for the numbered prefix (allowing, eg,
a0776d6b 2578sequential renumbering to not require this function counting back the
c567ac01
RS
2579index for each successive sibling)."
2580;;;_ . Code:
1977b8f6
RS
2581 ;; The options are ordered in likely frequence of use, most common
2582 ;; highest, least lowest. Ie, more likely to be doing prefix
2583 ;; adjustments than soliciting, and yet more than numbering.
2584 ;; Current prefix is least dominant, but most likely to be commonly
2585 ;; specified...
2586
2587 (let* (body
2588 numbering
2589 denumbering
fd5359c6
MR
2590 (depth (or depth (allout-depth)))
2591 (header-lead allout-header-prefix)
1977b8f6
RS
2592 (bullet-char
2593
2594 ;; Getting value for bullet char is practically the whole job:
2595
2596 (cond
2597 ; Simplest situation - level 1:
fd5359c6 2598 ((<= depth 1) (setq header-lead "") allout-primary-bullet)
1977b8f6 2599 ; Simple, too: all asterisks:
fd5359c6 2600 (allout-old-style-prefixes
1977b8f6
RS
2601 ;; Cheat - make body the whole thing, null out header-lead and
2602 ;; bullet-char:
2603 (setq body (make-string depth
fd5359c6 2604 (string-to-char allout-primary-bullet)))
1977b8f6
RS
2605 (setq header-lead "")
2606 "")
2607
2608 ;; (Neither level 1 nor old-style, so we're space padding.
2609 ;; Sneak it in the condition of the next case, whatever it is.)
2610
2611 ;; Solicitation overrides numbering and other cases:
2612 ((progn (setq body (make-string (- depth 2) ?\ ))
2613 ;; The actual condition:
2614 solicit)
fd5359c6 2615 (let* ((got (allout-solicit-alternate-bullet depth solicit)))
1977b8f6 2616 ;; Gotta check whether we're numbering and got a numbered bullet:
fd5359c6 2617 (setq numbering (and allout-numbered-bullet
1977b8f6 2618 (not (and number-control (not index)))
fd5359c6 2619 (string= got allout-numbered-bullet)))
1977b8f6
RS
2620 ;; Now return what we got, regardless:
2621 got))
2622
2623 ;; Numbering invoked through args:
fd5359c6 2624 ((and allout-numbered-bullet number-control)
1977b8f6 2625 (if (setq numbering (not (setq denumbering (not index))))
fd5359c6 2626 allout-numbered-bullet
19b84ba3 2627 (if (and prior-bullet
fd5359c6 2628 (not (string= allout-numbered-bullet
19b84ba3
RS
2629 prior-bullet)))
2630 prior-bullet
fd5359c6 2631 (allout-bullet-for-depth depth))))
1977b8f6
RS
2632
2633 ;;; Neither soliciting nor controlled numbering ;;;
2634 ;;; (may be controlled denumbering, tho) ;;;
2635
2636 ;; Check wrt previous sibling:
2637 ((and new ; only check for new prefixes
fd5359c6
MR
2638 (<= depth (allout-depth))
2639 allout-numbered-bullet ; ... & numbering enabled
1977b8f6
RS
2640 (not denumbering)
2641 (let ((sibling-bullet
2642 (save-excursion
2643 ;; Locate correct sibling:
fd5359c6
MR
2644 (or (>= depth (allout-depth))
2645 (allout-ascend-to-depth depth))
2646 (allout-get-bullet))))
1977b8f6 2647 (if (and sibling-bullet
fd5359c6 2648 (string= allout-numbered-bullet sibling-bullet))
1977b8f6
RS
2649 (setq numbering sibling-bullet)))))
2650
2651 ;; Distinctive prior bullet?
2652 ((and prior-bullet
fd5359c6 2653 (allout-distinctive-bullet prior-bullet)
1977b8f6 2654 ;; Either non-numbered:
fd5359c6
MR
2655 (or (not (and allout-numbered-bullet
2656 (string= prior-bullet allout-numbered-bullet)))
1977b8f6
RS
2657 ;; or numbered, and not denumbering:
2658 (setq numbering (not denumbering)))
2659 ;; Here 'tis:
2660 prior-bullet))
2661
2662 ;; Else, standard bullet per depth:
fd5359c6 2663 ((allout-bullet-for-depth depth)))))
1977b8f6
RS
2664
2665 (concat header-lead
2666 body
2667 bullet-char
2668 (if numbering
2669 (format "%d" (cond ((and index (numberp index)) index)
fd5359c6
MR
2670 (new (1+ (allout-sibling-index depth)))
2671 ((allout-sibling-index))))))
1977b8f6
RS
2672 )
2673 )
fd5359c6
MR
2674;;;_ > allout-open-topic (relative-depth &optional before use_sib_bullet)
2675(defun allout-open-topic (relative-depth &optional before use_sib_bullet)
e126900f 2676 "Open a new topic at depth RELATIVE-DEPTH.
19b84ba3
RS
2677
2678New topic is situated after current one, unless optional flag BEFORE
2679is non-nil, or unless current line is complete empty (not even
2680whitespace), in which case open is done on current line.
c567ac01 2681
9179616f
DL
2682If USE_SIB_BULLET is true, use the bullet of the prior sibling.
2683
c567ac01
RS
2684Nuances:
2685
2686- Creation of new topics is with respect to the visible topic
2687 containing the cursor, regardless of intervening concealed ones.
2688
2689- New headers are generally created after/before the body of a
2690 topic. However, they are created right at cursor location if the
2691 cursor is on a blank line, even if that breaks the current topic
2692 body. This is intentional, to provide a simple means for
2693 deliberately dividing topic bodies.
2694
2695- Double spacing of topic lists is preserved. Also, the first
2696 level two topic is created double-spaced (and so would be
2697 subsequent siblings, if that's left intact). Otherwise,
2698 single-spacing is used.
2699
2700- Creation of sibling or nested topics is with respect to the topic
2701 you're starting from, even when creating backwards. This way you
2702 can easily create a sibling in front of the current topic without
a0776d6b 2703 having to go to its preceding sibling, and then open forward
c567ac01 2704 from there."
1977b8f6 2705
fd5359c6 2706 (let* ((depth (+ (allout-current-depth) relative-depth))
1977b8f6
RS
2707 (opening-on-blank (if (looking-at "^\$")
2708 (not (setq before nil))))
2709 opening-numbered ; Will get while computing ref-topic, below
9179616f
DL
2710 ref-depth ; Will get while computing ref-topic, below
2711 ref-bullet ; Will get while computing ref-topic, next
1977b8f6
RS
2712 (ref-topic (save-excursion
2713 (cond ((< relative-depth 0)
fd5359c6 2714 (allout-ascend-to-depth depth))
1977b8f6 2715 ((>= relative-depth 1) nil)
fd5359c6
MR
2716 (t (allout-back-to-current-heading)))
2717 (setq ref-depth (allout-recent-depth))
9179616f 2718 (setq ref-bullet
fd5359c6
MR
2719 (if (> allout-recent-prefix-end 1)
2720 (allout-recent-bullet)
9179616f 2721 ""))
1977b8f6
RS
2722 (setq opening-numbered
2723 (save-excursion
fd5359c6 2724 (and allout-numbered-bullet
1977b8f6 2725 (or (<= relative-depth 0)
fd5359c6
MR
2726 (allout-descend-to-depth depth))
2727 (if (allout-numbered-type-prefix)
2728 allout-numbered-bullet))))
1977b8f6
RS
2729 (point)))
2730 dbl-space
c567ac01 2731 doing-beginning)
1977b8f6
RS
2732
2733 (if (not opening-on-blank)
2734 ; Positioning and vertical
2735 ; padding - only if not
2736 ; opening-on-blank:
353e2ef2 2737 (progn
1977b8f6
RS
2738 (goto-char ref-topic)
2739 (setq dbl-space ; Determine double space action:
c567ac01
RS
2740 (or (and (<= relative-depth 0) ; not descending;
2741 (save-excursion
a0776d6b 2742 ;; at b-o-b or preceded by a blank line?
c567ac01
RS
2743 (or (> 0 (forward-line -1))
2744 (looking-at "^\\s-*$")
2745 (bobp)))
1977b8f6 2746 (save-excursion
c567ac01 2747 ;; succeeded by a blank line?
fd5359c6 2748 (allout-end-of-current-subtree)
c567ac01 2749 (bolp)))
1977b8f6
RS
2750 (and (= ref-depth 1)
2751 (or before
2752 (= depth 1)
2753 (save-excursion
2754 ;; Don't already have following
2755 ;; vertical padding:
fd5359c6 2756 (not (allout-pre-next-preface)))))))
1977b8f6
RS
2757
2758 ; Position to prior heading,
c567ac01
RS
2759 ; if inserting backwards, and
2760 ; not going outwards:
2761 (if (and before (>= relative-depth 0))
fd5359c6 2762 (progn (allout-back-to-current-heading)
1977b8f6 2763 (setq doing-beginning (bobp))
c567ac01 2764 (if (not (bobp))
fd5359c6 2765 (allout-previous-heading)))
c567ac01 2766 (if (and before (bobp))
fd5359c6 2767 (allout-unprotected (open-line 1))))
1977b8f6 2768
c567ac01 2769 (if (<= relative-depth 0)
1977b8f6
RS
2770 ;; Not going inwards, don't snug up:
2771 (if doing-beginning
fd5359c6 2772 (allout-unprotected (open-line (if dbl-space 2 1)))
c567ac01
RS
2773 (if before
2774 (progn (end-of-line)
fd5359c6 2775 (allout-pre-next-preface)
c567ac01
RS
2776 (while (= ?\r (following-char))
2777 (forward-char 1))
2778 (if (not (looking-at "^$"))
fd5359c6
MR
2779 (allout-unprotected (open-line 1))))
2780 (allout-end-of-current-subtree)))
1977b8f6
RS
2781 ;; Going inwards - double-space if first offspring is,
2782 ;; otherwise snug up.
2783 (end-of-line) ; So we skip any concealed progeny.
fd5359c6 2784 (allout-pre-next-preface)
1977b8f6
RS
2785 (if (bolp)
2786 ;; Blank lines between current header body and next
2787 ;; header - get to last substantive (non-white-space)
2788 ;; line in body:
2789 (re-search-backward "[^ \t\n]" nil t))
2790 (if (save-excursion
fd5359c6
MR
2791 (allout-next-heading)
2792 (if (> (allout-recent-depth) ref-depth)
1977b8f6
RS
2793 ;; This is an offspring.
2794 (progn (forward-line -1)
2795 (looking-at "^\\s-*$"))))
2796 (progn (forward-line 1)
fd5359c6 2797 (allout-unprotected (open-line 1))))
1977b8f6
RS
2798 (end-of-line))
2799 ;;(if doing-beginning (goto-char doing-beginning))
c567ac01
RS
2800 (if (not (bobp))
2801 (progn (if (and (not (> depth ref-depth))
2802 (not before))
fd5359c6 2803 (allout-unprotected (open-line 1))
c567ac01 2804 (if (> depth ref-depth)
fd5359c6 2805 (allout-unprotected (newline 1))
c567ac01 2806 (if dbl-space
fd5359c6 2807 (allout-unprotected (open-line 1))
c567ac01 2808 (if (not before)
fd5359c6 2809 (allout-unprotected (newline 1))))))
c567ac01 2810 (if dbl-space
fd5359c6 2811 (allout-unprotected (newline 1)))
c567ac01
RS
2812 (if (and (not (eobp))
2813 (not (bolp)))
2814 (forward-char 1))))
1977b8f6 2815 ))
fd5359c6 2816 (insert (concat (allout-make-topic-prefix opening-numbered
eac9cf5f
PJ
2817 t
2818 depth)
2819 " "))
1977b8f6
RS
2820
2821 ;;(if doing-beginning (save-excursion (newline (if dbl-space 2 1))))
2822
2823
fd5359c6 2824 (allout-rebullet-heading (and use_sib_bullet ref-bullet);;; solicit
9179616f
DL
2825 depth ;;; depth
2826 nil ;;; number-control
2827 nil ;;; index
1977b8f6
RS
2828 t) (end-of-line)
2829 )
2830 )
c567ac01
RS
2831;;;_ . open-topic contingencies
2832;;;_ ; base topic - one from which open was issued
2833;;;_ , beginning char
a0776d6b 2834;;;_ , amount of space before will be used, unless opening in place
c567ac01
RS
2835;;;_ , end char will be used, unless opening before (and it still may)
2836;;;_ ; absolute depth of new topic
2837;;;_ ! insert in place - overrides most stuff
2838;;;_ ; relative depth of new re base
2839;;;_ ; before or after base topic
2840;;;_ ; spacing around topic, if any, prior to new topic and at same depth
2841;;;_ ; buffer boundaries - special provisions for beginning and end ob
2842;;;_ ; level 1 topics have special provisions also - double space.
2843;;;_ ; location of new topic
fd5359c6
MR
2844;;;_ > allout-open-subtopic (arg)
2845(defun allout-open-subtopic (arg)
c567ac01
RS
2846 "Open new topic header at deeper level than the current one.
2847
2848Negative universal arg means to open deeper, but place the new topic
2849prior to the current one."
1977b8f6 2850 (interactive "p")
fd5359c6
MR
2851 (allout-open-topic 1 (> 0 arg)))
2852;;;_ > allout-open-sibtopic (arg)
2853(defun allout-open-sibtopic (arg)
19b84ba3
RS
2854 "Open new topic header at same level as the current one.
2855
9179616f
DL
2856Positive universal arg means to use the bullet of the prior sibling.
2857
19b84ba3 2858Negative universal arg means to place the new topic prior to the current
c567ac01 2859one."
1977b8f6 2860 (interactive "p")
fd5359c6
MR
2861 (allout-open-topic 0 (> 0 arg) (< 1 arg)))
2862;;;_ > allout-open-supertopic (arg)
2863(defun allout-open-supertopic (arg)
c567ac01 2864 "Open new topic header at shallower level than the current one.
19b84ba3 2865
c567ac01
RS
2866Negative universal arg means to open shallower, but place the new
2867topic prior to the current one."
1977b8f6
RS
2868
2869 (interactive "p")
fd5359c6 2870 (allout-open-topic -1 (> 0 arg)))
c567ac01
RS
2871
2872;;;_ - Outline Alteration
2873;;;_ : Topic Modification
fd5359c6
MR
2874;;;_ = allout-former-auto-filler
2875(defvar allout-former-auto-filler nil
2265e017 2876 "Name of modal fill function being wrapped by `allout-auto-fill'.")
fd5359c6
MR
2877;;;_ > allout-auto-fill ()
2878(defun allout-auto-fill ()
aad94676 2879 "`allout-mode' autofill function.
19b84ba3
RS
2880
2881Maintains outline hanging topic indentation if
fd5359c6
MR
2882`allout-use-hanging-indents' is set."
2883 (let ((fill-prefix (if allout-use-hanging-indents
c567ac01
RS
2884 ;; Check for topic header indentation:
2885 (save-excursion
2886 (beginning-of-line)
fd5359c6 2887 (if (looking-at allout-regexp)
c567ac01
RS
2888 ;; ... construct indentation to account for
2889 ;; length of topic prefix:
fd5359c6 2890 (make-string (progn (allout-end-of-prefix)
c567ac01
RS
2891 (current-column))
2892 ?\ ))))))
fd5359c6 2893 (if (or allout-former-auto-filler allout-use-hanging-indents)
c567ac01 2894 (do-auto-fill))))
fd5359c6
MR
2895;;;_ > allout-reindent-body (old-depth new-depth &optional number)
2896(defun allout-reindent-body (old-depth new-depth &optional number)
e126900f 2897 "Reindent body lines which were indented at OLD-DEPTH to NEW-DEPTH.
c567ac01
RS
2898
2899Optional arg NUMBER indicates numbering is being added, and it must
a0776d6b 2900be accommodated.
c567ac01
RS
2901
2902Note that refill of indented paragraphs is not done."
1977b8f6
RS
2903
2904 (save-excursion
fd5359c6 2905 (allout-end-of-prefix)
c567ac01
RS
2906 (let* ((new-margin (current-column))
2907 excess old-indent-begin old-indent-end
2908 curr-ind
2909 ;; We want the column where the header-prefix text started
2910 ;; *before* the prefix was changed, so we infer it relative
2911 ;; to the new margin and the shift in depth:
2912 (old-margin (+ old-depth (- new-margin new-depth))))
353e2ef2 2913
c567ac01 2914 ;; Process lines up to (but excluding) next topic header:
fd5359c6 2915 (allout-unprotected
c567ac01
RS
2916 (save-match-data
2917 (while
2918 (and (re-search-forward "[\n\r]\\(\\s-*\\)"
2919 nil
2920 t)
2921 ;; Register the indent data, before we reset the
353e2ef2 2922 ;; match data with a subsequent `looking-at':
c567ac01
RS
2923 (setq old-indent-begin (match-beginning 1)
2924 old-indent-end (match-end 1))
fd5359c6 2925 (not (looking-at allout-regexp)))
c567ac01
RS
2926 (if (> 0 (setq excess (- (current-column)
2927 old-margin)))
2928 ;; Text starts left of old margin - don't adjust:
2929 nil
2930 ;; Text was hanging at or right of old left margin -
2931 ;; reindent it, preserving its existing indentation
2932 ;; beyond the old margin:
2933 (delete-region old-indent-begin old-indent-end)
2934 (indent-to (+ new-margin excess)))))))))
fd5359c6
MR
2935;;;_ > allout-rebullet-current-heading (arg)
2936(defun allout-rebullet-current-heading (arg)
9179616f
DL
2937 "Solicit new bullet for current visible heading."
2938 (interactive "p")
2939 (let ((initial-col (current-column))
fd5359c6 2940 (on-bullet (eq (point)(allout-current-bullet-pos)))
9179616f
DL
2941 (backwards (if (< arg 0)
2942 (setq arg (* arg -1)))))
2943 (while (> arg 0)
fd5359c6
MR
2944 (save-excursion (allout-back-to-current-heading)
2945 (allout-end-of-prefix)
2946 (allout-rebullet-heading t ;;; solicit
9179616f
DL
2947 nil ;;; depth
2948 nil ;;; number-control
2949 nil ;;; index
2950 t)) ;;; do-successors
2951 (setq arg (1- arg))
2952 (if (<= arg 0)
2953 nil
2954 (setq initial-col nil) ; Override positioning back to init col
2955 (if (not backwards)
fd5359c6
MR
2956 (allout-next-visible-heading 1)
2957 (allout-goto-prefix)
2958 (allout-next-visible-heading -1))))
9179616f 2959 (message "Done.")
fd5359c6 2960 (cond (on-bullet (goto-char (allout-current-bullet-pos)))
9179616f 2961 (initial-col (move-to-column initial-col)))))
fd5359c6
MR
2962;;;_ > allout-rebullet-heading (&optional solicit ...)
2963(defun allout-rebullet-heading (&optional solicit
1977b8f6
RS
2964 new-depth
2965 number-control
2966 index
2967 do-successors)
2968
c567ac01 2969 "Adjust bullet of current topic prefix.
1977b8f6 2970
9179616f
DL
2971If SOLICIT is non-nil, then the choice of bullet is solicited from
2972user. If it's a character, then that character is offered as the
2973default, otherwise the one suited to the context \(according to
2974distinction or depth) is offered. If non-nil, then the
2975context-specific bullet is just used.
1977b8f6 2976
e126900f 2977Second arg NEW-DEPTH forces the topic prefix to that depth, regardless
9179616f 2978of the topic's current depth.
1977b8f6 2979
c567ac01 2980Third arg NUMBER-CONTROL can force the prefix to or away from
fd5359c6 2981numbered form. It has effect only if `allout-numbered-bullet' is
c567ac01
RS
2982non-nil and soliciting was not explicitly invoked (via first arg).
2983Its effect, numbering or denumbering, then depends on the setting
45435c0e 2984of the fourth arg, INDEX.
1977b8f6 2985
45435c0e 2986If NUMBER-CONTROL is non-nil and fourth arg INDEX is nil, then the
c567ac01
RS
2987prefix of the topic is forced to be non-numbered. Null index and
2988non-nil NUMBER-CONTROL forces denumbering. Non-nil INDEX (and
2989non-nil NUMBER-CONTROL) forces a numbered-prefix form. If non-nil
2990INDEX is a number, then that number is used for the numbered
2991prefix. Non-nil and non-number means that the index for the
2265e017 2992numbered prefix will be derived by `allout-make-topic-prefix'.
1977b8f6 2993
c567ac01
RS
2994Fifth arg DO-SUCCESSORS t means re-resolve count on succeeding
2995siblings.
1977b8f6 2996
fd5359c6
MR
2997Cf vars `allout-stylish-prefixes', `allout-old-style-prefixes',
2998and `allout-numbered-bullet', which all affect the behavior of
c567ac01 2999this function."
1977b8f6 3000
fd5359c6 3001 (let* ((current-depth (allout-depth))
1977b8f6 3002 (new-depth (or new-depth current-depth))
fd5359c6
MR
3003 (mb allout-recent-prefix-beginning)
3004 (me allout-recent-prefix-end)
1977b8f6 3005 (current-bullet (buffer-substring (- me 1) me))
fd5359c6 3006 (new-prefix (allout-make-topic-prefix current-bullet
1977b8f6
RS
3007 nil
3008 new-depth
3009 solicit
3010 number-control
3011 index)))
3012
c567ac01 3013 ;; Is new one is identical to old?
1977b8f6
RS
3014 (if (and (= current-depth new-depth)
3015 (string= current-bullet
3016 (substring new-prefix (1- (length new-prefix)))))
c567ac01 3017 ;; Nothing to do:
1977b8f6
RS
3018 t
3019
3020 ;; New prefix probably different from old:
c567ac01 3021 ; get rid of old one:
fd5359c6 3022 (allout-unprotected (delete-region mb me))
1977b8f6 3023 (goto-char mb)
c567ac01
RS
3024 ; Dispense with number if
3025 ; numbered-bullet prefix:
fd5359c6
MR
3026 (if (and allout-numbered-bullet
3027 (string= allout-numbered-bullet current-bullet)
1977b8f6 3028 (looking-at "[0-9]+"))
fd5359c6 3029 (allout-unprotected
c567ac01 3030 (delete-region (match-beginning 0)(match-end 0))))
1977b8f6 3031
c567ac01 3032 ; Put in new prefix:
fd5359c6 3033 (allout-unprotected (insert new-prefix))
1977b8f6 3034
c567ac01 3035 ;; Reindent the body if elected and margin changed:
fd5359c6 3036 (if (and allout-reindent-bodies
c567ac01 3037 (not (= new-depth current-depth)))
fd5359c6 3038 (allout-reindent-body current-depth new-depth))
1977b8f6 3039
c567ac01
RS
3040 ;; Recursively rectify successive siblings of orig topic if
3041 ;; caller elected for it:
3042 (if do-successors
3043 (save-excursion
fd5359c6 3044 (while (allout-next-sibling new-depth nil)
c567ac01
RS
3045 (setq index
3046 (cond ((numberp index) (1+ index))
fd5359c6
MR
3047 ((not number-control) (allout-sibling-index))))
3048 (if (allout-numbered-type-prefix)
3049 (allout-rebullet-heading nil ;;; solicit
c567ac01
RS
3050 new-depth ;;; new-depth
3051 number-control;;; number-control
3052 index ;;; index
3053 nil))))) ;;;(dont!)do-successors
3054 ) ; (if (and (= current-depth new-depth)...))
fd5359c6 3055 ) ; let* ((current-depth (allout-depth))...)
c567ac01 3056 ) ; defun
fd5359c6
MR
3057;;;_ > allout-rebullet-topic (arg)
3058(defun allout-rebullet-topic (arg)
2265e017 3059 "Like `allout-rebullet-topic-grunt', but start from topic visible at point.
19b84ba3 3060
c567ac01 3061Descends into invisible as well as visible topics, however.
1977b8f6 3062
c567ac01 3063With repeat count, shift topic depth by that amount."
1977b8f6
RS
3064 (interactive "P")
3065 (let ((start-col (current-column))
3066 (was-eol (eolp)))
3067 (save-excursion
3068 ;; Normalize arg:
3069 (cond ((null arg) (setq arg 0))
3070 ((listp arg) (setq arg (car arg))))
3071 ;; Fill the user in, in case we're shifting a big topic:
3072 (if (not (zerop arg)) (message "Shifting..."))
fd5359c6
MR
3073 (allout-back-to-current-heading)
3074 (if (<= (+ (allout-recent-depth) arg) 0)
1977b8f6 3075 (error "Attempt to shift topic below level 1"))
fd5359c6 3076 (allout-rebullet-topic-grunt arg)
1977b8f6 3077 (if (not (zerop arg)) (message "Shifting... done.")))
c567ac01 3078 (move-to-column (max 0 (+ start-col arg)))))
fd5359c6
MR
3079;;;_ > allout-rebullet-topic-grunt (&optional relative-depth ...)
3080(defun allout-rebullet-topic-grunt (&optional relative-depth
1977b8f6
RS
3081 starting-depth
3082 starting-point
3083 index
3084 do-successors)
3085
c567ac01 3086 "Rebullet the topic at point, visible or invisible, and all
2265e017 3087contained subtopics. See `allout-rebullet-heading' for rebulleting
c567ac01 3088behavior.
1977b8f6 3089
e126900f 3090Arg RELATIVE-DEPTH means to shift the depth of the entire
c567ac01 3091topic that amount.
1977b8f6 3092
e126900f
JB
3093\(fn &optional RELATIVE-DEPTH)"
3094
3095 ;; All args except the first one are for internal recursive use by the
3096 ;; function itself.
1977b8f6
RS
3097
3098 (let* ((relative-depth (or relative-depth 0))
fd5359c6 3099 (new-depth (allout-depth))
1977b8f6
RS
3100 (starting-depth (or starting-depth new-depth))
3101 (on-starting-call (null starting-point))
3102 (index (or index
3103 ;; Leave index null on starting call, so rebullet-heading
3104 ;; calculates it at what might be new depth:
3105 (and (or (zerop relative-depth)
3106 (not on-starting-call))
fd5359c6 3107 (allout-sibling-index))))
1977b8f6
RS
3108 (moving-outwards (< 0 relative-depth))
3109 (starting-point (or starting-point (point))))
3110
3111 ;; Sanity check for excessive promotion done only on starting call:
3112 (and on-starting-call
3113 moving-outwards
3114 (> 0 (+ starting-depth relative-depth))
6a05d05f 3115 (error "Attempt to shift topic out beyond level 1")) ;;; ====>
1977b8f6
RS
3116
3117 (cond ((= starting-depth new-depth)
3118 ;; We're at depth to work on this one:
fd5359c6 3119 (allout-rebullet-heading nil ;;; solicit
1977b8f6
RS
3120 (+ starting-depth ;;; starting-depth
3121 relative-depth)
3122 nil ;;; number
3123 index ;;; index
3124 ;; Every contained topic will get hit,
3125 ;; and we have to get to outside ones
3126 ;; deliberately:
3127 nil) ;;; do-successors
3128 ;; ... and work on subsequent ones which are at greater depth:
3129 (setq index 0)
fd5359c6 3130 (allout-next-heading)
1977b8f6 3131 (while (and (not (eobp))
fd5359c6 3132 (< starting-depth (allout-recent-depth)))
1977b8f6 3133 (setq index (1+ index))
fd5359c6 3134 (allout-rebullet-topic-grunt relative-depth ;;; relative-depth
1977b8f6
RS
3135 (1+ starting-depth);;;starting-depth
3136 starting-point ;;; starting-point
3137 index))) ;;; index
3138
3139 ((< starting-depth new-depth)
3140 ;; Rare case - subtopic more than one level deeper than parent.
3141 ;; Treat this one at an even deeper level:
fd5359c6 3142 (allout-rebullet-topic-grunt relative-depth ;;; relative-depth
1977b8f6
RS
3143 new-depth ;;; starting-depth
3144 starting-point ;;; starting-point
3145 index))) ;;; index
3146
3147 (if on-starting-call
3148 (progn
3149 ;; Rectify numbering of former siblings of the adjusted topic,
3150 ;; if topic has changed depth
3151 (if (or do-successors
3152 (and (not (zerop relative-depth))
fd5359c6
MR
3153 (or (= (allout-recent-depth) starting-depth)
3154 (= (allout-recent-depth) (+ starting-depth
1977b8f6 3155 relative-depth)))))
fd5359c6 3156 (allout-rebullet-heading nil nil nil nil t))
1977b8f6
RS
3157 ;; Now rectify numbering of new siblings of the adjusted topic,
3158 ;; if depth has been changed:
3159 (progn (goto-char starting-point)
3160 (if (not (zerop relative-depth))
fd5359c6 3161 (allout-rebullet-heading nil nil nil nil t)))))
1977b8f6
RS
3162 )
3163 )
fd5359c6
MR
3164;;;_ > allout-renumber-to-depth (&optional depth)
3165(defun allout-renumber-to-depth (&optional depth)
19b84ba3
RS
3166 "Renumber siblings at current depth.
3167
3168Affects superior topics if optional arg DEPTH is less than current depth.
c567ac01
RS
3169
3170Returns final depth."
3171
3172 ;; Proceed by level, processing subsequent siblings on each,
3173 ;; ascending until we get shallower than the start depth:
3174
fd5359c6 3175 (let ((ascender (allout-depth))
9179616f 3176 was-eobp)
c567ac01 3177 (while (and (not (eobp))
fd5359c6
MR
3178 (allout-depth)
3179 (>= (allout-recent-depth) depth)
c567ac01
RS
3180 (>= ascender depth))
3181 ; Skip over all topics at
3182 ; lesser depths, which can not
3183 ; have been disturbed:
9179616f 3184 (while (and (not (setq was-eobp (eobp)))
fd5359c6
MR
3185 (> (allout-recent-depth) ascender))
3186 (allout-next-heading))
c567ac01 3187 ; Prime ascender for ascension:
fd5359c6
MR
3188 (setq ascender (1- (allout-recent-depth)))
3189 (if (>= (allout-recent-depth) depth)
3190 (allout-rebullet-heading nil ;;; solicit
c567ac01
RS
3191 nil ;;; depth
3192 nil ;;; number-control
3193 nil ;;; index
9179616f
DL
3194 t)) ;;; do-successors
3195 (if was-eobp (goto-char (point-max)))))
fd5359c6
MR
3196 (allout-recent-depth))
3197;;;_ > allout-number-siblings (&optional denumber)
3198(defun allout-number-siblings (&optional denumber)
c567ac01 3199 "Assign numbered topic prefix to this topic and its siblings.
1977b8f6 3200
c567ac01
RS
3201With universal argument, denumber - assign default bullet to this
3202topic and its siblings.
1977b8f6 3203
c567ac01
RS
3204With repeated universal argument (`^U^U'), solicit bullet for each
3205rebulleting each topic at this level."
1977b8f6
RS
3206
3207 (interactive "P")
3208
3209 (save-excursion
fd5359c6
MR
3210 (allout-back-to-current-heading)
3211 (allout-beginning-of-level)
3212 (let ((depth (allout-recent-depth))
c567ac01 3213 (index (if (not denumber) 1))
1977b8f6
RS
3214 (use-bullet (equal '(16) denumber))
3215 (more t))
3216 (while more
fd5359c6 3217 (allout-rebullet-heading use-bullet ;;; solicit
c567ac01 3218 depth ;;; depth
1977b8f6
RS
3219 t ;;; number-control
3220 index ;;; index
3221 nil) ;;; do-successors
3222 (if index (setq index (1+ index)))
fd5359c6
MR
3223 (setq more (allout-next-sibling depth nil))))))
3224;;;_ > allout-shift-in (arg)
3225(defun allout-shift-in (arg)
19b84ba3 3226 "Increase depth of current heading and any topics collapsed within it."
1977b8f6 3227 (interactive "p")
fd5359c6
MR
3228 (allout-rebullet-topic arg))
3229;;;_ > allout-shift-out (arg)
3230(defun allout-shift-out (arg)
19b84ba3 3231 "Decrease depth of current heading and any topics collapsed within it."
1977b8f6 3232 (interactive "p")
fd5359c6 3233 (allout-rebullet-topic (* arg -1)))
c567ac01 3234;;;_ : Surgery (kill-ring) functions with special provisions for outlines:
fd5359c6
MR
3235;;;_ > allout-kill-line (&optional arg)
3236(defun allout-kill-line (&optional arg)
c567ac01 3237 "Kill line, adjusting subsequent lines suitably for outline mode."
1977b8f6
RS
3238
3239 (interactive "*P")
fd5359c6
MR
3240 (if (not (and (allout-mode-p) ; active outline mode,
3241 allout-numbered-bullet ; numbers may need adjustment,
c567ac01 3242 (bolp) ; may be clipping topic head,
fd5359c6 3243 (looking-at allout-regexp))) ; are clipping topic head.
1977b8f6
RS
3244 ;; Above conditions do not obtain - just do a regular kill:
3245 (kill-line arg)
3246 ;; Ah, have to watch out for adjustments:
fd5359c6 3247 (let* ((depth (allout-depth)))
c567ac01 3248 ; Do the kill:
1977b8f6 3249 (kill-line arg)
c567ac01 3250 ; Provide some feedback:
1977b8f6
RS
3251 (sit-for 0)
3252 (save-excursion
c567ac01
RS
3253 ; Start with the topic
3254 ; following killed line:
fd5359c6
MR
3255 (if (not (looking-at allout-regexp))
3256 (allout-next-heading))
3257 (allout-renumber-to-depth depth)))))
3258;;;_ > allout-kill-topic ()
3259(defun allout-kill-topic ()
c567ac01
RS
3260 "Kill topic together with subtopics.
3261
3262Leaves primary topic's trailing vertical whitespace, if any."
1977b8f6
RS
3263
3264 ;; Some finagling is done to make complex topic kills appear faster
3265 ;; than they actually are. A redisplay is performed immediately
3266 ;; after the region is disposed of, though the renumbering process
3267 ;; has yet to be performed. This means that there may appear to be
3268 ;; a lag *after* the kill has been performed.
3269
3270 (interactive)
fd5359c6
MR
3271 (let* ((beg (prog1 (allout-back-to-current-heading)(beginning-of-line)))
3272 (depth (allout-recent-depth)))
3273 (allout-end-of-current-subtree)
1977b8f6 3274 (if (not (eobp))
c567ac01
RS
3275 (if (or (not (looking-at "^$"))
3276 ;; A blank line - cut it with this topic *unless* this
3277 ;; is the last topic at this level, in which case
3278 ;; we'll leave the blank line as part of the
3279 ;; containing topic:
3280 (save-excursion
fd5359c6
MR
3281 (and (allout-next-heading)
3282 (>= (allout-recent-depth) depth))))
c567ac01 3283 (forward-char 1)))
353e2ef2 3284
1977b8f6
RS
3285 (kill-region beg (point))
3286 (sit-for 0)
3287 (save-excursion
fd5359c6
MR
3288 (allout-renumber-to-depth depth))))
3289;;;_ > allout-yank-processing ()
3290(defun allout-yank-processing (&optional arg)
c567ac01 3291
aad94676 3292 "Incidental outline specific business to be done just after text yanks.
19b84ba3 3293
c567ac01 3294Does depth adjustment of yanked topics, when:
1977b8f6 3295
c567ac01
RS
32961 the stuff being yanked starts with a valid outline header prefix, and
32972 it is being yanked at the end of a line which consists of only a valid
1977b8f6
RS
3298 topic prefix.
3299
a0776d6b 3300Also, adjusts numbering of subsequent siblings when appropriate.
1977b8f6 3301
c567ac01
RS
3302Depth adjustment alters the depth of all the topics being yanked
3303the amount it takes to make the first topic have the depth of the
3304header into which it's being yanked.
1977b8f6 3305
c567ac01
RS
3306The point is left in front of yanked, adjusted topics, rather than
3307at the end (and vice-versa with the mark). Non-adjusted yanks,
aad94676 3308however, are left exactly like normal, not outline specific yanks."
c567ac01
RS
3309
3310 (interactive "*P")
3311 ; Get to beginning, leaving
3312 ; region around subject:
9179616f 3313 (if (< (my-mark-marker t) (point))
c567ac01
RS
3314 (exchange-point-and-mark))
3315 (let* ((subj-beg (point))
9179616f
DL
3316 (subj-end (my-mark-marker t))
3317 ;; 'resituate' if yanking an entire topic into topic header:
fd5359c6
MR
3318 (resituate (and (allout-e-o-prefix-p)
3319 (looking-at (concat "\\(" allout-regexp "\\)"))
3320 (allout-prefix-data (match-beginning 1)
c567ac01 3321 (match-end 1))))
353e2ef2 3322 ;; `rectify-numbering' if resituating (where several topics may
c567ac01
RS
3323 ;; be resituating) or yanking a topic into a topic slot (bol):
3324 (rectify-numbering (or resituate
fd5359c6 3325 (and (bolp) (looking-at allout-regexp)))))
c567ac01
RS
3326 (if resituate
3327 ; The yanked stuff is a topic:
3328 (let* ((prefix-len (- (match-end 1) subj-beg))
fd5359c6
MR
3329 (subj-depth (allout-recent-depth))
3330 (prefix-bullet (allout-recent-bullet))
c567ac01
RS
3331 (adjust-to-depth
3332 ;; Nil if adjustment unnecessary, otherwise depth to which
3333 ;; adjustment should be made:
3334 (save-excursion
3335 (and (goto-char subj-end)
3336 (eolp)
3337 (goto-char subj-beg)
fd5359c6 3338 (and (looking-at allout-regexp)
c567ac01
RS
3339 (progn
3340 (beginning-of-line)
3341 (not (= (point) subj-beg)))
fd5359c6
MR
3342 (looking-at allout-regexp)
3343 (allout-prefix-data (match-beginning 0)
c567ac01 3344 (match-end 0)))
fd5359c6 3345 (allout-recent-depth))))
c567ac01
RS
3346 done
3347 (more t))
fd5359c6 3348 (setq rectify-numbering allout-numbered-bullet)
c567ac01
RS
3349 (if adjust-to-depth
3350 ; Do the adjustment:
3351 (progn
3352 (message "... yanking") (sit-for 0)
3353 (save-restriction
3354 (narrow-to-region subj-beg subj-end)
3355 ; Trim off excessive blank
3356 ; line at end, if any:
3357 (goto-char (point-max))
3358 (if (looking-at "^$")
fd5359c6 3359 (allout-unprotected (delete-char -1)))
c567ac01
RS
3360 ; Work backwards, with each
3361 ; shallowest level,
3362 ; successively excluding the
3363 ; last processed topic from
3364 ; the narrow region:
3365 (while more
fd5359c6 3366 (allout-back-to-current-heading)
c567ac01 3367 ; go as high as we can in each bunch:
fd5359c6 3368 (while (allout-ascend-to-depth (1- (allout-depth))))
c567ac01 3369 (save-excursion
fd5359c6 3370 (allout-rebullet-topic-grunt (- adjust-to-depth
c567ac01 3371 subj-depth))
fd5359c6 3372 (allout-depth))
c567ac01
RS
3373 (if (setq more (not (bobp)))
3374 (progn (widen)
3375 (forward-char -1)
3376 (narrow-to-region subj-beg (point))))))
3377 (message "")
3378 ;; Preserve new bullet if it's a distinctive one, otherwise
3379 ;; use old one:
3380 (if (string-match (regexp-quote prefix-bullet)
fd5359c6 3381 allout-distinctive-bullets-string)
c567ac01
RS
3382 ; Delete from bullet of old to
3383 ; before bullet of new:
3384 (progn
3385 (beginning-of-line)
3386 (delete-region (point) subj-beg)
9179616f 3387 (set-marker (my-mark-marker t) subj-end)
c567ac01 3388 (goto-char subj-beg)
fd5359c6 3389 (allout-end-of-prefix))
c567ac01
RS
3390 ; Delete base subj prefix,
3391 ; leaving old one:
3392 (delete-region (point) (+ (point)
3393 prefix-len
3394 (- adjust-to-depth subj-depth)))
3395 ; and delete residual subj
3396 ; prefix digits and space:
3397 (while (looking-at "[0-9]") (delete-char 1))
3398 (if (looking-at " ") (delete-char 1))))
3399 (exchange-point-and-mark))))
3400 (if rectify-numbering
353e2ef2 3401 (progn
c567ac01
RS
3402 (save-excursion
3403 ; Give some preliminary feedback:
3404 (message "... reconciling numbers") (sit-for 0)
3405 ; ... and renumber, in case necessary:
3406 (goto-char subj-beg)
fd5359c6
MR
3407 (if (allout-goto-prefix)
3408 (allout-rebullet-heading nil ;;; solicit
3409 (allout-depth) ;;; depth
c567ac01
RS
3410 nil ;;; number-control
3411 nil ;;; index
3412 t))
3413 (message ""))))
3414 (if (not resituate)
3415 (exchange-point-and-mark))))
fd5359c6
MR
3416;;;_ > allout-yank (&optional arg)
3417(defun allout-yank (&optional arg)
aad94676 3418 "`allout-mode' yank, with depth and numbering adjustment of yanked topics.
19b84ba3 3419
a0776d6b 3420Non-topic yanks work no differently than normal yanks.
c567ac01
RS
3421
3422If a topic is being yanked into a bare topic prefix, the depth of the
3423yanked topic is adjusted to the depth of the topic prefix.
3424
2265e017 3425 1 we're yanking in an `allout-mode' buffer
c567ac01
RS
3426 2 the stuff being yanked starts with a valid outline header prefix, and
3427 3 it is being yanked at the end of a line which consists of only a valid
3428 topic prefix.
3429
3430If these conditions hold then the depth of the yanked topics are all
3431adjusted the amount it takes to make the first one at the depth of the
3432header into which it's being yanked.
3433
3434The point is left in front of yanked, adjusted topics, rather than
3435at the end (and vice-versa with the mark). Non-adjusted yanks,
3436however, (ones that don't qualify for adjustment) are handled
3437exactly like normal yanks.
3438
a0776d6b 3439Numbering of yanked topics, and the successive siblings at the depth
c567ac01
RS
3440into which they're being yanked, is adjusted.
3441
aad94676 3442`allout-yank-pop' works with `allout-yank' just like normal yank-pop
c567ac01 3443works with normal yank in non-outline buffers."
1977b8f6
RS
3444
3445 (interactive "*P")
3446 (setq this-command 'yank)
c567ac01 3447 (yank arg)
fd5359c6
MR
3448 (if (allout-mode-p)
3449 (allout-yank-processing)))
3450;;;_ > allout-yank-pop (&optional arg)
3451(defun allout-yank-pop (&optional arg)
2265e017 3452 "Yank-pop like `allout-yank' when popping to bare outline prefixes.
19b84ba3
RS
3453
3454Adapts level of popped topics to level of fresh prefix.
c567ac01
RS
3455
3456Note - prefix changes to distinctive bullets will stick, if followed
3457by pops to non-distinctive yanks. Bug..."
1977b8f6
RS
3458
3459 (interactive "*p")
1977b8f6 3460 (setq this-command 'yank)
c567ac01 3461 (yank-pop arg)
fd5359c6
MR
3462 (if (allout-mode-p)
3463 (allout-yank-processing)))
1977b8f6 3464
c567ac01
RS
3465;;;_ - Specialty bullet functions
3466;;;_ : File Cross references
fd5359c6
MR
3467;;;_ > allout-resolve-xref ()
3468(defun allout-resolve-xref ()
19b84ba3
RS
3469 "Pop to file associated with current heading, if it has an xref bullet.
3470
fd5359c6 3471\(Works according to setting of `allout-file-xref-bullet')."
1977b8f6 3472 (interactive)
fd5359c6 3473 (if (not allout-file-xref-bullet)
1977b8f6 3474 (error
fd5359c6
MR
3475 "outline cross references disabled - no `allout-file-xref-bullet'")
3476 (if (not (string= (allout-current-bullet) allout-file-xref-bullet))
353e2ef2 3477 (error "current heading lacks cross-reference bullet `%s'"
fd5359c6 3478 allout-file-xref-bullet)
1977b8f6
RS
3479 (let (file-name)
3480 (save-excursion
fd5359c6 3481 (let* ((text-start allout-recent-prefix-end)
fa29cfef 3482 (heading-end (progn (end-of-line) (point))))
1977b8f6
RS
3483 (goto-char text-start)
3484 (setq file-name
3485 (if (re-search-forward "\\s-\\(\\S-*\\)" heading-end t)
3486 (buffer-substring (match-beginning 1) (match-end 1))))))
3487 (setq file-name
3488 (if (not (= (aref file-name 0) ?:))
3489 (expand-file-name file-name)
353e2ef2 3490 ; A registry-files ref, strip the `:'
1977b8f6
RS
3491 ; and try to follow it:
3492 (let ((reg-ref (reference-registered-file
3493 (substring file-name 1) nil t)))
3494 (if reg-ref (car (cdr reg-ref))))))
3495 (if (or (file-exists-p file-name)
3496 (if (file-writable-p file-name)
3497 (y-or-n-p (format "%s not there, create one? "
3498 file-name))
3499 (error "%s not found and can't be created" file-name)))
3500 (condition-case failure
3501 (find-file-other-window file-name)
9179616f 3502 ('error failure))
1977b8f6
RS
3503 (error "%s not found" file-name))
3504 )
3505 )
3506 )
3507 )
19b84ba3 3508
9179616f 3509;;;_ #6 Exposure Control
c567ac01
RS
3510
3511;;;_ - Fundamental
fd5359c6
MR
3512;;;_ > allout-flag-current-subtree (flag)
3513(defun allout-flag-current-subtree (flag)
19b84ba3
RS
3514 "Hide or show subtree of currently-visible topic.
3515
fd5359c6 3516See `allout-flag-region' for more details."
19b84ba3 3517
c567ac01 3518 (save-excursion
fd5359c6
MR
3519 (allout-back-to-current-heading)
3520 (allout-flag-region (point)
3521 (progn (allout-end-of-current-subtree) (1- (point)))
19b84ba3 3522 flag)))
c567ac01 3523
c567ac01 3524;;;_ - Topic-specific
fd5359c6
MR
3525;;;_ > allout-show-entry ()
3526(defun allout-show-entry ()
3527 "Like `allout-show-current-entry', reveals entries nested in hidden topics.
c567ac01
RS
3528
3529This is a way to give restricted peek at a concealed locality without the
3530expense of exposing its context, but can leave the outline with aberrant
aad94676 3531exposure. `allout-hide-current-entry-completely' or `allout-show-to-offshoot'
c567ac01
RS
3532should be used after the peek to rectify the exposure."
3533
3534 (interactive)
3535 (save-excursion
9179616f
DL
3536 (let ((at (point))
3537 beg end)
fd5359c6 3538 (allout-goto-prefix)
9179616f
DL
3539 (setq beg (if (= (preceding-char) ?\r) (1- (point)) (point)))
3540 (re-search-forward "[\n\r]" nil t)
3541 (setq end (1- (if (< at (point))
3542 ;; We're on topic head line - show only it:
3543 (point)
3544 ;; or we're in body - include it:
fd5359c6
MR
3545 (max beg (or (allout-pre-next-preface) (point))))))
3546 (allout-flag-region beg end ?\n)
9179616f 3547 (list beg end))))
fd5359c6
MR
3548;;;_ > allout-show-children (&optional level strict)
3549(defun allout-show-children (&optional level strict)
c567ac01
RS
3550
3551 "If point is visible, show all direct subheadings of this heading.
19b84ba3 3552
2265e017 3553Otherwise, do `allout-show-to-offshoot', and then show subheadings.
c567ac01
RS
3554
3555Optional LEVEL specifies how many levels below the current level
3556should be shown, or all levels if t. Default is 1.
3557
3558Optional STRICT means don't resort to -show-to-offshoot, no matter
3559what. This is basically so -show-to-offshoot, which is called by
3560this function, can employ the pure offspring-revealing capabilities of
19b84ba3
RS
3561it.
3562
3563Returns point at end of subtree that was opened, if any. (May get a
3564point of non-opened subtree?)"
c567ac01
RS
3565
3566 (interactive "p")
19b84ba3
RS
3567 (let (max-pos)
3568 (if (and (not strict)
fd5359c6 3569 (allout-hidden-p))
c567ac01 3570
fd5359c6 3571 (progn (allout-show-to-offshoot) ; Point's concealed, open to
19b84ba3
RS
3572 ; expose it.
3573 ;; Then recurse, but with "strict" set so we don't
3574 ;; infinite regress:
fd5359c6 3575 (setq max-pos (allout-show-children level t)))
c567ac01 3576
19b84ba3
RS
3577 (save-excursion
3578 (save-restriction
3579 (let* ((start-pt (point))
fd5359c6
MR
3580 (chart (allout-chart-subtree (or level 1)))
3581 (to-reveal (allout-chart-to-reveal chart (or level 1))))
19b84ba3
RS
3582 (goto-char start-pt)
3583 (if (and strict (= (preceding-char) ?\r))
3584 ;; Concealed root would already have been taken care of,
3585 ;; unless strict was set.
9179616f 3586 (progn
fd5359c6
MR
3587 (allout-flag-region (point) (allout-snug-back) ?\n)
3588 (if allout-show-bodies
9179616f 3589 (progn (goto-char (car to-reveal))
fd5359c6 3590 (allout-show-current-entry)))))
19b84ba3
RS
3591 (while to-reveal
3592 (goto-char (car to-reveal))
fd5359c6
MR
3593 (allout-flag-region (point) (allout-snug-back) ?\n)
3594 (if allout-show-bodies
9179616f 3595 (progn (goto-char (car to-reveal))
fd5359c6 3596 (allout-show-current-entry)))
19b84ba3 3597 (setq to-reveal (cdr to-reveal)))))))))
fd5359c6
MR
3598;;;_ > allout-hide-point-reconcile ()
3599(defun allout-hide-reconcile ()
3600 "Like `allout-hide-current-entry'; hides completely if within hidden region.
c567ac01
RS
3601
3602Specifically intended for aberrant exposure states, like entries that were
2265e017 3603exposed by `allout-show-entry' but are within otherwise concealed regions."
c567ac01
RS
3604 (interactive)
3605 (save-excursion
fd5359c6
MR
3606 (allout-goto-prefix)
3607 (allout-flag-region (if (not (bobp)) (1- (point)) (point))
3608 (progn (allout-pre-next-preface)
c567ac01
RS
3609 (if (= ?\r (following-char))
3610 (point)
3611 (1- (point))))
3612 ?\r)))
fd5359c6
MR
3613;;;_ > allout-show-to-offshoot ()
3614(defun allout-show-to-offshoot ()
2265e017 3615 "Like `allout-show-entry', but reveals all concealed ancestors, as well.
c567ac01 3616
2265e017
MR
3617As with `allout-hide-current-entry-completely', useful for rectifying
3618aberrant exposure states produced by `allout-show-entry'."
c567ac01
RS
3619
3620 (interactive)
3621 (save-excursion
3622 (let ((orig-pt (point))
fd5359c6 3623 (orig-pref (allout-goto-prefix))
c567ac01
RS
3624 (last-at (point))
3625 bag-it)
3626 (while (or bag-it (= (preceding-char) ?\r))
3627 (beginning-of-line)
3628 (if (= last-at (setq last-at (point)))
3629 ;; Oops, we're not making any progress! Show the current
3630 ;; topic completely, and bag this try.
3631 (progn (beginning-of-line)
fd5359c6 3632 (allout-show-current-subtree)
c567ac01
RS
3633 (goto-char orig-pt)
3634 (setq bag-it t)
3635 (beep)
3636 (message "%s: %s"
fd5359c6 3637 "allout-show-to-offshoot: "
c567ac01 3638 "Aberrant nesting encountered.")))
fd5359c6 3639 (allout-show-children)
c567ac01 3640 (goto-char orig-pref))
19b84ba3 3641 (goto-char orig-pt)))
fd5359c6
MR
3642 (if (allout-hidden-p)
3643 (allout-show-entry)))
3644;;;_ > allout-hide-current-entry ()
3645(defun allout-hide-current-entry ()
c567ac01
RS
3646 "Hide the body directly following this heading."
3647 (interactive)
fd5359c6 3648 (allout-back-to-current-heading)
c567ac01 3649 (save-excursion
fd5359c6
MR
3650 (allout-flag-region (point)
3651 (progn (allout-end-of-current-entry) (point))
9179616f 3652 ?\r)))
fd5359c6
MR
3653;;;_ > allout-show-current-entry (&optional arg)
3654(defun allout-show-current-entry (&optional arg)
c567ac01 3655
19b84ba3 3656 "Show body following current heading, or hide the entry if repeat count."
c567ac01
RS
3657
3658 (interactive "P")
3659 (if arg
fd5359c6 3660 (allout-hide-current-entry)
c567ac01 3661 (save-excursion
fd5359c6
MR
3662 (allout-flag-region (point)
3663 (progn (allout-end-of-current-entry) (point))
19b84ba3 3664 ?\n))))
fd5359c6
MR
3665;;;_ > allout-hide-current-entry-completely ()
3666; ... allout-hide-current-entry-completely also for isearch dynamic exposure:
3667(defun allout-hide-current-entry-completely ()
2265e017 3668 "Like `allout-hide-current-entry', but conceal topic completely.
c567ac01
RS
3669
3670Specifically intended for aberrant exposure states, like entries that were
2265e017 3671exposed by `allout-show-entry' but are within otherwise concealed regions."
c567ac01
RS
3672 (interactive)
3673 (save-excursion
fd5359c6
MR
3674 (allout-goto-prefix)
3675 (allout-flag-region (if (not (bobp)) (1- (point)) (point))
3676 (progn (allout-pre-next-preface)
c567ac01
RS
3677 (if (= ?\r (following-char))
3678 (point)
3679 (1- (point))))
3680 ?\r)))
fd5359c6
MR
3681;;;_ > allout-show-current-subtree (&optional arg)
3682(defun allout-show-current-subtree (&optional arg)
19b84ba3 3683 "Show everything within the current topic. With a repeat-count,
353e2ef2 3684expose this topic and its siblings."
19b84ba3
RS
3685 (interactive "P")
3686 (save-excursion
fd5359c6 3687 (if (<= (allout-current-depth) 0)
19b84ba3 3688 ;; Outside any topics - try to get to the first:
fd5359c6 3689 (if (not (allout-next-heading))
6a05d05f 3690 (error "No topics")
19b84ba3
RS
3691 ;; got to first, outermost topic - set to expose it and siblings:
3692 (message "Above outermost topic - exposing all.")
fd5359c6 3693 (allout-flag-region (point-min)(point-max) ?\n))
19b84ba3 3694 (if (not arg)
fd5359c6
MR
3695 (allout-flag-current-subtree ?\n)
3696 (allout-beginning-of-level)
3697 (allout-expose-topic '(* :))))))
3698;;;_ > allout-hide-current-subtree (&optional just-close)
3699(defun allout-hide-current-subtree (&optional just-close)
19b84ba3 3700 "Close the current topic, or containing topic if this one is already closed.
c567ac01 3701
19b84ba3 3702If this topic is closed and it's a top level topic, close this topic
353e2ef2 3703and its siblings.
19b84ba3
RS
3704
3705If optional arg JUST-CLOSE is non-nil, do not treat the parent or
3706siblings, even if the target topic is already closed."
c567ac01
RS
3707
3708 (interactive)
19b84ba3
RS
3709 (let ((from (point))
3710 (orig-eol (progn (end-of-line)
fd5359c6 3711 (if (not (allout-goto-prefix))
6a05d05f 3712 (error "No topics found")
19b84ba3 3713 (end-of-line)(point)))))
fd5359c6 3714 (allout-flag-current-subtree ?\r)
19b84ba3
RS
3715 (goto-char from)
3716 (if (and (= orig-eol (progn (goto-char orig-eol)
3717 (end-of-line)
3718 (point)))
3719 (not just-close)
c567ac01 3720 ;; Structure didn't change - try hiding current level:
19b84ba3 3721 (goto-char from)
fd5359c6 3722 (if (allout-up-current-level 1 t)
19b84ba3
RS
3723 t
3724 (goto-char 0)
3725 (let ((msg
3726 "Top-level topic already closed - closing siblings..."))
3727 (message msg)
fd5359c6 3728 (allout-expose-topic '(0 :))
19b84ba3
RS
3729 (message (concat msg " Done.")))
3730 nil)
fd5359c6
MR
3731 (/= (allout-recent-depth) 0))
3732 (allout-hide-current-subtree))
19b84ba3 3733 (goto-char from)))
fd5359c6
MR
3734;;;_ > allout-show-current-branches ()
3735(defun allout-show-current-branches ()
c567ac01
RS
3736 "Show all subheadings of this heading, but not their bodies."
3737 (interactive)
3738 (beginning-of-line)
fd5359c6
MR
3739 (allout-show-children t))
3740;;;_ > allout-hide-current-leaves ()
3741(defun allout-hide-current-leaves ()
353e2ef2 3742 "Hide the bodies of the current topic and all its offspring."
c567ac01 3743 (interactive)
fd5359c6
MR
3744 (allout-back-to-current-heading)
3745 (allout-hide-region-body (point) (progn (allout-end-of-current-subtree)
c567ac01
RS
3746 (point))))
3747
3748;;;_ - Region and beyond
fd5359c6
MR
3749;;;_ > allout-show-all ()
3750(defun allout-show-all ()
c567ac01
RS
3751 "Show all of the text in the buffer."
3752 (interactive)
19b84ba3 3753 (message "Exposing entire buffer...")
fd5359c6 3754 (allout-flag-region (point-min) (point-max) ?\n)
19b84ba3 3755 (message "Exposing entire buffer... Done."))
fd5359c6
MR
3756;;;_ > allout-hide-bodies ()
3757(defun allout-hide-bodies ()
c567ac01
RS
3758 "Hide all of buffer except headings."
3759 (interactive)
fd5359c6
MR
3760 (allout-hide-region-body (point-min) (point-max)))
3761;;;_ > allout-hide-region-body (start end)
3762(defun allout-hide-region-body (start end)
c567ac01
RS
3763 "Hide all body lines in the region, but not headings."
3764 (save-excursion
3765 (save-restriction
3766 (narrow-to-region start end)
3767 (goto-char (point-min))
3768 (while (not (eobp))
fd5359c6
MR
3769 (allout-flag-region (point)
3770 (progn (allout-pre-next-preface) (point)) ?\r)
c567ac01
RS
3771 (if (not (eobp))
3772 (forward-char
3773 (if (looking-at "[\n\r][\n\r]")
3774 2 1)))))))
c567ac01 3775
fd5359c6
MR
3776;;;_ > allout-expose-topic (spec)
3777(defun allout-expose-topic (spec)
19b84ba3 3778 "Apply exposure specs to successive outline topic items.
c567ac01 3779
fd5359c6
MR
3780Use the more convenient frontend, `allout-new-exposure', if you don't
3781need evaluation of the arguments, or even better, the `allout-layout'
19b84ba3
RS
3782variable-keyed mode-activation/auto-exposure feature of allout outline
3783mode. See the respective documentation strings for more details.
c567ac01
RS
3784
3785Cursor is left at start position.
3786
19b84ba3
RS
3787SPEC is either a number or a list.
3788
3789Successive specs on a list are applied to successive sibling topics.
c567ac01
RS
3790
3791A simple spec \(either a number, one of a few symbols, or the null
19b84ba3
RS
3792list) dictates the exposure for the corresponding topic.
3793
3794Non-null lists recursively designate exposure specs for respective
3795subtopics of the current topic.
c567ac01 3796
353e2ef2 3797The `:' repeat spec is used to specify exposure for any number of
19b84ba3 3798successive siblings, up to the trailing ones for which there are
353e2ef2 3799explicit specs following the `:'.
c567ac01
RS
3800
3801Simple (numeric and null-list) specs are interpreted as follows:
3802
19b84ba3
RS
3803 Numbers indicate the relative depth to open the corresponding topic.
3804 - negative numbers force the topic to be closed before opening to the
3805 absolute value of the number, so all siblings are open only to
3806 that level.
3807 - positive numbers open to the relative depth indicated by the
3808 number, but do not force already opened subtopics to be closed.
3809 - 0 means to close topic - hide all offspring.
353e2ef2 3810 : - `repeat'
c567ac01 3811 apply prior element to all siblings at current level, *up to*
353e2ef2 3812 those siblings that would be covered by specs following the `:'
c567ac01
RS
3813 on the list. Ie, apply to all topics at level but the last
3814 ones. \(Only first of multiple colons at same level is
3815 respected - subsequent ones are discarded.)
19b84ba3
RS
3816 * - completely opens the topic, including bodies.
3817 + - shows all the sub headers, but not the bodies
3818 - - exposes the body of the corresponding topic.
c567ac01
RS
3819
3820Examples:
fd5359c6 3821\(allout-expose-topic '(-1 : 0))
c567ac01
RS
3822 Close this and all following topics at current level, exposing
3823 only their immediate children, but close down the last topic
3824 at this current level completely.
fd5359c6 3825\(allout-expose-topic '(-1 () : 1 0))
c567ac01
RS
3826 Close current topic so only the immediate subtopics are shown;
3827 show the children in the second to last topic, and completely
3828 close the last one.
fd5359c6 3829\(allout-expose-topic '(-2 : -1 *))
c567ac01
RS
3830 Expose children and grandchildren of all topics at current
3831 level except the last two; expose children of the second to
3832 last and completely open the last one."
3833
3834 (interactive "xExposure spec: ")
19b84ba3
RS
3835 (if (not (listp spec))
3836 nil
fd5359c6 3837 (let ((depth (allout-depth))
19b84ba3
RS
3838 (max-pos 0)
3839 prev-elem curr-elem
3840 stay done
3841 snug-back
3842 )
3843 (while spec
3844 (setq prev-elem curr-elem
3845 curr-elem (car spec)
3846 spec (cdr spec))
3847 (cond ; Do current element:
3848 ((null curr-elem) nil)
3849 ((symbolp curr-elem)
fd5359c6
MR
3850 (cond ((eq curr-elem '*) (allout-show-current-subtree)
3851 (if (> allout-recent-end-of-subtree max-pos)
3852 (setq max-pos allout-recent-end-of-subtree)))
3853 ((eq curr-elem '+) (allout-show-current-branches)
3854 (if (> allout-recent-end-of-subtree max-pos)
3855 (setq max-pos allout-recent-end-of-subtree)))
3856 ((eq curr-elem '-) (allout-show-current-entry))
19b84ba3
RS
3857 ((eq curr-elem ':)
3858 (setq stay t)
353e2ef2 3859 ;; Expand the `repeat' spec to an explicit version,
19b84ba3
RS
3860 ;; w.r.t. remaining siblings:
3861 (let ((residue ; = # of sibs not covered by remaining spec
3862 ;; Dang - could be nice to make use of the chart, sigh:
fd5359c6 3863 (- (length (allout-chart-siblings))
19b84ba3
RS
3864 (length spec))))
3865 (if (< 0 residue)
3866 ;; Some residue - cover it with prev-elem:
3867 (setq spec (append (make-list residue prev-elem)
3868 spec)))))))
3869 ((numberp curr-elem)
fd5359c6
MR
3870 (if (and (>= 0 curr-elem) (allout-visible-p))
3871 (save-excursion (allout-hide-current-subtree t)
19b84ba3
RS
3872 (if (> 0 curr-elem)
3873 nil
fd5359c6 3874 (if (> allout-recent-end-of-subtree max-pos)
19b84ba3 3875 (setq max-pos
fd5359c6 3876 allout-recent-end-of-subtree)))))
19b84ba3 3877 (if (> (abs curr-elem) 0)
fd5359c6
MR
3878 (progn (allout-show-children (abs curr-elem))
3879 (if (> allout-recent-end-of-subtree max-pos)
3880 (setq max-pos allout-recent-end-of-subtree)))))
19b84ba3 3881 ((listp curr-elem)
fd5359c6
MR
3882 (if (allout-descend-to-depth (1+ depth))
3883 (let ((got (allout-expose-topic curr-elem)))
19b84ba3
RS
3884 (if (and got (> got max-pos)) (setq max-pos got))))))
3885 (cond (stay (setq stay nil))
3886 ((listp (car spec)) nil)
3887 ((> max-pos (point))
3888 ;; Capitalize on max-pos state to get us nearer next sibling:
3889 (progn (goto-char (min (point-max) max-pos))
fd5359c6
MR
3890 (allout-next-heading)))
3891 ((allout-next-sibling depth))))
19b84ba3 3892 max-pos)))
fd5359c6
MR
3893;;;_ > allout-old-expose-topic (spec &rest followers)
3894(defun allout-old-expose-topic (spec &rest followers)
e126900f 3895 "Dictate wholesale exposure scheme for current topic, according to SPEC.
c567ac01
RS
3896
3897SPEC is either a number or a list. Optional successive args
3898dictate exposure for subsequent siblings of current topic.
3899
3900A simple spec (either a number, a special symbol, or the null list)
3901dictates the overall exposure for a topic. Non null lists are
3902composite specs whose first element dictates the overall exposure for
3903a topic, with the subsequent elements in the list interpreted as specs
3904that dictate the exposure for the successive offspring of the topic.
3905
3906Simple (numeric and null-list) specs are interpreted as follows:
3907
3908 - Numbers indicate the relative depth to open the corresponding topic:
3909 - negative numbers force the topic to be close before opening to the
3910 absolute value of the number.
3911 - positive numbers just open to the relative depth indicated by the number.
3912 - 0 just closes
353e2ef2
KH
3913 - `*' completely opens the topic, including bodies.
3914 - `+' shows all the sub headers, but not the bodies
3915 - `-' exposes the body and immediate offspring of the corresponding topic.
c567ac01
RS
3916
3917If the spec is a list, the first element must be a number, which
3918dictates the exposure depth of the topic as a whole. Subsequent
3919elements of the list are nested SPECs, dictating the specific exposure
3920for the corresponding offspring of the topic.
3921
e126900f 3922Optional FOLLOWERS arguments dictate exposure for succeeding siblings."
c567ac01
RS
3923
3924 (interactive "xExposure spec: ")
fd5359c6 3925 (let ((depth (allout-current-depth))
c567ac01
RS
3926 done
3927 max-pos)
3928 (cond ((null spec) nil)
3929 ((symbolp spec)
fd5359c6
MR
3930 (if (eq spec '*) (allout-show-current-subtree))
3931 (if (eq spec '+) (allout-show-current-branches))
3932 (if (eq spec '-) (allout-show-current-entry)))
c567ac01
RS
3933 ((numberp spec)
3934 (if (>= 0 spec)
fd5359c6 3935 (save-excursion (allout-hide-current-subtree t)
c567ac01
RS
3936 (end-of-line)
3937 (if (or (not max-pos)
3938 (> (point) max-pos))
3939 (setq max-pos (point)))
3940 (if (> 0 spec)
3941 (setq spec (* -1 spec)))))
3942 (if (> spec 0)
fd5359c6 3943 (allout-show-children spec)))
c567ac01 3944 ((listp spec)
fd5359c6 3945 ;(let ((got (allout-old-expose-topic (car spec))))
c567ac01
RS
3946 ; (if (and got (or (not max-pos) (> got max-pos)))
3947 ; (setq max-pos got)))
fd5359c6 3948 (let ((new-depth (+ (allout-current-depth) 1))
c567ac01 3949 got)
fd5359c6 3950 (setq max-pos (allout-old-expose-topic (car spec)))
c567ac01
RS
3951 (setq spec (cdr spec))
3952 (if (and spec
fd5359c6
MR
3953 (allout-descend-to-depth new-depth)
3954 (not (allout-hidden-p)))
3955 (progn (setq got (apply 'allout-old-expose-topic spec))
c567ac01
RS
3956 (if (and got (or (not max-pos) (> got max-pos)))
3957 (setq max-pos got)))))))
3958 (while (and followers
3959 (progn (if (and max-pos (< (point) max-pos))
3960 (progn (goto-char max-pos)
3961 (setq max-pos nil)))
3962 (end-of-line)
fd5359c6
MR
3963 (allout-next-sibling depth)))
3964 (allout-old-expose-topic (car followers))
c567ac01
RS
3965 (setq followers (cdr followers)))
3966 max-pos))
e126900f
JB
3967(make-obsolete 'allout-old-expose-topic
3968 "use `allout-expose-topic' (with different schema format) instead."
3969 "19.23")
fd5359c6
MR
3970;;;_ > allout-new-exposure '()
3971(defmacro allout-new-exposure (&rest spec)
3972 "Literal frontend for `allout-expose-topic', doesn't evaluate arguments.
2265e017
MR
3973Some arguments that would need to be quoted in `allout-expose-topic'
3974need not be quoted in `allout-new-exposure'.
c567ac01
RS
3975
3976Cursor is left at start position.
3977
fd5359c6 3978Use this instead of obsolete `allout-exposure'.
c567ac01
RS
3979
3980Examples:
fd5359c6 3981\(allout-exposure (-1 () () () 1) 0)
c567ac01
RS
3982 Close current topic at current level so only the immediate
3983 subtopics are shown, except also show the children of the
3984 third subtopic; and close the next topic at the current level.
fd5359c6 3985\(allout-exposure : -1 0)
c567ac01
RS
3986 Close all topics at current level to expose only their
3987 immediate children, except for the last topic at the current
353e2ef2 3988 level, in which even its immediate children are hidden.
fd5359c6 3989\(allout-exposure -2 : -1 *)
c567ac01
RS
3990 Expose children and grandchildren of first topic at current
3991 level, and expose children of subsequent topics at current
3992 level *except* for the last, which should be opened completely."
3993 (list 'save-excursion
fd5359c6
MR
3994 '(if (not (or (allout-goto-prefix)
3995 (allout-next-heading)))
3996 (error "allout-new-exposure: Can't find any outline topics"))
3997 (list 'allout-expose-topic (list 'quote spec))))
3998;;;_ > allout-exposure '()
3999(defmacro allout-exposure (&rest spec)
e126900f 4000 "Literal frontend for `allout-old-expose-topic', doesn't evaluate arguments
c567ac01
RS
4001and retains start position."
4002 (list 'save-excursion
fd5359c6
MR
4003 '(if (not (or (allout-goto-prefix)
4004 (allout-next-heading)))
6a05d05f 4005 (error "Can't find any outline topics"))
fd5359c6 4006 (cons 'allout-old-expose-topic
9179616f 4007 (mapcar (function (lambda (x) (list 'quote x))) spec))))
e126900f 4008(make-obsolete 'allout-exposure 'allout-new-exposure "19.23")
c567ac01 4009
9179616f 4010;;;_ #7 Systematic outline presentation - copying, printing, flattening
19b84ba3 4011
9179616f
DL
4012;;;_ - Mapping and processing of topics
4013;;;_ ( See also Subtree Charting, in Navigation code.)
fd5359c6
MR
4014;;;_ > allout-stringify-flat-index (flat-index)
4015(defun allout-stringify-flat-index (flat-index &optional context)
9179616f
DL
4016 "Convert list representing section/subsection/... to document string.
4017
4018Optional arg CONTEXT indicates interior levels to include."
4019 (let ((delim ".")
71296446 4020 result
9179616f
DL
4021 numstr
4022 (context-depth (or (and context 2) 1)))
4023 ;; Take care of the explicit context:
4024 (while (> context-depth 0)
4025 (setq numstr (int-to-string (car flat-index))
4026 flat-index (cdr flat-index)
4027 result (if flat-index
4028 (cons delim (cons numstr result))
4029 (cons numstr result))
4030 context-depth (if flat-index (1- context-depth) 0)))
4031 (setq delim " ")
4032 ;; Take care of the indentation:
4033 (if flat-index
4034 (progn
4035 (while flat-index
4036 (setq result
4037 (cons delim
4038 (cons (make-string
4039 (1+ (truncate (if (zerop (car flat-index))
4040 1
4041 (log10 (car flat-index)))))
4042 ? )
4043 result)))
4044 (setq flat-index (cdr flat-index)))
4045 ;; Dispose of single extra delim:
4046 (setq result (cdr result))))
4047 (apply 'concat result)))
fd5359c6
MR
4048;;;_ > allout-stringify-flat-index-plain (flat-index)
4049(defun allout-stringify-flat-index-plain (flat-index)
9179616f
DL
4050 "Convert list representing section/subsection/... to document string."
4051 (let ((delim ".")
4052 result)
4053 (while flat-index
4054 (setq result (cons (int-to-string (car flat-index))
4055 (if result
4056 (cons delim result))))
4057 (setq flat-index (cdr flat-index)))
4058 (apply 'concat result)))
fd5359c6
MR
4059;;;_ > allout-stringify-flat-index-indented (flat-index)
4060(defun allout-stringify-flat-index-indented (flat-index)
9179616f
DL
4061 "Convert list representing section/subsection/... to document string."
4062 (let ((delim ".")
71296446 4063 result
9179616f
DL
4064 numstr)
4065 ;; Take care of the explicit context:
4066 (setq numstr (int-to-string (car flat-index))
4067 flat-index (cdr flat-index)
4068 result (if flat-index
4069 (cons delim (cons numstr result))
4070 (cons numstr result)))
4071 (setq delim " ")
4072 ;; Take care of the indentation:
4073 (if flat-index
4074 (progn
4075 (while flat-index
4076 (setq result
4077 (cons delim
4078 (cons (make-string
4079 (1+ (truncate (if (zerop (car flat-index))
4080 1
4081 (log10 (car flat-index)))))
4082 ? )
4083 result)))
4084 (setq flat-index (cdr flat-index)))
4085 ;; Dispose of single extra delim:
4086 (setq result (cdr result))))
4087 (apply 'concat result)))
fd5359c6
MR
4088;;;_ > allout-listify-exposed (&optional start end format)
4089(defun allout-listify-exposed (&optional start end format)
19b84ba3 4090
9179616f 4091 "Produce a list representing exposed topics in current region.
c567ac01 4092
fd5359c6 4093This list can then be used by `allout-process-exposed' to manipulate
9179616f 4094the subject region.
353e2ef2 4095
9179616f 4096Optional START and END indicate bounds of region.
19b84ba3 4097
9179616f
DL
4098optional arg, FORMAT, designates an alternate presentation form for
4099the prefix:
c567ac01 4100
9179616f
DL
4101 list - Present prefix as numeric section.subsection..., starting with
4102 section indicated by the list, innermost nesting first.
4103 `indent' \(symbol) - Convert header prefixes to all white space,
4104 except for distinctive bullets.
c567ac01 4105
9179616f
DL
4106The elements of the list produced are lists that represents a topic
4107header and body. The elements of that list are:
c567ac01 4108
9179616f
DL
4109 - a number representing the depth of the topic,
4110 - a string representing the header-prefix, including trailing whitespace and
4111 bullet.
4112 - a string representing the bullet character,
4113 - and a series of strings, each containing one line of the exposed
4114 portion of the topic entry."
c567ac01 4115
9179616f
DL
4116 (interactive "r")
4117 (save-excursion
4118 (let*
4119 ;; state vars:
4120 (strings prefix pad result depth new-depth out gone-out bullet beg
4121 next done)
c567ac01 4122
9179616f
DL
4123 (goto-char start)
4124 (beginning-of-line)
4125 ;; Goto initial topic, and register preceeding stuff, if any:
fd5359c6 4126 (if (> (allout-goto-prefix) start)
9179616f
DL
4127 ;; First topic follows beginning point - register preliminary stuff:
4128 (setq result (list (list 0 "" nil
4129 (buffer-substring start (1- (point)))))))
4130 (while (and (not done)
4131 (not (eobp)) ; Loop until we've covered the region.
4132 (not (> (point) end)))
fd5359c6
MR
4133 (setq depth (allout-recent-depth) ; Current topics depth,
4134 bullet (allout-recent-bullet) ; ... bullet,
4135 prefix (allout-recent-prefix)
4136 beg (progn (allout-end-of-prefix t) (point))) ; and beginning.
9179616f 4137 (setq done ; The boundary for the current topic:
fd5359c6
MR
4138 (not (allout-next-visible-heading 1)))
4139 (setq new-depth (allout-recent-depth))
9179616f
DL
4140 (setq gone-out out
4141 out (< new-depth depth))
4142 (beginning-of-line)
4143 (setq next (point))
4144 (goto-char beg)
4145 (setq strings nil)
4146 (while (> next (point)) ; Get all the exposed text in
4147 (setq strings
4148 (cons (buffer-substring
4149 beg
4150 ;To hidden text or end of line:
4151 (progn
4152 (search-forward "\r"
4153 (save-excursion (end-of-line)
4154 (point))
4155 1)
4156 (if (= (preceding-char) ?\r)
4157 (1- (point))
4158 (point))))
4159 strings))
4160 (if (< (point) next) ; Resume from after hid text, if any.
4161 (forward-line 1))
4162 (setq beg (point)))
4163 ;; Accumulate list for this topic:
4164 (setq strings (nreverse strings))
4165 (setq result
4166 (cons
4167 (if format
4168 (let ((special (if (string-match
4169 (regexp-quote bullet)
fd5359c6 4170 allout-distinctive-bullets-string)
9179616f
DL
4171 bullet)))
4172 (cond ((listp format)
4173 (list depth
fd5359c6
MR
4174 (if allout-abbreviate-flattened-numbering
4175 (allout-stringify-flat-index format
9179616f 4176 gone-out)
fd5359c6 4177 (allout-stringify-flat-index-plain
9179616f
DL
4178 format))
4179 strings
4180 special))
4181 ((eq format 'indent)
4182 (if special
4183 (list depth
4184 (concat (make-string (1+ depth) ? )
4185 (substring prefix -1))
4186 strings)
4187 (list depth
4188 (make-string depth ? )
4189 strings)))
fd5359c6 4190 (t (error "allout-listify-exposed: %s %s"
9179616f
DL
4191 "invalid format" format))))
4192 (list depth prefix strings))
4193 result))
4194 ;; Reasses format, if any:
4195 (if (and format (listp format))
4196 (cond ((= new-depth depth)
4197 (setq format (cons (1+ (car format))
4198 (cdr format))))
4199 ((> new-depth depth) ; descending - assume by 1:
4200 (setq format (cons 1 format)))
4201 (t
4202 ; Pop the residue:
4203 (while (< new-depth depth)
4204 (setq format (cdr format))
4205 (setq depth (1- depth)))
4206 ; And increment the current one:
4207 (setq format
4208 (cons (1+ (or (car format)
4209 -1))
4210 (cdr format)))))))
4211 ;; Put the list with first at front, to last at back:
4212 (nreverse result))))
fd5359c6 4213;;;_ > allout-process-exposed (&optional func from to frombuf
9179616f 4214;;; tobuf format)
fd5359c6 4215(defun allout-process-exposed (&optional func from to frombuf tobuf
e126900f 4216 format start-num)
9179616f 4217 "Map function on exposed parts of current topic; results to another buffer.
353e2ef2 4218
e126900f 4219Apply FUNC to exposed portions FROM position TO position in buffer
9179616f
DL
4220FROMBUF to buffer TOBUF. Sixth optional arg, FORMAT, designates an
4221alternate presentation form:
c567ac01 4222
9179616f
DL
4223 `flat' - Present prefix as numeric section.subsection..., starting with
4224 section indicated by the start-num, innermost nesting first.
4225 X`flat-indented' - Prefix is like `flat' for first topic at each
4226 X level, but subsequent topics have only leaf topic
4227 X number, padded with blanks to line up with first.
4228 `indent' \(symbol) - Convert header prefixes to all white space,
4229 except for distinctive bullets.
c567ac01 4230
9179616f 4231Defaults:
e126900f 4232 FUNC: `allout-insert-listified'
9179616f
DL
4233 FROM: region start, if region active, else start of buffer
4234 TO: region end, if region active, else end of buffer
4235 FROMBUF: current buffer
4236 TOBUF: buffer name derived: \"*current-buffer-name exposed*\"
4237 FORMAT: nil"
4238
4239 ; Resolve arguments,
4240 ; defaulting if necessary:
fd5359c6 4241 (if (not func) (setq func 'allout-insert-listified))
9179616f
DL
4242 (if (not (and from to))
4243 (if (my-region-active-p)
4244 (setq from (region-beginning) to (region-end))
4245 (setq from (point-min) to (point-max))))
4246 (if frombuf
4247 (if (not (bufferp frombuf))
4248 ;; Specified but not a buffer - get it:
4249 (let ((got (get-buffer frombuf)))
4250 (if (not got)
fd5359c6 4251 (error (concat "allout-process-exposed: source buffer "
9179616f
DL
4252 frombuf
4253 " not found."))
4254 (setq frombuf got))))
4255 ;; not specified - default it:
4256 (setq frombuf (current-buffer)))
4257 (if tobuf
4258 (if (not (bufferp tobuf))
4259 (setq tobuf (get-buffer-create tobuf)))
4260 ;; not specified - default it:
4261 (setq tobuf (concat "*" (buffer-name frombuf) " exposed*")))
4262 (if (listp format)
4263 (nreverse format))
4264
4265 (let* ((listified
4266 (progn (set-buffer frombuf)
fd5359c6 4267 (allout-listify-exposed from to format))))
9179616f
DL
4268 (set-buffer tobuf)
4269 (mapcar func listified)
4270 (pop-to-buffer tobuf)))
4271
4272;;;_ - Copy exposed
fd5359c6
MR
4273;;;_ > allout-insert-listified (listified)
4274(defun allout-insert-listified (listified)
9179616f
DL
4275 "Insert contents of listified outline portion in current buffer.
4276
e126900f 4277LISTIFIED is a list representing each topic header and body:
9179616f
DL
4278
4279 \`(depth prefix text)'
4280
e126900f
JB
4281or
4282
4283 \`(depth prefix text bullet-plus)'
9179616f
DL
4284
4285If `bullet-plus' is specified, it is inserted just after the entire prefix."
4286 (setq listified (cdr listified))
4287 (let ((prefix (prog1
4288 (car listified)
4289 (setq listified (cdr listified))))
4290 (text (prog1
4291 (car listified)
4292 (setq listified (cdr listified))))
4293 (bullet-plus (car listified)))
eac9cf5f
PJ
4294 (insert prefix)
4295 (if bullet-plus (insert (concat " " bullet-plus)))
9179616f 4296 (while text
eac9cf5f 4297 (insert (car text))
9179616f 4298 (if (setq text (cdr text))
eac9cf5f
PJ
4299 (insert "\n")))
4300 (insert "\n")))
fd5359c6
MR
4301;;;_ > allout-copy-exposed-to-buffer (&optional arg tobuf format)
4302(defun allout-copy-exposed-to-buffer (&optional arg tobuf format)
9179616f
DL
4303 "Duplicate exposed portions of current outline to another buffer.
4304
4305Other buffer has current buffers name with \" exposed\" appended to it.
4306
4307With repeat count, copy the exposed parts of only the current topic.
4308
4309Optional second arg TOBUF is target buffer name.
4310
4311Optional third arg FORMAT, if non-nil, symbolically designates an
4312alternate presentation format for the outline:
4313
4314 `flat' - Convert topic header prefixes to numeric
4315 section.subsection... identifiers.
4316 `indent' - Convert header prefixes to all white space, except for
4317 distinctive bullets.
4318 `indent-flat' - The best of both - only the first of each level has
4319 the full path, the rest have only the section number
4320 of the leaf, preceded by the right amount of indentation."
c567ac01
RS
4321
4322 (interactive "P")
4323 (if (not tobuf)
4324 (setq tobuf (get-buffer-create (concat "*" (buffer-name) " exposed*"))))
4325 (let* ((start-pt (point))
fd5359c6
MR
4326 (beg (if arg (allout-back-to-current-heading) (point-min)))
4327 (end (if arg (allout-end-of-current-subtree) (point-max)))
9179616f
DL
4328 (buf (current-buffer))
4329 (start-list ()))
4330 (if (eq format 'flat)
4331 (setq format (if arg (save-excursion
4332 (goto-char beg)
fd5359c6 4333 (allout-topic-flat-index))
9179616f 4334 '(1))))
c567ac01 4335 (save-excursion (set-buffer tobuf)(erase-buffer))
fd5359c6 4336 (allout-process-exposed 'allout-insert-listified
c567ac01
RS
4337 beg
4338 end
4339 (current-buffer)
9179616f
DL
4340 tobuf
4341 format start-list)
c567ac01
RS
4342 (goto-char (point-min))
4343 (pop-to-buffer buf)
4344 (goto-char start-pt)))
fd5359c6
MR
4345;;;_ > allout-flatten-exposed-to-buffer (&optional arg tobuf)
4346(defun allout-flatten-exposed-to-buffer (&optional arg tobuf)
9179616f
DL
4347 "Present numeric outline of outline's exposed portions in another buffer.
4348
e126900f 4349The resulting outline is not compatible with outline mode - use
fd5359c6 4350`allout-copy-exposed-to-buffer' if you want that.
9179616f 4351
fd5359c6 4352Use `allout-indented-exposed-to-buffer' for indented presentation.
9179616f
DL
4353
4354With repeat count, copy the exposed portions of only current topic.
4355
e126900f 4356Other buffer has current buffer's name with \" exposed\" appended to
9179616f
DL
4357it, unless optional second arg TOBUF is specified, in which case it is
4358used verbatim."
4359 (interactive "P")
fd5359c6
MR
4360 (allout-copy-exposed-to-buffer arg tobuf 'flat))
4361;;;_ > allout-indented-exposed-to-buffer (&optional arg tobuf)
4362(defun allout-indented-exposed-to-buffer (&optional arg tobuf)
9179616f
DL
4363 "Present indented outline of outline's exposed portions in another buffer.
4364
e126900f 4365The resulting outline is not compatible with outline mode - use
fd5359c6 4366`allout-copy-exposed-to-buffer' if you want that.
9179616f 4367
fd5359c6 4368Use `allout-flatten-exposed-to-buffer' for numeric sectional presentation.
9179616f
DL
4369
4370With repeat count, copy the exposed portions of only current topic.
4371
e126900f 4372Other buffer has current buffer's name with \" exposed\" appended to
9179616f
DL
4373it, unless optional second arg TOBUF is specified, in which case it is
4374used verbatim."
4375 (interactive "P")
fd5359c6 4376 (allout-copy-exposed-to-buffer arg tobuf 'indent))
c567ac01
RS
4377
4378;;;_ - LaTeX formatting
e126900f
JB
4379;;;_ > allout-latex-verb-quote (string &optional flow)
4380(defun allout-latex-verb-quote (string &optional flow)
19b84ba3
RS
4381 "Return copy of STRING for literal reproduction across latex processing.
4382Expresses the original characters \(including carriage returns) of the
4383string across latex processing."
9179616f
DL
4384 (mapconcat (function
4385 (lambda (char)
c567ac01
RS
4386 (cond ((memq char '(?\\ ?$ ?% ?# ?& ?{ ?} ?_ ?^ ?- ?*))
4387 (concat "\\char" (number-to-string char) "{}"))
4388 ((= char ?\n) "\\\\")
9179616f 4389 (t (char-to-string char)))))
e126900f 4390 string
c567ac01 4391 ""))
fd5359c6
MR
4392;;;_ > allout-latex-verbatim-quote-curr-line ()
4393(defun allout-latex-verbatim-quote-curr-line ()
9179616f 4394 "Express line for exact \(literal) representation across latex processing.
19b84ba3
RS
4395
4396Adjust line contents so it is unaltered \(from the original line)
353e2ef2 4397across latex processing, within the context of a `verbatim'
c567ac01
RS
4398environment. Leaves point at the end of the line."
4399 (beginning-of-line)
4400 (let ((beg (point))
4401 (end (progn (end-of-line)(point))))
4402 (goto-char beg)
4403 (while (re-search-forward "\\\\"
4404 ;;"\\\\\\|\\{\\|\\}\\|\\_\\|\\$\\|\\\"\\|\\&\\|\\^\\|\\-\\|\\*\\|#"
4405 end ; bounded by end-of-line
4406 1) ; no matches, move to end & return nil
4407 (goto-char (match-beginning 0))
eac9cf5f 4408 (insert "\\")
c567ac01
RS
4409 (setq end (1+ end))
4410 (goto-char (1+ (match-end 0))))))
e126900f
JB
4411;;;_ > allout-insert-latex-header (buffer)
4412(defun allout-insert-latex-header (buffer)
c567ac01
RS
4413 "Insert initial latex commands at point in BUFFER."
4414 ;; Much of this is being derived from the stuff in appendix of E in
4415 ;; the TeXBook, pg 421.
e126900f 4416 (set-buffer buffer)
c567ac01
RS
4417 (let ((doc-style (format "\n\\documentstyle{%s}\n"
4418 "report"))
fd5359c6 4419 (page-numbering (if allout-number-pages
c567ac01
RS
4420 "\\pagestyle{empty}\n"
4421 ""))
4422 (linesdef (concat "\\def\\beginlines{"
4423 "\\par\\begingroup\\nobreak\\medskip"
4424 "\\parindent=0pt\n"
4425 " \\kern1pt\\nobreak \\obeylines \\obeyspaces "
4426 "\\everypar{\\strut}}\n"
4427 "\\def\\endlines{"
4428 "\\kern1pt\\endgroup\\medbreak\\noindent}\n"))
4429 (titlecmd (format "\\newcommand{\\titlecmd}[1]{{%s #1}}\n"
fd5359c6 4430 allout-title-style))
c567ac01 4431 (labelcmd (format "\\newcommand{\\labelcmd}[1]{{%s #1}}\n"
fd5359c6 4432 allout-label-style))
c567ac01 4433 (headlinecmd (format "\\newcommand{\\headlinecmd}[1]{{%s #1}}\n"
fd5359c6 4434 allout-head-line-style))
c567ac01 4435 (bodylinecmd (format "\\newcommand{\\bodylinecmd}[1]{{%s #1}}\n"
fd5359c6 4436 allout-body-line-style))
c567ac01
RS
4437 (setlength (format "%s%s%s%s"
4438 "\\newlength{\\stepsize}\n"
4439 "\\setlength{\\stepsize}{"
fd5359c6 4440 allout-indent
c567ac01
RS
4441 "}\n"))
4442 (oneheadline (format "%s%s%s%s%s%s%s"
4443 "\\newcommand{\\OneHeadLine}[3]{%\n"
4444 "\\noindent%\n"
4445 "\\hspace*{#2\\stepsize}%\n"
4446 "\\labelcmd{#1}\\hspace*{.2cm}"
4447 "\\headlinecmd{#3}\\\\["
fd5359c6 4448 allout-line-skip
c567ac01
RS
4449 "]\n}\n"))
4450 (onebodyline (format "%s%s%s%s%s%s"
4451 "\\newcommand{\\OneBodyLine}[2]{%\n"
4452 "\\noindent%\n"
4453 "\\hspace*{#1\\stepsize}%\n"
4454 "\\bodylinecmd{#2}\\\\["
fd5359c6 4455 allout-line-skip
c567ac01
RS
4456 "]\n}\n"))
4457 (begindoc "\\begin{document}\n\\begin{center}\n")
4458 (title (format "%s%s%s%s"
4459 "\\titlecmd{"
fd5359c6 4460 (allout-latex-verb-quote (if allout-title
c567ac01 4461 (condition-case err
fd5359c6 4462 (eval allout-title)
9179616f 4463 ('error "<unnamed buffer>"))
c567ac01
RS
4464 "Unnamed Outline"))
4465 "}\n"
4466 "\\end{center}\n\n"))
4467 (hsize "\\hsize = 7.5 true in\n")
4468 (hoffset "\\hoffset = -1.5 true in\n")
4469 (vspace "\\vspace{.1cm}\n\n"))
4470 (insert (concat doc-style
4471 page-numbering
4472 titlecmd
4473 labelcmd
4474 headlinecmd
4475 bodylinecmd
4476 setlength
4477 oneheadline
4478 onebodyline
4479 begindoc
4480 title
4481 hsize
4482 hoffset
4483 vspace)
4484 )))
e126900f
JB
4485;;;_ > allout-insert-latex-trailer (buffer)
4486(defun allout-insert-latex-trailer (buffer)
c567ac01 4487 "Insert concluding latex commands at point in BUFFER."
e126900f 4488 (set-buffer buffer)
c567ac01 4489 (insert "\n\\end{document}\n"))
fd5359c6
MR
4490;;;_ > allout-latexify-one-item (depth prefix bullet text)
4491(defun allout-latexify-one-item (depth prefix bullet text)
19b84ba3
RS
4492 "Insert LaTeX commands for formatting one outline item.
4493
9179616f 4494Args are the topics numeric DEPTH, the header PREFIX lead string, the
19b84ba3 4495BULLET string, and a list of TEXT strings for the body."
c567ac01
RS
4496 (let* ((head-line (if text (car text)))
4497 (body-lines (cdr text))
4498 (curr-line)
4499 body-content bop)
4500 ; Do the head line:
71296446 4501 (insert (concat "\\OneHeadLine{\\verb\1 "
fd5359c6 4502 (allout-latex-verb-quote bullet)
eac9cf5f
PJ
4503 "\1}{"
4504 depth
4505 "}{\\verb\1 "
4506 (if head-line
fd5359c6 4507 (allout-latex-verb-quote head-line)
eac9cf5f
PJ
4508 "")
4509 "\1}\n"))
c567ac01
RS
4510 (if (not body-lines)
4511 nil
eac9cf5f
PJ
4512 ;;(insert "\\beginlines\n")
4513 (insert "\\begin{verbatim}\n")
c567ac01
RS
4514 (while body-lines
4515 (setq curr-line (car body-lines))
4516 (if (and (not body-content)
4517 (not (string-match "^\\s-*$" curr-line)))
4518 (setq body-content t))
4519 ; Mangle any occurrences of
4520 ; "\end{verbatim}" in text,
4521 ; it's special:
4522 (if (and body-content
4523 (setq bop (string-match "\\end{verbatim}" curr-line)))
4524 (setq curr-line (concat (substring curr-line 0 bop)
4525 ">"
4526 (substring curr-line bop))))
eac9cf5f
PJ
4527 ;;(insert "|" (car body-lines) "|")
4528 (insert curr-line)
fd5359c6 4529 (allout-latex-verbatim-quote-curr-line)
eac9cf5f 4530 (insert "\n")
c567ac01
RS
4531 (setq body-lines (cdr body-lines)))
4532 (if body-content
4533 (setq body-content nil)
4534 (forward-char -1)
eac9cf5f 4535 (insert "\\ ")
c567ac01 4536 (forward-char 1))
eac9cf5f
PJ
4537 ;;(insert "\\endlines\n")
4538 (insert "\\end{verbatim}\n")
c567ac01 4539 )))
fd5359c6
MR
4540;;;_ > allout-latexify-exposed (arg &optional tobuf)
4541(defun allout-latexify-exposed (arg &optional tobuf)
9179616f 4542 "Format current topics exposed portions to TOBUF for latex processing.
19b84ba3
RS
4543TOBUF defaults to a buffer named the same as the current buffer, but
4544with \"*\" prepended and \" latex-formed*\" appended.
c567ac01
RS
4545
4546With repeat count, copy the exposed portions of entire buffer."
4547
4548 (interactive "P")
4549 (if (not tobuf)
4550 (setq tobuf
4551 (get-buffer-create (concat "*" (buffer-name) " latexified*"))))
4552 (let* ((start-pt (point))
fd5359c6
MR
4553 (beg (if arg (point-min) (allout-back-to-current-heading)))
4554 (end (if arg (point-max) (allout-end-of-current-subtree)))
c567ac01
RS
4555 (buf (current-buffer)))
4556 (set-buffer tobuf)
1977b8f6 4557 (erase-buffer)
fd5359c6 4558 (allout-insert-latex-header tobuf)
c567ac01 4559 (goto-char (point-max))
fd5359c6 4560 (allout-process-exposed 'allout-latexify-one-item
c567ac01
RS
4561 beg
4562 end
4563 buf
4564 tobuf)
4565 (goto-char (point-max))
fd5359c6 4566 (allout-insert-latex-trailer tobuf)
1977b8f6 4567 (goto-char (point-min))
c567ac01
RS
4568 (pop-to-buffer buf)
4569 (goto-char start-pt)))
4570
9179616f 4571;;;_ #8 miscellaneous
fd5359c6
MR
4572;;;_ > allout-mark-topic ()
4573(defun allout-mark-topic ()
c567ac01
RS
4574 "Put the region around topic currently containing point."
4575 (interactive)
4576 (beginning-of-line)
fd5359c6 4577 (allout-goto-prefix)
c567ac01 4578 (push-mark (point))
fd5359c6 4579 (allout-end-of-current-subtree)
c567ac01
RS
4580 (exchange-point-and-mark))
4581;;;_ > outlineify-sticky ()
19b84ba3
RS
4582;; outlinify-sticky is correct spelling; provide this alias for sticklers:
4583(defalias 'outlinify-sticky 'outlineify-sticky)
c567ac01 4584(defun outlineify-sticky (&optional arg)
a0776d6b 4585 "Activate outline mode and establish file var so it is started subsequently.
1977b8f6 4586
fd5359c6 4587See doc-string for `allout-layout' and `allout-init' for details on
19b84ba3
RS
4588setup for auto-startup."
4589
4590 (interactive "P")
4591
fd5359c6 4592 (allout-mode t)
19b84ba3
RS
4593
4594 (save-excursion
4595 (goto-char (point-min))
fd5359c6 4596 (if (looking-at allout-regexp)
19b84ba3 4597 t
fd5359c6 4598 (allout-open-topic 2)
eac9cf5f 4599 (insert (concat "Dummy outline topic header - see"
fd5359c6 4600 "`allout-mode' docstring: `^Hm'."))
9179616f 4601 (forward-line 1)
1977b8f6 4602 (goto-char (point-max))
9179616f 4603 (open-line 1)
fd5359c6 4604 (allout-open-topic 0)
eac9cf5f 4605 (insert "Local emacs vars.\n")
fd5359c6
MR
4606 (allout-open-topic 1)
4607 (insert "(`allout-layout' is for allout.el allout-mode)\n")
4608 (allout-open-topic 0)
eac9cf5f 4609 (insert "Local variables:\n")
fd5359c6
MR
4610 (allout-open-topic 0)
4611 (insert (format "allout-layout: %s\n"
4612 (or allout-layout
9179616f 4613 '(-1 : 0))))
fd5359c6 4614 (allout-open-topic 0)
eac9cf5f 4615 (insert "End:\n"))))
c567ac01 4616;;;_ > solicit-char-in-string (prompt string &optional do-defaulting)
1977b8f6 4617(defun solicit-char-in-string (prompt string &optional do-defaulting)
c567ac01 4618 "Solicit (with first arg PROMPT) choice of a character from string STRING.
1977b8f6 4619
c567ac01 4620Optional arg DO-DEFAULTING indicates to accept empty input (CR)."
1977b8f6
RS
4621
4622 (let ((new-prompt prompt)
4623 got)
4624
4625 (while (not got)
4626 (message "%s" new-prompt)
4627
4628 ;; We do our own reading here, so we can circumvent, eg, special
9179616f 4629 ;; treatment for `?' character. (Oughta use minibuffer keymap instead.)
1977b8f6 4630 (setq got
c567ac01 4631 (char-to-string (let ((cursor-in-echo-area nil)) (read-char))))
1977b8f6 4632
9179616f
DL
4633 (setq got
4634 (cond ((string-match (regexp-quote got) string) got)
4635 ((and do-defaulting (string= got "\r"))
4636 ;; Return empty string to default:
4637 "")
4638 ((string= got "\C-g") (signal 'quit nil))
4639 (t
4640 (setq new-prompt (concat prompt
4641 got
4642 " ...pick from: "
4643 string
4644 ""))
4645 nil))))
4646 ;; got something out of loop - return it:
4647 got)
1977b8f6 4648 )
c567ac01
RS
4649;;;_ > regexp-sans-escapes (string)
4650(defun regexp-sans-escapes (regexp &optional successive-backslashes)
4651 "Return a copy of REGEXP with all character escapes stripped out.
19b84ba3 4652
c567ac01
RS
4653Representations of actual backslashes - '\\\\\\\\' - are left as a
4654single backslash.
4655
4656Optional arg SUCCESSIVE-BACKSLASHES is used internally for recursion."
4657
4658 (if (string= regexp "")
4659 ""
4660 ;; Set successive-backslashes to number if current char is
4661 ;; backslash, or else to nil:
4662 (setq successive-backslashes
4663 (if (= (aref regexp 0) ?\\)
4664 (if successive-backslashes (1+ successive-backslashes) 1)
4665 nil))
4666 (if (or (not successive-backslashes) (= 2 successive-backslashes))
4667 ;; Include first char:
4668 (concat (substring regexp 0 1)
4669 (regexp-sans-escapes (substring regexp 1)))
4670 ;; Exclude first char, but maintain count:
4671 (regexp-sans-escapes (substring regexp 1) successive-backslashes))))
9179616f
DL
4672;;;_ > my-region-active-p ()
4673(defmacro my-region-active-p ()
4674 (if (fboundp 'region-active-p)
4675 '(region-active-p)
4676 'mark-active))
19b84ba3 4677;;;_ - add-hook definition for divergent emacsen
c567ac01
RS
4678;;;_ > add-hook (hook function &optional append)
4679(if (not (fboundp 'add-hook))
4680 (defun add-hook (hook function &optional append)
19b84ba3 4681 "Add to the value of HOOK the function FUNCTION unless already present.
353e2ef2 4682\(It becomes the first hook on the list unless optional APPEND is non-nil, in
c567ac01
RS
4683which case it becomes the last). HOOK should be a symbol, and FUNCTION may be
4684any valid function. HOOK's value should be a list of functions, not a single
4685function. If HOOK is void, it is first set to nil."
4686 (or (boundp hook) (set hook nil))
4687 (or (if (consp function)
4688 ;; Clever way to tell whether a given lambda-expression
4689 ;; is equal to anything in the hook.
4690 (let ((tail (assoc (cdr function) (symbol-value hook))))
4691 (equal function tail))
4692 (memq function (symbol-value hook)))
353e2ef2 4693 (set hook
c567ac01
RS
4694 (if append
4695 (nconc (symbol-value hook) (list function))
4696 (cons function (symbol-value hook)))))))
76407938 4697;;;_ : my-mark-marker to accommodate divergent emacsen:
9179616f 4698(defun my-mark-marker (&optional force buffer)
e126900f 4699 "Accommodate the different signature for mark-marker across Emacsen.
9179616f 4700
e126900f 4701XEmacs takes two optional args, while GNU Emacs does not,
9179616f 4702so pass them along when appropriate."
9471aeec 4703 (if (featurep 'xemacs)
9179616f
DL
4704 (mark-marker force buffer)
4705 (mark-marker)))
c567ac01 4706
9179616f 4707;;;_ #9 Under development
fd5359c6
MR
4708;;;_ > allout-bullet-isearch (&optional bullet)
4709(defun allout-bullet-isearch (&optional bullet)
9179616f 4710 "Isearch \(regexp) for topic with bullet BULLET."
c567ac01
RS
4711 (interactive)
4712 (if (not bullet)
4713 (setq bullet (solicit-char-in-string
4714 "ISearch for topic with bullet: "
fd5359c6 4715 (regexp-sans-escapes allout-bullets-string))))
353e2ef2 4716
c567ac01
RS
4717 (let ((isearch-regexp t)
4718 (isearch-string (concat "^"
fd5359c6 4719 allout-header-prefix
c567ac01
RS
4720 "[ \t]*"
4721 bullet)))
4722 (isearch-repeat 'forward)
4723 (isearch-mode t)))
19b84ba3 4724;;;_ ? Re hooking up with isearch - use isearch-op-fun rather than
353e2ef2 4725;;; wrapping the isearch functions.
1977b8f6
RS
4726
4727;;;_* Local emacs vars.
fd5359c6 4728;;; The following `allout-layout' local variable setting:
19b84ba3
RS
4729;;; - closes all topics from the first topic to just before the third-to-last,
4730;;; - shows the children of the third to last (config vars)
4731;;; - and the second to last (code section),
4732;;; - and closes the last topic (this local-variables section).
4733;;;Local variables:
fd5359c6 4734;;;allout-layout: (0 : -1 -1 0)
19b84ba3
RS
4735;;;End:
4736
ab5796a9 4737;;; arch-tag: cf38fbc3-c044-450f-8bff-afed8ba5681c
6a05d05f 4738;;; allout.el ends here