diff --git a/compile/AnalyzingCompiler.scala b/compile/AnalyzingCompiler.scala index 923d82c4a..f66fa2375 100644 --- a/compile/AnalyzingCompiler.scala +++ b/compile/AnalyzingCompiler.scala @@ -38,15 +38,15 @@ class AnalyzingCompiler(val scalaInstance: ScalaInstance, val manager: Component call("xsbt.ScaladocInterface", 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, log: Logger)(loader: Option[ClassLoader] = None, bindings: Seq[(String, Any)] = Nil): Unit = + 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.createBootClasspath else "" val (names, values) = bindings.unzip call("xsbt.ConsoleInterface", log)( - classOf[Array[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, loader.orNull, names.toArray[String], values.toArray[Any], 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) } def force(log: Logger): Unit = getInterfaceJar(log) private def call(interfaceClassName: String, log: Logger)(argTypes: Class[_]*)(args: AnyRef*) diff --git a/compile/interface/ConsoleInterface.scala b/compile/interface/ConsoleInterface.scala index b56e3c345..d19035b31 100644 --- a/compile/interface/ConsoleInterface.scala +++ b/compile/interface/ConsoleInterface.scala @@ -11,7 +11,7 @@ import scala.tools.nsc.util.ClassPath class ConsoleInterface { - def run(args: Array[String], bootClasspathString: String, classpathString: String, initialCommands: String, loader: ClassLoader, bindNames: Array[String], bindValues: Array[Any], log: Logger) + 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) @@ -47,6 +47,12 @@ class ConsoleInterface if(!initialCommands.isEmpty) interpreter.interpret(initialCommands) } + override def closeInterpreter() + { + if(!cleanupCommands.isEmpty) + interpreter.interpret(cleanupCommands) + super.closeInterpreter() + } } loop.main(if(loader eq null) compilerSettings else interpreterSettings) } diff --git a/main/ConsoleProject.scala b/main/ConsoleProject.scala index de84f5e56..86e5f761c 100644 --- a/main/ConsoleProject.scala +++ b/main/ConsoleProject.scala @@ -8,7 +8,7 @@ package sbt object ConsoleProject { - def apply(state: State, extra: String, options: Seq[String] = Nil)(implicit log: Logger) + def apply(state: State, extra: String, cleanupCommands: String = "", options: Seq[String] = Nil)(implicit log: Logger) { val extracted = Project extract state val bindings = ("currentState" -> state) :: ("extracted" -> extracted ) :: Nil @@ -17,6 +17,6 @@ object ConsoleProject val imports = Load.getImports(unit.unit) ++ Load.importAll(bindings.map(_._1)) val importString = imports.mkString("", ";\n", ";\n\n") val initCommands = importString + extra - (new Console(compiler))(unit.classpath, options, initCommands)(Some(unit.loader), bindings) + (new Console(compiler))(unit.classpath, options, initCommands, cleanupCommands)(Some(unit.loader), bindings) } } diff --git a/main/Defaults.scala b/main/Defaults.scala index ac4fbac83..e465f2927 100644 --- a/main/Defaults.scala +++ b/main/Defaults.scala @@ -191,6 +191,7 @@ object Defaults extends BuildCommon lazy val configTasks = docSetting(doc) ++ Seq( initialCommands in GlobalScope :== "", + cleanupCommands in GlobalScope :== "", compile <<= compileTask, compileInputs <<= compileInputsTask, compileIncSetup <<= compileIncSetupTask, @@ -461,9 +462,9 @@ object Defaults extends BuildCommon def consoleProjectTask = (state, streams, initialCommands in consoleProject) map { (state, s, extra) => ConsoleProject(state, extra)(s.log); println() } def consoleTask: Initialize[Task[Unit]] = consoleTask(fullClasspath, console) def consoleQuickTask = consoleTask(externalDependencyClasspath, consoleQuick) - def consoleTask(classpath: TaskKey[Classpath], task: TaskKey[_]): Initialize[Task[Unit]] = (compilers in task, classpath in task, scalacOptions in task, initialCommands in task, streams) map { - (cs, cp, options, initCommands, s) => - (new Console(cs.scalac))(data(cp), options, initCommands, s.log).foreach(msg => error(msg)) + 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, streams) map { + (cs, cp, options, initCommands, cleanup, s) => + (new Console(cs.scalac))(data(cp), options, initCommands, cleanup, s.log).foreach(msg => error(msg)) println() } diff --git a/main/Keys.scala b/main/Keys.scala index 2220ea977..f04c55782 100644 --- a/main/Keys.scala +++ b/main/Keys.scala @@ -127,6 +127,7 @@ object Keys val javacOptions = SettingKey[Seq[String]]("javac-options", "Options for the Java compiler.") val compileOrder = SettingKey[CompileOrder.Value]("compile-order", "Configures the order in which Java and sources within a single compilation are compiled. Valid values are: JavaThenScala, ScalaThenJava, or Mixed.") val initialCommands = SettingKey[String]("initial-commands", "Initial commands to execute when starting up the Scala interpreter.") + val cleanupCommands = SettingKey[String]("cleanup-commands", "Commands to execute before the Scala interpreter exits.") val compileInputs = TaskKey[Compiler.Inputs]("compile-inputs", "Collects all inputs needed for compilation.") val scalaHome = SettingKey[Option[File]]("scala-home", "If Some, defines the local Scala installation to use for compilation, running, and testing.") val scalaInstance = TaskKey[ScalaInstance]("scala-instance", "Defines the Scala instance to use for compilation, running, and testing.") diff --git a/main/actions/Console.scala b/main/actions/Console.scala index f4e03ce30..86960e852 100644 --- a/main/actions/Console.scala +++ b/main/actions/Console.scala @@ -10,17 +10,17 @@ final class Console(compiler: AnalyzingCompiler) { /** Starts an interactive scala interpreter session with the given classpath.*/ def apply(classpath: Seq[File], log: Logger): Option[String] = - apply(classpath, Nil, "", log) + apply(classpath, Nil, "", "", log) - def apply(classpath: Seq[File], options: Seq[String], initialCommands: String, log: Logger): Option[String] = - apply(classpath, options, initialCommands)(None, Nil)(log) + def apply(classpath: Seq[File], options: Seq[String], initialCommands: String, cleanupCommands: String, log: Logger): Option[String] = + apply(classpath, options, initialCommands, cleanupCommands)(None, Nil)(log) - def apply(classpath: Seq[File], options: Seq[String], loader: ClassLoader, initialCommands: String)(bindings: (String, Any)*)(implicit log: Logger): Option[String] = - apply(classpath, options, initialCommands)(Some(loader), bindings) + def apply(classpath: Seq[File], options: Seq[String], loader: ClassLoader, initialCommands: String, cleanupCommands: String)(bindings: (String, Any)*)(implicit log: Logger): Option[String] = + apply(classpath, options, initialCommands, cleanupCommands)(Some(loader), bindings) - def apply(classpath: Seq[File], options: Seq[String], initialCommands: String)(loader: Option[ClassLoader], bindings: Seq[(String, Any)])(implicit log: Logger): Option[String] = + def apply(classpath: Seq[File], options: Seq[String], initialCommands: String, cleanupCommands: String)(loader: Option[ClassLoader], bindings: Seq[(String, Any)])(implicit log: Logger): Option[String] = { - def console0 = compiler.console(classpath, options, initialCommands, log)(loader, bindings) + def console0 = compiler.console(classpath, options, initialCommands, cleanupCommands, log)(loader, bindings) JLine.withJLine( Run.executeTrapExit(console0, log) ) } }