From d6d922a85845c6a878594a0bf7b39465cfb76c2a Mon Sep 17 00:00:00 2001 From: Mark Harrah Date: Fri, 13 Jul 2012 13:40:59 -0400 Subject: [PATCH] display message after 'set' with defined and affected scopes+keys --- main/Main.scala | 13 ++-- main/Project.scala | 23 +------ main/SettingCompletions.scala | 112 ++++++++++++++++++++++++++++++++++ 3 files changed, 121 insertions(+), 27 deletions(-) create mode 100644 main/SettingCompletions.scala diff --git a/main/Main.scala b/main/Main.scala index 2ab01bf18..1cd054390 100644 --- a/main/Main.scala +++ b/main/Main.scala @@ -206,15 +206,14 @@ object BuiltinCommands val extracted = Project extract s import extracted._ val settings = EvaluateConfigurations.evaluateSetting(session.currentEval(), "", imports(extracted), arg, LineRange(0,0))(currentLoader) - val newSession = if(all) Project.setAll(extracted, settings) else setThis(s, extracted, settings, arg) - reapply(newSession, structure, s) + val setResult = if(all) SettingCompletions.setAll(extracted, settings) else SettingCompletions.setThis(s, extracted, settings, arg) + s.log.info(setResult.quietSummary) + s.log.debug(setResult.verboseSummary) + reapply(setResult.session, structure, s) } + // @deprecated("Use SettingCompletions.setThis", "0.13.0") def setThis(s: State, extracted: Extracted, settings: Seq[Project.Setting[_]], arg: String) = - { - import extracted._ - val append = Load.transformSettings(Load.projectScope(currentRef), currentRef.build, rootProject, settings) - session.appendSettings( append map (a => (a, arg.split('\n').toList))) - } + SettingCompletions.setThis(s, extracted, settings, arg) def inspect = Command(InspectCommand, inspectBrief, inspectDetailed)(inspectParser) { case (s, (option, sk)) => s.log.info(inspectOutput(s, option, sk)) s diff --git a/main/Project.scala b/main/Project.scala index c0206b189..6a43280d7 100755 --- a/main/Project.scala +++ b/main/Project.scala @@ -356,26 +356,9 @@ object Project extends Init[Scope] with ProjectExtra def reverseDependencies(cMap: Map[ScopedKey[_],Flattened], scoped: ScopedKey[_]): Iterable[ScopedKey[_]] = for( (key,compiled) <- cMap; dep <- compiled.dependencies if dep == scoped) yield key - def setAll(extracted: Extracted, settings: Seq[Setting[_]]) = - { - import extracted._ - val allDefs = relation(extracted.structure, true)._1s.toSeq - val projectScope = Load.projectScope(currentRef) - def resolve(s: Setting[_]): Seq[Setting[_]] = Load.transformSettings(projectScope, currentRef.build, rootProject, s :: Nil) - def rescope[T](setting: Setting[T]): Seq[Setting[_]] = - { - val akey = setting.key.key - val global = ScopedKey(Global, akey) - val globalSetting = resolve( Project.setting(global, setting.init, setting.pos) ) - globalSetting ++ allDefs.flatMap { d => - if(d.key == akey) - Seq( SettingKey(akey) in d.scope <<= global) - else - Nil - } - } - extracted.session.appendRaw(settings flatMap { x => rescope(x) } ) - } + //@deprecated("Use SettingCompletions.setAll when available.", "0.13.0") + def setAll(extracted: Extracted, settings: Seq[Setting[_]]): SessionSettings = + SettingCompletions.setAll(extracted, settings).session val ExtraBuilds = AttributeKey[List[URI]]("extra-builds", "Extra build URIs to load in addition to the ones defined by the project.") def extraBuilds(s: State): List[URI] = getOrNil(s, ExtraBuilds) diff --git a/main/SettingCompletions.scala b/main/SettingCompletions.scala new file mode 100644 index 000000000..ce623f620 --- /dev/null +++ b/main/SettingCompletions.scala @@ -0,0 +1,112 @@ +package sbt + + import java.io.File + import java.net.URI + import Project._ + import Scope.{GlobalScope,ThisScope} + import Load.BuildStructure + import Types.{idFun, Id} + import complete.DefaultParsers + +private[sbt] class SetResult(val session: SessionSettings, val verboseSummary: String, val quietSummary: String) +private[sbt] object SettingCompletions +{ + def setAll(extracted: Extracted, settings: Seq[Setting[_]]): SetResult = + { + import extracted._ + val r = relation(extracted.structure, true) + val allDefs = r._1s.toSeq + val projectScope = Load.projectScope(currentRef) + def resolve(s: Setting[_]): Seq[Setting[_]] = Load.transformSettings(projectScope, currentRef.build, rootProject, s :: Nil) + def rescope[T](setting: Setting[T]): Seq[Setting[_]] = + { + val akey = setting.key.key + val global = ScopedKey(Global, akey) + val globalSetting = resolve( Project.setting(global, setting.init, setting.pos) ) + globalSetting ++ allDefs.flatMap { d => + if(d.key == akey) + Seq( SettingKey(akey) in d.scope <<= global) + else + Nil + } + } + val redefined = settings.flatMap(x => rescope(x)) + val session = extracted.session.appendRaw(redefined) + setResult(session, r, redefined) + } + def setThis(s: State, extracted: Extracted, settings: Seq[Project.Setting[_]], arg: String): SetResult = + { + import extracted._ + val append = Load.transformSettings(Load.projectScope(currentRef), currentRef.build, rootProject, settings) + val r = relation(extracted.structure, true) + val newSession = session.appendSettings( append map (a => (a, arg.split('\n').toList))) + setResult(newSession, r, append) + } + + def setResult(session: SessionSettings, r: Relation[ScopedKey[_], ScopedKey[_]], redefined: Seq[Setting[_]])(implicit show: Show[ScopedKey[_]]): SetResult = + { + val redefinedKeys = redefined.map(_.key).toSet + val affectedKeys = redefinedKeys.flatMap(r.reverse) + def summary(verbose: Boolean): String = setSummary(redefinedKeys, affectedKeys, verbose) + new SetResult(session, summary(true), summary(false)) + } + def setSummary(redefined: Set[ScopedKey[_]], affected: Set[ScopedKey[_]], verbose: Boolean)(implicit display: Show[ScopedKey[_]]): String = + { + val QuietLimit = 3 + def strings(in: Set[ScopedKey[_]]): Seq[String] = in.toSeq.map(sk => display(sk)).sorted + def lines(in: Seq[String]): (String, Boolean) = + if(in.isEmpty) + ("no settings or tasks.", false) + else if(verbose) + (in.mkString("\n\t", "\n\t", "\n"), false) + else + quietList(in) + def quietList(in: Seq[String]): (String, Boolean) = + { + val (first, last) = in.splitAt(QuietLimit) + if(last.isEmpty) + (first.mkString(", "), false) + else + { + val s = first.take(QuietLimit - 1).mkString("", ", ", " and " + last.size + " others.") + (s, true) + } + } + if(redefined.isEmpty) + "No settings or tasks were redefined." + else + { + val (redef, trimR) = lines(strings(redefined)) + val (used, trimU) = lines(strings(affected)) + val details = if(trimR || trimU) "\n\tRun `last` for details." else "" + val valuesString = if(redefined.size == 1) "value" else "values" + "Defining %s\nThe new %s will be used by %s%s".format(redef, valuesString, used, details) + } + } + + /* + // add support to Completions for displaying information before or after completions vertically + // or for showing a completion on a line in columns + // possibly show after a completion is selected + // show available keys. can make this sorted by relevance and show top N + // based on the key, select scopes it is defined in (Compile, `package`) or Test with all scopes being shown on second tab + // show + // := (assign value) + // ~= (update value) + // <<= (assign dependent value) + // if key type is appendable, include + // += (append value) + // ++= (append values) + // <+= (append dependent value) + // <++= (append dependent values) + // + // on execution, can indicate that the new value will be used by x, y, z and 10 more (run `last` to see all) + // + val settingParser = matched(parser) + val parser = keyParser.flatMap { key => + scope(key).* ~ assign ~ initialization) + val scope = token("in" ~ Space) ~ token(scopes <~ Space) ~ token( + val assigns = Map( + ":=" -> + */ +} \ No newline at end of file