diff --git a/main/CommandSupport.scala b/main/CommandSupport.scala index 041ad5869..cd7163828 100644 --- a/main/CommandSupport.scala +++ b/main/CommandSupport.scala @@ -51,8 +51,27 @@ DelegatesCommand + """ This command prints the scopes that are searched for the key. """ + val LastGrepCommand = "last-grep" + val lastGrepBrief = (LastGrepCommand + " ", "Shows lines from the last output for 'key' that match 'pattern'.") + val lastGrepDetailed = +LastGrepCommand + """ + + is interpreted as a Scala expression of type sbt.Scoped and is typically a task key. + is a regular expression interpreted by java.util.Pattern + Lines that match 'pattern' from the last streams output associated with the key are displayed. + See also """ + LastCommand + "." + + val LastCommand = "last" + val lastBrief = (LastCommand + " ", "Prints the last output associated with 'key'.") + val lastDetailed = +LastCommand + """ + + is interpreted as a Scala expression of type sbt.Scoped. + The last streams output associated with the key (typically a task key) is redisplayed. + See also """ + LastGrepCommand + "." + val GetCommand = "get" - val getBrief = (GetCommand + " ", "Prints the value for the given key, the defining scope, related definitions, and dependencies.") + val getBrief = (GetCommand + " ", "Prints the value for 'key', the defining scope, related definitions, and dependencies.") val getDetailed = GetCommand + """ diff --git a/main/Main.scala b/main/Main.scala index f8c3fcaef..9cecb2db0 100644 --- a/main/Main.scala +++ b/main/Main.scala @@ -59,7 +59,7 @@ class xMain extends xsbti.AppMain object BuiltinCommands { def DefaultCommands: Seq[Command] = Seq(ignore, help, reload, read, history, continuous, exit, loadCommands, loadProject, compile, discover, - projects, project, setOnFailure, ifLast, multi, shell, set, get, eval, delegates,alias, append, nop, sessionCommand, act) + projects, project, setOnFailure, ifLast, multi, shell, set, get, eval, delegates,alias, append, last, lastGrep, nop, sessionCommand, act) def nop = Command.custom(s => success(() => s)) def ignore = Command.command(FailureWall)(identity) @@ -240,6 +240,26 @@ object BuiltinCommands logger(s).info(detailString) s }) + def lastGrep = Command.single(LastGrepCommand, lastGrepBrief, lastGrepDetailed) { (s,arg) => + val (pattern, keyString) = arg.span(!_.isWhitespace) + if(keyString.isEmpty) + { + logger(s).error("Expected , found '" + arg + "'") + s.fail + } + else + { + val sc = scopedCommand(LastGrepCommand) { (s, scope, key, structure) => + Output.lastGrep(scope, key, structure.streams, pattern) + s + } + sc(s, keyString) + } + } + def last = Command.single(LastCommand, lastBrief, lastDetailed)( scopedCommand(LastCommand) { (s, scope, key, structure) => + Output.last(scope, key, structure.streams) + s + }) def delegates = Command.single(DelegatesCommand, delegatesBrief, delegatesDetailed) ( scopedCommand(DelegatesCommand) { (s, scope, key, structure) => val log = logger(s) structure.delegates(scope).foreach(d => log.info(Project.display(Project.ScopedKey(d, key)))) diff --git a/main/Output.scala b/main/Output.scala new file mode 100644 index 000000000..63ea350f8 --- /dev/null +++ b/main/Output.scala @@ -0,0 +1,36 @@ +/* sbt -- Simple Build Tool + * Copyright 2011 Mark Harrah + */ +package sbt + + import java.util.regex.Pattern + import BuildStreams.{Streams, TaskStreams} + import Project.ScopedKey + +object Output +{ + def showMatches(pattern: Pattern)(line: String): Option[String] = + { + val matcher = pattern.matcher(line) + if(ConsoleLogger.formatEnabled) + { + val highlighted = matcher.replaceAll(scala.Console.RED + "$0" + scala.Console.RESET) + if(highlighted == line) None else Some(highlighted) + } + else if(matcher.find) + Some(line) + else + None + } + + def last(scope: Scope, key: AttributeKey[_], mgr: Streams): Unit = + printLines(lastLines(ScopedKey(scope,key), mgr)) + def printLines(lines: Seq[String]) = lines foreach println + def lastGrep(scope: Scope, key: AttributeKey[_], mgr: Streams, patternString: String) + { + val pattern = Pattern.compile(patternString) + printLines(lastLines(ScopedKey(scope,key), mgr).flatMap(showMatches(pattern)) ) + } + def lastLines(key: ScopedKey[_], mgr: Streams): Seq[String] = + mgr.use(key) { s => IO.readLines(s.readText( Project.fillTaskAxis(key) )) } +} diff --git a/main/Project.scala b/main/Project.scala index 14649cb88..84f0035c6 100644 --- a/main/Project.scala +++ b/main/Project.scala @@ -94,6 +94,9 @@ object Project extends Init[Scope] 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 "") + def fillTaskAxis(scoped: ScopedKey[_]): ScopedKey[_] = + ScopedKey(Scope.fillTaskAxis(scoped.scope, scoped.key), scoped.key) + def mapScope(f: Scope => Scope) = new (ScopedKey ~> ScopedKey) { def apply[T](key: ScopedKey[T]) = ScopedKey( f(key.scope), key.key) }