The BackgroundManager class is something I have vaguely dreamed about for decades. It handles all details of running separate processes in the background without blocking Leo.
Previous efforts were feeble. They merely provided a thin (useless!) wrapper around subprocess.Popen.
The BackgroundManager is much more capable. It manages a queue of background processes, and runs them one after another
in the background. It registers a handler with the IdleTimeManager
that checks to see if the presently running background process has
completed. If so, it writes its output to the log and starts another
background process in the queue.
Because only one background process from the queue is ever running, the background processes can to write their output to Leo's log without the output becoming intermixed.
You can kill all processes by calling BM.kill(). That's what the 'kill-pylint' command does. You can add processes to the queue at any time. For example, you can rerun the 'pylint' command while a background process is running.
The BackgroundManager is completely safe: all of its code runs in the main process.
Improvements
Ah, the joys of documentation. As I write this, I realize that it would be better to use a singleton BackgroundManager, say g.app.backgroundManager. This
would allow multiple kinds of background processes to coexist peacefully without intermixed output.
The following relatively minor changes are needed:
1. BM.start_process already can handle process corresponding to different commands passed to subprocess.Popen. However, the queue must be upgraded so it knows the type of each queued process. That is, a 'kind' argument should be added to BM.start_process.
2. Add a corresponding 'kind' argument to BM.kill. This would kill the queued processes of the given type, or all queued processes if the 'kind' is None or 'all'.
Another possible improvement: optionally run shlex on the command argument passed to BM.start_process.
At present, the 'pylint' command creates a string the hard, hard way. That probably won't change, but it might be possible to simplify command creation using shlex. The jury is still out on this one.
Summary
For the first time, there is an easy way of running processes safely in the background.
Relatively easy changes will allow background processes of different kinds to be run sequentially.
This removes another source of Emacs envy ;-)
Edward