Skip to content

Instantly share code, notes, and snippets.

@lihaoyi
Last active January 2, 2017 20:01
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save lihaoyi/1ebdd89b065a741a1ea72b5d780b9ab1 to your computer and use it in GitHub Desktop.
Save lihaoyi/1ebdd89b065a741a1ea72b5d780b9ab1 to your computer and use it in GitHub Desktop.
Setting up a "Walk through pre-loaded example snippets every time you press spacebar" experience in the Ammonite REPL
lihaoyi Ammonite$ amm
Loading...
Welcome to the Ammonite Repl 0.8.0
(Scala 2.11.8 Java 1.8.0_112)
@ {
val funnyFilter = ammonite.terminal.Filter.simple(" ")((b, c, m) =>
if (FunnyFrontEnd.nextLine == Nil) (b.take(c) ++ " " ++ b.drop(c), c+1)
else {
val head :: tail = FunnyFrontEnd.nextLine
FunnyFrontEnd.nextReader = new java.io.StringReader(head)
FunnyFrontEnd.nextLine = tail
(b, c)
}
)
object FunnyFrontEnd extends ammonite.repl.AmmoniteFrontEnd(funnyFilter){
var nextLine = List.empty[String]
var nextReader = new java.io.StringReader("")
def setNextLines(s: Seq[String]) = nextLine = s.toList
override def readLine(reader: java.io.Reader,
output: java.io.OutputStream,
prompt: String,
colors: ammonite.util.Colors,
compilerComplete: (Int, String) => (Int, Seq[String], Seq[String]),
history: IndexedSeq[String]) = {
val readerX = new java.io.Reader{
def close() = {reader.close(); nextReader.close()}
def read(cbuf: Array[Char], off: Int, len: Int) = {
val preRead = nextReader.read(cbuf, off, len)
if(preRead == len) preRead
else{
val preReadNum = math.max(0, preRead)
val postRead = reader.read(cbuf, off + preReadNum, len - preReadNum)
if (postRead == -1) -1 else postRead + preReadNum
}
}
}
super.readLine(readerX, output, prompt, colors, compilerComplete, history)
}
}
repl.frontEnd() = FunnyFrontEnd
}
funnyFilter: AnyRef with ammonite.terminal.Filter{def op(ti: ammonite.terminal.TermInfo): Option[ammonite.terminal.TermState]} = $sess.cmd0.funnyFilter:1
defined object FunnyFrontEnd
@ FunnyFrontEnd.setNextLines(Seq("println(\"Hello\")", "println(\"World\")"))
@ println("Hello")
Hello
@ println("World")
World
@lihaoyi
Copy link
Author

lihaoyi commented Dec 6, 2016

This is a demo i made for people on Gitter/Twitter that I thought was neat enough to share.

Ammonite exposes a lot of its API to you, and you can use it to do a lot of things like swap out the front-end that's taking input for a whole new one, or pass in extra input-filters you can use to implement custom hotkeys. Not many people know about this stuff or use it, but it's there.

In this case, it lets you implement a "presentation REPL" entirely in user-land, by substituting in a custom front-end that you can pre-load code strings into, and registering a filter on " " that loads the next code-string into the prompt, editable and ready to use, when you press .

You should be able to paste this into any Ammonite REPL (or put it in your predef.sc) and have it work without external plugins or anything. All the relevant code is in that snippet, so if you want to change the hotkeys or add additional logic you can do so by tweaking the linked code.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment