I'm interested in configuring my Emacs environment to perform real-time compilation of a Standard ML buffer, on the event corresponding to a ";" character being entered (at the end of a line), such that the result of the compilation shows in a second buffer in a parallel window. The online SML interpreter SOSML (https://sosml.org/editor) does something like this, with the compiler output going in another text field on the same page. It is reactive this same way, using the ";" character.

I have been able to figure out how to compile SML in Emacs via a shell in a separate buffer and window (M-x run-sml), but only by explicitly entering commands when I'd like to compile an entire file. I do have SML Mode installed in Emacs and the text analysis is working well. But I'm struggling to find documentation about how Emacs might be able to watch a buffer and react in realtime to a character (such as ";") to trigger compilation of that same buffer in another buffer and window.

I appreciate any suggestions as to the appropriate convention and tool here.

  • Side comment: ; is used in SML only in those places where side effects are present, so some large chunks of SML code can go without any ; in sight.
    – Stefan
    Feb 18, 2020 at 20:42

2 Answers 2


A straightforward way to catch this ; is with:

(add-hook 'post-self-insert-hook #'sml-recompile-after-semicolon nil t)

where sml-recompile-after-semicolon would look like:

(defun sml-recompile-after-semicolon ()
  (when (eq last-command-event ?\;)
    ...trigger recompilation...))

To trigger recompilation you can probably call sml-compile or something like that, but you'll need to handle the usual problems of detecting if the previous recompilation is still in process (and deciding what to do about it).

Also you'll probably want to delay the actual recompilation a little bit rather than start it right then and there even before self-insert-command has finished execution. You can do that for example with run-with-idle-timer.


Stefan's answer is the correct logic, and that did it for me in a few lines of ELisp.

I used the commands run-sml and sml-prog-prog-send-buffer to send it to inferior mode in a parallel buffer window.

Eventually though I switched to a key binding, since the backtick "`" character on my keyboard is more ergonomic for this purpose than the semicolon ";" character.

(defun sml-keybinding-hook () "Bind backtick for quick compilation"
(setq sml-indent-level 2)
(global-set-key (kbd "`") 'sml-prog-proc-send-buffer)
(setq words-include-escape t)
(add-hook 'sml-mode-hook 'sml-keybinding-hook)

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.