per-project commands with Commands configuration

This commit is contained in:
Mark Harrah 2011-02-08 20:38:18 -05:00
parent f780d67a78
commit 74013f3cc7
4 changed files with 36 additions and 26 deletions

View File

@ -32,30 +32,32 @@ object Command
val HistoryPath = SettingKey[Option[File]]("history")
val Analysis = AttributeKey[inc.Analysis]("analysis")
val Watch = SettingKey[Watched]("continuous-watch")
val Sample = SettingKey[String]("sample-setting")
val SampleTask = TaskKey[String]("sample-task")
val SampleInput = InputKey[String]("sample-input-task")
def command(name: String)(f: State => State): Command = command(name, Nil)(f)
def command(name: String, briefHelp: String, detail: String)(f: State => State): Command = command(name, Help(name, (name, briefHelp), detail) :: Nil)(f)
def command(name: String, help: Seq[Help])(f: State => State): Command = apply(name, help : _*)(state => success(() => f(state)))
def command(name: String, help: Seq[Help])(f: State => State): Command = make(name, help : _*)(state => success(() => f(state)))
def apply(name: String, briefHelp: (String, String), detail: String)(parser: State => Parser[() => State]): Command =
apply(name, Help(name, briefHelp, detail) )(parser)
def apply(name: String, help: Help*)(parser: State => Parser[() => State]): Command = new SimpleCommand(name, help, parser, AttributeMap.empty)
def make(name: String, briefHelp: (String, String), detail: String)(parser: State => Parser[() => State]): Command =
make(name, Help(name, briefHelp, detail) )(parser)
def make(name: String, help: Help*)(parser: State => Parser[() => State]): Command = new SimpleCommand(name, help, parser, AttributeMap.empty)
def apply[T](name: String, briefHelp: (String, String), detail: String)(parser: State => Parser[T])(effect: (State,T) => State): Command =
apply(name, Help(name, briefHelp, detail) )(parser)(effect)
def apply[T](name: String, help: Help*)(parser: State => Parser[T])(effect: (State,T) => State): Command =
make(name, help : _* )(s => applyEffect(parser(s))(t => effect(s,t)) )
def args(name: String, briefHelp: (String, String), detail: String, display: String)(f: (State, Seq[String]) => State): Command =
args(name, display, Help(name, briefHelp, detail) )(f)
def args(name: String, display: String, help: Help*)(f: (State, Seq[String]) => State): Command =
apply(name, help : _*)( state => spaceDelimited(display) map apply1(f, state) )
make(name, help : _*)( state => spaceDelimited(display) map apply1(f, state) )
def single(name: String, briefHelp: (String, String), detail: String)(f: (State, String) => State): Command =
single(name, Help(name, briefHelp, detail) )(f)
def single(name: String, help: Help*)(f: (State, String) => State): Command =
apply(name, help : _*)( state => token(trimmed(any.+.string) map apply1(f, state)) )
make(name, help : _*)( state => token(trimmed(any.+.string) map apply1(f, state)) )
def custom(parser: State => Parser[() => State], help: Seq[Help]): Command = new ArbitraryCommand(parser, help, AttributeMap.empty)
def custom(parser: State => Parser[() => State], help: Seq[Help] = Nil): Command = new ArbitraryCommand(parser, help, AttributeMap.empty)
def validID(name: String) =
Parser(OpOrID)(name).resultEmpty.isDefined

View File

@ -187,6 +187,7 @@ object Default
Name :== "test",
Version :== "0.1",
MaxErrors :== 100,
Project.Commands :== Nil,
Data <<= EvaluateTask.state map { state => Project.structure(state).data }
)
def paths = Seq(

View File

@ -24,7 +24,7 @@ class xMain extends xsbti.AppMain
{
final def run(configuration: xsbti.AppConfiguration): xsbti.MainResult =
{
import Commands.{initialize, defaults}
import BuiltinCommands.{initialize, defaults}
import CommandSupport.{DefaultsCommand, InitCommand}
val initialCommandDefs = Seq(initialize, defaults)
val commands = DefaultsCommand :: InitCommand :: configuration.arguments.map(_.trim).toList
@ -50,24 +50,24 @@ class xMain extends xsbti.AppMain
ErrorHandling.wideConvert { state.process(Command.process) } match
{
case Right(s) => s
case Left(t) => Commands.handleException(t, state)
case Left(t) => BuiltinCommands.handleException(t, state)
}
}
import DefaultParsers._
import CommandSupport._
object Commands
object BuiltinCommands
{
def DefaultCommands: Seq[Command] = Seq(ignore, help, reload, read, history, continuous, exit, loadCommands, loadProject, compile, discover,
projects, project, setOnFailure, ifLast, multi, shell, set, get, eval, delegates,alias, append, nop, sessionCommand, act)
def nop = Command.custom(s => success(() => s), Nil)
def nop = Command.custom(s => success(() => s))
def ignore = Command.command(FailureWall)(identity)
def detail(selected: Iterable[String])(h: Help): Option[String] =
h.detail match { case (commands, value) => if( selected exists commands ) Some(value) else None }
def help = Command(HelpCommand, helpBrief, helpDetailed)(helpParser)
def help = Command.make(HelpCommand, helpBrief, helpDetailed)(helpParser)
def helpParser(s: State) =
{
@ -88,7 +88,7 @@ object Commands
s
}
def alias = Command(AliasCommand, AliasBrief, AliasDetailed) { s =>
def alias = Command.make(AliasCommand, AliasBrief, AliasDetailed) { s =>
val name = token(OpOrID.examples( aliasNames(s) : _*) )
val assign = token(Space ~ '=' ~ OptSpace)
val sfree = removeAliases(s)
@ -155,7 +155,7 @@ object Commands
portAndSuccess || files
}
def read = Command(ReadCommand, ReadBrief, ReadDetailed)(s => applyEffect(readParser(s))(doRead(s)) )
def read = Command.make(ReadCommand, ReadBrief, ReadDetailed)(s => applyEffect(readParser(s))(doRead(s)) )
def doRead(s: State)(arg: Either[Int, Seq[File]]): State =
arg match
@ -201,7 +201,7 @@ object Commands
def history = Command.command("!!")(s => s)
//TODO: convert
/*def history = Command( historyHelp: _* ) { case (in, s) if in.line startsWith "!" =>
/*def history = Command.make( historyHelp: _* ) { case (in, s) if in.line startsWith "!" =>
val logError = (msg: String) => CommandSupport.logger(s).error(msg)
HistoryCommands(in.line.substring(HistoryPrefix.length).trim, (s get HistoryPath.key) getOrElse None, 500/*JLine.MaxHistorySize*/, logError) match
{
@ -220,7 +220,7 @@ object Commands
log.info("ans: " + result.tpe + " = " + result.value.toString)
s
}
def sessionCommand = Command(SessionCommand, sessionBrief, SessionSettings.Help)(SessionSettings.command)
def sessionCommand = Command.make(SessionCommand, sessionBrief, SessionSettings.Help)(SessionSettings.command)
def reapply(newSession: SessionSettings, structure: Load.BuildStructure, s: State): State =
{
logger(s).info("Reapplying settings...")
@ -268,7 +268,7 @@ object Commands
for(id <- build.defined.keys) log.info("\t" + prefix(id) + id)
}
def act = Command.custom(Act.actParser, Nil)
def act = Command.custom(Act.actParser)
def projects = Command.command(ProjectsCommand, projectsBrief, projectsDetailed ) { s =>
val extracted = Project extract s
@ -284,7 +284,7 @@ object Commands
case Some(nav) => f(nav)
}
def project = Command(ProjectCommand, projectBrief, projectDetailed)(ProjectNavigation.command)
def project = Command.make(ProjectCommand, projectBrief, projectDetailed)(ProjectNavigation.command)
def exit = Command.command(TerminateAction, Help(exitBrief) :: Nil ) ( doExit )
@ -381,9 +381,12 @@ object Commands
s.fail
}
def removeAliases(s: State): State = s.copy(processors = removeAliases(s.processors))
def removeAliases(as: Seq[Command]): Seq[Command] = as.filter(c => ! (c.tags contains CommandAliasKey))
def removeAliases(s: State): State = removeTagged(s, CommandAliasKey)
def removeAlias(s: State, name: String): State = s.copy(processors = s.processors.filter(c => !isAliasNamed(name, c)) )
def removeTagged(s: State, tag: AttributeKey[_]): State = s.copy(processors = removeTagged(s.processors, tag))
def removeTagged(as: Seq[Command], tag: AttributeKey[_]): Seq[Command] = as.filter(c => ! (c.tags contains tag))
def isAliasNamed(name: String, c: Command): Boolean = isNamed(name, getAlias(c))
def isNamed(name: String, alias: Option[(String,String)]): Boolean = alias match { case None => false; case Some((n,_)) => name == n }
@ -400,7 +403,7 @@ object Commands
s.processors.flatMap(c => getAlias(c).filter(tupled(pred)))
def newAlias(name: String, value: String): Command =
Command(name, (name, "'" + value + "'"), "Alias of '" + value + "'")(aliasBody(name, value)).tag(CommandAliasKey, (name, value))
Command.make(name, (name, "'" + value + "'"), "Alias of '" + value + "'")(aliasBody(name, value)).tag(CommandAliasKey, (name, value))
def aliasBody(name: String, value: String)(state: State): Parser[() => State] =
Parser(Command.combine(state.processors)(state))(value)

View File

@ -72,8 +72,10 @@ object Project extends Init[Scope]
val data = structure.data
val historyPath = HistoryPath in ref get data flatMap identity
val commands = (Commands in ref get data).toList.flatten[Command].map(_ tag (ProjectCommand, true))
val newProcessors = commands ++ BuiltinCommands.removeTagged(s.processors, ProjectCommand)
val newAttrs = s.attributes.put(Watch.key, makeWatched(data, ref, project)).put(HistoryPath.key, historyPath)
s.copy(attributes = newAttrs)
s.copy(attributes = newAttrs, processors = newProcessors)
}
def makeSettings(settings: Seq[Setting[_]], delegates: Scope => Seq[Scope], scopeLocal: ScopedKey[_] => Seq[Setting[_]]) =
translateUninitialized( make(settings)(delegates, scopeLocal) )
@ -133,12 +135,14 @@ object Project extends Init[Scope]
def reverseDependencies(cMap: CompiledMap, scoped: ScopedKey[_]): Iterable[ScopedKey[_]] =
for( (key,compiled) <- cMap; dep <- compiled.dependencies if dep == scoped) yield key
val ProjectCommand = AttributeKey[Boolean]("project-command")
val SessionKey = AttributeKey[SessionSettings]("session-settings")
val StructureKey = AttributeKey[Load.BuildStructure]("build-structure")
val AppConfig = SettingKey[xsbti.AppConfiguration]("app-configuration")
val ThisProject = SettingKey[Project]("project")
val ThisProjectRef = SettingKey[ProjectRef]("project-ref")
val Config = SettingKey[Configuration]("configuration")
val Commands = SettingKey[Seq[Command]]("commands")
}
import SessionSettings._
@ -166,7 +170,7 @@ object SessionSettings
type SessionMap = Map[(URI, String), Seq[SessionSetting]]
def reapply(session: SessionSettings, s: State): State =
Commands.reapply(session, Project.structure(s), s)
BuiltinCommands.reapply(session, Project.structure(s), s)
def clearSettings(s: State): State =
withSettings(s)(session => reapply(session.copy(append = session.append - session.current), s))