]> code.delx.au - gnu-emacs/commitdiff
Allow to invoke original M-TAB binding in 'flyspell-prog-mode'
authorEli Zaretskii <eliz@gnu.org>
Thu, 31 Dec 2015 15:44:07 +0000 (17:44 +0200)
committerEli Zaretskii <eliz@gnu.org>
Thu, 31 Dec 2015 15:44:07 +0000 (17:44 +0200)
* lisp/textmodes/flyspell.el (flyspell-prog-mode): Record the
original M-TAB binding in a buffer-local variable.
(flyspell-auto-correct-word): Invoke the original binding of M-TAB
if that is recorded, when point is in a place where flyspell
should not be active (e.g., because the user turned on
'flyspell-prog-mode').  (Bug#18533)

lisp/textmodes/flyspell.el

index 6c4a731629c3063f1deba3eb1e7dee2ae37fe3c8..8d13aa1dd5b71a10cd2234379e4e74a85578c95e 100644 (file)
@@ -399,6 +399,9 @@ like <img alt=\"Some thing.\">."
   (interactive)
   (setq flyspell-generic-check-word-predicate
         #'flyspell-generic-progmode-verify)
   (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))
 
   (flyspell-mode 1)
   (run-hooks 'flyspell-prog-mode-hook))
 
@@ -1904,105 +1907,114 @@ before point that's highlighted as misspelled."
   "Correct the current word.
 This command proposes various successive corrections for the current word."
   (interactive)
   "Correct the current word.
 This command proposes various successive corrections for the current word."
   (interactive)
-  (let ((pos     (point))
-       (old-max (point-max)))
-    ;; Use the correct dictionary.
-    (flyspell-accept-buffer-local-defs)
-    (if (and (eq flyspell-auto-correct-pos pos)
-            (consp flyspell-auto-correct-region))
-       ;; We have already been using the function at the same location.
-       (let* ((start (car flyspell-auto-correct-region))
-              (len   (cdr flyspell-auto-correct-region)))
-         (flyspell-unhighlight-at start)
-         (delete-region start (+ start len))
-         (setq flyspell-auto-correct-ring (cdr flyspell-auto-correct-ring))
-         (let* ((word (car flyspell-auto-correct-ring))
-                (len  (length word)))
-           (rplacd flyspell-auto-correct-region len)
-           (goto-char start)
-           (if flyspell-abbrev-p
-               (if (flyspell-already-abbrevp (flyspell-abbrev-table)
-                                             flyspell-auto-correct-word)
-                   (flyspell-change-abbrev (flyspell-abbrev-table)
-                                           flyspell-auto-correct-word
-                                           word)
-                 (flyspell-define-abbrev flyspell-auto-correct-word word)))
-           (funcall flyspell-insert-function word)
-           (flyspell-word)
-           (flyspell-display-next-corrections flyspell-auto-correct-ring))
-         (flyspell-ajust-cursor-point pos (point) old-max)
-         (setq flyspell-auto-correct-pos (point)))
-      ;; Fetch the word to be checked.
-      (let ((word (flyspell-get-word)))
-       (if (consp word)
-           (let ((start (car (cdr word)))
-                 (end (car (cdr (cdr word))))
-                 (word (car word))
-                 poss ispell-filter)
-             (setq flyspell-auto-correct-word word)
-             ;; Now check spelling of word..
-             (ispell-send-string "%\n") ;Put in verbose mode.
-             (ispell-send-string (concat "^" word "\n"))
-              ;; Wait until ispell has processed word.
-              (while (progn
-                       (accept-process-output ispell-process)
-                       (not (string= "" (car ispell-filter)))))
-             ;; Remove leading empty element.
-             (setq ispell-filter (cdr ispell-filter))
-             ;; Ispell process should return something after word is sent.
-             ;; Tag word as valid (i.e., skip) otherwise.
-             (or ispell-filter
-                 (setq ispell-filter '(*)))
-             (if (consp ispell-filter)
-                 (setq poss (ispell-parse-output (car ispell-filter))))
-             (cond
-              ((or (eq poss t) (stringp poss))
-               ;; Don't correct word.
-               t)
-              ((null poss)
-               ;; Ispell error.
-               (error "Ispell: error in Ispell process"))
-              (t
-               ;; The word is incorrect, we have to propose a replacement.
-               (let ((replacements (if flyspell-sort-corrections
-                                       (sort (car (cdr (cdr poss))) 'string<)
-                                     (car (cdr (cdr poss))))))
-                 (setq flyspell-auto-correct-region nil)
-                 (if (consp replacements)
-                     (progn
-                       (let ((replace (car replacements)))
-                         (let ((new-word replace))
-                           (if (not (equal new-word (car poss)))
-                               (progn
-                                 ;; the save the current replacements
-                                 (setq flyspell-auto-correct-region
-                                       (cons start (length new-word)))
-                                 (let ((l replacements))
-                                   (while (consp (cdr l))
-                                     (setq l (cdr l)))
-                                   (rplacd l (cons (car poss) replacements)))
-                                 (setq flyspell-auto-correct-ring
-                                       replacements)
-                                 (flyspell-unhighlight-at start)
-                                 (delete-region start end)
-                                 (funcall flyspell-insert-function new-word)
-                                 (if flyspell-abbrev-p
-                                     (if (flyspell-already-abbrevp
-                                          (flyspell-abbrev-table) word)
-                                         (flyspell-change-abbrev
-                                          (flyspell-abbrev-table)
-                                          word
-                                          new-word)
-                                       (flyspell-define-abbrev word
-                                                               new-word)))
-                                 (flyspell-word)
-                                 (flyspell-display-next-corrections
-                                  (cons new-word flyspell-auto-correct-ring))
-                                 (flyspell-ajust-cursor-point pos
-                                                              (point)
-                                                              old-max))))))))))
-             (setq flyspell-auto-correct-pos (point))
-             (ispell-pdict-save t)))))))
+  ;; 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.
+      (flyspell-accept-buffer-local-defs)
+      (if (and (eq flyspell-auto-correct-pos pos)
+               (consp flyspell-auto-correct-region))
+          ;; We have already been using the function at the same location.
+          (let* ((start (car flyspell-auto-correct-region))
+                 (len   (cdr flyspell-auto-correct-region)))
+            (flyspell-unhighlight-at start)
+            (delete-region start (+ start len))
+            (setq flyspell-auto-correct-ring (cdr flyspell-auto-correct-ring))
+            (let* ((word (car flyspell-auto-correct-ring))
+                   (len  (length word)))
+              (rplacd flyspell-auto-correct-region len)
+              (goto-char start)
+              (if flyspell-abbrev-p
+                  (if (flyspell-already-abbrevp (flyspell-abbrev-table)
+                                                flyspell-auto-correct-word)
+                      (flyspell-change-abbrev (flyspell-abbrev-table)
+                                              flyspell-auto-correct-word
+                                              word)
+                    (flyspell-define-abbrev flyspell-auto-correct-word word)))
+              (funcall flyspell-insert-function word)
+              (flyspell-word)
+              (flyspell-display-next-corrections flyspell-auto-correct-ring))
+            (flyspell-ajust-cursor-point pos (point) old-max)
+            (setq flyspell-auto-correct-pos (point)))
+        ;; Fetch the word to be checked.
+        (let ((word (flyspell-get-word)))
+          (if (consp word)
+              (let ((start (car (cdr word)))
+                    (end (car (cdr (cdr word))))
+                    (word (car word))
+                    poss ispell-filter)
+                (setq flyspell-auto-correct-word word)
+                ;; Now check spelling of word..
+                (ispell-send-string "%\n") ;Put in verbose mode.
+                (ispell-send-string (concat "^" word "\n"))
+                ;; Wait until ispell has processed word.
+                (while (progn
+                         (accept-process-output ispell-process)
+                         (not (string= "" (car ispell-filter)))))
+                ;; Remove leading empty element.
+                (setq ispell-filter (cdr ispell-filter))
+                ;; Ispell process should return something after word is sent.
+                ;; Tag word as valid (i.e., skip) otherwise.
+                (or ispell-filter
+                    (setq ispell-filter '(*)))
+                (if (consp ispell-filter)
+                    (setq poss (ispell-parse-output (car ispell-filter))))
+                (cond
+                 ((or (eq poss t) (stringp poss))
+                  ;; Don't correct word.
+                  t)
+                 ((null poss)
+                  ;; Ispell error.
+                  (error "Ispell: error in Ispell process"))
+                 (t
+                  ;; The word is incorrect, we have to propose a replacement.
+                  (let ((replacements (if flyspell-sort-corrections
+                                          (sort (car (cdr (cdr poss))) 'string<)
+                                        (car (cdr (cdr poss))))))
+                    (setq flyspell-auto-correct-region nil)
+                    (if (consp replacements)
+                        (progn
+                          (let ((replace (car replacements)))
+                            (let ((new-word replace))
+                              (if (not (equal new-word (car poss)))
+                                  (progn
+                                    ;; the save the current replacements
+                                    (setq flyspell-auto-correct-region
+                                          (cons start (length new-word)))
+                                    (let ((l replacements))
+                                      (while (consp (cdr l))
+                                        (setq l (cdr l)))
+                                      (rplacd l (cons (car poss) replacements)))
+                                    (setq flyspell-auto-correct-ring
+                                          replacements)
+                                    (flyspell-unhighlight-at start)
+                                    (delete-region start end)
+                                    (funcall flyspell-insert-function new-word)
+                                    (if flyspell-abbrev-p
+                                        (if (flyspell-already-abbrevp
+                                             (flyspell-abbrev-table) word)
+                                            (flyspell-change-abbrev
+                                             (flyspell-abbrev-table)
+                                             word
+                                             new-word)
+                                          (flyspell-define-abbrev word
+                                                                  new-word)))
+                                    (flyspell-word)
+                                    (flyspell-display-next-corrections
+                                     (cons new-word flyspell-auto-correct-ring))
+                                    (flyspell-ajust-cursor-point pos
+                                                                 (point)
+                                                                 old-max))))))))))
+                (setq flyspell-auto-correct-pos (point))
+                (ispell-pdict-save t))))))))
 
 ;;*---------------------------------------------------------------------*/
 ;;*    flyspell-auto-correct-previous-pos ...                           */
 
 ;;*---------------------------------------------------------------------*/
 ;;*    flyspell-auto-correct-previous-pos ...                           */