aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard M. Stallman2005-05-29 14:29:34 +0000
committerRichard M. Stallman2005-05-29 14:29:34 +0000
commita8c453e62da101436b7bde3ff3a6096ea73edfea (patch)
treed006c3be74aa4f0350df2c4eaf34692d530987dd
parent1f1f4de2dac71b48495ba00425022f8d5f52e7bf (diff)
downloademacs-a8c453e62da101436b7bde3ff3a6096ea73edfea.tar.gz
emacs-a8c453e62da101436b7bde3ff3a6096ea73edfea.zip
(flyspell-version): Function deleted.
(flyspell-auto-correct-previous-hook): Doc fix. (flyspell-emacs, flyspell-use-local-map): Vars moved up. (flyspell-default-delayed-commands): add backward-delete-char-untabify. (flyspell-abbrev-p): Default to nil. (flyspell-use-global-abbrev-table-p): Doc fix. (flyspell-large-region): Allow nil as value. (flyspell-use-meta-tab, flyspell-auto-correct-binding): New variables. (mail-mode-flyspell-verify): More robust handling of `mail-header-separator'. More efficient signature detection. Allow for regexp metacharacters in message-header-separator. Adding `To' not to be checked in mail-mode-flyspell-verify. (flyspell-prog-mode): Run flyspell-prog-mode-hook. (flyspell-mouse-map, flyspell-mode-map): Bind C-. and C-, . Bind M-TAB only if flyspell-use-meta-tab. Bind flyspell-auto-correct-binding. (flyspell-mode-on): Bind flyspell-mouse-map and flyspell-mode-map. (flyspell-mode): Doc fix. (flyspell-accept-buffer-local-defs): Preserve current buffer. (flyspell-word-cache-result): New var, always local. (flyspell-check-pre-word-p): Doc fix. (flyspell-check-changed-word-p): Handle spc like newline. (flyspell-post-command-hook): Set flyspell-word-cache-result. (flyspell-word-search-backward, flyspell-word-search-forward): New functions. (flyspell-word): Return t if nothing to check. When parsing TeX code, check for after } or \. Use flyspell-word-search-backward to find previous word. Return nil if duplicated word. For word already checked, return same value as last time. Set flyspell-word-cache-result after checking. Don't clobber the return value. (flyspell-get-word): Major rewrite. (flyspell-external-point-words): New locals pword, pcount. Fix size used in progress message. Find the proper corresponding word in flyspell-large-region-buffer. (flyspell-region): Check for flyspell-large-region = nil. (flyspell-highlight-incorrect-region): Clean up overlays in region. (flyspell-auto-correct-word): Check that WORD is a cons. (flyspell-correct-word): Likewise. (flyspell-auto-correct-previous-word): Narrow down to what's on the screen, and recenter overlays at the end of the next word.
-rw-r--r--lisp/ChangeLog50
-rw-r--r--lisp/textmodes/flyspell.el778
2 files changed, 510 insertions, 318 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index e9b6f94a619..493435c96dd 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -8,6 +8,9 @@
8 8
92005-05-29 Richard M. Stallman <rms@gnu.org> 92005-05-29 Richard M. Stallman <rms@gnu.org>
10 10
11 * flyspell.el (flyspell-version): Function deleted.
12 (flyspell-auto-correct-previous-hook): Doc fix.
13
11 * jit-lock.el (jit-lock-function, jit-lock-after-change): 14 * jit-lock.el (jit-lock-function, jit-lock-after-change):
12 Do nothing if memory is full. 15 Do nothing if memory is full.
13 16
@@ -25,6 +28,53 @@
25 * progmodes/which-func.el (which-func-update-1): Turn the mode 28 * progmodes/which-func.el (which-func-update-1): Turn the mode
26 off in case of error by setting which-func-mode. 29 off in case of error by setting which-func-mode.
27 30
312005-05-29 Manuel Serrano <Manuel.Serrano@sophia.inria.fr>
32
33 * flyspell.el (flyspell-emacs, flyspell-use-local-map): Vars moved up.
34 (flyspell-default-delayed-commands): add backward-delete-char-untabify.
35 (flyspell-abbrev-p): Default to nil.
36 (flyspell-use-global-abbrev-table-p): Doc fix.
37 (flyspell-large-region): Allow nil as value.
38 (flyspell-use-meta-tab, flyspell-auto-correct-binding): New variables.
39
40 (mail-mode-flyspell-verify): More robust handling
41 of `mail-header-separator'. More efficient signature detection.
42 Allow for regexp metacharacters in message-header-separator.
43 Adding `To' not to be checked in mail-mode-flyspell-verify.
44
45 (flyspell-prog-mode): Run flyspell-prog-mode-hook.
46 (flyspell-mouse-map): Bind M-TAB only if flyspell-use-meta-tab.
47 Bind flyspell-auto-correct-binding.
48 Bind C-. and C-, .
49 (flyspell-mode-map): Likewise.
50 (flyspell-mode): Doc fix.
51 (flyspell-accept-buffer-local-defs): Preserve current buffer.
52 (flyspell-mode-on): Bind flyspell-mouse-map and flyspell-mode-map.
53 (flyspell-word-cache-result): New var, always local.
54 (flyspell-check-pre-word-p): Doc fix.
55 (flyspell-check-changed-word-p): Handle spc like newline.
56 (flyspell-post-command-hook): Set flyspell-word-cache-result.
57 (flyspell-word-search-backward, flyspell-word-search-forward):
58 New functions.
59 (flyspell-word): Return t if nothing to check.
60 When parsing TeX code, check for after } or \.
61 Use flyspell-word-search-backward to find previous word.
62 Return nil if duplicated word.
63 For word already checked, return same value as last time.
64 Set flyspell-word-cache-result after checking.
65 Don't clobber the return value.
66 (flyspell-get-word): Major rewrite.
67 (flyspell-external-point-words): New locals pword, pcount.
68 Fix size used in progress message.
69 Find the proper corresponding word in flyspell-large-region-buffer.
70 (flyspell-region): Check for flyspell-large-region = nil.
71 (flyspell-highlight-incorrect-region): Clean up overlays in region.
72 (flyspell-auto-correct-word): Check that WORD is a cons.
73 (flyspell-correct-word): Likewise.
74 (flyspell-auto-correct-previous-word):
75 Narrow down to what's on the screen, and recenter overlays
76 at the end of the next word.
77
282005-05-29 Daniel Pfeiffer <occitan@esperanto.org> 782005-05-29 Daniel Pfeiffer <occitan@esperanto.org>
29 79
30 * progmodes/make-mode.el (makefile-rule-action-regex) 80 * progmodes/make-mode.el (makefile-rule-action-regex)
diff --git a/lisp/textmodes/flyspell.el b/lisp/textmodes/flyspell.el
index dbe8b1cfbc6..3175b73c22a 100644
--- a/lisp/textmodes/flyspell.el
+++ b/lisp/textmodes/flyspell.el
@@ -1,6 +1,6 @@
1;;; flyspell.el --- on-the-fly spell checker 1;;; flyspell.el --- on-the-fly spell checker
2 2
3;; Copyright (C) 1998, 2000, 2001, 2002, 2004 Free Software Foundation, Inc. 3;; Copyright (C) 1998, 2000, 2003, 2004, 2005 Free Software Foundation, Inc.
4 4
5;; Author: Manuel Serrano <Manuel.Serrano@sophia.inria.fr> 5;; Author: Manuel Serrano <Manuel.Serrano@sophia.inria.fr>
6;; Maintainer: FSF 6;; Maintainer: FSF
@@ -56,6 +56,21 @@
56 :group 'processes) 56 :group 'processes)
57 57
58;*---------------------------------------------------------------------*/ 58;*---------------------------------------------------------------------*/
59;* Which emacs are we currently running */
60;*---------------------------------------------------------------------*/
61(defvar flyspell-emacs
62 (cond
63 ((string-match "XEmacs" emacs-version)
64 'xemacs)
65 (t
66 'emacs))
67 "The type of Emacs we are currently running.")
68
69(defvar flyspell-use-local-map
70 (or (eq flyspell-emacs 'xemacs)
71 (not (string< emacs-version "20"))))
72
73;*---------------------------------------------------------------------*/
59;* User configuration ... */ 74;* User configuration ... */
60;*---------------------------------------------------------------------*/ 75;*---------------------------------------------------------------------*/
61(defcustom flyspell-highlight-flag t 76(defcustom flyspell-highlight-flag t
@@ -109,7 +124,8 @@ is highlighted."
109 delete-backward-char 124 delete-backward-char
110 backward-or-forward-delete-char 125 backward-or-forward-delete-char
111 delete-char 126 delete-char
112 scrollbar-vertical-drag) 127 scrollbar-vertical-drag
128 backward-delete-char-untabify)
113 "The standard list of delayed commands for Flyspell. 129 "The standard list of delayed commands for Flyspell.
114See `flyspell-delayed-commands'." 130See `flyspell-delayed-commands'."
115 :group 'flyspell 131 :group 'flyspell
@@ -199,15 +215,15 @@ http://strw.leidenuniv.nl/~dominik/Tools"
199 :type '(repeat (string))) 215 :type '(repeat (string)))
200 216
201(defcustom flyspell-abbrev-p 217(defcustom flyspell-abbrev-p
202 t 218 nil
203 "*If true, add correction to abbreviation table." 219 "*If non-nil, add correction to abbreviation table."
204 :group 'flyspell 220 :group 'flyspell
205 :version "21.1" 221 :version "21.1"
206 :type 'boolean) 222 :type 'boolean)
207 223
208(defcustom flyspell-use-global-abbrev-table-p 224(defcustom flyspell-use-global-abbrev-table-p
209 nil 225 nil
210 "*If true, prefer global abbrev table to local abbrev table." 226 "*If non-nil, prefer global abbrev table to local abbrev table."
211 :group 'flyspell 227 :group 'flyspell
212 :version "21.1" 228 :version "21.1"
213 :type 'boolean) 229 :type 'boolean)
@@ -224,10 +240,12 @@ Set this to nil if you don't want a modeline indicator."
224If the region is smaller than this number of characters, 240If the region is smaller than this number of characters,
225`flyspell-region' checks the words sequentially using regular 241`flyspell-region' checks the words sequentially using regular
226flyspell methods. Else, if the region is large, a new Ispell process is 242flyspell methods. Else, if the region is large, a new Ispell process is
227spawned for speed." 243spawned for speed.
244
245If `flyspell-large-region' is nil, all regions are treated as small."
228 :group 'flyspell 246 :group 'flyspell
229 :version "21.1" 247 :version "21.1"
230 :type 'number) 248 :type '(choice number boolean))
231 249
232(defcustom flyspell-insert-function (function insert) 250(defcustom flyspell-insert-function (function insert)
233 "*Function for inserting word by flyspell upon correction." 251 "*Function for inserting word by flyspell upon correction."
@@ -244,6 +262,20 @@ spawned for speed."
244 :group 'flyspell 262 :group 'flyspell
245 :type '(choice string (const nil))) 263 :type '(choice string (const nil)))
246 264
265(defcustom flyspell-use-meta-tab t
266 "*Non-nil means that flyspell uses META-TAB to correct word."
267 :group 'flyspell
268 :type 'boolean)
269
270(defcustom flyspell-auto-correct-binding
271 (cond
272 ((eq flyspell-emacs 'xemacs)
273 [(control \;)])
274 (t
275 [?\C-\;]))
276 "The key binding for flyspell auto correction."
277 :group 'flyspell)
278
247;*---------------------------------------------------------------------*/ 279;*---------------------------------------------------------------------*/
248;* Mode specific options */ 280;* Mode specific options */
249;* ------------------------------------------------------------- */ 281;* ------------------------------------------------------------- */
@@ -267,17 +299,24 @@ property of the major mode name.")
267(put 'message-mode 'flyspell-mode-predicate 'mail-mode-flyspell-verify) 299(put 'message-mode 'flyspell-mode-predicate 'mail-mode-flyspell-verify)
268(defun mail-mode-flyspell-verify () 300(defun mail-mode-flyspell-verify ()
269 "This function is used for `flyspell-generic-check-word-p' in Mail mode." 301 "This function is used for `flyspell-generic-check-word-p' in Mail mode."
270 (let ((in-headers (save-excursion 302 (let ((header-end (save-excursion
271 ;; When mail-header-separator is "", 303 (goto-char (point-min))
272 ;; it is likely to be found in both directions. 304 (re-search-forward
273 (not (re-search-backward (concat "^" (regexp-quote mail-header-separator) "$") nil t)))) 305 (concat "^"
274 (in-signature (save-excursion 306 (regexp-quote mail-header-separator)
275 (re-search-backward message-signature-separator nil t)))) 307 "$")
276 (cond (in-headers 308 nil t)
309 (point)))
310 (signature-begin (save-excursion
311 (goto-char (point-max))
312 (re-search-backward message-signature-separator
313 nil t)
314 (point))))
315 (cond ((< (point) header-end)
277 (and (save-excursion (beginning-of-line) 316 (and (save-excursion (beginning-of-line)
278 (looking-at "^Subject:")) 317 (looking-at "^Subject:"))
279 (> (point) (match-end 0)))) 318 (> (point) (match-end 0))))
280 (in-signature 319 ((> (point) signature-begin)
281 nil) 320 nil)
282 (t 321 (t
283 (save-excursion 322 (save-excursion
@@ -351,7 +390,8 @@ property of the major mode name.")
351 "Turn on `flyspell-mode' for comments and strings." 390 "Turn on `flyspell-mode' for comments and strings."
352 (interactive) 391 (interactive)
353 (setq flyspell-generic-check-word-p 'flyspell-generic-progmode-verify) 392 (setq flyspell-generic-check-word-p 'flyspell-generic-progmode-verify)
354 (flyspell-mode 1)) 393 (flyspell-mode 1)
394 (run-hooks 'flyspell-prog-mode-hook))
355 395
356;*---------------------------------------------------------------------*/ 396;*---------------------------------------------------------------------*/
357;* Overlay compatibility */ 397;* Overlay compatibility */
@@ -366,21 +406,6 @@ property of the major mode name.")
366(autoload 'previous-overlay-change "overlay" "Overlay compatibility kit." t) 406(autoload 'previous-overlay-change "overlay" "Overlay compatibility kit." t)
367 407
368;*---------------------------------------------------------------------*/ 408;*---------------------------------------------------------------------*/
369;* Which emacs are we currently running */
370;*---------------------------------------------------------------------*/
371(defvar flyspell-emacs
372 (cond
373 ((string-match "XEmacs" emacs-version)
374 'xemacs)
375 (t
376 'emacs))
377 "The type of Emacs we are currently running.")
378
379(defvar flyspell-use-local-map
380 (or (eq flyspell-emacs 'xemacs)
381 (not (string< emacs-version "20"))))
382
383;*---------------------------------------------------------------------*/
384;* The minor mode declaration. */ 409;* The minor mode declaration. */
385;*---------------------------------------------------------------------*/ 410;*---------------------------------------------------------------------*/
386(eval-when-compile (defvar flyspell-local-mouse-map)) 411(eval-when-compile (defvar flyspell-local-mouse-map))
@@ -391,9 +416,13 @@ property of the major mode name.")
391 416
392(defvar flyspell-mouse-map 417(defvar flyspell-mouse-map
393 (let ((map (make-sparse-keymap))) 418 (let ((map (make-sparse-keymap)))
419 (if flyspell-use-meta-tab
420 (define-key map "\M-\t" #'flyspell-auto-correct-word))
394 (define-key map (if (featurep 'xemacs) [button2] [down-mouse-2]) 421 (define-key map (if (featurep 'xemacs) [button2] [down-mouse-2])
395 #'flyspell-correct-word) 422 #'flyspell-correct-word)
396 (define-key map "\M-\t" #'flyspell-auto-correct-word) 423 (define-key map flyspell-auto-correct-binding 'flyspell-auto-correct-previous-word)
424 (define-key map [(control \,)] 'flyspell-goto-next-error)
425 (define-key map [(control \.)] 'flyspell-auto-correct-word)
397 map)) 426 map))
398 427
399;;;###autoload 428;;;###autoload
@@ -404,7 +433,18 @@ property of the major mode name.")
404 (setq minor-mode-map-alist 433 (setq minor-mode-map-alist
405 (cons (cons 'flyspell-mode flyspell-mode-map) 434 (cons (cons 'flyspell-mode flyspell-mode-map)
406 minor-mode-map-alist))) 435 minor-mode-map-alist)))
407 (define-key flyspell-mode-map "\M-\t" 'flyspell-auto-correct-word)) 436 (if flyspell-use-meta-tab
437 (define-key flyspell-mode-map "\M-\t" 'flyspell-auto-correct-word))
438 (cond
439 ((eq flyspell-emacs 'xemacs)
440 (define-key flyspell-mode-map flyspell-auto-correct-binding 'flyspell-auto-correct-previous-word)
441 (define-key flyspell-mode-map [(control \,)] 'flyspell-goto-next-error)
442 (define-key flyspell-mode-map [(control \.)] 'flyspell-auto-correct-word))
443 (flyspell-use-local-map
444 (define-key flyspell-mode-map flyspell-auto-correct-binding 'flyspell-auto-correct-previous-word)
445 (define-key flyspell-mode-map [?\C-\,] 'flyspell-goto-next-error)
446 (define-key flyspell-mode-map [?\C-\.] 'flyspell-auto-correct-word))))
447
408 448
409;; the name of the overlay property that defines the keymap 449;; the name of the overlay property that defines the keymap
410(defvar flyspell-overlay-keymap-property-name 'keymap) 450(defvar flyspell-overlay-keymap-property-name 'keymap)
@@ -456,7 +496,8 @@ With a prefix argument ARG, turn Flyspell minor mode on iff ARG is positive.
456Bindings: 496Bindings:
457\\[ispell-word]: correct words (using Ispell). 497\\[ispell-word]: correct words (using Ispell).
458\\[flyspell-auto-correct-word]: automatically correct word. 498\\[flyspell-auto-correct-word]: automatically correct word.
459\\[flyspell-correct-word] (or mouse-2): popup correct words. 499\\[flyspell-auto-correct-previous-word]: automatically correct the last misspelled word.
500\\[flyspell-correct-word] (or down-mouse-2): popup correct words.
460 501
461Hooks: 502Hooks:
462This runs `flyspell-mode-hook' after flyspell is entered. 503This runs `flyspell-mode-hook' after flyspell is entered.
@@ -512,22 +553,19 @@ in your .emacs file.
512 (and (consp ws) (window-minibuffer-p (car ws))))) 553 (and (consp ws) (window-minibuffer-p (car ws)))))
513 554
514;*---------------------------------------------------------------------*/ 555;*---------------------------------------------------------------------*/
515;* flyspell-version ... */
516;*---------------------------------------------------------------------*/
517;;;###autoload
518(defun flyspell-version ()
519 "The flyspell version"
520 (interactive)
521 "1.6h")
522
523;*---------------------------------------------------------------------*/
524;* flyspell-accept-buffer-local-defs ... */ 556;* flyspell-accept-buffer-local-defs ... */
525;*---------------------------------------------------------------------*/ 557;*---------------------------------------------------------------------*/
526(defun flyspell-accept-buffer-local-defs () 558(defun flyspell-accept-buffer-local-defs ()
527 (ispell-accept-buffer-local-defs) 559 ;; strange problem. If buffer in current window has font-lock turned on,
560 ;; but SET-BUFFER was called to point to an invisible buffer, this ispell
561 ;; call will reset the buffer to the buffer in the current window. However,
562 ;; it only happens at startup (fix by Albert L. Ting).
563 (let ((buf (current-buffer)))
564 (ispell-accept-buffer-local-defs)
565 (set-buffer buf))
528 (if (not (and (eq flyspell-dash-dictionary ispell-dictionary) 566 (if (not (and (eq flyspell-dash-dictionary ispell-dictionary)
529 (eq flyspell-dash-local-dictionary ispell-local-dictionary))) 567 (eq flyspell-dash-local-dictionary ispell-local-dictionary)))
530 ;; the dictionary has changed 568 ;; The dictionary has changed
531 (progn 569 (progn
532 (setq flyspell-dash-dictionary ispell-dictionary) 570 (setq flyspell-dash-dictionary ispell-dictionary)
533 (setq flyspell-dash-local-dictionary ispell-local-dictionary) 571 (setq flyspell-dash-local-dictionary ispell-local-dictionary)
@@ -566,6 +604,22 @@ in your .emacs file.
566 (let ((mode-predicate (get major-mode 'flyspell-mode-predicate))) 604 (let ((mode-predicate (get major-mode 'flyspell-mode-predicate)))
567 (if mode-predicate 605 (if mode-predicate
568 (setq flyspell-generic-check-word-p mode-predicate))) 606 (setq flyspell-generic-check-word-p mode-predicate)))
607 ;; work around the fact that the `local-map' text-property replaces the
608 ;; buffer's local map rather than shadowing it.
609 (set (make-local-variable 'flyspell-mouse-map)
610 (let ((map (copy-keymap flyspell-mouse-map)))
611 (set-keymap-parent map (current-local-map))
612 (if (and (eq flyspell-emacs 'emacs)
613 (not (string< emacs-version "20")))
614 (define-key map '[tool-bar] nil))
615 map))
616 (set (make-local-variable 'flyspell-mode-map)
617 (let ((map (copy-keymap flyspell-mode-map)))
618 (set-keymap-parent map (current-local-map))
619 (if (and (eq flyspell-emacs 'emacs)
620 (not (string< emacs-version "20")))
621 (define-key map '[tool-bar] nil))
622 map))
569 ;; the welcome message 623 ;; the welcome message
570 (if (and flyspell-issue-message-flag 624 (if (and flyspell-issue-message-flag
571 flyspell-issue-welcome-flag 625 flyspell-issue-welcome-flag
@@ -624,9 +678,11 @@ not the very same deplacement command."
624(defvar flyspell-word-cache-start nil) 678(defvar flyspell-word-cache-start nil)
625(defvar flyspell-word-cache-end nil) 679(defvar flyspell-word-cache-end nil)
626(defvar flyspell-word-cache-word nil) 680(defvar flyspell-word-cache-word nil)
681(defvar flyspell-word-cache-result '_)
627(make-variable-buffer-local 'flyspell-word-cache-start) 682(make-variable-buffer-local 'flyspell-word-cache-start)
628(make-variable-buffer-local 'flyspell-word-cache-end) 683(make-variable-buffer-local 'flyspell-word-cache-end)
629(make-variable-buffer-local 'flyspell-word-cache-word) 684(make-variable-buffer-local 'flyspell-word-cache-word)
685(make-variable-buffer-local 'flyspell-word-cache-result)
630 686
631;*---------------------------------------------------------------------*/ 687;*---------------------------------------------------------------------*/
632;* The flyspell pre-hook, store the current position. In the */ 688;* The flyspell pre-hook, store the current position. In the */
@@ -678,7 +734,7 @@ not the very same deplacement command."
678;* flyspell-check-pre-word-p ... */ 734;* flyspell-check-pre-word-p ... */
679;*---------------------------------------------------------------------*/ 735;*---------------------------------------------------------------------*/
680(defun flyspell-check-pre-word-p () 736(defun flyspell-check-pre-word-p ()
681 "Return non-nil if we should to check the word before point. 737 "Return non-nil if we should check the word before point.
682More precisely, it applies to the word that was before point 738More precisely, it applies to the word that was before point
683before the current command." 739before the current command."
684 (cond 740 (cond
@@ -735,7 +791,7 @@ before the current command."
735The answer depends of several criteria. 791The answer depends of several criteria.
736Mostly we check word delimiters." 792Mostly we check word delimiters."
737 (cond 793 (cond
738 ((and (eq (char-after start) ?\n) (> stop start)) 794 ((and (memq (char-after start) '(?\n ? )) (> stop start))
739 t) 795 t)
740 ((not (numberp flyspell-pre-point)) 796 ((not (numberp flyspell-pre-point))
741 t) 797 t)
@@ -924,7 +980,9 @@ Mostly we check word delimiters."
924 ;; when a word is not checked because of a delayed command 980 ;; when a word is not checked because of a delayed command
925 ;; we do not disable the ispell cache. 981 ;; we do not disable the ispell cache.
926 (if (and (symbolp this-command) (get this-command 'flyspell-delayed)) 982 (if (and (symbolp this-command) (get this-command 'flyspell-delayed))
927 (setq flyspell-word-cache-end -1)))) 983 (progn
984 (setq flyspell-word-cache-end -1)
985 (setq flyspell-word-cache-result '_)))))
928 (while (consp flyspell-changes) 986 (while (consp flyspell-changes)
929 (let ((start (car (car flyspell-changes))) 987 (let ((start (car (car flyspell-changes)))
930 (stop (cdr (car flyspell-changes)))) 988 (stop (cdr (car flyspell-changes))))
@@ -949,6 +1007,34 @@ Mostly we check word delimiters."
949 (message (format "mispelling `%s' %S" word replacements))))) 1007 (message (format "mispelling `%s' %S" word replacements)))))
950 1008
951;*---------------------------------------------------------------------*/ 1009;*---------------------------------------------------------------------*/
1010;* flyspell-word-search-backward ... */
1011;*---------------------------------------------------------------------*/
1012(defun flyspell-word-search-backward (word bound)
1013 (save-excursion
1014 (let ((r '())
1015 p)
1016 (while (and (not r) (setq p (search-backward word bound t)))
1017 (let ((lw (flyspell-get-word '())))
1018 (if (and (consp lw) (string-equal (car lw) word))
1019 (setq r p)
1020 (goto-char p))))
1021 r)))
1022
1023;*---------------------------------------------------------------------*/
1024;* flyspell-word-search-forward ... */
1025;*---------------------------------------------------------------------*/
1026(defun flyspell-word-search-forward (word bound)
1027 (save-excursion
1028 (let ((r '())
1029 p)
1030 (while (and (not r) (setq p (search-forward word bound t)))
1031 (let ((lw (flyspell-get-word '())))
1032 (if (and (consp lw) (string-equal (car lw) word))
1033 (setq r p)
1034 (goto-char (1+ p)))))
1035 r)))
1036
1037;*---------------------------------------------------------------------*/
952;* flyspell-word ... */ 1038;* flyspell-word ... */
953;*---------------------------------------------------------------------*/ 1039;*---------------------------------------------------------------------*/
954(defun flyspell-word (&optional following) 1040(defun flyspell-word (&optional following)
@@ -963,7 +1049,7 @@ Mostly we check word delimiters."
963 (if (or (eq flyspell-word nil) 1049 (if (or (eq flyspell-word nil)
964 (and (fboundp flyspell-generic-check-word-p) 1050 (and (fboundp flyspell-generic-check-word-p)
965 (not (funcall flyspell-generic-check-word-p)))) 1051 (not (funcall flyspell-generic-check-word-p))))
966 '() 1052 t
967 (progn 1053 (progn
968 ;; destructure return flyspell-word info list. 1054 ;; destructure return flyspell-word info list.
969 (setq start (car (cdr flyspell-word)) 1055 (setq start (car (cdr flyspell-word))
@@ -972,21 +1058,24 @@ Mostly we check word delimiters."
972 ;; before checking in the directory, we check for doublons. 1058 ;; before checking in the directory, we check for doublons.
973 (cond 1059 (cond
974 ((and (or (not (eq ispell-parser 'tex)) 1060 ((and (or (not (eq ispell-parser 'tex))
975 (not (eq (char-after start) ?\\))) 1061 (and (> start (point-min))
1062 (not (eq (char-after (1- start)) ?}))
1063 (not (eq (char-after (1- start)) ?\\))))
976 flyspell-mark-duplications-flag 1064 flyspell-mark-duplications-flag
977 (save-excursion 1065 (save-excursion
978 (goto-char start) 1066 (goto-char (1- start))
979 (word-search-backward word 1067 (let ((p (flyspell-word-search-backward
980 (- start 1068 word
981 (+ 1 (- end start))) 1069 (- start (1+ (- end start))))))
982 t))) 1070 (and p (/= p (1- start))))))
983 ;; yes, this is a doublon 1071 ;; yes, this is a doublon
984 (flyspell-highlight-incorrect-region start end 'doublon)) 1072 (flyspell-highlight-incorrect-region start end 'doublon)
1073 nil)
985 ((and (eq flyspell-word-cache-start start) 1074 ((and (eq flyspell-word-cache-start start)
986 (eq flyspell-word-cache-end end) 1075 (eq flyspell-word-cache-end end)
987 (string-equal flyspell-word-cache-word word)) 1076 (string-equal flyspell-word-cache-word word))
988 ;; this word had been already checked, we skip 1077 ;; this word had been already checked, we skip
989 nil) 1078 flyspell-word-cache-result)
990 ((and (eq ispell-parser 'tex) 1079 ((and (eq ispell-parser 'tex)
991 (flyspell-tex-command-p flyspell-word)) 1080 (flyspell-tex-command-p flyspell-word))
992 ;; this is a correct word (because a tex command) 1081 ;; this is a correct word (because a tex command)
@@ -1016,59 +1105,68 @@ Mostly we check word delimiters."
1016 (setq ispell-filter (cdr ispell-filter)) 1105 (setq ispell-filter (cdr ispell-filter))
1017 (if (consp ispell-filter) 1106 (if (consp ispell-filter)
1018 (setq poss (ispell-parse-output (car ispell-filter)))) 1107 (setq poss (ispell-parse-output (car ispell-filter))))
1019 (cond ((eq poss t) 1108 (let ((res (cond ((eq poss t)
1020 ;; correct 1109 ;; correct
1021 (flyspell-unhighlight-at start) 1110 (setq flyspell-word-cache-result t)
1022 (if (> end start) 1111 (flyspell-unhighlight-at start)
1023 (flyspell-unhighlight-at (- end 1))) 1112 (if (> end start)
1024 t) 1113 (flyspell-unhighlight-at (- end 1)))
1025 ((and (stringp poss) flyspell-highlight-flag) 1114 t)
1026 ;; correct 1115 ((and (stringp poss) flyspell-highlight-flag)
1027 (flyspell-unhighlight-at start) 1116 ;; correct
1028 (if (> end start) 1117 (setq flyspell-word-cache-result t)
1029 (flyspell-unhighlight-at (- end 1))) 1118 (flyspell-unhighlight-at start)
1030 t) 1119 (if (> end start)
1031 ((null poss) 1120 (flyspell-unhighlight-at (- end 1)))
1032 (flyspell-unhighlight-at start) 1121 t)
1033 (if (> end start) 1122 ((null poss)
1034 (flyspell-unhighlight-at (- end 1)))) 1123 (setq flyspell-word-cache-result t)
1035 ((or (and (< flyspell-duplicate-distance 0) 1124 (flyspell-unhighlight-at start)
1036 (or (save-excursion 1125 (if (> end start)
1037 (goto-char start) 1126 (flyspell-unhighlight-at (- end 1)))
1038 (word-search-backward word 1127 t)
1039 (point-min) 1128 ((or (and (< flyspell-duplicate-distance 0)
1040 t)) 1129 (or (save-excursion
1041 (save-excursion 1130 (goto-char start)
1042 (goto-char end) 1131 (flyspell-word-search-backward
1043 (word-search-forward word 1132 word
1044 (point-max) 1133 (point-min)))
1045 t)))) 1134 (save-excursion
1046 (and (> flyspell-duplicate-distance 0) 1135 (goto-char end)
1047 (or (save-excursion 1136 (flyspell-word-search-forward
1048 (goto-char start) 1137 word
1049 (word-search-backward 1138 (point-max)))))
1050 word 1139 (and (> flyspell-duplicate-distance 0)
1051 (- start 1140 (or (save-excursion
1052 flyspell-duplicate-distance) 1141 (goto-char start)
1053 t)) 1142 (flyspell-word-search-backward
1054 (save-excursion 1143 word
1055 (goto-char end) 1144 (- start
1056 (word-search-forward 1145 flyspell-duplicate-distance)))
1057 word 1146 (save-excursion
1058 (+ end 1147 (goto-char end)
1059 flyspell-duplicate-distance) 1148 (flyspell-word-search-forward
1060 t))))) 1149 word
1061 (if flyspell-highlight-flag 1150 (+ end
1062 (flyspell-highlight-duplicate-region start end poss) 1151 flyspell-duplicate-distance))))))
1063 (message (format "duplicate `%s'" word)))) 1152 (setq flyspell-word-cache-result nil)
1064 (t 1153 (if flyspell-highlight-flag
1065 ;; incorrect highlight the location 1154 (flyspell-highlight-duplicate-region
1066 (if flyspell-highlight-flag 1155 start end poss)
1067 (flyspell-highlight-incorrect-region start end poss) 1156 (message (format "duplicate `%s'" word)))
1068 (flyspell-notify-misspell start end word poss)))) 1157 nil)
1069 ;; return to original location 1158 (t
1070 (goto-char cursor-location) 1159 (setq flyspell-word-cache-result nil)
1071 (if ispell-quit (setq ispell-quit nil))))))))) 1160 ;; incorrect highlight the location
1161 (if flyspell-highlight-flag
1162 (flyspell-highlight-incorrect-region
1163 start end poss)
1164 (flyspell-notify-misspell start end word poss))
1165 nil))))
1166 ;; return to original location
1167 (goto-char cursor-location)
1168 (if ispell-quit (setq ispell-quit nil))
1169 res))))))))
1072 1170
1073;*---------------------------------------------------------------------*/ 1171;*---------------------------------------------------------------------*/
1074;* flyspell-tex-math-initialized ... */ 1172;* flyspell-tex-math-initialized ... */
@@ -1175,30 +1273,31 @@ this function changes the last char of the `ispell-casechars' string."
1175;*---------------------------------------------------------------------*/ 1273;*---------------------------------------------------------------------*/
1176;* flyspell-get-word ... */ 1274;* flyspell-get-word ... */
1177;*---------------------------------------------------------------------*/ 1275;*---------------------------------------------------------------------*/
1178(defun flyspell-get-word (following) 1276(defun flyspell-get-word (following &optional extra-otherchars)
1179 "Return the word for spell-checking according to Ispell syntax. 1277 "Return the word for spell-checking according to Ispell syntax.
1180If argument FOLLOWING is non-nil or if `ispell-following-word' 1278If optional argument FOLLOWING is non-nil or if `flyspell-following-word'
1181is non-nil when called interactively, then the following word 1279is non-nil when called interactively, then the following word
1182\(rather than preceding\) is checked when the cursor is not over a word. 1280\(rather than preceding\) is checked when the cursor is not over a word.
1183Optional second argument contains other chars that can be included in word 1281Optional second argument contains otherchars that can be included in word
1184many times. 1282many times.
1185 1283
1186Word syntax described by `ispell-dictionary-alist' (which see)." 1284Word syntax described by `flyspell-dictionary-alist' (which see)."
1187 (let* ((flyspell-casechars (flyspell-get-casechars)) 1285 (let* ((flyspell-casechars (flyspell-get-casechars))
1188 (flyspell-not-casechars (flyspell-get-not-casechars)) 1286 (flyspell-not-casechars (flyspell-get-not-casechars))
1189 (ispell-otherchars (ispell-get-otherchars)) 1287 (ispell-otherchars (ispell-get-otherchars))
1190 (ispell-many-otherchars-p (ispell-get-many-otherchars-p)) 1288 (ispell-many-otherchars-p (ispell-get-many-otherchars-p))
1191 (word-regexp (if (string< "" ispell-otherchars) 1289 (word-regexp (concat flyspell-casechars
1192 (concat flyspell-casechars 1290 "+\\("
1193 "+\\(" 1291 (if (not (string= "" ispell-otherchars))
1194 ispell-otherchars 1292 (concat ispell-otherchars "?"))
1195 "?" 1293 (if extra-otherchars
1196 flyspell-casechars 1294 (concat extra-otherchars "?"))
1197 "+\\)" 1295 flyspell-casechars
1198 (if ispell-many-otherchars-p 1296 "+\\)"
1199 "*" "?")) 1297 (if (or ispell-many-otherchars-p
1200 (concat flyspell-casechars "+"))) 1298 extra-otherchars)
1201 did-it-once 1299 "*" "?")))
1300 did-it-once prevpt
1202 start end word) 1301 start end word)
1203 ;; find the word 1302 ;; find the word
1204 (if (not (looking-at flyspell-casechars)) 1303 (if (not (looking-at flyspell-casechars))
@@ -1207,21 +1306,26 @@ Word syntax described by `ispell-dictionary-alist' (which see)."
1207 (re-search-backward flyspell-casechars (point-min) t))) 1306 (re-search-backward flyspell-casechars (point-min) t)))
1208 ;; move to front of word 1307 ;; move to front of word
1209 (re-search-backward flyspell-not-casechars (point-min) 'start) 1308 (re-search-backward flyspell-not-casechars (point-min) 'start)
1210 (let ((pos nil)) 1309 (while (and (or (and (not (string= "" ispell-otherchars))
1211 (if (string< "" ispell-otherchars) 1310 (looking-at ispell-otherchars))
1212 (while (and (looking-at ispell-otherchars) 1311 (and extra-otherchars (looking-at extra-otherchars)))
1213 (not (bobp)) 1312 (not (bobp))
1214 (or (not did-it-once) 1313 (or (not did-it-once)
1215 ispell-many-otherchars-p) 1314 ispell-many-otherchars-p)
1216 (not (eq pos (point)))) 1315 (not (eq prevpt (point))))
1217 (setq pos (point)) 1316 (if (and extra-otherchars (looking-at extra-otherchars))
1218 (setq did-it-once t) 1317 (progn
1219 (backward-char 1) 1318 (backward-char 1)
1220 (if (looking-at flyspell-casechars) 1319 (if (looking-at flyspell-casechars)
1221 (re-search-backward flyspell-not-casechars (point-min) 'move) 1320 (re-search-backward flyspell-not-casechars (point-min) 'move)))
1222 (backward-char -1))))) 1321 (setq did-it-once t
1322 prevpt (point))
1323 (backward-char 1)
1324 (if (looking-at flyspell-casechars)
1325 (re-search-backward flyspell-not-casechars (point-min) 'move)
1326 (backward-char -1))))
1223 ;; Now mark the word and save to string. 1327 ;; Now mark the word and save to string.
1224 (if (eq (re-search-forward word-regexp (point-max) t) nil) 1328 (if (not (re-search-forward word-regexp (point-max) t))
1225 nil 1329 nil
1226 (progn 1330 (progn
1227 (setq start (match-beginning 0) 1331 (setq start (match-beginning 0)
@@ -1280,25 +1384,37 @@ Word syntax described by `ispell-dictionary-alist' (which see)."
1280 (set-buffer buffer) 1384 (set-buffer buffer)
1281 (goto-char (point-min)) 1385 (goto-char (point-min))
1282 (let ((size (- flyspell-large-region-end flyspell-large-region-beg)) 1386 (let ((size (- flyspell-large-region-end flyspell-large-region-beg))
1283 (start flyspell-large-region-beg)) 1387 (start flyspell-large-region-beg)
1388 (pword "")
1389 (pcount 1))
1284 ;; now we are done with ispell, we have to find the word in 1390 ;; now we are done with ispell, we have to find the word in
1285 ;; the initial buffer 1391 ;; the initial buffer
1286 (while (< (point) (- (point-max) 1)) 1392 (while (< (point) (- (point-max) 1))
1287 ;; we have to fetch the incorrect word 1393 ;; we have to fetch the incorrect word
1288 (if (re-search-forward "\\([^\n]+\\)\n" (point-max) t) 1394 (if (re-search-forward "\\([^\n]+\\)\n" (point-max) t)
1289 (let ((word (match-string 1))) 1395 (let ((word (match-string 1)))
1396 (if (string= word pword)
1397 (setq pcount (1+ pcount))
1398 (progn
1399 (setq pword word)
1400 (setq pcount 1)))
1290 (goto-char (match-end 0)) 1401 (goto-char (match-end 0))
1291 (set-buffer flyspell-large-region-buffer)
1292 (goto-char flyspell-large-region-beg)
1293 (if flyspell-issue-message-flag 1402 (if flyspell-issue-message-flag
1294 (message "Spell Checking...%d%% [%s]" 1403 (message "Spell Checking...%d%% [%s]"
1295 (* 100 (/ (float (- (point) start)) size)) 1404 (* 100 (/ (float (point)) (point-max)))
1296 word)) 1405 word))
1297 (if (search-forward word flyspell-large-region-end t) 1406 (set-buffer flyspell-large-region-buffer)
1407 (goto-char flyspell-large-region-beg)
1408 (let ((keep t)
1409 (n 0))
1410 (while (and (or (< n pcount) keep)
1411 (search-forward word flyspell-large-region-end t))
1298 (progn 1412 (progn
1299 (setq flyspell-large-region-beg (point))
1300 (goto-char (- (point) 1)) 1413 (goto-char (- (point) 1))
1301 (flyspell-word))) 1414 (setq n (1+ n))
1415 (setq keep (flyspell-word))))
1416 (if (= n pcount)
1417 (setq flyspell-large-region-beg (point))))
1302 (set-buffer buffer)) 1418 (set-buffer buffer))
1303 (goto-char (point-max))))) 1419 (goto-char (point-max)))))
1304 ;; we are done 1420 ;; we are done
@@ -1370,7 +1486,7 @@ Word syntax described by `ispell-dictionary-alist' (which see)."
1370 (let ((old beg)) 1486 (let ((old beg))
1371 (setq beg end) 1487 (setq beg end)
1372 (setq end old))) 1488 (setq end old)))
1373 (if (> (- end beg) flyspell-large-region) 1489 (if (and flyspell-large-region (> (- end beg) flyspell-large-region))
1374 (flyspell-large-region beg end) 1490 (flyspell-large-region beg end)
1375 (flyspell-small-region beg end))))) 1491 (flyspell-small-region beg end)))))
1376 1492
@@ -1517,15 +1633,23 @@ for the overlay."
1517 (if (or flyspell-highlight-properties 1633 (if (or flyspell-highlight-properties
1518 (not (flyspell-properties-at-p beg))) 1634 (not (flyspell-properties-at-p beg)))
1519 (progn 1635 (progn
1636 ;; we cleanup all the overlay that are in the region, not
1637 ;; beginning at the word start position
1638 (if (< (1+ beg) end)
1639 (let ((os (overlays-in (1+ beg) end)))
1640 (while (consp os)
1641 (if (flyspell-overlay-p (car os))
1642 (delete-overlay (car os)))
1643 (setq os (cdr os)))))
1520 ;; we cleanup current overlay at the same position 1644 ;; we cleanup current overlay at the same position
1521 (if (and (not flyspell-persistent-highlight) 1645 (if (and (not flyspell-persistent-highlight)
1522 (overlayp flyspell-overlay)) 1646 (overlayp flyspell-overlay))
1523 (delete-overlay flyspell-overlay) 1647 (delete-overlay flyspell-overlay)
1524 (let ((overlays (overlays-at beg))) 1648 (let ((os (overlays-at beg)))
1525 (while (consp overlays) 1649 (while (consp os)
1526 (if (flyspell-overlay-p (car overlays)) 1650 (if (flyspell-overlay-p (car os))
1527 (delete-overlay (car overlays))) 1651 (delete-overlay (car os)))
1528 (setq overlays (cdr overlays))))) 1652 (setq os (cdr os)))))
1529 ;; now we can use a new overlay 1653 ;; now we can use a new overlay
1530 (setq flyspell-overlay 1654 (setq flyspell-overlay
1531 (make-flyspell-overlay 1655 (make-flyspell-overlay
@@ -1677,69 +1801,71 @@ This command proposes various successive corrections for the current word."
1677 (flyspell-ajust-cursor-point pos (point) old-max) 1801 (flyspell-ajust-cursor-point pos (point) old-max)
1678 (setq flyspell-auto-correct-pos (point))) 1802 (setq flyspell-auto-correct-pos (point)))
1679 ;; fetch the word to be checked 1803 ;; fetch the word to be checked
1680 (let ((word (flyspell-get-word nil)) 1804 (let ((word (flyspell-get-word nil)))
1681 start end poss) 1805 (if (consp word)
1682 ;; destructure return word info list. 1806 (let ((start (car (cdr word)))
1683 (setq start (car (cdr word)) 1807 (end (car (cdr (cdr word))))
1684 end (car (cdr (cdr word))) 1808 (word (car word))
1685 word (car word)) 1809 poss)
1686 (setq flyspell-auto-correct-word word) 1810 (setq flyspell-auto-correct-word word)
1687 ;; now check spelling of word. 1811 ;; now check spelling of word.
1688 (process-send-string ispell-process "%\n") ;put in verbose mode 1812 (process-send-string ispell-process "%\n") ;put in verbose mode
1689 (process-send-string ispell-process (concat "^" word "\n")) 1813 (process-send-string ispell-process (concat "^" word "\n"))
1690 ;; wait until ispell has processed word 1814 ;; wait until ispell has processed word
1691 (while (progn 1815 (while (progn
1692 (accept-process-output ispell-process) 1816 (accept-process-output ispell-process)
1693 (not (string= "" (car ispell-filter))))) 1817 (not (string= "" (car ispell-filter)))))
1694 (setq ispell-filter (cdr ispell-filter)) 1818 (setq ispell-filter (cdr ispell-filter))
1695 (if (consp ispell-filter) 1819 (if (consp ispell-filter)
1696 (setq poss (ispell-parse-output (car ispell-filter)))) 1820 (setq poss (ispell-parse-output (car ispell-filter))))
1697 (cond ((or (eq poss t) (stringp poss)) 1821 (cond
1698 ;; don't correct word 1822 ((or (eq poss t) (stringp poss))
1699 t) 1823 ;; don't correct word
1700 ((null poss) 1824 t)
1701 ;; ispell error 1825 ((null poss)
1702 (error "Ispell: error in Ispell process")) 1826 ;; ispell error
1703 (t 1827 (error "Ispell: error in Ispell process"))
1704 ;; the word is incorrect, we have to propose a replacement 1828 (t
1705 (let ((replacements (if flyspell-sort-corrections 1829 ;; the word is incorrect, we have to propose a replacement
1706 (sort (car (cdr (cdr poss))) 'string<) 1830 (let ((replacements (if flyspell-sort-corrections
1707 (car (cdr (cdr poss)))))) 1831 (sort (car (cdr (cdr poss))) 'string<)
1708 (setq flyspell-auto-correct-region nil) 1832 (car (cdr (cdr poss))))))
1709 (if (consp replacements) 1833 (setq flyspell-auto-correct-region nil)
1710 (progn 1834 (if (consp replacements)
1711 (let ((replace (car replacements))) 1835 (progn
1712 (let ((new-word replace)) 1836 (let ((replace (car replacements)))
1713 (if (not (equal new-word (car poss))) 1837 (let ((new-word replace))
1714 (progn 1838 (if (not (equal new-word (car poss)))
1715 ;; the save the current replacements 1839 (progn
1716 (setq flyspell-auto-correct-region 1840 ;; the save the current replacements
1717 (cons start (length new-word))) 1841 (setq flyspell-auto-correct-region
1718 (let ((l replacements)) 1842 (cons start (length new-word)))
1719 (while (consp (cdr l)) 1843 (let ((l replacements))
1720 (setq l (cdr l))) 1844 (while (consp (cdr l))
1721 (rplacd l (cons (car poss) replacements))) 1845 (setq l (cdr l)))
1722 (setq flyspell-auto-correct-ring 1846 (rplacd l (cons (car poss) replacements)))
1723 replacements) 1847 (setq flyspell-auto-correct-ring
1724 (flyspell-unhighlight-at start) 1848 replacements)
1725 (delete-region start end) 1849 (flyspell-unhighlight-at start)
1726 (funcall flyspell-insert-function new-word) 1850 (delete-region start end)
1727 (if flyspell-abbrev-p 1851 (funcall flyspell-insert-function new-word)
1728 (if (flyspell-already-abbrevp 1852 (if flyspell-abbrev-p
1729 (flyspell-abbrev-table) word) 1853 (if (flyspell-already-abbrevp
1730 (flyspell-change-abbrev 1854 (flyspell-abbrev-table) word)
1731 (flyspell-abbrev-table) 1855 (flyspell-change-abbrev
1732 word 1856 (flyspell-abbrev-table)
1733 new-word) 1857 word
1734 (flyspell-define-abbrev word new-word))) 1858 new-word)
1735 (flyspell-word) 1859 (flyspell-define-abbrev word
1736 (flyspell-display-next-corrections 1860 new-word)))
1737 (cons new-word flyspell-auto-correct-ring)) 1861 (flyspell-word)
1738 (flyspell-ajust-cursor-point pos 1862 (flyspell-display-next-corrections
1739 (point) 1863 (cons new-word flyspell-auto-correct-ring))
1740 old-max)))))))))) 1864 (flyspell-ajust-cursor-point pos
1741 (setq flyspell-auto-correct-pos (point)) 1865 (point)
1742 (ispell-pdict-save t))))) 1866 old-max))))))))))
1867 (setq flyspell-auto-correct-pos (point))
1868 (ispell-pdict-save t)))))))
1743 1869
1744;*---------------------------------------------------------------------*/ 1870;*---------------------------------------------------------------------*/
1745;* flyspell-auto-correct-previous-pos ... */ 1871;* flyspell-auto-correct-previous-pos ... */
@@ -1752,8 +1878,8 @@ This command proposes various successive corrections for the current word."
1752;*---------------------------------------------------------------------*/ 1878;*---------------------------------------------------------------------*/
1753(defun flyspell-auto-correct-previous-hook () 1879(defun flyspell-auto-correct-previous-hook ()
1754 "Hook to track successive calls to `flyspell-auto-correct-previous-word'. 1880 "Hook to track successive calls to `flyspell-auto-correct-previous-word'.
1755Sets flyspell-auto-correct-previous-pos to nil" 1881Sets `flyspell-auto-correct-previous-pos' to nil"
1756 (interactive) 1882 (interactive)
1757 (remove-hook 'pre-command-hook (function flyspell-auto-correct-previous-hook) t) 1883 (remove-hook 'pre-command-hook (function flyspell-auto-correct-previous-hook) t)
1758 (unless (eq this-command (function flyspell-auto-correct-previous-word)) 1884 (unless (eq this-command (function flyspell-auto-correct-previous-word))
1759 (setq flyspell-auto-correct-previous-pos nil))) 1885 (setq flyspell-auto-correct-previous-pos nil)))
@@ -1761,45 +1887,57 @@ Sets flyspell-auto-correct-previous-pos to nil"
1761;*---------------------------------------------------------------------*/ 1887;*---------------------------------------------------------------------*/
1762;* flyspell-auto-correct-previous-word ... */ 1888;* flyspell-auto-correct-previous-word ... */
1763;*---------------------------------------------------------------------*/ 1889;*---------------------------------------------------------------------*/
1764(defun flyspell-auto-correct-previous-word (position) 1890(defun flyspell-auto-correct-previous-word (position)
1765 "*Auto correct the first mispelled word that occurs before point." 1891 "*Auto correct the first mispelled word that occurs before point.
1892But don't look beyond what's visible on the screen."
1766 (interactive "d") 1893 (interactive "d")
1767 1894
1768 (add-hook 'pre-command-hook 1895 (let (top bot)
1769 (function flyspell-auto-correct-previous-hook) t t) 1896 (save-excursion
1770 1897 (move-to-window-line 0)
1771 (save-excursion 1898 (setq top (point))
1772 (unless flyspell-auto-correct-previous-pos 1899 (move-to-window-line -1)
1773 ;; only reset if a new overlay exists 1900 (setq bot (point)))
1774 (setq flyspell-auto-correct-previous-pos nil) 1901 (save-excursion
1775 1902 (save-restriction
1776 (let ((overlay-list (overlays-in (point-min) position)) 1903 (narrow-to-region top bot)
1777 (new-overlay 'dummy-value)) 1904 (re-search-forward "\\s \\|\\'" nil t)
1778 1905 (overlay-recenter (point))
1779 ;; search for previous (new) flyspell overlay 1906
1780 (while (and new-overlay 1907 (add-hook 'pre-command-hook
1781 (or (not (flyspell-overlay-p new-overlay)) 1908 (function flyspell-auto-correct-previous-hook) t t)
1782 ;; check if its face has changed 1909
1783 (not (eq (get-char-property 1910 (unless flyspell-auto-correct-previous-pos
1784 (overlay-start new-overlay) 'face) 1911 ;; only reset if a new overlay exists
1785 'flyspell-incorrect-face)))) 1912 (setq flyspell-auto-correct-previous-pos nil)
1786 (setq new-overlay (car-safe overlay-list)) 1913
1787 (setq overlay-list (cdr-safe overlay-list))) 1914 (let ((overlay-list (overlays-in (point-min) position))
1788 1915 (new-overlay 'dummy-value))
1789 ;; if nothing new exits new-overlay should be nil 1916
1790 (if new-overlay;; the length of the word may change so go to the start 1917 ;; search for previous (new) flyspell overlay
1791 (setq flyspell-auto-correct-previous-pos 1918 (while (and new-overlay
1792 (overlay-start new-overlay))))) 1919 (or (not (flyspell-overlay-p new-overlay))
1793 1920 ;; check if its face has changed
1794 (when flyspell-auto-correct-previous-pos 1921 (not (eq (get-char-property
1795 (save-excursion 1922 (overlay-start new-overlay) 'face)
1796 (goto-char flyspell-auto-correct-previous-pos) 1923 'flyspell-incorrect-face))))
1797 (let ((ispell-following-word t));; point is at start 1924 (setq new-overlay (car-safe overlay-list))
1798 (if (numberp flyspell-auto-correct-previous-pos) 1925 (setq overlay-list (cdr-safe overlay-list)))
1799 (goto-char flyspell-auto-correct-previous-pos)) 1926
1800 (flyspell-auto-correct-word)) 1927 ;; if nothing new exits new-overlay should be nil
1801 ;; the point may have moved so reset this 1928 (if new-overlay ;; the length of the word may change so go to the start
1802 (setq flyspell-auto-correct-previous-pos (point)))))) 1929 (setq flyspell-auto-correct-previous-pos
1930 (overlay-start new-overlay)))))
1931
1932 (when flyspell-auto-correct-previous-pos
1933 (save-excursion
1934 (goto-char flyspell-auto-correct-previous-pos)
1935 (let ((ispell-following-word t)) ;; point is at start
1936 (if (numberp flyspell-auto-correct-previous-pos)
1937 (goto-char flyspell-auto-correct-previous-pos))
1938 (flyspell-auto-correct-word))
1939 ;; the point may have moved so reset this
1940 (setq flyspell-auto-correct-previous-pos (point))))))))
1803 1941
1804;*---------------------------------------------------------------------*/ 1942;*---------------------------------------------------------------------*/
1805;* flyspell-correct-word ... */ 1943;* flyspell-correct-word ... */
@@ -1814,72 +1952,76 @@ The word checked is the word at the mouse position."
1814 (let ((save (point))) 1952 (let ((save (point)))
1815 (mouse-set-point event) 1953 (mouse-set-point event)
1816 (let ((cursor-location (point)) 1954 (let ((cursor-location (point))
1817 (word (flyspell-get-word nil)) 1955 (word (flyspell-get-word nil)))
1818 start end poss replace) 1956 (if (consp word)
1819 ;; destructure return word info list. 1957 (let ((start (car (cdr word)))
1820 (setq start (car (cdr word)) 1958 (end (car (cdr (cdr word))))
1821 end (car (cdr (cdr word))) 1959 (word (car word))
1822 word (car word)) 1960 poss replace)
1823 ;; now check spelling of word. 1961 ;; now check spelling of word.
1824 (process-send-string ispell-process "%\n") ;put in verbose mode 1962 (process-send-string ispell-process "%\n") ;put in verbose mode
1825 (process-send-string ispell-process (concat "^" word "\n")) 1963 (process-send-string ispell-process (concat "^" word "\n"))
1826 ;; wait until ispell has processed word 1964 ;; wait until ispell has processed word
1827 (while (progn 1965 (while (progn
1828 (accept-process-output ispell-process) 1966 (accept-process-output ispell-process)
1829 (not (string= "" (car ispell-filter))))) 1967 (not (string= "" (car ispell-filter)))))
1830 (setq ispell-filter (cdr ispell-filter)) 1968 (setq ispell-filter (cdr ispell-filter))
1831 (if (consp ispell-filter) 1969 (if (consp ispell-filter)
1832 (setq poss (ispell-parse-output (car ispell-filter)))) 1970 (setq poss (ispell-parse-output (car ispell-filter))))
1833 (cond ((or (eq poss t) (stringp poss)) 1971 (cond
1834 ;; don't correct word 1972 ((or (eq poss t) (stringp poss))
1835 t) 1973 ;; don't correct word
1836 ((null poss) 1974 t)
1837 ;; ispell error 1975 ((null poss)
1838 (error "Ispell: error in Ispell process")) 1976 ;; ispell error
1839 ((string-match "GNU" (emacs-version)) 1977 (error "Ispell: error in Ispell process"))
1840 ;; the word is incorrect, we have to propose a replacement 1978 ((string-match "GNU" (emacs-version))
1841 (setq replace (flyspell-emacs-popup event poss word)) 1979 ;; the word is incorrect, we have to propose a replacement
1842 (cond ((eq replace 'ignore) 1980 (setq replace (flyspell-emacs-popup event poss word))
1843 (goto-char save) 1981 (cond ((eq replace 'ignore)
1844 nil) 1982 (goto-char save)
1845 ((eq replace 'save) 1983 nil)
1846 (goto-char save) 1984 ((eq replace 'save)
1847 (process-send-string ispell-process (concat "*" word "\n")) 1985 (goto-char save)
1848 (flyspell-unhighlight-at cursor-location) 1986 (process-send-string ispell-process
1849 (setq ispell-pdict-modified-p '(t))) 1987 (concat "*" word "\n"))
1850 ((or (eq replace 'buffer) (eq replace 'session)) 1988 (flyspell-unhighlight-at cursor-location)
1851 (process-send-string ispell-process (concat "@" word "\n")) 1989 (setq ispell-pdict-modified-p '(t)))
1852 (if (null ispell-pdict-modified-p) 1990 ((or (eq replace 'buffer) (eq replace 'session))
1853 (setq ispell-pdict-modified-p 1991 (process-send-string ispell-process
1854 (list ispell-pdict-modified-p))) 1992 (concat "@" word "\n"))
1855 (flyspell-unhighlight-at cursor-location) 1993 (if (null ispell-pdict-modified-p)
1856 (goto-char save) 1994 (setq ispell-pdict-modified-p
1857 (if (eq replace 'buffer) 1995 (list ispell-pdict-modified-p)))
1858 (ispell-add-per-file-word-list word))) 1996 (flyspell-unhighlight-at cursor-location)
1859 (replace 1997 (goto-char save)
1860 (flyspell-unhighlight-at cursor-location) 1998 (if (eq replace 'buffer)
1861 (let ((new-word (if (atom replace) 1999 (ispell-add-per-file-word-list word)))
1862 replace 2000 (replace
1863 (car replace))) 2001 (flyspell-unhighlight-at cursor-location)
1864 (cursor-location (+ (- (length word) (- end start)) 2002 (let ((new-word (if (atom replace)
1865 cursor-location))) 2003 replace
1866 (if (not (equal new-word (car poss))) 2004 (car replace)))
1867 (let ((old-max (point-max))) 2005 (cursor-location
1868 (delete-region start end) 2006 (+ (- (length word) (- end start))
1869 (funcall flyspell-insert-function new-word) 2007 cursor-location)))
1870 (if flyspell-abbrev-p 2008 (if (not (equal new-word (car poss)))
1871 (flyspell-define-abbrev word new-word)) 2009 (let ((old-max (point-max)))
1872 (flyspell-ajust-cursor-point save 2010 (delete-region start end)
1873 cursor-location 2011 (funcall flyspell-insert-function new-word)
1874 old-max))))) 2012 (if flyspell-abbrev-p
1875 (t 2013 (flyspell-define-abbrev word new-word))
1876 (goto-char save) 2014 (flyspell-ajust-cursor-point save
1877 nil))) 2015 cursor-location
1878 ((eq flyspell-emacs 'xemacs) 2016 old-max)))))
1879 (flyspell-xemacs-popup 2017 (t
1880 event poss word cursor-location start end save) 2018 (goto-char save)
1881 (goto-char save))) 2019 nil)))
1882 (ispell-pdict-save t)))) 2020 ((eq flyspell-emacs 'xemacs)
2021 (flyspell-xemacs-popup
2022 event poss word cursor-location start end save)
2023 (goto-char save)))
2024 (ispell-pdict-save t))))))
1883 2025
1884;*---------------------------------------------------------------------*/ 2026;*---------------------------------------------------------------------*/
1885;* flyspell-xemacs-correct ... */ 2027;* flyspell-xemacs-correct ... */