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 Answers1

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.
Tobias
  • 32,569
  • 1
  • 34
  • 75