#shell #scala #interactive #readline
#оболочка #scala #интерактивная #строка чтения
Вопрос:
Я хочу написать интерактивную оболочку в scala с поддержкой строки чтения (Ctrl-l, клавиши со стрелками, редактирование строк, история и т. Д.).
Я знаю, как это сделать на python:
# enable support for Ctrl-l, arrow keys, line editing, history, etc.
import readline
finished = False
while not finished:
try:
line = raw_input('> ')
if line:
if line == 'q':
finished = True
else:
print line
except KeyboardInterrupt:
print 'Ctrl-c'; finished = True
except EOFError:
print 'Ctrl-d'; finished = True
Я хочу написать простую программу scala с точно таким же поведением. Моим ближайшим решением до сих пор является следующий scala:
// used to support Ctrl-l, arrow keys, line editing, history, etc.
import scala.tools.jline
val consoleReader = new jline.console.ConsoleReader()
var finished = false
while (!finished) {
val line = consoleReader.readLine("> ")
if (line == null) {
println("Ctrl-d")
finished = true
} else if (line.size > 0) {
if (line == "q") {
finished = true
} else {
println(line)
}
}
}
Открытые вопросы:
- как обрабатывать ctrl-c?
- можно ли использовать исключения аналогично python?
- является ли это оптимальным решением или его можно улучшить?
Ответ №1:
Вы могли бы написать иерархию jline
событий, например:
sealed trait JLineEvent
case class Line(value: String) extends JLineEvent
case object EmptyLine extends JLineEvent
case object EOF extends JLineEvent
Затем вы можете инкапсулировать while
цикл в функцию, которая принимает в качестве параметра функцию JLineEvent
:
def console( handler: JLineEvent => Boolean ) {
val consoleReader = new jline.console.ConsoleReader()
var finished = false
while (!finished) {
val line = consoleReader.readLine("> ")
if (line == null) {
finished = handler( EOF )
} else if (line.size == 0) {
finished = handler( EmptyLine )
} else if (line.size > 0) {
finished = handler( Line( line ) )
}
}
Наконец, вы можете вызвать его с помощью соответствующей функции:
console {
case EOF =>
println("Ctrl-d")
true
case Line(s) if s == "q" =>
true
case Line(s) =>
println(line)
false
case _ =>
false
}
Для перехвата ctrl C
, возможно, могут быть перехваты выключения.