Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Hotkey to stop REPL?

Is there a hotkey to stop/exit the Scala REPL ?

Example: I start the Scala REPL from SBT with command console, then do something stupid like an endless loop and want to end the REPL without closing the shell at all. Something like Ctrl+C, Ctrl+D or Ctrl+Z (which all do not work).

Update: Used OS: Windows 7 64 Bit.

Ctrl+D exists SBT and the REPL, but Ctrl+D does NOT exit the REPL when I am in an endless loop like

while(true) prinln("test")

Is there a way to get out of the endless loop with a hotkey without closing the shell ? Or is this not possible because the REPL will not react to hotkeys until the loop is through (which will, of course, not happen in this case) ?

like image 437
John Threepwood Avatar asked Aug 08 '12 21:08

John Threepwood


People also ask

How do you stop an execution in REPL?

You can just press ctrl-d (*nix) or ctrl-z (Windows) to exit the REPL.

How do I exit REPL console?

In a running REPL, you can exit it by using the key combination Ctrl + C , and keying it in twice.


1 Answers

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
...
like image 80
0__ Avatar answered Sep 30 '22 12:09

0__