Skip to content

Instantly share code, notes, and snippets.

@jvican
Created June 26, 2019 18:04
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 jvican/a178335b07e866f113373571f77fd47b to your computer and use it in GitHub Desktop.
Save jvican/a178335b07e866f113373571f77fd47b to your computer and use it in GitHub Desktop.
Nailgun CLI implementation **prototype** via Caseapp for Sailgun (Scala based client)
package sailgun.caseapp
import _root_.caseapp.core.Parser
import _root_.caseapp.core.Messages
import _root_.caseapp.core.WithHelp
import java.io.PrintStream
import java.io.InputStream
import sailgun.protocol.Defaults
import sailgun.protocol.Streams
import sailgun.logging.SailgunLogger
import java.util.concurrent.atomic.AtomicBoolean
import sailgun.TcpClient
/**
* An implementation of a CLI via case-app.
*
* Unfortunately, GraalVM Native Image doesn't correctly generate a native
* image because of parsing errors and warnings generated by the use of macros
* in case-app via Shapeless. For that reason, this class is left here but it's
* not used by default, preferring a CLI implementation that requires no macros
* and works with GraalVM Native Image.
*/
abstract class Cli(in: InputStream, out: PrintStream, err: PrintStream) {
private implicit val cliParamsParser: Parser[CliParams] = Parser.generic
private implicit val messagesParams =
Messages.messages[CliParams].copy(appName = "nailgun", progName = "nailgun")
private implicit val messagesParamsHelp = messagesParams.withHelp
def exit(code: Int): Unit
def run(args: Array[String]): Unit = {
def errorAndExit(msg: String): Unit = { err.println(msg); exit(1) }
cliParamsParser.withHelp.detailedParse(args) match {
case Left(a) => errorAndExit(a)
case Right((WithHelp(usage, help, result), remainingArgs, extraArgs)) =>
if (usage) out.println(messagesParams.usageMessage)
if (help)
out.println("Type `--nailgun-help` to print help of nailgun CLI.")
result match {
case Left(parserError) => errorAndExit(parserError)
case Right(params) =>
if (params.nailgunShowVersion)
out.println(s"Nailgun v${Defaults.Version}")
if (params.nailgunHelp) {
out.println(messagesParams.helpMessage)
exit(0)
} else {
remainingArgs.headOption match {
case None => errorAndExit("Missing nailgun command to server!")
case Some(cmd) =>
// Reconstruct arguments to pass them to the server correctly
val cmdArgs = {
val remaining0 = remainingArgs.tail
if (extraArgs.isEmpty) remaining0
else remaining0 ++ List("--") ++ extraArgs
}
val streams = Streams(in, out, err)
val client = TcpClient(params.nailgunServer, params.nailgunPort)
val logger = new SailgunLogger("log", out, isVerbose = params.verbose)
val code = client.run(
cmd,
cmdArgs.toArray,
Defaults.cwd,
Defaults.env,
streams,
logger,
new AtomicBoolean(false)
)
logger.debug(s"Return code is $code")
exit(code)
}
}
}
}
}
}
object Cli extends Cli(System.in, System.out, System.err) {
def main(args: Array[String]): Unit = run(args)
override def exit(code: Int) = System.exit(code)
}
package sailgun.caseapp
import _root_.caseapp.{ExtraName, HelpMessage}
import sailgun.protocol.Defaults
final case class CliParams(
nailgunServer: String = Defaults.Host,
nailgunPort: Int = Defaults.Port,
nailgunHelp: Boolean = false,
verbose: Boolean = false,
@ExtraName("--nailgun-showversion")
nailgunShowVersion: Boolean = false
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment