4

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

  • 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). – Harald Hanche-Olsen Apr 26 '16 at 12:00
  • What about (setq whitespace-style '(face trailing))? – JeanPierre Apr 26 '16 at 12:02
  • and customizing the face whitespace-trailing. – JeanPierre Apr 26 '16 at 12:09
  • @JeanPierre I've spent a ton of time trying to tweak whitespace-style with no luck – Cezar Apr 30 '16 at 6:32
6

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.

  • That works, but I find the dots to be more subtle which I like a lot. – Cezar Apr 26 '16 at 12:22
6

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.

  • That is very close, with a small exception. See the first and second screenshots. – Cezar May 1 '16 at 15:09
  • @Cezar This is apparently by design, see third paragraph of gnu.org/software/emacs/manual/html_node/emacs/… – JeanPierre May 1 '16 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 May 1 '16 at 17:19
  • @JeanPierre in addition, the spaces are visible in the current line if you use hl-line-mode. – PythonNut May 2 '16 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 May 3 '16 at 19:34

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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