【问题标题】:Hotkey to stop REPL?停止 REPL 的热键?
【发布时间】:2012-08-08 21:22:37
【问题描述】:

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

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

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

Ctrl+D 存在 SBT 和 REPL,但 Ctrl+D 不退出 REPL 时我处于一个无限循环中,就像

while(true) prinln("test")

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

【问题讨论】:

  • hm 你用的是什么操作系统?因为 ctrl+c 似乎对我有用(在 MacOS 10.6 下)
  • 你是从 sbt 启动的,因为你说console
  • @MateuszDymczyk 哦,我明白了,这似乎是操作系统特定的问题。我使用的是 Windows 7 64 位版。 Ctrl+C 对我不起作用。
  • @0__ 是的,你是对的。我现在在我的问题中明确了这一点。

标签: scala read-eval-print-loop


【解决方案1】:

以下适用于 Scala 2.10.0-M6,但在 2.9.2 中,您可能可以在 REPL 电源模式下使用 :wrap 实现类似的效果。

假设 REPL 通过 sbt console 从 sbt 开始——不失一般性(否则你可以将 ReplUtil 类放在 scala 的类路径中)。假设以下类在类路径上,例如它的来源是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>"
    }
  }
}

那么下面会激活半异步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
...

【讨论】:

  • Q 怎么可能是 +6 而 A 是 +0?无论如何,鉴于 :wrap 的消亡,REPL 需要通用模板,内置“定时”、“可中断”等。
【解决方案2】:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-13
    • 1970-01-01
    • 2012-11-19
    • 1970-01-01
    • 1970-01-01
    • 2023-03-27
    相关资源
    最近更新 更多