TL;DR flyspell-correct is package for correcting words with flyspell via custom interface. It’s available on GitHub and MELPA.

It’s very common to make mistakes while writing notes, comments or whatever. And a desire to have spell checking software is natural. In Emacs we usually use Flyspell for that purpose. It’s great piece of software, but sometimes it lacks better interface for correcting words. Especially since there are completion packages like popup.el, helm, ivy etc. Actually there are already available separate packages for correcting words via popup.el (wiki, flyspell-popup) and helm (helm-flyspell). Since recently I have switched from helm to ivy, I’ve found a lack of similar package for ivy, so I decided to write my own.

Since available packages are all the same, except the part that calls completion front-end, my goal was to provide generic package that allows to use any interface. With some predefined (popup, helm and ivy).

In order to use this package, just install it from MELPA, setup flyspell-correct-interface variable to one of predefined (flyspell-correct-ivy, flyspell-correct-helm or flyspell-correct-popup) or your own interface function. Then all you have to do is to call flyspell-correct-word-generic with cursor on misspelled word. You can also bind flyspell-correct-word-generic to any key binding.

;; set ivy as correcting interface
(setq flyspell-correct-interface 'flyspell-correct-ivy)
;; bind flyspell-correct-word-generic
(define-key flyspell-mode-map (kbd "C-;") 'flyspell-correct-word-generic)

Implementing custom interfaces

As it was already said, you can implement your own interface for correcting word. It has to be function that accepts list of candidates and misspelled word as it’s arguments. This function must return either replacement string or a tuple of (command, word) to be used by flyspell-do-correct. Available commands are save, session and buffer. Refer to flyspell documentation for more information.

Let’s check flyspell-correct-ivy for example of custom interface.

(defun flyspell-correct-ivy (candidates word)
  "Run `ivy-read' for the given CANDIDATES given by flyspell for the WORD.
Return a selected word to use as a replacement."
  (let* (result
         (action-default (lambda (x) (setq result x)))
         (action-save-word (lambda (_) (setq result (cons 'save word))))
         (action-accept-session (lambda (_) (setq result (cons 'session word))))
         (action-accept-buffer (lambda (_) (setq result (cons 'buffer word))))
         (action `(1
                   ("o" ,action-default "correct")
                   ("s" ,action-save-word "Save")
                   ("S" ,action-accept-session "Accept (session)")
                   ("b" ,action-accept-buffer "Accept (buffer)"))))
    (ivy-read (format "Suggestions for \"%s\" in dictionary \"%s\": "
                      word (or ispell-local-dictionary
              :action action
              :caller 'flyspell-correct-ivy)

As you see, it’s pretty straightforward. Just run ivy-read with candidates provided by flysepll for misspelled word. Default action just returns selected replacement word. While other actions return mentioned tuple of (command, word).

That’s all. Hope you’ll like this package.

P. S. And as always - contributions are warmly welcome.

Posted on May 9, 2016 by Boris Buliga

Source: flyspell-correct