4

Q: how does one approximate the functionality of the non-existent pre-self-insert-hook?

This question is inspired by the curiosity that is the combination of abbrev-mode and self-insert-command. The docstring for the latter:

Insert the character you type.

Whichever character you type to run this command is inserted. Before insertion, expand-abbrev is executed if the inserted character does not have word syntax and the previous character in the buffer does. After insertion, the value of auto-fill-function is called if the auto-fill-chars table has a non-nil value for the inserted character. At the end, it runs post-self-insert-hook.

It looks to be the case that the call to expand-abbrev is baked directly into self-insert-command -- I assume for efficiency reasons, because it is ancient, or both (feel free to comment if you happen to know why). Ordinarily, I would have expected such a function to run via a hook. However, although there is a post-self-insert-hook, there is no pre-self-insert-hook.

In the absence of such a hook, how does one approximate that functionality, and, more importantly, do so with a minimum of fuss?

None of the options I can think of are ideal:

  • advice: self-insert-command is a primitive defined in C and therefore ignores advice
  • pre-command-hook: simple, but it's overkill because it runs before every command, and not just self-insert-command, and one may only want to run the command as part of self-insert-command
  • define a wrapper around self-insert-command: this appears to be what org-mode and smartparens do (with org-self-insert-command and sp--self-insert-command), but seems complicated by the fact that a) you'd need to rebind an awful lot of keys to use it, b) if one uses multiple major or minor modes that use their own wrapper functions, one needs to keep track of fallback functions so that one does not lose the functionality of other wrappers when rebinding keys (at least I think so; I'm not so sure I understand this part).
Dan
  • 32,584
  • 6
  • 98
  • 168
  • Actually, it's not **so** ancient. It was apparently added in Emacs 23. Dunno why. Seems like `self-insert-command` should only, well, self-insert... You might want to ask `emacs-devel@gnu.org` your question (and why `self-insert-command` does `expand-abbrev`). – Drew Apr 05 '15 at 00:40
  • Well, you *used to be able to advise primitives* defined in C. (On n'arrete pas le progres.) You can still, however, advise `expand-abbrev` - does that help? – Drew Apr 05 '15 at 00:41
  • Define a new input method? I mean, you could define an input method to use your function before self-inserting command, so that would be equivalent to having a `before-` hook. – wvxvw Apr 05 '15 at 05:05
  • You *can* advise functions *defined* in C, but the advice won't apply if it's *called* from C. – npostavs Apr 05 '15 at 18:57
  • @dan (thinking out loud) What about an input-method? – PythonNut Apr 06 '15 at 05:26
  • Fiddling about with `self-insert-command` directly will not work. Section `23.3.2 Keymaps and Minor Modes` of the manual states: `Do not try substituting your own definition of `self-insert-command' for the standard one. The editor command loop handles this function specially.` – Tobias Apr 06 '15 at 05:27

1 Answers1

5

You can advise self-insert-command just fine. In older Emacsen, it was sometimes (often) called directly from C, but since Emacs-24 (IIRC) it's never called directly from C, so the advice should work reliably.

Stefan
  • 26,154
  • 3
  • 46
  • 84