Skip to content

Commit

Permalink
Merge pull request #184 from vigoo/repeated
Browse files Browse the repository at this point in the history
Repeated modifier
  • Loading branch information
vigoo authored Mar 12, 2021
2 parents f9c8297 + fe2ecca commit ff1e5c0
Show file tree
Hide file tree
Showing 4 changed files with 29 additions and 5 deletions.
2 changes: 2 additions & 0 deletions clipp-core/src/main/scala/io/github/vigoo/clipp/clipp.scala
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,13 @@ import io.github.vigoo.clipp.errors.ParserError

/**
* Type class for parsing a command line argument to type T
*
* @tparam T
*/
trait ParameterParser[T] {
/**
* Parse the command line argument into type T or fail with an error message
*
* @param value command line argument
* @return Either failure or the parsed value
*/
Expand Down
20 changes: 15 additions & 5 deletions clipp-core/src/main/scala/io/github/vigoo/clipp/syntax.scala
Original file line number Diff line number Diff line change
Expand Up @@ -57,19 +57,29 @@ trait syntax {
withDocumentedChoices: List[T]): Parameter.Spec[T] =
liftF(SimpleParameter(placeholder, description, Some(withDocumentedChoices), implicitly))

def command(validValues: String*): Free[Parameter, String] =
def command(validValues: String*): Parameter.Spec[String] =
liftF(Command(validValues.toList, None))

def command(validValues: List[String], withDocumentedChoices: List[String]): Free[Parameter, String] =
def command(validValues: List[String], withDocumentedChoices: List[String]): Parameter.Spec[String] =
liftF(Command(validValues, Some(withDocumentedChoices)))

def optional[T](parameter: Parameter.Spec[T]): Free[Parameter, Option[T]] =
def optional[T](parameter: Parameter.Spec[T]): Parameter.Spec[Option[T]] =
liftF[Parameter, Option[T]](Optional(parameter))

def metadata(programName: String): Free[Parameter, Unit] =
def repeated[T](parameter: Parameter.Spec[T]): Parameter.Spec[List[T]] = {
def go(acc: List[T]): Parameter.Spec[List[T]] =
optional(parameter).flatMap {
case None => pure(acc.reverse)
case Some(item) => go(item :: acc)
}

go(List.empty)
}

def metadata(programName: String): Parameter.Spec[Unit] =
liftF[Parameter, Unit](SetMetadata(ParameterParserMetadata(programName, None)))

def metadata(programName: String, description: String): Free[Parameter, Unit] =
def metadata(programName: String, description: String): Parameter.Spec[Unit] =
liftF[Parameter, Unit](SetMetadata(ParameterParserMetadata(programName, Some(description))))

def pure[T](value: T): Parameter.Spec[T] =
Expand Down
11 changes: 11 additions & 0 deletions clipp-core/src/test/scala/io/github/vigoo/clipp/ParserSpecs.scala
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ class ParserSpecs extends Specification {
verbose <- flag("Verbosity", 'v', "verbose")
} yield (verbose, name, password)

private val specMultiNamedParams = for {
names <- repeated { namedParameter[String]("Name", "name", 'n', "name", "username") }
_ <- namedParameter[String]("other", "other", "other")
} yield names

private val specMix = for {
name <- namedParameter[String]("User name", "name", 'u', "name", "username")
verbose <- flag("Verbosity", 'v', "verbose")
Expand Down Expand Up @@ -100,6 +105,12 @@ class ParserSpecs extends Specification {
)
}

"be able to collect multiple named parameters" in {
Parser.extractParameters(Seq("--name", "1", "--other", "param", "--username", "2", "-n", "3"), specMultiNamedParams) should beRight(
(List("1", "2", "3"))
)
}

"optional named parameter works" in {
val spec = for {
required <- namedParameter[String]("A required parameter", "value", "required")
Expand Down
1 change: 1 addition & 0 deletions docs/docs/docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@ The semantics of these parsing commands are the following:
- `namedParameter[T]` looks for a `--name value` pair of arguments *before the first command location* (if any), **removes both** from the list of arguments and parses the value with an instance of the `ParameterParser` type class
- `parameter[T]` takes the first argument that does not start with `-` *before the first command location* (if any) and **removes it from the list of arguments, then parses the value with an instance of the `ParameterParser` type class
- `optional` makes parser specification section optional
- `repeated` repeates a parser specification until it fails and collects the results as a list.
- `command` is a special parameter with a fix set of values, which is parsed by taking the first argument that does not start with `-` and **it drops all the arguments until the command** from the list of arguments.

The semantics of `command` strongly influences the set of CLI interfaces parseable by this library, but it is
Expand Down

0 comments on commit ff1e5c0

Please sign in to comment.