Ihor Radchenko wrote:
Sorry for the late reply.
And likewise for mine!
I've attached a patch that adds faces for headline indicators, plain
list indicators, and leading whitespace significant to plain list structure.
I am not sure about leading spaces.
You may need different things depending what kind of element the leading
spaces apply to. That might be non-trivial.
Perhaps source blocks should be exempted...
I'd appreciate thoughts on this.
What I mostly had in mind is the common customization when code blocks,
example blocks, etc have their own background color. Then, if you apply
the same face to all the indentation, it may look unexpected.
In the attached patch, quoted block types (src, export, example) are
skipped entirely by leading space fontification. Only org syntax is
fontified. This does apply the keyword within quote and verse blocks,
which I believe it should.
The introduced faces are defined without any properties. Customization
is left to the user. Visually, nothing changes by default; and nothing
should clash unless the user does so intentionally.
From 20b14d2cae30a2fdc5682cb272db52d4d68fe5b5 Mon Sep 17 00:00:00 2001
From: Jeff Valk <[email protected]>
Date: Sat, 25 Apr 2026 07:36:18 -0400
Subject: [PATCH] Add faces for structural syntax elements
This adds an identifying face and fontification for each of the
following syntax elements that convey document structure:
- headline indicators (stars)
- plain list item indicators (bullets or numerals)
- leading whitespace, significant for plain list depth
These faces are defined without any properties. This adds useful
semantic information, but reserves any visual customization to the
user.
---
lisp/org-faces.el | 15 +++++++++++++++
lisp/org.el | 31 +++++++++++++++++++++++++++----
2 files changed, 42 insertions(+), 4 deletions(-)
diff --git a/lisp/org-faces.el b/lisp/org-faces.el
index b0f5ef9d7..15be3405f 100644
--- a/lisp/org-faces.el
+++ b/lisp/org-faces.el
@@ -740,6 +740,21 @@ level `org-n-level-faces'."
"Face used for clock display for overrun tasks in mode line."
:group 'org-faces)
+(defface org-headline-indicator
+ '((t ()))
+ "Face used for stars in a headline."
+ :group 'org-faces)
+
+(defface org-plain-list-indicator
+ '((t ()))
+ "Face used for bullets or numerals in a plain list."
+ :group 'org-faces)
+
+(defface org-indentation
+ '((t ()))
+ "Face used for significant leading whitespace."
+ :group 'org-faces)
+
(provide 'org-faces)
;;; org-faces.el ends here
diff --git a/lisp/org.el b/lisp/org.el
index cb36497f4..f60d17d6f 100644
--- a/lisp/org.el
+++ b/lisp/org.el
@@ -5830,6 +5830,18 @@ by a #."
(add-text-properties closing-start end '(invisible t)))
t)))))
+(defun org-fontify-leading-spaces (limit)
+ "Fontify leading whitespace."
+ (when (re-search-forward "^[ \t]+" limit t)
+ (let* ((beg (match-beginning 0))
+ (end (match-end 0)))
+ ;; Indentation is significant for plain list items and their
+ ;; paragraphs, which lack bullet or numeral indicators.
+ ;; Fontify, skipping quoted block types. See `org-protecting-blocks'.
+ (unless (memq 'org-block (ensure-list (get-text-property beg 'face)))
+ (add-face-text-property beg end 'org-indentation)))
+ t))
+
(defun org-fontify-extend-region (beg end _old-len)
(let ((end (if (progn (goto-char end) (looking-at-p "^[*#]"))
(min (point-max) (1+ end))
@@ -6099,7 +6111,14 @@ needs to be inserted at a specific position in the font-lock sequence.")
"^\\(\\**\\)\\(\\* \\)\\(.*\\)")
(1 (org-get-level-face 1))
(2 (org-get-level-face 2))
- (3 (org-get-level-face 3)))
+ (3 (org-get-level-face 3)))
+ ;; Plain lists
+ `(,(if org-list-allow-alphabetical
+ "^[ \t]*\\(\\([-+]\\|[0-9]+[.)]\\|[a-zA-Z][.)]\\)[ \t\r\n]\\)"
+ "^[ \t]*\\(\\([-+]\\|[0-9]+[.)]\\)[ \t\r\n]\\)")
+ (1 'org-plain-list-indicator))
+ '("^[ \t]+\\(\\*[ \t\r\n]\\)" ; star as bullet requires indentation
+ (1 'org-plain-list-indicator))
;; Table lines
'("^[ \t]*\\(\\(|\\|\\+-[-+]\\).*\\S-\\)\n?"
(0 'org-table-row t)
@@ -6208,6 +6227,9 @@ needs to be inserted at a specific position in the font-lock sequence.")
(org-cite-try-load-processor org-cite-activate-processor))
;; prepends faces
'(org-cite-activate))
+ ;; Leading spaces, respecting blocks
+ ;; Apply this after all blocks.
+ '(org-fontify-leading-spaces)
;; COMMENT
;; Apply this last, after all the markup is highlighted, so
;; that even "bright" markup will become dim.
@@ -6316,10 +6338,11 @@ needs to be inserted at a specific position in the font-lock sequence.")
(org-l (if org-odd-levels-only (1+ (/ org-l0 2)) org-l0))
(org-f (if org-cycle-level-faces
(nth (% (1- org-l) org-n-level-faces) org-level-faces)
- (nth (1- (min org-l org-n-level-faces)) org-level-faces))))
+ (nth (1- (min org-l org-n-level-faces)) org-level-faces)))
+ (org-f-stars (list 'org-headline-indicator org-f)))
(cond
- ((eq n 1) (if org-hide-leading-stars 'org-hide org-f))
- ((eq n 2) org-f)
+ ((eq n 1) (if org-hide-leading-stars 'org-hide org-f-stars))
+ ((eq n 2) org-f-stars)
(t (unless org-level-color-stars-only org-f)))))
(defun org-face-from-face-or-color (context inherit face-or-color)
base-commit: e989c60c2e96789c8900b4425ec9180bda3a2030
--
2.53.0