2010-07-17 18:07:41 +02:00
|
|
|
/* sbt -- Simple Build Tool
|
|
|
|
|
* Copyright 2008, 2009, 2010 Mark Harrah
|
|
|
|
|
*/
|
|
|
|
|
package sbt
|
|
|
|
|
|
2010-07-19 18:38:42 +02:00
|
|
|
import Execute.NodeView
|
2010-07-17 18:07:41 +02:00
|
|
|
import complete.HistoryCommands
|
|
|
|
|
import HistoryCommands.{Start => HistoryPrefix}
|
2010-07-28 05:01:45 +02:00
|
|
|
import sbt.build.{AggressiveCompile, Auto, Build, BuildException, LoadCommand, Parse, ParseException, ProjectLoad, SourceLoad}
|
2010-07-17 18:07:41 +02:00
|
|
|
import scala.annotation.tailrec
|
2010-07-28 05:01:45 +02:00
|
|
|
import scala.collection.JavaConversions._
|
|
|
|
|
import Path._
|
|
|
|
|
|
|
|
|
|
import java.io.File
|
2010-07-17 18:07:41 +02:00
|
|
|
|
|
|
|
|
/** This class is the entry point for sbt.*/
|
|
|
|
|
class xMain extends xsbti.AppMain
|
|
|
|
|
{
|
|
|
|
|
final def run(configuration: xsbti.AppConfiguration): xsbti.MainResult =
|
|
|
|
|
{
|
2010-07-28 05:01:45 +02:00
|
|
|
import Commands.{initialize, defaults}
|
|
|
|
|
import CommandSupport.{DefaultsCommand, InitCommand}
|
|
|
|
|
val initialCommandDefs = Seq(initialize, defaults)
|
|
|
|
|
val commands = DefaultsCommand :: InitCommand :: configuration.arguments.map(_.trim).toList
|
2010-09-05 16:56:24 +02:00
|
|
|
val state = State( () )( configuration, initialCommandDefs, Set.empty, None, commands, AttributeMap.empty, Next.Continue )
|
2010-07-17 18:07:41 +02:00
|
|
|
run(state)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@tailrec final def run(state: State): xsbti.MainResult =
|
|
|
|
|
{
|
|
|
|
|
import Next._
|
|
|
|
|
state.next match
|
|
|
|
|
{
|
|
|
|
|
case Continue => run(next(state))
|
|
|
|
|
case Fail => Exit(1)
|
|
|
|
|
case Done => Exit(0)
|
|
|
|
|
case Reload =>
|
|
|
|
|
val app = state.configuration.provider
|
|
|
|
|
new Reboot(app.scalaProvider.version, state.commands, app.id, state.configuration.baseDirectory)
|
|
|
|
|
}
|
|
|
|
|
}
|
2010-08-05 01:41:11 +02:00
|
|
|
def next(state: State): State =
|
|
|
|
|
ErrorHandling.wideConvert { state.process(process) } match
|
|
|
|
|
{
|
|
|
|
|
case Right(s) => s
|
|
|
|
|
case Left(t) => Commands.handleException(t, state)
|
|
|
|
|
}
|
2010-07-17 18:07:41 +02:00
|
|
|
def process(command: String, state: State): State =
|
|
|
|
|
{
|
2010-07-28 05:01:45 +02:00
|
|
|
val in = Input(command, None)
|
2010-07-19 18:31:22 +02:00
|
|
|
Commands.applicable(state).flatMap( _.run(in) ).headOption.getOrElse {
|
2010-08-05 01:41:46 +02:00
|
|
|
if(command.isEmpty) state
|
|
|
|
|
else {
|
|
|
|
|
System.err.println("Unknown command '" + command + "'")
|
|
|
|
|
state.fail
|
|
|
|
|
}
|
2010-07-17 18:07:41 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2010-07-28 05:01:45 +02:00
|
|
|
import CommandSupport._
|
2010-07-17 18:07:41 +02:00
|
|
|
object Commands
|
|
|
|
|
{
|
2010-09-05 17:19:34 +02:00
|
|
|
def DefaultCommands = Seq(ignore, help, reload, read, history, continuous, exit, load, loadCommands, loadProject, compile, discover,
|
2010-08-05 01:41:46 +02:00
|
|
|
projects, project, setOnFailure, ifLast, multi, shell, alias, append, act)
|
2010-07-28 05:01:45 +02:00
|
|
|
|
2010-09-05 17:16:53 +02:00
|
|
|
def ignore = nothing(Set(FailureWall))
|
|
|
|
|
|
|
|
|
|
def nothing(ignore: Set[String]) = Command.univ { s => Apply(){ case in if ignore(in.line) => s } }
|
|
|
|
|
|
2010-07-17 18:07:41 +02:00
|
|
|
def applicable(state: State): Stream[Apply] =
|
2010-07-19 18:31:22 +02:00
|
|
|
state.processors.toStream.flatMap(_.applies(state) )
|
2010-07-28 05:01:45 +02:00
|
|
|
|
|
|
|
|
def detail(selected: Iterable[String])(h: Help): Option[String] =
|
|
|
|
|
h.detail match { case (commands, value) => if( selected exists commands ) Some(value) else None }
|
|
|
|
|
|
|
|
|
|
def help = Command.simple(HelpCommand, helpBrief, helpDetailed) { (in, s) =>
|
|
|
|
|
|
|
|
|
|
val h = applicable(s).flatMap(_.help)
|
|
|
|
|
val argStr = (in.line stripPrefix HelpCommand).trim
|
2010-07-17 18:07:41 +02:00
|
|
|
|
2010-07-28 05:01:45 +02:00
|
|
|
val message =
|
|
|
|
|
if(argStr.isEmpty)
|
|
|
|
|
h.map( _.brief match { case (a,b) => a + " : " + b } ).mkString("\n", "\n", "\n")
|
|
|
|
|
else
|
|
|
|
|
h flatMap detail( argStr.split("""\s+""", 0) ) mkString("\n", "\n\n", "\n")
|
2010-07-17 18:07:41 +02:00
|
|
|
System.out.println(message)
|
|
|
|
|
s
|
|
|
|
|
}
|
|
|
|
|
|
2010-07-28 05:01:45 +02:00
|
|
|
def alias = Command.simple(AliasCommand, AliasBrief, AliasDetailed) { (in, s) =>
|
|
|
|
|
in.arguments.split("""\s*=\s*""",2).toSeq match {
|
|
|
|
|
case Seq(name, value) => addAlias(s, name.trim, value.trim)
|
|
|
|
|
case Seq(x) if !x.isEmpty=> printAlias(s, x.trim); s
|
|
|
|
|
case _ => printAliases(s); s
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
def shell = Command.simple(Shell, ShellBrief, ShellDetailed) { (in, s) =>
|
2010-08-05 01:41:46 +02:00
|
|
|
val historyPath = s.project match { case he: HistoryEnabled => he.historyPath; case _ => Some(s.baseDir / ".history") }
|
2010-07-28 05:01:45 +02:00
|
|
|
val reader = new LazyJLineReader(historyPath, new LazyCompletor(completor(s)))
|
|
|
|
|
val line = reader.readLine("> ")
|
2010-08-05 01:41:46 +02:00
|
|
|
line match {
|
|
|
|
|
case Some(line) => s.copy()(onFailure = Some(Shell), commands = line +: Shell +: s.commands)
|
|
|
|
|
case None => s
|
|
|
|
|
}
|
2010-07-28 05:01:45 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
def multi = Command.simple(Multi, MultiBrief, MultiDetailed) { (in, s) =>
|
|
|
|
|
in.arguments.split(";").toSeq ::: s
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
def ifLast = Command.simple(IfLast, IfLastBrief, IfLastDetailed) { (in, s) =>
|
|
|
|
|
if(s.commands.isEmpty) in.arguments :: s else s
|
|
|
|
|
}
|
2010-08-05 01:41:46 +02:00
|
|
|
def append = Command.simple(Append, AppendLastBrief, AppendLastDetailed) { (in, s) =>
|
|
|
|
|
s.copy()(commands = s.commands :+ in.arguments)
|
|
|
|
|
}
|
2010-07-28 05:01:45 +02:00
|
|
|
|
|
|
|
|
def setOnFailure = Command.simple(OnFailure, OnFailureBrief, OnFailureDetailed) { (in, s) =>
|
|
|
|
|
s.copy()(onFailure = Some(in.arguments))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
def reload = Command.simple(ReloadCommand, ReloadBrief, ReloadDetailed) { (in, s) =>
|
|
|
|
|
runExitHooks(s).reload
|
|
|
|
|
}
|
|
|
|
|
|
2010-11-24 20:10:48 +01:00
|
|
|
def defaults = Command.simple(DefaultsCommand) { (in, s) =>
|
2010-07-28 05:01:45 +02:00
|
|
|
s ++ DefaultCommands
|
|
|
|
|
}
|
|
|
|
|
|
2010-11-24 20:10:48 +01:00
|
|
|
def initialize = Command.simple(InitCommand) { (in, s) =>
|
2010-08-05 01:41:46 +02:00
|
|
|
/*"load-commands -base ~/.sbt/commands" :: */readLines( readable( sbtRCs(s) ) ) ::: s
|
2010-07-28 05:01:45 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
def read = Command.simple(ReadCommand, ReadBrief, ReadDetailed) { (in, s) =>
|
2010-09-28 00:59:35 +02:00
|
|
|
getSource(in, s.baseDir) match
|
|
|
|
|
{
|
|
|
|
|
case Left(portAndSuccess) =>
|
|
|
|
|
val port = math.abs(portAndSuccess)
|
|
|
|
|
val previousSuccess = portAndSuccess >= 0
|
|
|
|
|
readMessage(port, previousSuccess) match
|
|
|
|
|
{
|
|
|
|
|
case Some(message) => (message :: (ReadCommand + " " + port) :: s).copy()(onFailure = Some(ReadCommand + " " + (-port)))
|
|
|
|
|
case None =>
|
|
|
|
|
System.err.println("Connection closed.")
|
|
|
|
|
s.fail
|
|
|
|
|
}
|
|
|
|
|
case Right(from) =>
|
|
|
|
|
val notFound = notReadable(from)
|
|
|
|
|
if(notFound.isEmpty)
|
|
|
|
|
readLines(from) ::: s // this means that all commands from all files are loaded, parsed, and inserted before any are executed
|
|
|
|
|
else {
|
|
|
|
|
logger(s).error("Command file(s) not readable: \n\t" + notFound.mkString("\n\t"))
|
|
|
|
|
s
|
|
|
|
|
}
|
2010-07-28 05:01:45 +02:00
|
|
|
}
|
|
|
|
|
}
|
2010-09-28 00:59:35 +02:00
|
|
|
private def getSource(in: Input, baseDirectory: File) =
|
|
|
|
|
{
|
|
|
|
|
try { Left(in.line.stripPrefix(ReadCommand).trim.toInt) }
|
|
|
|
|
catch { case _: NumberFormatException => Right(in.splitArgs map { p => new File(baseDirectory, p) }) }
|
|
|
|
|
}
|
|
|
|
|
private def readMessage(port: Int, previousSuccess: Boolean): Option[String] =
|
|
|
|
|
{
|
|
|
|
|
// split into two connections because this first connection ends the previous communication
|
|
|
|
|
xsbt.IPC.client(port) { _.send(previousSuccess.toString) }
|
|
|
|
|
// and this second connection starts the next communication
|
|
|
|
|
xsbt.IPC.client(port) { ipc =>
|
|
|
|
|
val message = ipc.receive
|
|
|
|
|
if(message eq null) None else Some(message)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2010-09-05 17:19:19 +02:00
|
|
|
def continuous = Command { case s @ State(p: Project with Watched) =>
|
|
|
|
|
Apply( Help(continuousBriefHelp) ) {
|
|
|
|
|
case in if in.line startsWith ContinuousExecutePrefix => Watched.executeContinuously(p, s, in)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2010-08-05 01:41:46 +02:00
|
|
|
def history = Command { case s @ State(p: HistoryEnabled) =>
|
2010-07-28 05:01:45 +02:00
|
|
|
Apply( historyHelp: _* ) {
|
2010-07-17 18:07:41 +02:00
|
|
|
case in if in.line startsWith("!") =>
|
2010-08-05 01:41:46 +02:00
|
|
|
val logError: (String => Unit) = p match { case l: Logged => (s: String) => l.log.error(s) ; case _ => System.err.println _ }
|
|
|
|
|
HistoryCommands(in.line.substring(HistoryPrefix.length).trim, p.historyPath, 500/*JLine.MaxHistorySize*/, logError) match
|
2010-07-17 18:07:41 +02:00
|
|
|
{
|
|
|
|
|
case Some(commands) =>
|
2010-07-28 05:01:45 +02:00
|
|
|
commands.foreach(println) //printing is more appropriate than logging
|
2010-07-17 18:07:41 +02:00
|
|
|
(commands ::: s).continue
|
|
|
|
|
case None => s.fail
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2010-07-28 05:01:45 +02:00
|
|
|
|
2010-08-05 01:41:46 +02:00
|
|
|
def indent(withStar: Boolean) = if(withStar) "\t*" else "\t"
|
|
|
|
|
def listProject(p: Named, current: Boolean, log: Logger) = printProject( indent(current), p, log)
|
2010-07-28 05:01:45 +02:00
|
|
|
def printProject(prefix: String, p: Named, log: Logger) = log.info(prefix + p.name)
|
|
|
|
|
|
|
|
|
|
def projects = Command { case s @ State(d: Member[_]) =>
|
|
|
|
|
Apply.simple(ProjectsCommand, projectsBrief, projectsDetailed ) { (in,s) =>
|
|
|
|
|
val log = logger(s)
|
2010-10-30 19:24:23 +02:00
|
|
|
d.navigation.projectClosure(s).foreach { case n: Named => listProject(n, d eq n, log); case _ => () }
|
2010-07-28 05:01:45 +02:00
|
|
|
s
|
|
|
|
|
}(s)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
def project = Command { case s @ State(d: Member[_] with Named) =>
|
|
|
|
|
Apply.simple(ProjectCommand, projectBrief, projectDetailed ) { (in,s) =>
|
|
|
|
|
val to = in.arguments
|
|
|
|
|
if(to.isEmpty)
|
|
|
|
|
{
|
|
|
|
|
logger(s).info(d.name)
|
|
|
|
|
s
|
|
|
|
|
}
|
2010-10-30 19:24:23 +02:00
|
|
|
else if(to == "/")
|
|
|
|
|
setProject(d.navigation.initialProject(s), s)
|
|
|
|
|
else if(to.forall(_ == '.'))
|
|
|
|
|
if(to.length > 1) gotoParent(to.length - 1, d, s) else s
|
2010-07-28 05:01:45 +02:00
|
|
|
else
|
|
|
|
|
{
|
2010-10-30 19:24:23 +02:00
|
|
|
d.navigation.projectClosure(s).find { case n: Named => n.name == to; case _ => false } match
|
2010-07-28 05:01:45 +02:00
|
|
|
{
|
2010-10-30 19:24:23 +02:00
|
|
|
case Some(np) => setProject(np, s)
|
2010-07-28 05:01:45 +02:00
|
|
|
case None => logger(s).error("Invalid project name '" + to + "' (type 'projects' to list available projects)."); s.fail
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}(s)
|
|
|
|
|
}
|
2010-10-30 19:24:23 +02:00
|
|
|
@tailrec def gotoParent[Node <: Member[Node]](n: Int, base: Member[Node], s: State): State =
|
|
|
|
|
base.navigation.parentProject match
|
|
|
|
|
{
|
|
|
|
|
case Some(pp) => if(n <= 1) setProject(pp, s) else gotoParent(n-1, pp, s)
|
|
|
|
|
case None => if(s.project == base) s else setProject(base, s)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
def setProject(np: AnyRef, s: State): State =
|
|
|
|
|
{
|
|
|
|
|
np match { case n: Named =>
|
|
|
|
|
logger(s).info("Set current project to " + n.name)
|
|
|
|
|
}
|
|
|
|
|
s.copy(np)()
|
|
|
|
|
}
|
2010-07-28 05:01:45 +02:00
|
|
|
def exit = Command { case s => Apply( Help(exitBrief) ) {
|
|
|
|
|
case in if TerminateActions contains in.line =>
|
|
|
|
|
runExitHooks(s).exit(true)
|
2010-07-17 18:07:41 +02:00
|
|
|
}
|
|
|
|
|
}
|
2010-07-19 18:38:42 +02:00
|
|
|
|
|
|
|
|
def act = Command { case s @ State(p: Tasked) =>
|
|
|
|
|
new Apply {
|
|
|
|
|
def help = p.help
|
2010-07-28 05:01:45 +02:00
|
|
|
def complete = in => Completions()
|
2010-07-19 18:38:42 +02:00
|
|
|
def run = in => {
|
2010-07-28 05:01:45 +02:00
|
|
|
val (checkCycles, maxThreads) = p match {
|
2010-07-19 18:38:42 +02:00
|
|
|
case c: TaskSetup => (c.checkCycles, c.maxThreads)
|
|
|
|
|
case _ => (false, Runtime.getRuntime.availableProcessors)
|
|
|
|
|
}
|
2010-08-14 15:50:22 +02:00
|
|
|
for( (task, taskToNode) <- p.act(in, s)) yield
|
2010-09-28 00:59:14 +02:00
|
|
|
processResult(runTask(task, checkCycles, maxThreads)(taskToNode), s, s.fail)
|
2010-07-19 18:38:42 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2010-07-28 05:01:45 +02:00
|
|
|
|
2010-08-05 01:41:46 +02:00
|
|
|
def discover = Command { case s @ State(analysis: inc.Analysis) =>
|
|
|
|
|
Apply.simple(Discover, DiscoverBrief, DiscoverDetailed) { (in, s) =>
|
|
|
|
|
val command = Parse.discover(in.arguments)
|
|
|
|
|
val discovered = Build.discover(analysis, command)
|
|
|
|
|
println(discovered.mkString("\n"))
|
|
|
|
|
s
|
|
|
|
|
}(s)
|
|
|
|
|
}
|
2010-09-04 14:25:34 +02:00
|
|
|
def compile = Command.simple(CompileName, CompileBrief, CompileDetailed ) { (in, s) =>
|
2010-08-05 01:41:46 +02:00
|
|
|
val command = Parse.compile(in.arguments)(s.baseDir)
|
2010-08-10 14:46:27 +02:00
|
|
|
try {
|
|
|
|
|
val analysis = Build.compile(command, s.configuration)
|
|
|
|
|
s.copy(project = analysis)()
|
|
|
|
|
} catch { case e: xsbti.CompileFailed => s.fail /* already logged */ }
|
2010-08-05 01:41:46 +02:00
|
|
|
}
|
2010-07-28 05:01:45 +02:00
|
|
|
def load = Command.simple(Load, Parse.helpBrief(Load, LoadLabel), Parse.helpDetail(Load, LoadLabel, false) ) { (in, s) =>
|
2010-09-13 04:44:33 +02:00
|
|
|
loadCommand(in.arguments, s.configuration, false, "sbt.Project") match
|
2010-07-28 05:01:45 +02:00
|
|
|
{
|
|
|
|
|
case Right(Seq(newValue)) => runExitHooks(s).copy(project = newValue)()
|
2010-08-10 14:46:27 +02:00
|
|
|
case Left(e) => handleException(e, s, false)
|
2010-07-28 05:01:45 +02:00
|
|
|
}
|
|
|
|
|
}
|
2010-09-05 17:12:44 +02:00
|
|
|
|
|
|
|
|
def loadProject = Command.simple(LoadProject, LoadProjectBrief, LoadProjectDetailed) { (in, s) =>
|
|
|
|
|
val base = s.configuration.baseDirectory
|
2010-09-13 04:58:22 +02:00
|
|
|
lazy val p: Project = MultiProject.load(s.configuration, ConsoleLogger() /*TODO*/, ProjectInfo.externals(exts))(base)
|
|
|
|
|
// lazy so that p can forward-reference it
|
|
|
|
|
lazy val exts: Map[File, Project] = MultiProject.loadExternals(p :: Nil, p.info.construct).updated(base, p)
|
|
|
|
|
exts// force
|
|
|
|
|
runExitHooks(s).copy(project = p)().put(MultiProject.InitialProject, p)
|
2010-09-05 17:12:44 +02:00
|
|
|
}
|
2010-07-17 18:07:41 +02:00
|
|
|
|
2010-08-10 14:46:27 +02:00
|
|
|
def handleException(e: Throwable, s: State, trace: Boolean = true): State = {
|
2010-08-05 01:41:11 +02:00
|
|
|
// TODO: log instead of print
|
2010-08-10 14:46:27 +02:00
|
|
|
if(trace)
|
|
|
|
|
e.printStackTrace
|
2010-08-05 01:41:11 +02:00
|
|
|
System.err.println(e.toString)
|
|
|
|
|
s.fail
|
|
|
|
|
}
|
|
|
|
|
|
2010-07-28 05:01:45 +02:00
|
|
|
def runExitHooks(s: State): State = {
|
|
|
|
|
ExitHooks.runExitHooks(s.exitHooks.toSeq)
|
|
|
|
|
s.copy()(exitHooks = Set.empty)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
def loadCommands = Command.simple(LoadCommand, Parse.helpBrief(LoadCommand, LoadCommandLabel), Parse.helpDetail(LoadCommand, LoadCommandLabel, true) ) { (in, s) =>
|
2010-08-05 01:41:46 +02:00
|
|
|
applyCommands(s, buildCommands(in.arguments, s.configuration))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
def buildCommands(arguments: String, configuration: xsbti.AppConfiguration): Either[Throwable, Seq[Any]] =
|
2010-08-10 14:44:34 +02:00
|
|
|
loadCommand(arguments, configuration, true, classOf[CommandDefinitions].getName)
|
2010-08-05 01:41:46 +02:00
|
|
|
|
|
|
|
|
def applyCommands(s: State, commands: Either[Throwable, Seq[Any]]): State =
|
|
|
|
|
commands match {
|
2010-07-28 05:01:45 +02:00
|
|
|
case Right(newCommands) =>
|
2010-08-10 14:44:34 +02:00
|
|
|
val asCommands = newCommands flatMap {
|
|
|
|
|
case c: CommandDefinitions => c.commands
|
|
|
|
|
case x => error("Not an instance of CommandDefinitions: " + x.asInstanceOf[AnyRef].getClass)
|
|
|
|
|
}
|
2010-07-28 05:01:45 +02:00
|
|
|
s.copy()(processors = asCommands ++ s.processors)
|
2010-08-10 14:46:27 +02:00
|
|
|
case Left(e) => handleException(e, s, false)
|
2010-07-17 18:07:41 +02:00
|
|
|
}
|
|
|
|
|
|
2010-07-28 05:01:45 +02:00
|
|
|
def loadCommand(line: String, configuration: xsbti.AppConfiguration, allowMultiple: Boolean, defaultSuper: String): Either[Throwable, Seq[Any]] =
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
val parsed = Parse(line)(configuration.baseDirectory)
|
|
|
|
|
Right( Build( translateEmpty(parsed, defaultSuper), configuration, allowMultiple) )
|
|
|
|
|
}
|
2010-07-17 18:07:41 +02:00
|
|
|
catch { case e @ (_: ParseException | _: BuildException | _: xsbti.CompileFailed) => Left(e) }
|
2010-07-19 18:38:42 +02:00
|
|
|
|
2010-07-28 05:01:45 +02:00
|
|
|
def translateEmpty(load: LoadCommand, defaultSuper: String): LoadCommand =
|
|
|
|
|
load match {
|
|
|
|
|
case ProjectLoad(base, Auto.Explicit, "") => ProjectLoad(base, Auto.Subclass, defaultSuper)
|
|
|
|
|
case s @ SourceLoad(_, _, _, _, Auto.Explicit, "") => s.copy(auto = Auto.Subclass, name = defaultSuper)
|
|
|
|
|
case x => x
|
|
|
|
|
}
|
2010-07-19 18:38:42 +02:00
|
|
|
|
|
|
|
|
def runTask[Task[_] <: AnyRef](root: Task[State], checkCycles: Boolean, maxWorkers: Int)(implicit taskToNode: NodeView[Task]): Result[State] =
|
|
|
|
|
{
|
|
|
|
|
val (service, shutdown) = CompletionService[Task[_], Completed](maxWorkers)
|
|
|
|
|
|
|
|
|
|
val x = new Execute[Task](checkCycles)(taskToNode)
|
|
|
|
|
try { x.run(root)(service) } finally { shutdown() }
|
|
|
|
|
}
|
2010-09-28 00:59:14 +02:00
|
|
|
def processResult[State](result: Result[State], original: State, onFailure: => State): State =
|
2010-07-19 18:38:42 +02:00
|
|
|
result match
|
|
|
|
|
{
|
|
|
|
|
case Value(v) => v
|
2010-09-13 04:43:42 +02:00
|
|
|
case Inc(inc) =>
|
|
|
|
|
println(Incomplete.show(inc, true))
|
|
|
|
|
println("Task did not complete successfully")
|
2010-09-28 00:59:14 +02:00
|
|
|
onFailure
|
2010-07-19 18:38:42 +02:00
|
|
|
}
|
2010-07-28 05:01:45 +02:00
|
|
|
|
|
|
|
|
def completor(s: State): jline.Completor = new jline.Completor {
|
|
|
|
|
lazy val apply = applicable(s)
|
|
|
|
|
def complete(buffer: String, cursor: Int, candidates: java.util.List[_]): Int =
|
|
|
|
|
{
|
|
|
|
|
val correct = candidates.asInstanceOf[java.util.List[String]]
|
|
|
|
|
val in = Input(buffer, Some(cursor))
|
|
|
|
|
val completions = apply.map(_.complete(in))
|
|
|
|
|
val maxPos = if(completions.isEmpty) -1 else completions.map(_.position).max
|
|
|
|
|
correct ++= ( completions flatMap { c => if(c.position == maxPos) c.candidates else Nil } )
|
|
|
|
|
maxPos
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
def addAlias(s: State, name: String, value: String): State =
|
|
|
|
|
{
|
|
|
|
|
val in = Input(name, None)
|
|
|
|
|
if(in.name == name) {
|
|
|
|
|
val removed = removeAlias(s, name)
|
|
|
|
|
if(value.isEmpty) removed else removed.copy()(processors = new Alias(name, value) +: removed.processors)
|
|
|
|
|
} else {
|
|
|
|
|
System.err.println("Invalid alias name '" + name + "'.")
|
|
|
|
|
s.fail
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
def removeAlias(s: State, name: String): State =
|
|
|
|
|
s.copy()(processors = s.processors.filter { case a: Alias if a.name == name => false; case _ => true } )
|
|
|
|
|
|
|
|
|
|
def printAliases(s: State): Unit = {
|
|
|
|
|
val strings = aliasStrings(s)
|
|
|
|
|
if(!strings.isEmpty) println( strings.mkString("\t", "\n\t","") )
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
def printAlias(s: State, name: String): Unit =
|
|
|
|
|
for(a <- aliases(s)) if (a.name == name) println("\t" + name + " = " + a.value)
|
|
|
|
|
|
|
|
|
|
def aliasStrings(s: State) = aliases(s).map(a => a.name + " = " + a.value)
|
|
|
|
|
def aliases(s: State) = s.processors collect { case a: Alias => a }
|
|
|
|
|
|
2010-08-10 14:44:34 +02:00
|
|
|
final class Alias(val name: String, val value: String) extends Command {
|
2010-07-28 05:01:45 +02:00
|
|
|
assert(name.length > 0)
|
|
|
|
|
assert(value.length > 0)
|
|
|
|
|
def applies = s => Some(Apply() {
|
|
|
|
|
case in if in.name == name=> (value + " " + in.arguments) :: s
|
|
|
|
|
})
|
|
|
|
|
}
|
2010-07-17 18:07:41 +02:00
|
|
|
}
|