mirror of https://github.com/sbt/sbt.git
Do not require leading semicolon for multi command
It has long been a frustration of mine that it is necessary to prepend multiple commands with a ';'. In this commit, I relax that restriction. I had to reorder the command definitions so that multi comes before act. This was because if the multi command did not have a leading semicolon, then it would be handled by the action parser before the multi command parser had a shot at it. Sadness ensued.
This commit is contained in:
parent
51d986d751
commit
c00cc37953
|
|
@ -39,7 +39,6 @@ object BasicCommands {
|
|||
ignore,
|
||||
help,
|
||||
completionsCommand,
|
||||
multi,
|
||||
ifLast,
|
||||
append,
|
||||
setOnFailure,
|
||||
|
|
@ -164,7 +163,10 @@ object BasicCommands {
|
|||
)
|
||||
def commandParser = state.map(s => (s.combinedParser & cmdPart) | cmdPart).getOrElse(cmdPart)
|
||||
val part = semi.flatMap(_ => matched(commandParser) <~ token(OptSpace)).map(_.trim)
|
||||
part.+ map (_.toList)
|
||||
(cmdPart.? ~ part.+).map {
|
||||
case (Some(h), t) => h.mkString.trim +: t.toList
|
||||
case (_, t) => t.toList
|
||||
}
|
||||
}
|
||||
|
||||
def multiParser(s: State): Parser[List[String]] = multiParserImpl(Some(s))
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ 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 parseEither: Either[String, Seq[String]] = Parser.parse(s, parser)
|
||||
}
|
||||
}
|
||||
import MultiParserSpec._
|
||||
|
|
@ -45,4 +46,20 @@ class MultiParserSpec extends FlatSpec with Matchers {
|
|||
"""; setStringValue "foo;bar"; checkStringValue "foo;bar"""".parse shouldBe
|
||||
Seq("""setStringValue "foo;bar"""", """checkStringValue "foo;bar"""")
|
||||
}
|
||||
it should "parse commands without leading ';'" in {
|
||||
"setStringValue foo; setStringValue bar".parse shouldBe Seq(
|
||||
"setStringValue foo",
|
||||
"setStringValue bar"
|
||||
)
|
||||
"foo; bar".parse shouldBe Seq("foo", "bar")
|
||||
"foo bar ;bar".parse shouldBe Seq("foo bar", "bar")
|
||||
"foo \"a;b\"; bar".parse shouldBe Seq("foo \"a;b\"", "bar")
|
||||
" foo ; bar \"b;c\"".parse shouldBe Seq("foo", "bar \"b;c\"")
|
||||
}
|
||||
it should "not parse single commands without leading ';'" in {
|
||||
"foo".parseEither shouldBe Left("Expected ';'\nfoo\n ^")
|
||||
"foo bar baz".parseEither shouldBe Left("Expected ';'\nfoo bar baz\n ^")
|
||||
"foo bar baz;".parseEither shouldBe
|
||||
Left("Expected not ';'\nExpected '\"'\nfoo bar baz;\n ^")
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -241,6 +241,7 @@ object BuiltinCommands {
|
|||
export,
|
||||
boot,
|
||||
initialize,
|
||||
BasicCommands.multi,
|
||||
act,
|
||||
continuous,
|
||||
flushFileTreeRepository
|
||||
|
|
|
|||
|
|
@ -7,3 +7,15 @@
|
|||
> checkStringValue bar
|
||||
|
||||
> ; setStringValue foo; setStringValue bar; setStringValue baz; checkStringValue baz
|
||||
|
||||
> setStringValue foo; setStringValue bar
|
||||
|
||||
> checkStringValue bar
|
||||
|
||||
> setStringValue foo; setStringValue bar; setStringValue baz
|
||||
|
||||
> checkStringValue baz
|
||||
|
||||
-> setStringValue foo; taskThatFails; setStringValue bar
|
||||
|
||||
> checkStringValue foo
|
||||
|
|
|
|||
|
|
@ -8,6 +8,9 @@
|
|||
|
||||
> ~; setStringValue foo; setStringValue bar; checkStringValue bar
|
||||
|
||||
# no leading semicolon
|
||||
> ~ setStringValue foo; setStringValue bar; checkStringValue bar
|
||||
|
||||
> ~ setStringValue foo
|
||||
|
||||
> checkStringValue foo
|
||||
|
|
|
|||
Loading…
Reference in New Issue