bitbucket/overview | download 3.0
$ find . -name '*.c' | entr make
$ ls *.md | entr +notify & $ while read F; do > markdown2html $F > done < notify
Interactive SQL: OGG (47.0M, theora-vorbis) | WEBM (14.2M, vp8-vorbis)
The Event Notify Test Runner is a general-purpose Unix utility intended to make rapid feedback and automated testing natural and completely ordinary.
$ ls *.css *.html | entr reload-browser Firefox
reload-browser is a script bundled with the 3.0 release which uses xdotool or AppleScript to send a refresh keystroke to the active tab in your browser.
It is not uncommon for modern web frameworks to continuously hunt for file system changes and auto-reloads when run in single threaded or standalone mode. This functionality is superfluous if the application can respond to signals. The following will reload nginx every time the configuration is modified:
$ ls /etc/nginx/nginx.conf | entr pkill -HUP nginx
entr is a zero-configuration tool with no external build or runtime dependencies. The interface to entr is not only minimal, it aims to be simple enough to create a new category of ad hoc automation. These micro-tests reduce keystrokes, but more importantly they emphasize the utility of automated checks.
Tightening the edit-test feedback loop requires a tool that is tuned for one task. inotifywait is lightweight, but it only works on Linux, and does not provide a direct means of saying “run this command if any of these files change”. In practice scripting with inotify-tools is difficult because there are a number of significant conditions to contend with:
Finally, FIFO mode provides a means of creating more sophisticated scripts by relaying the names of altered filenames through a named pipe. The watch script is a nice example of this feature in use.
entr adheres to the principle of separation of concerns, yet the reload (-r) option was added to solve a common use case that would otherwise require some careful scripting:
$ ls *.rb | entr -r ruby main.rb
Other special-purpose flags were added because they reduce highly repetitive actions or reduce friction. One of the most repetitive actions was to clear the screen before running tests; hence the -c flag:
$ find src/ | entr -c ./test.sh
The special /_ argument (somewhat analogous to $_ in Perl) provides a quick way to refer to the first file that changed. When a single file is listed this is a handy way to avoid typing a pathname twice:
$ echo /tmp/my.sql | entr psql -f /_
In the 2.9 release, a directory watch option (-d) was added to react to events when a new file is added to a directory. It was determined early on that entr would not implement it's own file search syntax, relying on standard Unix tools instead. The implication of this is that if a new file appears it must exit and allow an external shell loop to rescan the file system. One way to implement this feature would be to simply require the users to list directories:
$ while sleep 1; do > ls -d src/*.py src | entr ./setup.py > done
This is “correct” from a POSIX point of view, but in addition to forcing the user to spend time thinking about how how options in ls interact with shell globing, using find to accomplish a similar task suddenly becomes difficult.
In this instance entr leans heavily on the principle of least surprise. The promise to the user is simply to “run the utility if a new file is added to the project”. The previous example works, and so does this:
$ while sleep 1; do > ls src/*.py | entr ./setup.py > done
In directory watch mode the parent directory of each file is implicitly added to the watch list. This behavior is very unusual for a command line tool, but in practice it behaves as most users would expect.
Finally, the sharp edges of shell scripting were removed by providing a well-behaved example in the man page. Using sleep 1 as the test condition for the while loop prevents repeat failures from pegging the CPU and it allows the user to break out with Ctrl-C.
I have written as if incorporating automated responses can be accomplished without special demands on the Unix development environment, but in practice the ability to split a window into multiple panes is the key to making this workflow efficient. A window manager such as i3 or the terminal multiplexer tmux enables you to quickly spit the screen so that you can see the results as you work.
tmux steps automation up to the next level by enabling you to control applications in other panes via keystrokes. This combination can be wired up in any number of ways to create some very interesting auto-responders. Consider the following
With this mechanism in place we can fetch and compare headers using any tool capable of printing output or writing to a file—no plugins or specialized functionality required.