Subject: bug#5805: 23.3 abbrev-insert needs a limited save-excursion

From: Bob Nnamtrop <[email-masked]>
Date: Thu, 7 Jul 2011 15:46:02 -0600

On Thu, Jul 7, 2011 at 2:59 PM, Stefan Monnier <[email-masked]> wrote:
> tags 5805 patch
> thanks
>
>> I agree with the original poster that a save-excursion is needed in
>> abbrev-expand and by making its scope limited (see below) it will not
>> interfere with abbrevs that want to change point. The reason I find it
>> annoying the way it is now is that some modes (e.g., idlwave) use
>> abbrev's extensively to change keywords (e.g. capitalize them). These
>> are defined without the leading "\". So if I am any number of lines
>> with only whitespace below a keyword defined in this way (e.g. endfor)
>> and run expand-abbrev then the point moves even if no visible change
>> takes place. This is a VERY common occurrence for me since in viper
>> mode changing from insert to vi mode runs expand-abbrev! Placing the
>> save-excursion just around the part of abbrev-insert that actually
>> expands the abbrev fixes this problem and does not limit abbrev's from
>> moving the point (idlwave does this extensively as well and I've
>> tested that it is not impacted).
>
> Hmm... sounds like an interesting solution.  I'll take a closer look and
> get back to you.  Thank you.
>
>> Here is the diff against the
>> abbrev.el in emacs 23.3 (note that whitespace not adjusted).
>
> Highly appreciated.
>
>
>        Stefan
>

I've been thinking about this some more and while I think the
save-excursion solution mentioned above is not a bad idea, perhaps
fixing this at the heart of the problem would be better. The basic
problem is that changing state from viper insert state to viper vi
state causes abbrev's to be expanded if there is any amount of white
space between the point and an abbrev. This differs from the rules of
e.g. "space" causing an abbrev to be expanded. A space (or comma, ret,
etc) will only cause an abbrev to expand if it is immediately after an
abbrev. If changing state from viper insert to vi state followed the
same rules then everything would work nicer.

For example, what commonly happens to me is I type an abbrev (say \ef)
then return. In idlwave mode this causes \ef to be expanded to endfor
and the cursor blinks to the corresponding begin and back. Now if I
type a return and a tab to indent and then exit viper insert state
abbrev-expand is run again (since endfor is also an abbrev, for
itself) and the cursor again blinks to the begin and the cursor is
left on the endfor. The save-excursion fix only fixes where the cursor
is left. The blinking still occurs. Thus it is only a partial fix.

The rule should be "if a space (or any other non-word character) would
not cause an abbrev to expand then exiting from viper insert state
should not cause an abbrev to expand". And vise-versa. This would fix
all the issues I have with abbrev.

I've been trying to implement this today but without success. I know
why changing viper state causes abbrev to run. There is a line

(if abbrev-mode (expand-abbrev))

in viper-change-state-to-vi in viper-cmd.el which causes it. What I
cannot figure out is what causes a normal space (or comma, ret, etc)
to make an abbrev expand when one is directly after an abbrev (and
when the point is one space past the abbrev another space does not
cause an expansion, unlike the code above). Maybe you could give me a
hint. Is there a "abbrev-pending" or something like that.

Thanks,
Bob