flyspell-correct
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 helm
to ivy
, 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 (ivy
, helm
, popup
or dummy
) or any user-defined.
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-ivy
, flyspell-correct-helm
, flyspell-correct-popup
, flyspell-correct-ido
, 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 binding.
;; 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, word)
tuple, where command
can be one of the following:
skip
- meaning that no action is required for current incorrectword
;save
- meaning that theword
must be saved in a dictionary;session
- meaning that theword
must be saved for the current session;buffer
- meaning that theword
must be saved for the current buffer.
Let’s check 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 provided by flyspell
for the incorrect word. Default action just returns selected replacement word. While other actions return mentioned tuple of (command, word)
.
Distraction-free meaning
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 skip
command.
The direction of the spelling can be changed by calling flyspell-correct-wrapper
with C-u C-u
.
Screenshots
Ivy interface
Popup interface
Helm interface
Ido interface
Last few words
Contributions are warmly welcome!