GNU bug report logs - #76884
30.1 problem with flyspell-maybe-correct-transposition

Previous Next

Package: emacs;

Reported by: Jim Diamond <jim <at> jdvb.ca>

Date: Sun, 9 Mar 2025 10:21:02 UTC

Severity: normal

Found in version 30.1

To reply to this bug, email your comments to 76884 AT debbugs.gnu.org.

Toggle the display of automated, internal messages from the tracker.

View this report as an mbox folder, status mbox, maintainer mbox


Report forwarded to bug-gnu-emacs <at> gnu.org:
bug#76884; Package emacs. (Sun, 09 Mar 2025 10:21:02 GMT) Full text and rfc822 format available.

Acknowledgement sent to Jim Diamond <jim <at> jdvb.ca>:
New bug report received and forwarded. Copy sent to bug-gnu-emacs <at> gnu.org. (Sun, 09 Mar 2025 10:21:02 GMT) Full text and rfc822 format available.

Message #5 received at submit <at> debbugs.gnu.org (full text, mbox):

From: Jim Diamond <jim <at> jdvb.ca>
To: bug-gnu-emacs <at> gnu.org
Subject: 30.1 problem with flyspell-maybe-correct-transposition
Date: Sat, 8 Mar 2025 20:50:26 -0400
I recently upgraded to emacs 30.1.  For many years I had been using a
function which automatically corrected transposition errors, but it no
longer works in 30.1.  The author of that function kindly pointed me to the
fact that such functionality has been part of flyspell for a long time, and
that I should add
    (add-hook 'flyspell-incorrect-hook 'flyspell-maybe-correct-transposition)
to my init.el.

So I put that line in my init.el and started editing away, only to discover
that it doesn't do exactly what I want.  To reproduce the problem,


(1) Create a file ABC like this
----------------- cut here --------------------

ABC

----------------- cut here --------------------

(2) Replace your entire init.el with this one line:
(add-hook 'flyspell-incorrect-hook 'flyspell-maybe-correct-transposition)
(Or start with "emacs -Q" and make the "obvious" changes to the procedure
below.)

(3) Fire up a fresh emacs as follows:
emacs ABC

(4) Turn on flyspell
M-x flyspell-mode

(5) Navigate to the end of the 'abc' line

(6) Type Ctrl-T

Result: I get "CAB", whereas I expect "ACB".  This is not merely
unexpected, but an actual problem.

Now, I know that "cab" is an English word, and that "acb" is not, and
I presume flyspell is looking at "ACB" immediately after I do the Ctrl-T
and "fixes" the resulting spelling error.

(Finance wonks may recognize ACB as the abbreviation for "adjusted cost
base", so it is something I might actually want to type.  Yes, I could add
ACB to my dictionary, but that doesn't solve the problem in general,
because there are lots of acronyms which are just one transposition away
from a "normal" word.)

With my old setup in emacs 28 and before, the transposition correction
function was triggered when emacs was about to see if there was an
abbreviation to expand, so if I was anticipating a problem I could
transpose two letters and then move away from the "word" using something
other than a space (e.g., arrow keys), and the text would stay how I wanted
it.

I posted this on gnu.emacs.help looking for a work-around, but a person
with far more emacs expertise than me said it was a bug and I should submit
a bug report.  Here it is.

Thanks.
                                Jim




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#76884; Package emacs. (Sun, 09 Mar 2025 11:01:02 GMT) Full text and rfc822 format available.

Message #8 received at 76884 <at> debbugs.gnu.org (full text, mbox):

From: Eli Zaretskii <eliz <at> gnu.org>
To: Jim Diamond <jim <at> jdvb.ca>
Cc: 76884 <at> debbugs.gnu.org
Subject: Re: bug#76884: 30.1 problem with flyspell-maybe-correct-transposition
Date: Sun, 09 Mar 2025 13:00:31 +0200
> Date: Sat, 8 Mar 2025 20:50:26 -0400
> From: Jim Diamond <jim <at> jdvb.ca>
> 
> I recently upgraded to emacs 30.1.  For many years I had been using a
> function which automatically corrected transposition errors, but it no
> longer works in 30.1.  The author of that function kindly pointed me to the
> fact that such functionality has been part of flyspell for a long time, and
> that I should add
>     (add-hook 'flyspell-incorrect-hook 'flyspell-maybe-correct-transposition)
> to my init.el.
> 
> So I put that line in my init.el and started editing away, only to discover
> that it doesn't do exactly what I want.  To reproduce the problem,
> 
> 
> (1) Create a file ABC like this
> ----------------- cut here --------------------
> 
> ABC
> 
> ----------------- cut here --------------------
> 
> (2) Replace your entire init.el with this one line:
> (add-hook 'flyspell-incorrect-hook 'flyspell-maybe-correct-transposition)
> (Or start with "emacs -Q" and make the "obvious" changes to the procedure
> below.)
> 
> (3) Fire up a fresh emacs as follows:
> emacs ABC
> 
> (4) Turn on flyspell
> M-x flyspell-mode
> 
> (5) Navigate to the end of the 'abc' line
> 
> (6) Type Ctrl-T
> 
> Result: I get "CAB", whereas I expect "ACB".  This is not merely
> unexpected, but an actual problem.

What causes that problem is that add-hook you did.  If you want C-t to
transpose characters, and Flyspell to not react on C-t, then why did
you add to that hook?

IOW, I don't understand what scenario worked for you in older versions
of Emacs and no longer works in Emacs 30.1.  Could you please show a
recipe, starting from "emacs -Q", which did NOT convert ABC into CAB
in Emacs 29 or earlier, but does with Emacs 30.1?  Because if I try
using that add-hook in Emacs 28.2, I get the same result: ABC => CAB,
if I type C-t at the end of the ABC line.  So I'm confused regarding
the problem which you found in Emacs 30 that didn't exist before.

> With my old setup in emacs 28 and before, the transposition correction
> function was triggered when emacs was about to see if there was an
> abbreviation to expand, so if I was anticipating a problem I could
> transpose two letters and then move away from the "word" using something
> other than a space (e.g., arrow keys), and the text would stay how I wanted
> it.

Sorry, I don't understand this description.  Could you please show a
recipe with all the commands and key sequences explicit?




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#76884; Package emacs. (Sun, 09 Mar 2025 19:09:01 GMT) Full text and rfc822 format available.

Message #11 received at 76884 <at> debbugs.gnu.org (full text, mbox):

From: Eli Zaretskii <eliz <at> gnu.org>
To: Jim Diamond <jim <at> jdvb.ca>
Cc: 76884 <at> debbugs.gnu.org
Subject: Re: bug#76884: 30.1 problem with flyspell-maybe-correct-transposition
Date: Sun, 09 Mar 2025 21:08:25 +0200
> Date: Sun, 9 Mar 2025 13:46:23 -0300
> From: Jim Diamond <jim <at> jdvb.ca>
> Cc: 76884 <at> debbugs.gnu.org
> 
> >> Result: I get "CAB", whereas I expect "ACB".  This is not merely
> >> unexpected, but an actual problem.
> 
> > What causes that problem is that add-hook you did.  If you want C-t to
> > transpose characters, and Flyspell to not react on C-t, then why did
> > you add to that hook?
> 
> I added to that hook because, when the above-mentioned "automatically fix
> transposition errors" stopped working (with my upgrade to 30.1), I went
> looking for a newer version of the software.  The original author told me
> that flyspell has had the ability to automatically fix transposition errors
> for some time, and thus he has stopped updating his code.  And he suggested
> I add that function to that hook.  So I did.
> 
> Given that he (presumably!) understands perfectly what his original
> software did, I assumed that adding to that hook would do the same thing.
> It doesn't, at least the way I am using it.

So let me see if I understand what you are describing.

You had a bunch of function in auto-correct.el which would
automatically fix transposed characters as side effect of expanding
abbrevs, which happens when you type a non-word character such as SPC
after a sequence of word-constituent characters.  This code stopped
working in Emacs 30.1 (any idea why, btw?).  So you were looking for a
replacement, and someone told you that setting flyspell-incorrect-hook
to call flyspell-maybe-correct-transposition would do the job.  But it
doesn't do the job as you'd like it, because it attempts to fix
mis-spellings too early, immediately when you type C-t instead of when
you type SPC after C-t.  So your bug report is that using
flyspell-maybe-correct-transposition this way doesn't work as you'd
like, and you consider that a bug.  Did I understand you correctly?

> I realize that the flyspell mechanism doesn't rely on abbrev mode, and so
> my original question to the gnu emacs newsgroup was a hope that someone
> with more elisp knowledge than me could help me out.  But, as I mentioned,
> someone with far more elisp knowledge than me claimed it was a bug, and I
> believed him.  So here we are.

If I understood you correctly, there's no bug in what
flyspell-maybe-correct-transposition does, and invoking it from
flyspell-incorrect-hook is indeed supposed to work as you see, which
is not what you want.  flyspell-incorrect-hook is called when Flyspell
decides the word before point is mis-spelled and underlines it with
that red wavy underline, and that happens as soon as you type C-t.

I think you should figure out why the functions you used before no
longer work and adapt them to Emacs 30, so you could keep using them
as you did before.  Because Flyspell and its hook will not allow you
to have the same functionality if the ability to type C-t without
having Flyspell intervene right away is not part of what
flyspell-maybe-correct-transposition can offer.

If you explain why auto-correct no longer works and show the details,
maybe we can even find the solution as part of this discussion,
although it will no longer be about a bug in Flyspell.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#76884; Package emacs. (Mon, 10 Mar 2025 00:44:03 GMT) Full text and rfc822 format available.

Message #14 received at 76884 <at> debbugs.gnu.org (full text, mbox):

From: Jim Diamond <jim <at> jdvb.ca>
To: Eli Zaretskii <eliz <at> gnu.org>
Cc: 76884 <at> debbugs.gnu.org
Subject: Re: bug#76884: 30.1 problem with flyspell-maybe-correct-transposition
Date: Sun, 9 Mar 2025 13:46:23 -0300
On Sun, Mar  9, 2025 at 13:00 (+0200), Eli Zaretskii wrote:

>> Date: Sat, 8 Mar 2025 20:50:26 -0400
>> From: Jim Diamond <jim <at> jdvb.ca>

>> I recently upgraded to emacs 30.1.  For many years I had been using a
>> function which automatically corrected transposition errors, but it no
>> longer works in 30.1.  The author of that function kindly pointed me to the
>> fact that such functionality has been part of flyspell for a long time, and
>> that I should add
>>     (add-hook 'flyspell-incorrect-hook 'flyspell-maybe-correct-transposition)
>> to my init.el.

>> So I put that line in my init.el and started editing away, only to discover
>> that it doesn't do exactly what I want.  To reproduce the problem,


>> (1) Create a file ABC like this
>> ----------------- cut here --------------------

>> ABC

>> ----------------- cut here --------------------

>> (2) Replace your entire init.el with this one line:
>> (add-hook 'flyspell-incorrect-hook 'flyspell-maybe-correct-transposition)
>> (Or start with "emacs -Q" and make the "obvious" changes to the procedure
>> below.)

>> (3) Fire up a fresh emacs as follows:
>> emacs ABC

>> (4) Turn on flyspell
>> M-x flyspell-mode

>> (5) Navigate to the end of the 'abc' line

>> (6) Type Ctrl-T

>> Result: I get "CAB", whereas I expect "ACB".  This is not merely
>> unexpected, but an actual problem.

> What causes that problem is that add-hook you did.  If you want C-t to
> transpose characters, and Flyspell to not react on C-t, then why did
> you add to that hook?

I added to that hook because, when the above-mentioned "automatically fix
transposition errors" stopped working (with my upgrade to 30.1), I went
looking for a newer version of the software.  The original author told me
that flyspell has had the ability to automatically fix transposition errors
for some time, and thus he has stopped updating his code.  And he suggested
I add that function to that hook.  So I did.

Given that he (presumably!) understands perfectly what his original
software did, I assumed that adding to that hook would do the same thing.
It doesn't, at least the way I am using it.


> IOW, I don't understand what scenario worked for you in older versions
> of Emacs and no longer works in Emacs 30.1.  Could you please show a
> recipe, starting from "emacs -Q", which did NOT convert ABC into CAB
> in Emacs 29 or earlier, but does with Emacs 30.1?   Because if I try
> using that add-hook in Emacs 28.2, I get the same result: ABC => CAB,
> if I type C-t at the end of the ABC line.  So I'm confused regarding
> the problem which you found in Emacs 30 that didn't exist before.

I am thinking you ignored the part where I said "For many years I had been
using a function which automatically corrected transposition errors, but it
no longer works in 30.1.  The author of that function kindly pointed me to
the fact that such functionality has been part of flyspell for a long time,
and that I should add
     (add-hook 'flyspell-incorrect-hook 'flyspell-maybe-correct-transposition)
to my init.el."

(Many years is sincce 1999 or so, in case anyone reading this is wondering.)

So the "recipe" doesn't depend on flyspell.  It depends on abbrev-mode, and
most recently was triggered as follows:
        (advice-add abbrev-expand-function 
            :before (lambda () (fix-transposed-characters)))
This worked in 28.2 and (IIRC) in 29.4.


>> With my old setup in emacs 28 and before, the transposition correction
>> function was triggered when emacs was about to see if there was an
>> abbreviation to expand, so if I was anticipating a problem I could
>> transpose two letters and then move away from the "word" using something
>> other than a space (e.g., arrow keys), and the text would stay how I wanted
>> it.

> Sorry, I don't understand this description.  Could you please show a
> recipe with all the commands and key sequences explicit?


With apologies to the original author of the code (John Wiegley), here is
my somewhat modified version of his code which did what I want in 28.2.  I
hesitated to mention his name because some of my changes may be abhorrent
to him or other people reading this, and I don't want any bad thoughts or
words sent his way.

I don't have a system with 29.3 or 29.4 to test this, but I did test this
on 28.2.

(1) Put this code in a file called auto-correct.el:

%%%%%------------------ auto-correct.el --------------------

(require 'ispell)

(defvar correct-words-applicable-modes
  '(text-mode zsd-mail-mode c-mode c++-mode texinfo-mode plain-tex-mode)
  "*A list of modes in which words should be automatically corrected.")

(defun auto-correct-check-word ()
  "Call ispell-word with ispell-check-only set to t.
Setting this to t will not prompt for corrections, but return nil if the
word is incorrect.  Redefine (message) and (beep) to shut ispell up."
  (let ((ispell-check-only t)
        (beep-def (symbol-function 'beep))
        (message-def (symbol-function 'message))
        (found t)
       )
    (defun beep () (setq found nil))
    (defun message (&rest garbage) t)
    (ispell-word nil t)
    (fset 'beep beep-def)
    (fset 'message message-def)
    found
  )
)

(defun fix-transposed-characters ()
    "Fix any transposed characters in the input."
    (catch 'done
        (if (and (memq major-mode correct-words-applicable-modes)
                 (not (auto-correct-check-word)))
            (let ((end (point)))
                (backward-word 1)
                (if (not (looking-at "[a-zA-Z]+\\([ \t]\\|$\\)"))
                    (prong
                        (goto-char end)
                        (throw 'done t)
                    )
                )
                (if (and
                        (equal major-mode 'plain-tex-mode)
                        (if (not (bobp))
                            (save-excursion
                                (backward-char 1)
                                (looking-at "\\\\")
                            )
                            nil
                        )
                    )
                    (prong
                        (goto-char end)
                        (throw 'done t)
                    )
                )
                (let ((case-fold-search nil))
                    (if (looking-at "[A-Z]+\\([ \t]\\|$\\)")
                        (prong
                            (goto-char end)
                            (throw 'done t)
                        )
                    )
                )
                (forward-char 1)
                (while (< (point) end)
                    (transpose-chars nil)
                    (if (auto-correct-check-word)
                        (progn
                            (goto-char end)
                            (throw 'done t)
                        )
                        (forward-char -1)
                        (transpose-chars nil)
                    )
                )
            )
        )
    )
)

(advice-add abbrev-expand-function 
            :before (lambda () (fix-transposed-characters)))

%%%---------------------------------------------------

(2) In the same directory as this auto-correct.el file, start up emacs 28.2:
       emacs -Q

(3) Load and execute the auto-correction code:
        ESC : (load-file "auto-correct.el") RTE

(4) Visit a file "a.txt"
        C-x C-f a.txt RTE

(5) Turn on abbrev mode and flyspell mode:
        ESC : (abbrev-mode t) RET
        ESC : (flyspell-mode) RTE

(4) Enter the 3 chars "abc" on a single line.
        a b c

(5) At the end of the single line, type Ctrl-T:
        C-t

(6) Note that you now have "acb", not "cab".

Following that, if I now enter a space, "acb" is automagically changed to
"cab", as expected.

But (and this is the salient point) "acb" *is not* changed to "cab"
immediately upon typing Ctrl-T, it is only done when the abbrev
functionality is exercised (I believe this is the correct thing to say).

I realize that the flyspell mechanism doesn't rely on abbrev mode, and so
my original question to the gnu emacs newsgroup was a hope that someone
with more elisp knowledge than me could help me out.  But, as I mentioned,
someone with far more elisp knowledge than me claimed it was a bug, and I
believed him.  So here we are.


Does that fully explain the issue, as well as what I would like to achieve?
If not, let me know and I'll add whatever detail is needed.

Cheers.
                                Jim




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#76884; Package emacs. (Mon, 10 Mar 2025 00:45:03 GMT) Full text and rfc822 format available.

Message #17 received at 76884 <at> debbugs.gnu.org (full text, mbox):

From: Jim Diamond <jim <at> jdvb.ca>
To: Eli Zaretskii <eliz <at> gnu.org>
Cc: 76884 <at> debbugs.gnu.org
Subject: Re: bug#76884: 30.1 problem with flyspell-maybe-correct-transposition
Date: Sun, 9 Mar 2025 17:59:15 -0300
On Sun, Mar  9, 2025 at 21:08 (+0200), Eli Zaretskii wrote:

>> Date: Sun, 9 Mar 2025 13:46:23 -0300
>> From: Jim Diamond <jim <at> jdvb.ca>
>> Cc: 76884 <at> debbugs.gnu.org

>>>> Result: I get "CAB", whereas I expect "ACB".  This is not merely
>>>> unexpected, but an actual problem.

>>> What causes that problem is that add-hook you did.  If you want C-t to
>>> transpose characters, and Flyspell to not react on C-t, then why did
>>> you add to that hook?

>> I added to that hook because, when the above-mentioned "automatically fix
>> transposition errors" stopped working (with my upgrade to 30.1), I went
>> looking for a newer version of the software.  The original author told me
>> that flyspell has had the ability to automatically fix transposition errors
>> for some time, and thus he has stopped updating his code.  And he suggested
>> I add that function to that hook.  So I did.

>> Given that he (presumably!) understands perfectly what his original
>> software did, I assumed that adding to that hook would do the same thing.
>> It doesn't, at least the way I am using it.

> So let me see if I understand what you are describing.

> You had a bunch of function in auto-correct.el which would
> automatically fix transposed characters as side effect of expanding
> abbrevs, which happens when you type a non-word character such as SPC
> after a sequence of word-constituent characters.  This code stopped
> working in Emacs 30.1 (any idea why, btw?).

No, the error message I got was opaque to me, and so that was when I went
looking for a newer version of auto-correct.el

> So you were looking for a replacement, and someone told you that setting
> flyspell-incorrect-hook to call flyspell-maybe-correct-transposition
> would do the job.

Correct.

> But it doesn't do the job as you'd like it, because it attempts to fix
> mis-spellings too early, immediately when you type C-t instead of when
> you type SPC after C-t.

Correct.

> So your bug report is that using flyspell-maybe-correct-transposition
> this way doesn't work as you'd like, and you consider that a bug.  Did I
> understand you correctly?

No.  As I already said (twice?) I thought there might be some setting to
make it work as I would like, and I posted to the gnu emacs newsgroup,
where an experienced emacs and elisp person opined that it was a bug and I
should report it.

>> I realize that the flyspell mechanism doesn't rely on abbrev mode, and so
>> my original question to the gnu emacs newsgroup was a hope that someone
>> with more elisp knowledge than me could help me out.  But, as I mentioned,
>> someone with far more elisp knowledge than me claimed it was a bug, and I
>> believed him.  So here we are.

> If I understood you correctly, there's no bug in what
> flyspell-maybe-correct-transposition does,

I'd say that is arguable, but let's carry on.

> and invoking it from flyspell-incorrect-hook is indeed supposed to work
> as you see, which is not what you want.  flyspell-incorrect-hook is
> called when Flyspell decides the word before point is mis-spelled and
> underlines it with that red wavy underline, and that happens as soon as
> you type C-t.

Indeed it does.

> I think you should figure out why the functions you used before no
> longer work and adapt them to Emacs 30, so you could keep using them
> as you did before.

It would appear that is my way forward.

> Because Flyspell and its hook will not allow you to have the same
> functionality if the ability to type C-t without having Flyspell
> intervene right away is not part of what
> flyspell-maybe-correct-transposition can offer.

OK.  I will interpret that as a definitive "no" answer to my original
question of "is there anything I can configure in flyspell to get what I
want.

> If you explain why auto-correct no longer works and show the details,
> maybe we can even find the solution as part of this discussion,
> although it will no longer be about a bug in Flyspell.

I will reset things back to how they were and wait for the problem to
repeat itself.  (Unfortunately, the error and subsequent backtrace are not
as easily reproducible as would be convenient.)

                                Jim




This bug report was last modified 155 days ago.

Previous Next


GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.