All Downloads are FREE. Search and download functionalities are using the official Maven repository.

ammonite.repl.Repl.scala Maven / Gradle / Ivy

There is a newer version: 1.6.7-2-c28002d
Show newest version
package ammonite.repl

import java.io.{PrintStream, InputStream, OutputStream, InputStreamReader}
import ammonite.repl.frontend._
import acyclic.file
import ammonite.repl.interp.Interpreter
import ammonite.terminal.Filter

import scala.annotation.tailrec
class Repl(input: InputStream,
           output: OutputStream,
           error: OutputStream,
           storage: Ref[Storage],
           predef: String = "",
           replArgs: Seq[Bind[_]] = Nil) {

  val prompt = Ref("@ ")

  val colors = Ref[Colors](Colors.Default)
  val frontEnd = Ref[FrontEnd](AmmoniteFrontEnd(Filter.empty))

  val printStream = new PrintStream(output, true)
  val errorPrintStream = new PrintStream(error, true)
  var history = new History(Vector())


  def printlnWithColor(color: String, endColor: String, s: String) = {
    Seq(color, s, endColor, "\n").foreach(errorPrintStream.print)
  }
  val printer = Printer(
    _.foreach(printStream.print),
    printlnWithColor(colors().warning(), colors().reset(), _),
    printlnWithColor(colors().error(), colors().reset(), _),
    printlnWithColor("", "", _)
  )
  Timer("Repl init printer")

  
  val interp: Interpreter = new Interpreter(
    prompt,
    frontEnd,
    frontEnd().width,
    frontEnd().height,
    pprint.Config.Colors.PPrintConfig,
    colors,
    printer,
    storage,
    history,
    predef,
    replArgs
  )

  Timer("Repl init interpreter")
  val reader = new InputStreamReader(input)
  def action() = for{
    (code, stmts) <- frontEnd().action(
      input,
      reader,
      output,
      colors().prompt() + prompt() + colors().reset(),
      colors(),
      interp.pressy.complete(_, interp.eval.previousImportBlock, _),
      storage().fullHistory(),
      addHistory = (code) => if (code != "") {
        storage().fullHistory() = storage().fullHistory() :+ code
        history = history :+ code
      }
    )
    _ <- Signaller("INT") { interp.mainThread.stop() }
    out <- interp.processLine(code, stmts)
  } yield {
    Timer("interp.processLine end")
    printStream.println()
    out
  }

  def ammoniteVersion = ammonite.Constants.version
  def scalaVersion = scala.util.Properties.versionNumberString
  def javaVersion = System.getProperty("java.version")

  def printBanner(): Unit = {
    printStream.println(s"Welcome to the Ammonite Repl $ammoniteVersion")
    printStream.println(s"(Scala $scalaVersion Java $javaVersion)")
  }

  def run(): Any = {
    printBanner()
    @tailrec def loop(): Any = {
      val res = action()
      Timer("End Of Loop")
      val res2 = res match{
        case Res.Exit(value) =>
          printStream.println("Bye!")
          value
        case Res.Failure(ex, msg) => printer.error(msg)
        case Res.Exception(ex, msg) =>
          printer.error(
            Repl.showException(ex, colors().error(), colors().reset(), colors().literal())
          )
          printer.error(msg)
        case _ =>
      }

      if (interp.handleOutput(res)) loop()
      else res2
    }
    loop()
  }
}

object Repl{
  def highlightFrame(f: StackTraceElement,
                     error: String,
                     highlightError: String,
                     source: String) = {
    val src =
      if (f.isNativeMethod) source + "Native Method" + error
      else s"$source${f.getFileName}$error:$source${f.getLineNumber}$error"

    val prefix :+ clsName = f.getClassName.split('.').toSeq
    val prefixString = prefix.map(_+'.').mkString("")
    val clsNameString = clsName.replace("$", error+"$"+highlightError)
    val method =
      s"$error$prefixString$highlightError$clsNameString$error" +
        s".$highlightError${f.getMethodName}$error"

    s"  $method($src)"
  }
  def showException(ex: Throwable, error: String, highlightError: String, source: String) = {
    val cutoff = Set("$main", "evaluatorRunPrinter")
    val traces = Ex.unapplySeq(ex).get.map(exception =>
      error + exception.toString + "\n" +
        exception
          .getStackTrace
          .takeWhile(x => !cutoff(x.getMethodName))
          .map(highlightFrame(_, error, highlightError, source))
          .mkString("\n")
    )
    traces.mkString("\n")
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy