I'd like my Scala program to be able to programmatically determine either its script filename or its class name, store the string in a variable program
and print out the name.
Java has several methods for this.
I'd like my Scala program to be able to programmatically determine either its script filename or its class name, store the string in a variable program
and print out the name.
Java has several methods for this.
I think this is the simplest:
val program = new Exception().getStackTrace.head.getFileName
Parsing the stack trace as hinted by 0__ should take care of most of the use cases, in particular when the object with the main method is not in a file of the same name:
package utils
trait ProgramInfo {
val programInfo = try {
throw new RuntimeException("x")
} catch {
case e: RuntimeException =>
val arr = new java.io.CharArrayWriter()
val buffer = new java.io.PrintWriter(arr)
e.printStackTrace(buffer)
val trace = arr.toString
val lines = io.Source.fromString(trace)
val pat = """^.*at.*\.main\(([^:]*)(:.*)?\).*$""".r
lines.getLines().collectFirst{case pat(n, l) => n}.getOrElse("<none>")
}
}
object ProgramInfo extends ProgramInfo
Then you call this like that:
println(utils.ProgramInfo.programInfo)
or you mix in into your main object
object A extends utils.ProgramInfo {
def main(args: Array[String]) {
println(programInfo)
}
}
This works for scripts scala A.script
whether the code is wrapped in an object or not. This also works when compiled with scalac
and run as scala A
. When run with the REPL, this will return <none>
.
Not exactly sure what you are looking for...
$ scala -e 'println( "I am " + getClass.getName )'
gives me
"I am Main$$anon$1"
And
$ scala -e 'try { sys.error( "" )} catch { case e => println( "I am " + e.getStackTrace()( 3 ))}'
gives me
"I am Main.main(scalacmd2873893687624153305.scala)"
// With help from huynhjl
// http://stackoverflow.com/questions/8129185#8131613
import scala.util.matching.Regex.MatchIterator
object ScriptName {
val program = {
val filenames = new RuntimeException("").getStackTrace.map { t => t.getFileName }
val scala = filenames.indexOf("NativeMethodAccessorImpl.java")
if (scala == -1)
"<console>"
else
filenames(scala - 1)
}
def main(args: Array[String]) {
val prog = program
println("Program: " + prog)
}
}
Rosetta Code
#!/bin/bash
exec scala "$0" "$0" "$@"
!#
val program = args(0)
println(program)