losizm / little-cli

The Scala library that provides extension methods to Apache Commons CLI.

Version Matrix


The Scala library that provides extension methods to Apache Commons CLI.

Maven Central

Getting Started

To get started, add little-cli to your project:

libraryDependencies += "com.github.losizm" %% "little-cli" % "1.0.0"

There's a runtime dependency to Apache Commons CLI, so you'll need to add that too.

libraryDependencies += "commons-cli" % "commons-cli" % "1.4"

NOTE: Starting with version 1.0, little-cli is written for Scala 3 exclusively. See previous releases for compatibility with Scala 2.12 and Scala 2.13.

How It Works

Here's an example showing the library in action.

import little.cli.Cli.{ application, option }
import little.cli.Implicits.{ *, given }

// Create application with supplied usage and options
val app = application("grep [ options ... ] <pattern> [ <fileName> ... ]",
  option("i", "ignore-case", false, "Perform case insensitive matching"),
  option("l", "files-with-matches", false, "Print file name only"),
  option("m", "max-count", true, "Stop reading file after 'num' matches").argName("num"),
  option("n", "line-number", false, "Include line number of match"),
  option("r", "recursive", false, "Recursively search subdirectories"),
  option("x", "exclude", true, "Exclude filename pattern from search").argName("pattern")

val args = Array("-ilr", "--exclude", "*.swp", "exception", "src/main/scala")

// Parse arguments
val cmd = app.parse(args)

cmd.hasOption("help") match
  case true =>
    // Print help to System.out
  case false =>
    // Get command arguments and pretend to do something
    val pattern  = cmd.getArg(0)
    val fileName = cmd.getArg(1)
    println(s"Searching for files with '$pattern' in $fileName directory...")

Mapping Option Values and Arguments

Option values and arguments can be mapped to types other than String by adding a given ValueMapper[T] to scope. There are default implementations for Int, Long, File, and Path defined in Implicits. Feel free to define your own for other types.

import java.io.File
import little.cli.Cli.{ application, option }
import little.cli.Implicits.{ *, given }
import little.cli.ValueMapper

case class KeepAlive(idleTimeout: Int, maxRequests: Int)

// Define how to map value to KeepAlive
given ValueMapper[KeepAlive] =
  _.split(":") match
    case Array(timeout, max) => KeepAlive(timeout.toInt, max.toInt)

val app = application("start-server [ options ... ] port",
  option("d", "directory", true, "Location of public files directory"),
  option("k", "keep-alive", true, "Allow persistent connections").argName("timeout:max")

val cmd = app.parse("-d ./public_html --keep-alive 5:10 8080".split("\\s+"))

// Map keep-alive option
val keepAlive = cmd.mapOptionValue[KeepAlive]("keep-alive")

// Map directory option
val directory = cmd.mapOptionValue[File]("directory")

// Map port argument
val port = cmd.mapArg[Int](0)

Checking Multiple Options

At times, you may need to check multiple options, possibly from a group of mutually exclusive options, to determine what action to take. For those occasions, you have the overloaded hasOption extension method to CommandLine.

import java.io.{ ByteArrayInputStream, FileInputStream }
import little.cli.Cli.{ application, group, option }
import little.cli.Implicits.{ *, given }

val app = application("post-request [ options ... ] url",
  option("H", true, "Add header").argName("header"),
  // Define group of mutually exclusive options
    option("d", true, "Use supplied inline data").argName("data"),
    option("f", true, "Use data from supplied file").argName("file"),
    option("s", false, "Use data from stdin (default)")

val cmd = app.parse("-f ./message.json http://localhost:8080/messages".split("\\s+"))

// Check option group and assign input stream
val in = cmd.hasOptions("d", "f", "s") match {
  case (true, _, _) => ByteArrayInputStream(cmd.getOptionValue("d").getBytes)
  case (_, true, _) => FileInputStream(cmd.getOptionValue("f"))
  case _            => System.in

val url = cmd.getArg(0)

API Documentation

See scaladoc for additional details.


little-cli is licensed under the Apache License, Version 2. See LICENSE for more information.