From 11c2b2239c9c7764320fed0a2014ec1e056d88dc Mon Sep 17 00:00:00 2001 From: Mark Harrah Date: Tue, 1 Mar 2011 08:51:14 -0500 Subject: [PATCH] continuous polling interval now in milliseconds --- main/Main.scala | 4 ++-- main/Project.scala | 22 ++++++---------------- main/Watched.scala | 16 +++++++++++----- util/io/SourceModificationWatch.scala | 6 +++--- 4 files changed, 22 insertions(+), 26 deletions(-) diff --git a/main/Main.scala b/main/Main.scala index d9544fcf4..ae6ecb475 100644 --- a/main/Main.scala +++ b/main/Main.scala @@ -11,7 +11,7 @@ package sbt import sbt.complete.{DefaultParsers, Parser} import Command.applyEffect - import Keys.{Analysis,HistoryPath,Logged,ShellPrompt,Watch} + import Keys.{Analysis,HistoryPath,Logged,ShellPrompt} import scala.annotation.tailrec import scala.collection.JavaConversions._ import Function.tupled @@ -197,7 +197,7 @@ object BuiltinCommands // TODO: nest def continuous = Command.single(ContinuousExecutePrefix, Help(continuousBriefHelp) ) { (s, arg) => - withAttribute(s, Watch.key, "Continuous execution not configured.") { w => + withAttribute(s, Watched.Configuration, "Continuous execution not configured.") { w => val repeat = ContinuousExecutePrefix + (if(arg.startsWith(" ")) arg else " " + arg) Watched.executeContinuously(w, s, arg, repeat) } diff --git a/main/Project.scala b/main/Project.scala index 5219ad7c7..fafe3bebb 100644 --- a/main/Project.scala +++ b/main/Project.scala @@ -75,13 +75,14 @@ object Project extends Init[Scope] val ref = ProjectRef(uri, id) val project = Load.getProject(structure.units, uri, id) logger(s).info("Set current project to " + id + " (in build " + uri +")") + def get[T](k: SettingKey[T]): Option[T] = k in ref get structure.data - val data = structure.data - val historyPath = HistoryPath in ref get data flatMap identity - val prompt = ShellPrompt in ref get data - val commands = (Commands in ref get data).toList.flatten[Command].map(_ tag (ProjectCommand, true)) + val historyPath = get(HistoryPath) flatMap identity + val prompt = get(ShellPrompt) + val watched = get(Watch) + val commands = get(Commands).toList.flatten[Command].map(_ tag (ProjectCommand, true)) val newProcessors = commands ++ BuiltinCommands.removeTagged(s.processors, ProjectCommand) - val newAttrs = s.attributes.put(Watch.key, makeWatched(data, ref, project)).put(HistoryPath.key, historyPath) + val newAttrs = setCond(Watched.Configuration, watched, s.attributes).put(HistoryPath.key, historyPath) s.copy(attributes = setCond(ShellPrompt.key, prompt, newAttrs), processors = newProcessors) } def setCond[T](key: AttributeKey[T], vopt: Option[T], attributes: AttributeMap): AttributeMap = @@ -89,17 +90,6 @@ object Project extends Init[Scope] def makeSettings(settings: Seq[Setting[_]], delegates: Scope => Seq[Scope], scopeLocal: ScopedKey[_] => Seq[Setting[_]]) = translateUninitialized( make(settings)(delegates, scopeLocal) ) - def makeWatched(data: Settings[Scope], ref: ProjectRef, project: Project): Watched = - { - def getWatch(ref: ProjectRef) = Watch in ref get data - getWatch(ref) match - { - case Some(currentWatch) => - val subWatches = project.uses flatMap { p => getWatch(p) } - Watched.multi(currentWatch, subWatches) - case None => Watched.empty - } - } def display(scoped: ScopedKey[_]): String = Scope.display(scoped.scope, scoped.key.label) def display(ref: ProjectRef): String = "(" + (ref.uri map (_.toString) getOrElse "") + ")" + (ref.id getOrElse "") diff --git a/main/Watched.scala b/main/Watched.scala index 7a07dbce4..def8c918d 100644 --- a/main/Watched.scala +++ b/main/Watched.scala @@ -5,13 +5,17 @@ package sbt import CommandSupport.{ClearOnFailure,FailureWall} import annotation.tailrec + import java.io.File trait Watched { /** A `PathFinder` that determines the files watched when an action is run with a preceeding ~ when this is the current * project. This project does not need to include the watched paths for projects that this project depends on.*/ - def watchPaths: PathFinder = Path.emptyPathFinder + 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 } object Watched @@ -21,24 +25,25 @@ object Watched def multi(base: Watched, paths: Seq[Watched]): Watched = new AWatched { - override val watchPaths = (base.watchPaths /: paths)(_ +++ _.watchPaths) + 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 } def empty: Watched = new AWatched - val PollDelaySeconds = 1 + val PollDelayMillis = 500 def isEnter(key: Int): Boolean = key == 10 || key == 13 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 = watched.watchPaths + val sourcesFinder = Path.finder { watched watchPaths s } val watchState = s get ContinuousState getOrElse WatchState.empty if(watchState.count > 0) System.out.println(watchState.count + ". Waiting for source changes... (press enter to interrupt)") - val (triggered, newWatchState) = SourceModificationWatch.watch(sourcesFinder, PollDelaySeconds, watchState)(shouldTerminate) + val (triggered, newWatchState) = SourceModificationWatch.watch(sourcesFinder, watched.pollInterval, watchState)(shouldTerminate) if(triggered) (ClearOnFailure :: next :: FailureWall :: repeat :: s).put(ContinuousState, newWatchState) @@ -49,4 +54,5 @@ object Watched } } val ContinuousState = AttributeKey[WatchState]("watch state") + val Configuration = AttributeKey[Watched]("watched-configuration") } \ No newline at end of file diff --git a/util/io/SourceModificationWatch.scala b/util/io/SourceModificationWatch.scala index 4b7e709bb..d6b6c7b70 100644 --- a/util/io/SourceModificationWatch.scala +++ b/util/io/SourceModificationWatch.scala @@ -7,7 +7,7 @@ package sbt object SourceModificationWatch { - @tailrec def watch(sourcesFinder: PathFinder, pollDelaySec: Int, state: WatchState)(terminationCondition: => Boolean): (Boolean, WatchState) = + @tailrec def watch(sourcesFinder: PathFinder, pollDelayMillis: Int, state: WatchState)(terminationCondition: => Boolean): (Boolean, WatchState) = { import state._ @@ -30,11 +30,11 @@ object SourceModificationWatch (true, newState) else { - Thread.sleep(pollDelaySec * 1000) + Thread.sleep(pollDelayMillis) if(terminationCondition) (false, newState) else - watch(sourcesFinder, pollDelaySec, newState)(terminationCondition) + watch(sourcesFinder, pollDelayMillis, newState)(terminationCondition) } } }