mirror of https://github.com/sbt/sbt.git
Export approximate command lines executed for 'doc', 'compile', and 'console'
This commit is contained in:
parent
daf300f4a9
commit
f2d29d8678
|
|
@ -82,6 +82,9 @@ private final class CachedCompiler0(args: Array[String], output: Output, initial
|
|||
|
||||
def noErrors(dreporter: DelegatingReporter) = !dreporter.hasErrors && command.ok
|
||||
|
||||
def commandArguments(sources: Array[File]): Array[String] =
|
||||
(command.settings.recreateArgs ++ sources.map(_.getAbsolutePath)).toArray[String]
|
||||
|
||||
def run(sources: Array[File], changes: DependencyChanges, callback: AnalysisCallback, log: Logger, delegate: Reporter, progress: CompileProgress): Unit = synchronized
|
||||
{
|
||||
debug(log, "Running cached compiler " + hashCode.toHexString + ", interfacing (CompilerInterface) with Scala compiler " + scala.tools.nsc.Properties.versionString)
|
||||
|
|
|
|||
|
|
@ -11,18 +11,18 @@ import scala.tools.nsc.util.ClassPath
|
|||
|
||||
class ConsoleInterface
|
||||
{
|
||||
def commandArguments(args: Array[String], bootClasspathString: String, classpathString: String, log: Logger): Array[String] =
|
||||
MakeSettings.sync(args, bootClasspathString, classpathString, log).recreateArgs.toArray[String]
|
||||
|
||||
def run(args: Array[String], bootClasspathString: String, classpathString: String, initialCommands: String, cleanupCommands: String, loader: ClassLoader, bindNames: Array[String], bindValues: Array[Any], log: Logger)
|
||||
{
|
||||
val options = args.toList
|
||||
lazy val interpreterSettings = MakeSettings.sync(options, log)
|
||||
val compilerSettings = MakeSettings.sync(options, log)
|
||||
lazy val interpreterSettings = MakeSettings.sync(args.toList, log)
|
||||
val compilerSettings = MakeSettings.sync(args, bootClasspathString, classpathString, log)
|
||||
|
||||
if(!bootClasspathString.isEmpty)
|
||||
compilerSettings.bootclasspath.value = bootClasspathString
|
||||
compilerSettings.classpath.value = classpathString
|
||||
log.info(Message("Starting scala interpreter..."))
|
||||
log.debug(Message(" Boot classpath: " + compilerSettings.bootclasspath.value))
|
||||
log.debug(Message(" Classpath: " + compilerSettings.classpath.value))
|
||||
log.info(Message(""))
|
||||
val loop = new InterpreterLoop {
|
||||
|
||||
|
|
@ -68,6 +68,15 @@ object MakeSettings
|
|||
throw new InterfaceCompileFailed(Array(), Array(), command.usageMsg)
|
||||
}
|
||||
|
||||
def sync(args: Array[String], bootClasspathString: String, classpathString: String, log: Logger): Settings =
|
||||
{
|
||||
val compilerSettings = sync(args.toList, log)
|
||||
if(!bootClasspathString.isEmpty)
|
||||
compilerSettings.bootclasspath.value = bootClasspathString
|
||||
compilerSettings.classpath.value = classpathString
|
||||
compilerSettings
|
||||
}
|
||||
|
||||
def sync(options: List[String], log: Logger) =
|
||||
{
|
||||
val settings = apply(options, log)
|
||||
|
|
|
|||
|
|
@ -13,8 +13,10 @@ package compiler
|
|||
* provided by scalaInstance. This class requires a ComponentManager in order to obtain the interface code to scalac and
|
||||
* the analysis plugin. Because these call Scala code for a different Scala version than the one used for this class, they must
|
||||
* be compiled for the version of Scala being used.*/
|
||||
final class AnalyzingCompiler(val scalaInstance: xsbti.compile.ScalaInstance, val provider: CompilerInterfaceProvider, val cp: xsbti.compile.ClasspathOptions) extends CachedCompilerProvider
|
||||
final class AnalyzingCompiler private(val scalaInstance: xsbti.compile.ScalaInstance, val provider: CompilerInterfaceProvider, val cp: xsbti.compile.ClasspathOptions, onArgsF: Seq[String] => Unit) extends CachedCompilerProvider
|
||||
{
|
||||
def this(scalaInstance: xsbti.compile.ScalaInstance, provider: CompilerInterfaceProvider, cp: xsbti.compile.ClasspathOptions) =
|
||||
this(scalaInstance, provider, cp, _ => ())
|
||||
def this(scalaInstance: ScalaInstance, provider: CompilerInterfaceProvider) = this(scalaInstance, provider, ClasspathOptions.auto)
|
||||
|
||||
@deprecated("A Logger is no longer needed.", "0.13.0")
|
||||
|
|
@ -23,6 +25,8 @@ final class AnalyzingCompiler(val scalaInstance: xsbti.compile.ScalaInstance, va
|
|||
@deprecated("A Logger is no longer needed.", "0.13.0")
|
||||
def this(scalaInstance: xsbti.compile.ScalaInstance, provider: CompilerInterfaceProvider, cp: xsbti.compile.ClasspathOptions, log: Logger) = this(scalaInstance, provider, cp)
|
||||
|
||||
def onArgs(f: Seq[String] => Unit): AnalyzingCompiler = new AnalyzingCompiler(scalaInstance, provider, cp, f)
|
||||
|
||||
def apply(sources: Seq[File], changes: DependencyChanges, classpath: Seq[File], singleOutput: File, options: Seq[String], callback: AnalysisCallback, maximumErrors: Int, cache: GlobalsCache, log: Logger)
|
||||
{
|
||||
val arguments = (new CompilerArguments(scalaInstance, cp))(Nil, classpath, None, options)
|
||||
|
|
@ -39,6 +43,7 @@ final class AnalyzingCompiler(val scalaInstance: xsbti.compile.ScalaInstance, va
|
|||
|
||||
def compile(sources: Seq[File], changes: DependencyChanges, callback: AnalysisCallback, log: Logger, reporter: Reporter, progress: CompileProgress, compiler: CachedCompiler)
|
||||
{
|
||||
onArgsF(compiler.commandArguments(sources.toArray))
|
||||
call("xsbt.CompilerInterface", "run", log)(
|
||||
classOf[Array[File]], classOf[DependencyChanges], classOf[AnalysisCallback], classOf[xLogger], classOf[Reporter], classOf[CompileProgress], classOf[CachedCompiler]) (
|
||||
sources.toArray, changes, callback, log, reporter, progress, compiler )
|
||||
|
|
@ -59,19 +64,35 @@ final class AnalyzingCompiler(val scalaInstance: xsbti.compile.ScalaInstance, va
|
|||
def doc(sources: Seq[File], classpath: Seq[File], outputDirectory: File, options: Seq[String], log: Logger, reporter: Reporter): Unit =
|
||||
{
|
||||
val arguments = (new CompilerArguments(scalaInstance, cp))(sources, classpath, Some(outputDirectory), options)
|
||||
onArgsF(arguments)
|
||||
call("xsbt.ScaladocInterface", "run", log) (classOf[Array[String]], classOf[xLogger], classOf[Reporter]) (
|
||||
arguments.toArray[String] : Array[String], log, reporter)
|
||||
}
|
||||
def console(classpath: Seq[File], options: Seq[String], initialCommands: String, cleanupCommands: String, log: Logger)(loader: Option[ClassLoader] = None, bindings: Seq[(String, Any)] = Nil): Unit =
|
||||
{
|
||||
val arguments = new CompilerArguments(scalaInstance, cp)
|
||||
val classpathString = CompilerArguments.absString(arguments.finishClasspath(classpath))
|
||||
val bootClasspath = if(cp.autoBoot) arguments.createBootClasspathFor(classpath) else ""
|
||||
onArgsF(consoleCommandArguments(classpath, options, log))
|
||||
val (classpathString, bootClasspath) = consoleClasspaths(classpath)
|
||||
val (names, values) = bindings.unzip
|
||||
call("xsbt.ConsoleInterface", "run", log)(
|
||||
classOf[Array[String]], classOf[String], classOf[String], classOf[String], classOf[String], classOf[ClassLoader], classOf[Array[String]], classOf[Array[Any]], classOf[xLogger])(
|
||||
options.toArray[String]: Array[String], bootClasspath, classpathString, initialCommands, cleanupCommands, loader.orNull, names.toArray[String], values.toArray[Any], log)
|
||||
}
|
||||
|
||||
private[this] def consoleClasspaths(classpath: Seq[File]): (String, String) =
|
||||
{
|
||||
val arguments = new CompilerArguments(scalaInstance, cp)
|
||||
val classpathString = CompilerArguments.absString(arguments.finishClasspath(classpath))
|
||||
val bootClasspath = if(cp.autoBoot) arguments.createBootClasspathFor(classpath) else ""
|
||||
(classpathString, bootClasspath)
|
||||
}
|
||||
def consoleCommandArguments(classpath: Seq[File], options: Seq[String], log: Logger): Seq[String] =
|
||||
{
|
||||
val (classpathString, bootClasspath) = consoleClasspaths(classpath)
|
||||
val argsObj = call("xsbt.ConsoleInterface", "commandArguments", log)(
|
||||
classOf[Array[String]], classOf[String], classOf[String], classOf[xLogger])(
|
||||
options.toArray[String]: Array[String], bootClasspath, classpathString, log)
|
||||
argsObj.asInstanceOf[Array[String]].toSeq
|
||||
}
|
||||
def force(log: Logger): Unit = provider(scalaInstance, log)
|
||||
private def call(interfaceClassName: String, methodName: String, log: Logger)(argTypes: Class[_]*)(args: AnyRef*): AnyRef =
|
||||
{
|
||||
|
|
|
|||
|
|
@ -20,10 +20,14 @@ trait JavaCompiler extends xsbti.compile.JavaCompiler
|
|||
}
|
||||
apply(sources, classpath, outputDirectory, options)(log)
|
||||
}
|
||||
|
||||
def onArgs(f: Seq[String] => Unit): JavaCompiler
|
||||
}
|
||||
trait Javadoc
|
||||
{
|
||||
def doc(sources: Seq[File], classpath: Seq[File], outputDirectory: File, options: Seq[String], maximumErrors: Int, log: Logger)
|
||||
|
||||
def onArgs(f: Seq[String] => Unit): Javadoc
|
||||
}
|
||||
trait JavaTool extends Javadoc with JavaCompiler
|
||||
{
|
||||
|
|
@ -34,6 +38,8 @@ trait JavaTool extends Javadoc with JavaCompiler
|
|||
compile(JavaCompiler.javadoc, sources, classpath, outputDirectory, options)(log)
|
||||
|
||||
def compile(contract: JavacContract, sources: Seq[File], classpath: Seq[File], outputDirectory: File, options: Seq[String])(implicit log: Logger): Unit
|
||||
|
||||
def onArgs(f: Seq[String] => Unit): JavaTool
|
||||
}
|
||||
object JavaCompiler
|
||||
{
|
||||
|
|
@ -52,18 +58,25 @@ object JavaCompiler
|
|||
}
|
||||
}
|
||||
|
||||
def construct(f: Fork, cp: ClasspathOptions, scalaInstance: ScalaInstance): JavaTool =
|
||||
new JavaTool {
|
||||
def compile(contract: JavacContract, sources: Seq[File], classpath: Seq[File], outputDirectory: File, options: Seq[String])(implicit log: Logger) {
|
||||
val augmentedClasspath = if(cp.autoBoot) classpath ++ Seq(scalaInstance.libraryJar) else classpath
|
||||
val javaCp = ClasspathOptions.javac(cp.compiler)
|
||||
val arguments = (new CompilerArguments(scalaInstance, javaCp))(sources, augmentedClasspath, Some(outputDirectory), options)
|
||||
log.debug("Calling " + contract.name.capitalize + " with arguments:\n\t" + arguments.mkString("\n\t"))
|
||||
val code: Int = f(contract, arguments, log)
|
||||
log.debug(contract.name + " returned exit code: " + code)
|
||||
if( code != 0 ) throw new CompileFailed(arguments.toArray, contract.name + " returned nonzero exit code", Array())
|
||||
}
|
||||
def construct(f: Fork, cp: ClasspathOptions, scalaInstance: ScalaInstance): JavaTool = new JavaTool0(f, cp, scalaInstance, _ => ())
|
||||
|
||||
private[this] class JavaTool0(f: Fork, cp: ClasspathOptions, scalaInstance: ScalaInstance, onArgsF: Seq[String] => Unit) extends JavaTool
|
||||
{
|
||||
def onArgs(g: Seq[String] => Unit): JavaTool = new JavaTool0(f, cp, scalaInstance, g)
|
||||
def commandArguments(sources: Seq[File], classpath: Seq[File], outputDirectory: File, options: Seq[String], log: Logger): Seq[String] =
|
||||
{
|
||||
val augmentedClasspath = if(cp.autoBoot) classpath ++ Seq(scalaInstance.libraryJar) else classpath
|
||||
val javaCp = ClasspathOptions.javac(cp.compiler)
|
||||
(new CompilerArguments(scalaInstance, javaCp))(sources, augmentedClasspath, Some(outputDirectory), options)
|
||||
}
|
||||
def compile(contract: JavacContract, sources: Seq[File], classpath: Seq[File], outputDirectory: File, options: Seq[String])(implicit log: Logger) {
|
||||
val arguments = commandArguments(sources, classpath, outputDirectory, options, log)
|
||||
onArgsF(arguments)
|
||||
val code: Int = f(contract, arguments, log)
|
||||
log.debug(contract.name + " returned exit code: " + code)
|
||||
if( code != 0 ) throw new CompileFailed(arguments.toArray, contract.name + " returned nonzero exit code", Array())
|
||||
}
|
||||
}
|
||||
def directOrFork(cp: ClasspathOptions, scalaInstance: ScalaInstance)(implicit doFork: Fork): JavaTool =
|
||||
construct(directOrForkJavac, cp, scalaInstance)
|
||||
|
||||
|
|
|
|||
|
|
@ -7,5 +7,7 @@ import java.io.File;
|
|||
|
||||
public interface CachedCompiler
|
||||
{
|
||||
/** Returns an array of arguments representing the nearest command line equivalent of a call to run but without the command name itself.*/
|
||||
public String[] commandArguments(File[] sources);
|
||||
public void run(File[] sources, DependencyChanges cpChanges, AnalysisCallback callback, Logger log, Reporter delegate, CompileProgress progress);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
*/
|
||||
package sbt
|
||||
|
||||
import java.io.File
|
||||
import java.io.{File, PrintWriter}
|
||||
import compiler.{AnalyzingCompiler, JavaCompiler}
|
||||
|
||||
import Predef.{conforms => _, _}
|
||||
|
|
@ -20,8 +20,9 @@ object Doc
|
|||
import RawCompileLike._
|
||||
def scaladoc(label: String, cache: File, compiler: AnalyzingCompiler): Gen =
|
||||
cached(cache, prepare(label + " Scala API documentation", compiler.doc))
|
||||
|
||||
def javadoc(label: String, cache: File, doc: sbt.compiler.Javadoc): Gen =
|
||||
cached(cache, prepare(label + " Scala API documentation", filterSources(javaSourcesOnly, doc.doc)))
|
||||
cached(cache, prepare(label + " Java API documentation", filterSources(javaSourcesOnly, doc.doc)))
|
||||
|
||||
val javaSourcesOnly: File => Boolean = _.getName.endsWith(".java")
|
||||
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ ShowCommand + """ <setting>
|
|||
|
||||
val LastCommand = "last"
|
||||
val LastGrepCommand = "last-grep"
|
||||
val ExportCommand = "export"
|
||||
|
||||
val lastGrepBrief = (LastGrepCommand, "Shows lines from the last output for 'key' that match 'pattern'.")
|
||||
val lastGrepDetailed =
|
||||
|
|
@ -56,6 +57,17 @@ LastCommand + """
|
|||
|
||||
See also '""" + LastGrepCommand + "'."
|
||||
|
||||
val exportBrief = (ExportCommand, "Displays the equivalent command line(s) for previously executed tasks.")
|
||||
val exportDetailed =
|
||||
s"""$ExportCommand <task-key>+
|
||||
Prints the approximate command line(s) for the previously executed tasks.
|
||||
|
||||
NOTE: These command lines are necessarily approximate. Usually tasks do not actually
|
||||
execute the command line and the actual command line program may not be installed or
|
||||
on the PATH. Incremental tasks will typically show the command line for the previous
|
||||
incremental run and not for a full run.
|
||||
"""
|
||||
|
||||
val InspectCommand = "inspect"
|
||||
val inspectBrief = (InspectCommand, "Prints the value for 'key', the defining scope, delegates, related definitions, and dependencies.")
|
||||
val inspectDetailed =
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@
|
|||
package sbt
|
||||
|
||||
import java.io.File
|
||||
import compiler.AnalyzingCompiler
|
||||
|
||||
object ConsoleProject
|
||||
{
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ package sbt
|
|||
import scala.xml.NodeSeq
|
||||
import org.apache.ivy.core.module.{descriptor, id}
|
||||
import descriptor.ModuleDescriptor, id.ModuleRevisionId
|
||||
import java.io.File
|
||||
import java.io.{File, PrintWriter}
|
||||
import java.net.{URI,URL,MalformedURLException}
|
||||
import java.util.concurrent.Callable
|
||||
import sbinary.DefaultProtocol.StringFormat
|
||||
|
|
@ -619,9 +619,11 @@ object Defaults extends BuildCommon
|
|||
val label = nameForSrc(config.name)
|
||||
val (options, runDoc) =
|
||||
if(hasScala)
|
||||
(in.config.options ++ Opts.doc.externalAPI(xapis), Doc.scaladoc(label, s.cacheDirectory / "scala", in.compilers.scalac))
|
||||
(in.config.options ++ Opts.doc.externalAPI(xapis),
|
||||
Doc.scaladoc(label, s.cacheDirectory / "scala", in.compilers.scalac.onArgs(exported(s, "scaladoc"))))
|
||||
else if(hasJava)
|
||||
(in.config.javacOptions, Doc.javadoc(label, s.cacheDirectory / "java", in.compilers.javac))
|
||||
(in.config.javacOptions,
|
||||
Doc.javadoc(label, s.cacheDirectory / "java", in.compilers.javac.onArgs(exported(s, "javadoc"))))
|
||||
else
|
||||
(Nil, RawCompileLike.nop)
|
||||
runDoc(srcs, cp, out, options, in.config.maxErrors, s.log)
|
||||
|
|
@ -641,15 +643,29 @@ object Defaults extends BuildCommon
|
|||
def consoleTask(classpath: TaskKey[Classpath], task: TaskKey[_]): Initialize[Task[Unit]] =
|
||||
(compilers in task, classpath in task, scalacOptions in task, initialCommands in task, cleanupCommands in task, taskTemporaryDirectory in task, scalaInstance in task, streams) map {
|
||||
(cs, cp, options, initCommands, cleanup, temp, si, s) =>
|
||||
val fullcp = (data(cp) ++ si.jars).distinct
|
||||
val cpFiles = data(cp)
|
||||
val fullcp = (cpFiles ++ si.jars).distinct
|
||||
val loader = sbt.classpath.ClasspathUtilities.makeLoader(fullcp, si, IO.createUniqueDirectory(temp))
|
||||
(new Console(cs.scalac))(data(cp), options, loader, initCommands, cleanup)()(s.log).foreach(msg => error(msg))
|
||||
val compiler = cs.scalac.onArgs(exported(s, "scala"))
|
||||
(new Console(compiler))(cpFiles, options, loader, initCommands, cleanup)()(s.log).foreach(msg => error(msg))
|
||||
println()
|
||||
}
|
||||
|
||||
private[this] def exported(w: PrintWriter, command: String): Seq[String] => Unit = args =>
|
||||
w.println( (command +: args).mkString(" ") )
|
||||
private[this] def exported(s: TaskStreams, command: String): Seq[String] => Unit = args =>
|
||||
exported(s.text("export"), command)
|
||||
|
||||
def compileTaskSettings: Seq[Setting[_]] = inTask(compile)(compileInputsSettings)
|
||||
|
||||
def compileTask = (compileInputs in compile, streams) map { (i,s) => Compiler(i,s.log) }
|
||||
def compileTask: Initialize[Task[inc.Analysis]] = Def.task { compileTaskImpl(streams.value, (compileInputs in compile).value) }
|
||||
private[this] def compileTaskImpl(s: TaskStreams, ci: Compiler.Inputs): inc.Analysis =
|
||||
{
|
||||
lazy val x = s.text("export")
|
||||
def onArgs(cs: Compiler.Compilers) = cs.copy(scalac = cs.scalac.onArgs(exported(x, "scalac")), javac = cs.javac.onArgs(exported(x, "javac")))
|
||||
val i = ci.copy(compilers = onArgs(ci.compilers))
|
||||
Compiler(i,s.log)
|
||||
}
|
||||
def compileIncSetupTask =
|
||||
(dependencyClasspath, skip in compile, definesClass, compilerCache, streams, incOptions) map { (cp, skip, definesC, cache, s, incOptions) =>
|
||||
Compiler.IncSetup(analysisMap(cp), definesC, skip, s.cacheDirectory / "inc_compile", cache, incOptions)
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ object BuiltinCommands
|
|||
def ScriptCommands: Seq[Command] = Seq(ignore, exit, Script.command, act, nop)
|
||||
def DefaultCommands: Seq[Command] = Seq(ignore, help, about, tasks, settingsCommand, loadProject,
|
||||
projects, project, reboot, read, history, set, sessionCommand, inspect, loadProjectImpl, loadFailed, Cross.crossBuild, Cross.switchVersion,
|
||||
setOnFailure, clearOnFailure, ifLast, multi, shell, continuous, eval, alias, append, last, lastGrep, boot, nop, call, exit, act)
|
||||
setOnFailure, clearOnFailure, ifLast, multi, shell, continuous, eval, alias, append, last, lastGrep, export, boot, nop, call, exit, act)
|
||||
def DefaultBootCommands: Seq[String] = LoadProject :: (IfLast + " " + Shell) :: Nil
|
||||
|
||||
def boot = Command.make(BootCommand)(bootParser)
|
||||
|
|
@ -295,20 +295,26 @@ object BuiltinCommands
|
|||
|
||||
val spacedKeyParser = (s: State) => Act.requireSession(s, token(Space) ~> Act.scopedKeyParser(s))
|
||||
val spacedAggregatedParser = (s: State) => Act.requireSession(s, token(Space) ~> Act.aggregatedKeyParser(s))
|
||||
val aggregatedKeyValueParser: State => Parser[Option[AnyKeys]] =
|
||||
(s: State) => spacedAggregatedParser(s).map(x => Act.keyValues(s)(x) ).?
|
||||
val exportParser: State => Parser[AnyKeys] = (s: State) => spacedAggregatedParser(s).map(x => Act.keyValues(s)(x) )
|
||||
val aggregatedKeyValueParser: State => Parser[Option[AnyKeys]] = s => exportParser(s).?
|
||||
|
||||
def lastGrepParser(s: State) = Act.requireSession(s, (token(Space) ~> token(NotSpace, "<pattern>")) ~ aggregatedKeyValueParser(s))
|
||||
def last = Command(LastCommand, lastBrief, lastDetailed)(aggregatedKeyValueParser) {
|
||||
case (s,Some(sks)) =>
|
||||
val (str, ref, display) = extractLast(s)
|
||||
Output.last(sks, str.streams(s), printLast(s))(display)
|
||||
keepLastLog(s)
|
||||
case (s,Some(sks)) => lastImpl(s, sks, None)
|
||||
case (s, None) =>
|
||||
for(logFile <- lastLogFile(s)) yield
|
||||
Output.last( logFile, printLast(s) )
|
||||
keepLastLog(s)
|
||||
}
|
||||
def export = Command(ExportCommand, exportBrief, exportDetailed)(exportParser) { (s, sks) =>
|
||||
lastImpl(s, sks, Some("export"))
|
||||
}
|
||||
private[this] def lastImpl(s: State, sks: AnyKeys, sid: Option[String]): State =
|
||||
{
|
||||
val (str, ref, display) = extractLast(s)
|
||||
Output.last(sks, str.streams(s), printLast(s), sid)(display)
|
||||
keepLastLog(s)
|
||||
}
|
||||
|
||||
/** Determines the log file that last* commands should operate on. See also isLastOnly. */
|
||||
def lastLogFile(s: State) =
|
||||
|
|
|
|||
|
|
@ -16,8 +16,12 @@ object Output
|
|||
{
|
||||
final val DefaultTail = "> "
|
||||
|
||||
@deprecated("Explicitly provide None for the stream ID.", "0.13.0")
|
||||
def last(keys: Values[_], streams: Streams, printLines: Seq[String] => Unit)(implicit display: Show[ScopedKey[_]]): Unit =
|
||||
printLines( flatLines(lastLines(keys, streams))(idFun) )
|
||||
last(keys, streams, printLines, None)(display)
|
||||
|
||||
def last(keys: Values[_], streams: Streams, printLines: Seq[String] => Unit, sid: Option[String])(implicit display: Show[ScopedKey[_]]): Unit =
|
||||
printLines( flatLines(lastLines(keys, streams, sid))(idFun) )
|
||||
|
||||
def last(file: File, printLines: Seq[String] => Unit, tailDelim: String = DefaultTail): Unit =
|
||||
printLines(tailLines(file, tailDelim))
|
||||
|
|
@ -42,13 +46,19 @@ object Output
|
|||
}
|
||||
}
|
||||
|
||||
def lastLines(keys: Values[_], streams: Streams): Values[Seq[String]] =
|
||||
def lastLines(keys: Values[_], streams: Streams, sid: Option[String] = None): Values[Seq[String]] =
|
||||
{
|
||||
val outputs = keys map { (kv: KeyValue[_]) => KeyValue(kv.key, lastLines(kv.key, streams)) }
|
||||
val outputs = keys map { (kv: KeyValue[_]) => KeyValue(kv.key, lastLines(kv.key, streams, sid)) }
|
||||
outputs.filterNot(_.value.isEmpty)
|
||||
}
|
||||
def lastLines(key: ScopedKey[_], mgr: Streams): Seq[String] = mgr.use(key) { s => IO.readLines(s.readText( Project.fillTaskAxis(key) )) }
|
||||
|
||||
@deprecated("Explicitly provide None for the stream ID.", "0.13.0")
|
||||
def lastLines(key: ScopedKey[_], mgr: Streams): Seq[String] = lastLines(key, mgr, None)
|
||||
|
||||
def lastLines(key: ScopedKey[_], mgr: Streams, sid: Option[String]): Seq[String] = mgr.use(key) { s => IO.readLines(s.readText( Project.fillTaskAxis(key), sid )) }
|
||||
|
||||
def tailLines(file: File, tailDelim: String): Seq[String] = headLines(IO.readLines(file).reverse, tailDelim).reverse
|
||||
|
||||
@tailrec def headLines(lines: Seq[String], tailDelim: String): Seq[String] =
|
||||
if(lines.isEmpty)
|
||||
lines
|
||||
|
|
|
|||
Loading…
Reference in New Issue