Entr(1) – Run tests whenever files change
entrproject.org
entrproject.org
https://linux.die.net/man/7/inotify
https://en.wikipedia.org/wiki/Inotify
There is also a less well utilized fsnotify feature for filesystem-wide notifications. Here is a cross-platform go implementation which also supports OSX: https://github.com/fsnotify/fsnotify
Entr on the other hand works like a charm. You can see on the website that it details a number of edge cases with inotify that it works around. I'm not even sure it's an exhaustive list.
Also, inotify is suboptimal for this use case. inotify has no recursion support, which means that the user must keep a watch on all files individually. There is also a limit to the number of inotify watches that can be in place at any one time.
A more modern, and more suitable interface for this use case is fanotify[0]. It doesn't provide all the functions that inotify does, but importantly it supports recursion, which alone would seem to make it a more obvious choice for this task.
Any more information on this? I'm curious to read why.
fanotify is not an alternative because it cannot monitor file deletion or renames and it requires root permission.
If it doesn't care what file is modified and just wants to run a command on any change, why would it need to do this?
Another use-case is a desktop search tool.
$ fswatch -0 -event ./main.lua | xargs -0 -n 1 -I {} lua ./main.luaentr is cross-platform on OS X, linux and BSD.
watching_testrunner has no BSD support
watchman is way too big and not domain specific enough to my needs
sniffer worked quite well but it required having a scent.py file everywhere
entr keeps it all in a neat, unix like package you can pipe files to.
I keep some example usage in my book, The Tao of tmux at https://leanpub.com/the-tao-of-tmux/read#leanpub-auto-file-w.... In this section I demonstrate my workflow with entr(1) in a Makefile. The code I use in the example should work across OS X / BSD / Linux (note the utilities like find(1) may behave a bit differently across unix-like systems).
I use the Makefile w/ entr(1) in development on my projects like tmuxp at https://github.com/tony/tmuxp/blob/master/Makefile. tmuxp is BSD-licensed so you're free to work off that if you'd like to try it on your own project.
ls -d * | entr make
Just a nit: this seems to be imperfect for filenames containing new lines (I know, I know). An xargs like -0, --null option could make it more robust. Then the equivalent of the above command would be something like: find . -maxdepth 1 -name '[!.]*' -print0 | entr -0 make
Edit: Seems like -print0 is not POSIX compliant. Is there any safe way to pass a list of paths using the shell in a fully POSIX compliant way?Nitpicking… or maybe not: if you take the habit of running `cmd * ` whatever the command, I guess you might end up writing dangerous things like `rm * ` in a script which will fatally end up running in a directory containing a file named “-R”.
printf '%s\0' * | xxdOne note: the browser reloading script was not installed on debian, so I downloaded it. It was not clear from the documentation if that was the intention.
And it also doesn't run coverage checks, it's only for running the test i'm currently working on.
But yes, the ruby infrastructure is pretty bloated i recon.
Much simpler than most tools I've seen like it.
This is true if all that happens is a page reload, butamy frameworks are able to patch code or styles into the running page without a reload. This requires more than a signal handler.
It felt like this kind of tool would/should be one of those standard command line tools always available, or the at least of those standard things everyone knows to install, like silversearcher/ripgrep etc.
What would be really great is a fuse DAG.
Some paths should run programs on write, others on read.
The filesystem is already the lock provider for a lot of programs; we should be using it as the event processor.
This is inherently polyglot -- every programming language in common use has FS utils.
You might even try to limit which tests to run based on the test coverage (from previous runs) of the changed functions or statements.
And then there's also ideas like LightTable's inline evaluation [1].