Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions compiler/src/dotty/tools/repl/JLineTerminal.scala
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,10 @@ class JLineTerminal extends java.io.Closeable {

def close(): Unit = terminal.close()

/** Register a signal handler and return the previous handler */
def handle(signal: org.jline.terminal.Terminal.Signal, handler: org.jline.terminal.Terminal.SignalHandler): org.jline.terminal.Terminal.SignalHandler =
terminal.handle(signal, handler)

/** Provide syntax highlighting */
private class Highlighter(using Context) extends reader.Highlighter {
def highlight(reader: LineReader, buffer: String): AttributedString = {
Expand Down
34 changes: 31 additions & 3 deletions compiler/src/dotty/tools/repl/ReplDriver.scala
Original file line number Diff line number Diff line change
Expand Up @@ -211,16 +211,44 @@ class ReplDriver(settings: Array[String],
val line = terminal.readLine(completer)
ParseResult(line)
} catch {
case _: EndOfFileException |
_: UserInterruptException => // Ctrl+D or Ctrl+C
case _: EndOfFileException => // Ctrl+D
Quit
case _: UserInterruptException => // Ctrl+C at prompt - clear and continue
SigKill
}
}

@tailrec def loop(using state: State)(): State = {

val res = readLine()
if (res == Quit) state
else loop(using interpret(res))()
// Ctrl-C pressed at prompt - just continue with same state (line is cleared by JLine)
else if (res == SigKill) loop(using state)()
else {
// Set up interrupt handler for command execution
var firstCtrlCEntered = false
val thread = Thread.currentThread()
val previousSignalHandler = terminal.handle(
org.jline.terminal.Terminal.Signal.INT,
(sig: org.jline.terminal.Terminal.Signal) => {
if (!firstCtrlCEntered) {
firstCtrlCEntered = true
thread.interrupt()
out.println("\nInterrupting running thread, Ctrl-C again to terminate the REPL Process")
}else {
out.println("\nTerminating REPL Process...")
System.exit(130) // Standard exit code for SIGINT
}
}
)

val newState =
try interpret(res)
// Restore previous handler
finally terminal.handle(org.jline.terminal.Terminal.Signal.INT, previousSignalHandler)

loop(using newState)()
}
}

try runBody { loop() }
Expand Down
Loading