diff --git a/main-command/src/main/scala/sbt/BasicCommands.scala b/main-command/src/main/scala/sbt/BasicCommands.scala index 6ea7a6f9c..b78e147bb 100644 --- a/main-command/src/main/scala/sbt/BasicCommands.scala +++ b/main-command/src/main/scala/sbt/BasicCommands.scala @@ -208,10 +208,11 @@ object BasicCommands { else Parser.success(result.toList) } - (cmdParser ~ multiCmdParser.+).flatMap { - case ("", rest) => validateCommands(rest) - case (p, rest) => validateCommands(rest).map(p :: _) - } + (cmdParser ~ multiCmdParser.+) + .flatMap { + case ("", rest) => validateCommands(rest) + case (p, rest) => validateCommands(rest).map(p :: _) + } } def multiParser(s: State): Parser[List[String]] = multiParserImpl(Some(s)) diff --git a/main-command/src/main/scala/sbt/Command.scala b/main-command/src/main/scala/sbt/Command.scala index 2244660a4..ec224b551 100644 --- a/main-command/src/main/scala/sbt/Command.scala +++ b/main-command/src/main/scala/sbt/Command.scala @@ -184,7 +184,8 @@ object Command { ) def process(command: String, state: State): State = { - parse(command, state.combinedParser) match { + (if (command.contains(";")) parse(command, state.combinedParser) + else parse(command, state.nonMultiParser)) match { case Right(s) => s() // apply command. command side effects happen here case Left(errMsg) => state.log error errMsg diff --git a/main-command/src/main/scala/sbt/State.scala b/main-command/src/main/scala/sbt/State.scala index 32fd3c7a8..1d044cb3c 100644 --- a/main-command/src/main/scala/sbt/State.scala +++ b/main-command/src/main/scala/sbt/State.scala @@ -53,7 +53,11 @@ final case class State( private[sbt] lazy val (multiCommands, nonMultiCommands) = definedCommands.partition(_.nameOption.contains(BasicCommandStrings.Multi)) private[sbt] lazy val nonMultiParser = Command.combine(nonMultiCommands)(this) - lazy val combinedParser = multiCommands.foldRight(nonMultiParser)(_.parser(this) | _) + lazy val combinedParser: Parser[() => State] = + multiCommands.headOption match { + case Some(multi) => multi.parser(this) | nonMultiParser + case _ => nonMultiParser + } def source: Option[CommandSource] = currentCommand match { diff --git a/main-command/src/test/scala/sbt/MultiParserSpec.scala b/main-command/src/test/scala/sbt/MultiParserSpec.scala index a2f580f10..88aea432d 100644 --- a/main-command/src/test/scala/sbt/MultiParserSpec.scala +++ b/main-command/src/test/scala/sbt/MultiParserSpec.scala @@ -14,7 +14,10 @@ import sbt.internal.util.complete.Parser object MultiParserSpec { val parser: Parser[Seq[String]] = BasicCommands.multiParserImpl(None) implicit class StringOps(val s: String) { - def parse: Seq[String] = Parser.parse(s, parser).right.get + def parse: Seq[String] = Parser.parse(s, parser) match { + case Right(x) => x + case Left(x) => sys.error(s) + } def parseEither: Either[String, Seq[String]] = Parser.parse(s, parser) } }