9

是否有停止/退出 Scala REPL 的热键?

示例:我使用 command 从 SBT 启动 Scala REPL console,然后执行一些愚蠢的操作,例如无限循环,并希望在完全不关闭 shell 的情况下结束 REPL。像Ctrl+ CCtrl+DCtrl+之类的东西Z(都不起作用)。

更新: 使用的操作系统:Windows 7 64 位。

Ctrl+D存在 SBT 和 REPL,但是当我处于无限循环中时Ctrl+不会退出 REPLD

while(true) prinln("test")

有没有办法在不关闭外壳的情况下使用热键退出无限循环?或者这是不可能的,因为 REPL 在循环结束之前不会对热键做出反应(当然,在这种情况下不会发生)?

4

2 回答 2

2

The following works with Scala 2.10.0-M6, but in 2.9.2 you can probably achieve something similar using :wrap in REPL power mode.

Assume that the REPL is started from sbt via sbt console—without loss of generality (you may otherwise just put the ReplUtil class on scala's class path). Assume the following class is on the class path, e.g. its source is at src/main/scala/ReplUtil.scala:

import java.util.concurrent.{Executors, ExecutorService, TimeoutException, TimeUnit}
import concurrent._

object ReplUtil {
  @volatile private var exec: ExecutorService = _
  @volatile private var threads = Set.empty[ Thread ]
  private def freshPool() { exec = Executors.newCachedThreadPool() }
  freshPool()

  private implicit def context = ExecutionContext.fromExecutorService( exec )

  def panic() {
    (new Thread {
      override def run() {
        try {
          exec.shutdownNow()
          exec.awaitTermination( 1, TimeUnit.SECONDS ) 
        } finally {
          val th = threads
          threads = Set.empty
          th.foreach( _.stop )
          freshPool()
        }
      }
    }).start()
  }    

  def spawn[T](t: => T) = {
    var futPrint = false
    val fut = future {
       val th = Thread.currentThread()
       threads += th
       val res = try { t } finally { threads -= th }
       if( futPrint ) println( "<calculation done>\n" + res )
       t
    }
    try {
      Await.result( fut, util.Duration( 4, TimeUnit.SECONDS )).toString
    } catch {
      case e: TimeoutException =>
        futPrint = true
        "<ongoing calculation>"
    }
  }
}

Then the following will activate the semi-asynchronous REPL:

$ sbt console
...
Welcome to Scala version 2.10.0-M6 (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_33).
...
scala> import ReplUtil.panic
import ReplUtil.panic

scala> :power
** Power User mode enabled - BEEP WHIR GYVE **
...

scala> power.intp.setExecutionWrapper("ReplUtil.spawn")

scala> 2+2
res1: Int = 4

scala> Thread.sleep(6000); 33
<ongoing calculation>

scala> <calculation done>
res2: Int = 33

scala> while(true) { Thread.sleep(2000); println( "Zzz" )}
Zzz
Zzz
<ongoing calculation>
scala> panic

scala> [error] (pool-5-thread-1) java.lang.ExceptionInInitializerError
java.lang.ExceptionInInitializerError
...
Caused by: java.lang.InterruptedException: sleep interrupted
...
于 2012-08-09T01:50:41.387 回答
0

与该主题相关的是一个有用的Shift+D键绑定,用于在 eclipse scala 工作表中退出程序的非终止评估。

于 2017-02-22T07:19:12.527 回答