Dec 07 2011

Windows CoffeeScript Auto-Compiler using Groovy and JDK 7 WatcherService

Published by at 10:19 am under CoffeeScript,Groovy,JDK 7

Update: Node.js for Windows has been improved since this post, so this information is obsolete. Last time I checked I was able to run CoffeeScript the same on Windows as I do on Linux and OSX.

If you’re using the CoffeeScript compiler for Windows (By Alexey Lebedev) you’ve probably noted a lack of a -w or “–watch” argument. These arguments can be very handy if you are working with a coffeescript file and want to quickly see the results of your edits. Given this lack of functionality and my desire to write some code in Groovy 1.8 using some of the NIO2 JDK 7 features I decided to write a little script that wraps this CoffeeScript compiler and fills in this missing feature.

If you’re following along at home you’ll want to download the above-mentioned CoffeeScript compiler and put it somewhere in your command path. Another useful piece of software is the Baretail executable. Baretail is a real-time log file reader for Windows. It’s, basically, a Windows GUI version of tail -f on a Unix system and allows you to see the output of your CoffeeScript compiler in real time. If you know of a better alternative to Baretail, please let me know.


So let’s dive right into the Groovy code:

import java.nio.file.FileSystemNotFoundException
import java.nio.file.FileSystems
import java.nio.file.Files
import java.nio.file.LinkOption
import java.nio.file.Path
import java.nio.file.Paths
import java.nio.file.WatchEvent
 
import static java.nio.file.StandardWatchEventKinds.*
import java.nio.file.WatchKey
import java.nio.file.WatchService
import java.nio.file.attribute.FileAttribute
import java.util.concurrent.TimeUnit
 
// #1
if (!(1..2).contains(this.args.length)) {
    println "Syntax: coffeewatch.groovy <source-path> [output-path]"
    println "If [output-path] not specified, 'js' dir will be created and used"
    return;
}
 
// #2
WatchService watcher = FileSystems.getDefault().newWatchService()
 
// #3
Path sourcePath = Paths.get(this.args[0])
if (Files.notExists(sourcePath, new LinkOption[0])) {
    println "source path ${this.args[0]} not found"
    return
}
 
// #4
Path outputDir = Paths.get((this.args.length == 1) ? "js" : this.args[1])
 
// #5
def brewCoffee = {
    def proc = """coffee.exe -c -o ${outputDir} ${this.args[0]}""".execute()
    println proc.in.text
}
 
// #6
if (Files.notExists(outputDir, new LinkOption[0])) {
    Files.createDirectory(outputDir, new FileAttribute<?>[0])
    brewCoffee()
}
 
// #7
sourcePath.register(watcher, ENTRY_CREATE, ENTRY_MODIFY);
 
// #8
for(;;) {
    WatchKey key = watcher.take()
    List<WatchEvent<?>> events = key.pollEvents();
    events.each { event ->
       brewCoffee()
       key.reset();
    }
}

The Groovy script you see here is akin to the bash or ksh scripts I used to write when I worked exclusively on Unix machines. Groovy makes a great drop-in replacement for bash, especially if you’re a Java developer. Anyway, the script takes two arguments: CoffeeScript source path and JavaScript output path.

Starting with #1, I’ve added a check to ensure that the correct number of command-line arguments were passed. Item #2 shows a way to get a WatchService reference. This is a new interface in Java 7 related to watching for file system events. In section #2 I’m using the NIO.2 AIP to check whether the coffeescript source directory exists. If it does exist the in section #4 I’m creating an output directory with the name specified or “js” if nothing is specified. Section #5 defines a closure that calls the Coffeescript compiler. Section #6 created the output directory if it doesn’t exist and does the initial COffeescript to JS compile. Section #7 registers the watcher and section #8 runs the compiler each time a CREATE or MODIFY event is detected. The script runs in an infinite loop and the pollEvents()method blocks until an event is received.

It’s nothing fancy, but it gets the job done. One caveat is that setting JAVA_HOME to point to JDK 1.7 broke Maven 3.x for me. I had to modify the Maven executable to set JAVA_HOME to JDK 1.6.



2 responses so far

2 Responses to “Windows CoffeeScript Auto-Compiler using Groovy and JDK 7 WatcherService”

  1. Linnon 18 Dec 2011 at 4:34 pm

    It’s been about a year in the Apple vs Samsung fight. Still no clear winner. Over and out.

  2. Tonyon 01 Jul 2012 at 10:51 am

    I’ve since just installed nodejs. The script was fun to write, but the Java file system watcher did not always behave how I wanted. For instance, I often got multiple events when a file was saved, thus causing multiple re-compiles for one file change.

Trackback URI | Comments RSS

Leave a Reply