Subject: bug#9038: 24.0.50; limit expand-abbrev in viper mode state change

From: Bob Nnamtrop <[email-masked]>
Date: Sat, 9 Jul 2011 11:09:52 -0600

Changing from viper insert state to vi state (called "changing state"
below for brevity) causes expand-abbrev to run if abbrev's are turned
on. This is good but I think the rule for if an abbrev is expanded
should agree with the rule in self-insert-command when in insert mode.
Thus "changing state" should only attempt to expand abbrev if and only
if the previous char has word syntax. This is easily achieved with the
following patch (against trunk):

=== modified file 'lisp/emulation/viper-cmd.el'
--- lisp/emulation/viper-cmd.el 2011-05-23 17:57:17 +0000
+++ lisp/emulation/viper-cmd.el 2011-07-09 16:20:55 +0000
@@ -617,7 +617,8 @@
     (or (viper-overlay-p viper-replace-overlay)
       (viper-set-replace-overlay (point-min) (point-min)))
     (viper-hide-replace-overlay)
-    (if abbrev-mode (expand-abbrev))
+    (if (and abbrev-mode (eq (char-syntax (preceding-char)) ?w))
+        (expand-abbrev))
     (if (and auto-fill-function (> (current-column) fill-column))
        (funcall auto-fill-function))
     ;; don't leave whitespace lines around

More detail:

The reason I want this is because with the present behavior abbrev's
often get run multiple times which can be very annoying. For example,
in idlwave mode if I type in an "if ... endif" block, when I hit
return after the endif the endif is caught as a abbrev which causes
its hook to run (which moves the point to the corresponding begin and
back). Now if I hit escape to change state the abbrev is caught again
and the hook runs again. This occurs even though typing a non-word
char would NOT have caused expand-abbrev to run. If I go back to
insert mode and type any number of non-word char (including returns)
and go back to vi mode this will happen again. Very annoying behavior.

As stated, the "changing state" behavior will run expand-abbrev even
if the point is many lines below the line with the abbrev. In emacs
23.1 and before, "changing state" would only run expand-abbrev if the
abbrev was on the same line. This behavior changed in revision 98777
on 2009-11-25 which changed abbrev--before-point (and thus
expand-abbrev) and made it jump up arbitrary number of lines to find a
abbrev (note that if the abbrev-table has a re for the abbrev the
behavior is the same as the old behavior of staying on one line).  The
doc-string for expand-abbrev says "Expand the abbrev before point, if
there is an abbrev there". The "before point" is a bit ambiguous but
to me it implies directly before point and not 10 lines up! I mention
this because the "changing state" behavior got much more annoying
after this revision since expand-abbrev was no longer bound to the
line that point was on.

Thanks,
Bob