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

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

The newest version!
package ammonite.repl

import java.io.{InputStream, OutputStream, OutputStreamWriter}

import ammonite.terminal.filters._
import GUILikeFilters.SelectionFilter
import ammonite.terminal._
import fastparse.core.Parsed

import ammonite.util.{Colors, Res}
import ammonite.interp.Parsers
case class AmmoniteFrontEnd(extraFilters: Filter = Filter.empty) extends FrontEnd{

  def width = FrontEndUtils.width
  def height = FrontEndUtils.height

  def action(input: InputStream,
             reader: java.io.Reader,
             output: OutputStream,
             prompt: String,
             colors: Colors,
             compilerComplete: (Int, String) => (Int, Seq[String], Seq[String]),
             history: IndexedSeq[String],
             addHistory: String => Unit) = {
    readLine(reader, output, prompt, colors, compilerComplete, history) match{
      case None => Res.Exit(())
      case Some(code) =>
        addHistory(code)
        Parsers.Splitter.parse(code) match{
          case Parsed.Success(value, idx) =>
            Res.Success((code, value))
          case Parsed.Failure(_, index, extra) =>
            Res.Failure(
              fastparse.core.ParseError.msg(extra.input, extra.traced.expected, index)
            )
        }
    }
  }

  val cutPasteFilter = ReadlineFilters.CutPasteFilter()

  def readLine(reader: java.io.Reader,
               output: OutputStream,
               prompt: String,
               colors: Colors,
               compilerComplete: (Int, String) => (Int, Seq[String], Seq[String]),
               history: IndexedSeq[String]) = {

    val writer = new OutputStreamWriter(output)

    val autocompleteFilter: Filter = Filter.action(SpecialKeys.Tab){
      case TermState(rest, b, c, _) =>
        val (newCursor, completions, details) = compilerComplete(c, b.mkString)
        val details2 = for (d <- details) yield {

          Highlighter.defaultHighlight(
            d.toVector,
            colors.comment(),
            colors.`type`(),
            colors.literal(),
            colors.keyword(),
            fansi.Attr.Reset
          ).mkString
        }

        lazy val common = FrontEndUtils.findPrefix(completions, 0)

        val blacklisted = Seq(
          "!=",
          "==",
          "asInstanceOf",
          "equals",
          "getClass",
          "hashCode",
          "isInstanceOf",
          "toString",
          "|>"
        )

        val completions2 = for(comp <- completions.filterNot(blacklisted.contains)) yield {

          val (left, right) = comp.splitAt(common.length)
          (colors.comment()(left) ++ right).render
        }
        val stdout =
          FrontEndUtils.printCompletions(completions2, details2)
                       .mkString

        if (details.nonEmpty || completions.isEmpty)
          Printing(TermState(rest, b, c), stdout)
        else{
          val newBuffer = b.take(newCursor) ++ common ++ b.drop(c)
          Printing(TermState(rest, newBuffer, newCursor + common.length), stdout)
        }

    }

    // Enter
    val multilineFilter = Filter.action(
      SpecialKeys.NewLine,
      ti => Parsers.split(ti.ts.buffer.mkString).isEmpty
    ){
      case TermState(rest, b, c, _) => BasicFilters.injectNewLine(b, c, rest)
    }

    val historyFilter = new HistoryFilter(
      () => history.reverse, colors.comment()
    )
    val selectionFilter = GUILikeFilters.SelectionFilter(indent = 2)

    val allFilters = Filter.merge(
      UndoFilter(),
      historyFilter,
      extraFilters,
      selectionFilter,
      GUILikeFilters.altFilter,
      GUILikeFilters.fnFilter,
      ReadlineFilters.navFilter,
      autocompleteFilter,
      cutPasteFilter,
      multilineFilter,
      BasicFilters.all
    )


    val res = Terminal.readLine(
      prompt,
      reader,
      writer,
      allFilters,
      displayTransform = { (buffer, cursor) =>


        val indices = Highlighter.defaultHighlightIndices(
          buffer,
          colors.comment(),
          colors.`type`(),
          colors.literal(),
          colors.keyword(),
          fansi.Attr.Reset
        )
        val highlighted = fansi.Str(Highlighter.flattenIndices(indices, buffer).mkString)
        val (newBuffer, offset) = SelectionFilter.mangleBuffer(
          selectionFilter, highlighted, cursor, colors.selected()
        )

        val newNewBuffer = HistoryFilter.mangleBuffer(
          historyFilter, newBuffer, cursor, fansi.Underlined.On
        )
        (newNewBuffer, offset)
      }
    )
    res
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy