2

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.

Observe Lines Bleeding out on the right

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.

last child]

  • In general, messing with the text-properties (expressly setting the text properties) when font-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 in org-mode use font-lock and org-agenda-mode uses text-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 active region ... 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 ... – lawlist Aug 24 at 18:22
  • Thanks, I did not know this. I'll investigate how to do the same thing with font-lock. – Aquaactress Aug 24 at 21:47
  • Here is a link to the opening thread I referred to above where the Emacs developers discuss face properties that extend to the end of the display line (e.g., end of the text area / window body width): lists.gnu.org/archive/html/emacs-devel/2019-08/msg00132.html In a couple of those posts, they compare/contrast terminal and GUI builds where certain face attributes extend to the end of the display line .... Inasmuch as these things are handled internally by the display engine, Lisp workarounds may include stop highlighting before reaching EOL; or, fold to next line without face ... – lawlist Aug 24 at 22:35
  • Thanks for this link. I tried folding to the next line without face by setting the second argument of outline-flag-region to the start of the next line. However I like having a blank line in between fold. Also doing this results in end_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. – Aquaactress Aug 25 at 0:09
  • Years ago, I stopped using the background face for everything (except region) because of problems like this ... I also stopped using bold ... but I forget the reason at the moment for that decision. – lawlist Aug 25 at 0:14
0

May not be the answer you were looking for, but the simplest way might be to change the org-block-end-line variable face to that of the default background, thus ensuring that there's nothing to leak in the first place. Also, end_src line generally seems useless in that all the code-block arguments belong in the begin_line, or better yet an entirely separate #+header:.

  • Thanks you for your answer. I had noticed this when I used themes (like avk-daylight) whose background was the same as the src block line. Actually, the line bleeding bothered me so much that I tend to mostly use such themes. – Aquaactress Aug 29 at 3:04
  • Like I said, no need to bother with themes, all it takes is addind the '(org-block-end-line ((t (:background "#")))) to the (custom-set-faces) inside the dot file, where # is your background hex. – causenetsofv Aug 29 at 5:15
  • You say no need to bother with themes but that I need to specify the specific background hex. If I did this what would happen if I changed themes using load-theme? Would I need to change the background hex? If this is the case, this would involve the current theme. This being said, I'm sure there is away to programatically update this value via an advice to load-theme. However, even still, I do not feel comfortable accepting such an answer because it introduces a visible side-effect: namely changing the face of #+end_src lines. – Aquaactress Aug 30 at 14:30
  • If you're asking whether a given theme takes priorty over manually set properties, the answer is it doesn't. Once you explicitly define a face setting it gets rendered above the the load-theme properties. – causenetsofv Aug 31 at 3:37

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.