mirror of https://github.com/sbt/sbt.git
command cleanup, load project by default, prompt on load failure
This commit is contained in:
parent
aadcd0c9fb
commit
04910baf2f
|
|
@ -86,8 +86,8 @@ object Act
|
||||||
processResult(result, logger(s), show)
|
processResult(result, logger(s), show)
|
||||||
s
|
s
|
||||||
}
|
}
|
||||||
def actParser(s: State): Parser[() => State] =
|
def actParser(s: State): Parser[() => State] = requireSession(s, actParser0(s))
|
||||||
if(s get Project.SessionKey isEmpty) failure("No project loaded") else actParser0(s)
|
|
||||||
private[this] def actParser0(state: State) =
|
private[this] def actParser0(state: State) =
|
||||||
{
|
{
|
||||||
val extracted = Project extract state
|
val extracted = Project extract state
|
||||||
|
|
@ -103,4 +103,8 @@ object Act
|
||||||
val defaultConf = (ref: ProjectRef) => if(Project.getProject(ref, structure).isDefined) defaultConfig(structure.data)(ref) else None
|
val defaultConf = (ref: ProjectRef) => if(Project.getProject(ref, structure).isDefined) defaultConfig(structure.data)(ref) else None
|
||||||
scopedKey(structure.index.keyIndex, curi, cid, defaultConf, structure.index.keyMap)
|
scopedKey(structure.index.keyIndex, curi, cid, defaultConf, structure.index.keyMap)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def requireSession[T](s: State, p: => Parser[T]): Parser[T] =
|
||||||
|
if(s get Project.SessionKey isEmpty) failure("No project loaded") else p
|
||||||
}
|
}
|
||||||
|
|
@ -151,10 +151,10 @@ ProjectCommand +
|
||||||
def DefaultsBrief = (DefaultsCommand, DefaultsDetailed)
|
def DefaultsBrief = (DefaultsCommand, DefaultsDetailed)
|
||||||
def DefaultsDetailed = "Registers default built-in commands"
|
def DefaultsDetailed = "Registers default built-in commands"
|
||||||
|
|
||||||
def ReloadCommand = "reload"
|
def RebootCommand = "reboot"
|
||||||
def ReloadBrief = "Reloads the session and then executes the remaining commands."
|
def RebootBrief = "Reboots sbt and then executes the remaining commands."
|
||||||
def ReloadDetailed =
|
def RebootDetailed =
|
||||||
ReloadCommand + """
|
RebootCommand + """
|
||||||
This command is equivalent to exiting, restarting, and running the
|
This command is equivalent to exiting, restarting, and running the
|
||||||
remaining commands with the exception that the jvm is not shut down.
|
remaining commands with the exception that the jvm is not shut down.
|
||||||
"""
|
"""
|
||||||
|
|
@ -232,14 +232,17 @@ CompileSyntax + """
|
||||||
Cached information about the compilation will be written to 'cache'.
|
Cached information about the compilation will be written to 'cache'.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
val FailureWall = "--"
|
val FailureWall = "---"
|
||||||
|
|
||||||
def Load = "load"
|
def Load = "load"
|
||||||
def LoadLabel = "a project"
|
def LoadLabel = "a project"
|
||||||
def LoadCommand = "load-commands"
|
def LoadCommand = "load-commands"
|
||||||
def LoadCommandLabel = "commands"
|
def LoadCommandLabel = "commands"
|
||||||
|
|
||||||
def LoadProject = "loadp"
|
def LoadFailed = "load-failed"
|
||||||
|
|
||||||
|
def LoadProjectImpl = "loadp"
|
||||||
|
def LoadProject = "reload"
|
||||||
def LoadProjectBrief = LoadProjectDetailed
|
def LoadProjectBrief = LoadProjectDetailed
|
||||||
def LoadProjectDetailed = "Loads the project in the current directory"
|
def LoadProjectDetailed = "Loads the project in the current directory"
|
||||||
|
|
||||||
|
|
@ -247,6 +250,7 @@ CompileSyntax + """
|
||||||
def ShellBrief = ShellDetailed
|
def ShellBrief = ShellDetailed
|
||||||
def ShellDetailed = "Provides an interactive prompt from which commands can be run."
|
def ShellDetailed = "Provides an interactive prompt from which commands can be run."
|
||||||
|
|
||||||
|
def ClearOnFailure = "--"
|
||||||
def OnFailure = "-"
|
def OnFailure = "-"
|
||||||
def OnFailureBrief = (OnFailure + " command", "Registers 'command' to run if a command fails.")
|
def OnFailureBrief = (OnFailure + " command", "Registers 'command' to run if a command fails.")
|
||||||
def OnFailureDetailed =
|
def OnFailureDetailed =
|
||||||
|
|
|
||||||
|
|
@ -24,10 +24,10 @@ class xMain extends xsbti.AppMain
|
||||||
{
|
{
|
||||||
final def run(configuration: xsbti.AppConfiguration): xsbti.MainResult =
|
final def run(configuration: xsbti.AppConfiguration): xsbti.MainResult =
|
||||||
{
|
{
|
||||||
import BuiltinCommands.{initialize, defaults}
|
import BuiltinCommands.{initialize, defaults, DefaultBootCommands}
|
||||||
import CommandSupport.{DefaultsCommand, InitCommand}
|
import CommandSupport.{DefaultsCommand, InitCommand}
|
||||||
val initialCommandDefs = Seq(initialize, defaults)
|
val initialCommandDefs = Seq(initialize, defaults)
|
||||||
val commands = DefaultsCommand :: InitCommand :: configuration.arguments.map(_.trim).toList
|
val commands = DefaultsCommand +: InitCommand +: (DefaultBootCommands ++ configuration.arguments.map(_.trim))
|
||||||
val state = State( configuration, initialCommandDefs, Set.empty, None, commands, initialAttributes, Next.Continue )
|
val state = State( configuration, initialCommandDefs, Set.empty, None, commands, initialAttributes, Next.Continue )
|
||||||
run(state)
|
run(state)
|
||||||
}
|
}
|
||||||
|
|
@ -58,8 +58,9 @@ class xMain extends xsbti.AppMain
|
||||||
import CommandSupport._
|
import CommandSupport._
|
||||||
object BuiltinCommands
|
object BuiltinCommands
|
||||||
{
|
{
|
||||||
def DefaultCommands: Seq[Command] = Seq(ignore, help, reload, read, history, continuous, exit, loadCommands, loadProject, compile, discover,
|
def DefaultCommands: Seq[Command] = Seq(ignore, help, reboot, read, history, continuous, exit, loadCommands, loadProject, loadProjectImpl, loadFailed, compile, discover,
|
||||||
projects, project, setOnFailure, ifLast, multi, shell, set, inspect, eval, alias, append, last, lastGrep, nop, sessionCommand, act)
|
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
|
||||||
|
|
||||||
def nop = Command.custom(s => success(() => s))
|
def nop = Command.custom(s => success(() => s))
|
||||||
def ignore = Command.command(FailureWall)(identity)
|
def ignore = Command.command(FailureWall)(identity)
|
||||||
|
|
@ -135,8 +136,9 @@ object BuiltinCommands
|
||||||
def setOnFailure = Command.single(OnFailure, OnFailureBrief, OnFailureDetailed) { (s, arg) =>
|
def setOnFailure = Command.single(OnFailure, OnFailureBrief, OnFailureDetailed) { (s, arg) =>
|
||||||
s.copy(onFailure = Some(arg))
|
s.copy(onFailure = Some(arg))
|
||||||
}
|
}
|
||||||
|
def clearOnFailure = Command.command(ClearOnFailure)(s => s.copy(onFailure = None))
|
||||||
|
|
||||||
def reload = Command.command(ReloadCommand, ReloadBrief, ReloadDetailed) { s =>
|
def reboot = Command.command(RebootCommand, RebootBrief, RebootDetailed) { s =>
|
||||||
s.runExitHooks().reload
|
s.runExitHooks().reload
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -244,8 +246,8 @@ object BuiltinCommands
|
||||||
Output.lastGrep(sk.scope, sk.key, Project.structure(s).streams, pattern)
|
Output.lastGrep(sk.scope, sk.key, Project.structure(s).streams, pattern)
|
||||||
s
|
s
|
||||||
}
|
}
|
||||||
val spacedKeyParser = (s: State) => token(Space) ~> Act.scopedKeyParser(s)
|
val spacedKeyParser = (s: State) => Act.requireSession(s, token(Space) ~> Act.scopedKeyParser(s))
|
||||||
def lastGrepParser(s: State) = (token(Space) ~> token(NotSpace, "<pattern>")) ~ spacedKeyParser(s)
|
def lastGrepParser(s: State) = Act.requireSession(s, (token(Space) ~> token(NotSpace, "<pattern>")) ~ spacedKeyParser(s))
|
||||||
def last = Command(LastCommand, lastBrief, lastDetailed)(spacedKeyParser) { (s,sk) =>
|
def last = Command(LastCommand, lastBrief, lastDetailed)(spacedKeyParser) { (s,sk) =>
|
||||||
Output.last(sk.scope, sk.key, Project.structure(s).streams)
|
Output.last(sk.scope, sk.key, Project.structure(s).streams)
|
||||||
s
|
s
|
||||||
|
|
@ -305,7 +307,29 @@ object BuiltinCommands
|
||||||
} catch { case e: xsbti.CompileFailed => s.fail /* already logged */ }
|
} catch { case e: xsbti.CompileFailed => s.fail /* already logged */ }
|
||||||
}
|
}
|
||||||
|
|
||||||
def loadProject = Command.command(LoadProject, LoadProjectBrief, LoadProjectDetailed) { s =>
|
def loadFailed = Command.command(LoadFailed)(handleLoadFailed)
|
||||||
|
@tailrec def handleLoadFailed(s: State): State =
|
||||||
|
{
|
||||||
|
val result = (SimpleReader.readLine("Project loading failed: (r)etry, (q)uit, or (i)gnore? ") getOrElse Quit).toLowerCase
|
||||||
|
def matches(s: String) = !result.isEmpty && (s startsWith result)
|
||||||
|
|
||||||
|
if(matches("retry"))
|
||||||
|
LoadProject :: s
|
||||||
|
else if(matches(Quit))
|
||||||
|
s.exit(ok = false)
|
||||||
|
else if(matches("ignore"))
|
||||||
|
s
|
||||||
|
else
|
||||||
|
{
|
||||||
|
println("Invalid response.")
|
||||||
|
handleLoadFailed(s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def loadProjectCommands = (OnFailure + " " + LoadFailed) :: LoadProjectImpl :: ClearOnFailure :: FailureWall :: Nil
|
||||||
|
def loadProject = Command.command(LoadProject, LoadProjectBrief, LoadProjectDetailed) { loadProjectCommands ::: _ }
|
||||||
|
|
||||||
|
def loadProjectImpl = Command.command(LoadProjectImpl) { s =>
|
||||||
val (eval, structure) = Load.defaultLoad(s, logger(s))
|
val (eval, structure) = Load.defaultLoad(s, logger(s))
|
||||||
val session = Load.initialSession(structure, eval)
|
val session = Load.initialSession(structure, eval)
|
||||||
Project.setProject(session, structure, s)
|
Project.setProject(session, structure, s)
|
||||||
|
|
|
||||||
|
|
@ -228,9 +228,11 @@ object SessionSettings
|
||||||
{
|
{
|
||||||
val project = Project.getProject(pref, structure).getOrElse(error("Invalid project reference " + pref))
|
val project = Project.getProject(pref, structure).getOrElse(error("Invalid project reference " + pref))
|
||||||
val appendTo: File = BuildPaths.configurationSources(project.base).headOption.getOrElse(new File(project.base, "build.sbt"))
|
val appendTo: File = BuildPaths.configurationSources(project.base).headOption.getOrElse(new File(project.base, "build.sbt"))
|
||||||
val sbtAppend = settingStrings(settings).flatMap("" :: _ :: Nil)
|
val baseAppend = settingStrings(settings).flatMap("" :: _ :: Nil)
|
||||||
IO.writeLines(appendTo, sbtAppend, append = true)
|
val adjustedLines = if( hasTrailingBlank(IO.readLines(appendTo)) ) baseAppend else baseAppend
|
||||||
|
IO.writeLines(appendTo, adjustedLines, append = true)
|
||||||
}
|
}
|
||||||
|
def hasTrailingBlank(lines: Seq[String]) = lines.takeRight(1).exists(_.trim.isEmpty)
|
||||||
def printAllSettings(s: State): State =
|
def printAllSettings(s: State): State =
|
||||||
withSettings(s){ session =>
|
withSettings(s){ session =>
|
||||||
for( ((uri,id), settings) <- session.append if !settings.isEmpty) {
|
for( ((uri,id), settings) <- session.append if !settings.isEmpty) {
|
||||||
|
|
|
||||||
|
|
@ -65,16 +65,17 @@ object State
|
||||||
{
|
{
|
||||||
val remaining = s.commands.dropWhile(_ != FailureWall)
|
val remaining = s.commands.dropWhile(_ != FailureWall)
|
||||||
if(remaining.isEmpty)
|
if(remaining.isEmpty)
|
||||||
{
|
applyOnFailure(s, Nil, exit(ok = false))
|
||||||
s.onFailure match
|
|
||||||
{
|
|
||||||
case Some(c) => s.copy(commands = c :: Nil, onFailure = None)
|
|
||||||
case None => exit(ok = false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
s.copy(commands = remaining)
|
applyOnFailure(s, remaining, s.copy(commands = remaining))
|
||||||
}
|
}
|
||||||
|
private[this] def applyOnFailure(s: State, remaining: Seq[String], noHandler: => State): State =
|
||||||
|
s.onFailure match
|
||||||
|
{
|
||||||
|
case Some(c) => s.copy(commands = c +: remaining, onFailure = None)
|
||||||
|
case None => noHandler
|
||||||
|
}
|
||||||
|
|
||||||
def runExitHooks(): State = {
|
def runExitHooks(): State = {
|
||||||
ExitHooks.runExitHooks(s.exitHooks.toSeq)
|
ExitHooks.runExitHooks(s.exitHooks.toSeq)
|
||||||
s.copy(exitHooks = Set.empty)
|
s.copy(exitHooks = Set.empty)
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
*/
|
*/
|
||||||
package sbt
|
package sbt
|
||||||
|
|
||||||
import CommandSupport.FailureWall
|
import CommandSupport.{ClearOnFailure,FailureWall}
|
||||||
import annotation.tailrec
|
import annotation.tailrec
|
||||||
|
|
||||||
trait Watched
|
trait Watched
|
||||||
|
|
@ -41,7 +41,7 @@ object Watched
|
||||||
val (triggered, newWatchState) = SourceModificationWatch.watch(sourcesFinder, PollDelaySeconds, watchState)(shouldTerminate)
|
val (triggered, newWatchState) = SourceModificationWatch.watch(sourcesFinder, PollDelaySeconds, watchState)(shouldTerminate)
|
||||||
|
|
||||||
if(triggered)
|
if(triggered)
|
||||||
(next :: FailureWall :: repeat :: s).put(ContinuousState, newWatchState)
|
(ClearOnFailure :: next :: FailureWall :: repeat :: s).put(ContinuousState, newWatchState)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
while (System.in.available() > 0) System.in.read()
|
while (System.in.available() > 0) System.in.read()
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue