3

How can one enable org-indent-mode (or otherwise indent content to Org headings) while still maintaining a consistent visual fill column?

enter image description here

2
  • Does this still happen? I tried replicating this in 2022 with org-mode + org-indent-mode + visual-fill-column-mode, and I didn't see the undesired overflow.
    – g-gundam
    Commented Oct 15, 2022 at 16:17
  • @g-gundam This happens for me in Org 9.5.5 on Emacs 28.1. Commented Oct 15, 2022 at 23:56

3 Answers 3

2

I've finally figured out the solution to this.

Basically, the problem is that when org-indent does its fancy visual indentation it changes the visual position of columns on the screen. So for fill to be consistent between indentation levels current-fill-column needs to be adjusted by the current level of indentation.

The way org-indent accomplishes its visual indentation is by setting the line-prefix text property. You can reproduce this for yourself by putting some text in a Fundamental Mode buffer and running (set-text-properties (point-min) (point-max) '(line-prefix " ")). You'll see the text shifted over by two columns, just like how org-indent does it, and if you look at the (current-column) you'll see that those are also shifted over.

So this can be fixed by some return advice on current-fill column that adjusts it by the length of the line-prefix at point:

(defun my-org-indent-fill-column-advice (res)
  (cond
   ((and (boundp 'org-indent-mode) org-indent-mode)
    (- res
       (length (plist-get (text-properties-at (point))
                          'line-prefix))))
   (t res)))
(advice-add 'current-fill-column :filter-return #'my-org-indent-fill-column-advice)
1
  • Welcome to Emacs Stack Exchange! An excellent solution to a four year problem. I've tested it out and it works perfectly. Commented Aug 31 at 16:21
1

One way of achieving this behavior is to disable org-indent-mode and set org-adapt-indentation to t. The side effect of this configuration is that spaces will be added to Org file, where org-indent-mode only acts at render time.

1

The only way I found to do this is by overriding the function that returns the fill column.

(defun current-fill-column ()
      "Return the fill-column to use for this line.
Subtracts right margin and org indentation level from fill-column"
      (let ((indent-level (if (bound-and-true-p org-indent-mode)
                              (* org-indent-indentation-per-level
                                 (org-current-level))
                            0))
            (margin (or (get-text-property (point) 'right-margin) 0)))
        (- fill-column indent-level margin)))

This probably misses some edge cases, since the original function is more complex, but this is working for my purposes so far.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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