Tooltip #3: entr
There’s nothing quite like tightening up your feedback loop between changing code and observing a program’s changed behavior to help you become and stay focused.
There are lots of tools out there meant to help with special cases of this, like guard
, but setting them up can be a bit inconvenient. Knowing this, some of the more mature build tools and test runners have --watch
options built in to make it easy to rerun a command whenever any of its depended upon files change, but there, if you want a file change to trigger a command that the tool doesn’t know how to run, you’re left with configuring a general purpose file watcher.
#Enter entr
The entr
utility is everything I wanted guard
to be. It is one of those tools that’s never anything but a pleasure to use. It fills a specific role, it’s reliable, and it has an absolutely minimal set of options (3!).
You use the CLI by piping into it a list of files you want it to watch, and you give it a command to run each time it notices a file has changed.
ls **/*.rb | entr rake spec
Nice! You can give it -c
option to clear the screen before running each command, to effectively anchor short output to the top of the terminal window. The -r
option tells it to kill and rerun the command in case it hasn’t exited by the time it sees the next file change, which is useful for things like opening a REPL or restarting a dev server.
ls **/*.rb | entr -r bundle exec foreman start
You can tell entr
to give your command a path to the file that changed with /_
.
ls **/*.rb | entr echo /_ changed
#Examples
The project page linked above and the manpage included with the tool itself both have great examples, but I’ll mix a couple of those with a couple of my own here.
To watch any file checked into your git
repo:
git ls-tree -r HEAD --name-only | entr -r rake spec
This one’s so handy I have an alias git ls
in my ~/.gitconfig
for it.
[alias]
ls = ls-tree -r HEAD --name-only
If your current task is scoped to certain files and you only want to run their tests, you can.
find app -name 'media*.rb' | entr rspec spec/**/media*.rb
I just found this when writing this post, but it looks like with chrome-cli it is dead simple to reload the current tab.
brew install chrome-cli
find . -name '*.sass' -or -name '*.coffee' | entr chrome-cli reload
You can only give entr
a single command, but you can mux multiple commands into a single string argument to your favorite shell.
git ls | entr -cr fish -c "rake spec; or say 'red alert! red alert!'"
That’s it for my examples! The ultimate example on the project page uses entr
to send a key to a tmux
pane running vim
to reload a vimdiff
session, but I haven’t taken it nearly that far yet.