5

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.

2 Answers2

5

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))
    (expand-abbrev)))

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

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"
  (interactive)
  (insert "e")
  (expand-abbrev))

(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"
  (interactive)
  (insert "e")
  (when (save-excursion
          (backward-char)
          (looking-back (regexp-opt e-expansion-prefixes) 1))
    (expand-abbrev)))