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