From d01c0f4157f50c43610dc53383ddf2e348b46a89 Mon Sep 17 00:00:00 2001 From: Mark Harrah Date: Tue, 4 May 2010 22:22:30 -0400 Subject: [PATCH] history help --- notes | 7 -- sbt/src/main/scala/sbt/Main.scala | 51 ++----------- .../scala/sbt/complete/HistoryCommands.scala | 76 +++++++++++++++++++ 3 files changed, 83 insertions(+), 51 deletions(-) create mode 100644 sbt/src/main/scala/sbt/complete/HistoryCommands.scala diff --git a/notes b/notes index 7d36752e2..5f336d8e4 100644 --- a/notes +++ b/notes @@ -1,10 +1,3 @@ -Added: -1. prefix continuous compilation with run number -2. Added pomRepositoryFilter(repo: MavenRepository): Boolean that excludes local repositories by default -3. Added pomPostProcess(pom: Node): Node to make advanced manipulation of the default pom easier (pomExtra covers basic cases) -4. Added 'reset' command to reset JLine terminal. This needs to be run after suspending and then resuming sbt. - - - script tasks (in 'scripts' branch). To use: 1) add implementation of jsr223 to project/build/lib, declare in project/plugins, or add to sbt startup classpath 2) Mix sbt.scripts.Scripts into your project definition diff --git a/sbt/src/main/scala/sbt/Main.scala b/sbt/src/main/scala/sbt/Main.scala index 955c81158..6287c019a 100755 --- a/sbt/src/main/scala/sbt/Main.scala +++ b/sbt/src/main/scala/sbt/Main.scala @@ -5,6 +5,8 @@ package sbt import java.io.File import scala.collection.immutable.TreeSet +import complete.HistoryCommands +import HistoryCommands.{Start => HistoryPrefix} /** This class is the entry point for sbt. If it is given any arguments, it interprets them * as actions, executes the corresponding actions, and exits. If there were no arguments provided, @@ -199,7 +201,7 @@ class xMain extends xsbti.AppMain } case action :: tail if action.startsWith(HistoryPrefix) => - historyCommand(action.substring(HistoryPrefix.length).trim, baseProject.historyPath, JLine.MaxHistorySize, project.log) match + HistoryCommands(action.substring(HistoryPrefix.length).trim, baseProject.historyPath, JLine.MaxHistorySize, project.log) match { case Some(commands) => commands.foreach(println) //better to print it than to log it @@ -280,46 +282,6 @@ class xMain extends xsbti.AppMain if(message eq null) None else Some(message) } } - private def historyCommand(s: String, historyPath: Option[Path], maxLines: Int, log: Logger): Option[List[String]] = - { - val lines = historyPath.toList.flatMap(h => xsbt.FileUtilities.readLines(h.asFile) ).toArray - if(lines.isEmpty) - { - log.warn("No history") - None - } - else - { - val ListPrefix = ":" - val history = complete.History(lines, log) - if(s.startsWith(ListPrefix)) - { - val rest = s.substring(ListPrefix.length) - val show = complete.History.number(rest).getOrElse(lines.length) - printHistory(history, maxLines, show) - Some(Nil) - } - else { - val command = historyCommand(history, s, log) - command.foreach(lines(lines.length - 1) = _) - historyPath foreach { h => xsbt.FileUtilities.writeLines(h.asFile, lines) } - Some(command.toList) - } - } - } - private def printHistory(history: complete.History, historySize: Int, show: Int): Unit = history.list(historySize, show).foreach(println) - private def historyCommand(history: complete.History, s: String, log: Logger): Option[String] = - { - val ContainsPrefix = "?" - val Last = "!" - val PreviousPrefix = "-" - if(s == Last) - history !! - else if(s.startsWith(ContainsPrefix)) - history !? s.substring(ContainsPrefix.length) - else - history ! s - } object SetProject { def unapply(s: String) = @@ -403,8 +365,6 @@ class xMain extends xsbti.AppMain val reader = new LazyJLineReader(baseProject.historyPath, MainCompletor(completors), baseProject.log) reader.readLine("> ").getOrElse(ExitCommand) } - - val HistoryPrefix = "!" /** The name of the command that loads a console with access to the current project through the variable 'project'.*/ val ProjectConsoleAction = "console-project" /** The name of the command that shows the current project and logging level of that project.*/ @@ -459,7 +419,9 @@ class xMain extends xsbti.AppMain private def logLevels: Iterable[String] = TreeSet.empty[String] ++ Level.levels.map(_.toString) /** The list of all interactive commands other than logging level.*/ private def basicCommands: Iterable[String] = TreeSet(ShowProjectsAction, ShowActions, ShowCurrent, HelpAction, - RebootCommand, TraceCommand, ContinuousCompileCommand, ProjectConsoleAction, BuilderCommand) ++ logLevels.toList ++ TerminateActions + RebootCommand, TraceCommand, ContinuousCompileCommand, ProjectConsoleAction, BuilderCommand) ++ + logLevels.toList ++ TerminateActions ++ + HistoryCommands.plainCommands private def processAction(baseProject: Project, currentProject: Project, action: String, isInteractive: Boolean): Boolean = action match @@ -497,6 +459,7 @@ class xMain extends xsbti.AppMain printCmd(CrossBuildPrefix + " ", "Executes the project specified action or method for all versions of Scala defined in crossScalaVersions.") printCmd(SpecificBuildPrefix + " ", "Changes the version of Scala building the project and executes the provided command. is optional.") printCmd(ProcessorPrefix, "Prefix for commands for managing processors. Run '" + ProcessorPrefix + "help' for details.") + printCmd(HistoryPrefix, "Prefix for history commands. Run '" + HistoryPrefix+ "' for history command help.") printCmd(ShowActions, "Shows all available actions.") printCmd(RebootCommand, "Reloads sbt, picking up modifications to sbt.version or scala.version and recompiling modified project definitions.") printCmd(HelpAction, "Displays this help message.") diff --git a/sbt/src/main/scala/sbt/complete/HistoryCommands.scala b/sbt/src/main/scala/sbt/complete/HistoryCommands.scala new file mode 100644 index 000000000..0117e922c --- /dev/null +++ b/sbt/src/main/scala/sbt/complete/HistoryCommands.scala @@ -0,0 +1,76 @@ +package sbt.complete + +object HistoryCommands +{ + val Start = "!" + // second characters + val Contains = "?" + val Last = "!" + val ListCommands = ":" + + def ContainsFull = h(Contains) + def LastFull = h(Last) + def ListFull = h(ListCommands) + + def ListN = ListFull + "n" + def ContainsString = Contains + "string" + def Previous = Start + "-n" + def Nth = Start + "n" + + private def h(s: String) = Start + s + def plainCommands = Seq(ListFull, Start, LastFull, ContainsFull) + + def descriptions = Seq( + LastFull -> "Execute the last command again", + ListFull -> "Show all previous commands", + ListN -> "Show the last n commands", + ContainsString -> "Execute the most recent command containing 'string'", + Previous -> "Execute the nth command before this one", + Nth -> ("Execute the command with index n, as shown by the " + ListFull + " command") + ) + def printHelp(log: Logger): Unit = + println("History commands:\n " + (descriptions.map{ case (c,d) => c + " " + d}).mkString("\n ")) + + def apply(s: String, historyPath: Option[Path], maxLines: Int, log: Logger): Option[List[String]] = + if(s.isEmpty) + { + printHelp(log) + Some(Nil) + } + else + { + val lines = historyPath.toList.flatMap(h => xsbt.FileUtilities.readLines(h.asFile) ).toArray + if(lines.isEmpty) + { + log.warn("No history") + None + } + else + { + val history = complete.History(lines, log) + if(s.startsWith(ListCommands)) + { + val rest = s.substring(ListCommands.length) + val show = complete.History.number(rest).getOrElse(lines.length) + printHistory(history, maxLines, show) + Some(Nil) + } + else { + val command = historyCommand(history, s, log) + command.foreach(lines(lines.length - 1) = _) + historyPath foreach { h => xsbt.FileUtilities.writeLines(h.asFile, lines) } + Some(command.toList) + } + } + } + def printHistory(history: complete.History, historySize: Int, show: Int): Unit = history.list(historySize, show).foreach(println) + def historyCommand(history: complete.History, s: String, log: Logger): Option[String] = + { + if(s == Last) + history !! + else if(s.startsWith(Contains)) + history !? s.substring(Contains.length) + else + history ! s + } +} \ No newline at end of file