This has been bugging me for a long time too!
org-fontify-meta-lines-and-blocks-1
is responsible for setting the fonts of the meta lines. Looking at its source one can see that for keywords in ("+title:" "+subtitle:" "+author:" "+email:" "+date:")
it sets the font org-document-info-keyword
for the keyword itself, while the values get fonts org-document-title
or org-document-info
. It doesn't fontify the whitespace between the keyword and the value though and this is why we have misalignment.
On the other hand, lines with keywords not in the above list (the last cond
case in the code) get fontified fully with face org-meta-line
. For these there is no alignment problem (try this).
One way to address this is to overwrite (e.g. using :override advice) org-fontify-meta-lines-and-blocks-1
with a version which provides the desired START and END arguments in the calls to add-text-properties
. This is a very long function though...
Another way is to make use of the hooks provided by org-set-font-lock-defaults
(which indirectly calls org-fontify-meta-lines-and-blocks-1
) to override the defaults. org-font-lock-hook
can be used to insert defaults at the beginning of the list of defaults, which is called org-font-lock-extra-keywords
, and org-font-lock-set-keywords-hook
can modify this list arbitrarily before it is passed to font-lock-defaults
. doom-themes-enable-org-fontification
provides a good example of the latter approach.
A third way is to make use of the function font-lock-add-keywords
. Using this approach, with the following in my init.el the header is properly aligned:
(font-lock-add-keywords
'org-mode
'(("^#\\+\\(title\\|TITLE\\):\\(.*\\)$"
2 'org-document-title t)
("^#\\+\\(subtitle\\|author\\|email\\|date\\):\\(.*\\)$"
2 'org-document-info t)
("^#\\+\\(SUBTITLE\\|AUTHOR\\|EMAIL\\|DATE\\):\\(.*\\)$"
2 'org-document-info t))
't)
(defun my-org-fixed-pitch ()
(interactive)
(set-face-attribute 'org-meta-line nil :inherit 'fixed-pitch)
(set-face-attribute 'org-document-title nil :inherit 'fixed-pitch)
(set-face-attribute 'org-document-info nil :inherit 'fixed-pitch)
(set-face-attribute 'org-document-info-keyword nil :inherit 'fixed-pitch))
(add-hook 'org-mode-hook #'my-org-fixed-pitch)
Note that to actually align the header (i.e. set the right number of spaces) one can select it and then use M-x align-regexp RET <space> RET
.
The same alignment issue occurs within property drawers and can be fixed similarly by adding (set-face-attribute 'org-special-keyword nil :inherit 'fixed-pitch)
to my-org-fixed-pitch
above and the following in init.el:
(defconst my-org-property-re "^\\(?4:[ ]*\\)\\(?1::\\(?2:\\S-+\\):\\)\\(?:\\(?6:\\(?3:$\\)\\)\\|\\(?6:[ ]+\\)\\(?3:.*?\\)\\)\\(?5:[ ]*\\)$"
"Like `org-property-re' but adding one capture group.")
(font-lock-add-keywords
'org-mode
`((,my-org-property-re
6 'org-special-keyword t))
't)
Furthermore, I suspect a similar issue is behind the misalignment of paragraphs under headings that is visible in the left window of the image, and that persists even when one sets a fixed-pitch font for the headings.