Skip to content

Instantly share code, notes, and snippets.

@clintval
Last active June 13, 2019 02:09
Show Gist options
  • Select an option

  • Save clintval/68e6f90b49a986e11ccfa62bff651213 to your computer and use it in GitHub Desktop.

Select an option

Save clintval/68e6f90b49a986e11ccfa62bff651213 to your computer and use it in GitHub Desktop.
A small demo for prototyping shell utility helpers and trait abstraction
package com.clintval.misc
trait CommandLineTool {
val Executable: String
def exec(args: String*): ProcessBuilder = { new ProcessBuilder(Executable +: args: _*) }
}
trait Testable {
self: CommandLineTool =>
val TestCommand: Seq[String]
lazy val Available: Boolean = {
val process = execArgs(TestCommand: _*).redirectErrorStream(true)
process.start().waitFor() == 0
}
}
trait Versioned {
self: CommandLineTool =>
val VersionFlag: String = "--version"
lazy val version: String = exec(VersionFlag).redirectErrorStream(true).start().getOutputStream.toString // Unlikely to work! Pseudo-code
}
trait Modular {
self: CommandLineTool =>
def TestModuleCommand(module: String): Seq[String]
def TestModuleCommand(modules: Seq[String]): Seq[Seq[String]] = modules.map(TestModuleCommand)
def ModuleAvailable(module: String): Boolean = {
val process = execArgs(TestModuleCommand(module): _*).redirectErrorStream(true)
process.start().waitFor() == 0
}
def ModuleAvailable(modules: String*): Boolean = modules.map(ModuleAvailable).forall(_ == true)
}
trait Python extends CommandLineTool with Versioned with Modular with Testable {
val TestCommand: Seq[String] = Seq(VersionFlag)
def TestModuleCommand(module: String): Seq[String] = Seq("-c", s"'import $module'")
}
object GhostScript extends CommandLineTool with Testable with Versioned {
val Executable: String = "gs"
val TestCommand: Seq[String] = Seq(VersionFlag)
}
object Java extends CommandLineTool with Testable with Versioned {
val Executable: String = "java"
override val VersionFlag: String = "-version"
val TestCommand: Seq[String] = Seq(VersionFlag)
}
object Python extends Python { val Executable: String = "python" }
object Python2 extends Python { val Executable: String = "python2" }
object Python3 extends Python { val Executable: String = "python3" }
object Rscript extends CommandLineTool with Versioned with Modular with Testable {
val Executable: String = "Rscript"
val TestCommand: Seq[String] = Seq(VersionFlag)
def TestModuleCommand(module: String): Seq[String] = Seq("-e", s"stopifnot(require('$module'))")
}
object LetsTryThemOut {
Rscript.ModuleAvailable("ggplot2", "dplyr")
Python3.ModuleAvailable("numpy", "pandas")
Python2.ModuleAvailable("numpy")
Rscript.version == "R scripting front-end version 3.6.0 (2019-04-26)"
Java.version == "java version \"1.8.0_192\""
Python2.version == "Python 2.7.16"
Python3.version == "Python 3.7.2"
Python.version == "Python 3.7.2" // Must be my default Python!
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment