Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
xsbt coffee script plugin (example) using sourceGenerators
import sbt._
import Keys._
import Process._
import Project.Initialize
object CoffeeScriptPlugin extends Plugin {
val coffeeSource = SettingKey[File]("coffee-source", "Directory containing coffee files.")
val coffeeTarget = SettingKey[File]("coffee-target", "Output directory for translated coffee scripts.")
val coffeeClean = TaskKey[Unit]("coffee-clean", "Clean just the files generated from coffee sources.")
val coffee = TaskKey[Unit]("coffee", "Compile the coffee sources.")
private def base (file: File) = file.getName.toString.substring(0, file.getName.toString.lastIndexOf("."))
private def javascript(coffee: File, targetDir: File) =
new File(targetDir, base(coffee) + ".js")
private def outdated (coffee: File, javascript: File) =
(! javascript.exists) || (coffee.lastModified > javascript.lastModified)
private def compile (coffee: File, target: File, out: Logger) {
val cmd = "coffee --compile --output %s %s".format(target, coffee)
val rc = Process(cmd).run.exitValue()
private def compileChanged (sources: File, target: File, out: Logger) = {
for (coffee <- sources.listFiles)
if (outdated(coffee, javascript(coffee, target)))
compile(coffee, target, out)
private def coffeeCleanTask: Initialize[Task[Unit]] =
(streams, coffeeTarget) map {
(out, target) =>"Cleaning " + target)
// Note: the sourceGenerator task returns an empty list because we
// don't want SBT to invoke the scala compiler on Javscript files.
private def coffeeSourceGeneratorTask: Initialize[Task[Seq[File]]] =
(streams, coffeeSource, coffeeTarget) map {
(out, sourceDir, targetDir) =>
compileChanged(sourceDir, targetDir, out.log)
private def coffeeTask: Initialize[Task[Unit]] =
(streams, coffeeSource, coffeeTarget) map {
(out, sourceDir, targetDir) =>
compileChanged(sourceDir, targetDir, out.log)
// Use declarations here just as you would in build.sbt.
override def settings = Seq (
coffeeSource <<= (baseDirectory) { (d) => new File(d, "/src/main/coffee") },
coffeeTarget <<= (baseDirectory) { (d) => new File(d, "/src/main/www/js") },
cleanFiles <+= (coffeeTarget) { (t) => t},
coffeeClean <<= coffeeCleanTask,
coffee <<= coffeeTask,
sourceGenerators in Compile <+= coffeeSourceGeneratorTask
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment