From 650bef7b067fd46ccf0dbbcabb8d1fe63b91269a Mon Sep 17 00:00:00 2001 From: Mark Harrah Date: Sat, 9 Apr 2011 15:04:18 -0400 Subject: [PATCH] demo script command --- main/Main.scala | 2 +- main/Script.scala | 56 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 main/Script.scala diff --git a/main/Main.scala b/main/Main.scala index 4fa8766e2..36734d621 100644 --- a/main/Main.scala +++ b/main/Main.scala @@ -59,7 +59,7 @@ class xMain extends xsbti.AppMain import CommandSupport._ object BuiltinCommands { - def DefaultCommands: Seq[Command] = Seq(ignore, help, reboot, read, history, continuous, exit, loadProject, loadProjectImpl, loadFailed, + def DefaultCommands: Seq[Command] = Seq(ignore, help, reboot, read, history, continuous, exit, loadProject, loadProjectImpl, loadFailed, Script.command, projects, project, setOnFailure, clearOnFailure, ifLast, multi, shell, set, inspect, eval, alias, append, last, lastGrep, nop, sessionCommand, act) def DefaultBootCommands: Seq[String] = LoadProject :: (IfLast + " " + Shell) :: Nil diff --git a/main/Script.scala b/main/Script.scala new file mode 100644 index 000000000..3bdebc0ca --- /dev/null +++ b/main/Script.scala @@ -0,0 +1,56 @@ +/* sbt -- Simple Build Tool + * Copyright 2011 Mark Harrah + */ +package sbt + + import java.io.File + import Keys._ + import EvaluateConfigurations.{evaluateConfiguration => evaluate} + import Configurations.Compile + +object Script +{ + lazy val command = + Command.command("script") { state => + val scriptArg = state.remainingCommands.headOption getOrElse error("No script file specified") + val script = new File(scriptArg).getAbsoluteFile + val extracted = Project.extract(state) + import extracted._ + + val eval = session.currentEval() + val settings = blocks(script).flatMap { block => + evaluate(eval, script.getPath, block.lines, currentUnit.imports, block.offset) + } + val scriptAsSource = sources in Compile := script :: Nil + val asScript = scalacOptions ++= Seq("-Xscript", script.getName.stripSuffix(".scala")) + val logQuiet = (logLevel in Global := Level.Warn) :: (showSuccess in Global := false) :: Nil + val append = Load.transformSettings(Load.projectScope(currentRef), currentRef.build, rootProject, asScript +: (logQuiet ++ settings)) + val newStructure = Load.reapply(session.original ++ append, structure) + val newState = "run" :: state.copy(remainingCommands = state.remainingCommands.drop(1)) + Project.setProject(session, newStructure, newState) + } + + final case class Block(offset: Int, lines: Seq[String]) + def blocks(file: File): Seq[Block] = + { + val lines = IO.readLines(file).toIndexedSeq + def blocks(b: Block, acc: List[Block]): List[Block] = + if(b.lines.isEmpty) + acc.reverse + else + { + val (dropped, blockToEnd) = b.lines.span { line => ! line.startsWith(BlockStart) } + val (block, remaining) = blockToEnd.span { line => ! line.startsWith(BlockEnd) } + val offset = b.offset + dropped.length + blocks(Block(offset + block.length, remaining), Block(offset, block.drop(1)) :: acc ) + } + blocks(Block(0, lines), Nil) + } + val BlockStart = "/***" + val BlockEnd = "*/" + def fail(s: State, msg: String): State = + { + System.err.println(msg) + s.fail + } +}