Subject: Re: bug#18533: 24.4.50; flyspell-prog-mode and lisp interaction

From: Eli Zaretskii <[email-masked]>
Date: Sun, 27 Dec 2015 19:35:13 +0200

[Resending, as my original message didn't make it to the bug tracker.]

> From: Tom Tromey <[email-masked]>
> Date: Mon, 07 Dec 2015 23:37:42 -0500
> Cc: [email-masked]
> 
> Tom> I ran emacs -Q.
> Tom> Then in *scratch*, M-x flyspell-prog-mode
> Tom> Then typed `(igno<M-TAB>'
> 
> Tom> I expected this to complete to `(ignore', because point it not in a
> Tom> comment or string.
> Tom> However, flyspell instead changes this to `(Gino'.
> 
> FWIW I solved this to my own satisfaction by setting
> flyspell-use-meta-tab to nil.  This isn't maybe quite as nice as having
> the key binding automatically be aware of flyspell-prog-mode, but it's
> good enough for me.

Thanks, and sorry for letting this issue fall through the cracks for
so long.

Looking at the code, it sounds like the behavior you expected was
never intended to happen.  However, I found that a relatively simple
change can do what you want.  Does the patch below look reasonable?

--- lisp/textmodes/flyspell.el~4	2015-11-11 07:57:35.000000000 +0200
+++ lisp/textmodes/flyspell.el	2015-12-08 19:01:54.033105000 +0200
@@ -399,6 +399,9 @@
   (interactive)
   (setq flyspell-generic-check-word-predicate
         #'flyspell-generic-progmode-verify)
+  (setq-local flyspell--prev-meta-tab-binding
+              (or (local-key-binding "\M-\t" t)
+                  (global-key-binding "\M-\t" t)))
   (flyspell-mode 1)
   (run-hooks 'flyspell-prog-mode-hook))
 
@@ -1904,6 +1907,15 @@
   "Correct the current word.
 This command proposes various successive corrections for the current word."
   (interactive)
+  ;; If we are not in the construct where flyspell should be active,
+  ;; invoke the original binding of M-TAB, if that was recorded.
+  (if (and (local-variable-p 'flyspell--prev-meta-tab-binding)
+           (commandp flyspell--prev-meta-tab-binding t)
+           (fboundp flyspell-generic-check-word-predicate)
+           (not (funcall flyspell-generic-check-word-predicate))
+           (equal (where-is-internal 'flyspell-auto-correct-word nil t)
+                  [?\M-\t]))
+      (call-interactively flyspell--prev-meta-tab-binding)
   (let ((pos     (point))
 	(old-max (point-max)))
     ;; Use the correct dictionary.
@@ -2002,7 +2014,7 @@
 							       (point)
 							       old-max))))))))))
 	      (setq flyspell-auto-correct-pos (point))
-	      (ispell-pdict-save t)))))))
+                (ispell-pdict-save t))))))))
 
 ;;*---------------------------------------------------------------------*/
 ;;*    flyspell-auto-correct-previous-pos ...                           */