entr as a test watcher
Published Feb 3, 2021
When I’m programming, I like to get feedback about my code as fast as possible. I like to learn about all of my bugs every time I’m “done thinking” (every time I save a file). Nowadays, LSP integrations have made it possible to get syntax and type checking on every keystroke, which is even faster than that! But everything else has to run on save.
When I discovered entr, I knew it would immediately change my workflow. I use it all the time for iterating on little one-off scripts. I edit in one terminal window and run this in another:
If it ever depends on multiple files (for larger projects or separate test data), I’ll combine it with fd like this:
But I ran into a problem using this when adding or removing files because entr (intentionally) doesn’t update the list of files by itself.
Its manual has an example for solving this (using its
-d option and a bash loop):
But I would sometimes get double-runs of my tests, which was weird and slow. So far, I’ve narrowed it down to an interaction between Neovim, ALE, Rubocop, and the write-tempfile-and-rename-into-place pattern for atomic rewrites. In other words, I have no idea.
But I do have a fix! The answer up front:
The trick turned out to be two parts:
-poption to delay execution until something changes.
- Accepting the limitation of needing to wait for a file save for the first test run.
Here’s how it works:
fd .finds all the files and directories starting from the current working directory.
entr -cdpdoes nothing yet because
-pmakes it wait for a change.
- I save a file or press Space.
entrnotices that, clears the screen (
-c), and runs
- If no directories changed (no files added or removed), goto 3.
- If a directory changed,
entrexits with status code 2 (which is falsy in bash), so
until’s condition has not been met.
- The body of the loop runs, so the
echomessage is printed.
untilloops, so goto 1.
I thought this was pretty clever, because the instructions are there when I run the command and when it “stops” on a directory change.
If you don’t like telling yourself what to do, replace the
echo command with
: (no-op) or