Subject: Margin strings are displayed in reverse order of overlay priority (low-priority specs hide high-priority ones)

From: Clément Pit-Claudel <[email-masked]>
Date: Fri, 24 Apr 2020 11:56:45 -0400

Hi all,

The following sample shows the words "low", "mid" and "high" in the left margin using overlays.

(with-current-buffer (get-buffer-create "*margins*")
  (erase-buffer)
  (delete-all-overlays)
  (setq left-margin-width 16)
  (let ((beg (point))
        (end (progn (insert "test") (point))))
    (let ((ov-low (make-overlay beg end)))
      (overlay-put ov-low 'before-string (propertize "low" 'display '((margin left-margin) "low")))
      (overlay-put ov-low 'priority 10))
    (let ((ov-mid (make-overlay beg end)))
      (overlay-put ov-mid 'before-string (propertize "mid" 'display '((margin left-margin) "mid")))
      (overlay-put ov-mid 'priority 50))
    (let ((ov-high (make-overlay beg end)))
      (overlay-put ov-high 'before-string (propertize "high" 'display '((margin left-margin) "high")))
      (overlay-put ov-high 'priority 100))))

All three overlays begin at the same point.  Currently, it seems that margin specs are concatenated in order of increasing priority.  This is likely due to before-strings being concatenated in that order?
One unfortunate side effect of this is that, when margins are too narrow, low-priority margin specs are displayed before high-priority ones, and hence high-priority ones are not visible.

Additionally, unlike fringe bitmaps, for which the highest-priority bitmap replaces all others on the same line, there doesn't seem to be a way for higher-priority margin specs to replace lower-priority ones.

This issue came up when trying to develop a mode to indicate errors and warnings in the margins (instead of drawing symbols in the fringes).  Currently, if a line contains errors and warnings, Flycheck will place multiple overlays on the same line, and the fringe bitmap corresponding to the highest-priority one will be displayed.  But if we put a symbol in the margins instead of the fringes, the symbols won't override each others: instead, they will be concatenated, often in the wrong order (as shown in the attached screenshot).

It would be great if margin specs could be displayed in order of decreasing priority, or if some mechanism existed to indicate that two margin specs are intended to replace each other (the highest-priority one replacing the lowest-priority one), rather than being concatenated.

Clément.