Allow to invoke original M-TAB binding in 'flyspell-prog-mode'

* 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)
This commit is contained in:
Eli Zaretskii 2015-12-31 17:44:07 +02:00
parent bb83bb11f9
commit 6d11f6ed9a

View file

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