2012-08-08 24 views
9

Czy istnieje skrót klawiszowy do zatrzymania/wyjścia z REPL Scala?Skrót do zatrzymania REPL?

Przykład: Uruchamiam Scala REPL z SBT za pomocą polecenia console, następnie robię coś głupiego jak nieskończona pętla i chcę zakończyć REPL bez zamykania powłoki. Coś takiego Ctrl + C, Ctrl + D lub Ctrl + Z (które nie działają).

Aktualizacja: Używany system operacyjny: Windows 7 64 Bit.

Ctrl + D istnieje SBT i rEPL, ale Ctrl + D NIE opuścić rEPL kiedy jestem w nieskończonej pętli jak

while(true) prinln("test") 

Czy istnieje sposób, aby wydostać się z pętli bez końca za pomocą skrótu bez zamykania powłoki? Czy nie jest to możliwe, ponieważ REPL nie reaguje na skróty klawiszowe dopóki pętla nie zostanie zakończona (co oczywiście nie stanie się w tym przypadku)?

+0

hm z jakiego systemu operacyjnego korzystasz? Ponieważ ctrl + c wydaje mi się odpowiednią sztuczką (pod MacOS 10.6) –

+0

uruchamiasz z sbt, ponieważ mówisz 'console'? –

+0

@MateuszDymczyk O, widzę, to wydaje się być problemem specyficznym dla OS. Używam Windows 7 64 Bit Edition. Ctrl + C nie działa dla mnie. –

Odpowiedz

2

Poniższe działa z Scala 2.10.0-M6, ale w 2.9.2 prawdopodobnie można uzyskać coś podobnego przy użyciu trybu mocy REPL w trybie REPL :wrap.

Załóżmy, że REPL jest uruchamiany z sbt przez sbt console — bez utraty ogólności (możesz po prostu po prostu umieścić klasę ReplUtil na ścieżce klasy scala). Załóżmy, że na ścieżce klasy znajduje się następująca klasa, np. jego źródłem jest 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>" 
    } 
    } 
} 

Następnie dodaje się uaktywni semi-asynchroniczny 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 
... 
+0

Jak Q może być +6, gdy A jest równe +0? W każdym razie, biorąc pod uwagę koniec: wrap, REPL potrzebuje ogólnego szablonu, z wbudowanymi "timed", "interruptible" itd. –

0

związane z tematem jest użytecznym SHIFT + D klucz wiążące dla wychodzenia non kończenie ocen programu podczas pracy w arkuszu kalkulacyjnym eclipse scala.