[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

bug#32280: 26.1; FLYSPELL-BUFFER sometimes misbehaves for some input in

From: Artem Boldarev
Subject: bug#32280: 26.1; FLYSPELL-BUFFER sometimes misbehaves for some input in a large enough buffer
Date: Tue, 7 Aug 2018 13:56:58 +0300
User-agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:52.0) Gecko/20100101 Thunderbird/52.9.1


Thanks, Eli! I have tried the proposed patch, and it seems to solve the problem.

Thanks to everyone who have helped to track down the problem.

By the way, are there any chances to see these changes incorporated into Emacs 26.2?

Kind regards,

I have tried to do as you suggested. The result is the same as in my
previous letter.
And now I understand why.  The problem is not with comparing the
length of the misspelled word, the problem is with this part of

              ;; Iterate on string search until string is found as word,
              ;; not as substring.
              (while keep
                (if (search-forward word
                                    flyspell-large-region-end t)
                    (let* ((found-list
                              ;; Move back into the match
                              ;; so flyspell-get-word will find it.
                              (forward-char -1)
                              (flyspell-get-word)))  <<<<<<<<<<<<<<<<<<<<<<
                           (found (car found-list))
                           (found-length (length found))
                           (misspell-length (length word)))

When the misspelled word doesn't match CASECHARS, the call to
flyspell-get-word will find an entirely different word than the one
which was originally found as misspelled: it will find the first word
before point that matches CASECHARS.  In your case, since the
misspelled words were in English, flyspell-get-word will find the
first Cyrillic word before point.  From there on, the logic of the
code in flyspell-external-point-words completely breaks down, and
yields results that are more-or-less random.

IOW, the assumption of the current logic in
flyspell-external-point-words is that the misspelled word is from the
same language that is supported by the current dictionary, and in your
case this assumption is false.  This is why the problem disappeared as
soon as you added Latin alphabetic characters to CASECHARS.

So please try this patch for flyspell.el, it should fix your problem
with the original setup of ru_RU (it also fixes an unrelated wrong
assumption which goes back to the days when the spell-checking program
could only be either Ispell or Aspell):

diff --git a/lisp/textmodes/flyspell.el b/lisp/textmodes/flyspell.el
index 5726bd8..4d7a189 100644
--- a/lisp/textmodes/flyspell.el
+++ b/lisp/textmodes/flyspell.el
@@ -1420,10 +1420,20 @@ flyspell-external-point-words
  The list of incorrect words should be in `flyspell-external-ispell-buffer'.
  \(We finish by killing that buffer and setting the variable to nil.)
  The buffer to mark them in is `flyspell-large-region-buffer'."
-  (let (words-not-found
-       (ispell-otherchars (ispell-get-otherchars))
-       (buffer-scan-pos flyspell-large-region-beg)
-       case-fold-search)
+  (let* (words-not-found
+         (flyspell-casechars (flyspell-get-casechars))
+         (ispell-otherchars (ispell-get-otherchars))
+         (ispell-many-otherchars-p (ispell-get-many-otherchars-p))
+         (word-chars (concat flyspell-casechars
+                             "+\\("
+                             (if (not (string= "" ispell-otherchars))
+                                 (concat ispell-otherchars "?"))
+                             flyspell-casechars
+                             "+\\)"
+                             (if ispell-many-otherchars-p
+                                 "*" "?")))
+         (buffer-scan-pos flyspell-large-region-beg)
+         case-fold-search)
      (with-current-buffer flyspell-external-ispell-buffer
        (goto-char (point-min))
        ;; Loop over incorrect words, in the order they were reported,
@@ -1453,11 +1463,18 @@ flyspell-external-point-words
                              ;; Move back into the match
                              ;; so flyspell-get-word will find it.
                              (forward-char -1)
-                             (flyspell-get-word)))
+                              ;; Is this a word that matches the
+                              ;; current dictionary?
+                              (if (looking-at word-chars)
+                                 (flyspell-get-word))))
                           (found (car found-list))
                           (found-length (length found))
                           (misspell-length (length word)))
                      (when (or
+                             ;; Misspelled word is not from the
+                             ;; language supported by the current
+                             ;; dictionary.
+                             (null found)
                             ;; Size matches, we really found it.
                             (= found-length misspell-length)
                             ;; Matches as part of a boundary-char separated
@@ -1479,13 +1496,21 @@ flyspell-external-point-words
                             ;; backslash) and none of the previous
                             ;; conditions match.
                             (and (not ispell-really-aspell)
+                                  (not ispell-really-hunspell)
+                                  (not ispell-really-enchant)
                                    (goto-char (- (nth 1 found-list) 1))
                                    (if (looking-at "[\\]" )
                        (setq keep nil)
-                       (flyspell-word nil t)
+                        ;; Don't try spell-checking words whose
+                        ;; characters don't match CASECHARS, because
+                        ;; flyspell-word will then consider as
+                        ;; misspelling the preceding word that matches
+                        ;; CASECHARS.
+                        (or (null found)
+                           (flyspell-word nil t))
                        ;; Search for next misspelled word will begin from
                        ;; end of last validated match.
                        (setq buffer-scan-pos (point))))

reply via email to

[Prev in Thread] Current Thread [Next in Thread]