14

From time to time I happen to M-! some_command just to find that the command runs longer than I expected and keeps my emacs frozen for long seconds. So I glaze at my frozen emacs and kick myself for not using M-& some_command and promise myself to use M-& next time. But M-! is in my muscle memory for decades… And of course there is Ctrl-G, but there are cases when breaking command and re-running it is not preferable (mayhaps it may break sth, mayhaps would be costly to rerun…).

Similar mistake in shell konsole is trivial to correct, Ctrl-Z, bg and job is running in the background.

Does there exist some similar trick in emacs - a way to turn currently running foreground (synchronous) command into backgroundized (asynchronous) one?

Note: in case it is impossible for default M-!, I am open to suggestions of how to rebind M-! into something else (what would be functionally equivalent apart from this trick).

Mekk
  • 1,017
  • 7
  • 14
  • 2
    You may be interested to know that simply adding an `&` to the end of a regular `shell-command` (`M-!`) will make it asynchronous. Of course, you must do this before running a command, but at least you can use the same keybinding. – nanny Jul 07 '15 at 17:24
  • 4
    You could always just remap `M-!` to `async-shell-command`. :-) Seems like the only thing you lose is getting the output in the echo area when it is short enough. – glucas Jul 07 '15 at 19:33
  • 1
    @nanny, in fact, that's all `async-shell-command` does. It adds an `&` to the end of the `COMMAND` string and executes `shell-command`. – Matthew Piziak Jul 23 '15 at 16:47

1 Answers1

2

Does there exist some similar trick in emacs - a way to turn currently running foreground (synchronous) command into backgroundized (asynchronous) one?

I suspect no such trick exists. The problem is that the synchronous shell command (which is really call-process-region) blocks the emacs event loop. The only way to break it is to kill the process with a USR1 or USR2 signal or do C-g. (There may be other ways, but that's what I do).

This means there's nothing you can do because you don't have a way to invoke the trick, as Emacs does not process input while the event loop is stalled.


One thing you can do is simply swap the keys:

(global-set-key (kbd "M-!") #'async-shell-command)
(global-set-key (kbd "M-&") #'shell-command)
PythonNut
  • 10,243
  • 2
  • 29
  • 75
  • Rebinding M-! to async-shell-command makes partial sense, but: (1) I am not sure about M-1 M-! behaviour (command output to buffer) – simple fast cases work but what if the command is slower and I type sth? (2) in many cases I like the _freeze until command finishes_ behaviour as it gives clear finish indication (some commands have no output…), therefore explicit keystroke „put to background” would be nicer (3) async leaves those *Async* buffers which must be reaped – Mekk Jul 28 '15 at 05:30
  • I am thinking whether some wrapper around async-shell-command would be possible to write (a function which would spawn async-shell-command, then wait for it's finish, react to Ctrl-G by aborting command and to some other keystroke by leaving it running but not waiting anymore, and reap *Async* buffer once done if output is empty or short). I am not sure how to do that waiting part… – Mekk Jul 28 '15 at 05:34