Add parsing of command line options

This commit is contained in:
Jarek Sacha 2023-05-15 15:07:40 -04:00
parent 4f7829eea8
commit e263bfaf7b
No known key found for this signature in database
GPG key ID: F29625CE62288163
9 changed files with 180 additions and 9 deletions

View file

@ -1,2 +1,14 @@
version = "3.7.3" version = 3.7.3
runner.dialect = scala3 runner.dialect = scala3
preset = IntelliJ
align.preset = more
maxColumn = 120
docstrings.style = Asterisk
docstrings.blankFirstLine = yes
docstrings.wrap = no
importSelectors = singleLine
newlines.source = keep
rewrite.scala3.convertToNewSyntax = yes

View file

@ -5,12 +5,24 @@ enablePlugins(ScalaNativePlugin)
// set to Debug for compilation details (Info is default) // set to Debug for compilation details (Info is default)
logLevel := Level.Info logLevel := Level.Info
libraryDependencies ++= Seq(
"com.github.scopt" %%% "scopt" % "4.1.0"
)
Compile/run/mainClass := Some("ij_plugins.imagej_launcher.Main")
// import to add Scala Native options // import to add Scala Native options
import scala.scalanative.build._ import scala.scalanative.build._
// defaults set with common options shown // defaults set with common options shown
nativeConfig ~= { c => nativeConfig ~= { c =>
c.withLTO(LTO.none) // thin c.withLTO(LTO.none) // thin
.withMode(Mode.debug) // releaseFast .withMode(Mode.debug) // releaseFast
.withGC(GC.immix) // commix .withGC(GC.immix) // commix
} }
//// Enable verbose reporting during compilation
//nativeConfig ~= { c =>
// c.withCompileOptions(c.compileOptions ++ Seq("-v"))
//}

View file

@ -1 +1 @@
sbt.version = 1.8.2 sbt.version = 1.8.3

View file

@ -1 +1 @@
addSbtPlugin("org.scala-native" % "sbt-scala-native" % "0.4.10") addSbtPlugin("org.scala-native" % "sbt-scala-native" % "0.4.12")

View file

@ -1,4 +0,0 @@
object Main {
def main(args: Array[String]): Unit =
println("Hello, world!")
}

View file

@ -0,0 +1,17 @@
/*
* Copyright (c) 2000-2023 Jarek Sacha. All Rights Reserved.
* Author's e-mail: jpsacha at gmail.com
*/
package ij_plugins.imagej_launcher
import scala.collection.immutable
enum ErrorCode(val value: Int, val message: String):
case OK extends ErrorCode(0, "OK")
case InvalidCommandLineArguments extends ErrorCode(-10, "Invalid command line arguments")
case GeneralError extends ErrorCode(-100, "General error")
case UnhandledNonFatalError extends ErrorCode(-200, "Unhandled non-fatal error")
case UnhandledFatalError extends ErrorCode(-300, "Unhandled fatal error")
case NotImplemented extends ErrorCode(-400, "Functionality not implemented")
override def toString: String = s"$message [exit code: $value]"

View file

@ -0,0 +1,14 @@
/*
* Copyright (c) 2000-2023 Jarek Sacha. All Rights Reserved.
* Author's e-mail: jpsacha at gmail.com
*/
package ij_plugins.imagej_launcher
import ij_plugins.imagej_launcher.Main.Config
class Launcher(logger: Logger) {
def run(config: Config): ErrorCode = {
ErrorCode.NotImplemented
}
}

View file

@ -0,0 +1,28 @@
/*
* Copyright (c) 2000-2023 Jarek Sacha. All Rights Reserved.
* Author's e-mail: jpsacha at gmail.com
*/
package ij_plugins.imagej_launcher
import ij_plugins.imagej_launcher.Logger.Level
class Logger {
var level: Level = Level.Info
def debug(msg: String): Unit = pprint(Level.Debug, msg)
def info(msg: String): Unit = pprint(Level.Info, msg)
def error(msg: String): Unit = pprint(Level.Error, msg)
private def pprint(l: Level, message: String): Unit =
if l.level <= level.level then println(s"${l.name}: $message")
}
object Logger:
enum Level(val level: Int, val name: String):
case Off extends Level(0, "OFF")
case Error extends Level(200, "ERROR")
case Info extends Level(400, "INFO")
case Debug extends Level(500, "DEBUG")
case All extends Level(Int.MaxValue, "DEBUG")

View file

@ -0,0 +1,92 @@
/*
* Copyright (c) 2000-2023 Jarek Sacha. All Rights Reserved.
* Author's e-mail: jpsacha at gmail.com
*/
package ij_plugins.imagej_launcher
import ij_plugins.imagej_launcher.ErrorCode
import scopt.{DefaultOEffectSetup, OParser}
import java.io.File
object Main {
private val logger = new Logger()
private val AppName = "ijp-imagej-launcher"
// private val AppVersion = s"${Version.version} [${Version.buildTimeStr}]"
private val AppVersion = s"0.1.0"
private val VersionMessage = s"v.$AppVersion"
private val AppDescription =
"""Native launcher for ImageJ2
|""".stripMargin
case class Config(
logLevel: Logger.Level = Logger.Level.Error,
dryRun: Boolean = false,
javaHome: Option[File] = None
)
def main(args: Array[String]): Unit =
setupLogger(Logger.Level.All)
val ret: ErrorCode =
parseCommandLine(args) match
case Some(config) =>
setupLogger(config.logLevel)
runLauncher(config)
case None =>
// arguments are bad
ErrorCode.InvalidCommandLineArguments
val msg = s"${ret.message} [exit code: ${ret.value}]"
if ret == ErrorCode.OK then
logger.info(msg)
else
logger.error(msg)
// System.exit(ret.value)
end main
private def parseCommandLine(args: Array[String]): Option[Config] =
val builder = OParser.builder[Config]
val parser1 = {
import builder.*
OParser.sequence(
programName(AppName),
head(AppName, VersionMessage),
note(AppDescription),
//
help('h', "help").text("prints this usage text"),
//
version("version").text("prints version"),
//
opt[Unit]("dry-run")
.action((_, c) => c.copy(dryRun = true))
.text("show the command line, but do not run anything"),
//
opt[Unit]("info")
.action((_, c) => c.copy(logLevel = Logger.Level.Info))
.text("informational output"),
//
opt[Unit]("debug")
.action((_, c) => c.copy(logLevel = Logger.Level.Debug))
.text("verbose output"),
//
opt[File]("java-home")
.valueName("<path>")
.action((path, c) => c.copy(javaHome = Option(path)))
.text("specify JAVA_HOME explicitly"),
//
opt[Unit]("print-java-home")
.action((_, c) => c.copy(dryRun = true))
.text("print ImageJ's idea of JAVA_HOME")
)
}
OParser.parse(parser1, args, Config())
end parseCommandLine
private def setupLogger(logLevel: Logger.Level): Unit = logger.level = logLevel
private def runLauncher(config: Config): ErrorCode = new Launcher(logger).run(config)
}