1

I have wrote the following abbrev definition file, and saved it as my_abbrev.el:

(define-abbrev-table 'global-abbrev-table '(
    ("else__" "else begin

end")
    ))

;; turn on abbrev mode globally
(setq-default abbrev-mode t)

I loaded it from my init.el:

(load-file "~/.emacs.d/my_abbrev.el")

However, when typing "else__" followed by a space, it is not expanding. when evaluating the expression list-abbrev, I see the following (as I expected):

(global-abbrev-table)

"else__"       0    "else begin

end"

What am I missing? why is my abbrev not expanding?

1

If (abbrev-table-get global-abbrev-table :regexp) is nil the abbreviation before point is determined by backward-word and forward-word (see doc of define-abbrev-table).

But in most major modes the underscore _ will not have word syntax.

First, we need to accept symbols as abbreviations. Abbrev-tables have a regular expression that matches abbreviations with looking-back in expand-abbrev:

(abbrev-table-put global-abbrev-table :regexp "\\_<\\(\\(?:\\sw\\|\\s_\\)+\\)")

expand-abbrev is run in self-insert-command. Relevant part of the doc of self-insert-command:

Before insertion, ‘expand-abbrev’ is executed if the inserted character does not have word syntax and the previous character in the buffer does.

So we have still the problem that after typing else__ the char before point does not have word syntax. There are two ways of solving it:

  1. You change your abbrev to something like else_a (the last a standing for abbrev). The last character before point is word consistent and the expansion will work after hitting space or newline.
  2. Keep else__ as abbreviation and use a similar solution as in another answer about abbrev:
(defvar pre-self-insert-hook nil
  "Normal hook run before `self-insert-command'.")

(defun run-pre-self-insert-hook (&rest args)
  (run-hooks 'pre-self-insert-hook))

(advice-add 'self-insert-command :before #'run-pre-self-insert-hook)

(defun my-symbols-expand-abbrev ()
  "Also expand if the preceeding char has symbol syntax."
  (when (and (eq (char-syntax (aref (this-command-keys-vector) 0)) ?\s)
         (char-before) ;; avoid error at beginning of buffer
         (eq (char-syntax (char-before)) ?_))
    (expand-abbrev)))

(add-hook 'pre-self-insert-hook #'my-symbols-expand-abbrev)

Comments:

  1. Consider to expand else__ only in those major modes where it makes sense.
  2. Consider using the library skeleton.el instead of abbrev.el. You can define skeletons with define-skeleton and use them with skeleton-insert. Skeletons allow you to place point easily between begin and end. Furthermore it allows you to indent and format the source code automagically.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.