Processes from Emacs

Keeping everything in Emacs opens up a world of possibilities, combined with a freedom found less and less in our virtual spaces. With this quick trick, you can run your (non-interactive) development processes displayed in a buffer as a child process of Emacs itself.

To make things easier, I rely on Projectile, and a few small helper functions. The first is +jcf-display-process.

;;;###autoload
(defun +jcf-display-process (command &rest args)
  (let* ((bufname (format "*%s*" (mapconcat 'identity (cons command args) " ")))
         (process (apply 'start-file-process command bufname command args)))
    (with-current-buffer (process-buffer process)
      (display-buffer (current-buffer))
      (comint-mode)
      (set-process-filter process 'comint-output-filter)
      (when (modulep! :editor evil)
        (evil-normal-state)))))

There are some Doom-isms in there to remove if you’re journeying alone, but the core sequence will be the same for all explorers.

  1. Define a name for our buffer that we can use to find our running process
  2. Start a new process using start-file-process
  3. Switch to and display the newly created buffer
  4. Activate comint-mode and filter output using comint to enable colourful output
  5. Switch to normal state as we’ll be navigating rather than inserting

With a helper like this autoloaded, functions like the one below that run a process at the root of the current project become a doddle.

(defun +jcf/devenv-up ()
  "Run \"devenv up\" in the current project."
  (interactive)
  (require 'projectile)
  (projectile-with-default-dir (projectile-ensure-project (projectile-project-root))
    (+jcf-display-process "devenv" "up")))

I bind the above to SPC p u to bring up my project, without leaving Emacs.