Monday, April 7, 2008

Emacs Tip #17: flyspell and flyspell-prog-mode

Being in front of the computer hasn't helped my spelling because it's so easy to let the computer catch and fix the spelling errors for me. Of course Emacs has spell checking (M-x spell-{buffer,region,string,word}), but what is really handy is spell-checking as you type.

Enter flyspell.

flyspell is a minor-mode, so enabling it only causes spell-checking in that buffer, so it's handy to add the hooks to turn it on for the modes you deem appropriate (mail messages, text files, etc.). But wait, you do most of your work programming, right? Just turn on flyspell-prog-mode, and only your comments and strings will be checked for spelling errors.

It has the standard installation - only the major entry point is the routine 'flyspell-mode where the filename is "flyspell.el", so you need to tell Emacs to look for that appropriately. Here's what I use to enable flyspell and turn it on for a couple of different modes.


(autoload 'flyspell-mode "flyspell" "On-the-fly spelling checker." t)
(add-hook 'message-mode-hook 'turn-on-flyspell)
(add-hook 'text-mode-hook 'turn-on-flyspell)
(add-hook 'c-mode-common-hook 'flyspell-prog-mode)
(add-hook 'tcl-mode-hook 'flyspell-prog-mode)
(defun turn-on-flyspell ()
"Force flyspell-mode on using a positive arg. For use in hooks."
(interactive)
(flyspell-mode 1))

8 comments:

Andrew Gwozdziewycz said...

I've been using flyspell mode for quite a while and love it. However, your tip made me discover the flyspell-prog-mode, which will come in much more handy for code. Thanks

awhan said...

i can't seem to enable flyspell-prog-mode for .cpp files. could you help me with the correct .emacs settings ?

BFW said...

@awhan Have you tried just doing M-x flyspell-prog-mode when in a C++ buffer? If that works, then you just need to find the right hook to add 'turn-on-flyspell to the right hook, which for C/C++ should be (add-hook 'c-mode-common-hook 'flyspell-prog-mode)

awhan said...

Yes I did try M-x flyspell-prog-mode and it works. The relevant content of my .emacs is as follows :

(autoload 'flyspell-mode "flyspell" "On-the-fly spelling checker." t)
(add-hook 'message-mode-hook 'turn-on-flyspell)
(add-hook 'text-mode-hook 'turn-on-flyspell)
(add-hook 'c-mode-common-hook 'flyspell-prog-mode)
(add-hook 'c++-mode-common-hook 'flyspell-prog-mode)
(add-hook 'emacs-lisp-mode-hook 'flyspell-prog-mode)
(add-hook 'c++-mode-hook 'turn-on-flyspell-prog-mode t)
(defun turn-on-flyspell ()
"Force flyspell-mode on using a positive argument. For use in hooks."
(interactive)
(flyspell-mode 1))

but I might have been misled into thinking that it is not working due to the following screenshot

http://picasaweb.google.com/lh/photo/HsjX8rzWHVNO9UlSazTXUw?authkey=Gv1sRgCKTY8KzXtLrb8gE&feat=directlink

which shows in red fstream, iostream and cmath.

I was hoping that flyspell understands that these are part of C++ Standard library.

Any ways thanks for the help.

BFW said...

@awhan You've got me stumped. It does indeed look like flyspell is checking all the words.

The last ideas I have are

1) check the value of flyspell-generic-check-word-predicate - in prog mode, it should be set to 'flyspell-generic-progmode-verify.

(that's the only difference between prog mode and normal)

2) if that doesn't solve it, then it's time to fire up the debugger and track things down...

Brad Howes said...

@BFW The issue is that C/C++ mode puts the contents of <> in the font-lock-string-face face, which is one of the faces in flyspell-prog-text-faces. Thus, flyspell checks it. One could create a separate face for #include files, based on font-lock-string-face so that it has the same display characteristics, but with a different symbol so that it is not found in flyspell-prog-text-faces.

Customizing the font-lock defaults for a programming mode used to be a pain. Not sure if that has changed.

Anonymous said...

@awhan

This should work:
(add-hook 'c-mode-common-hook 'flyspell-prog-mode)

דרור עתריה said...

Thanks! I didn't know this "flyspell-prog-mode". Now I do :)