#+title: jinx.el - Enchanted Spell Checker
#+author: Daniel Mendler
#+language: en
#+export_file_name: jinx.texi
#+texinfo_dir_category: Emacs misc features
#+texinfo_dir_title: Jinx: (jinx).
#+texinfo_dir_desc: Enchanted Spell Checker

#+html: <a href="https://www.gnu.org/software/emacs/"><img alt="GNU Emacs" src="https://github.com/minad/corfu/blob/screenshots/emacs.svg?raw=true"/></a>
#+html: <a href="https://elpa.gnu.org/packages/jinx.html"><img alt="GNU ELPA" src="https://elpa.gnu.org/packages/jinx.svg"/></a>
#+html: <a href="https://elpa.gnu.org/devel/jinx.html"><img alt="GNU-devel ELPA" src="https://elpa.gnu.org/devel/jinx.svg"/></a>
#+html: <a href="https://melpa.org/#/jinx"><img alt="MELPA" src="https://melpa.org/packages/jinx-badge.svg"/></a>
#+html: <a href="https://stable.melpa.org/#/jinx"><img alt="MELPA Stable" src="https://stable.melpa.org/packages/jinx-badge.svg"/></a>

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 takes not much intervention.
Jinx can safely co-exist with Emacs's built-in spell-checker.

Jinx's high performance and low resource usage comes from directly calling the
widely-used API of the Enchant library (see [[https://abiword.github.io/enchant/][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. Thanks to the Enchant API, this method is widely used by other text
editors and supports [[https://nuspell.github.io/][Nuspell]], [[http://hunspell.github.io/][Hunspell]], [[http://aspell.net/][Aspell]] and a few lesser known 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. For modes listed
in =jinx-camel-modes= composite words in camelCase and PascalCase are accepted.

#+html: <img src="https://github.com/minad/jinx/blob/screenshots/screenshot.png?raw=true">

* Installing Jinx

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

Jinx requires =libenchant=. Enchant library is a required dependency for Jinx to
compile its module at install time. If =pkg-config= is available when installing
Jinx, Jinx will use =pkg-config= to locate =libenchant=.

On Debian or Ubuntu, install the packages =libenchant-2-dev= and =pkg-config=. On
Fedora or RHEL, install the package =enchant2-devel=. On Mac, install =enchant2= and
=pkgconfig=.

* Using Jinx

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

#+begin_src emacs-lisp
  ;; 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))
#+end_src

Jinx autoloads the commands =jinx-correct= and =jinx-languages=. Invoking
=jinx-correct= corrects the misspellings. Binding =jinx-correct= to =M-$= chord takes
over that chord from Emacs's default assignment to =ispell word=. Since Jinx is
independent of the Emacs's Ispell package, =M-$= can be re-used.

#+begin_src emacs-lisp
  (keymap-global-set "<remap> <ispell-word>" #'jinx-correct)
#+end_src

- =M-$= triggers correction for the misspelled word next to point.
- =C-u M-$= triggers correction for the entire buffer.

Suggested corrections are displayed via a completion menu. You can press 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. By pressing =M-n= (=M-p=) again
in the correction menu, you can skip to the next (previous) misspelling.

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

#+begin_src emacs-lisp
  (use-package jinx
    :hook (emacs-startup . global-jinx-mode)
    :bind ([remap ispell-word] . jinx-correct))
#+end_src

* Enchant backends and personal dictionaries

Enchant uses different backends for different languages (to be spell-checked).
The backends are ordered as specified in the configuration file
=~/.config/enchant/enchant.ordering=. For most languages, Enchant uses Hunspell by
default.

Depending on the backend the personal dictionary will be taken from different
locations, e.g., =~/.aspell.LANG.pws= or =~/.config/enchant/=. It is possible to
symlink different personal dictionaries such that they are shared by different
spell checkers. See the [[https://abiword.github.io/enchant/src/enchant.html][Enchant manual]] for details.

* 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.

- [[https://github.com/astoff/jit-spell][jit-spell]]: Jinx UI borrows ideas from Augusto Stoffel's Jit-spell. Jit-spell
  uses the less efficient Ispell process communication instead Jinx's calling
  native API. Since Jit-spell highlights misspellings in the entire buffer and
  does not confine to just the visible text, Jit-spell affected load and latency
  negatively in my tests ([[https://github.com/astoff/jit-spell/issues/9][issue on github]]).

- [[https://codeberg.org/ideasman42/emacs-spell-fu][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 ([[https://codeberg.org/ideasman42/emacs-spell-fu/issues/40][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 Emacs's 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=.

* Contributions

Since this package is part of [[https://elpa.gnu.org/packages/jinx.html][GNU ELPA]] contributions require a copyright
assignment to the FSF.
