1

I'm trying to fill programmatically an Org buffer (especially the elements quote-block, paragraph and item). Note that all following attempts contains a (org-cycle '(64)) because they all don't work when headings are not fully expanded (not sure why).

First attempt

(defun test/org-fill-whole-buffer-1 ()
  (interactive)
  (org-cycle '(64))
  (mark-whole-buffer)
  (org-fill-paragraph nil (list (point-min) (point-max))))

It works partially:

  • items right above a quote block are not filled;
  • items after multiple line breaks are not filled.

And per the documentation, mark-whole-buffer should not be called programmatically.

Second attempt

(defun test/org-fill-whole-buffer-2 ()
  (interactive)
  (org-cycle '(64))
  (save-excursion
    (org-element-map (org-element-parse-buffer 'element)
    'paragraph
      (lambda (elt)
    (when-let* ((target-point (org-element-property :contents-begin elt)))
          (goto-char target-point)
          (org-fill-paragraph nil t))))))

This obviously doesn't work (or works randomly) because once the first element is filled, the position of the subsequent ones is not correct anymore.

Third attempt

Improved version of test/org-fill-whole-buffer-2: fill elements in reverse order of their appearances. Now the elements positions are correct as they are not altered by previous org-fill-paragraph calls.

(defun test/org-fill-whole-buffer-3 (types)
  "Fill Org elements of TYPES in the whole Org buffer."
  (interactive
   (list 'paragraph))
  (org-cycle '(64))
  (save-excursion
    (mapc (lambda (n)
            (goto-char n)
            (org-fill-paragraph nil t))
      (reverse
       (org-element-map (org-element-parse-buffer 'element)
               types
             (lambda (elt)
               (when-let* ((target-point (org-element-property :contents-begin elt)))
         target-point)))))))

However, there are still some issues I can't really understand.

  1. For instance, assuming that all nodes are folded, and that I call (test/org-fill-whole-buffer-3 'paragraph), I obtain this: enter image description here But then if I M-x undo-tree-undo, fold headings, and call again (test/org-fill-whole-buffer-3 'paragraph), I obtain this: enter image description here

  2. The function seems to be also "point-dependent", meaning that if I goto-char onto a problematic item (see point 1) before calling (test/org-fill-whole-buffer-3 'paragraph), then that item would fill properly at the first time as the second picture showed (but not other problematic items).

  3. Interestingly, test/org-fill-whole-buffer-1 doesn't have the issue of point 1, but have issue with some items. So, one may think that calling (test/org-fill-whole-buffer-1) and (test/org-fill-whole-buffer-3 'item) successively would work as they complete each other. Nope, that doesn't work for a mysterious reason.

For these reasons, I had trouble to make a minimal reproducible example to illustrate issues I have with test/org-fill-whole-buffer-3. But the essence of this question is still "how to fill a whole Org buffer programmatically, included Org elements quote-block, paragraph and item ?", so any brand-new solution is welcomed.

EDIT: Here are pastebin links of my real world Org buffer. Special attention should be made on the two items containing org-dict-tlfi links (see the pictures above). The expected result is as shown in the second picture, which could be achieved interactively with M-q (org-fill-paragraph) at the beginning of the unfilled item.

Org mode version: 9.4.4

6
  • 1
    Can you put your input file on some pastebin and add a link to your question (or if it is small enough, just add it to the question)? That would make it easier for people to reproduce your findings and increase your chances of getting an answer. As it stands, we would have to create a file to reproduce. I did that and I tried your function-1, which does not work at all for me, and your function-3, which works fine on my example file, even without the unfolding. But it's not clear what that means without a given reference point.
    – NickD
    Jul 22 '21 at 6:50
  • @NickD Thanks, I forgot about pastebin. With the full instance, I'm able to reproduce it. I edited the question, hope that it would be helpful. Jul 22 '21 at 8:22
  • I took the paragraph under the "Notre professeur..." QUOTE block in your problem 1 above and moved it to a test.org file and tried to fill it: it fills badly with a long line starting at "mettre sur son ..." and C-e then only gets me to after the first paren after "... ses ergots". I think something in that item confuses the parser. Can you isolate the problems you have found and cut-and-paste the items/paragraphs into a separate file? I'd like to try them all and see if there is any commonality.
    – NickD
    Jul 23 '21 at 22:00
  • Actually, I don't see any other problems. Running your third attempt on the original file produced this for me.
    – NickD
    Jul 23 '21 at 22:15
  • @NickD That's what I tried before you tell me about pastebin: I isolated some problematic parts of the buffer, but cannot reproduce the issue. I succeeded to do so with the full Org file, though. I wrote the reproduce step under John Kitchin's answer, but was too tired to update it in the question. I highly suspect that the issue has something to do with font-lock. Will update the question to include detailed steps to reproduce, environment and expected result. Jul 24 '21 at 7:14
1

This seems to give the expected result for me:

(defun custom-org-fill ()
  (interactive)
  (save-excursion
    (org-with-wide-buffer
     (cl-loop for el in (reverse
             (org-element-map (org-element-parse-buffer)
                 '(paragraph quote-block item) #'identity))
          do
          (goto-char (org-element-property :contents-begin el))
          (org-fill-paragraph)))))
2
  • Thanks. Unfortunately, it still doesn't work for me (even with emacs -Q plus Org 9.4.6), but I have a better understanding of the issue now. It seems that the behaviour is exactly as font-lock would have been disabled, which explains why only items containing Org link failed to fill properly (the Org link is longer than its description). An important step to reproduce is to make sure that the function is called only one time on the buffer. Even (custom-org-fill), (undo), then (custom-org-fill) would yield a different result. Jul 23 '21 at 5:14
  • BTW, it seems your function can be improved further by removing the save-excursion as it is already called in org-with-wide-buffer, and removing elements quote-block and item as their :contents-begin value overlap with paragraph's. +1 for the org-with-wide-buffer, it solved elegantly the issue of folded headings. Jul 23 '21 at 5:17

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.