mirror of https://github.com/sbt/sbt.git
more improvements to 'tasks' and 'settings' commands
This commit is contained in:
parent
75dfccf098
commit
c358a8a5b0
|
|
@ -126,13 +126,19 @@ It does not list the scopes the %<s are defined in; use the 'inspect' command fo
|
|||
|
||||
def settingsBrief(label: String) = (label, "Displays the " + label + " defined for the current project.")
|
||||
def settingsDetailed(label: String) =
|
||||
"""%s -[v|vv|...|V]
|
||||
"""%s [-(v|vv|...|V)] [filter]
|
||||
|
||||
Displays the %<s defined directly or indirectly for the current project.
|
||||
Additional %<s may be displayed by providing -v, -vv, ... or -V for all %<s.
|
||||
""".format(label)
|
||||
Additional %<s may be displayed by providing -v, -vv, ... or providing
|
||||
-V to display all %<s.
|
||||
|
||||
def moreAvailableMessage(label: String) = "More " + label + " may be viewed by increasing verbosity. See '" + BasicCommandStrings.HelpCommand + " " + label + "'.\n"
|
||||
A filter may be given to restrict the %<s shown. The names of %<s are searched for an exact match against the filter, in which case only the description of the exact match is displayed. Otherwise, the filter is interpreted as a regular expression and all %<s whose name or description match the regular expression are displayed.
|
||||
|
||||
Note that this is an additional filter on top of the %<s selected by the -v style switches, so you must specify -V to search all tasks. Use the %s command to search all commands, tasks, and settings at once.
|
||||
""".format(label, BasicCommandStrings.HelpCommand)
|
||||
|
||||
def moreAvailableMessage(label: String, search: Boolean) =
|
||||
"More %s may be %s by increasing verbosity. See '%s %s'.\n".format(label, if(search) "searched" else "viewed", BasicCommandStrings.HelpCommand, label)
|
||||
|
||||
def aboutBrief = "Displays basic information about sbt and the build."
|
||||
def aboutDetailed = aboutBrief
|
||||
|
|
|
|||
|
|
@ -241,7 +241,7 @@ object Keys
|
|||
val updateConfiguration = SettingKey[UpdateConfiguration]("update-configuration", "Configuration for resolving and retrieving managed dependencies.", DSetting)
|
||||
val ivySbt = TaskKey[IvySbt]("ivy-sbt", "Provides the sbt interface to Ivy.", CTask)
|
||||
val ivyModule = TaskKey[IvySbt#Module]("ivy-module", "Provides the sbt interface to a configured Ivy module.", CTask)
|
||||
val update = TaskKey[UpdateReport]("update", "Resolves and optionally retrieves dependencies, producing a report.", ASetting)
|
||||
val update = TaskKey[UpdateReport]("update", "Resolves and optionally retrieves dependencies, producing a report.", ATask)
|
||||
val transitiveUpdate = TaskKey[Seq[UpdateReport]]("transitive-update", "UpdateReports for the internal dependencies of this project.", DTask)
|
||||
val updateClassifiers = TaskKey[UpdateReport]("update-classifiers", "Resolves and optionally retrieves classified artifacts, such as javadocs and sources, for dependency definitions, transitively.", BPlusTask, update)
|
||||
val transitiveClassifiers = SettingKey[Seq[String]]("transitive-classifiers", "List of classifiers used for transitively obtaining extra artifacts for sbt or declared dependencies.", BSetting)
|
||||
|
|
|
|||
|
|
@ -131,21 +131,26 @@ object BuiltinCommands
|
|||
def tasks = showSettingLike(TasksCommand, tasksPreamble, KeyRanks.MainTaskCutoff, key => isTask(key.manifest) )
|
||||
|
||||
def showSettingLike(command: String, preamble: String, cutoff: Int, keep: AttributeKey[_] => Boolean) =
|
||||
Command(command, settingsBrief(command), settingsDetailed(command))(const(verbosityParser)) { (s: State, verbosity: Int) =>
|
||||
System.out.println(preamble)
|
||||
val prominentOnly = verbosity <= 1
|
||||
val verboseFilter = if(prominentOnly) highPass(cutoff) else topNRanked(25*verbosity)
|
||||
System.out.println(tasksHelp(s, keys => verboseFilter(keys filter keep) ))
|
||||
System.out.println()
|
||||
if(prominentOnly) System.out.println(moreAvailableMessage(command))
|
||||
s
|
||||
Command(command, settingsBrief(command), settingsDetailed(command))(showSettingParser(keep)) {
|
||||
case (s: State, (verbosity: Int, selected: Option[String])) =>
|
||||
if(selected.isEmpty) System.out.println(preamble)
|
||||
val prominentOnly = verbosity <= 1
|
||||
val verboseFilter = if(prominentOnly) highPass(cutoff) else topNRanked(25*verbosity)
|
||||
System.out.println(tasksHelp(s, keys => verboseFilter(keys filter keep), selected ))
|
||||
System.out.println()
|
||||
if(prominentOnly) System.out.println(moreAvailableMessage(command, selected.isDefined))
|
||||
s
|
||||
}
|
||||
def showSettingParser(keepKeys: AttributeKey[_] => Boolean)(s: State): Parser[(Int, Option[String])] =
|
||||
verbosityParser ~ selectedParser(s, keepKeys).?
|
||||
def selectedParser(s: State, keepKeys: AttributeKey[_] => Boolean): Parser[String] =
|
||||
singleArgument( allTaskAndSettingKeys(s).filter(keepKeys).map(_.label).toSet )
|
||||
def verbosityParser: Parser[Int] = success(1) | ((Space ~ "-") ~> (
|
||||
'v'.id.+.map(_.size + 1) |
|
||||
("V" ^^^ Int.MaxValue)
|
||||
) )
|
||||
def taskDetail(keys: Seq[AttributeKey[_]], filter: Seq[AttributeKey[_]] => Seq[AttributeKey[_]]): Seq[(String,String)] =
|
||||
sortByLabel(filter(withDescription(keys))) flatMap taskStrings
|
||||
def taskDetail(keys: Seq[AttributeKey[_]]): Seq[(String,String)] =
|
||||
sortByLabel(withDescription(keys)) flatMap taskStrings
|
||||
|
||||
def allTaskAndSettingKeys(s: State): Seq[AttributeKey[_]] =
|
||||
{
|
||||
|
|
@ -163,8 +168,14 @@ object BuiltinCommands
|
|||
def topNRanked(n: Int) = (keys: Seq[AttributeKey[_]]) => sortByRank(keys).take(n)
|
||||
def highPass(rankCutoff: Int) = (keys: Seq[AttributeKey[_]]) => sortByRank(keys).takeWhile(_.rank <= rankCutoff)
|
||||
|
||||
def tasksHelp(s: State, filter: Seq[AttributeKey[_]] => Seq[AttributeKey[_]]): String =
|
||||
aligned(" ", " ", taskDetail(allTaskAndSettingKeys(s), filter)) mkString("\n", "\n", "")
|
||||
def tasksHelp(s: State, filter: Seq[AttributeKey[_]] => Seq[AttributeKey[_]], arg: Option[String]): String =
|
||||
{
|
||||
val commandAndDescription = taskDetail(filter(allTaskAndSettingKeys(s)))
|
||||
arg match {
|
||||
case Some(selected) =>detail(selected, commandAndDescription.toMap)
|
||||
case None => aligned(" ", " ", commandAndDescription) mkString("\n", "\n", "")
|
||||
}
|
||||
}
|
||||
|
||||
def taskStrings(key: AttributeKey[_]): Option[(String, String)] = key.description map { d => (key.label, d) }
|
||||
|
||||
|
|
@ -314,7 +325,7 @@ object BuiltinCommands
|
|||
def actHelp = (s: State) => CommandStrings.showHelp ++ keysHelp(s)
|
||||
def keysHelp(s: State): Help =
|
||||
if(Project.isProjectLoaded(s))
|
||||
Help.detailOnly(taskDetail(allTaskAndSettingKeys(s), idFun))
|
||||
Help.detailOnly(taskDetail(allTaskAndSettingKeys(s)))
|
||||
else
|
||||
Help.empty
|
||||
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@ package sbt
|
|||
import BasicKeys._
|
||||
|
||||
import java.io.File
|
||||
import java.util.regex.Pattern
|
||||
|
||||
object BasicCommands
|
||||
{
|
||||
|
|
@ -27,47 +26,18 @@ object BasicCommands
|
|||
{
|
||||
val h = (Help.empty /: s.definedCommands)(_ ++ _.help(s))
|
||||
val helpCommands = h.detail.keySet
|
||||
val arg = (NotSpaceClass ~ any.*) map { case (ns, s) => (ns +: s).mkString }
|
||||
val spacedArg = (token(Space) ~> token( arg examples helpCommands )).?
|
||||
val spacedArg = singleArgument(helpCommands).?
|
||||
applyEffect(spacedArg)(runHelp(s, h))
|
||||
}
|
||||
|
||||
def runHelp(s: State, h: Help)(arg: Option[String]): State =
|
||||
{
|
||||
val message = arg match {
|
||||
case None =>
|
||||
aligned(" ", " ", h.brief).mkString("\n", "\n", "\n")
|
||||
case Some(x) =>
|
||||
detail(x, h.detail)
|
||||
case None => aligned(" ", " ", h.brief).mkString("\n", "\n", "\n")
|
||||
case Some(x) => detail(x, h.detail)
|
||||
}
|
||||
System.out.println(message)
|
||||
s
|
||||
}
|
||||
def detail(selected: String, detailMap: Map[String, String]): String =
|
||||
detailMap.get(selected) match
|
||||
{
|
||||
case Some(exactDetail) =>exactDetail
|
||||
case None => layoutDetails(searchHelp(selected, detailMap))
|
||||
}
|
||||
def searchHelp(selected: String, detailMap: Map[String, String]): Map[String, String] =
|
||||
{
|
||||
val pattern = Pattern.compile(selected, HelpPatternFlags)
|
||||
detailMap flatMap { case (k,v) =>
|
||||
val contentMatches = Highlight.showMatches(pattern)(v)
|
||||
val keyMatches = Highlight.showMatches(pattern)(k)
|
||||
val keyString = Highlight.bold(keyMatches getOrElse k)
|
||||
val contentString = contentMatches getOrElse v
|
||||
if(keyMatches.isDefined || contentMatches.isDefined)
|
||||
(keyString, contentString) :: Nil
|
||||
else
|
||||
Nil
|
||||
}
|
||||
}
|
||||
def layoutDetails(details: Map[String,String]): String =
|
||||
details.map { case (k,v) => k + ":\n\n " + v } mkString("\n", "\n\n", "\n")
|
||||
|
||||
final val HelpPatternFlags = Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE
|
||||
|
||||
def multiParser(s: State): Parser[Seq[String]] =
|
||||
{
|
||||
val nonSemi = token(charClass(_ != ';').+, hide= const(true))
|
||||
|
|
|
|||
|
|
@ -1,6 +1,10 @@
|
|||
package sbt
|
||||
|
||||
import java.io.File
|
||||
import java.util.regex.Pattern
|
||||
|
||||
import complete.Parser
|
||||
import complete.DefaultParsers._
|
||||
|
||||
object CommandUtil
|
||||
{
|
||||
|
|
@ -29,4 +33,37 @@ object CommandUtil
|
|||
case None => s.log.error(ifMissing); s.fail
|
||||
case Some(nav) => f(nav)
|
||||
}
|
||||
|
||||
def singleArgument(exampleStrings: Set[String]): Parser[String] =
|
||||
{
|
||||
val arg = (NotSpaceClass ~ any.*) map { case (ns, s) => (ns +: s).mkString }
|
||||
token(Space) ~> token( arg examples exampleStrings )
|
||||
}
|
||||
def detail(selected: String, detailMap: Map[String, String]): String =
|
||||
detailMap.get(selected) match
|
||||
{
|
||||
case Some(exactDetail) =>exactDetail
|
||||
case None =>
|
||||
val details = searchHelp(selected, detailMap)
|
||||
if(details.isEmpty) "No matches for regular expression '" + selected + "'." else layoutDetails(details)
|
||||
}
|
||||
def searchHelp(selected: String, detailMap: Map[String, String]): Map[String, String] =
|
||||
{
|
||||
val pattern = Pattern.compile(selected, HelpPatternFlags)
|
||||
detailMap flatMap { case (k,v) =>
|
||||
val contentMatches = Highlight.showMatches(pattern)(v)
|
||||
val keyMatches = Highlight.showMatches(pattern)(k)
|
||||
val keyString = Highlight.bold(keyMatches getOrElse k)
|
||||
val contentString = contentMatches getOrElse v
|
||||
if(keyMatches.isDefined || contentMatches.isDefined)
|
||||
(keyString, contentString) :: Nil
|
||||
else
|
||||
Nil
|
||||
}
|
||||
}
|
||||
def layoutDetails(details: Map[String,String]): String =
|
||||
details.map { case (k,v) => k + ":\n\n " + v } mkString("\n", "\n\n", "\n")
|
||||
|
||||
final val HelpPatternFlags = Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE
|
||||
|
||||
}
|
||||
Loading…
Reference in New Issue