I'm currently using Flyspell to auto-correct the previous word as I type, which is convenient. However, the spell-checker I use, Hunspell, makes some strange decisions.

For example, the misspelled word "hte" is corrected in the following order:

hate HT ht GTE the ...

when it's obvious (at least to me!) that the first correction should be "the"!

I'm not sure whether this is a Flyspell problem or a Hunspell problem. Is it because Flyspell (which, as I understand it, uses ispell behind the scenes) does not get enough context to do a better spell correction, or because the Hunspell dictionary is not good enough?

What's a better way to automatic spelling correction in Emacs?

  • 3
    I would imagine that's hunspell itself, but you can run it directly from the command line on the same text, and see which order the suggestions come out in.
    – phils
    Mar 13, 2016 at 8:22
  • See if this suits your needs while spelling becomes more context aware.
    – Emacs User
    Mar 15, 2016 at 22:45
  • 1
    I believe that for English aspell may give better results than hunspell, but I've never compared them myself.
    – Alan Third
    Aug 16, 2016 at 14:09
  • 2
    I use aspell and have been pleased with it's performance.
    – Qudit
    Sep 14, 2016 at 19:54
  • 1
    Mine seems to work properly, I use this: (when (executable-find "hunspell") (setq-default ispell-program-name "hunspell") (setq ispell-really-hunspell t)) Apr 14, 2017 at 22:12

4 Answers 4


I use enchant in wcheck-mode, which lists "the" as the first suggested correction (though with wcheck you don't have to scroll through corrections to select the one you want, you just type the number or letter of the correction you want).

For example, if I type the following:

To be or not to be, that is hte question.

and then M-x wcheck-actions with point on "hte", I get the following suggestions:

1) [Add to dictionary]  2) the  3) ht  4) he  5) hate  6) hie
7) ate  8) rte  9) hoe  0) hue  a) Ste  b) Rte  c) Ute  d) ht e
--- Choose -----------------------------------------------------
Number or letter (1-9,0,a-d):

Below is my wcheck config (including a hydra and a general.el keybinding which are not strictly necessary, but may be useful, so I'm including them here).

;; * wcheck
;; A very configurable and powerful spellchecker
;;    https://github.com/tlikonen/wcheck-mode
;;    http://www.emacswiki.org/emacs/WcheckMode
;; See the wcheck README for a detailed explanation of these settings.
(autoload 'wcheck-mode "wcheck-mode"
  "Toggle wcheck-mode." t)
(autoload 'wcheck-change-language "wcheck-mode"
  "Switch wcheck-mode languages." t)
(autoload 'wcheck-actions "wcheck-mode"
  "Open actions menu." t)
(autoload 'wcheck-jump-forward "wcheck-mode"
  "Move point forward to next marked text area." t)
(autoload 'wcheck-jump-backward "wcheck-mode"
  "Move point backward to previous marked text area." t)
;; ** Automatically turn on wcheck in text-mode buffers
(dolist (hook '(text-mode-hook))
  (add-hook hook (lambda () (wcheck-mode 1))))
;; ** Automatically turn off wcheck in org-mode buffers
;;    (which for some reason run text-mode hooks, so wcheck needs
;;    to be explicitly disabled in org-mode, or it'll screw up the coloring)
(dolist (hook '(org-mode-hook))
  (add-hook hook (lambda () (wcheck-mode 0))))
;; Hydra for wcheck-mode
(defhydra hydra-wcheck-menu (:hint nil :foreign-keys warn)
_w_:wcheck mode        _f_:forward to next error
_l_:change language    _b_:backward to prev error     _q_:quit
  ("w" wcheck-mode :exit t)
  ("l" wcheck-change-language :exit t)
  ("a" wcheck-actions :exit t)
  ("f" wcheck-jump-forward :exit t)
  ("b" wcheck-jump-backward :exit t)
  ("q" nil nil nil :exit t))
;; Bind some keys under the \mk leader:
(general-define-key :states 'normal
                    :keymaps 'global
                    "\\mk" 'hydra-wcheck-menu/body)

(setq wcheck-language-data
      '(("American English"
         (program . "/usr/bin/enchant")
         (args "-l" "-d" "en_US")
         (action-program . "/usr/bin/enchant")
         (action-args "-a" "-d" "en_US")
         (action-parser . enchant-suggestions-menu))))
(setq wcheck-language "American English")
(defun enchant-suggestions-menu (marked-text)
  (cons (cons "[Add to dictionary]" 'enchant-add-to-dictionary)
(defvar enchant-dictionaries-dir "~/.config/enchant")
(defun enchant-add-to-dictionary (marked-text)
  (let* ((word (aref marked-text 0))
         (language (aref marked-text 4))
         (file (let ((code (nth 1 (member "-d" (wcheck-query-language-data
                                                language 'action-args)))))
                 (when (stringp code)
                   (concat (file-name-as-directory enchant-dictionaries-dir)
                           code ".dic")))))
    (when (and file (file-writable-p file))
        (insert word) (newline)
        (append-to-file (point-min) (point-max) file)
        (message "Added word \"%s\" to the %s dictionary"
                 word language)))))

As mentioned before, you can try aspell. I've also tried hunspell, but I had the same problems as you. I found this answer.

  (if (file-exists-p "/usr/bin/aspell")
        (setq ispell-program-name "aspell")
        (eval-after-load "ispell"
          '(progn (defun ispell-get-coding-system () 'utf-8)))))

You can adjust the sorting by setting flyspell-sort-corrections to non-nil and flyspell-sort-corrections-function to a function which takes care of the sorting.

In addition to that I have written a package recently which you can use to create a so called frog-menu. The README describes how you can use it to select spelling corrections in a more efficient way.


I've been having the same issue, but all I can do is explain the "strange decisions": you're getting the alternatives in alphabetical order.

The only "better way" I've found is that once I know the things are in alphabetical order, I can use C-; to blitz through the alternatives really quickly, and if I go past the one I want, I use C-/ to undo.

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.