Skip to content

Commit 27d6181

Browse files
Merge pull request #7 from kevinvandervlist/jline
Add Jline ('readline') to the REPL for convenience
2 parents d1314ae + 641355e commit 27d6181

File tree

4 files changed

+21
-18
lines changed

4 files changed

+21
-18
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ This provides a parser and interpreter and REPL for the untyped lambda calculus.
77
The REPL has tracing capabilities to show all intermediate reduction steps.
88
Among others, the following features are supported:
99

10-
* Lambda is either a `λ` or a `\ `, so `\x.x` and `λx.x` are identical.
10+
* Lambda is either a `λ` or a `\\ `, so `\\x.x` and `λx.x` are identical.
1111
* There is a shorthand available for nesting, so `λx y z.x y z` is equal to `λx.λy.λz.x y z`.
1212
* The parser is fully left-associative, so `x y z` is `(x y) z`.
1313
* The REPL can toggle between a normal and a *tracing* mode, showing all intermediate reduction steps.

build.sbt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,8 @@ lazy val repl = (project in file("repl")).
5757
libraryDependencies ++= Seq(
5858
"org.scala-lang.modules" %% "scala-parser-combinators" % sParSecVersion,
5959
"org.typelevel" %% "cats" % catsVersion,
60-
"org.typelevel" %% "cats-free" % catsVersion
60+
"org.typelevel" %% "cats-free" % catsVersion,
61+
"org.jline" % "jline" % "3.1.2"
6162
),
6263
mainClass in assembly := Some("nl.soqua.lcpi.repl.Main")
6364
).dependsOn(ast, parser, interpreter % "test->test;compile->compile")

repl/src/main/scala/nl/soqua/lcpi/repl/Main.scala

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6,46 +6,48 @@ import nl.soqua.lcpi.interpreter.Context
66
import nl.soqua.lcpi.repl.lib.{CombinatorLibrary, DiskIO}
77
import nl.soqua.lcpi.repl.monad.{ReplCompiler, ReplState}
88
import nl.soqua.lcpi.repl.parser.StdInParser
9+
import org.jline.reader.LineReaderBuilder
10+
import org.jline.terminal.TerminalBuilder
911

1012
import scala.io.Source
1113
import scala.util.Try
1214

1315
object Main extends App {
1416
var ctx = CombinatorLibrary loadIn Context()
1517

16-
def drawShell(): Unit = print("lcpi λ> ")
18+
val prompt = "lcpi λ> "
1719

1820
println(
1921
"""
2022
|A λ-calculus interpreter. Type `help` for usage information.
2123
""".stripMargin
2224
)
2325

24-
drawShell()
25-
2626
var state = ReplState.empty
2727
var effect: Any = _
2828

29+
val terminal = TerminalBuilder.builder()
30+
.system(true)
31+
.build()
32+
33+
val lineReader = LineReaderBuilder.builder()
34+
.terminal(terminal)
35+
.build()
36+
2937
val compiler = new DiskIO() with ReplCompiler {
3038
override def readFile(path: String): Try[Stream[String]] = Try {
3139
Source.fromFile(new File(path)).getLines().toStream
3240
}
3341
}
3442

35-
for (ln <- io.Source.stdin.getLines) {
36-
StdInParser(ln) match {
43+
while (!state.terminated) {
44+
val line = Try(lineReader.readLine(prompt)).getOrElse("quit")
45+
StdInParser(line) match {
3746
case Left(e) => println(e)
38-
case Right(cmd) => cmd.foldMap(compiler.compile).run(state).value match {
39-
case (s: ReplState, _) if s.terminated =>
40-
System.exit(0)
41-
case (s: ReplState, effect: String) =>
42-
state = s
43-
println(effect)
44-
case (s: ReplState, _) =>
45-
state = s
46-
case _ =>
47+
case Right(cmd) => state = cmd.foldMap(compiler.compile).run(state).value match {
48+
case (s: ReplState, effect: String) => println(effect); s
49+
case (s: ReplState, _) => s
4750
}
4851
}
49-
drawShell()
5052
}
5153
}

repl/src/main/scala/nl/soqua/lcpi/repl/Messages.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ object Messages {
1313
val help: String =
1414
s"""
1515
|Notation:
16-
|* λ is either a λ or a \\. So both \\x.x and λx.x are allowed.
16+
|* λ is either a λ or a \\\\. So both \\\\x.x and λx.x are allowed.
1717
|* You can assign variables; `I := λx.x` stores the identity function to the variable `I`.
1818
| These have to be capitalized.
1919
|

0 commit comments

Comments
 (0)