readline provides Scala Native bindings for the GNU Readline Library.
The goal of this project is to provide an easy-to-use Scala Native facade for the portion of the library that is often used to create REPL's. An example REPL application is provided below that just echos what is typed, however the example also shows how to use readline's history feature including not adding duplicates to the history.
The more "programmer friendly" part of this library is found in the io.github.edadma.readline.facade
package. That's the only package you need to import from, as seen in the example below. The other package in the library is io.github.edadma.readline.extern
which provides for interaction with the Readline C library using Scala Native interoperability elements from the so-call unsafe
namespace. There are no public declarations in the io.github.edadma.readline.facade
package that use unsafe
types in their parameter or return types, making it a pure Scala facade. Consequently, you never have to worry about memory allocation or type conversions.
To use this library, libreadline-dev
needs to be installed:
sudo apt install libreadline-dev
Include the following in your project/plugins.sbt
:
addSbtPlugin("com.codecommit" % "sbt-github-packages" % "0.5.2")
Include the following in your build.sbt
:
resolvers += Resolver.githubPackages("edadma")
libraryDependencies += "io.github.edadma" %%% "readline" % "0.1.2"
Use the following import
in your code:
import io.github.edadma.readline.facade._
This example provides the skeleton for a REPL with history support, including making sure duplicates don't get added to the history.
import io.github.edadma.readline.facade._
import scala.annotation.tailrec
import Console._
object Main extends App {
val homeDir = System.getProperty("user.home")
val HISTORY_FILE = s"$homeDir/.my_readline_history"
var historyExists = read_history(HISTORY_FILE)
@tailrec
def repl(): Unit = {
val prompt = s"${CYAN}type something$RESET> "
val line = readline(prompt)
if (line != null) {
val s = line.trim
if (s nonEmpty) {
println(s"type typed '$s'")
// do something with 's'
val prev = history_get(history_base + history_length - 1)
if (prev == null || prev != s) {
add_history(s) // only add to history if it's not a duplicate of the previous item
if (historyExists == 0)
append_history(1, HISTORY_FILE)
else {
historyExists = 0
write_history(HISTORY_FILE)
}
}
}
repl()
}
}
repl()
}
The official documentation for the Readline library can be found at readline. The official documentation for the history library can be found at history.