Last active
January 2, 2017 20:01
-
-
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.