branch: elpa/adoc-mode
commit 717bce9c18039ced2a929ea4438267907714d2a5
Author: Bozhidar Batsov <[email protected]>
Commit: Bozhidar Batsov <[email protected]>

    Add outline cycling commands
    
    Add adoc-cycle (TAB), which rotates the visibility of the section
    subtree at point between folded, child titles, and fully shown when
    point is on a one-line title, and otherwise indents as usual; a prefix
    argument cycles the whole buffer. Add adoc-cycle-buffer (S-TAB), which
    rotates the buffer between overview, contents, and show-all.
    
    Both are thin wrappers over the outline-cycle / outline-cycle-buffer
    primitives, building on the outline-minor-mode integration.
---
 CHANGELOG.md           |  1 +
 README.adoc            |  2 +-
 adoc-mode.el           | 31 +++++++++++++++++++++++++++++++
 test/adoc-mode-test.el | 43 +++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 76 insertions(+), 1 deletion(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5343d29810..af2b323b0a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,7 @@
 
 ### New features
 
+- Add outline cycling commands modelled on `org-mode` and `markdown-mode`: 
`adoc-cycle` (`TAB`) rotates the visibility of the section subtree at point 
(folded / child titles / fully shown) when point is on a one-line title, and 
otherwise indents as usual; `adoc-cycle-buffer` (`S-TAB`) rotates the whole 
buffer between overview, contents, and show-all. Both build on the 
`outline-cycle` / `outline-cycle-buffer` primitives.
 - Add list editing: `adoc-promote` (`M-left`) and `adoc-demote` (`M-right`) 
now nest the list item at point one level deeper or shallower (for unordered 
`*`/`-` and implicitly-numbered `.` lists) in addition to acting on section 
titles, and the new `adoc-insert-list-item` (`M-RET`) inserts a sibling item 
below the current one, keeping its indentation and marker and incrementing the 
number/letter of explicitly-numbered items.
 - Add `adoc-move-list-item-up` (`M-up`) and `adoc-move-list-item-down` 
(`M-down`), which move the list item at point (together with its nested 
sub-items) past its previous/next sibling, and `adoc-renumber-list`, which 
renumbers a contiguous arabic (`1.`) or alphabetic (`a.`/`A.`) 
explicitly-numbered list starting from its first item's value.
 - Add heading navigation commands modelled on `markdown-mode` and `org-mode`: 
`adoc-next-visible-heading` (`C-c C-n`), `adoc-previous-visible-heading` (`C-c 
C-p`), `adoc-forward-same-level` (`C-c C-f`), `adoc-backward-same-level` (`C-c 
C-b`), and `adoc-up-heading` (`C-c C-u`). They understand both one-line (`== 
Title`) and two-line (underlined) titles and skip headings hidden by folding. 
`outline-minor-mode` is now enabled by default so the folding commands are 
available out of the box.
diff --git a/README.adoc b/README.adoc
index dfb469fb05..6d50179d91 100644
--- a/README.adoc
+++ b/README.adoc
@@ -44,7 +44,7 @@ Here are some of the main features of `adoc-mode`:
 - list editing: `M-left` / `M-right` nest the list item at point deeper or 
shallower, `M-RET` inserts a sibling item (incrementing the number for 
explicitly-numbered lists), `M-up` / `M-down` move an item (with its sub-items) 
past its siblings, and `M-x adoc-renumber-list` renumbers an 
explicitly-numbered list
 - navigate to anchors (`C-c C-a`) and follow URLs, `include::` macros, and 
xrefs at point (`C-c C-o` / `M-.`)
 - nested `imenu` index with hierarchical heading structure
-- `outline-minor-mode` enabled out of the box for folding (one-line title 
style only)
+- outline folding built on `outline-minor-mode` (enabled out of the box): 
`TAB` cycles the subtree at point, `S-TAB` cycles the whole buffer (overview / 
contents / show all), one-line title style only
 - integration with `flyspell-mode` (skips non-prose regions), comment commands 
(`M-;`), and compilation mode
 
 === Demo
diff --git a/adoc-mode.el b/adoc-mode.el
index e7084b0578..5b6b1f4540 100644
--- a/adoc-mode.el
+++ b/adoc-mode.el
@@ -44,6 +44,7 @@
 
 (require 'cl-lib)
 (require 'compile)
+(require 'outline)
 (require 'subr-x)
 (require 'adoc-mode-image)
 (require 'adoc-mode-tempo)
@@ -3556,6 +3557,31 @@ buffer stops the search.  With a negative ARG, move 
forward."
           (goto-char orig)
           (user-error "No parent section title"))))))
 
+;;;; Outline cycling
+
+(defun adoc-cycle (&optional arg)
+  "Cycle the visibility of the section subtree at point.
+On a section title, rotate its subtree between folded, child
+titles only, and fully shown (via `outline-cycle').  Off a title,
+indent or insert a tab as usual.  With a prefix ARG, cycle the
+visibility of the whole buffer instead (see `adoc-cycle-buffer').
+
+Only one-line titles (e.g. `== Title') are recognised by the
+underlying `outline-minor-mode'."
+  (interactive "P")
+  (cond
+   (arg (adoc-cycle-buffer))
+   ((outline-on-heading-p) (outline-cycle))
+   (t (indent-for-tab-command))))
+
+(defun adoc-cycle-buffer ()
+  "Cycle the visibility of all section titles in the buffer.
+Rotate between an overview (top-level titles only), a table of
+contents (all titles, no bodies), and the fully expanded buffer
+\(via `outline-cycle-buffer')."
+  (interactive)
+  (outline-cycle-buffer))
+
 (defvar sgml-char-names)
 
 (defun adoc-make-unichar-alist ()
@@ -3746,6 +3772,8 @@ ITEMS is a list of (name pos . level)."
     (define-key map (kbd "M-RET") 'adoc-insert-list-item)
     (define-key map (kbd "M-<up>") 'adoc-move-list-item-up)
     (define-key map (kbd "M-<down>") 'adoc-move-list-item-down)
+    (define-key map (kbd "TAB") 'adoc-cycle)
+    (define-key map (kbd "<backtab>") 'adoc-cycle-buffer)
     (define-key map "\C-c\C-t" 'adoc-toggle-title-type)
     (define-key map "\C-c\C-a" 'adoc-goto-ref-label)
     (define-key map "\C-c\C-o" 'adoc-follow-thing-at-point)
@@ -3758,6 +3786,9 @@ ITEMS is a list of (name pos . level)."
         ["Backward (same level)" adoc-backward-same-level]
         ["Up to parent heading" adoc-up-heading]
         "---"
+        ["Cycle subtree visibility" adoc-cycle]
+        ["Cycle buffer visibility" adoc-cycle-buffer]
+        "---"
         ["Promote (title / list item)" adoc-promote]
         ["Demote (title / list item)" adoc-demote]
         ["Insert list item" adoc-insert-list-item]
diff --git a/test/adoc-mode-test.el b/test/adoc-mode-test.el
index 565e3ca528..2923c3da64 100644
--- a/test/adoc-mode-test.el
+++ b/test/adoc-mode-test.el
@@ -1013,6 +1013,49 @@ on top of the `<mark>' default)."
     (adoc-up-heading 1)
     (should (looking-at-p "Doc Title$"))))
 
+;;;; Outline cycling
+
+(defun adoctest-cycle-buffer ()
+  "Set up a temp buffer with a small document for cycling tests."
+  (adoc-mode)
+  (insert "= Top\n\n== A\n\nbody a\n\n== B\n\nbody b\n")
+  (font-lock-ensure)
+  (goto-char (point-min)))
+
+(ert-deftest adoctest-test-cycle-subtree ()
+  (with-temp-buffer
+    (adoctest-cycle-buffer)
+    (let ((body (save-excursion (search-forward "body a") (point))))
+      (search-forward "== A") (beginning-of-line)
+      (should-not (outline-invisible-p body))
+      ;; on a heading, cycling folds the subtree, then reveals it again
+      (adoc-cycle)
+      (should (outline-invisible-p body))
+      (adoc-cycle)
+      (should-not (outline-invisible-p body)))))
+
+(ert-deftest adoctest-test-cycle-off-heading-does-not-fold ()
+  (with-temp-buffer
+    (adoctest-cycle-buffer)
+    (let ((body (save-excursion (search-forward "body a") (point))))
+      ;; point on an ordinary line: cycling must not fold anything
+      (goto-char body)
+      (adoc-cycle)
+      (should-not (outline-invisible-p body)))))
+
+(ert-deftest adoctest-test-cycle-buffer ()
+  (with-temp-buffer
+    (adoctest-cycle-buffer)
+    (let ((body (save-excursion (search-forward "body a") (point))))
+      (should-not (outline-invisible-p body))
+      ;; a prefix argument cycles the whole buffer: overview hides bodies
+      (adoc-cycle '(4))
+      (should (outline-invisible-p body))
+      ;; ... and the dedicated command eventually shows everything again
+      (adoc-cycle-buffer)
+      (adoc-cycle-buffer)
+      (should-not (outline-invisible-p body)))))
+
 ;;;; List editing
 
 (ert-deftest adoctest-test-list-promote-demote-unordered ()

Reply via email to