11

With:

(when window-system
  (set-face-background 'hl-line "light yellow")
  (global-hl-line-mode 1))

current line highlighted by yellow background, but if text has background properties it also overwritten (like diff-mode, rainbow-mode).

Is it possible to set background only for parts that have no appropriate properties?

UPDATE I start experimenting, seems that stipple isn't conflicting with background:

(set-face-stipple 'hl-line '(4 4 "\x01\x00\x00\x00"))
(set-face-attribute 'hl-line nil :inherit nil)

But stipple unfortunately damage text appearance...

Drew
  • 75,699
  • 9
  • 109
  • 225
gavenkoa
  • 3,352
  • 19
  • 36
  • 1
    Another possibility you may wish to consider is a removal function placed at the tail end of each hl-line command loop, such that a search is performed from the beginning of the current line to the end of the current line (or to the end of the current visual line, if applicable) and the hl-line overlay face can then be removed from wherever other text with a different background color exists. You will likely be searching for highlighting placed by font-lock, although you might also have highlighting placed with other overlays (e.g., flyspell errors / duplicates). – lawlist Apr 01 '15 at 13:55
  • 1
    @lawlist I am interested in its implementation; can you please add the full solution below? – Kaushal Modi Apr 01 '15 at 15:01
  • @kaushalmodi -- I know how to do this for specific overlays or raw text at point, but not for specific text-properties / font-lock highlighting at point. Because I would need to research how to test for those latter two occurrences in order to properly answer this question, I chose to to make a comment instead. Here is a snippet [borrowed from one of Drew's libraries] to test for specific overlays at point: `(when (memq NAME-OF-FACE (mapcar (function (lambda (ovr) (overlay-get ovr 'face))) (overlays-at (point)))) (remove-overlays BEGINNING-POINT ENDING-POINT 'face hl-line))` – lawlist Apr 01 '15 at 16:18

3 Answers3

6

I end with a partial solution - highlight only from the end of line:

(defun my-hl-line-range-function ()
  (cons (line-end-position) (line-beginning-position 2)))
(setq hl-line-range-function #'my-hl-line-range-function)

(when window-system
  (require 'hl-line)
  (set-face-attribute 'hl-line nil :inherit nil :background "light yellow")
  (setq global-hl-line-sticky-flag t)
  (global-hl-line-mode 1))
gavenkoa
  • 3,352
  • 19
  • 36
5

The problem is that sometimes text property face is used for highlighting, and hl-line-mode uses an overlay. And overlays always appear "on top of" text property face highlighting.

diff-mode, for example, uses the text property, not an overlay. So for cases like this you are out of luck.

But for highlighting that is produced by an overlay you can just reduce the overlay priority of the hl-line overlay: either hl-line-overlay or global-hl-line-overlay, so that that overlay appears to be "below" the other overlay highlighting.

If you use library hl-line+.el then you can use option hl-line-overlay-priority to set the overlay priority. See also Emacs Wiki page Highlight Current Line. (But again, changing the overlay priority has no effect if the other highlighting is not from an overlay.)

Drew
  • 75,699
  • 9
  • 109
  • 225
  • Thanks for answer. I don't bother about difference between faces and overlays... +1 – gavenkoa Apr 02 '15 at 09:01
  • How do I access that `hl-line-overlay` property? It e.g. does not show up in `customize-variable`. – 9000 Nov 09 '16 at 19:51
  • 1
    @9000: As the answer says, if you use library `hl-line+.el` then you just customize option `hl-line-overlay-priority`. Otherwise, you cannot (except by redefining or advising the preprovided functions). That's the point of providing this user option. – Drew Nov 10 '16 at 03:03
  • 1
    @9000 You just need to redefine the function `hl-line-make-overlay` in your `init.el`. (Or use `(advice-add 'hl-line-make-overlay :override #'my/hl-line-make-overlay)`.) It's rather useless though, as the background properties are ignored. – HappyFace May 19 '21 at 17:27
1

Stumbled on this question when attempting not to make the hl-line override the background (although it was indentation guides in this case):

I settled on this, which starts drawing the highlight line after the indentation:

(defun my-hl-line-range-function ()
  (cons
   (+ (line-beginning-position 1) (current-indentation))
   (line-beginning-position 2)))
(setq hl-line-range-function #'my-hl-line-range-function)

Replacing (+ (line-beginning-position 1) (current-indentation)) with (point) works too, (starting at the cursor).

ideasman42
  • 8,375
  • 1
  • 28
  • 105