3

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?

Tianxiang Xiong
  • 3,848
  • 16
  • 27
  • 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 '16 at 08:22
  • See if this [suits your needs](http://endlessparentheses.com/ispell-and-abbrev-the-perfect-auto-correct.html) while spelling becomes more context aware. – Emacs User Mar 15 '16 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 '16 at 14:09
  • 2
    I use aspell and have been pleased with it's performance. – Qudit Sep 14 '16 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)) – eflanigan00 Apr 14 '17 at 22:12
  • This might be worth a look: http://blog.binchen.org/posts/what-s-the-best-spell-check-set-up-in-emacs.html – eflanigan00 Apr 14 '17 at 22:14
  • `aspell` gives exactly the same suggestions. – politza Sep 10 '17 at 21:40
  • "hate" seems to me to be a better suggestion that "the" – Edman Mar 29 '19 at 01:55

4 Answers4

3

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")
      (progn
        (setq ispell-program-name "aspell")
        (eval-after-load "ispell"
          '(progn (defun ispell-get-coding-system () 'utf-8)))))
Edman
  • 1,167
  • 7
  • 13
bertfred
  • 1,699
  • 1
  • 11
  • 23
3

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)
  "
Wcheck
--------------
_w_:wcheck mode        _f_:forward to next error
_l_:change language    _b_:backward to prev error     _q_:quit
                     _a_:actions
"
  ("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)
        (wcheck-parser-ispell-suggestions)))
;;
(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))
      (with-temp-buffer
        (insert word) (newline)
        (append-to-file (point-min) (point-max) file)
        (message "Added word \"%s\" to the %s dictionary"
                 word language)))))
;;
;;------------------------------------------------------------------------
izkon
  • 1,798
  • 10
  • 23
0

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.

Norman Ramsey
  • 1,113
  • 6
  • 13
0

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.

clemera
  • 3,401
  • 13
  • 40