9

I've tried to configure whitespace-mode to do what I want but with no luck. I'm trying to achieve the following (see image).

enter image description here

4
  • 1
    I had to download the picture and change the contrast before I could tell what you are trying to achieve. In case others have the same problem, trailing whitespace is displayed as dots ·········· in a rather dark gray on black (or even darker gray). Commented Apr 26, 2016 at 12:00
  • What about (setq whitespace-style '(face trailing))?
    – JeanPierre
    Commented Apr 26, 2016 at 12:02
  • and customizing the face whitespace-trailing.
    – JeanPierre
    Commented Apr 26, 2016 at 12:09
  • @JeanPierre I've spent a ton of time trying to tweak whitespace-style with no luck
    – Cezar
    Commented Apr 30, 2016 at 6:32

2 Answers 2

12

Ignoring whitespace-mode, there's always:

(setq-default show-trailing-whitespace t)

and

M-x customize-face RET trailing-whitespace RET

which might not give you that exact visualisation, but will let you visualise trailing whitespace nevertheless.

I also have a keybinding for this:

(defun toggle-show-trailing-whitespace ()
  "Toggle `show-trailing-whitespace'."
  (interactive)
  (setq show-trailing-whitespace (not show-trailing-whitespace)))

For whitespace-mode ensure you have trailing included in whitespace-style, and once again there's a specific face:

M-x customize-face RET whitespace-trailing RET

In either case, I don't know how you'll get spaces to appear as dots for that face only, unless you can specify a font which has dots for spaces? Someone else might know otherwise.

1
  • That works, but I find the dots to be more subtle which I like a lot.
    – Cezar
    Commented Apr 26, 2016 at 12:22
8

The documentation in the emacs manual says:

Whitespace mode is a buffer-local minor mode that lets you “visualize” many kinds of whitespace in the buffer, by either drawing the whitespace characters with a special face or displaying them as special glyphs.

The relevant docstrings contain more information. So let's say we want do display spaces as ·:

(setq whitespace-display-mappings '((space-mark 32 [?·])))

Note we could add an entry for tab-mark for this to apply to tabs as well.

Now this is only applied if whitespace-style contains space-mark:

(setq whitespace-style '(space-mark))

The problem is we can't specify different glyphs for different kinds of spaces (in your case, trailing versus other spaces), but what we can specify for each kind is a face to be used, so we instead do:

(setq whitespace-style '(face trailing spaces space-mark))   

that is in addition of using the · glyph, we want both trailing spaces and (non trailing, I guess) spaces to be displayed by faces.

Now we have to M-xcustomize-face whitespace-space to a "non visible" face by setting both its Foreground and Background attributes to our background color ; and whitespace-trailing to whatever we want.

Note that whitespace-mode has to be restarted for changes to these variables to take effect.

Also, non trailing whitespaces will be visible as a · when point is there if the cursor-type is a box, or when in highlighted region, that can be annoying.

After all, this is a bit convoluted:

  • there's a space in the buffer there,

  • but it is displayed as a · glyph,

  • but its face "hides" it, making it look like a space.

Additionnaly, trailing white spaces are not shown when point is at line end, after these spaces; this is by design:

This feature does not apply when point is at the end of the line containing the whitespace. Strictly speaking, that is “trailing whitespace” nonetheless, but displaying it specially in that case looks ugly while you are typing in new text. In this special case, the location of point is enough to show you that the spaces are present.

If you really want to change this, here is how it's implemented in whitespace.el:

(defun whitespace-trailing-regexp (limit)
  "Match trailing spaces which do not contain the point at end of line."
  (let ((status t))
    (while (if (re-search-forward whitespace-trailing-regexp limit t)
               (= whitespace-point (match-end 1)) ;; loop if point at eol
             (setq status nil)))          ;; end of buffer
    status))

You can redefine this function in your init file, removing the end of line test:

(defun whitespace-trailing-regexp (limit)
  "Match all trailing spaces. This overloads the definition in whitespace.el."
  (let ((status t))
    (while (unless (re-search-forward whitespace-trailing-regexp limit t)
             (setq status nil)))          ;; end of buffer
    status))

Of course, all of this must be done after whitespace has been loaded, which can be ensured by including (require 'whitespace) first. Another possibility would be to advise the function, I'm not sure what's the prefered way here.

6
  • That is very close, with a small exception. See the first and second screenshots.
    – Cezar
    Commented May 1, 2016 at 15:09
  • @Cezar This is apparently by design, see third paragraph of gnu.org/software/emacs/manual/html_node/emacs/…
    – JeanPierre
    Commented May 1, 2016 at 17:05
  • @Cezar ... but I think can be easily fixed by tweaking the code. I'll update my answer. Another pitfall, non trailing whitespaces are also visible in highlighted region.
    – JeanPierre
    Commented May 1, 2016 at 17:19
  • @JeanPierre in addition, the spaces are visible in the current line if you use hl-line-mode.
    – PythonNut
    Commented May 2, 2016 at 1:48
  • @PythonNut Indeed. Displaying spaces as a dot is done through a display-table and hiding hit with a face is er... a bit of a hack.
    – JeanPierre
    Commented May 3, 2016 at 19:34

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.