@@ -175,6 +175,10 @@ class ReplDriver(settings: Array[String],
175175 s """ Welcome to Scala $simpleVersionString ( $javaVersion, Java $javaVmName).
176176 |Type in expressions for evaluation. Or try :help. """ .stripMargin)
177177
178+ // Track the time of last Ctrl-C
179+ var lastCtrlCTime : Long = 0L
180+ val ctrlCWindowMs = 1000L // 1 second window for double Ctrl-C
181+
178182 /** Blockingly read a line, getting back a parse result */
179183 def readLine ()(using state : State ): ParseResult = {
180184 given Context = state.context
@@ -211,16 +215,44 @@ class ReplDriver(settings: Array[String],
211215 val line = terminal.readLine(completer)
212216 ParseResult (line)
213217 } catch {
214- case _ : EndOfFileException |
215- _ : UserInterruptException => // Ctrl+D or Ctrl+C
218+ case _ : EndOfFileException => // Ctrl+D
216219 Quit
220+ case _ : UserInterruptException => // Ctrl+C at prompt - clear and continue
221+ SigKill
217222 }
218223 }
219224
220225 @ tailrec def loop (using state : State )(): State = {
221226 val res = readLine()
222227 if (res == Quit ) state
223- else loop(using interpret(res))()
228+ else if (res == SigKill ) {
229+ // Ctrl-C pressed at prompt - just continue with same state (line is cleared by JLine)
230+ loop(using state)()
231+ } else {
232+ // Set up interrupt handler for command execution
233+ val thread = Thread .currentThread()
234+ val signalHandler = terminal.handle(
235+ org.jline.terminal.Terminal .Signal .INT ,
236+ (sig : org.jline.terminal.Terminal .Signal ) => {
237+ val now = System .currentTimeMillis()
238+ if (now - lastCtrlCTime < ctrlCWindowMs) {
239+ // Second Ctrl-C within window - interrupt the thread
240+ out.println(" \n Terminating REPL..." )
241+ thread.interrupt()
242+ System .exit(130 ) // Standard exit code for SIGINT
243+ } else {
244+ // First Ctrl-C - warn user
245+ lastCtrlCTime = now
246+ out.println(" \n Press Ctrl-C again to terminate the process" )
247+ }
248+ }
249+ )
250+
251+ val newState = interpret(res)
252+ // Restore previous handler
253+ terminal.handle(org.jline.terminal.Terminal .Signal .INT , signalHandler)
254+ loop(using newState)()
255+ }
224256 }
225257
226258 try runBody { loop() }
0 commit comments