mirror of https://github.com/sbt/sbt.git
add 'project /' and 'project ..' commands
This commit is contained in:
parent
730b613007
commit
f462cda1fb
|
|
@ -79,9 +79,18 @@ trait Named
|
||||||
{
|
{
|
||||||
def name: String
|
def name: String
|
||||||
}
|
}
|
||||||
|
|
||||||
|
trait Navigation[Project]
|
||||||
|
{
|
||||||
|
def parentProject: Option[Project]
|
||||||
|
def self: Project
|
||||||
|
def initialProject(s: State): Project
|
||||||
|
def projectClosure(s: State): Seq[Project]
|
||||||
|
def rootProject: Project
|
||||||
|
}
|
||||||
trait Member[Node <: Member[Node]]
|
trait Member[Node <: Member[Node]]
|
||||||
{ self: Node =>
|
{
|
||||||
def projectClosure(state: State): Seq[Node]
|
def navigation: Navigation[Node]
|
||||||
}
|
}
|
||||||
trait Tasked
|
trait Tasked
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -53,6 +53,14 @@ ProjectCommand +
|
||||||
""" + ProjectCommand + """ name
|
""" + ProjectCommand + """ name
|
||||||
Changes to the project with the provided name.
|
Changes to the project with the provided name.
|
||||||
This command fails if there is no project with the given name.
|
This command fails if there is no project with the given name.
|
||||||
|
""" + ProjectCommand + """ /
|
||||||
|
Changes to the initial project.
|
||||||
|
""" + ProjectCommand + """ ..
|
||||||
|
Changes to the parent project of the current project.
|
||||||
|
If there is no parent project, the current project is unchanged.
|
||||||
|
|
||||||
|
Use n+1 dots to change to the nth parent.
|
||||||
|
For example, 'project ....' is equivalent to three consecutive 'project ..' commands.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def projectsBrief = (ProjectsCommand, projectsDetailed)
|
def projectsBrief = (ProjectsCommand, projectsDetailed)
|
||||||
|
|
|
||||||
|
|
@ -199,7 +199,7 @@ object Commands
|
||||||
def projects = Command { case s @ State(d: Member[_]) =>
|
def projects = Command { case s @ State(d: Member[_]) =>
|
||||||
Apply.simple(ProjectsCommand, projectsBrief, projectsDetailed ) { (in,s) =>
|
Apply.simple(ProjectsCommand, projectsBrief, projectsDetailed ) { (in,s) =>
|
||||||
val log = logger(s)
|
val log = logger(s)
|
||||||
d.projectClosure(s).foreach { case n: Named => listProject(n, d eq n, log); case _ => () }
|
d.navigation.projectClosure(s).foreach { case n: Named => listProject(n, d eq n, log); case _ => () }
|
||||||
s
|
s
|
||||||
}(s)
|
}(s)
|
||||||
}
|
}
|
||||||
|
|
@ -212,17 +212,34 @@ object Commands
|
||||||
logger(s).info(d.name)
|
logger(s).info(d.name)
|
||||||
s
|
s
|
||||||
}
|
}
|
||||||
|
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
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
d.projectClosure(s).find { case n: Named => n.name == to; case _ => false } match
|
d.navigation.projectClosure(s).find { case n: Named => n.name == to; case _ => false } match
|
||||||
{
|
{
|
||||||
case Some(np) => logger(s).info("Set current project to " + to); s.copy(np)()
|
case Some(np) => setProject(np, s)
|
||||||
case None => logger(s).error("Invalid project name '" + to + "' (type 'projects' to list available projects)."); s.fail
|
case None => logger(s).error("Invalid project name '" + to + "' (type 'projects' to list available projects)."); s.fail
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}(s)
|
}(s)
|
||||||
}
|
}
|
||||||
|
@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)()
|
||||||
|
}
|
||||||
def exit = Command { case s => Apply( Help(exitBrief) ) {
|
def exit = Command { case s => Apply( Help(exitBrief) ) {
|
||||||
case in if TerminateActions contains in.line =>
|
case in if TerminateActions contains in.line =>
|
||||||
runExitHooks(s).exit(true)
|
runExitHooks(s).exit(true)
|
||||||
|
|
|
||||||
|
|
@ -152,7 +152,12 @@ object MultiContext
|
||||||
val static = (o: Owner, s: String) => context(o).static(o, s)
|
val static = (o: Owner, s: String) => context(o).static(o, s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
final class MultiNavigation(val self: Project, val parentProject: Option[Project]) extends Navigation[Project]
|
||||||
|
{
|
||||||
|
def initialProject(s: State): Project = MultiProject.initialProject(s, rootProject)
|
||||||
|
def projectClosure(s: State): Seq[Project] = MultiProject.topologicalSort(initialProject(s))
|
||||||
|
@tailrec final lazy val rootProject: Project = parentProject match { case Some(p) => p.navigation.rootProject; case None => self }
|
||||||
|
}
|
||||||
trait Project extends Tasked with HistoryEnabled with Member[Project] with Named with ConsoleTask with Watched
|
trait Project extends Tasked with HistoryEnabled with Member[Project] with Named with ConsoleTask with Watched
|
||||||
{
|
{
|
||||||
val info: ProjectInfo
|
val info: ProjectInfo
|
||||||
|
|
@ -165,8 +170,7 @@ trait Project extends Tasked with HistoryEnabled with Member[Project] with Named
|
||||||
def historyPath = Some(outputRootPath / ".history")
|
def historyPath = Some(outputRootPath / ".history")
|
||||||
def streamBase = outputRootPath / "streams"
|
def streamBase = outputRootPath / "streams"
|
||||||
|
|
||||||
def projectClosure(s: State): Seq[Project] = MultiProject.topologicalSort(MultiProject.initialProject(s, rootProject))
|
def navigation: Navigation[Project] = new MultiNavigation(this, info.parent)
|
||||||
@tailrec final def rootProject: Project = info.parent match { case Some(p) => p.rootProject; case None => this }
|
|
||||||
|
|
||||||
implicit def streams = Dummy.Streams
|
implicit def streams = Dummy.Streams
|
||||||
def input = Dummy.In
|
def input = Dummy.In
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue