flyspell-correct is a package for distraction-free words correction with
flyspell via selected 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 a 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. 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
I’ve found a lack of similar package for
ivy, so I decided to write my own.
But available packages are all the same, except the part that calls completion
front-end, so my goal was to provide a generic package allowing usage of any
interface. Either from the predefined set (
This is an introduction post, for more up-to-date documentation, please refer to README file.
In order to use this package, just install it from MELPA, setup
flyspell-correct-interface variable to one of predefined
flyspell-correct-dummy) or your own interface
function. Then all you have to do is to call
flyspell-correct-wrapper from any
point of the buffer. You can also bind
flyspell-correct-wrapper to any key
;; set ivy as correcting interface setq flyspell-correct-interface #'flyspell-correct-ivy) ( ;; bind flyspell-correct-wrapper "C-;") #'flyspell-correct-wrapper)(define-key flyspell-mode-map (kbd
Implementing custom interfaces
As it was already said, you can implement your own interface for correcting
words. It has to be a function that takes two arguments - candidates and
incorrect word. It has to return either replacement word or
command can be one of the following:
skip- meaning that no action is required for current incorrect
save- meaning that the
wordmust be saved in a dictionary;
session- meaning that the
wordmust be saved for the current session;
buffer- meaning that the
wordmust be saved for the current buffer.
flyspell-correct-ivy as an example of a custom interface.
defun flyspell-correct-ivy (candidates word) ("Run `ivy-read' for the given CANDIDATES. List of CANDIDATES is given by flyspell for the WORD. Return a selected word to use as a replacement or a tuple of (command, word) to be used by `flyspell-do-correct'." let* (result (lambda (x) (setq result x))) (action-default (lambda (_) (setq result (cons 'save word)))) (action-save-word (lambda (_) (setq result (cons 'session word)))) (action-accept-session (lambda (_) (setq result (cons 'buffer word)))) (action-accept-buffer (lambda (_) (setq result (cons 'skip word)))) (action-skip-word (1 (action `("o" ,action-default "correct") ("s" ,action-save-word "Save") ("S" ,action-accept-session "Accept (session)") ("b" ,action-accept-buffer "Accept (buffer)") ("k" ,action-skip-word "Skip")))) (format "Suggestions for \"%s\" in dictionary \"%s\": " (ivy-read (or ispell-local-dictionary word ( ispell-dictionary"Default")) candidates :action action :caller 'flyspell-correct-ivy) result))
As you see, it’s pretty straightforward. Just run
ivy-read with candidates
flyspell for the incorrect word. Default action just returns selected
replacement word. While other actions return mentioned tuple of
One of the most important parts of the
flyspell-correct package is the ability
to correct words that are far from the point. By default,
flyspell-correct-wrapper jumps to the first incorrect word before the point.
So you don’t have to move the point manually to correct a mistake made several
words or lines before.
Also, if you happen to have multiple mistakes before the point, you can use
flyspell-correct-wrapper in a so-called ‘rapid mode’. Just call it with a
universal argument (e.g.
C-u C-;) and you’ll get an option to correct all
mistakes one by one in a current direction. If you want to leave incorrect word
as is, just use
The direction of the spelling can be changed by calling
Last few words
Contributions are warmly welcome!