Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Fetching contributors…

Cannot retrieve contributors at this time

83 lines (73 sloc) 3.412 kb
/* sbt -- Simple Build Tool
* Copyright 2009, 2010 Mikko Peltonen, Stuart Roebuck, Mark Harrah
*/
package sbt
import BasicCommandStrings.ClearOnFailure
import State.FailureWall
import annotation.tailrec
import java.io.File
import Types.const
trait Watched
{
/** The files watched when an action is run with a preceeding ~ */
def watchPaths(s: State): Seq[File] = Nil
def terminateWatch(key: Int): Boolean = Watched.isEnter(key)
/** The time in milliseconds between checking for changes. The actual time between the last change made to a file and the
* execution time is between `pollInterval` and `pollInterval*2`.*/
def pollInterval: Int = Watched.PollDelayMillis
/** The message to show when triggered execution waits for sources to change.*/
def watchingMessage(s: WatchState): String = Watched.defaultWatchingMessage(s)
/** The message to show before an action is run. */
def triggeredMessage(s: WatchState): String = Watched.defaultTriggeredMessage(s)
}
object Watched
{
val defaultWatchingMessage: WatchState => String = _.count + ". Waiting for source changes... (press enter to interrupt)"
val defaultTriggeredMessage: WatchState => String = const("")
val clearWhenTriggered: WatchState => String = const(clearScreen)
def clearScreen: String = "\033[2J\033[0;0H"
private[this] class AWatched extends Watched
def multi(base: Watched, paths: Seq[Watched]): Watched =
new AWatched
{
override def watchPaths(s: State) = (base.watchPaths(s) /: paths)(_ ++ _.watchPaths(s))
override def terminateWatch(key: Int): Boolean = base.terminateWatch(key)
override val pollInterval = (base +: paths).map(_.pollInterval).min
override def watchingMessage(s: WatchState) = base.watchingMessage(s)
override def triggeredMessage(s: WatchState) = base.triggeredMessage(s)
}
def empty: Watched = new AWatched
val PollDelayMillis = 500
def isEnter(key: Int): Boolean = key == 10 || key == 13
def printIfDefined(msg: String) = if(!msg.isEmpty) System.out.println(msg)
def executeContinuously(watched: Watched, s: State, next: String, repeat: String): State =
{
@tailrec def shouldTerminate: Boolean = (System.in.available > 0) && (watched.terminateWatch(System.in.read()) || shouldTerminate)
val sourcesFinder = PathFinder { watched watchPaths s }
val watchState = s get ContinuousState getOrElse WatchState.empty
if(watchState.count > 0)
printIfDefined(watched watchingMessage watchState)
val (triggered, newWatchState, newState) =
try {
val (triggered, newWatchState) = SourceModificationWatch.watch(sourcesFinder, watched.pollInterval, watchState)(shouldTerminate)
(triggered, newWatchState, s)
}
catch { case e: Exception =>
val log = s.log
log.error("Error occurred obtaining files to watch. Terminating continuous execution...")
MainLoop.handleException(e, s, log)
(false, watchState, s.fail)
}
if(triggered) {
printIfDefined(watched triggeredMessage newWatchState)
(ClearOnFailure :: next :: FailureWall :: repeat :: s).put(ContinuousState, newWatchState)
}
else
{
while (System.in.available() > 0) System.in.read()
s.put(ContinuousState, WatchState.empty)
}
}
val ContinuousState = AttributeKey[WatchState]("watch state", "Internal: tracks state for continuous execution.")
val Configuration = AttributeKey[Watched]("watched-configuration", "Configures continuous execution.")
}
Jump to Line
Something went wrong with that request. Please try again.