case class Params(
  mode: String = "",
  input: Option[File] = None,
  output: Option[File] = None,
  keyRing: Option[File] = None,
  key: String = "",
  password: String = "",
  genDigest: Boolean = false
) {
  def withEncrypt() = this.copy(mode = "encrypt")
  def withDecrypt() = this.copy(mode = "decrypt")
  def withInput(f: File) = this.copy(input = Some(f))
  def withOutput(f: File) = this.copy(input = Some(f))
  def withKeyRing(f: File) = this.copy(keyRing = Some(f))
  def withKey(k: String) = this.copy(key = k)
  def withPassword(p: String) = this.copy(password = p)
  def withGenDigest() = this.copy(genDigest = true)
}
  
val parser = new SmartOptionParser[Params]("licensing") {
  head("licensing", "<version goes here>")
  smartCmd("encrypt", "encrypt a license file.", _.withEncrypt()).children(
    smartOpt('i', "input",    "<file>", "the plaintext license file to be encrypted",         _.withInput    ).required(),
    smartOpt('o', "output",   "<file>", "the encrypted license file to write",                _.withOutput   ).required(),
    smartOpt('r', "keyring",  "<file>", "the PRIVATE keyring containing the encryption cert", _.withKeyRing  ).required(),
    smartOpt('k', "key",      "<text>", "the name of the key containing the encryption cert", _.withKey      ).required(),
    smartOpt('p', "password", "<text>", "the key's password",                                 _.withPassword ).required()
  )
  smartCmd("decrypt", "decrypt a license file.", _.withDecrypt()).children(
    smartOpt('i', "input",   "<file>", "the encrypted license file to be decrypted",        _.withInput   ).required(),
    smartOpt('o', "output",  "<file>", "the plaintext license file to write",               _.withOutput  ).required(),
    smartOpt('r', "keyring", "<file>", "the PUBLIC keyring containing the decryption cert", _.withKeyRing ).required()
  )
  checkConfig { p =>
    if (p.mode != "encrypt" && p.mode != "decrypt") {
      println(this.usage)
      failure("Must specify a command: encrypt or decrypt.")
    } else success
  }
  smartFlag("dumpdigest", "output the digest, as Scala code, to the console", _.withGenDigest() )

  help("help") text "prints this usage text"
}

def main(args: Array[String]): Unit = {
  parser.parse(args, Params()) map { config =>
    println(config)
    ...
  } getOrElse {
    println("bad args")
  }
}