Packages

  • package root
    Definition Classes
    root
  • package com
    Definition Classes
    root
  • package loopfor
    Definition Classes
    com
  • package scalop

    A simple option parser.

    A simple option parser.

    Overview

    An option parser is an ordered collection of option name and option processor pairs that matches on a sequence of arguments, yielding a map of option names to option values. As the parser recognizes option names in the argument sequence, it applies the corresponding processor function to obtain the option value. This process is repeated until the argument sequence is exhausted or the parser encounters an error.

    An option name can be expressed in both long and short form. For any given sequence of arguments, long options are detected by the presence of a -- prefix and short options with a - prefix. Examples include --verbose and -v, respectively.

    An option processor is an arbitrary function whose purpose is to return a value that gets assigned to the option name. A processor may consider and absorb subsequent arguments in computing the value, such as --timeout that might expect the next argument to be an integer. Library users are encouraged to utilize the predefined builder methods rather than implement processor functions from scratch.

    Option Construction

    The construction of an option is best done using the DSL, which is available from the following import statement.

    import com.loopfor.scalop._

    The following is a simple option that demonstrates how the DSL is used to pair an option name with a corresponding processor.

    val opt = ("verbose", 'v') ~> just(true)

    The ~> method triggers an implicit conversion of the tuple ("verbose", 'v') into an option name and then binds the processor function just(true), resulting in an option.

    An option can also be adorned with a default value upon construction using the ~~ operator following the processor function. Doing so ensures that the option is assigned the default value in the absence of being specified in an argument sequence at the time of parsing.

    val opt = ("verbose", 'v') ~> just(true) ~~ false

    A sequence of options can then be constructed using the :: operator. Note that the order of options is important since the parser will evaluate arguments against those options based on traversal order of the sequence.

    val opts = ("verbose", 'v') ~> just(true) ~~ false ::
               ("timeout", 't') ~> as[Int] ~~ 0 ::
               "encoding" ~> as[Charset] ~~ Charset.forName("UTF-8") ::
               '?' ~> just(true) ~~ false ::
               Nil
    Replacing Options

    A replacing option is one which replaces values previously assigned to an option name during argument parsing. Options of this type are created using the ~> operator.

    For example:

    val opt = "timeout" ~> as[Int]

    Given the following sequence of arguments, the value of timeout at the completion of parsing would be 60.

    --timeout 30 --timeout 60
    Appending Options

    An appending option is one which appends values to a sequence of values previously assigned to an option name during argument parsing. Options of this type are created using the ~>+ operator.

    For example:

    val opt = "server" ~>+ as[String]

    Given the following sequence of arguments, the value of server at the completion of parsing would be Seq("foo.com", "bar.com").

    --server foo.com --server bar.com
    Parser Construction

    The construction of an option parser happens implicitly when the <~ operator is applied to either a single option or a sequence of options.

    The following illustrates the evaluation of arguments against a sequence of options. Note that an ephemeral instance of an option parser is constructed as a byproduct of applying the <~ operator.

    val opts = ("verbose", 'v') ~> just(true) ~~ false ::
               ("timeout", 't') ~> as[Int] ~~ 0 ::
               "encoding" ~> as[Charset] ~~ Charset.forName("UTF-8") ::
               '?' ~> just(true) ~~ false ::
               Nil
    
    val optr = opts <~ Seq("--verbose", "-t", "30", "--encoding", "iso-8859-1", "this", "and", "that")

    In the aforementioned example, invoking the parser with the given sequence of arguments produces an option result containing a map of option names to option values. Notice that a value is associated with both long and short forms of the option name regardless of which form is specified in the argument sequence.

    "verbose" -> true
    "v" -> true
    "timeout" -> 30
    "t" -> 30
    "encoding" -> Charset(ISO-8859-1)
    "?" -> false
    "@" -> Seq("this", "and", "that")

    The @ option is a special name containing all non-option values trailing the last option in the argument sequence.

    Parser Behavior

    Given a sequence of arguments, such as those provided by a shell when supplying arguments to a command line program, an option parser behaves in the following manner.

    The parser recursively applies the following algorithm as it traverses the argument sequence.

    • If the next argument is equal to "--", the sequence of all subsequent arguments is assigned to the special option name "@" and the parser terminates, returning the option value map. By convention, the -- option is used to explicitly terminate options so that remaining arguments, which might be prefixed with -- or -, are not treated as options.
    • If the next argument is either a long or short option name recognized by the parser, the corresponding processor function is applied to the remaining arguments, yielding a value, which is then associated with the option name, both long and short, in the option value map. However, if the argument happens to be an option that is not recognized by the parser, then an exception is thrown. Otherwise, the parser is recursively applied to the remaining sequence of arguments.
    • If the next argument is not an option, implying that it contains neither a -- nor a - prefix, then the remaining argument sequence is assigned to the "@" option and the parser terminates.

    Finally, default values for each option are assigned to the option value map if values for those corresponding options are absent.

    In cases where values, which follow an option, contain either a - or -- prefix, such values must be escaped by prepending the \ character. Otherwise, the parser will interpret the value as an option and proceed accordingly.

    The following example will parse incorrectly since -10 will be interpreted as an option.

    --time-adjust -10

    The correct way to specify this value is as follows:

    --time-adjust \-10
    Option Processors

    An option processor is a function accepting as input:

    • the sequence of arguments that follow an option name

    and returning as output a tuple containing:

    • the sequence of arguments following those consumed by the processor
    • the option value

    The argument sequence provided as input are those that follow the recognized option. For example, given the following argument sequence:

    --verbose -F foo.out --timeout 10
    

    Assuming -F was recognized by the parser, then the sequence provided to the associated processor function would be:

    Seq("foo.out", "--timeout", "10")

    Since a processor may expect additional arguments following the option, as is the case with -F, the resulting sequence will be the arguments that follow those absorbed by the processor, which in this case, would be:

    Seq("--timeout", "10")

    In cases where a processor requires additional arguments, it is often necessary to perform some degree of validation or transformation, both of which may fail. Exceptions that propagate beyond the processor function are caught by the parser and converted to OptException. Additionally, the yell() methods are provided as a convenience for processor implementations to throw instances of OptException.

    Processor Construction

    A processor is typically constructed using one of the predefined builders, the choice of which depends on the nature of the option.

    For standalone options with no additional argument, the just builder can be used to explicitly assign a value.

    ("verbose", 'v') ~> just(true)

    For options that contain one additional argument, the as builders simplify construction of the processor by standardizing the manner in which error cases are handled, such as missing arguments and problems encountered with argument converters.

    The simplest form of using as follows, which essentially converts the argument into the parameterized type.

    ("timeout", 't') ~> as[Int]

    As with all uses of as, an argument converter must be implicitly defined or supplied directly to the function. Argument converters are discussed in more detail below.

    A secondary form of using as accepts a user-supplied function, which performs additional processing on the argument once converted. The result of that function becomes the value of the option.

    The following example illustrates how a function can be used for validation or alteration.

    ("timeout", 't') ~> as { arg: Int => if (arg < 0) 0 else arg }

    The type of the return value does not need to match the type of the converted argument, which is demonstrated below.

    ("timeout", 't') ~> as { arg: Int => (if (arg < 0) 0 else arg).seconds }

    For options that might contain an additional argument, the maybe builders are similar to their as counterparts in that the handling of error cases is standardized. All processors constructed in this manner yield Option[A] rather than A. This is necessary to distinguish between the presence or absence of a subsequent argument.

    The simplest form of using maybe is demonstrated below.

    val opts = "help" ~> maybe[String]

    The value of the option will vary depending on the arguments provided to the parser:

    optr = opts <~ Seq()
    optr("help") // undefined
    
    optr = opts <~ Seq("--help")
    optr("help") == None
    
    optr = opts <~ Seq("--help", "foo")
    optr("help") == Some("foo")

    A secondary form of using maybe accepts a user-supplied function, but is invoked only if a subsequent argument is present.

    "help" ~> maybe { arg: String => if (canHelp(arg)) arg else "*" }
    Argument Converters

    An argument converter is a function that transforms individual argument strings into other types. A converter accepts as input:

    • an argument string

    and returns an Either[String, A] where:

    • Right(A) conveys successful conversion to an instance of type A
    • Left(String) conveys failure with corresponding user-readable text

    A handful of implicit argument converters are provided in the com.loopfor.scalop package as a convenience for constructing the most common option types. In the absence of a suitable converter, a custom implementation can be written quite easily. The following example converts an argument string into its equivalent JDK logging level.

    import java.util.logging.Level
    
    implicit def argToLevel(arg: String): Either[String, Level] = {
      try Right(Level.parse(arg.toUpperCase)) catch {
        case _: IllegalArgumentException => Left("unrecognized level")
      }
    }

    Providing this converter simplifies option construction as follows.

    val opts = ("level", 'L') ~> as[Level] ~~ Level.OFF
    Definition Classes
    loopfor
  • Opt
  • OptException
  • OptName
  • OptParser
  • OptResult

package scalop

A simple option parser.

Overview

An option parser is an ordered collection of option name and option processor pairs that matches on a sequence of arguments, yielding a map of option names to option values. As the parser recognizes option names in the argument sequence, it applies the corresponding processor function to obtain the option value. This process is repeated until the argument sequence is exhausted or the parser encounters an error.

An option name can be expressed in both long and short form. For any given sequence of arguments, long options are detected by the presence of a -- prefix and short options with a - prefix. Examples include --verbose and -v, respectively.

An option processor is an arbitrary function whose purpose is to return a value that gets assigned to the option name. A processor may consider and absorb subsequent arguments in computing the value, such as --timeout that might expect the next argument to be an integer. Library users are encouraged to utilize the predefined builder methods rather than implement processor functions from scratch.

Option Construction

The construction of an option is best done using the DSL, which is available from the following import statement.

import com.loopfor.scalop._

The following is a simple option that demonstrates how the DSL is used to pair an option name with a corresponding processor.

val opt = ("verbose", 'v') ~> just(true)

The ~> method triggers an implicit conversion of the tuple ("verbose", 'v') into an option name and then binds the processor function just(true), resulting in an option.

An option can also be adorned with a default value upon construction using the ~~ operator following the processor function. Doing so ensures that the option is assigned the default value in the absence of being specified in an argument sequence at the time of parsing.

val opt = ("verbose", 'v') ~> just(true) ~~ false

A sequence of options can then be constructed using the :: operator. Note that the order of options is important since the parser will evaluate arguments against those options based on traversal order of the sequence.

val opts = ("verbose", 'v') ~> just(true) ~~ false ::
           ("timeout", 't') ~> as[Int] ~~ 0 ::
           "encoding" ~> as[Charset] ~~ Charset.forName("UTF-8") ::
           '?' ~> just(true) ~~ false ::
           Nil
Replacing Options

A replacing option is one which replaces values previously assigned to an option name during argument parsing. Options of this type are created using the ~> operator.

For example:

val opt = "timeout" ~> as[Int]

Given the following sequence of arguments, the value of timeout at the completion of parsing would be 60.

--timeout 30 --timeout 60
Appending Options

An appending option is one which appends values to a sequence of values previously assigned to an option name during argument parsing. Options of this type are created using the ~>+ operator.

For example:

val opt = "server" ~>+ as[String]

Given the following sequence of arguments, the value of server at the completion of parsing would be Seq("foo.com", "bar.com").

--server foo.com --server bar.com
Parser Construction

The construction of an option parser happens implicitly when the <~ operator is applied to either a single option or a sequence of options.

The following illustrates the evaluation of arguments against a sequence of options. Note that an ephemeral instance of an option parser is constructed as a byproduct of applying the <~ operator.

val opts = ("verbose", 'v') ~> just(true) ~~ false ::
           ("timeout", 't') ~> as[Int] ~~ 0 ::
           "encoding" ~> as[Charset] ~~ Charset.forName("UTF-8") ::
           '?' ~> just(true) ~~ false ::
           Nil

val optr = opts <~ Seq("--verbose", "-t", "30", "--encoding", "iso-8859-1", "this", "and", "that")

In the aforementioned example, invoking the parser with the given sequence of arguments produces an option result containing a map of option names to option values. Notice that a value is associated with both long and short forms of the option name regardless of which form is specified in the argument sequence.

"verbose" -> true
"v" -> true
"timeout" -> 30
"t" -> 30
"encoding" -> Charset(ISO-8859-1)
"?" -> false
"@" -> Seq("this", "and", "that")

The @ option is a special name containing all non-option values trailing the last option in the argument sequence.

Parser Behavior

Given a sequence of arguments, such as those provided by a shell when supplying arguments to a command line program, an option parser behaves in the following manner.

The parser recursively applies the following algorithm as it traverses the argument sequence.

  • If the next argument is equal to "--", the sequence of all subsequent arguments is assigned to the special option name "@" and the parser terminates, returning the option value map. By convention, the -- option is used to explicitly terminate options so that remaining arguments, which might be prefixed with -- or -, are not treated as options.
  • If the next argument is either a long or short option name recognized by the parser, the corresponding processor function is applied to the remaining arguments, yielding a value, which is then associated with the option name, both long and short, in the option value map. However, if the argument happens to be an option that is not recognized by the parser, then an exception is thrown. Otherwise, the parser is recursively applied to the remaining sequence of arguments.
  • If the next argument is not an option, implying that it contains neither a -- nor a - prefix, then the remaining argument sequence is assigned to the "@" option and the parser terminates.

Finally, default values for each option are assigned to the option value map if values for those corresponding options are absent.

In cases where values, which follow an option, contain either a - or -- prefix, such values must be escaped by prepending the \ character. Otherwise, the parser will interpret the value as an option and proceed accordingly.

The following example will parse incorrectly since -10 will be interpreted as an option.

--time-adjust -10

The correct way to specify this value is as follows:

--time-adjust \-10
Option Processors

An option processor is a function accepting as input:

  • the sequence of arguments that follow an option name

and returning as output a tuple containing:

  • the sequence of arguments following those consumed by the processor
  • the option value

The argument sequence provided as input are those that follow the recognized option. For example, given the following argument sequence:

--verbose -F foo.out --timeout 10

Assuming -F was recognized by the parser, then the sequence provided to the associated processor function would be:

Seq("foo.out", "--timeout", "10")

Since a processor may expect additional arguments following the option, as is the case with -F, the resulting sequence will be the arguments that follow those absorbed by the processor, which in this case, would be:

Seq("--timeout", "10")

In cases where a processor requires additional arguments, it is often necessary to perform some degree of validation or transformation, both of which may fail. Exceptions that propagate beyond the processor function are caught by the parser and converted to OptException. Additionally, the yell() methods are provided as a convenience for processor implementations to throw instances of OptException.

Processor Construction

A processor is typically constructed using one of the predefined builders, the choice of which depends on the nature of the option.

For standalone options with no additional argument, the just builder can be used to explicitly assign a value.

("verbose", 'v') ~> just(true)

For options that contain one additional argument, the as builders simplify construction of the processor by standardizing the manner in which error cases are handled, such as missing arguments and problems encountered with argument converters.

The simplest form of using as follows, which essentially converts the argument into the parameterized type.

("timeout", 't') ~> as[Int]

As with all uses of as, an argument converter must be implicitly defined or supplied directly to the function. Argument converters are discussed in more detail below.

A secondary form of using as accepts a user-supplied function, which performs additional processing on the argument once converted. The result of that function becomes the value of the option.

The following example illustrates how a function can be used for validation or alteration.

("timeout", 't') ~> as { arg: Int => if (arg < 0) 0 else arg }

The type of the return value does not need to match the type of the converted argument, which is demonstrated below.

("timeout", 't') ~> as { arg: Int => (if (arg < 0) 0 else arg).seconds }

For options that might contain an additional argument, the maybe builders are similar to their as counterparts in that the handling of error cases is standardized. All processors constructed in this manner yield Option[A] rather than A. This is necessary to distinguish between the presence or absence of a subsequent argument.

The simplest form of using maybe is demonstrated below.

val opts = "help" ~> maybe[String]

The value of the option will vary depending on the arguments provided to the parser:

optr = opts <~ Seq()
optr("help") // undefined

optr = opts <~ Seq("--help")
optr("help") == None

optr = opts <~ Seq("--help", "foo")
optr("help") == Some("foo")

A secondary form of using maybe accepts a user-supplied function, but is invoked only if a subsequent argument is present.

"help" ~> maybe { arg: String => if (canHelp(arg)) arg else "*" }
Argument Converters

An argument converter is a function that transforms individual argument strings into other types. A converter accepts as input:

  • an argument string

and returns an Either[String, A] where:

  • Right(A) conveys successful conversion to an instance of type A
  • Left(String) conveys failure with corresponding user-readable text

A handful of implicit argument converters are provided in the com.loopfor.scalop package as a convenience for constructing the most common option types. In the absence of a suitable converter, a custom implementation can be written quite easily. The following example converts an argument string into its equivalent JDK logging level.

import java.util.logging.Level

implicit def argToLevel(arg: String): Either[String, Level] = {
  try Right(Level.parse(arg.toUpperCase)) catch {
    case _: IllegalArgumentException => Left("unrecognized level")
  }
}

Providing this converter simplifies option construction as follows.

val opts = ("level", 'L') ~> as[Level] ~~ Level.OFF
Linear Supertypes
Ordering
  1. Alphabetic
  2. By Inheritance
Inherited
  1. scalop
  2. AnyRef
  3. Any
  1. Hide All
  2. Show All
Visibility
  1. Public
  2. Protected

Type Members

  1. type ArgConverter[A] = (String) => Either[String, A]

    A function that converts string arguments into another type.

    A function that converts string arguments into another type.

    The use of Either as the return type allows the conversion function to alternatively report errors in the form of user-readable text.

    If the conversion is successful, return Right(A), otherwise return Left(String) containing the error text.

  2. trait Opt[+A] extends AnyRef

    An option definition.

    An option definition.

    An instance of this class is typically constructed using the DSL when binding a processor function to an OptName using the ~> and ~>+ methods.

    A

    the value type

  3. class OptException extends Exception

    An exception thrown by OptParser.

  4. trait OptName extends AnyRef

    An option name containing both long and short forms.

    An option name containing both long and short forms.

    Option names can be expressed in one of three forms, all of which are represented by this type:

    • long only
    • short only
    • both long and short

    An instance of this class is typically constructed using the DSL in which several implicit methods convert various combinations of types to OptName when the ~> and ~>+ methods are used to bind a processor.

    The following types are implicitly converted:

    • (String, Char) -- represents both long and short forms
    • String -- represents long form only
    • Char -- represents short form only

    Examples

    ("help", '?')
    "help"
    '?'

    Constraints

    The construction of both long and short names is constrained to a subset of printable characters found in the US-ASCII character set. A violation of these constraints will cause IllegalArgumentException to be thrown by the constructor.

    A long name must adhere to the following regular expression:

    [a-zA-Z0-9][a-zA-Z0-9-]+

    A short name must adhere to the following regular expression:

    [a-zA-Z0-9?]
  5. trait OptParser extends AnyRef

    An option parser defined with a sequence of option definitions.

  6. type OptProcessor[+A] = (Seq[String]) => (Seq[String], A)

    A function that serves as a processor for an option name.

  7. trait OptResult extends AnyRef

    The result of parsing an argument sequence.

Value Members

  1. implicit def argToBoolean(arg: String): Either[String, Boolean]
  2. implicit val argToBooleanOption: ArgConverter[Option[Boolean]]
  3. implicit def argToByte(arg: String): Either[String, Byte]
  4. implicit def argToByteOption: ArgConverter[Option[Byte]]
  5. implicit def argToCharset(arg: String): Either[String, Charset]
  6. implicit val argToCharsetOption: ArgConverter[Option[Charset]]
  7. implicit def argToDouble(arg: String): Either[String, Double]
  8. implicit def argToDoubleOption: ArgConverter[Option[Double]]
  9. implicit def argToFile(arg: String): Either[String, File]
  10. implicit val argToFileOption: ArgConverter[Option[File]]
  11. implicit def argToFloat(arg: String): Either[String, Float]
  12. implicit def argToFloatOption: ArgConverter[Option[Float]]
  13. implicit def argToInt(arg: String): Either[String, Int]
  14. implicit def argToIntOption: ArgConverter[Option[Int]]
  15. implicit def argToLong(arg: String): Either[String, Long]
  16. implicit def argToLongOption: ArgConverter[Option[Long]]
  17. implicit def argToShort(arg: String): Either[String, Short]
  18. implicit def argToShortOption: ArgConverter[Option[Short]]
  19. implicit def argToString(arg: String): Either[String, String]
  20. implicit def argToStringOption: ArgConverter[Option[String]]
  21. implicit def argToURI(arg: String): Either[String, URI]
  22. implicit val argToURIOption: ArgConverter[Option[URI]]
  23. implicit def argToURL(arg: String): Either[String, URL]
  24. implicit val argToURLOption: ArgConverter[Option[URL]]
  25. def as[A](implicit converter: ArgConverter[A]): OptProcessor[A]

    Returns a processor that transforms a single argument.

    Returns a processor that transforms a single argument.

    Example

    val opts = ("level", 'L') ~> as[Int] ~~ 0
    A

    The value type of the processor.

    converter

    An implicit function that converts an argument to type A.

  26. def as[A, B](fn: (A) => B)(implicit converter: ArgConverter[A]): OptProcessor[B]

    Returns a processor that transforms a single argument.

    Returns a processor that transforms a single argument.

    Example

    val opts = ("timeout", 't') ~> as { arg: Int => arg.seconds } ~~ 60.seconds
    A

    The type of the argument.

    B

    The value type of the processor.

    fn

    A function that transforms an argument of type A to an instance of type B.

    converter

    An implicit function that converts an argument to type A.

  27. implicit def charToOptName(sname: Char): OptName
  28. def just[A](fn: => A): OptProcessor[A]

    Returns a processor whose value does not depend on additional arguments.

    Returns a processor whose value does not depend on additional arguments.

    Example

    val opts = ("verbose", 'v') ~> set(true) ~~ false
    A

    The option type.

    fn

    A function that returns an instance of A.

  29. def maybe[A](implicit converter: ArgConverter[A]): OptProcessor[Option[A]]

    Returns a processor that transforms an optional argument.

    Returns a processor that transforms an optional argument.

    Example

    val opts = ("help", '?') ~> maybe[String]
    A

    The value type of the processor.

    converter

    An implicit function that converts an argument to type A.

  30. def maybe[A, B](fn: (A) => B)(implicit converter: ArgConverter[A]): OptProcessor[Option[B]]

    Returns a processor that transforms an optional argument.

    Returns a processor that transforms an optional argument.

    Example

    val opts = ("help", '?') ~> maybe { arg: String => if (canHelp(arg)) arg else "*" }
    A

    The type of the argument.

    B

    The value type of the processor.

    fn

    A function that transforms an argument of type A to an instance of type B.

    converter

    An implicit function that converts an argument to type A.

  31. implicit def optToOptParser(opt: Opt[_]): OptParser
  32. implicit def optsToOptParser(opts: Seq[Opt[_]]): OptParser
  33. implicit def stringToOptName(lname: String): OptName
  34. implicit def tupleToOptName(name: (String, Char)): OptName
  35. def yell(message: String, cause: Throwable): Nothing

    A convenience method that throws OptException.

  36. def yell(message: String): Nothing

    A convenience method that throws OptException.

  37. object Opt

    Constructs Opt values.

  38. object OptName

    Constructs OptName values.

  39. object OptParser

    Constructs OptParser values.

  40. object OptResult

    Constructs OptResult values.

Inherited from AnyRef

Inherited from Any

Ungrouped