/* sbt -- Simple Build Tool * Copyright 2008, 2009, 2010, 2011 Mark Harrah */ package sbt import ProjectNavigation._ import Project.updateCurrent import Keys.sessionSettings import complete.{DefaultParsers, Parser} import DefaultParsers._ import java.net.URI object ProjectNavigation { def command(s: State): Parser[() => State] = if(s get sessionSettings isEmpty) failure("No project loaded") else (new ProjectNavigation(s)).command } final class ProjectNavigation(s: State) { val extracted = Project extract s import extracted.{currentRef, structure, session} def setProject(nuri: URI, nid: String) = { val neval = if(currentRef.build == nuri) session.currentEval else mkEval(nuri) updateCurrent(s.put(sessionSettings, session.setCurrent(nuri, nid, neval))) } def mkEval(nuri: URI) = Load.lazyEval(structure.units(nuri).unit) def getRoot(uri: URI) = Load.getRootProject(structure.units)(uri) def apply(action: Option[ResolvedReference]): State = action match { case None => show(); s case Some(BuildRef(uri)) => changeBuild(uri) case Some(ProjectRef(uri, id)) => selectProject(uri, id) /* else if(to.forall(_ == '.')) if(to.length > 1) gotoParent(to.length - 1, nav, s) else s */ // semantics currently undefined } def show(): Unit = s.log.info(currentRef.project + " (in build " + currentRef.build + ")") def selectProject(uri: URI, to: String): State = if( structure.units(uri).defined.contains(to) ) setProject(uri, to) else fail("Invalid project name '" + to + "' in build " + uri + " (type 'projects' to list available projects).") def changeBuild(newBuild: URI): State = if(structure.units contains newBuild) setProject(newBuild, getRoot(newBuild)) else fail("Invalid build unit '" + newBuild + "' (type 'projects' to list available builds).") def fail(msg: String): State = { s.log.error(msg) s.fail } import complete.Parser._ import complete.Parsers._ val parser: Parser[Option[ResolvedReference]] = { val reference = Act.resolvedReference(structure.index.keyIndex, currentRef.build, success(())) val root = token('/' ^^^ rootRef) success(None) | some( token(Space) ~> (root | reference) ) } def rootRef = ProjectRef(currentRef.build, getRoot(currentRef.build)) val command: Parser[() => State] = Command.applyEffect(parser)(apply) }