Skip to content

Commit

Permalink
initial import
Browse files Browse the repository at this point in the history
  • Loading branch information
eed3si9n committed Nov 20, 2011
0 parents commit 4c5f5cb
Show file tree
Hide file tree
Showing 5 changed files with 211 additions and 0 deletions.
49 changes: 49 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
sbt-inspectr is an sbt plugin for calling inspect recursively.

## latest
0.0.1

## how to setup
Add the following to your `~/.sbt/plugins/build.sbt`:

addSbtPlugin("com.eed3si9n" % "sbt-inspectr" % "X.X.X")

## how to use
The above automatically adds `inspectr` command.
It displays the value of the key, and then displays all of its dependencies and their values in a tree.

```
helloworld> inspectr package
[info] compile:package = Task[java.io.File]
[info] +-compile:package-bin = Task[java.io.File]
[info] +-compile:package-configuration(for package-bin) = Task[sbt.Packag..
[info] | +-compile:mappings(for package-bin) = Task[scala.collection.Seq[..
[info] | | +-compile:products = Task[scala.collection.Seq[java.io.File]]
[info] | |
[info] | +-compile:artifact-path(for package-bin) = target/scala-2.9.1/he..
[info] | | +-*/*:artifact-name = <function3>
[info] | | +-*:cross-target = target/scala-2.9.1
[info] | | +-*/*:scala-version = 2.9.1
[info] | | +-compile:artifact(for package-bin) = Artifact(helloworld,jar,..
[info] | | | +-*/*:artifact-classifier = None
[info] | | | +-compile:configuration = compile
[info] | | |
[info] | | +-*:project-id = production:helloworld:0.1-SNAPSHOT
[info] | |
[info] | +-compile:package-options(for package-bin) = Task[scala.collecti..
[info] | +-*:name = helloworld
[info] | +-compile:main-class = Task[scala.Option[java.lang.String]]
[info] | +-*:organization-name = production
[info] | +-*:organization = production
[info] | +-*/*:homepage = None
[info] | +-*/*:package-options = Task[scala.collection.Seq[sbt.PackageO..
[info] | +-*/*:version = 0.1-SNAPSHOT
[info] |
[info] +-compile:cache-directory(for package-bin) = target/scala-2.9.1/ca..
[info] +-compile:streams(for package-bin) = Task[sbt.std.TaskStreams[sbt...
[info] +-*/*:streams-manager = Task[sbt.std.Streams[sbt.Init$ScopedKey[..
[info]
```

## License
MIT License.
27 changes: 27 additions & 0 deletions build.sbt
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
sbtPlugin := true

name := "sbt-inspectr"

organization := "com.eed3si9n"

version := "0.0.1"

scalacOptions := Seq("-deprecation", "-unchecked")

publishTo <<= version { (v: String) =>
val nexus = "http://nexus.scala-tools.org/content/repositories/"
if(v endsWith "-SNAPSHOT") Some("Scala Tools Nexus" at nexus + "snapshots/")
else Some("Scala Tools Nexus" at nexus + "releases/")
}

credentials += Credentials(Path.userHome / ".ivy2" / ".credentials")

publishArtifact in (Compile, packageBin) := true

publishArtifact in (Test, packageBin) := false

publishArtifact in (Compile, packageDoc) := false

publishArtifact in (Compile, packageSrc) := false

publishMavenStyle := true
97 changes: 97 additions & 0 deletions src/main/scala/sbtinspectr/Inspectr.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
package sbtinspectr

import sbt._
import Keys._
import sbt.Project.{ScopedKey, flattenLocals, compiled}
import sbt.Load.BuildStructure

// see http://harrah.github.com/xsbt/latest/sxr/Project.scala.html
object Inspectr {
def apply(structure: BuildStructure, build: URI, scoped: ScopedKey[_],
generation: Int)(implicit display: Show[ScopedKey[_]]): Inspectr = {
val key = scoped.key
val scope = scoped.scope

lazy val clazz = key.manifest.erasure
lazy val firstType = key.manifest.typeArguments.head
val (typeName: String, value: Option[_]) =
structure.data.get(scope, key) match {
case None => ("", None)
case Some(v) =>
if(clazz == classOf[Task[_]]) ("Task[" + firstType.toString + "]", None)
else if(clazz == classOf[InputTask[_]]) ("InputTask[" + firstType.toString + "]", None)
else (key.manifest.toString, Some(v))
}

val description = key.description getOrElse{""}
val definedIn = structure.data.definingScope(scope, key) match {
case Some(sc) => display(ScopedKey(sc, key))
case None => ""
}
val cMap = flattenLocals(compiled(structure.settings, false)(structure.delegates, structure.scopeLocal, display))
// val related = cMap.keys.filter(k => k.key == key && k.scope != scope)
val depends = cMap.get(scoped) match { case Some(c) => c.dependencies.toSet; case None => Set.empty }
// val reverse = reverseDependencies(cMap, scoped)

Inspectr(display(scoped), definedIn, typeName, value, description, build,
depends map { apply(structure, build, _, generation + 1) })
}
}

case class Inspectr(name: String,
definedIn: String,
typeName: String,
value: Option[Any],
description: String,
build: URI,
depends: Set[Inspectr]) {
// [info] foo
// [info] +-bar
// [info] | +-baz
// [info] |
// [info] +-quux
def toAscii: String = {
toAsciiLines(0).mkString("\n")
}

private def toAsciiLines(level: Int): Vector[String] = {
def valueString: String =
value map {
case f: File =>
try {
val base = new File(build)
val rel: String = ((f :: Nil) x relativeTo(base)).head._2
if (rel.length < f.toString.length) rel
else f.toString
} catch {
case _ => f.toString
}
case x => x.toString
} getOrElse {typeName}

def toLine(level: Int): String = {
val s = (" " * level) +
(if (level == 0) "" else "+-") + definedIn +
" = " + valueString
if (s.length > 72) s.slice(0, 70) + ".."
else s
}

def insertBar(s: String, at: Int): String =
s.slice(0, at) +
(s(at).toString match {
case " " => "|"
case x => x
}) +
s.slice(at + 1, s.length)

val dependLines = Vector(depends.toSeq: _*) map {_.toAsciiLines(level + 1)}
val withBar = dependLines.zipWithIndex flatMap {
case (lines, pos) if pos < (depends.size - 1) => lines map {insertBar(_, 2 * (level + 1))}
case (lines, pos) =>
if (lines.last.trim != "") lines ++ Vector(" " * (level + 1))
else lines
}
toLine(level) +: withBar
}
}
30 changes: 30 additions & 0 deletions src/main/scala/sbtinspectr/InspectrCommand.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package sbtinspectr

object InspectrCommand {
import sbt._
import Keys._
import complete.Parser
import complete.DefaultParsers._
import CommandSupport.logger

val inspectrCommand = "inspectr"
val inspectrBrief = (inspectrCommand + " <key>", "Prints the value for 'key', and all of its dependencies' values.")
val inspectrDetailed = inspectrCommand + """ <key>
For a plain setting, the value bound to the key argument is displayed
using its toString method.
Otherwise, the type of task ("Task" or "Input task") is displayed.
The process is repeated recursively for all of the settings that this
setting depends on, and displayed as a tree.
"""

def inspectr = Command(inspectrCommand, inspectrBrief, inspectrDetailed)(inspectrParser) { case (s, (sk)) =>
// see http://harrah.github.com/xsbt/latest/sxr/Main.scala.html
implicit val show = Project.showContextKey(s)
val tree = Inspectr(Project.structure(s), Project.session(s).current.build, sk, 0).toAscii
logger(s).info(tree)
s
}

lazy val inspectrParser = (s: State) => BuiltinCommands.spacedKeyParser(s)
}
8 changes: 8 additions & 0 deletions src/main/scala/sbtinspectr/Plugin.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package sbtinspectr

import sbt._
import Keys._

object Plugin extends sbt.Plugin {
override lazy val settings = Seq(commands ++= Seq(InspectrCommand.inspectr))
}

0 comments on commit 4c5f5cb

Please sign in to comment.