How do I get the current script or class name in S

2020-04-10 13:58发布

问题:

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.

回答1:

I think this is the simplest:

val program = new Exception().getStackTrace.head.getFileName


回答2:

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>.



回答3:

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)"


回答4:

// 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



回答5:

#!/bin/bash
exec scala "$0" "$0" "$@"
!#

val program = args(0)
println(program)