Under-Appreciated Tools

inotifywait: How to Get Instant Refresh for LaTeX and HTML

Here we discuss how to use inotifywait and other command line tools to get instant refresh functionality when editing latex or HTML generating markup texts.

Ah, the joys of creating a document via editing of a plain text file using your editor of choice. Via straight-forwardness of Markdown or producing beautifully type set formulas with , the source of it all are text files that can be version controlled and processed using whatever command line tool you have come across recently.

But let’s be honest, not being able to obtain instant visually feedback is a disadvantage. Here (and I am tempted to say only here), the what you see is what you get (WYSIWYG) editor like MS Word excels.

When writing a blog entry using a locally served jekyll, this is actually not a problem, since jekyll detects when files change and regenerates the HTML pages accordingly.

Solution for LaTeX

Why isn’t there something like that for ? Well, one reason may be that output is typically not served via webservers. On the other side, there is no inherent reason, why you have to serve static HTML pages, when you could just load them in your browser.

So to answer the question and come to the point of the article: inotifywait to the rescue! The underlying library lets you subscribe for file system events. That is, it yields a file descriptor that can be polled. If the underlying file is modified, accessed or created (et cetera) the poll will succeed and you can handle the respective event.

So if you are working on a file hierarchy under your current working directory and you would like to compile your document main.tex using rubber, then the following code does the job:

while inotifywait -e modify,create -r .
    rubber main
  1. I highly recommend using rubber, latexmk or a customized Makefile that takes care of all the steps to produce a PDF. So far rubber has not let me down.

  2. -r sets up recursive watches.

  3. -e lets you subscribe the type of events.

  4. Do not rely on inotify for tricky multi-threaded things. You may miss events when a watch has not been set up or the file has been renamed or deleted before you become aware of it.

  5. Now you just need a PDF viewer like okular with auto-refresh and every save-document-action in your editor translates into a refreshed view of your PDF.

Solution for HTML

Well, that was refreshing to hear. LaTeX-to-PDF? Check. Can we do the same for HTML? Sure, whenever a HTML page is generated, we could just open a Tab in a browser. Actually refreshing an existing active Tab in a browser is a bit harder and requires xdotool. This utility essentially allows you to script window manager interaction. Thus, we can use xdotool to search for the chromium window, press F5 and switch back. Here is the full script, which assumes

  • that you dump the HTML output into /tmp/page.compiled/,
  • have opened a single chromium window,
  • have the tab of interest active in the window.
while inotifywait -e modify -r /tmp/page.compiled/
    curwin=$(xdotool getactivewindow)
    targetWin=$(xdotool search  --name " - Chromium" )

    if (( $(grep -c . <<<"$targetWin") > 1 )); then
        echo "Found multiple windows, please specify a more \
discriminative window title"
        exit 1

    # refresh target window
    xdotool windowactivate "$targetWin"  && xdotool key F5

    # switch focus back to original window 
    xdotool windowactivate "$curwin"

xdotool can be used for many interesting tasks. In this case, just be aware that selection of the correct window may require some calibration (see the definition of $targetWin).

Have you found other interesting use cases for the above mentioned tools? I would be delighted if you shared them by leaving a comment.

Post a Comment

All comments are held for moderation; Markdown formatting accepted;
By posting you agree to the following privacy policy.

This is a honeypot form. Do not use this form unless you want to get your IP address blacklisted. Use the second form below for comments.
Name: (required)
E-mail: (required, not published)
Website: (optional)
Name: (required)
E-mail: (required, not published)
Website: (optional)