The https://www.emacswiki.org/emacs/AbbrevMode says

You can have different abbrevs for each mode (cperl, c++, Message);

but it doesn't show exactly how, yet that's exactly what I am looking for. So,

I found the following code from here,

(setq xem-abbrev-table nil)

(define-abbrev-table 'xem-abbrev-table
    ("`d" "(defun f▮ ()\n  \"DOCSTRING\"\n  (interactive)\n  (let (VAR)\n\n  ))" )
    ("`i" "(insert ▮)" )
    ("`l" "(let (x▮)\n x\n)" )
    ("`m" "(message \"%s▮\" ARGS)" )
    ("`p" "(point)" )
    ("s" "(setq ▮ VAL)" )
    ("w" "(when ▮)" )
    ("bsnp" "(buffer-substring-no-properties START▮ END)" )
    ;; hundreds more
  "Abbrev table for `xem'"

(abbrev-table-put xem-abbrev-table :regexp "\\([_-*0-9A-Za-z]+\\)")
(abbrev-table-put xem-abbrev-table :case-fixed t)
(abbrev-table-put xem-abbrev-table :system t)

(define-derived-mode xem prog-mode "∑lisp"
  "A major mode for emacs lisp...."

  (abbrev-mode 1)

  :abbrev-table xem-abbrev-table ; actually, we don't need this line, because our name is “xem” + “-abbrev-table” so define-derived-mode will find it and set for us

Q1: I want to change it to a minor mode for the elisp major mode, how to do that? Please be specific, as I know the question is quite similar with How to use abbrev with different configuration for each mode? but I don't understand the replies there as I don't know elisp except copying from working code.

Q2: Note the first several abbreviations have leading "`", that's what the prefix I want all my abbreviations to start with, but it's not working, maybe because of Alternative to abbrev-mode that supports special characters in abbreviations? however, I really don't understand the elisp code there. So, can you make the above code work with leading "`" as abbreviations prefix please?


Using an abbreviation prefix comes from https://www.emacswiki.org/emacs/AbbrevMode as well:

    ;;; sample abbrev definitions
    (eval-after-load "cc-mode"
      '(declare-abbrevs (c-mode-abbrev-table c++-mode-abbrev-table)
           (("#s"    "#include <>" "C-b")
            ("#i"    "#include \"\"" "C-b")
            ("#ifn"  "#ifndef")
            ("#e"    "#endif /* */" "C-3 C-b")
            ("#ifd"  "#ifdef")
. . .

However, that's not exactly what I was looking for, defining different abbrevs for each mode, because "The third column is a series of keystrokes you should have issued after the expansion".

1 Answer 1


As you've seen, abbrev normally requires the abbreviation to contain only word-constituent characters, and that doesn't normally include `. You could make that character word-constituent by changing its syntax for the mode in question, but I believe it would be better to adapt abbrev (only) to your requirement (as lots of things are affected by syntax).

You may find this suitable:

(defvar my-abbrev-regexp
  (rx (or bol (not (any "`" wordchar)))
      (group (one-or-more (any "`" wordchar)))
      (zero-or-more (not (any "`" wordchar))))
  "Use as :regexp in abbrev tables to make \\=` a valid abbrev char.

If `words-include-escapes' is used then this regexp can fail.
Refer to the elisp comments in `abbrev--before-point' for details.")

And then to use it in emacs-lisp-mode:

(abbrev-table-put emacs-lisp-mode-abbrev-table :regexp my-abbrev-regexp)
(define-abbrev emacs-lisp-mode-abbrev-table "`foo" "bar")
(add-hook 'emacs-lisp-mode-hook #'abbrev-mode)

To use it with a mode which is not loaded by default, you would do something like this:

(with-eval-after-load "sh-script"
  (abbrev-table-put sh-mode-abbrev-table :regexp my-abbrev-regexp)
  (define-abbrev sh-mode-abbrev-table "`foo" "bar")
  (add-hook 'sh-mode-hook #'abbrev-mode))

Where "sh-script" is the name of the library (sans .el extension or similar) in which the major mode sh-mode is defined, as indicated by C-hf sh-mode.

Note that you don't need to define a minor mode. Every major mode has an abbrev table, which is available for you to use provided that the library defining the major mode has been loaded (hence the use of with-eval-after-load for things which aren't loaded by default).

  • Thanks for such comprehensive answer, which even includes the answer to the question "to use it with a mode which is not loaded by default" that I will be asking as the follow up 😁🙏
    – xpt
    Jun 23, 2021 at 13:34
  • I have a follow up question phils, at emacs.stackexchange.com/questions/66548/…. Really hoping that can be fixed as well. thx!
    – xpt
    Jul 1, 2021 at 15:50
  • An additional note about this general approach: The self-insert-command only triggers abbrev expansion if the previous character has word syntax; so even with a custom regexp, the abbrev still needs to end with a word char in order for automated expansions to do their thing.
    – phils
    Dec 12, 2021 at 14:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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