2011-10-27 31 views
5

Tôi muốn viết vỏ tương tác trong scala, với hỗ trợ cho readline (Ctrl-l, phím mũi tên, chỉnh sửa dòng, lịch sử, vv).Làm thế nào để viết vỏ tương tác với hỗ trợ readline trong scala?

Tôi biết làm thế nào để làm điều đó trong 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 

Tôi muốn viết một chương trình scala đơn giản, với chính xác hành vi tương tự. giải pháp gần gũi nhất của tôi cho đến bây giờ là scala sau:

// 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) 
    } 
    } 
} 

Các câu hỏi mở là:

  • làm thế nào để xử lý ctrl-c?
  • có thể sử dụng ngoại lệ theo cách tương tự như python không?
  • là giải pháp tối ưu này hoặc nó có thể được cải thiện?

Trả lời

7

Bạn có thể viết một hệ thống các jline sự kiện, ví dụ:

sealed trait JLineEvent 
case class Line(value: String) extends JLineEvent 
case object EmptyLine extends JLineEvent 
case object EOF extends JLineEvent 

Sau đó, bạn có thể rút gọn các while vòng lặp trong một chức năng mà mất như tham số hàm của 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)) 
    } 
    } 

Cuối cùng, bạn có thể gọi nó bằng chức năng thích hợp:

console { 
    case EOF => 
      println("Ctrl-d") 
      true 
    case Line(s) if s == "q" => 
      true 
    case Line(s) => 
      println(line) 
      false 
    case _ => 
      false 
} 

Để bắt ctrl+C có lẽ móc tắt máy có thể là một giải pháp.

Các vấn đề liên quan