I've been playing with flyspell lately and with my recently established setup for spell-check, I wanted to enable it for all modes. I found that flyspell-mode and flyspell-prog-mode are best for text-mode and prog-mode respectively and found in an answer to a similar question that it can be done as:

(add-hook 'text-mode-hook
(add-hook 'prog-mode-hook

I've done the same thing but have noticed that for both the cases, flyspell-mode gets enabled and the flyspell-prog-mode doesn't get enabled at all. My code can be found here and it's the exact same as suggested.

Any help would be appreciated.

1 Answer 1


To help answer this question, we can perform the following steps:

  1. Load the flyspell.el library by typing M: aka M-x eval-expression, and then (require 'flyspell)

  2. Locate the source code for the function flyspell-prog-mode by typing:

    M-x find-function RET flyspell-prog-mode RET

Step two leads us to the source code of the function flyspell-prog-mode, which looks like this in Emacs 26:

(defun flyspell-prog-mode ()
  "Turn on `flyspell-mode' for comments and strings."
  (setq flyspell-generic-check-word-predicate
  (setq-local flyspell--prev-meta-tab-binding
              (or (local-key-binding "\M-\t" t)
                  (global-key-binding "\M-\t" t)))
  (flyspell-mode 1)
  (run-hooks 'flyspell-prog-mode-hook))

Based upon our review of the source code, we now know that flsypell-mode is activated when calling flyspell-prog-mode, which is the second to the last line that reads: (flyspell-mode 1). And, we see that two variables are expressly set when calling flyspell-prog-mode; i.e., flyspell-generic-check-word-predicate and flyspell--prev-meta-tab-binding. We observe that flyspell--prev-meta-tab-binding is set on a buffer-local basis with setq-local.

We see that flyspell-generic-check-word-predicate is set with setq and we wonder to ourselves whether that variable is buffer-local already or whether the value is being modified on a global basis. To satisfy our curiosity, we look up the variable with C-h v aka M-x describe-variable. We read the *Help* buffer and see that this variable was already buffer-local and we surmise that this is the reason why setq was used when setting the aforementioned variable in the function flyspell-prog-mode -- the *Help* buffer states in relevant part: "Automatically becomes buffer-local when set."

CONCLUSION:  flyspell-prog-mode is not really a mode per se; i.e., it is not a minor-mode and it is not a major-mode. Instead, it is just flyspell-mode plus the setting of two variables on a buffer-local basis; i.e., flyspell-generic-check-word-predicate and flyspell--prev-meta-tab-binding. flyspell-generic-check-word-predicate is set with the value of a function named flyspell-generic-progmode-verify. flyspell--prev-meta-tab-binding is a keyboard shortcut. The hook flyspell-prog-mode-hook has no default value, but we could add anything that is appropriate; e.g., (add-hook 'flyspell-prog-mode-hook (lambda () (message "Turned on flyspell-prog-mode ...")))

  • I had a suspicion but that shows the proof! However, as per the description, flyspell-prog-mode is supposed to only run spell-check on comments and strings in a program buffer, but I see that it's trying to run it for language keywords like defvar and progn as well for my Lisp files. Do you think I missed something?
    – myTerminal
    Commented Dec 13, 2019 at 15:46
  • I am unable to duplicate the results you are seeing. I open Emacs 26 on OSX without any user-configuration and evaluate the following snippet: (progn (require 'flyspell) (setq ispell-program-name "/absolute/path/to/the/executable/of/aspell") (find-library "flyspell") (flyspell-prog-mode)) Then, I use isearch by typing C-s and then enter the word defvar and am transported to the first occurrence which is just before flyspell-mode-map, and then I press RET to exit ispell and leave the cursor right where it is. When I place the cursor anywhere on the word defvar, no error.
    – lawlist
    Commented Dec 14, 2019 at 1:29
  • I have the same result (i.e., no spelling error detected) when I use the following snippet in a .emacs file without any additional user-configuration: (require 'flyspell) (add-hook 'prog-mode-hook 'flyspell-prog-mode) (setq ispell-program-name "/absolute/path/to/the/executable/of/aspell") (add-hook 'emacs-startup-hook (lambda () (with-current-buffer (find-library "flyspell") (re-search-forward "defvar" nil t)))) If there are other buffers that have focus, then switch to the flyspell.el buffer and maneuver the cursor over the word defvar -- I see no misspelling indicated.
    – lawlist
    Commented Dec 14, 2019 at 1:46

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.