How can I expand oe to ö immediately after hitting the e without hitting any extra key like space for expansion?

Why? For better ergonomics I've remapped some keys like ö, ü and thus must write them with oe and ue.

  • 5
    What do you think about changing the input-method instead of using abbrevs? C-x RET C-\ german-postfix
    – Marco Wahl
    Jun 24 '19 at 14:48

Out of the box it is not possible with the abbrev system since self-insert-command calls expand-abbrev only when a non-word character is to be inserted. Citation from the doc string of expand-abbrev:

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 to put a before-advice on self-insert-command that also calls some kind of expand-abbrev on characters with word syntax.

We should keep that mechanism as local as possible to avoid an errornous abbrev system.

  1. We introduce a new buffer local variable abbrev-in-word-regexp. Only text that matches this regexp is expanded mid-word.
  2. We do not add our expand-abbrev directly to self-insert-command but add a hook pre-self-insert-command-hook. We can add our stuff there buffer-locally.
  3. We setup the expansion in the hook variable of the major mode.
(defvar-local abbrev-in-word-regexp nil
  "Run `expand-abbrev' if text before point matches this regexp.")

(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-in-word-expand-abbrev ()
  "Run `expand-abbrev' when text before point matches `abbrev-in-word-regexp'."
  (when (looking-back abbrev-in-word-regexp (line-beginning-position))

(defun my-text-mode-setup ()
  "Work to be done in `text-mode-hook'."
  (setq abbrev-in-word-regexp "\\([aou]e\\)")
  (add-hook 'pre-self-insert-hook #'my-in-word-expand-abbrev nil t))

(add-hook 'text-mode-hook #'my-text-mode-setup)

You could try something like this: add additional behavior to "e" itself. Make it insert by default, but try to expand otherwise

(defun e-insert-or-expand ()
  "Insert 'e', and if it is part of an abbrev, expand the abbrev"
  (insert "e")

(global-set-key "e" 'e-insert-or-expand)

If you want to refine this to only happening when you are behind a valid expansion prefix (o or u) you could do something like

(defvar e-expansion-prefixes '("o" "u"))

(defun e-insert-or-expand ()
  "Insert 'e', and if it is part of an abbrev, expand the abbrev"
  (insert "e")
  (when (save-excursion
          (looking-back (regexp-opt e-expansion-prefixes) 1))

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.