@@ -4,10 +4,13 @@ import dotty.tools.dotc.core.StdNames.str
44
55import java .io .PrintStream
66import java .lang .reflect .Method
7+ import scala .annotation .tailrec
78import scala .util .control .NonFatal
9+ import scala .util .{Failure , Success , Try }
810
911/** Interprets Scala code, based on `dotty.tools.repl.ScriptEngine` */
1012class SCIMain (out : PrintStream , loader : ClassLoader ) {
13+ import SCIMain .*
1114
1215 private val driver =
1316 new ReplDriver (
@@ -21,32 +24,41 @@ class SCIMain(out: PrintStream, loader: ClassLoader) {
2124 out,
2225 Some (loader)
2326 )
24-
25- private var state = driver.initialState
2627 private val rendering = new Rendering (Some (getClass.getClassLoader))
28+ private var state = driver.initialState
2729
2830 def bind (tup : (String , Any )): Unit =
2931 state = driver.bind(tup._1, tup._2)(using state)
3032
3133 def interpret (line : String ): SCResults = {
32- val methodOpt : Option [Method ] =
33- try {
34+ // Parse script
35+ val methodTry : Try [Option [Method ]] =
36+ Try {
3437 evalToMethod(line)
35- } catch {
36- case NonFatal (ex) =>
37- // ex.printStackTrace()
38- // ex.printStackTrace(out)
39- return SCResults .Error
4038 }
4139
42- val valueOpt : Option [Any ] = methodOpt.map(_.invoke(null ))
40+ // Execute parsed script
41+ val result : Try [Unit ] =
42+ for methodOpt <- methodTry yield {
43+ for method <- methodOpt do
44+ val value = method.invoke(null )
45+ if value != () then
46+ out.println(s " ${method.getName}: $value" )
47+ }
48+
49+ // Interpret script execution result
50+ result match
51+ case Success (_) =>
52+ SCResults .Success
53+ case Failure (ex) =>
54+ if wasCausedByImageJMacroAbort(ex) then
55+ out.println(s " WARNING: Detected ImageJ's \" $IMAGEJ_MACRO_CANCELED\" request. Stopping script execution. " )
56+ SCResults .Success
57+ else
58+ // ex.printStackTrace()
59+ // ex.printStackTrace(out)
60+ SCResults .Error
4361
44- val value = valueOpt.getOrElse(())
45- val methodName = methodOpt.fold(" " )(_.getName)
46- if (methodOpt.isDefined && valueOpt.isDefined && ! valueOpt.contains(())) {
47- out.println(s " $methodName: $value" )
48- }
49- SCResults .Success
5062 }
5163
5264 private def evalToMethod (script : String ): Option [Method ] = {
@@ -59,4 +71,23 @@ class SCIMain(out: PrintStream, loader: ClassLoader) {
5971 .find(_.getName == s " ${str.REPL_RES_PREFIX }$vid" )
6072 }
6173
74+ /**
75+ * Check if exception has a signature of an exception thrown by ImageJ to indicate that macro cancellation.
76+ * @param t exception to test
77+ * @return `true` is the exception matches the ImageJ' macro abort exception.
78+ */
79+ @ tailrec
80+ private final def wasCausedByImageJMacroAbort (t : Throwable ): Boolean = {
81+ if t == null then
82+ false
83+ else if t.isInstanceOf [RuntimeException ] & t.getMessage == IMAGEJ_MACRO_CANCELED then
84+ true
85+ else
86+ wasCausedByImageJMacroAbort(t.getCause)
87+ }
88+
6289}
90+
91+ object SCIMain :
92+ private val IMAGEJ_MACRO_CANCELED = " Macro canceled"
93+ end SCIMain
0 commit comments