The ispell package serves as the underlying interface in Emacs for communicating with external spell checking programs. Building upon this, the flyspell package is a built-in minor mode that provides on-the-fly spell checking. It highlights misspelled words as you type and offers interactive corrections. This article presents a practical configuration for Emacs that sets up ispell to use Aspell for both programming and standard text editing.
Additionally, it addresses a common issue for developers. While writing code, variables such as filepath or buffername in comments or docstrings are often flagged as errors, generating visual noise in your programming buffers. This article contains a specific configuration to reduce these false positives.
Setting the backend and dictionary
The first step is to configure Emacs to use Aspell as the underlying spell checking engine, set the default dictionary used by Ispell and Flyspell, and suppress unnecessary startup messages:
;; Set the ispell program name to aspell
(setq ispell-program-name "aspell")
;; Set the global default dictionary for the Ispell process.
(setq ispell-dictionary "en_US")
;; Suppress non-corrective messages from ispell-word.
(setq ispell-quietly t)Code language: Lisp (lisp)
Note that this configuration explicitly targets the US English dictionary "en_US". If you write in a different language or require a different regional dialect, such as "en_GB" or "fr_FR", replace "en_US" with your preferred language code.
Configuring aspell flags
The following configures Aspell's suggestion mode to "ultra", which favors very close spelling and phonetic matches when generating suggestions:
;; Configures Aspell's suggestion mode to "ultra", which provides more
;; aggressive and detailed suggestions for misspelled words.
(setq ispell-extra-args '("--sug-mode=ultra"))Code language: Lisp (lisp)
Handling compound words in source code
Comments and string literals in source code are heavily populated with compound variable names and technical terms, such as filepath, buffername, or checkbox. Aspell may flag these as errors, generating visual noise in programming buffers.
To resolve this, we pass the --run-together flag to Aspell. This flag allows Aspell to recognize words formed by combining valid dictionary words without spaces. (It only affects words in the comments and strings that Flyspell checks; it does not cause Flyspell to check arbitrary identifiers elsewhere in the source buffer.)
To apply this cleanly, we can define a custom wrapper function that we will later attach to our programming modes using add-hook. This function activates flyspell-prog-mode and then safely appends the required flags buffer-locally using add-to-list, which inherently prevents duplicate arguments if the mode is toggled off and on:
(defun my-flyspell-prog-mode (&rest _args)
"Append Ispell arguments buffer-locally."
;; The --run-together flag instructs Aspell to accept words formed by
;; combining two or more valid dictionary words without spaces, treating the
;; resulting string as valid.
;;
;; This is excellent for source code. Code is heavily populated with
;; compound variable names and technical terms (e.g., filepath, buffername,
;; checkbox).
;; URL: https://www.jamescherti.com/emacs-spell-checker-flyspell-ispell-aspell/
(make-local-variable 'ispell-extra-args)
(dolist (item '("--run-together"
;; "--ignore=2"
;; "--run-together-min=3"
;; "--run-together-limit=16"
;; "--camel-case"
))
(add-to-list 'ispell-extra-args item))
(flyspell-prog-mode))Code language: Lisp (lisp)
Here are four additional flags worth uncommenting in the my-flyspell-prog-mode function above. Each provides specific advantages for programming workflows, along with some tradeoffs to consider:
--run-together-limit=4: Increases the maximum number of combined words allowed in a single string from the default limit of two up to 4. (A higher limit increases the probability that a genuine typo will be silently ignored because Aspell manages to break the misspelling down into a sequence of several shorter valid words. It also adds a slight processing overhead.)--run-together-min=3: Specifies the minimum character length required for each individual word within a compound string. It prevents Aspell from validating typos by improperly splitting them into tiny one- or two-letter words. Tradeoff: It will flag legitimate variables that use short prefixes, such asmyordb.--ignore=2: Configures Aspell to completely skip words containing two characters or fewer. Tradeoff: You lose spell checking for actual two-letter English words (such as "is", "an", "to", "of").--camel-case: Enables Aspell's camel-case word handling, allowing camelCase identifiers to be checked more appropriately. It can reduce false positives for identifiers such asmyHttpRequestthat appear in docstrings and comments. Tradeoff: It can occasionally mask a typo if its components are individually recognized as valid words.
Initializing the Packages
Finally, we use add-hook to bind the spell checking functions to the appropriate Emacs hooks:
;; The flyspell package is a built-in Emacs minor mode that provides on-the-fly
;; spell checking. It highlights misspelled words as you type, offering
;; interactive corrections.
;; URL: https://www.jamescherti.com/emacs-spell-checker-flyspell-ispell-aspell/
(defun my-flyspell-enable-appropriate-mode ()
"Enable the appropriate Flyspell mode based on the current major mode."
(if (or (derived-mode-p 'conf-mode)
(derived-mode-p 'yaml-mode)
(derived-mode-p 'yaml-ts-mode)
(derived-mode-p 'ansible-mode)
(derived-mode-p 'nxml-mode)
(derived-mode-p 'sgml-mode))
(my-flyspell-prog-mode)
(flyspell-mode 1)))
(add-hook 'prog-mode-hook #'my-flyspell-prog-mode)
(add-hook 'conf-mode-hook #'my-flyspell-enable-appropriate-mode)
(add-hook 'text-mode-hook #'my-flyspell-enable-appropriate-mode)Code language: Lisp (lisp)
Note: Configuration files such as YAML and Ansible playbooks can present an edge case because some source-like modes are based on text-mode rather than prog-mode. Without an explicit override, such modes may receive ordinary Flyspell behavior rather than programming-mode behavior. Since these files behave more like source code, we use a custom dispatcher function to apply my-flyspell-prog-mode to them instead.