A GNU Emacs learning experience with text-mode hooks

For a while, one of my little irritations with my Emacs environment was that sometimes, when I fired up Emacs to edit some code and then quit out of it, Emacs would complain that there was still an ispell process running and ask me what to do with it. This was especially mysterious to me as I don't normally use flyspell-prog-mode (I find it too irritating for general use). Recently I got sufficiently irritated to use a combination of the ELisp debugger and strategic ' (message ...) ' usage to track this down, which initially looked like one issue and actually turned out to be another one that I discovered only as part of writing this entry.

One of the major modes in GNU Emacs is text-mode. I have a text-mode hook, probably like many people, and one of the things it does is turn on flyspell-mode in that buffer, which causes flyspell to invoke ispell and thus start an ispell process. It's also my custom from long ago to set the default major mode of buffers to text-mode (the out of the box default is fundamental-mode). If I'm editing something and it's not program source code, it's almost always text and having to say 'M-x text-mode' all the time is the kind of annoyance GNU Emacs is designed to erase.

When I used debug-on-entry to find out where the ispell process was starting from, it pointed to my text-mode hook. At first I theorized that code buffers were starting out in the default mode (and thus triggering my text-mode hook) before being switched to their proper mode, but strategic use of ' (message ...) ' in my text-mode hook revealed that it was actually being triggered on a scratch buffer for Flycheck. So I switched my theory to Flycheck creating scratch buffers without specifying their mode, so they would up in the default major-mode, which for normal setups is fundamental-mode but for me is text-mode, triggering my text-mode hook and starting ispell.

Except I looked at the Flycheck source and this is wrong. Here, let me quote a small bit:

(define-derived-mode flycheck-error-message-mode text-mode
  "Flycheck error messages"
  "Major mode for extended error messages.")

Flycheck explicitly derives the mode for some of its scratch buffers from text-mode, which of course means that they run text-mode hooks. This is a perfectly reasonable thing to do in general, since text-mode is the appropriate mode in general for, well, text, but it leads me to today's GNU Emacs learning experience which is that text-mode hooks may run in surprising buffers, not just text files I'm visiting and editing . I shouldn't put anything in my text-mode hook that I want only for real text files that I'm editing, at least not without guarding it somehow. One of those things is flyspell, not just because of its side effects of starting an ispell process but also because I don't particularly want flyspell to mark 'misspelled' words in, for example, Flycheck diagnostics.

( Flyspell's markings also get in the way of mouse based copy and paste .)

My solution was to guard what my text-mode hook did so that it only happens in buffers associated with a file:

(defun cks/text-mode-hook ()
  (when buffer-file-name
     ....))

It's possible that some day I'll want my text-mode setup in an anonymous buffer, but until that day I'll leave such scratch buffers alone. I could probably do a bit better by looking for buffer names that start and end with * (this is the usual GNU Emacs naming convention for explicit scratch buffers), but that would take a bit more work.

(Although not much more, now that I've found string-prefix-p and string-suffix-p .)