@@ -5,6 +5,9 @@ import scala.annotation.tailrec
5
5
import scala .io .Source
6
6
import scala .util .Try
7
7
import java .net .URLClassLoader
8
+ import sys .process ._
9
+ import java .io .File
10
+ import java .lang .Thread
8
11
9
12
enum ExecuteMode :
10
13
case Guess
@@ -20,6 +23,7 @@ case class Settings(
20
23
residualArgs : List [String ] = List .empty,
21
24
scriptArgs : List [String ] = List .empty,
22
25
targetScript : String = " " ,
26
+ areWithCompiler : Boolean = false ,
23
27
) {
24
28
def withExecuteMode (em : ExecuteMode ): Settings = this .executeMode match
25
29
case ExecuteMode .Guess =>
@@ -42,10 +46,15 @@ case class Settings(
42
46
println(s " not found $file" )
43
47
this .copy(exitCode = 2 )
44
48
end withTargetScript
49
+
50
+ def withCompiler : Settings =
51
+ this .copy(areWithCompiler = true )
45
52
}
46
53
47
54
object MainGenericRunner {
48
55
56
+ final val classpathSeparator = " :"
57
+
49
58
@ tailrec
50
59
def process (args : List [String ], settings : Settings ): Settings = args match
51
60
case Nil =>
@@ -69,6 +78,8 @@ object MainGenericRunner {
69
78
residualArgs = settings.residualArgs :+ " -verbose"
70
79
)
71
80
)
81
+ case " -with-compiler" :: tail =>
82
+ process(tail, settings.withCompiler)
72
83
case arg :: tail =>
73
84
val line = Try (Source .fromFile(arg).getLines.toList).toOption.flatMap(_.headOption)
74
85
if arg.endsWith(" .scala" ) || arg.endsWith(" .sc" ) || (line.nonEmpty && raw " #!.*scala " .r.matches(line.get)) then
@@ -85,24 +96,39 @@ object MainGenericRunner {
85
96
settings.executeMode match
86
97
case ExecuteMode .Repl =>
87
98
val properArgs =
88
- List (" -classpath" , settings.classPath.mkString(" ; " )).filter(Function .const(settings.classPath.nonEmpty))
99
+ List (" -classpath" , settings.classPath.mkString(classpathSeparator )).filter(Function .const(settings.classPath.nonEmpty))
89
100
++ settings.residualArgs
90
101
repl.Main .main(properArgs.toArray)
91
102
case ExecuteMode .Run =>
92
103
val properArgs =
93
- List (" -classpath" , settings.classPath.mkString(" ;" )).filter(Function .const(settings.classPath.nonEmpty))
104
+ val newClasspath = settings.classPath ++ getClasspath :+ " ."
105
+ List (" -classpath" , newClasspath.mkString(classpathSeparator)).filter(Function .const(newClasspath.nonEmpty))
94
106
++ settings.residualArgs
95
- // TODO this is just a java proxy?
107
+ s " java ${properArgs.mkString( " " )} " . ! // For now we collect classpath that coursier provides for convenience
96
108
case ExecuteMode .Script =>
97
109
val properArgs =
98
- List (" classpath" , settings.classPath.mkString(" ; " )).filter(Function .const(settings.classPath.nonEmpty))
110
+ List (" - classpath" , settings.classPath.mkString(classpathSeparator )).filter(Function .const(settings.classPath.nonEmpty))
99
111
++ settings.residualArgs
100
112
++ List (" -script" , settings.targetScript)
101
113
++ settings.scriptArgs
102
114
scripting.Main .main(properArgs.toArray)
103
115
case ExecuteMode .Guess =>
104
116
val properArgs =
105
- List (" -classpath" , settings.classPath.mkString(" ; " )).filter(Function .const(settings.classPath.nonEmpty))
117
+ List (" -classpath" , settings.classPath.mkString(classpathSeparator )).filter(Function .const(settings.classPath.nonEmpty))
106
118
++ settings.residualArgs
107
119
repl.Main .main(properArgs.toArray)
120
+
121
+
122
+ private def getClasspath (cl : ClassLoader ): Array [String ] = cl match
123
+ case null => Array ()
124
+ case u : URLClassLoader => u.getURLs.map(_.toURI.toString) ++ getClasspath(cl.getParent)
125
+ case cl if cl.getClass.getName == " jdk.internal.loader.ClassLoaders$AppClassLoader" =>
126
+ // Required with JDK >= 9
127
+ sys.props.getOrElse(" java.class.path" , " " )
128
+ .split(File .pathSeparator)
129
+ .filter(_.nonEmpty)
130
+ case _ => getClasspath(cl.getParent)
131
+
132
+ private def getClasspath : List [String ] =
133
+ getClasspath(Thread .currentThread().getContextClassLoader).toList
108
134
}
0 commit comments