11

I was about to post the question but then I saw it on Stack Overflow while searching for auto-correct possibilities. The linked question has no answers, so I thought it'd have more luck on this site. Here's the text:

I wish there were a way so that when I mistype a word, flyspell could autocorrect it to the "most likely" correction. When I mistype a word and then hit OPTION-TAB to correct it, flyspell ALMOST ALWAYS picks the correct correction by default as the main suggestion.

However, I want flyspell to do this with every word I mistype, WITHOUT my having to hit OPTION-TAB. Just from hitting the SPACE bar and moving on to the next word.

Is this possible?

So basically something like auto-correct on mobile phones. Such a feature would be useful to have for modes like jabber and capture in org-mode


Edit:

I'd rather have this feature as a separate minor mode than overwriting the default fly-spell functionality. It could be activated in addition or instead of fly-spell when needed

Tymric
  • 762
  • 1
  • 6
  • 15
  • 1
    I am certain it is possible (and probably not difficult to hack), but I feel obliged to say that IMHO that would be a very bad idea. – mbork Oct 29 '14 at 12:31
  • 1
    @mbork It would be a bad idea to change how fly-spell works, but what's wrong with having an additional minor mode that can be activated/deactivated on demand? – Tymric Oct 29 '14 at 12:43
  • I'm constantly annoyed by a similar feature on my phone. I don't like machines pretending that they are smarter than me, especially that they aren't;-): they vocabulary is very limited, especially that I sometimes *want* to type non-words (like some proper nouns). – mbork Oct 29 '14 at 14:42
  • @mbork True, but it also has advantages, like not having to worry about typing every ``'``. I use a [German keyboard](http://blogoscoped.com/files/german-keyboard-layout.png), and my pinkies have to do the splits every time I reach for that key – Tymric Oct 29 '14 at 14:49
  • 1
    @mbork To solve the "non_words" issue, could we perhaps bind ``S-SPC`` to "leave-that-word-alone"? – Tymric Oct 29 '14 at 14:56
  • Well, that is basically `C-q SPC`, you don't really need a separate command (unless you're unhappy with such a keybinding). Still, I personally don't like the idea. – mbork Oct 29 '14 at 20:14

3 Answers3

6

Let me refer you to my post on this.


I've found that abbrevs are the best way to do correction on SPC, you only need to define the corrections that you want. For that, I take the following approach:

  1. Add the code below to your init file.
  2. Whever you type something wrong, hit C-x C-i and choose one of the corrections offered.
  3. That's it! The correction will be automatically replaced there, and will automatically be performed every time you make this mistake from now on.

Here's the code

(define-key ctl-x-map "\C-i" 'endless/ispell-word-then-abbrev)

(defun endless/ispell-word-then-abbrev (p)
  "Call `ispell-word'. Then create an abbrev for the correction made.
With prefix P, create local abbrev. Otherwise it will be global."
  (interactive "P")
  (let ((bef (downcase (or (thing-at-point 'word) ""))) aft)
    (call-interactively 'ispell-word)
    (setq aft (downcase (or (thing-at-point 'word) "")))
    (unless (string= aft bef)
      (message "\"%s\" now expands to \"%s\" %sally"
               bef aft (if p "loc" "glob"))
      (define-abbrev
        (if p local-abbrev-table global-abbrev-table)
        bef aft))))

(setq save-abbrevs t)
(setq-default abbrev-mode t)

Manually, adding the corrections might sound cumbersome, but it's really not. You're just hitting a couple of keys, and you'll notice a few corrections will get you a long way.

Besides, the alternative (letting ispell choose the correction for you every time the word doesn't exist) will get you wrong corrections more often than not. So it's best to define your own anyway. It even solves the problem of when you actually want to type non-words.

Malabarba
  • 22,878
  • 6
  • 78
  • 163
  • I tried adding a substitution for ``dont`` to ``don't`` using ``C-x C-i 1`` but it added the letter ``t`` instead (``"dont" now expands to "t" globally``). I don't think it handles apostrophes well. Is there a fix for that? – Tymric Oct 29 '14 at 16:12
  • @Timmy Is that in a programming mode? In text-mode that doesn't happen for me. – Malabarba Oct 30 '14 at 11:08
  • I tried it in a jabber conversation, but after your comment I tested it in text-mode and it worked globally. Thank you – Tymric Oct 30 '14 at 12:27
2

Here's a simple attempt:

(defun my-flyspell-correct-on-space ()
  (interactive)
  (when flyspell-mode
    (flyspell-auto-correct-word))
  (self-insert-command 1))
(local-set-key " " 'my-flyspell-correct-on-space)

It behaves strangely when you insert more than one space in a row, and sometimes it splits off part of the word being corrected. Thus this post is community wiki; feel free to improve it.

legoscia
  • 6,012
  • 29
  • 54
  • 6
    I'd rather leave the space key alone, and instead use `post-self-insert-hook` to track the insertion of spaces and act accordingly. That's safer and more efficient. –  Oct 29 '14 at 12:35
1

Late answer inspired by another question about autocorrect and @legoscia's answer. Here's a quick minor mode that will autocorrect on the fly, using flyspell. It is, in effect, "global" in that it advises self-insert-command, but only fires in buffers that have flyspell-mode turned on.

(defun flyspell-ac-word (&optional arg)
  "Autocorrect a word when entering a non-word character."
  (when flyspell-mode
    (unless (eq ?w (char-syntax (string-to-char (this-command-keys))))
      (when (or (bobp)
                (eq ?w (char-syntax (char-before))))
        (flyspell-auto-correct-word)))))

(define-minor-mode flyspell-autocorrect-mode
  "Toggle `flyspell-autocorrect-mode'.  Fires flyspell on a
just-completed word.  Only operates when `flyspell-mode' is on."
  :init-value nil
  :lighter (" AC")
  (if flyspell-autocorrect-mode
      (progn 
        (require 'flyspell)
        (advice-add #'self-insert-command :before #'flyspell-ac-word))
    (advice-remove #'self-insert-command #'flyspell-ac-word)))
Dan
  • 32,584
  • 6
  • 98
  • 168