Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do you write a Scala script that will react to file changes

Tags:

scala

I would like to change the following batch script to Scala (just for fun), however, the script must keep running and listen for changes to the *.mkd files. If any file is changed, then the script should re-generate the affected doc. File IO has always been my Achilles heel...

#!/bin/sh
for file in *.mkd
do
  pandoc --number-sections $file -o "${file%%.*}.pdf"
done

Any ideas around a good approach to this will be appreciated.

like image 520
Jack Avatar asked Nov 06 '13 08:11

Jack


People also ask

What is Scala Script?

Scala combines object-oriented and functional programming in one concise, high-level language. Scala's static types help avoid bugs in complex applications, and its JVM and JavaScript runtimes let you build high-performance systems with easy access to huge ecosystems of libraries.


1 Answers

The following code, taken from my answer on: Watch for project files also can watch a directory and execute a specific command:

#!/usr/bin/env scala

import java.nio.file._
import scala.collection.JavaConversions._
import scala.sys.process._

val file = Paths.get(args(0))
val cmd = args(1)
val watcher = FileSystems.getDefault.newWatchService

file.register(
  watcher, 
  StandardWatchEventKinds.ENTRY_CREATE,
  StandardWatchEventKinds.ENTRY_MODIFY,
  StandardWatchEventKinds.ENTRY_DELETE
)

def exec = cmd run true

@scala.annotation.tailrec
def watch(proc: Process): Unit = {
  val key = watcher.take
  val events = key.pollEvents

  val newProc = 
    if (!events.isEmpty) {
      proc.destroy()
      exec
    } else proc

  if (key.reset) watch(newProc)
  else println("aborted")
}

watch(exec)

Usage:

watchr.scala markdownFolder/ "echo \"Something changed!\""

Extensions have to be made to the script to inject file names into the command. As of now this snippet should just be regarded as a building block for the actual answer.

Modifying the script to incorporate the *.mkd wildcards would be non-trivial as you'd have to manually search for the files and register a watch on all of them. Re-using the script above and placing all files in a directory has the added advantage of picking up new files when they are created.

As you can see it gets pretty big and messy pretty quick just relying on Scala & Java APIs, you would be better of relying on alternative libraries or just sticking to bash while using INotify.

like image 55
tzbob Avatar answered Nov 15 '22 10:11

tzbob