# flyspell, emacs and aspell seem to diverge

I'm using the following configuration for aspell in my .emacs file

(setq ispell-program-name "/opt/local/bin/aspell")
(setq ispell-list-command "list")


and my ~/.aspell.conf contains the following line

add-tex-command bibliographystyle p


trying this latex file:

\documentclass{article}
\begin{document}
\bibliographystyle{plainnat}
\end{document}


emacs flyspell mode shows me plainnat as an error.

When I invoke aspell from the command line with the following command

aspell --dont-tex-check-comments -c ~/test.tex


it shows no errors. Flyspell does not seem to use aspell or the aspell config. How can I change this in such a manner that I only have to maintain one config for my spell checking needs and not have an extra config for flyspell?

-
When I try your test case aspell --dont-tex-check-comments does show "plainnat" as a spelling error. This seems correct seeing that plainnat is not a TeX comment. To ignore plainnat properly the spell checker would need to be able to differentiate between e.g. \bibliographystyle and \emph and ignore the content of the former but not the latter. If it matters I am using International Ispell Version 3.1.20 (but really Aspell 0.60.7-20110707). –  N.N. Jun 28 '12 at 14:24
To clarify this a little more: aspell is able to ignore tex commands. This is what the "add-tex-command bibliographystyle p" line does. This line excludes the first parameter of bibliographystyle from the spellcheck. Which is does when I invoke aspell from the commandline but not during a flyspell run. –  Kungi Jul 3 '12 at 11:42

Flyspell uses a mode-specific function called flyspell-generic-check-word-predicate to identify areas to ignore when highlighting spelling errors. This is slightly more involved than normal customizations.

As I understand it, there are three steps. First, set the flyspell-mode-predicate property of LaTeX-mode to the name of your custom function. Second, define a function that will return t when point is on a word you want to ignore. Third, add a hook to LaTeX-mode to define flyspell-generic-check-word-predicate to use this new function whenever you enter LaTeX mode.

(The order doesn't really matter, so long as all three steps are done before you open a latex file.)

If you don't know elisp, that probably doesn't make much sense to you. Adding the following to your .emacs file and restarting Emacs should solve the problem. If you want to add additional regions to ignore, the part to play with is the (save-excursion ... ) form.

(put 'LaTeX-mode 'flyspell-mode-predicate 'auctex-mode-flyspell-verify)
(defun auctex-mode-flyspell-verify ()
"Function used for flyspell-generic-check-word-predicate' in auctex mode."
(save-excursion
(forward-word -2)
(not (looking-at "bibliographystyle{"))))

(lambda () (setq flyspell-generic-check-word-predicate
'auctex-mode-flyspell-verify)))

-
Why are you using the (forward-word -2) here? Where is the point exactly when this function gets invoced? –  Kungi Jul 25 '12 at 9:29
(forward-word -2) backs up to the beginning of the previous word. -1 backs up to the beginning of the current word. The point is to see if the previous word is bibliography style. If it is, don't flyspell the current word. Most of the work is done behind the scenes by flyspell. –  Tyler Jul 25 '12 at 11:16

This is more of a long comment than a real answer.

The behavior is even more confusing that what you describe. I used your file but added a misspelled word in a comment and a "fake" TeX command with a misspelled word as its argument

\documentclass{article}
\begin{document}
\bibliographystyle{plainnat}
\bdfg{rwt}
\end{document}
% qwrx


Behavior that I saw:

• Using aspell -c test.tex this gives an error for "plainnat" and "rwt", but not for "qwrx". I guess my aspell doesn't need the --dont-tex-check-comments switch.
• Using ispell-buffer in emacs gives an error only for "rwt".
• Using flyspell-buffer in emacs gives an error for "plainnat", "rwt" and "qwrx".
• Putting point on "qwrx" or "plainnat" in emacs, and then using either ispell-word or flyspell-word gives an error.
• Putting point on either "bibliographystyle" or "bdfg" in emacs, and then using ispell-word gives an error, but using flyspell-word gives no error.
• All of the above was verified running ispell-kill-ispell before running the commands, to ensure that you start with a fresh ispell process. But if you, e.g., spell-check the buffer with ispell-buffer, "(a)ccept" "rwt" as an OK word for this session, and then run flyspell-buffer, flyspell will no longer complain about "rwt"

I believe that what's going on is that neither ispell nor flyspell send the entire buffer as a unit to aspell and ask it to spellcheck it [1]. Instead, the two modes go through the file one word at a time, and send each individual word to aspell. While flyspell does eventually call the function ispell-word to make the actual call to aspell [2], the logic of which words to spellcheck is different in flyspell vs ispell. It appears that both contain logic relevant to TeX/LaTeX, but not the same logic.

So aspell never gets a chance to apply its custom rules regarding TeX commands and their arguments, because it doesn't realize that the word "plainnat" is part of a TeX command.

I was using emacs 24.3, AUCTeX (although I don't thnk that AUCTeX does anything that really changes this behavior), aspell 3.1.20. Cygwin.

[1] This is implicit in Tyler's answer, but I think it's worth pointing it out very explicitly, because emacs' behavior here doesn't make any sense until you understand this!

[2] This probably explains the behavior in my last bullet point.

-
This answer is also relevant: stackoverflow.com/a/4674349/274967 –  Dan Becker Feb 14 at 6:08

A simpler solution is to customize the variable flyspell-tex-command-regexp. The default value is

$$\(begin\|end$$[   ]*{\|$$cite[a-z*]*\|label\|ref\|eqref\|usepackage\|documentclass$$[     ]*$$$[^]]*$$$?{[^{}]*\)


Just append \|bibliographystyle (read "or bibliographystyle") as shown below:

$$\(begin\|end$$[   ]*{\|$$cite[a-z*]*\|label\|ref\|eqref\|usepackage\|documentclass\|bibliographystyle$$[  ]*$$$[^]]*$$$?{[^{}]*\)


You can replace bibliographystyle by other commands whose input you may want to ignore, e.g. newenvironment`.

-