Skip to content

Miscellaneous

cats-effect

case-app has a module helping using it in cats-effect applications.

Add a dependency to it like

//> using dep com.github.alexarchambault::case-app-cats:2.1.1
(for other build tools, see setup and change case-app to case-app-cats)

Single command

Use IOCaseApp for a single-command application:

import caseapp.catseffect._
import cats.data.NonEmptyList
import cats.effect._

case class ExampleOptions(
  foo: String = "",
  thing: NonEmptyList[String]
)

object IOCaseExample extends IOCaseApp[ExampleOptions] {
  def run(options: ExampleOptions, arg: RemainingArgs): IO[ExitCode] = IO {
    // Core of the app
    // ...
    ExitCode.Success
  }
}

Multiple subcommands

Use IOCommand and IOCommandsEntryPoint for applications with multiple subcommands — the cats-effect equivalents of Command and CommandsEntryPoint:

import caseapp._
import caseapp.catseffect._
import cats.effect._

case class GrindOptions(
  @HelpMessage("Type of beans")
  beans: String = "arabica",
  @HelpMessage("Grind size")
  size: String = "medium"
)

object Grind extends IOCommand[GrindOptions] {
  override def names = List(List("grind"))
  def run(options: GrindOptions, args: RemainingArgs): IO[ExitCode] =
    IO.println(s"Grinding ${options.beans} (${options.size})").as(ExitCode.Success)
}

case class BrewOptions(
  @HelpMessage("Brewing method")
  method: String = "pourover",
  @HelpMessage("Water temperature in Celsius")
  temp: Int = 96
)

object Brew extends IOCommand[BrewOptions] {
  override def names = List(List("brew"))
  def run(options: BrewOptions, args: RemainingArgs): IO[ExitCode] =
    IO.println(s"Brewing with ${options.method} at ${options.temp}°C").as(ExitCode.Success)
}

object CoffeeApp extends IOCommandsEntryPoint {
  def progName = "coffee"
  def commands = Seq(Grind, Brew)
}

IOCommand extends IOCaseApp, the same way Command extends CaseApp, and supports custom names, group, hidden, hasHelp and hasFullHelp. Shell completions (enableCompleteCommand / enableCompletionsCommand) are not supported by IOCommandsEntryPoint yet.

IOCommandsEntryPoint supports defaultCommand for a fallback when no subcommand is specified, just like CommandsEntryPoint.