@@ -159,6 +159,10 @@ class ReplDriver(settings: Array[String],
159159 s """ Welcome to Scala $simpleVersionString ( $javaVersion, Java $javaVmName).
160160 |Type in expressions for evaluation. Or try :help. """ .stripMargin)
161161
162+ // Track the time of last Ctrl-C
163+ var lastCtrlCTime : Long = 0L
164+ val ctrlCWindowMs = 1000L // 1 second window for double Ctrl-C
165+
162166 /** Blockingly read a line, getting back a parse result */
163167 def readLine ()(using state : State ): ParseResult = {
164168 given Context = state.context
@@ -195,16 +199,44 @@ class ReplDriver(settings: Array[String],
195199 val line = terminal.readLine(completer)
196200 ParseResult (line)
197201 } catch {
198- case _ : EndOfFileException |
199- _ : UserInterruptException => // Ctrl+D or Ctrl+C
202+ case _ : EndOfFileException => // Ctrl+D
200203 Quit
204+ case _ : UserInterruptException => // Ctrl+C at prompt - clear and continue
205+ SigKill
201206 }
202207 }
203208
204209 @ tailrec def loop (using state : State )(): State = {
205210 val res = readLine()
206211 if (res == Quit ) state
207- else loop(using interpret(res))()
212+ else if (res == SigKill ) {
213+ // Ctrl-C pressed at prompt - just continue with same state (line is cleared by JLine)
214+ loop(using state)()
215+ } else {
216+ // Set up interrupt handler for command execution
217+ val thread = Thread .currentThread()
218+ val signalHandler = terminal.handle(
219+ org.jline.terminal.Terminal .Signal .INT ,
220+ (sig : org.jline.terminal.Terminal .Signal ) => {
221+ val now = System .currentTimeMillis()
222+ if (now - lastCtrlCTime < ctrlCWindowMs) {
223+ // Second Ctrl-C within window - interrupt the thread
224+ out.println(" \n Terminating REPL..." )
225+ thread.interrupt()
226+ System .exit(130 ) // Standard exit code for SIGINT
227+ } else {
228+ // First Ctrl-C - warn user
229+ lastCtrlCTime = now
230+ out.println(" \n Press Ctrl-C again to terminate the process" )
231+ }
232+ }
233+ )
234+
235+ val newState = interpret(res)
236+ // Restore previous handler
237+ terminal.handle(org.jline.terminal.Terminal .Signal .INT , signalHandler)
238+ loop(using newState)()
239+ }
208240 }
209241
210242 try runBody { loop() }
0 commit comments