When I open the Linux Kernel code, my default indentation conflicts with the desired formatting of the Kernel. I use Emacs Prelude, so I added the settings from this link to my c-mode-common-hook. I constrain the indentation only to the Kernel code base by checking the path of the opened file, as they did on the link.

However, one problem remained. Since the Kernel codebase uses tabs and my global whitespace-style is set to '(face tabs empty trailing lines-tail), a bunch of whitespaces in the Kernel code are highlighted. How can I disable tab highlighting within my c-mode-common-hook?

Note that I still want to keep highlighting in other buffers that are not the part of the Kernel codebase.

Update: It looks like setting buffer-local variable does not solve the problem. If I do:

(setq-local whitespace-style (remq 'tabs whitespace-style)

in c-mode-common-hook, it does correctly set the buffer-local variable. I can check it by doing M-: whitespace-style in a Kernel code buffer (it shows the new value I set). However, the buffer still highlights the tabs. It is only when I do M-x whitespace-mode once to disable it, and once more to enable it again that the highlight actually disappears. Unluckily, if I add two (whitespace-mode) in c-mode-common-hook after setting the buffer-local variable, it does not have the same effect as when I call it with M-x once the buffer is fully initialized.

  • The variable whitespace-style is a global variable, which I determined by evaluating (require 'whitespace) and then C-h v (aka M-x describe-variable), enter the variable name, and reading the *Help* buffer. Some popular libraries take a global variable and make it a buffer-local variable and then set the value for that particular buffer. This can be accomplished by ensuring the target buffer has focus and calling (make-local-variable 'whitespace-style) and then (while the target buffer has focus) call (setq whitespace-style ...) and the value set will be buffer-local.
    – lawlist
    Commented Dec 7, 2019 at 8:23
  • @lawlist Thank you. It looks like buffer-locals do not help in this particular case. Please check the update to the question.
    – yujaiyu
    Commented Dec 7, 2019 at 17:04
  • (whitespace-mode) is equivalent to (whitespace-mode 1). i.e. it doesn't toggle, it just enables. This goes for minor modes in general. You could try (whitespace-mode -1) (whitespace-mode 1), but it will be better to set the desired style before calling it in the first place. Depending on the final approach this might entail adding a (require 'whitespace) as well, to ensure whitespace-style exists.
    – phils
    Commented Dec 7, 2019 at 21:42

2 Answers 2


You could do this -- essentially the same as @lawlist's comment:

(add-hook 'c-mode-common-hook 'my-c-mode-common-hook)

(defun my-c-mode-common-hook ()
  "Custom behaviours for `c-mode-common-hook'."
  (when (boundp 'whitespace-style)
    (setq-local whitespace-style (remq 'tabs whitespace-style))))

I constrain the indentation only to the Kernel code base by checking the path of the opened file, as they did on the link.

You might instead use directory-local variables for that purpose. Your .dir-locals.el file might simply be:

((nil . ((whitespace-style . (face empty trailing lines-tail)))))
  • Thank you. It looks like it's something in whitespace-mode itself that prevents it from removing the highlights over whitespaces. Even with the buffer-local variable set correctly, it does not solve the problem. Please check the updated question.
    – yujaiyu
    Commented Dec 7, 2019 at 17:06
  • Right, it's probably going to depend on when whitespace-mode is called in the overall sequence. Show us in the question where that is happening, and it will help.
    – phils
    Commented Dec 7, 2019 at 21:40

I use a hook to edit the whitespace-style variable in a buffer-local way and then have to turn whitespace-mode off and on manually.

;; Major mode for the Go programming language
;; Tree-sitter + Go is not really ready, see https://github.com/dominikh/go-mode.el/issues/428
;; "...the buggy, low-effort go-ts-mode that comes bundled with Emacs..."
;; brew install gopls
(use-package go-mode
  :ensure t
  ("\\.go\\'" . go-mode)
  (go-mode . my-setup-tabs-for-go)
  (go-mode . eglot-ensure)
  (before-save . gofmt-before-save)
  ;; Use 4 spaces to display Tabs, and don't highlight
  (defun my-setup-tabs-for-go ()
    ;; Set these Emacs variables locally, only in Go buffers :custom modifies
    ;; globally). `:custom-local' is a feature request, see:
    ;; https://github.com/jwiegley/use-package/issues/790#issuecomment-1855538903
    (setq-local tab-width 4
                indent-tabs-mode 1
                whitespace-style '(face trailing lines-char empty space-before-tab space-after-tab))
    ;; HACK: `whitespace-style' is global, and setting locally doesn't take
    ;; effect for some reason until `whitespace-mode' is restarted
    ;; https://emacs.stackexchange.com/questions/54212/whitespace-mode-settings-on-per-major-mode-basis
    (whitespace-mode 0)
    (whitespace-mode 1)))

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.