Flyspell is a minor mode that enables *on-the-fly spell checking* in Emacs. It is hardly intrusive. Flyspell highlights incorrect words as soon as they are completed or as soon as the TextCursor hits a new word.

Flyspell is included as of Emacs 20.3; It also has a [[http://www-sop.inria.fr/mimosa/Manuel.Serrano/flyspell/flyspell.html Homepage]]

See also FlyspellWithoutColors.

See FlyspellXmlLang to switch to the appropriate language indicated in the XML document and see FlyspellBabel to switch language as indicated by LaTeX Babel commands.

== flyspell in other modes ==
Here is an example to enable it for text-mode, and disable it for log-edit-mode and change-log-mode.  These two are derived from text-mode, and thus enabling flyspell-mode for text-mode also enables it for these two.  An alternative solution would be the writing of a flyspell-mode-predicate such that symbols
are ignored by flyspell.

    (dolist (hook '(text-mode-hook))
      (add-hook hook (lambda () (flyspell-mode 1))))
    (dolist (hook '(change-log-mode-hook log-edit-mode-hook))
      (add-hook hook (lambda () (flyspell-mode -1))))

The idiom used above makes it very easy to enable and disable flyspell for
the various major-modes out there: Just add the relevant hook to the list
where the other hooks already are.

=== Enable flyspell for comments in source code ===
Programmers can use flyspell-prog-mode to enable spell checking only within comments of source code.

[new]
Flyspell comes with a mode to check comments and strings in programming modes. Just type M-x flyspell-prog-mode or add it to your mode hooks

  (add-hook 'c++-mode-hook
          (lambda ()
            (flyspell-prog-mode)
            ; ...
          ))

- [[ruediger]] -

=== All modes with autodetect ===

One may want to be able to enable Flyspell, and have it automatically decide on `flyspell-mode' or `flyspell-prog-mode', based on the type of buffer/mode in use.  Perhaps one even wants Flyspell on by default.  The following functions will achieve (most of) that.  Written using Emacs 27.1 on Debian 11.1 in 2021 October.

    (defun flyspell-on-for-buffer-type ()
      "Enable Flyspell appropriately for the major mode of the current buffer.  Uses `flyspell-prog-mode' for modes derived from `prog-mode', so only strings and comments get checked.  All other buffers get `flyspell-mode' to check all text.  If flyspell is already enabled, does nothing."
      (interactive)
      (if (not (symbol-value flyspell-mode)) ; if not already on
	(progn
	  (if (derived-mode-p 'prog-mode)
	    (progn
	      (message "Flyspell on (code)")
	      (flyspell-prog-mode))
	    ;; else
	    (progn
	      (message "Flyspell on (text)")
	      (flyspell-mode 1)))
	  ;; I tried putting (flyspell-buffer) here but it didn't seem to work
	  )))
    
    (defun flyspell-toggle ()
      "Turn Flyspell on if it is off, or off if it is on.  When turning on, it uses `flyspell-on-for-buffer-type' so code-vs-text is handled appropriately."
      (interactive)
      (if (symbol-value flyspell-mode)
	  (progn ; flyspell is on, turn it off
	    (message "Flyspell off")
	    (flyspell-mode -1))
	  ; else - flyspell is off, turn it on
	  (flyspell-on-for-buffer-type)))

One can then bind `flyspell-toggle' to a key, to have a way to quickly turn Flyspell on or off, as appropriate.  For example:

    (global-set-key (kbd "C-c f") 'flyspell-toggle )

To have Flyspell automatically turn on for some/all/most buffers, add `flyspell-on-for-buffer-type' to one or more ModeHooks, as appropriate.  `find-file-hook' happens every time a buffer associated with a file is created.  That will trigger for everything except buffers not associated with a file.

    (add-hook 'find-file-hook 'flyspell-on-for-buffer-type)

Unfortunately, there does not appear to be a good way to hook creation of *any* buffer.  However, adding `flyspell-on-for-buffer-type' to multiple hooks is reasonably harmless -- the first thing it does is check if Flyspell is already enabled, and does nothing if so.  So one can try painting with a broad brush:

    (add-hook 'after-change-major-mode-hook 'flyspell-on-for-buffer-type)

== Performance ==
[new]
I highly suggest setting `flyspell-issue-message-flag' to nil, as printing messages for every word (when checking the entire buffer) causes an enormous slowdown.  -- [[nschum]]

== Avoid false positives ==
[new] 
I recently started using flyspell and am enjoying its features. Is
there a way to disable flyspell for certain regexps? For instance, I
would like to disable flyspell when typing a url. Otherwise, when
entering a url such as
http://www.emacswiki.org/cgi-bin/emacs/FlySpell, www, emacswiki, cgi
and FlySpell are highlighted as errors. Any advice would be greatly
appreciated. -- MattLundin

[new]
There is only one way, using flyspell-generic-check-word-predicate which should be a function. In such a function you can use thing at point.

However it is a bit difficult to manage this as this variable may be
only one function. I have submitted a patch to Emacs devel to take
care of this.

[new]
Thanks for pointing me to the flyspell-generic-check-word-predicate
variable. -- MattLundin

[new]
I am interested in a working solution to ignore spellchecking URLs and email addresses. The answer at http://superuser.com/a/345461/40407 seems to be relevant to making a solution with flyspell-generic-check-word-predicate, though not specificly for URLs  and email addresses. MattLundin, did you come up with something?

== Change dictionaries ==
[new]
As I often need to switch between English and German I use this function:

      (defun fd-switch-dictionary()
      (interactive)
      (let* ((dic ispell-current-dictionary)
    	 (change (if (string= dic "deutsch8") "english" "deutsch8")))
        (ispell-change-dictionary change)
        (message "Dictionary switched from %s to %s" dic change)
        ))
    
      (global-set-key (kbd "<f8>")   'fd-switch-dictionary)
    

-- FlorianDiesch

[new]

[new]
I too cycle through different languages, but not all that is available in the system. I use the following code inside my .emacs.

    (let ((langs '("american" "francais" "brasileiro")))
      (setq lang-ring (make-ring (length langs)))
      (dolist (elem langs) (ring-insert lang-ring elem)))

    (defun cycle-ispell-languages ()
      (interactive)
      (let ((lang (ring-ref lang-ring -1)))
        (ring-insert lang-ring lang)
        (ispell-change-dictionary lang)))

    (global-set-key [f6] 'cycle-ispell-languages)

-- DiogoRamos

[new]

How can I ignore or add a word without using the popup menu?

Use flyspell-auto-correct-word.

This is not working for me.  With flyspell-auto-correct-word I can go
through all suggestions for correction, but I do not get an option to
insert the word into my dictionary.

[new]
== Success in adding new words into the personal dictionary ==

I used "M x ispell-region", and the words that ispell considered having incorrect spellings were highlighted.  The point moved to the first
"mis-spelled" word.  By typing "i", I inserted the word into my personal dictionary.  Later I found that the personal dictionary was stored in the file $HOME/.aspell.en.pws in pure text format.  Although the word was added when I used "ispell" instead of "flyspell", but once added, flyspell also recognized the word as having a correct spelling. :-) This information came from the web page: http://www.delorie.com/gnu/docs/emacs/emacs_109.html .  Thanks!

-- Namo Amitabha

[new]
You can also type "a" to make the word session-local and "A" to make it buffer-local (i.e. to add it to your !LocalWords list.)

-- [[Bernard_Hurley]]

[new]
I wanted a way to automagically insert a word into the user dictionary, and added this to my .emacs file:

<pre>
;;; --------------------------------------------------- adding words to flyspell

(eval-when-compile (require 'cl))

(defun append-aspell-word (new-word)
 (let ((header "personal_ws-1.1")
       (file-name (substitute-in-file-name "$HOME/.aspell.en.pws"))
       (read-words (lambda (file-name)
                    (let ((all-lines (with-temp-buffer
                                      (insert-file-contents file-name)
                                      (split-string (buffer-string) "\n" t))))
                     (if (null all-lines)
                       ""
                      (split-string (mapconcat 'identity (cdr all-lines) "\n")
                                    nil 
                                    t))))))
  (when (file-readable-p file-name)
   (let* ((cur-words (eval (list read-words file-name)))
          (all-words (delq header (cons new-word cur-words)))
          (words (delq nil (remove-duplicates all-words :test 'string=))))
    (with-temp-file file-name     
     (insert (concat header 
                     " en "
                     (number-to-string (length words))
                     "\n"
                     (mapconcat 'identity (sort words #'string<) "\n"))))))
  (unless (file-readable-p file-name)
   (with-temp-file file-name
    (insert (concat header " en 1\n" new-word "\n")))))
 (ispell-kill-ispell t) ; restart ispell
 (flyspell-mode)
 (flyspell-mode))

(defun append-aspell-current ()
 "Add current word to aspell dictionary"
 (interactive)
 (append-aspell-word (thing-at-point 'word)))
</pre>

-- Aaron Michaux

== Easy Spell Check: key bindings and function to make FlySpell/ispell/aspell easy to use w/ out a mouse ==

Place the below code in your .emacs

F8 will call [http://www.emacswiki.org/emacs/InteractiveSpell ispell] (or aspell, etc) for the word the cursor is on (or near).  You can also use the built-in key binding M-$.

Ctrl-Shift-F8 enables/disables FlySpell for your current buffer (highlights misspelled words as you type)

Ctrl-Meta-F8 runs FlySpell on your current buffer (highlights all misspelled words in the buffer)

Ctrl-F8 calls ispell for the FlySpell highlighted word prior to the cursor's position

Meta-F8 calls ispell for the FlySpell highlighted word after the cursor's position

<pre>
;; easy spell check
(global-set-key (kbd "<f8>") 'ispell-word)
(global-set-key (kbd "C-S-<f8>") 'flyspell-mode)
(global-set-key (kbd "C-M-<f8>") 'flyspell-buffer)
(global-set-key (kbd "C-<f8>") 'flyspell-check-previous-highlighted-word)
(defun flyspell-check-next-highlighted-word ()
  "Custom function to spell check next highlighted word"
  (interactive)
  (flyspell-goto-next-error)
  (ispell-word)
  )
(global-set-key (kbd "M-<f8>") 'flyspell-check-next-highlighted-word)
</pre>

[new]

How can I position the flyspell suggestions in a window that is below the current window? Currently, on Aquamacs, running leuven color theme, when the suggestions come up, the tabs do not disappear (they did when i wasn't using the color theme). The theme is really nice (in conjunction with org-mode) so I do not wish to get rid of that. How can i force the suggestion window to appear just above the modeline?

== Run flyspell with aspell instead of ispell ==
If you use flyspell with aspell instead of ispell you have to add :

<pre>
(setq ispell-list-command "--list")
</pre>

Because the "-l" option mean "--lang" in aspell and the "-l" option mean "--list" in ispell.
flyspell-buffer, and flyspell-region are affected by this problem.

== Run flyspell-buffer after change to dictionary ==
[new]

If I add a word during a flyspell session, it's still marked up as misspelled.  And flyspell-correct-previous-word tells me that it's spelling is correct.  How do I run flyspell-buffer on the buffer every time the dictionary is modified?

-kd

[new]

Found a working solution at https://www.reddit.com/r/emacs/comments/4oc7pg/spellcheck_flyspellmode_underlines_disappear_when/:

<pre>
(defun flyspell-buffer-after-pdict-save (&rest _)
  (flyspell-buffer))

(advice-add 'ispell-pdict-save :after #'flyspell-buffer-after-pdict-save)
</pre>

The above solution might trigger too often the ##flyspell-buffer## command. In order to avoid that, you can change the ##ispell-pdict-save## call by ##flyspell-mode-off##. Thanks to that, ##flyspell## will recheck the buffer when you save a word in your personal dictionary and not after correcting a word or even after dismissing the correction menu.

== Flyspell with subword-mode ==
[new]

When the subword mode is on, especially with cc-mode, the words are distinguished more skilfully, e.g., "GoodBadType" -> "Good", "Bad", and "Type". How do I set the flyspell to work in this context?

-Kiwon

[new]

Flyspell has no built-in support for subword-mode, however, it is possible to adapt Flyspell to be more competent when subword-mode is activated.  There are three primary changes that need to be made:

# Word boundary detection needs to updated for both Flyspell and ispell
# ##flyspell-small-region## needs to be updated to advance by subwords, not whole words
## ##flyspell-large-region## has similar issues which are more difficult to fix, though aspell offers a pseudo-solution
# ##flyspell-post-command-hook## needs to know to trigger after typing a subword boundary

Code addressing (1) is as follows:
<pre>
;; Like looking-at but with an offset
(defun my-looking-at (regexp &optional offset)
  (let ((pos (+ (or offset 0) (point))))
    (when (and (>= pos (point-min)) (< pos (point-max)))
      (string-match regexp (string (char-after pos))))))

;; Call the right forward function and move past otherchars
(defun my-forward (&optional backward)
  (let ((ispell-casechars (ispell-get-casechars))
        (ispell-otherchars (ispell-get-otherchars))
        (ispell-many-otherchars-p (ispell-get-many-otherchars-p))
        (offset (if backward -1 0))
        (dir (if backward -1 1))
        (continue t))
    (if subword-mode (subword-forward dir) (forward-word dir))
    (while (and continue
                (not (string= "" ispell-otherchars))
                (my-looking-at ispell-otherchars offset)
                (my-looking-at ispell-casechars (+ dir offset)))
      (if subword-mode (subword-forward dir) (forward-word dir))
      (setq continue ispell-many-otherchars-p))))
(defun my-backward () (my-forward t))

;; Properly find boundaries of words in CamelCase
(defun my-ispell-get-word (orig-fun &optional following extra-otherchars)
  (if (not subword-mode)
      (funcall orig-fun following extra-otherchars)
    (if following (my-forward) (if (not (eobp)) (forward-char)))
    (let* ((beg (progn (my-backward) (point-marker)))
           (end (progn (my-forward) (point-marker)))
           (word (buffer-substring-no-properties beg end)))
      (list word beg end))))
(advice-add #'ispell-get-word :around #'my-ispell-get-word)
(advice-add #'flyspell-get-word :around #'my-ispell-get-word)
</pre>
This makes use of ##subword-forward## and ##-backward## to identify word boundaries while being careful to respect spelling non-delimiters like ##'## when used as an apostrophe (expressed in ispell's ##otherchars##).  Optional argument `extra-otherchars' is ignored in the above, but can be incorporated similarly if desired.

Code addressing (2) is as follows:
<pre>
;; Simplify and use my-forward to handle CamelCase words
(defun my-flyspell-small-region (orig-fun beg end)
  ;; (if (not subword-mode)
  ;;     (funcall orig-fun beg end)
  (save-excursion
    (if (> beg end) (setq beg (prog1 end (setq end beg))))
    (if (< beg (point-min)) (setq beg (point-min)))
    (if (> end (point-max)) (setq end (point-max)))
    (goto-char beg)
    (while (< (point) end)
      (flyspell-word t)
      ;; (sit-for 0) ;; uncomment to enable animation
      (my-forward))))
(advice-add #'flyspell-small-region :around #'my-flyspell-small-region)
</pre>
(Note that this depends on ##my-forward## from (1).)  This removes the status messages and the cursor sweep animation, which become a bit jarring when used with (3) below.  (This should be fine for ''small'' regions, after all, unless you've disabled ##flyspell-large-region##.)  Note the use use of ##(flyspell-word t)## to check forward rather than backward: this permits simpler cursor movement and also avoids double-checking each word (as is done in the standard implementation!).

A pseudo-solution for ##flyspell-large-region## with aspell is as follows:
<pre>
;; Fake handling of CamelCase words in flyspell-large-region
(defun my-flyspell-large-region (orig-fun beg end)
  (let ((ispell-extra-args ispell-extra-args)
        (subword-mode subword-mode))
    (when (and subword-mode (string-match "aspell\\'" ispell-program-name))
      (push "--run-together" ispell-extra-args)
      (push "--run-together-limit=6" ispell-extra-args)
      (push "--run-together-min=2" ispell-extra-args)
      (setq subword-mode nil))
    (funcall orig-fun beg end)))
(advice-add #'flyspell-large-region :around #'my-flyspell-large-region)

...

;; Use aspell if installed
(when (executable-find "aspell")
  (setq ispell-program-name "aspell")
  (setq ispell-list-command "--list"))
</pre>
This exploits aspell's ##--run-together## family of options to accept CamelCase words, but it also ends up permitting missingspaces and other typos that form run-together words, like "theis".  aspell's default case sensitivity does at least prevent the flagrant disregard of word boundaries within CamelCase words.  (The choice of ##--run-together-limit=6## and ##-min=2## should serve most uses of CamelCase, which often include words as short as "is" but typically stick to brief phrases.)

In order to address (3), it is necessary to alter the logic Flyspell uses to decide when to trigger:
<pre>
;; Only check the previous word if no longer editing it
(defun my-flyspell-check-pre-word-p ()
  (and (eq flyspell-pre-buffer (current-buffer))
       (numberp flyspell-pre-point)
       (/= (save-excursion
             (goto-char (1- flyspell-pre-point))
             (my-forward)
             (point))
           (save-excursion
             (if (not (bobp)) (backward-char))
             (my-forward)
             (point)))))

;; Simplify and use flyspell-region in the post-command-hook
(defun my-flyspell-post-command-hook (orig-fun)
  (when flyspell-mode
    (with-local-quit
      (let ((command this-command)
            deactivate-mark)
        ;; Handle word at previous location
        (when (my-flyspell-check-pre-word-p)
          (save-excursion
            (goto-char (1- flyspell-pre-point))
            (flyspell-word)))
        ;; Handle word at current location
        (when (flyspell-check-word-p)
          (flyspell-word))
        ;; Handle all other recent changes
        (while (and (not (input-pending-p)) (consp flyspell-changes))
          (let* ((change (pop flyspell-changes))
                 (beg (car change))
                 (end (cdr change)))
            (flyspell-region beg end)))
        (setq flyspell-previous-command command)))))
(advice-add #'flyspell-post-command-hook :around #'my-flyspell-post-command-hook)
</pre>
(Also depends on ##my-forward## from (1).)  ##flyspell-post-command-hook## is replaced primarily to check the word at ##(1- flyspell-pre-point)## rather than directly at ##flyspell-pre-point## so subwords are checked as you type them.  The while-loop at the end now also unconditionally calls ##flyspell-region## rather than ##flyspell-word##, '''which renders flyspell extremely aggressive when altering large chunks of text.'''

I realize the above is a fairly extensive change, but I believe it's roughly the minimum alteration needed to add subword checking as you type.  All of the above is also compatible with disabling subword-mode, though doing so still leaves in some differences: notably, unconditionally calling ##flyspell-region## in ##flyspell-post-command-hook##.  Should the maintainers of Flyspell ever read this, I would ask that they check that the logic expressed in their various ##-p## functions to ensure they behave as intended.  In particular ##flypsell-check-changed-word-p##'s last line appears to be missing an ##and##, and as a result may be incapable of returning non-nil. ---rriegs

== Flyspell with popup.el ==
If you'd like to use Flyspell's menu selection in the terminal, or just prefer to use popup.el over the graphical menu, stick this somewhere in your load path:
<pre>
    (defun flyspell-emacs-popup-textual (event poss word)
      "A textual flyspell popup menu."
      (require 'popup)
      (let* ((corrects (if flyspell-sort-corrections
                           (sort (car (cdr (cdr poss))) 'string<)
                         (car (cdr (cdr poss)))))
             (cor-menu (if (consp corrects)
                           (mapcar (lambda (correct)
                                     (list correct correct))
                                   corrects)
                         '()))
             (affix (car (cdr (cdr (cdr poss)))))
             show-affix-info
             (base-menu  (let ((save (if (and (consp affix) show-affix-info)
                                         (list
                                          (list (concat "Save affix: " (car affix))
                                                'save)
                                          '("Accept (session)" session)
                                          '("Accept (buffer)" buffer))
                                       '(("Save word" save)
                                         ("Accept (session)" session)
                                         ("Accept (buffer)" buffer)))))
                           (if (consp cor-menu)
                               (append cor-menu (cons "" save))
                             save)))
             (menu (mapcar
                    (lambda (arg) (if (consp arg) (car arg) arg))
                    base-menu)))
        (cadr (assoc (popup-menu* menu :scroll-bar t) base-menu))))
</pre>
and put this in your init file:
<pre>
    (eval-after-load "flyspell"
      '(progn
         (fset 'flyspell-emacs-popup 'flyspell-emacs-popup-textual)))
</pre>
Now calling "flyspell-correct-word-before-point" or middle-clicking a word will create a textual popup. When working from the terminal, this will prevent the dreaded "This command requires pop-up dialogs" error.

== Automatically displaying a textual popup in a terminal while using the usual emacs menu in the GUI ==
[new]

If you run an emacs server with both terminal and GUI clients you may wish for the type of menu to be selected automatically depending on which client you are using.  Instead of redefining flyspell-emacs-popup it's better to advise it so that flyspell-emacs-popup-textual (defined above) or the original function can be called as necessary

First a small helper function to use as the advice:
<pre>
  (defun flyspell-emacs-popup-choose (org-fun event poss word)
    (if (window-system)
        (funcall org-fun event poss word)
      (flyspell-emacs-popup-textual event poss word)))
</pre>
Now put this in your init file:
<pre>
    (eval-after-load "flyspell"
      '(progn
          (advice-add 'flyspell-emacs-popup :around #'flyspell-emacs-popup-choose)))
</pre>

Note:  I have used the new syntax for advice.  If you don't have the latest emacs you may need to change this to the old syntax.
[[Bernard Hurley]]

== Skipping flyspell on specific region ==
This is useful for code block in org files, but any region with clear delimiters can be skipped

  (add-to-list 'ispell-skip-region-alist '("^#+BEGIN_SRC" . "^#+END_SRC"))

- [[chedi]] -

== Flyspell with Hunspell on buffer with Japanese ==

Lines (false positives) are shown under many Japanese phrases.  One
solution
(http://lists.gnu.org/archive/html/help-gnu-emacs/2018-02/msg00141.html)
is shown below. -- Tak Kunihiro

<pre>
(defvar ispell-regexp-ja "[一-龠ぁ-🈀ァ-𛀀ー・、。々]+"
  "Regular expression to match a Japanese word.
The expression can be [^\000-\377]+, [^!-~]+, or [一-龠ぁ-🈀ァ-𛀀ー・、。々]+")
;; (add-to-list 'ispell-skip-region-alist (list ispell-regexp-ja))
(defun flyspell-skip-ja (beg end info)
  "Tell flyspell to skip a Japanese word.
Call this on `flyspell-incorrect-hook'."
  (string-match ispell-regexp-ja (buffer-substring beg end)))
(add-hook 'flyspell-incorrect-hook 'flyspell-skip-ja)
</pre>

== Key binding to insert into personal dictionary ==
It may be useful to have a key binding that inserts a highlighted word -- nominally misspelled -- into one's personal dictionary.  It can be a little more convenient than navigating the full popup menu of Flyspell options.

    (global-set-key (kbd "C-c s") 'flyspell-learn-word-at-point)
    
    (defun flyspell-learn-word-at-point ()
      "Takes the highlighted word at point -- nominally a misspelling -- and inserts it into the personal/private dictionary, such that it is known and recognized as a valid word in the future."
      (interactive)
      (let ((current-location (point))
	    (word (flyspell-get-word)))
	(when (consp word)
	  (flyspell-do-correct
	    'save nil
	    (car word)
	    current-location
	    (cadr word)
	    (caddr word)
	    current-location))))

Code based on https://stackoverflow.com/a/22116480/6884780 posted 2014 March 01 by "user2053036", retrieved 2021 October.  Tested with Emacs 27.1 on Debian 11.1.

----
CategoryModes | CategorySpelling ==
