It's definitely possible. Here is my initial attempt at creating the 3 window split with a jest test runner, a source file, and it's associated spec file. You can put this code in your config and try it out via M-x jest-open.
(defun jest-spec-for-file (file)
"Given a file, return its matching spec file."
(let* ((dirname (file-name-directory file))
(filename (file-name-nondirectory file))
(ext (file-name-extension file))
(basename
(replace-regexp-in-string (concat "." ext "$") "" filename)))
(concat dirname basename ".spec." ext)))
(defvar jest-command "jest --watch"
"This is the shell command used to run jest.")
(defun jest-run (&optional term)
"Switch to the jest buffer if it exists or create a new one."
(interactive)
(if (get-buffer "jest") (switch-to-buffer "jest")
(cond ((equal term 'vterm)
(progn
(vterm "jest")
(vterm-send-string (concat jest-command "\n"))))
(t
(progn
(term "/bin/bash")
(rename-buffer "jest")
(term-send-raw-string (concat jest-command "\n"))
))
)))
(defun jest-open (file)
"Create a 3 window layout containing jest|source|spec."
(interactive "f")
(let* ((spec (jest-spec-for-file file)))
(delete-other-windows)
(split-window-right)
(split-window-right)
(jest-run) ; change this to (jest-run 'vterm)
(windmove-right)
(find-file file)
(windmove-right)
(find-file spec)
(windmove-left)))
How It Works
We have 3 functions and a variable.
(jest-spec-for-file file)
Return the spec file associated with file
.
This is just pure string manipulation that takes a string like /tmp/index.js
and returns /tmp/index.spec.js
.
jest-command
This variable contains the shell command used to invoke jest. Feel free to adapt it to your needs.
(jest-run &optional term)
If a buffer named "jest" exists, switch to it. Otherwise, create a term (or vterm) buffer and run jest-command
inside of it. I have it default to use term
since it's included with stock emacs, but I highly recommend giving vterm a try. Anything that's even slightly animated will look better in vterm. When you're ready to make the switch, change the line that says:
(jest-run)
to
(jest-run 'vterm)
Also, keep in mind that if you hit q to stop jest, this function won't try to restart it. Once the jest buffer is created, all control is deferred to you.
(jest-open file)
Finally, we have the function that creates the 3 window split and sets up the buffers such that you have a jest test runner on the left, the source in the middle, and a spec file on the right. It will also place the focus on the middle window, because I think that's what would be most intuitive.
You can give it a try by hitting M-x jest-open and selecting a file when prompted. If you end up wanting to use this frequently, you can bind it to a key. You can do it the doom way too.
PS
I tried to write this in a way that works in any Emacs configuration. It should work just fine in Doom. As you explore this code (or any other elisp), I encourage you to use C-h f look up the docs for functions. I also like using M-x ielm to start up an interactive elisp repl to feel how things work. Doing this really accelerated my elisp self-education.