Processing Scala command-line arguments with Argot, and passing command-line arguments through SBT

Argot is the name of a Scala library that lets you read command-line options/arguments from a Scala application. (Presumably it will work with Java and other JVM-based languages as well.)

I’m trying to use Argot with an application of mine named Cato, and when I had problems getting Argot to work -- and then needed to pass command-line arguments to my application through SBT -- I decided to write this quick little test code and article.

In short, if you create a normal SBT 0.13 project and set up your build.sbt file like this:

name := "Argot"

version := "1.0"

scalaVersion := "2.10.3"

resolvers += "Typesafe Repository" at "http://repo.typesafe.com/typesafe/releases/"

libraryDependencies += "org.clapper" %% "argot" % "1.0.3"

this little test program should work:

package test1

import org.clapper.argot._
import ArgotConverters._

/**
 * Test the command line option stuff with SBT like this:
 * 
 *     `sbt "run -m cato.cfg"`
 *     
 * The double quotes are needed as shown to pass the `-m cato.cfg` parameter to
 * my application (shown below). This works properly, and my program prints the
 * following, expected output:
 * 
 *     `filename = cato.cfg`
 * 
 */
object Test1 {

    val parser = new ArgotParser("Cato", preUsage=Some("Cato, Version 0.1. Copyright (c) 2014, Alvin J. Alexander (alvinalexander.com)."))

    // this line supports `-m filename` and `--mappingfile filename`
    val mappingFile = parser.option[String](List("m", "mappingfile"), "filename", "The canonical name of the data types mapping file.")
    
    def main(args: Array[String]) {
        try {
            parser.parse(args)
            mappingFile.value match {
                case Some(filename) => println(s"filename = $filename")
                case None => println("None")
            }
        } catch {
            case e: ArgotUsageException => println(e.message)
        }
    }
    
}

Just name that file Test1.scala, and put it in the root SBT directory or under src/main/scala.

Passing a command line argument to the application (through SBT)

The Test1 application will look for the -m command-line flag. Actually, this is defined as an optional flag via Argot, but assuming that we do want to pass that command-line flag and its filename to the Test1 application, this is how you do that with SBT:

prompt> sbt "run -m cato.cfg"

Loading /Users/Al/bin/sbt-0.13.1/bin/sbt-launch-lib.bash
[info] Loading global plugins from /Users/Al/.sbt/0.13/plugins
[info] Set current project to Argot (in build file:/Users/Al/Projects/Scala/Tests/Argot/)
[info] Compiling 1 Scala source to /Users/Al/Projects/Scala/Tests/Argot/target/scala-2.10/classes...
[info] Running test1.Test1 -m cato.cfg
filename = cato.cfg
[success] Total time: 7 s, completed Nov 25, 2014 5:44:58 PM

As that output shows, SBT ran the Test1 application with my -m cato.cfg parameter like this:

Running test1.Test1 -m cato.cfg

and the resulting output was this:

filename = cato.cfg

If you just type sbt run at the command line you’ll see that the Test1 application also runs, but since no command-line flags are passed to the application, it prints None and exits.

Summary

As a quick summary, if you wanted to see a little “Hello, world” example of how to get started with Argot, or wanted to see one way to pass command-line arguments to a Scala application through SBT, I hope this example is helpful.