emacs-elpa-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[elpa] externals/org f83e45526b: org-toggle-item: Move footnote-definiti


From: ELPA Syncer
Subject: [elpa] externals/org f83e45526b: org-toggle-item: Move footnote-definitions out of the lists
Date: Fri, 11 Nov 2022 00:57:55 -0500 (EST)

branch: externals/org
commit f83e45526b5ec4627d601673be3680e2dece1b33
Author: Ihor Radchenko <yantar92@posteo.net>
Commit: Ihor Radchenko <yantar92@posteo.net>

    org-toggle-item: Move footnote-definitions out of the lists
    
    * lisp/org-list.el (org-toggle-item): When headings contain
    footnote-definitions, move them out of the list.  Footnote-definitions
    must not be indented and hence cannot belong to the list.  Ensure that
    definitions do not slurp the following element after the list.
    Consider when the list created by `org-toggle-item' is continued by an
    existing list.
    * testing/lisp/test-org-list.el (test-org-list/toggle-item): Add
    tests.
    
    Reported-by: Ypo <ypuntot@gmail.com>
    Link: https://orgmode.org/list/877d3k70lu.fsf@localhost
---
 lisp/org-list.el              | 73 ++++++++++++++++++++++++++++++++++++++-----
 testing/lisp/test-org-list.el | 63 +++++++++++++++++++++++++++++++++++++
 2 files changed, 128 insertions(+), 8 deletions(-)

diff --git a/lisp/org-list.el b/lisp/org-list.el
index dbd64599e0..7da2187cb1 100644
--- a/lisp/org-list.el
+++ b/lisp/org-list.el
@@ -3021,7 +3021,38 @@ If it is an item, convert all items to normal lines.
 If it is normal text, change region into a list of items.
 With a prefix argument ARG, change the region in a single item."
   (interactive "P")
-  (let ((shift-text
+  (let ((extract-footnote-definitions
+         (lambda (end)
+           ;; Remove footnote definitions from point to END.
+           ;; Return the list of the extracted definitions.
+           (let (definitions element)
+             (save-excursion
+               (while (re-search-forward org-footnote-definition-re end t)
+                 (setq element (org-element-at-point))
+                 (when (eq 'footnote-definition
+                           (org-element-type element))
+                   (push (buffer-substring-no-properties
+                          (org-element-property :begin element)
+                          (org-element-property :end element))
+                         definitions)
+                   ;; Ensure at least 2 blank lines after the last
+                   ;; footnote definition, thus not slurping the
+                   ;; following element.
+                   (unless (<= 2 (org-element-property
+                                 :post-blank
+                                 (org-element-at-point)))
+                     (setf (car definitions)
+                           (concat (car definitions)
+                                   (make-string
+                                    (- 2 (org-element-property
+                                          :post-blank
+                                          (org-element-at-point)))
+                                    ?\n))))
+                   (delete-region
+                    (org-element-property :begin element)
+                    (org-element-property :end element))))
+               definitions))))
+        (shift-text
         (lambda (ind end)
           ;; Shift text in current section to IND, from point to END.
           ;; The function leaves point to END line.
@@ -3079,7 +3110,7 @@ With a prefix argument ARG, change the region in a single 
item."
             (skip-chars-forward " \t")
             (delete-region (point) (match-end 0)))
           (forward-line)))
-       ;; Case 2. Start at an heading: convert to items.
+       ;; Case 2. Start at a heading: convert to items.
        ((org-at-heading-p)
         ;; Remove metadata
         (let (org-loop-over-headlines-in-active-region)
@@ -3095,7 +3126,9 @@ With a prefix argument ARG, change the region in a single 
item."
                              (t (length (match-string 0))))))
                ;; Level of first heading.  Further headings will be
                ;; compared to it to determine hierarchy in the list.
-               (ref-level (org-reduced-level (org-outline-level))))
+               (ref-level (org-reduced-level (org-outline-level)))
+                (footnote-definitions
+                 (funcall extract-footnote-definitions end)))
           (while (< (point) end)
             (let* ((level (org-reduced-level (org-outline-level)))
                    (delta (max 0 (- level ref-level)))
@@ -3124,8 +3157,8 @@ With a prefix argument ARG, change the region in a single 
item."
                        "[X]"
                      "[ ]"))
                   (org-list-write-struct struct
-                                         (org-list-parents-alist struct)
-                                         old)))
+                                 (org-list-parents-alist struct)
+                                 old)))
               ;; Ensure all text down to END (or SECTION-END) belongs
               ;; to the newly created item.
               (let ((section-end (save-excursion
@@ -3133,13 +3166,23 @@ With a prefix argument ARG, change the region in a 
single item."
                 (forward-line)
                 (funcall shift-text
                          (+ start-ind (* (1+ delta) bul-len))
-                         (min end section-end)))))))
+                         (min end section-end)))))
+           (when footnote-definitions
+             (goto-char end)
+             ;; Insert footnote definitions after the list.
+             (unless (bolp) (beginning-of-line 2))
+             ;; At (point-max).
+             (unless (bolp) (insert "\n"))
+             (dolist (def footnote-definitions)
+               (insert def)))))
        ;; Case 3. Normal line with ARG: make the first line of region
        ;;         an item, and shift indentation of others lines to
        ;;         set them as item's body.
        (arg (let* ((bul (org-list-bullet-string "-"))
                    (bul-len (length bul))
-                   (ref-ind (org-current-text-indentation)))
+                   (ref-ind (org-current-text-indentation))
+                    (footnote-definitions
+                     (funcall extract-footnote-definitions end)))
               (skip-chars-forward " \t")
               (insert bul)
               (forward-line)
@@ -3150,7 +3193,21 @@ With a prefix argument ARG, change the region in a 
single item."
                          (+ ref-ind bul-len)
                          (min end (save-excursion (or (outline-next-heading)
                                                       (point)))))
-                (forward-line))))
+                (forward-line))
+               (when footnote-definitions
+                 ;; If the new list is followed by same-level items,
+                 ;; move past them as well.
+                 (goto-char (org-element-property
+                             :end
+                             (org-element-lineage
+                              (org-element-at-point (1- end))
+                              '(plain-list) t)))
+                 ;; Insert footnote definitions after the list.
+                 (unless (bolp) (beginning-of-line 2))
+                 ;; At (point-max).
+                 (unless (bolp) (insert "\n"))
+                 (dolist (def footnote-definitions)
+                   (insert def)))))
        ;; Case 4. Normal line without ARG: turn each non-item line
        ;;         into an item.
        (t
diff --git a/testing/lisp/test-org-list.el b/testing/lisp/test-org-list.el
index 1c13c5d970..0ee3a14c27 100644
--- a/testing/lisp/test-org-list.el
+++ b/testing/lisp/test-org-list.el
@@ -1356,6 +1356,69 @@ b. Item 2<point>"
            (goto-char (point-max))
            (org-toggle-item nil)
            (buffer-string))))
+  ;; When headings contain footnote definitions, move the definition
+  ;; out of the list.  Footnote definitions cannot be indented.
+  (should
+   (equal "- Main headline
+  - Headline 1
+    bbbbbbbb [fn:1]
+
+- Headline 2
+[fn:1] cccccccccccccccc
+
+
+"
+          (org-test-with-temp-text "* Main headline
+** Headline 1
+bbbbbbbb [fn:1]
+
+[fn:1] cccccccccccccccc
+* Headline 2"
+            (transient-mark-mode 1)
+            (push-mark (point) t t)
+            (goto-char (point-max))
+            (org-toggle-item t)
+            (buffer-string))))
+  ;; Footnote definitions that did not have trailing double blank line
+  ;; must not slurp the following element.
+  (should
+   (equal "- Head 1
+- Head 2
+[fn:1] cccccccccccccccc
+
+
+Paragraph outside footnote definitions."
+          (org-test-with-temp-text "* Head 1
+[fn:1] cccccccccccccccc
+* Head 2
+
+
+Paragraph outside footnote definitions."
+            (transient-mark-mode 1)
+            (push-mark (point) t t)
+            (search-forward "Head 2")
+            (org-toggle-item t)
+            (buffer-string))))
+  ;; Move footnote definitions past pre-existing items after.
+  (should
+   (equal "- Line 1
+  Line 2
+- next item
+[fn:1] definition
+
+
+"
+          (org-test-with-temp-text "Line 1
+Line 2
+[fn:1] definition
+
+
+- next item"
+            (transient-mark-mode 1)
+            (push-mark (point) t t)
+            (search-forward "definition")
+            (org-toggle-item t)
+            (buffer-string))))
   ;; When argument ARG is non-nil, change the whole region into
   ;; a single item.
   (should



reply via email to

[Prev in Thread] Current Thread [Next in Thread]