fmv1992 / scala_cli_parser   0.4.3

GNU General Public License v3.0 only GitHub

A simple configuration-file-based CLI parser for Scala.

Scala versions: 2.13
Scala Native versions: 0.4

scala_cli_parser

Documentation.

  • dev:

    • Build status

    • codecov

  • Available for Scala 2.11 (both JVM and Scala Native), 2.12 and 2.13.


A library for parsing command line arguments.

It’s main feature is that CLI parsing is defined on a config file. For example consider a very simple sum program:

package fmv1992.scala_cli_parser.util.test

import fmv1992.fmv1992_scala_utilities.util.S
import fmv1992.scala_cli_parser.cli.ArgumentCLI
import fmv1992.scala_cli_parser.util.MainTestableConfBased

object TestSum extends MainTestableConfBased {

  val version = "0.0.0"

  val programName = "TestSum"

  val CLIConfigContents =
    S.putfile("./src/test/resources/test_cli_example_02_gnu.txt")

  def testableMain(args: Set[ArgumentCLI]): Seq[String] = {
    args
      .find(_.name == "help")
      .orElse(args.find(_.name == "version"))
      .orElse(args.find(_.name == "sum"))
      .getOrElse(throw new Exception()) match {
      case a: ArgumentCLI if (a.name == "help")    => getHelp
      case a: ArgumentCLI if (a.name == "version") => getVersion
      case a: ArgumentCLI if (a.name == "sum") =>
        Seq(a.values.map(_.toInt).sum.toString)
    }
  }
}

It can be configured with the following config file:

# Well formated cli config file.
# Used in tests:
#   1.  Used to test `default`.

name: debug
    n: 0
    description: Turn on debugging.

name: version
    n: 0
    description: Show the program version.
# This is a comment.

name: sum
    n: 2
    description: | Sum arguments.
                 |
                 | Use multiline.
    default: 0,0

name: help
    n: 0
    description: Help text.

# vim: set filetype=config fileformat=unix wrap spell spelllang=en:

And its usages are as follows:

  1. TestSum --version
    
    TestSum 0.0.0
    
  2. TestSum --help
    
    TestSum --debug --help --sum --version
        --debug: Turn on debugging.
        --help: Help text.
        --sum: Sum arguments.
    
               Use multiline.
        --version: Show the program version.
    
  3. TestSum --sum 1992 1
    
    1993
    

Config specification

The source of truth is the full .conf fullConfigParser.

Also the current options are considered around here.

Links

TODO

Short term

  • Create an interface for this package (newly created fmv1992.scala_cli_parser.conf) so that other packages might use it through a well defined interface.

    CURRENT: needs verification.

  • Add config specification (this is somewhat in the docs).

  • Add config specification (this is somewhat in the docs).

  • Add a Main class to this project. It should check the validity of .conf files (by reading the stdin).

  • Review permissions for util entities like ParserWithTry.

  • Stop using the:

    object Obj {
    
    private case class TraitImpl() ⋯
    
    def apply ⋯
    
    }
    

    Pattern. It disallows pattern matching.

Long term

  • Add richer interactions between CLI arguments. Eg:

    rule_01:
        type: mutually_exclusive
        args: version,help
    
  • Add scalacheck to testing.

  • On the part of parsing config files everything but fullConfigParser should be private.

  • Improve the documentation of this project. Good scaladoc references:

    1. https://gist.github.com/JohnStarich/6d8ba934828180cdcc502f571cefecd8.

    2. https://github.com/scala/docs.scala-lang/blob/main/_style/scaladoc.md.

  • When Scala 2.11 support is dropped: between 0022b3e0a0198d4c970531db3a74c25e0b055f98 and 37424215d82a77ca618333521bce4827394bee66 some shims had to be introduced to make 2.11 compatible with future versions. Revert this when dropping support for Scala 2.11.

  • On project one: the design of CLIConfigTestableMain is conflicting with zio.App.

  • Improve parsing process. Parsers can actually fail and provide a useful error message.

  • Add lihaoyi’s scala compiler acyclic plugin. See commaefa4ec.

  • The type subsection seems hard to implement. Using str or int would make ArgumentCLIArgumentCLI[String] for instance. Uniform usage of it in a Set[ArgumentCLI] would be cumbersome. Maybe ok by using pattern matching? In any case this is not a priority right now.

Discussion

Interesting to notice that a parser behavior is influenced by the parsers and the combiners (e.g.: ???).

Branches

  • dev:

  • dev_0.x_scala_native:

    • Scala Native support was added by dev_unstable. Delete it.
  • dev_restart:

    • Used to devise new strategy for dev_unstable. Delete it soon.
  • dev_add_default_to_argumentconf:

    • Add a default subsection to be parsed. Done. Delete it soon.
  • dev_unstable:

    *̶ (̶B̶a̶c̶k̶l̶o̶g̶)̶:̶ O̶n̶ t̶h̶e̶ p̶a̶r̶t̶ o̶f̶ p̶a̶r̶s̶i̶n̶g̶ c̶o̶n̶f̶i̶g̶ f̶i̶l̶e̶s̶ e̶v̶e̶r̶y̶t̶h̶i̶n̶g̶ b̶u̶t̶ ̶f̶u̶l̶l̶C̶o̶n̶f̶i̶g̶P̶a̶r̶s̶e̶r̶̶ s̶h̶o̶u̶l̶d̶ b̶e̶ p̶r̶i̶v̶a̶t̶e̶.̶

    *̶ (̶B̶a̶c̶k̶l̶o̶g̶)̶:̶ I̶m̶p̶r̶o̶v̶e̶ p̶a̶r̶s̶i̶n̶g̶ p̶r̶o̶c̶e̶s̶s̶.̶ P̶a̶r̶s̶e̶r̶s̶ c̶a̶n̶ a̶c̶t̶u̶a̶l̶l̶y̶ f̶a̶i̶l̶ a̶n̶d̶ p̶r̶o̶v̶i̶d̶e̶ a̶ u̶s̶e̶f̶u̶l̶ e̶r̶r̶o̶r̶ m̶e̶s̶s̶a̶g̶e̶.̶

  • master:

Discussion

Interesting to notice that a parser behavior is influenced by the parsers and the combiners (e.g.: mapper).