7

I want to enable show-trailing-whitespace for editable file and disable show-trailing-whitespace for read only files. I've tried

(defun my/read-only-whitespace ()
  (setq-local show-trailing-whitespace (not buffer-read-only)))

(setq-default show-trailing-whitespace t)
(add-hook 'read-only-mode-hook #'my/read-only-whitespace)

But this only only seems to work if I enable read-only-mode manually. When I open a buffer that becomes read-only automatically (e.g. a read-only file) then the hook is not run.

Is there a hook that runs for all read-only buffers?

Moyamo
  • 388
  • 2
  • 7

2 Answers2

6

If you want this to act in any buffer, not just a file-visiting buffer then find-file-hook is not appropriate. (You said "all buffers", but you also spoke of editable/non-editable "files".)

If you want it to work in all buffers then this is one solution:

(defun my-show-trailing-ws ()
  "Show trailing whitespace in the current buffer, unless it is read-only."
  (setq-local show-trailing-whitespace (not buffer-read-only)))

(add-hook 'post-command-hook 'my-show-trailing-ws)

You can wrap that in a minor mode command, if you like.

Another possibility is to use an idle timer, but post-command-hook seems fine for what you're looking for.

As far as I know, there is no hook that corresponds to a change in buffer-read-only. However, if you use Emacs 26 or later then you can use function add-variable-watcher to turn on/off showing trailing whitespace whenever variable buffer-read-only is changed.

(add-variable-watcher 'buffer-read-only 'foo) ; Add watcher `foo'

(defun foo (symbol newval operation where) ; 100% untested...
   "Show trailing whitespace in the current buffer, unless it is read-only."
   (when (and (eq symbol 'buffer-read-only)
              (memq operation '(set let))
              (eq where (current-buffer)))
     (setq-local show-trailing-whitespace (not newval))))
Drew
  • 75,699
  • 9
  • 109
  • 225
  • It seems a bit overkill to run this function after every command. Is their no simpler way? – Moyamo Jan 21 '18 at 20:18
  • @Moyamo Try it, then decide if you think it makes emacs sluggish. My bet is that you won't notice any slowdown or increased cpu usage due to this code. If you're worried, make sure that `my-show-trailing-ws` is compiled. – Harald Hanche-Olsen Jan 21 '18 at 20:28
  • The variable watcher solution for Emacs 26 works well. – GDP2 Jun 06 '19 at 16:22
1

You could use find-file-hook and check the read only status of the buffer:

(defun my/read-only-whitespace ()
  (when buffer-read-only
    (setq-local show-trailing-whitespace (not buffer-read-only))))
(add-hook 'find-file-hook 'my/read-only-whitespace)
Harald Hanche-Olsen
  • 2,401
  • 12
  • 15