val box: List[String] =
List(
"+---------------+",
"| |",
"+---+---+---+---+",
"| q | c | d | = |",
"+---+---+---+---+",
"| 1 | 2 | 3 | + |",
"+---+---+---+---+",
"| 4 | 5 | 6 | - |",
"+---+---+---+---+",
"| 7 | 8 | 9 | * |",
"+---+---+---+---+"
)
val buttons: String = {
val standard = "qcd=123+456-789*0()/"
val extra = "QCD \033\010\014\n"
standard + extra
}
val showbox: IO[Unit] = seqn((1 to 13).zip(box).map(t => writeat((1, t._1))(t._2)).toList)
def display(s: String): IO[Unit] =
for {
_ <- writeat((3, 2))(" ")
_ <- writeat((3, 2))(s.toCharArray.takeRight(13).mkString)
} yield ()
def calc(s: String): IO[Unit] =
for {
_ <- display(s)
c <- getChar
_ <- if (buttons.contains(c)) process(c)(s)
else for {
_ <- beep
_ <- calc(s)
} yield ()
} yield ()
def process(c: Char)(s: String): IO[Unit] = s match {
case _ if "qQ\033".contains(c) => quit
case _ if "dD\010\014".contains(c) => delete(s)
case _ if "=\n".contains(c) => eval(s)
case _ if "cC".contains(c) => clear
case _ => process(c)(s)
}
def quit = goto((1, 14))
def delete(s: String) = s match {
case "" => calc("")
case xs => calc(xs.head.toString)
}
import ParserMain._
def eval(s: String): IO[Unit] = expr.run(s) match {
case Some((_, n)) => calc(n.toString)
case None =>
for {
_ <- beep
_ <- calc(s)
} yield ()
}
def clear: IO[Unit] = calc("")
def press(c: Char)(s: String): IO[Unit] = calc(s + c.toString)
val run: IO[Unit] =
for {
_ <- cls
_ <- showbox
_ <- clear
} yield ()
run.unsafeRunSync()