emacs-devel
[Top][All Lists]
Advanced

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

Re: mailabbrev.el, mailalias.el and related package.


From: Luc Teirlinck
Subject: Re: mailabbrev.el, mailalias.el and related package.
Date: Sat, 16 Feb 2002 20:32:32 -0600 (CST)

This concerns the overly aggressive expansion of mailabbrevs.

I believe the following completely explains why the bug we have been
discussing occurs in Emacs21.2.50, but not in 21.1.90 or earlier
versions.

In the present message, I just will try to point out what I believe is
going wrong.  I will send a follow-up message on what could be done
from here.  

I believe the following change in the mailabbrev code is responsible:

Copy of a message of Richard Stallman:

        Richard Stallman address@hidden 
        Sat, 2 Feb 2002 21:41:58 -0700 (MST) 

        This is very strange.  mailabbrev.el does assume the existence
        of mail-mode-abbrev-table, as you say.  But the code in
        sendmail.el seems not to have used mail-mode-abbrev-table
        until a few months ago.  Perhaps this was an unreported bug.
        I had better investigate further.

        Maybe sendmail-pre-abbrev-expand-hook needs to always restore
        local-abbrev-table and the syntax table to whatever they were
        before
        it was called?

        I agree.  The reason this was not done was an undoc feature I didn't
        know about: setting up a different, convenient syntax table for
        address headers.  The feature could be useful but the implementation
        was unreliable, so I eliminated it.

I assume you are talking about mail-mode-header-syntax-table.

The documentation string for that syntax table is extremely
misleading.  It suggests that the purpose of this table is to provide
for more appropriate behavior of forward-sexp and forward-word and the
like.  As you correctly point out in your remarks above, the
implementation was unreliable.  Maybe it might be possible to make it
reliable.  My package does not attempt that.  I believed it looked
like quite a bit of work, as well as a possible source of potentially
nasty bugs.  (Maybe it is not.)  Anyway, you seem to have concluded
that it was not worth the trouble.  I came to the same conclusion.

However, regardless of what the documentation string says, even if this
forward-sexp and forward-word stuff would have been implemented
correctly, this would have been a very secondary use for that syntax
table.  The main reason for that syntax table is its use in abbrev
expansion.  In as far as I see, there is nothing wrong with the syntax
table itself.  Instead, there is something wrong with the way it is
used at places were it should not be and there is something wrong with its
misleading documentation string.

I still use it, as well as mail-abbrev-syntax-table in my new package,
because they are essential for appropriate mailabbrev expansion.  My
package is (I hope) however a lot more careful about when they get
used.  I just changed the documentation string of
mail-mode-header-syntax-table to say that this syntax table is used for
mailabbrev expansion purposes.


       Does this version solve the problem?

I will not recopy the entire proposed (and apparently implemented in
Emacs21.2.50) version, just the function where I suspect trouble.
I added personal remarks in three key places:


(defun sendmail-pre-abbrev-expand-hook ()
  (and (and mail-abbrevs (not (eq mail-abbrevs t)))
       (if (mail-abbrev-in-expansion-header-p)

           ;; We are in a To: (or CC:, or whatever) header, and
           ;; should use word-abbrevs to expand mail aliases.
           (let ((local-abbrev-table mail-abbrevs)
                 (old-syntax-table (syntax-table)))

             ;; Before anything else, resolve aliases if they need it.
             (and mail-abbrev-aliases-need-to-be-resolved
                  (mail-resolve-all-aliases))

             ;; Now proceed with the abbrev section.
             ;;   -  We already installed mail-abbrevs as the abbrev
table.
             ;;   -  Then install the mail-abbrev-syntax-table, which
             ;;      temporarily marks all of the
             ;;      non-alphanumeric-atom-characters (the "_"
             ;;      syntax ones) as being normal word-syntax.  We do
this
             ;;      because the C code for expand-abbrev only works
on words,
             ;;      and we want these characters to be considered
words for
             ;;      the purpose of abbrev expansion.
             ;;   -  Then we call expand-abbrev again, recursively, to
do
             ;;      the abbrev expansion with the above syntax table.
             ;;   -  Restore the previous syntax table.
             ;;   -  Then we do a trick which tells the expand-abbrev
frame
             ;;      which invoked us to not continue (and thus not
             ;;      expand twice.) This means that any abbrev
expansion
             ;;      will happen as a result of this function's call
to
             ;;      expand-abbrev, and not as a result of the call to
             ;;      expand-abbrev which invoked *us*.

Personal Remark:

It "@" and "." had syntax "_" here, they would be set to "w" in the
mail-abbrev-syntax-table defined below, which is what should be
happening.  But they have syntax "." (see below) and it stays ".".

             (make-local-variable 'mail-abbrev-syntax-table)
             (unless mail-abbrev-syntax-table
               (let ((tab (copy-syntax-table old-syntax-table))
                     (_ (aref (standard-syntax-table) ?_))
                     (w (aref (standard-syntax-table) ?w)))
                 (map-char-table
                  (function (lambda (key value)
                              (if (equal value _)
                                  (set-char-table-range tab key w))))
                  tab)
                 (setq mail-abbrev-syntax-table tab)))

             ;; If the character just typed was
                non-alpha-symbol-syntax,
             ;; then don't expand the abbrev now (that is, don't
                expand
             ;; when the user types -.)  Check the character's syntax
                in
             ;; the usual syntax table.

Personal Remarks:

I guess "usual syntax table" means the mail mode or message mode
syntax tables.  The trouble with these is that several characters have
punctuation syntax in these tables that really should have symbol
constituent syntax in the following code.  Relevant for the concrete
examples we have been discussing are "@" and ".".  They are not the
only ones.  A complete (or at least, so I believe) list is provided in
the definition of mail-mode-header-syntax-table.  That is why that
syntax table is needed.  Forget about the stuff in the documentation
string.  In my version, I deleted that.

If "." had syntax "_", the next two lines of code would prevent it
from expanding abbrevs.  But it has syntax ".".  Hence it does expand
abbrevs.

             (or (and (integerp last-command-char)
                      (eq (char-syntax last-command-char) ?_))
                 (let ((pre-abbrev-expand-hook nil)) ; That's us;
                      don't loop.
                   ;; Use this table so that abbrevs can have hyphens
                      in them.
Personal Remarks:

The next line of code is were "@" and "." and friends are supposed to
get set to "w".  As explained above, this does not happen.
                      
                      (set-syntax-table mail-abbrev-syntax-table)

                   (unwind-protect
                       (expand-abbrev)
                     ;; Now set it back to what it was before.
                     (set-syntax-table old-syntax-table))))
             (setq abbrev-start-location (point-max) ; This is the
                      trick.
                   abbrev-start-location-buffer (current-buffer)))

         (if (or (not mail-abbrevs-only)
                 (eq this-command 'expand-abbrev))
             ;; We're not in a mail header where mail aliases should
             ;; be expanded, then use the normal mail-mode abbrev
                 table
             ;; (if any) and the normal mail-mode syntax table.
             nil
           ;; This is not a mail abbrev, and we should not expand it.
           ;; This kludge stops expand-abbrev from doing anything.
           (setq abbrev-start-location (point-max)
                 abbrev-start-location-buffer (current-buffer))))
       ))




reply via email to

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