diff --git a/README.md b/README.md index 52dd980e4..e1075d3fd 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,7 @@ project directory, the runner will figure out the versions of sbt and scala required by the project and download them if necessary. There's also a template project sbt coming together, but it's unfinished. +See below for how to pull the template project in as a plugin. However the runner is quite useful already. Here's a sample use of the runner: it creates a new project using a @@ -97,3 +98,25 @@ Current -help output: In the case of duplicated or conflicting options, the order above shows precedence: JAVA_OPTS lowest, command line options highest. + + +## Template project + +To gain access to the awesome, simply add the following /project/plugins/project/Build.scala file: + + import sbt._ + object PluginDef extends Build { + override def projects = Seq(root) + lazy val root = Project("plugins", file(".")) dependsOn(extras) + lazy val extras = uri("git://github.com/jsuereth/sbt-extras") + } + +Now to continue the amazement, simply extend the TemplateBuild trait in your project. For example, in your +/project/Build.scala file add: + + import sbt._ + import template.TemplateBuild + + object MyAwesomeBuild extends TemplateBuild {} + +The Template build isn't quite finished. There will most likely be a build.sbt DSL variant that does not require a project scala file. diff --git a/build.sbt b/build.sbt new file mode 100644 index 000000000..e227a442a --- /dev/null +++ b/build.sbt @@ -0,0 +1,8 @@ +sbtPlugin := true + +name := "sbt-extras-plugin" + +organization := "org.improving" + +version <<= (sbtVersion)("0.1.0-%s".format(_)) + diff --git a/project/Build.scala b/project/Build.scala deleted file mode 100644 index 49ca97009..000000000 --- a/project/Build.scala +++ /dev/null @@ -1,119 +0,0 @@ -import sbt._ -import Keys._ -import Load.{ BuildStructure, StructureIndex } -import scala.collection.{ mutable, immutable } - -trait SbtCreateConfig { - def name: String - def organization: String - def version: String - def scalaVersion: String -} -object SbtCreateConfig { - private def prop(propName: String, alt: String) = System.getProperty(propName) match { - case null => alt - case value => value - } - implicit def defaultProjectConfig = new SbtCreateConfig { - def name = prop("sbt-create.name", "project-name-here") - def organization = prop("sbt-create.organization", "your.organization.here") - def version = prop("sbt-create.version", "0.1-SNAPSHOT") - def scalaVersion = prop("sbt.scala.version", "2.9.0-1") - } -} - -class TemplateBuild(implicit sbtCreateConfig: SbtCreateConfig) extends Build { - // BuildStructure contains: - // units: Map[URI, LoadedBuildUnit] - // root: URI - // settings: Seq[Setting[_]] - // data: Settings[Scope] - // index: StructureIndex - // streams: Streams - // delegates: Scope => Seq[Scope] - // scopeLocal: ScopeLocal - - private val cachedExtraction = new collection.mutable.HashMap[State, WState] - private implicit def stateWrapper(state: State): WState = - cachedExtraction.getOrElseUpdate(state, new WState(state)) - private implicit def revealStructure(state: State): BuildStructure = - stateWrapper(state).structure - private implicit def revealStructureIndex(state: State): StructureIndex = - revealStructure(state).index - private implicit def revealSession(state: State): SessionSettings = - stateWrapper(state).session - - private class WState(state: State) { - val extracted = Project extract state - - def projectId = extracted.currentProject.id - def structure = extracted.structure - def session = extracted.session - def currentRef = extracted.currentRef - def rootProject = structure.rootProject - def allProjects = structure.allProjects - - def index = structure.index - def taskToKey = index.taskToKey - def keyMap = index.keyMap // Map[String, AttributeKey[_]] - def keyIndex = index.keyIndex - def currentKeys = keyIndex keys Some(currentRef) map index.keyMap - def sortedKeys = currentKeys.toSeq sortBy (_.label) - } - - private class Tap[T](target: T) { - def show(): Unit = target match { - case xs: TraversableOnce[_] => xs foreach println - case _ => println(target) - } - def tap[U](f: T => U): T = { - f(target) - target - } - } - private implicit def createTapper[T](target: T): Tap[T] = new Tap(target) - - def currentBranch = ("git status -sb".lines_! headOption) getOrElse "-" stripPrefix "## " - - val buildShellPrompt = { - (state: State) => "%s:%s>".format( - state.projectId, - currentBranch - ) - } - - lazy val testSettings = Seq( - libraryDependencies ++= Seq( - "org.scala-tools.testing" % "specs_2.9.0-1" % "1.6.8" % "test" - ), - libraryDependencies <+= (scalaVersion)(v => "org.scala-lang" % "scala-compiler" % v) - ) - - lazy val buildSettings = Seq( - resolvers += ScalaToolsSnapshots, - organization := sbtCreateConfig.organization, - version := sbtCreateConfig.version, - scalaVersion := sbtCreateConfig.scalaVersion, - // retrieveManaged := true, - shellPrompt := buildShellPrompt - // logLevel := Level.Debug, - ) - - lazy val templateConfig = Project( - id = sbtCreateConfig.name, - base = file("."), - aggregate = Nil, - dependencies = Nil, - delegates = Nil, - settings = Defaults.defaultSettings ++ buildSettings ++ testSettings ++ Seq( - commands += helpNames - ) - ) - - // A sample command definition. - def helpNames = Command.command("help-names") { (state: State) => - state tap (_.sortedKeys map (_.label) show) - } -} - -object TemplateBuild extends TemplateBuild { } diff --git a/src/main/scala/Main.scala b/src/main/scala/Main.scala index bff37c687..7727601c7 100644 --- a/src/main/scala/Main.scala +++ b/src/main/scala/Main.scala @@ -1,7 +1,121 @@ package template -object Main { - def main(args: Array[String]): Unit = { - println("Skeleton main, reporting for duty on " + util.Properties.versionString) +import sbt._ +import Keys._ +import Load.{ BuildStructure, StructureIndex } +import scala.collection.{ mutable, immutable } + +object SbtExtrasPlugin extends Plugin {} + +trait SbtCreateConfig { + def name: String + def organization: String + def version: String + def scalaVersion: String +} +object SbtCreateConfig { + private def prop(propName: String, alt: String) = System.getProperty(propName) match { + case null => alt + case value => value + } + implicit def defaultProjectConfig = new SbtCreateConfig { + def name = prop("sbt-create.name", "project-name-here") + def organization = prop("sbt-create.organization", "your.organization.here") + def version = prop("sbt-create.version", "0.1-SNAPSHOT") + def scalaVersion = prop("sbt.scala.version", "2.9.0-1") + } +} + +class TemplateBuild(implicit sbtCreateConfig: SbtCreateConfig) extends Build { + // BuildStructure contains: + // units: Map[URI, LoadedBuildUnit] + // root: URI + // settings: Seq[Setting[_]] + // data: Settings[Scope] + // index: StructureIndex + // streams: Streams + // delegates: Scope => Seq[Scope] + // scopeLocal: ScopeLocal + + private val cachedExtraction = new collection.mutable.HashMap[State, WState] + private implicit def stateWrapper(state: State): WState = + cachedExtraction.getOrElseUpdate(state, new WState(state)) + private implicit def revealStructure(state: State): BuildStructure = + stateWrapper(state).structure + private implicit def revealStructureIndex(state: State): StructureIndex = + revealStructure(state).index + private implicit def revealSession(state: State): SessionSettings = + stateWrapper(state).session + + private class WState(state: State) { + val extracted = Project extract state + + def projectId = extracted.currentProject.id + def structure = extracted.structure + def session = extracted.session + def currentRef = extracted.currentRef + def rootProject = structure.rootProject + def allProjects = structure.allProjects + + def index = structure.index + def taskToKey = index.taskToKey + def keyMap = index.keyMap // Map[String, AttributeKey[_]] + def keyIndex = index.keyIndex + def currentKeys = keyIndex keys Some(currentRef) map index.keyMap + def sortedKeys = currentKeys.toSeq sortBy (_.label) + } + + private class Tap[T](target: T) { + def show(): Unit = target match { + case xs: TraversableOnce[_] => xs foreach println + case _ => println(target) + } + def tap[U](f: T => U): T = { + f(target) + target + } + } + private implicit def createTapper[T](target: T): Tap[T] = new Tap(target) + + def currentBranch = ("git status -sb".lines_! headOption) getOrElse "-" stripPrefix "## " + + val buildShellPrompt = { + (state: State) => "%s:%s> ".format( + state.projectId, + currentBranch + ) + } + + lazy val testSettings = Seq( + libraryDependencies ++= Seq( + "org.scala-tools.testing" % "specs_2.9.0-1" % "1.6.8" % "test" + ), + libraryDependencies <+= (scalaVersion)(v => "org.scala-lang" % "scala-compiler" % v) + ) + + lazy val buildSettings = Seq( + resolvers += ScalaToolsSnapshots, + organization := sbtCreateConfig.organization, + version := sbtCreateConfig.version, + scalaVersion := sbtCreateConfig.scalaVersion, + // retrieveManaged := true, + shellPrompt := buildShellPrompt + // logLevel := Level.Debug, + ) + + lazy val templateConfig = Project( + id = sbtCreateConfig.name, + base = file("."), + aggregate = Nil, + dependencies = Nil, + delegates = Nil, + settings = Defaults.defaultSettings ++ buildSettings ++ testSettings ++ Seq( + commands += helpNames + ) + ) + + // A sample command definition. + def helpNames = Command.command("help-names") { (state: State) => + state tap (_.sortedKeys map (_.label) show) } }