* obsolete/ooutline.el (outline-mode):
[bpt/emacs.git] / lisp / obsolete / ooutline.el
CommitLineData
55535639 1;;; ooutline.el --- outline mode commands for Emacs
b578f267 2
bbf5eb28 3;; Copyright (C) 1986, 1993, 1994, 1997 Free Software Foundation, Inc.
26d1e4fd 4
9750e079 5;; Maintainer: FSF
612abcae 6;; Keywords: outlines
9750e079 7
26d1e4fd
BP
8;; This file is part of GNU Emacs.
9
10;; GNU Emacs is free software; you can redistribute it and/or modify
11;; it under the terms of the GNU General Public License as published by
e5167999 12;; the Free Software Foundation; either version 2, or (at your option)
26d1e4fd
BP
13;; any later version.
14
15;; GNU Emacs is distributed in the hope that it will be useful,
16;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18;; GNU General Public License for more details.
19
20;; You should have received a copy of the GNU General Public License
b578f267
EN
21;; along with GNU Emacs; see the file COPYING. If not, write to the
22;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
23;; Boston, MA 02111-1307, USA.
26d1e4fd 24
edbd2f74
ER
25;;; Commentary:
26
27;; This package is a major mode for editing outline-format documents.
28;; An outline can be `abstracted' to show headers at any given level,
29;; with all stuff below hidden. See the Emacs manual for details.
30
e5167999
ER
31;;; Code:
32
26d1e4fd 33;; Jan '86, Some new features added by Peter Desnoyers and rewritten by RMS.
bbf5eb28
RS
34
35(defgroup outlines nil
36 "Support for hierarchical outlining"
37 :prefix "outline-"
38 :group 'editing)
39
40
41(defcustom outline-regexp nil
26d1e4fd
BP
42 "*Regular expression to match the beginning of a heading.
43Any line whose beginning matches this regexp is considered to start a heading.
44The recommended way to set this is with a Local Variables: list
bbf5eb28
RS
45in the file it applies to. See also outline-heading-end-regexp."
46 :type '(choice regexp (const nil))
47 :group 'outlines)
9f9d8941
KH
48
49;; Can't initialize this in the defvar above -- some major modes have
50;; already assigned a local value to it.
51(or (default-value 'outline-regexp)
52 (setq-default outline-regexp "[*\^L]+"))
a1506d29 53
bbf5eb28 54(defcustom outline-heading-end-regexp "[\n\^M]"
26d1e4fd
BP
55 "*Regular expression to match the end of a heading line.
56You can assume that point is at the beginning of a heading when this
57regexp is searched for. The heading ends at the end of the match.
58The recommended way to set this is with a \"Local Variables:\" list
bbf5eb28
RS
59in the file it applies to."
60 :type 'regexp
61 :group 'outlines)
26d1e4fd 62
1644b1a5 63(defvar outline-mode-prefix-map nil)
26d1e4fd 64
1644b1a5 65(if outline-mode-prefix-map
26d1e4fd 66 nil
1644b1a5
RS
67 (setq outline-mode-prefix-map (make-sparse-keymap))
68 (define-key outline-mode-prefix-map "\C-n" 'outline-next-visible-heading)
69 (define-key outline-mode-prefix-map "\C-p" 'outline-previous-visible-heading)
70 (define-key outline-mode-prefix-map "\C-i" 'show-children)
71 (define-key outline-mode-prefix-map "\C-s" 'show-subtree)
72 (define-key outline-mode-prefix-map "\C-d" 'hide-subtree)
73 (define-key outline-mode-prefix-map "\C-u" 'outline-up-heading)
74 (define-key outline-mode-prefix-map "\C-f" 'outline-forward-same-level)
75 (define-key outline-mode-prefix-map "\C-b" 'outline-backward-same-level)
76 (define-key outline-mode-prefix-map "\C-t" 'hide-body)
77 (define-key outline-mode-prefix-map "\C-a" 'show-all)
78 (define-key outline-mode-prefix-map "\C-c" 'hide-entry)
79 (define-key outline-mode-prefix-map "\C-e" 'show-entry)
80 (define-key outline-mode-prefix-map "\C-l" 'hide-leaves)
81 (define-key outline-mode-prefix-map "\C-k" 'show-branches)
82 (define-key outline-mode-prefix-map "\C-q" 'hide-sublevels)
83 (define-key outline-mode-prefix-map "\C-o" 'hide-other))
84
85(defvar outline-mode-menu-bar-map nil)
86(if outline-mode-menu-bar-map
87 nil
88 (setq outline-mode-menu-bar-map (make-sparse-keymap))
89
90 (define-key outline-mode-menu-bar-map [hide]
ee1a4f84
RS
91 (cons "Hide" (make-sparse-keymap "Hide")))
92
1644b1a5 93 (define-key outline-mode-menu-bar-map [hide hide-other]
93da9e09 94 '("Hide Other" . hide-other))
1644b1a5 95 (define-key outline-mode-menu-bar-map [hide hide-sublevels]
93da9e09 96 '("Hide Sublevels" . hide-sublevels))
1644b1a5 97 (define-key outline-mode-menu-bar-map [hide hide-subtree]
32e61280 98 '("Hide Subtree" . hide-subtree))
1644b1a5 99 (define-key outline-mode-menu-bar-map [hide hide-entry]
32e61280 100 '("Hide Entry" . hide-entry))
1644b1a5 101 (define-key outline-mode-menu-bar-map [hide hide-body]
32e61280 102 '("Hide Body" . hide-body))
1644b1a5 103 (define-key outline-mode-menu-bar-map [hide hide-leaves]
32e61280 104 '("Hide Leaves" . hide-leaves))
ee1a4f84 105
1644b1a5 106 (define-key outline-mode-menu-bar-map [show]
ee1a4f84
RS
107 (cons "Show" (make-sparse-keymap "Show")))
108
1644b1a5 109 (define-key outline-mode-menu-bar-map [show show-subtree]
32e61280 110 '("Show Subtree" . show-subtree))
1644b1a5 111 (define-key outline-mode-menu-bar-map [show show-children]
32e61280 112 '("Show Children" . show-children))
1644b1a5 113 (define-key outline-mode-menu-bar-map [show show-branches]
32e61280 114 '("Show Branches" . show-branches))
1644b1a5 115 (define-key outline-mode-menu-bar-map [show show-entry]
32e61280 116 '("Show Entry" . show-entry))
1644b1a5 117 (define-key outline-mode-menu-bar-map [show show-all]
32e61280 118 '("Show All" . show-all))
ee1a4f84 119
1644b1a5 120 (define-key outline-mode-menu-bar-map [headings]
ee1a4f84
RS
121 (cons "Headings" (make-sparse-keymap "Headings")))
122
1644b1a5 123 (define-key outline-mode-menu-bar-map [headings outline-backward-same-level]
ee1a4f84 124 '("Previous Same Level" . outline-backward-same-level))
1644b1a5 125 (define-key outline-mode-menu-bar-map [headings outline-forward-same-level]
ee1a4f84 126 '("Next Same Level" . outline-forward-same-level))
1644b1a5 127 (define-key outline-mode-menu-bar-map [headings outline-previous-visible-heading]
ee1a4f84 128 '("Previous" . outline-previous-visible-heading))
1644b1a5 129 (define-key outline-mode-menu-bar-map [headings outline-next-visible-heading]
ee1a4f84 130 '("Next" . outline-next-visible-heading))
1644b1a5 131 (define-key outline-mode-menu-bar-map [headings outline-up-heading]
ee1a4f84 132 '("Up" . outline-up-heading)))
26d1e4fd 133
1644b1a5
RS
134(defvar outline-mode-map nil "")
135
136(if outline-mode-map
137 nil
138 (setq outline-mode-map (nconc (make-sparse-keymap) text-mode-map))
139 (define-key outline-mode-map "\C-c" outline-mode-prefix-map)
140 (define-key outline-mode-map [menu-bar] outline-mode-menu-bar-map))
141
bbf5eb28
RS
142(defcustom outline-minor-mode nil
143 "Non-nil if using Outline mode as a minor mode of some other mode."
144 :type 'boolean
145 :group 'outlines)
326c43dc
RS
146(make-variable-buffer-local 'outline-minor-mode)
147(put 'outline-minor-mode 'permanent-local t)
8f22b9e0
RS
148(or (assq 'outline-minor-mode minor-mode-alist)
149 (setq minor-mode-alist (append minor-mode-alist
150 (list '(outline-minor-mode " Outl")))))
26d1e4fd 151
b9998c33
RS
152(defvar outline-font-lock-keywords
153 '(;; Highlight headings according to the level.
2729bba0 154 ("^\\([*]+\\)[ \t]*\\([^\n\r]+\\)?[ \t]*[\n\r]"
b9998c33
RS
155 (1 font-lock-string-face)
156 (2 (let ((len (- (match-end 1) (match-beginning 1))))
157 (or (cdr (assq len '((1 . font-lock-function-name-face)
158 (2 . font-lock-keyword-face)
159 (3 . font-lock-comment-face))))
160 font-lock-variable-name-face))
161 nil t))
a7acbbe4 162 ;; Highlight citations of the form [1] and [Mar94].
d951f8cb 163 ("\\[\\([[:upper:]][[:alpha:]]+\\)*[0-9]+\\]" . font-lock-type-face))
b9998c33
RS
164 "Additional expressions to highlight in Outline mode.")
165
26d1e4fd
BP
166(defun outline-mode ()
167 "Set major mode for editing outlines with selective display.
168Headings are lines which start with asterisks: one for major headings,
a1506d29 169two for subheadings, etc. Lines not starting with asterisks are body lines.
26d1e4fd
BP
170
171Body text or subheadings under a heading can be made temporarily
a1506d29 172invisible, or visible again. Invisible lines are attached to the end
26d1e4fd
BP
173of the heading, so they move with it, if the line is killed and yanked
174back. A heading with text hidden under it is marked with an ellipsis (...).
175
176Commands:\\<outline-mode-map>
177\\[outline-next-visible-heading] outline-next-visible-heading move by visible headings
178\\[outline-previous-visible-heading] outline-previous-visible-heading
179\\[outline-forward-same-level] outline-forward-same-level similar but skip subheadings
180\\[outline-backward-same-level] outline-backward-same-level
181\\[outline-up-heading] outline-up-heading move from subheading to heading
182
eb6692ed
KH
183\\[hide-body] make all text invisible (not headings).
184\\[show-all] make everything in buffer visible.
26d1e4fd
BP
185
186The remaining commands are used when point is on a heading line.
187They apply to some of the body or subheadings of that heading.
188\\[hide-subtree] hide-subtree make body and subheadings invisible.
189\\[show-subtree] show-subtree make body and subheadings visible.
190\\[show-children] show-children make direct subheadings visible.
191 No effect on body, or subheadings 2 or more levels down.
192 With arg N, affects subheadings N levels down.
eb6692ed
KH
193\\[hide-entry] make immediately following body invisible.
194\\[show-entry] make it visible.
195\\[hide-leaves] make body under heading and under its subheadings invisible.
26d1e4fd 196 The subheadings remain visible.
eb6692ed 197\\[show-branches] make all subheadings at all levels visible.
26d1e4fd
BP
198
199The variable `outline-regexp' can be changed to control what is a heading.
200A line is a heading if `outline-regexp' matches something at the
201beginning of the line. The longer the match, the deeper the level.
202
203Turning on outline mode calls the value of `text-mode-hook' and then of
204`outline-mode-hook', if they are non-nil."
205 (interactive)
206 (kill-all-local-variables)
207 (setq selective-display t)
208 (use-local-map outline-mode-map)
209 (setq mode-name "Outline")
210 (setq major-mode 'outline-mode)
211 (define-abbrev-table 'text-mode-abbrev-table ())
212 (setq local-abbrev-table text-mode-abbrev-table)
213 (set-syntax-table text-mode-syntax-table)
214 (make-local-variable 'paragraph-start)
dad432c6 215 (setq paragraph-start (concat paragraph-start "\\|\\("
26d1e4fd
BP
216 outline-regexp "\\)"))
217 ;; Inhibit auto-filling of header lines.
218 (make-local-variable 'auto-fill-inhibit-regexp)
219 (setq auto-fill-inhibit-regexp outline-regexp)
220 (make-local-variable 'paragraph-separate)
dad432c6 221 (setq paragraph-separate (concat paragraph-separate "\\|\\("
26d1e4fd 222 outline-regexp "\\)"))
d31e6eaf
SM
223 (make-local-variable 'font-lock-defaults)
224 (setq font-lock-defaults '(outline-font-lock-keywords t))
a46b893b 225 (make-local-variable 'change-major-mode-hook)
9ea9bca3 226 (add-hook 'change-major-mode-hook 'show-all)
e1c31ddb 227 (run-mode-hooks 'text-mode-hook 'outline-mode-hook))
26d1e4fd 228
bbf5eb28 229(defcustom outline-minor-mode-prefix "\C-c@"
e8c138c2
RS
230 "*Prefix key to use for Outline commands in Outline minor mode.
231The value of this variable is checked as part of loading Outline mode.
bbf5eb28
RS
232After that, changing the prefix key requires manipulating keymaps."
233 :type 'string
234 :group 'outlines)
6e301d24 235
8f1e8ff0
RS
236(defvar outline-minor-mode-map nil)
237(if outline-minor-mode-map
238 nil
239 (setq outline-minor-mode-map (make-sparse-keymap))
ee1a4f84 240 (define-key outline-minor-mode-map [menu-bar]
1644b1a5 241 outline-mode-menu-bar-map)
6e301d24 242 (define-key outline-minor-mode-map outline-minor-mode-prefix
1644b1a5 243 outline-mode-prefix-map))
8f1e8ff0
RS
244
245(or (assq 'outline-minor-mode minor-mode-map-alist)
246 (setq minor-mode-map-alist
247 (cons (cons 'outline-minor-mode outline-minor-mode-map)
248 minor-mode-map-alist)))
249
250(defun outline-minor-mode (&optional arg)
326c43dc
RS
251 "Toggle Outline minor mode.
252With arg, turn Outline minor mode on if arg is positive, off otherwise.
253See the command `outline-mode' for more information on this mode."
26d1e4fd
BP
254 (interactive "P")
255 (setq outline-minor-mode
256 (if (null arg) (not outline-minor-mode)
257 (> (prefix-numeric-value arg) 0)))
258 (if outline-minor-mode
259 (progn
260 (setq selective-display t)
26d1e4fd 261 (run-hooks 'outline-minor-mode-hook))
671e87b3 262 (setq selective-display nil))
85111db5
RS
263 ;; When turning off outline mode, get rid of any ^M's.
264 (or outline-minor-mode
265 (outline-flag-region (point-min) (point-max) ?\n))
a57c6a28 266 (force-mode-line-update))
26d1e4fd 267\f
476731da
RS
268(defvar outline-level 'outline-level
269 "Function of no args to compute a header's nesting level in an outline.
270It can assume point is at the beginning of a header line.")
271
6483e43f
KH
272;; This used to count columns rather than characters, but that made ^L
273;; appear to be at level 2 instead of 1. Columns would be better for
274;; tab handling, but the default regexp doesn't use tabs, and anyone
275;; who changes the regexp can also redefine the outline-level variable
276;; as appropriate.
26d1e4fd
BP
277(defun outline-level ()
278 "Return the depth to which a statement is nested in the outline.
279Point must be at the beginning of a header line. This is actually
eb6692ed 280the number of characters that `outline-regexp' matches."
26d1e4fd
BP
281 (save-excursion
282 (looking-at outline-regexp)
eb6692ed 283 (- (match-end 0) (match-beginning 0))))
26d1e4fd
BP
284
285(defun outline-next-preface ()
f4136d9c
RS
286 "Skip forward to just before the next heading line.
287If there's no following heading line, stop before the newline
288at the end of the buffer."
26d1e4fd
BP
289 (if (re-search-forward (concat "[\n\^M]\\(" outline-regexp "\\)")
290 nil 'move)
f4136d9c
RS
291 (goto-char (match-beginning 0)))
292 (if (memq (preceding-char) '(?\n ?\^M))
293 (forward-char -1)))
26d1e4fd
BP
294
295(defun outline-next-heading ()
296 "Move to the next (possibly invisible) heading line."
297 (interactive)
298 (if (re-search-forward (concat "[\n\^M]\\(" outline-regexp "\\)")
299 nil 'move)
300 (goto-char (1+ (match-beginning 0)))))
301
302(defun outline-back-to-heading ()
c1eaf68c
RS
303 "Move to previous heading line, or beg of this line if it's a heading.
304Only visible heading lines are considered."
26d1e4fd
BP
305 (beginning-of-line)
306 (or (outline-on-heading-p)
eb6692ed
KH
307 (re-search-backward (concat "^\\(" outline-regexp "\\)") nil t)
308 (error "before first heading")))
26d1e4fd
BP
309
310(defun outline-on-heading-p ()
a2b3bd0f 311 "Return t if point is on a (visible) heading line."
26d1e4fd
BP
312 (save-excursion
313 (beginning-of-line)
eb6692ed 314 (and (bolp)
26d1e4fd
BP
315 (looking-at outline-regexp))))
316
317(defun outline-end-of-heading ()
318 (if (re-search-forward outline-heading-end-regexp nil 'move)
319 (forward-char -1)))
320
321(defun outline-next-visible-heading (arg)
322 "Move to the next visible heading line.
323With argument, repeats or can move backward if negative.
324A heading line is one that starts with a `*' (or that
325`outline-regexp' matches)."
326 (interactive "p")
327 (if (< arg 0)
328 (beginning-of-line)
329 (end-of-line))
eb6692ed
KH
330 (or (re-search-forward (concat "^\\(" outline-regexp "\\)") nil t arg)
331 (error ""))
26d1e4fd
BP
332 (beginning-of-line))
333
334(defun outline-previous-visible-heading (arg)
335 "Move to the previous heading line.
336With argument, repeats or can move forward if negative.
337A heading line is one that starts with a `*' (or that
338`outline-regexp' matches)."
339 (interactive "p")
340 (outline-next-visible-heading (- arg)))
341
342(defun outline-flag-region (from to flag)
343 "Hides or shows lines from FROM to TO, according to FLAG.
344If FLAG is `\\n' (newline character) then text is shown,
345while if FLAG is `\\^M' (control-M) the text is hidden."
05cf4426
RS
346 (let (buffer-read-only)
347 (subst-char-in-region from to
348 (if (= flag ?\n) ?\^M ?\n)
349 flag t)))
26d1e4fd
BP
350\f
351(defun hide-entry ()
352 "Hide the body directly following this heading."
353 (interactive)
354 (outline-back-to-heading)
355 (outline-end-of-heading)
356 (save-excursion
357 (outline-flag-region (point) (progn (outline-next-preface) (point)) ?\^M)))
358
359(defun show-entry ()
360 "Show the body directly following this heading."
361 (interactive)
362 (save-excursion
363 (outline-flag-region (point) (progn (outline-next-preface) (point)) ?\n)))
364
365(defun hide-body ()
366 "Hide all of buffer except headings."
367 (interactive)
368 (hide-region-body (point-min) (point-max)))
369
370(defun hide-region-body (start end)
371 "Hide all body lines in the region, but not headings."
372 (save-excursion
373 (save-restriction
374 (narrow-to-region start end)
375 (goto-char (point-min))
376 (if (outline-on-heading-p)
377 (outline-end-of-heading))
378 (while (not (eobp))
379 (outline-flag-region (point)
380 (progn (outline-next-preface) (point)) ?\^M)
381 (if (not (eobp))
382 (progn
383 (forward-char
384 (if (looking-at "[\n\^M][\n\^M]")
385 2 1))
386 (outline-end-of-heading)))))))
387
388(defun show-all ()
389 "Show all of the text in the buffer."
390 (interactive)
391 (outline-flag-region (point-min) (point-max) ?\n))
392
393(defun hide-subtree ()
394 "Hide everything after this heading at deeper levels."
395 (interactive)
396 (outline-flag-subtree ?\^M))
397
398(defun hide-leaves ()
399 "Hide all body after this heading at deeper levels."
400 (interactive)
401 (outline-back-to-heading)
402 (outline-end-of-heading)
403 (hide-region-body (point) (progn (outline-end-of-subtree) (point))))
404
405(defun show-subtree ()
406 "Show everything after this heading at deeper levels."
407 (interactive)
408 (outline-flag-subtree ?\n))
409
93da9e09 410(defun hide-sublevels (levels)
a2b3bd0f 411 "Hide everything but the top LEVELS levels of headers, in whole buffer."
9e9afbf8 412 (interactive "p")
71d78000 413 (if (< levels 1)
9e9afbf8 414 (error "Must keep at least one level of headers"))
71d78000 415 (setq levels (1- levels))
9e9afbf8
RS
416 (save-excursion
417 (goto-char (point-min))
6f3c2ad9
RS
418 ;; Keep advancing to the next top-level heading.
419 (while (or (and (bobp) (outline-on-heading-p))
420 (outline-next-heading))
421 (let ((end (save-excursion (outline-end-of-subtree) (point))))
422 ;; Hide everything under that.
423 (outline-flag-region (point) end ?\^M)
424 ;; Show the first LEVELS levels under that.
a9fd843b 425 (if (> levels 0)
6f3c2ad9
RS
426 (show-children levels))
427 ;; Move to the next, since we already found it.
428 (goto-char end)))))
9e9afbf8 429
93da9e09 430(defun hide-other ()
9e9afbf8
RS
431 "Hide everything except for the current body and the parent headings."
432 (interactive)
93da9e09 433 (hide-sublevels 1)
9e9afbf8
RS
434 (let ((last (point))
435 (pos (point)))
436 (while (save-excursion
437 (and (re-search-backward "[\n\r]" nil t)
438 (eq (following-char) ?\r)))
439 (save-excursion
440 (beginning-of-line)
441 (if (eq last (point))
442 (progn
443 (outline-next-heading)
444 (outline-flag-region last (point) ?\n))
445 (show-children)
446 (setq last (point)))))))
447
26d1e4fd
BP
448(defun outline-flag-subtree (flag)
449 (save-excursion
450 (outline-back-to-heading)
451 (outline-end-of-heading)
452 (outline-flag-region (point)
453 (progn (outline-end-of-subtree) (point))
454 flag)))
455
456(defun outline-end-of-subtree ()
457 (outline-back-to-heading)
458 (let ((opoint (point))
459 (first t)
476731da 460 (level (funcall outline-level)))
26d1e4fd 461 (while (and (not (eobp))
476731da 462 (or first (> (funcall outline-level) level)))
26d1e4fd
BP
463 (setq first nil)
464 (outline-next-heading))
d8ec2bc8
KH
465 (if (memq (preceding-char) '(?\n ?\^M))
466 (progn
c7cd67bd 467 ;; Go to end of line before heading
d8ec2bc8
KH
468 (forward-char -1)
469 (if (memq (preceding-char) '(?\n ?\^M))
470 ;; leave blank line before heading
471 (forward-char -1))))))
26d1e4fd
BP
472\f
473(defun show-branches ()
474 "Show all subheadings of this heading, but not their bodies."
475 (interactive)
476 (show-children 1000))
477
478(defun show-children (&optional level)
479 "Show all direct subheadings of this heading.
480Prefix arg LEVEL is how many levels below the current level should be shown.
481Default is enough to cause the following heading to appear."
482 (interactive "P")
483 (setq level
484 (if level (prefix-numeric-value level)
485 (save-excursion
c1eaf68c 486 (outline-back-to-heading)
476731da 487 (let ((start-level (funcall outline-level)))
26d1e4fd 488 (outline-next-heading)
babf687a
RS
489 (if (eobp)
490 1
491 (max 1 (- (funcall outline-level) start-level)))))))
26d1e4fd 492 (save-excursion
c1eaf68c
RS
493 (save-restriction
494 (outline-back-to-heading)
495 (setq level (+ level (funcall outline-level)))
496 (narrow-to-region (point)
497 (progn (outline-end-of-subtree)
498 (if (eobp) (point-max) (1+ (point)))))
499 (goto-char (point-min))
500 (while (and (not (eobp))
501 (progn
502 (outline-next-heading)
503 (not (eobp))))
504 (if (<= (funcall outline-level) level)
505 (save-excursion
506 (outline-flag-region (save-excursion
507 (forward-char -1)
508 (if (memq (preceding-char) '(?\n ?\^M))
509 (forward-char -1))
510 (point))
511 (progn (outline-end-of-heading) (point))
512 ?\n)))))))
26d1e4fd
BP
513\f
514(defun outline-up-heading (arg)
515 "Move to the heading line of which the present line is a subheading.
516With argument, move up ARG levels."
517 (interactive "p")
518 (outline-back-to-heading)
476731da 519 (if (eq (funcall outline-level) 1)
26d1e4fd 520 (error ""))
eb6692ed
KH
521 (while (and (> (funcall outline-level) 1)
522 (> arg 0)
523 (not (bobp)))
524 (let ((present-level (funcall outline-level)))
525 (while (not (< (funcall outline-level) present-level))
526 (outline-previous-visible-heading 1))
527 (setq arg (- arg 1)))))
26d1e4fd
BP
528
529(defun outline-forward-same-level (arg)
a2b3bd0f
RS
530 "Move forward to the ARG'th subheading at same level as this one.
531Stop at the first and last subheadings of a superior heading."
26d1e4fd
BP
532 (interactive "p")
533 (outline-back-to-heading)
534 (while (> arg 0)
535 (let ((point-to-move-to (save-excursion
a1506d29 536 (outline-get-next-sibling))))
26d1e4fd
BP
537 (if point-to-move-to
538 (progn
539 (goto-char point-to-move-to)
540 (setq arg (1- arg)))
541 (progn
542 (setq arg 0)
543 (error ""))))))
544
545(defun outline-get-next-sibling ()
a2b3bd0f 546 "Move to next heading of the same level, and return point or nil if none."
476731da 547 (let ((level (funcall outline-level)))
26d1e4fd 548 (outline-next-visible-heading 1)
476731da 549 (while (and (> (funcall outline-level) level)
26d1e4fd
BP
550 (not (eobp)))
551 (outline-next-visible-heading 1))
476731da 552 (if (< (funcall outline-level) level)
26d1e4fd
BP
553 nil
554 (point))))
a1506d29 555
26d1e4fd 556(defun outline-backward-same-level (arg)
a2b3bd0f
RS
557 "Move backward to the ARG'th subheading at same level as this one.
558Stop at the first and last subheadings of a superior heading."
26d1e4fd
BP
559 (interactive "p")
560 (outline-back-to-heading)
561 (while (> arg 0)
562 (let ((point-to-move-to (save-excursion
563 (outline-get-last-sibling))))
564 (if point-to-move-to
565 (progn
566 (goto-char point-to-move-to)
567 (setq arg (1- arg)))
568 (progn
569 (setq arg 0)
570 (error ""))))))
571
572(defun outline-get-last-sibling ()
a2b3bd0f 573 "Move to next heading of the same level, and return point or nil if none."
476731da 574 (let ((level (funcall outline-level)))
26d1e4fd 575 (outline-previous-visible-heading 1)
476731da 576 (while (and (> (funcall outline-level) level)
26d1e4fd
BP
577 (not (bobp)))
578 (outline-previous-visible-heading 1))
476731da 579 (if (< (funcall outline-level) level)
26d1e4fd
BP
580 nil
581 (point))))
582
8f1e8ff0
RS
583(provide 'outline)
584
ab5796a9 585;;; arch-tag: 14ed00e1-bd40-4db8-86e5-3b82ce326e45
55535639 586;;; ooutline.el ends here