Skip to content

Instantly share code, notes, and snippets.

@kevinwright
Created May 31, 2016 13:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kevinwright/25daaefc372183b8fa19e8f54f2eb6b2 to your computer and use it in GitHub Desktop.
Save kevinwright/25daaefc372183b8fa19e8f54f2eb6b2 to your computer and use it in GitHub Desktop.
Improved syntax for scopt
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")
}
}
import scopt._
abstract class SmartOptionParser[Config](programName: String) extends scopt.OptionParser[Config](programName){
def smartCmd(
name : String,
description : String,
fn : (Config) => Config
): OptionDef[Unit, Config] = cmd(name) action { (_, c) => fn(c) } text description
def smartOpt[T: scopt.Read](
char : Char,
name : String,
valName : String,
description : String,
fn : (Config) => (T) => Config
): OptionDef[T, Config] = opt[T](char, name) valueName valName action { (x, c) => fn(c)(x) } text description
def smartFlag(
name : String,
description : String,
fn : (Config) => Config
): OptionDef[Unit, Config] = opt[Unit](name) action { (_, c) => fn(c) } text description
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment