Enchanted Spell Checker
jinx-, 2023-Sep-21, 110 KiB
Daniel Mendler <mail@daniel-mendler.de>
Browse ELPA's repository
CGit or Gitweb

To install this package from Emacs, use package-install or list-packages.

Full description


Jinx is a fast just-in-time spell-checker for Emacs. Jinx highlights misspelled words in the text of the visible portion of the buffer. For efficiency, Jinx highlights misspellings lazily, recognizes window boundaries and text folding, if any. For example, when unfolding or scrolling, only the newly visible part of the text is checked if it has not been checked before. Each misspelling can be corrected from a list of dictionary words presented as a completion menu.

Installing Jinx is straight-forward and configuring should not need much intervention. Jinx can be used completely on its own, but can also safely co-exist with Emacs's built-in spell-checker Ispell.

Jinx's high performance and low resource usage comes from directly calling the widely-used API of the Enchant library (see libenchant). Jinx automatically compiles jinx-mod.c and loads the dynamic module at startup. By binding directly to the native Enchant API, Jinx avoids the slower backend process communication with Aspell. Enchant is widely used by other text editors and supports Nuspell, Hunspell, Aspell and a few language-specific backends.

Jinx supports spell-checking multiple languages in the same buffer. See the jinx-languages variable to customize for multiple languages. Jinx can flexibly ignore misspellings via faces (jinx-exclude-faces and jinx-include-faces), regular expressions (jinx-exclude-regexps), and programmable predicates. Jinx comes preconfigured for the most important Emacs major modes. Modes like Java, Ruby or Rust are listed in jinx-camel-modes. For these modes composite words in camelCase and PascalCase are accepted.

1. Installation

Jinx can be installed from GNU ELPA or MELPA directly with package-install.

Jinx requires libenchant. Enchant library is a required dependency for Jinx to compile its module at install time. If pkgconf or pkg-config is available when installing Jinx, Jinx will use it to locate libenchant. Depending on your operating system and Linux distribution you have to install different packages:

  • Debian, Ubuntu: libenchant-2-dev, pkgconf
  • Arch, Gentoo: enchant, pkgconf
  • Guix: emacs-jinx or enchant, pkgconf
  • Void, Fedora: enchant2-devel, pkgconf
  • FreeBSD, OpenBSD, Mac: enchant2, pkgconf

2. Configuration

Jinx has two modes: the command, global-jinx-mode activates globally; and the command, jinx-mode, for activating for specific modes.

;; Alternative 1: Enable Jinx globally
(add-hook 'emacs-startup-hook #'global-jinx-mode)

;; Alternative 2: Enable Jinx per mode
(dolist (hook '(text-mode-hook prog-mode-hook conf-mode-hook))
  (add-hook hook #'jinx-mode))

The commands jinx-correct and jinx-languages are marked as autoloads. Invoking jinx-correct corrects the misspellings. Binding jinx-correct to M-$ takes over that key from the default assignment to ispell-word. Since Jinx is independent of the Ispell package, M-$ can be re-used.

(keymap-global-set "M-$" #'jinx-correct)
(keymap-global-set "C-M-$" #'jinx-languages)
  • M-$ triggers correction for the misspelled word before point.
  • C-u M-$ triggers correction for the entire buffer.
  • C-u C-u M-$ forces correction of the word at point, even if it is not misspelled.

A sample configuration with the popular use-package macro is shown here:

(use-package jinx
  :hook (emacs-startup . global-jinx-mode)
  :bind (("M-$" . jinx-correct)
	 ("C-M-$" . jinx-languages)))

See also the Jinx Wiki for additional configuration tips. The wiki documents configurations to save misspellings as global abbreviations and support for Ispell LocalWords.

3. Correcting misspellings

After invoking the command jinx-correct, suggested corrections are displayed as a completion menu. You can press the displayed digit keys to quickly select a suggestion. Furthermore the menu offers options to save the word temporarily for the current session, in the personal dictionary or in the file-local variables.

Note that you can enter arbitrary input at the correction prompt in order to make the correction or to store a modified word in the personal dictionary. For example if you typed alotriomorpc, the prompt offers you the option @alotriomorpc which would add this word to your personal dictionary upon selection. You can then correct the option to @allotriomorphic and add it to the dictionary.

While inside the jinx-correct prompt, the keys M-n and M-p are bound to jinx-next and jinx-previous respectively and allow you to move the next and previous misspelled word.

The completion menu is compatible with all popular completion UIs: Vertico, Mct, Icomplete, Ivy, Helm and the default completions buffer. In case you use Vertico I suggest that you tweak the completion display via vertico-multiform-mode for the completion category jinx. You can for example use the grid display such that more suggestions fit on the screen and enable annotations.

(add-to-list 'vertico-multiform-categories
	     '(jinx grid (vertico-grid-annotate . 20)))
(vertico-multiform-mode 1)

4. Navigating between misspellings

As mentioned before, when correcting a word with jinx-correct, the movement commands jinx-next and jinx-previous are available on the keys M-n and M-p to navigate to the next and previous misspelling respectively. The movement commands work from within the minibuffer during jinx-correct and also globally outside the minibuffer context.

While the commands are not bound globally by default, they are available as M-n and M-p if point is placed on top of a misspelled word overlay. If you want you can add them and other commands to the jinx-mode-map, such that they are always available independent of point placement. If repeat-mode from Emacs 28 is enabled, the movement can be repeated with the keys n and p.

5. Enchant backends and personal dictionaries

Enchant uses different backends for different languages. The backends are ordered as specified in the personal configuration file ~/.config/enchant/enchant.ordering and the system-wide configuration file /usr/share/enchant-2/enchant.ordering. Enchant uses Hunspell as default backend for most languages. There are a few exceptions. For English Enchant prefers Aspell and for Finnish and Turkish special backends called Voikko and Zemberek are used. On non-Linux operating systems Enchant may also integrate with the spell-checker provided by the operating system.

Depending on the backend the personal dictionary will be taken from different locations, e.g., ~/.aspell.LANG.pws or ~/.config/enchant/LANG.dic. It is possible to symlink different personal dictionaries such that they are shared by different spell checkers. See the Enchant manual for details.

6. Alternative spell-checking packages

There exist multiple alternative spell-checking packages for Emacs, most famously the builtin ispell.el and flyspell.el packages. The main advantages of Jinx are its automatic checking of the visible text, its sharp focus on performance and the ability to easily use multiple dictionaries at once. The following three alternative packages come closest to the behavior of Jinx.

  • jit-spell: Jinx UI borrows ideas from Augusto Stoffel's Jit-spell. Jit-spell uses the less efficient Ispell process communication instead of Jinx's calling a native API. Since Jit-spell does not restrict spell checking to the visible text only, it may enqueue the entire buffer too eagerly for checking. This happens when scrolling around or when stealth font locking is enabled. For this reason, Jit-spell affected load and latency in my tests (issue on Github).
  • spell-fu: The idea to check words just in the visible text came from Campbell Barton's spell-fu package. Spell-fu is fast but incurs high memory overhead on account of its dictionary in a hash table. For languages with compound words and inflected word forms, this overhead magnifies (issue on Codeberg). By accessing the Enchant API directly, Jinx avoids any overhead. Jinx also benefits from the advanced spell-checker algorithms of Enchant (affixation, compound words, etc.).
  • flyspell: Flyspell is a built-in package. Flyspell highlights misspellings while typing. Only the word under the cursor is spell-checked. Jinx, on the other hand, is more effective because it automatically checks for misspellings in the entire visible text of the buffer at once. Flyspell can check the entire buffer but must be instructed to do so via the command flyspell-buffer.

7. Contributions

Since this package is part of GNU ELPA contributions require a copyright assignment to the FSF.

Old versions

jinx- KiB
jinx- KiB
jinx- KiB
jinx- KiB
jinx- KiB
jinx- KiB
jinx- KiB
jinx- KiB
jinx- KiB
jinx- KiB


1. Development

  • Allow capitalized form of a word if non-capitalized word is stored in the session word list.
  • Replace jinx-excluded-modes with global-jinx-modes, the Emacs 28 convention for globalized minor modes.
  • jinx-correct: Offer session words as suggestions.
  • Add jinx-correct-nearest, jinx-correct-all and jinx-correct-word commands. The command jinx-correct dispatches to one of those commands depending on the prefix argument.

2. Version 0.9 (2023-07-02)

  • 🪄 Make sure that Emojis are not marked as misspelled 🧙🏼‍♀️.
  • Rename jinx-correct-next/previous to jinx-next/previous. The commands can be used outside the minibuffer.
  • Bind M-n and M-p to jinx-next/previous in jinx-overlay-map.
  • Bind M-$ to jinx-correct in the jinx-overlay-map.
  • Add jinx-repeat-map.
  • Rename category of Jinx overlays to jinx-overlay.
  • Rename jinx-misspelled-map to jinx-overlay-map.
  • Add many more language modes to jinx-camel-modes.

3. Version 0.8 (2023-04-28)

  • jinx-correct: Consistently move backward to the previous misspelling. In order to move backward further, press M-$ again (or M-p). Move forward with M-n.
  • jinx-correct-select: Support more than 10 quick keys.
  • jinx-languages: New argument LANGS.
  • Add jinx-faces customization group.
  • Add configurable save actions via jinx--save-keys.
  • Detect C compiler via $CC or executable-find.

4. Version 0.7 (2023-04-21)

  • Bugfixes
  • jinx-languages: Only ask in file-backed buffers if file-local variable should be saved.
  • Push undo-boundary before correcting a word, such that corrections are not undone in a single step.
  • jinx-correct: Use + as prefix to add word to the current session.
  • Add jinx-correct-map bound in the jinx-correct minibuffer.
  • Add navigation keys to correction UI. The commands jinx-correct-next and jinx-correct-previous are bound to the keys M-n and M-p in the jinx-correct-map respectively. The commands accept prefix arguments to skip over a number of misspellings.
  • Add quick selection keys to correction UI. The command jinx-correct-select is bound to the keys 1 to 9 in the jinx-correct-map.
  • Try to locate the native module jinx-mod.so first on the load-path before attempting to compile it. This is useful if the module is packed and installed separately.

5. Version 0.6 (2023-04-17)

  • Fix the type of a few characters: . punctuation character, ' word character, % and $ identifier characters.
  • Abandon flyspell-mode-predicate completely. Rely on faces only.
  • jinx-languages: The value must be a string now. Multiple language codes can be separated by space.
  • jinx-languages: Ask if the file-local variable should be saved when changing the language.
  • Add jinx-local-words to save file-local words. jinx-correct supports saving to jinx-local-words by pressing *.
  • Add a lighter and a minor mode menu.
  • Avoid scheduling the idle timer while typing a word.

6. Version 0.5 (2023-04-05)

  • Add jinx-languages command to switch languages locally or globally.
  • jinx-correct: When checking the whole buffer via C-u M-$, don't restore original point position upon C-g to ease cursory edits. Instead push a mark which can be used to go back to the original position.
  • Add jinx-mode-map to make it easy to bind keys if jinx-mode is enabled. The map is empty by default.
  • Ignore single quotes and apostrophes at the beginning and end of words. Please provide feedback if this is a reasonable approach.
  • Support spell checking of camelCased words via the jinx-camel-modes variable.

7. Version 0.4 (2023-03-27)

  • jinx-languages: Fall back to $LANG environment variable, since current-locale-environment is an Emacs 29 addition.
  • jinx--mod-wordchars: Handle non-UTF8 return values gracefully.
  • jinx-correct: Always start from nearest overlay.
  • jinx-misspelled: Use less obtrusive color for the underlining.

… …