The problem is that when there is one line in between folded headings with source blocks the text properties of the #end-src line bleeds out. You can see the lines bleeding on the right in the image.
Update Progress So Far
step 1
To do this I have taken two steps.
The first is to unfontify the end of the last line of a subtree when hiding it if that line is the end of a source block. That's the line responsible for the bleeding. This will ensure that the font face doesn't bleed out when a block is hidden with outline-hide-subtree
.
(defun dwim-unfontify-last-line-of-subtree (&rest _)
"Unfontify last line of subtree if it's a source block."
(save-excursion
(org-end-of-subtree)
(beginning-of-line)
(when (looking-at-p (rx "#+end_src"))
(font-lock-unfontify-region
(line-end-position) (1+ (line-end-position))))))
(advice-add #'outline-hide-subtree :after #'dwim-unfontify-last-line-of-subtree)
step 2
The second step is the hard one. I determined that outline-show-heading
is the fundamental function for showing headings. This function checks if the heading being shown has
(defun dwim-fontify-last-line-of-block (&rest _)
"Do what I mean: fontify last line of source block.
When the heading has a source block as the last item (in the subtree) do one of the
following:
If the source block is now visible, fontify the end its last line.
If it's invisible, unfontify its last line."
(let (font-lock-fn invisible-p heading-name)
(save-excursion
;; Debugging
;; (save-match-data
;; (beginning-of-line)
;; (looking-at
;; (rx bol (+ "*") "\s" (submatch (+ (not (any "\n"))))))
;; (setq heading-name (match-string-np 1)))
(org-end-of-subtree)
(beginning-of-line)
(when (looking-at-p (rx "#+end_src"))
(setq invisible-p (outline-invisible-p (line-end-position)))
(setq font-lock-fn
(if invisible-p
#'font-lock-unfontify-region
#'font-lock-fontify-region))
;; Debugging
;; (message "-%s-’s end_src is %svisible"
;; heading-name
;; (if invisible-p "in" ""))
(funcall font-lock-fn
(line-end-position)
(1+ (line-end-position)))))))
(advice-add #'outline-show-heading :after #'dwim-fontify-last-line-of-block)
problem
This is extremely close to working. If you use outline-toggle-children
to display the children of a subtree and every child is a subtree (in other words each is displayed as a folded headline), the last source block of every headline should be invisible. That's because all the headings are folded. But (outline-invisible-p (line-end-position))
says the last child of that subtree remains visible.
The picture below shows what I mean. You can see the last child of the Top level headings is bleeding out. And the last child of the level Completion
heading is bleeding. This is what happens when I displayed them with outline-toggle-fold
.
text-properties
(expressly setting the text properties) whenfont-lock
is active is just asking for trouble. The best practice, in my opinion, is to use one or the other. Since flat-text files inorg-mode
usefont-lock
andorg-agenda-mode
usestext-properties
, I would suggest any changes you make be limited as such. The easiest solution is to not use a background face, except for an activeregion
... There is a lengthy recent discussion on the Emacs Devel list spanning several days about face attributes that extend to the end of the line ...font-lock
.outline-flag-region
to the start of the next line. However I like having a blank line in between fold. Also doing this results inend_src
lines looking like this:#+end_src...
. Right now, I'm thinking the best workaround my be, as you mentioned, "stop highlighting before reaching EOL". However I would want to do this conditionally: only just before I fold a heading. And to highlight normally just before unfolding.region
) because of problems like this ... I also stopped using bold ... but I forget the reason at the moment for that decision.