diff options
author | Jan Christopher Vogt <oss.nsp@cvogt.org> | 2016-10-02 15:09:11 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2016-10-02 15:09:11 -0400 |
commit | 3e35d0809240a3379dd3d71d42655e00b9cff421 (patch) | |
tree | 72afac7f4e6458572c319655c46c9ec11007029d /stage1/Stage1Lib.scala | |
parent | 8515ca06ae5ae2501467f5af91bec2f5a80251c1 (diff) | |
parent | cea45c3b3dd7353ce1636467387bb8d47e7dd920 (diff) | |
download | cbt-3e35d0809240a3379dd3d71d42655e00b9cff421.tar.gz cbt-3e35d0809240a3379dd3d71d42655e00b9cff421.tar.bz2 cbt-3e35d0809240a3379dd3d71d42655e00b9cff421.zip |
Merge pull request #253 from cvogt/run
Run
Diffstat (limited to 'stage1/Stage1Lib.scala')
-rw-r--r-- | stage1/Stage1Lib.scala | 69 |
1 files changed, 62 insertions, 7 deletions
diff --git a/stage1/Stage1Lib.scala b/stage1/Stage1Lib.scala index c427b77..5e65018 100644 --- a/stage1/Stage1Lib.scala +++ b/stage1/Stage1Lib.scala @@ -8,7 +8,7 @@ import java.nio.file._ import java.nio.file.attribute.FileTime import javax.tools._ import java.security._ -import java.util.{Set=>_,Map=>_,_} +import java.util.{Set=>_,Map=>_,List=>_,_} import java.util.concurrent.ConcurrentHashMap import javax.xml.bind.annotation.adapters.HexBinaryAdapter @@ -95,12 +95,6 @@ class Stage1Lib( val logger: Logger ) extends BaseLib{ // ========== compilation / execution ========== - def runMainIfFound(cls: String, args: Seq[String], classLoader: ClassLoader ): ExitCode = { - if( classLoader.canLoad(cls) ){ - runMain(cls, args, classLoader ) - } else ExitCode.Success - } - def runMain( cls: String, args: Seq[String], classLoader: ClassLoader, fakeInstance: Boolean = false ): ExitCode = { import java.lang.reflect.Modifier logger.lib(s"Running $cls.main($args) with classLoader: " ++ classLoader.toString) @@ -118,6 +112,67 @@ class Stage1Lib( val logger: Logger ) extends BaseLib{ } } + /** shows an interactive dialogue in the shell asking the user to pick one of many choices */ + def pickOne[T]( msg: String, choices: Seq[T] )( show: T => String ): Option[T] = { + if(choices.size == 0) None else if(choices.size == 1) Some(choices.head) else { + Option(System.console).map{ + console => + val indexedChoices: Map[Int, T] = choices.zipWithIndex.toMap.mapValues(_+1).map(_.swap) + System.err.println( + indexedChoices.map{ case (index,choice) => s"[${index}] "++show(choice)}.mkString("\n") + ) + val range = s"1 - ${indexedChoices.size}" + System.err.println() + System.err.println( msg ++ " [" ++ range ++ "] " ) + val answer = console.readLine() + val choice = try{ + Some(Integer.parseInt(answer)) + }catch{ + case e:java.lang.NumberFormatException => None + } + + choice.flatMap(indexedChoices.get).orElse{ + System.err.println("Not in range "++range) + None + } + }.getOrElse{ + System.err.println("Using '"++show(choices.head)++"' because System.console() == null. Use `cbt direct <task>` or see https://github.com/cvogt/cbt/issues/236") + None + } + } + } + + /** interactively pick one main class */ + def runClass( mainClasses: Seq[Class[_]] ): Option[Class[_]] = { + pickOne( "Which one do you want to run?", mainClasses )( _.toString ) + } + + def mainClasses( targetDirectory: File, classLoader : ClassLoader ): Seq[Class[_]] = { + val arrayClass = classOf[Array[String]] + val unitClass = classOf[Unit] + + listFilesRecursive(targetDirectory) + .filter(_.isFile) + .map(_.getPath) + .collect{ + // no $ to avoid inner classes + case path if !path.contains("$") && path.endsWith(".class") => + classLoader.loadClass( + path + .stripSuffix(".class") + .stripPrefix(targetDirectory.getPath) + .stripPrefix(File.separator) // 1 for the slash + .replace(File.separator, ".") + ) + }.filter( + _.getDeclaredMethods().exists( m => + m.getName == "main" + && m.getParameterTypes.toList == List(arrayClass) + && m.getReturnType == unitClass + ) + ) + } + implicit class ClassLoaderExtensions(classLoader: ClassLoader){ def canLoad(className: String) = { try{ |