In the Org mode mailing list a patch for this has been suggested in September 2020. All that has to be done is redefine the function org--align-tags-here
. Below I reproduce the new function definition suggested in the patch, with some adjustments to make it work with org-indent-mode
, ensure that there is always visible space between heading and tag, adapt it for use with override advice, and with code to (re-)align tags when opening a file. It works best for non-negative values of org-tags-column
.
Note that the (org-align-tags t)
in the Org mode hook slows down opening large Org files: To align tags in a file with 3400 headings (all with tags) and 11000 lines takes me around two seconds.
The code below makes it impossible to type space at the end of a headline with tags in the usual way. However, to type a space at the end of a headline you can either use C-q SPC
, or org-edit-headline
. You can also uncomment the line (org-fix-tags-on-the-fly)
in the source of org-self-insert-command
. Use org-set-tags-command
to align tags upon creation.
(defun my-org--align-tags-here (to-col)
"Align tags on the current headline to TO-COL.
Since TO-COL is derived from `org-tags-column', a negative value is
interpreted as alignment flush-right, a positive value as flush-left,
and 0 means insert a single space in between the headline and the tags."
;; source: https://list.orgmode.org/[email protected]/
(save-excursion
(when (org-match-line org-tag-line-re)
(let* ((tags-start (match-beginning 1))
(tags-end (match-end 1))
(tags-pixel-width
(car (window-text-pixel-size (selected-window)
tags-start tags-end)))
(blank-start (progn
(goto-char tags-start)
(skip-chars-backward " \t")
(point)))
;; use this to avoid a 0-width space before tags on long lines:
(blank-start-col (progn
(goto-char blank-start)
(current-column)))
;; this is to makes it work with org-indent-mode:
(lpref (if (org-fold-folded-p) 0
(length (get-text-property (point) 'line-prefix)))))
;; If there is more than one space between the headline and
;; tags, delete the extra spaces. Might be better to make the
;; delete region one space smaller rather than inserting a new
;; space?
(when (> tags-start (1+ blank-start))
(delete-region blank-start tags-start)
(goto-char blank-start)
(insert " "))
(if (or (= to-col 0) (< (abs to-col) (1- blank-start-col)))
;; Just leave one normal space width
(remove-text-properties blank-start (1+ blank-start)
'(my-display nil))
(message "In here: %s" lpref)
(let ((align-expr
(if (> to-col 0)
;; Left-align positive values
(+ to-col lpref)
;; Right-align negative values by subtracting the
;; width of the tags. Conveniently, the pixel
;; specification allows us to mix units,
;; subtracting a pixel width from a column number.
`(- ,(- lpref to-col) (,tags-pixel-width)))))
(put-text-property blank-start (1+ blank-start)
'my-display
`(space . (:align-to ,align-expr)))))))))
(defun my-fix-tag-alignment ()
(setq org-tags-column 70) ;; adjust this
(advice-add 'org--align-tags-here :override #'my-org--align-tags-here)
;; this is needed to make it work with https://github.com/minad/org-modern:
(add-to-list 'char-property-alias-alist '(display my-display))
;; this is needed to align tags upon opening an org file:
(org-align-tags t))
(add-hook 'org-mode-hook #'my-fix-tag-alignment)
shr
uses this. Then submit patch. It should probably plug in toorg-indent-mode
. Otherwise make a feature request.