2012-08-08 18 views
9

¿Hay una tecla de acceso rápido para detener/salir del Scala REPL?Tecla de acceso rápido para detener REPL?

Ejemplo: inicio el Scala REPL desde SBT con el comando console, luego hago algo estúpido como un bucle sin fin y quiero finalizar el REPL sin cerrar el shell en absoluto. Algo así como Ctrl +C,Ctrl + D o Ctrl +Z (que todo no funcionan).

Actualización: SO utilizado: Windows 7 64 Bit.

Ctrl + D existe SBT y de la réplica, pero Ctrl + D no sale del REPL cuando estoy en un bucle sin fin como

while(true) prinln("test") 

¿Hay una manera de salir del ciclo sin fin con una tecla de acceso rápido sin cerrar el caparazón? ¿O esto no es posible porque el REPL no reaccionará a las teclas rápidas hasta que el ciclo haya terminado (lo que, por supuesto, no sucederá en este caso)?

+0

hm ¿qué sistema operativo está utilizando? Porque ctrl + c parece ser el truco para mí (bajo MacOS 10.6) –

+0

¿Estás iniciando desde sbt, porque dices 'console'? –

+0

@MateuszDymczyk Ah, ya veo, esto parece ser un problema específico del sistema operativo. Yo uso Windows 7 64 Bit Edition. Ctrl + C no funciona para mí. –

Respuesta

2

Lo siguiente funciona con Scala 2.10.0-M6, pero en 2.9.2 probablemente pueda lograr algo similar usando :wrap en el modo de energía REPL.

asumir que el REPL se inicia desde SBT través sbt console — sin pérdida de generalidad (es posible que de otro modo sólo hay que poner la clase ReplUtil en el camino de la clase de la Scala). Supongamos que la siguiente clase está en la ruta de clases, p. su fuente es en 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>" 
    } 
    } 
} 

entonces la siguiente activará el REPL semi-asíncrono:

$ 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 
... 
+0

¿Cómo puede una Q ser +6 mientras que A es +0? De todos modos, dado el fallecimiento de: wrap, REPL necesita plantillas genéricas, con funciones integradas para "temporizado", "interrumpible", etc. –

0

relacionado con el tema es un útil Shift + D clave de enlace para salir no finalizando las evaluaciones de un programa cuando se encuentra dentro de una hoja de trabajo de scala de eclipse.

Cuestiones relacionadas