diff --git a/amm/repl/src/main/scala/ammonite/repl/AmmoniteFrontEnd.scala b/amm/repl/src/main/scala/ammonite/repl/AmmoniteFrontEnd.scala index 0ef01dc5f..76abbcd37 100644 --- a/amm/repl/src/main/scala/ammonite/repl/AmmoniteFrontEnd.scala +++ b/amm/repl/src/main/scala/ammonite/repl/AmmoniteFrontEnd.scala @@ -50,7 +50,9 @@ case class AmmoniteFrontEnd(extraFilters: Filter = Filter.empty) extends FrontEn val autocompleteFilter: Filter = Filter.action(SpecialKeys.Tab){ case TermState(rest, b, c, _) => - val (newCursor, completions, details) = compilerComplete(c, b.mkString) + val (newCursor, completions, details) = TTY.withSttyOverride(TTY.restoreSigInt()) { + compilerComplete(c, b.mkString) + } val details2 = for (d <- details) yield { Highlighter.defaultHighlight( diff --git a/amm/repl/src/main/scala/ammonite/repl/Repl.scala b/amm/repl/src/main/scala/ammonite/repl/Repl.scala index b111bce5a..886a2cb81 100644 --- a/amm/repl/src/main/scala/ammonite/repl/Repl.scala +++ b/amm/repl/src/main/scala/ammonite/repl/Repl.scala @@ -173,6 +173,14 @@ class Repl(input: InputStream, case ex => Res.Exception(ex, "") } + _ <- Signaller("INT") { + // Put a fake `ThreadDeath` error in `lastException`, because `Thread#stop` + // raises an error with the stack trace of *this interrupt thread*, rather + // than the stack trace of *the mainThread* + lastException = new ThreadDeath() + lastException.setStackTrace(Repl.truncateStackTrace(interp.mainThread.getStackTrace)) + interp.mainThread.stop() + } (code, stmts) <- frontEnd().action( input, reader, @@ -186,14 +194,6 @@ class Repl(input: InputStream, history = history :+ code } ) - _ <- Signaller("INT") { - // Put a fake `ThreadDeath` error in `lastException`, because `Thread#stop` - // raises an error with the stack trace of *this interrupt thread*, rather - // than the stack trace of *the mainThread* - lastException = new ThreadDeath() - lastException.setStackTrace(Repl.truncateStackTrace(interp.mainThread.getStackTrace)) - interp.mainThread.stop() - } out <- interp.processLine(code, stmts, currentLine, false, () => currentLine += 1) } yield { printer.outStream.println() diff --git a/amm/repl/src/main/scala/ammonite/repl/Signaller.scala b/amm/repl/src/main/scala/ammonite/repl/Signaller.scala index fb45cc07b..a22dc144f 100644 --- a/amm/repl/src/main/scala/ammonite/repl/Signaller.scala +++ b/amm/repl/src/main/scala/ammonite/repl/Signaller.scala @@ -29,7 +29,8 @@ case class Signaller(sigStr: String)(f: => Unit) extends Scoped{ finally{ val head::tail = handlers(sig) handlers(sig) = tail - sun.misc.Signal.handle(sig, head) + val handlerToRegister = tail.headOption.getOrElse(sun.misc.SignalHandler.SIG_DFL) + sun.misc.Signal.handle(sig, handlerToRegister) } } } @@ -41,6 +42,6 @@ case class Signaller(sigStr: String)(f: => Unit) extends Scoped{ trait Scoped{ def apply[T](t: => T): T def foreach[T](t: Unit => T): T = apply(t(())) - def flatMap[T, M[_]](t: Unit => M[T]): M[T] = apply(t(())) + def flatMap[T](t: Unit => T): T = apply(t(())) def map[T](t: Unit => T): T = apply(t(())) } \ No newline at end of file diff --git a/terminal/src/main/scala/ammonite/terminal/Terminal.scala b/terminal/src/main/scala/ammonite/terminal/Terminal.scala index a609f5b22..639c89c20 100644 --- a/terminal/src/main/scala/ammonite/terminal/Terminal.scala +++ b/terminal/src/main/scala/ammonite/terminal/Terminal.scala @@ -36,20 +36,9 @@ object Terminal { filters: Filter, displayTransform: (Vector[Char], Int) => (fansi.Str, Int) = LineReader.noTransform) : Option[String] = { - - - val initialConfig = TTY.init() - try { + TTY.withSttyOverride(TTY.readLineStty()) { new LineReader(ConsoleDim.width(), prompt, reader, writer, filters, displayTransform) .readChar(TermState(LazyList.continually(reader.read()), Vector.empty, 0, ""), 0) - }finally{ - - // Don't close these! Closing these closes stdin/stdout, - // which seems to kill the entire program - - // reader.close() - // writer.close() - TTY.stty(initialConfig) } } } diff --git a/terminal/src/main/scala/ammonite/terminal/Utils.scala b/terminal/src/main/scala/ammonite/terminal/Utils.scala index ca5ab040b..0b0d23d27 100644 --- a/terminal/src/main/scala/ammonite/terminal/Utils.scala +++ b/terminal/src/main/scala/ammonite/terminal/Utils.scala @@ -93,17 +93,6 @@ object TTY{ import sys.process._ Seq("sh", "-c", s"$pathedTput $s 2> /dev/tty").!!.trim.toInt } - def init() = { - stty("-a") - - val initialConfig = stty("-g").trim - stty("-icanon min 1 -icrnl -inlcr -ixon") - sttyFailTolerant("dsusp undef") - stty("-echo") - stty("intr undef") - - initialConfig - } private def sttyCmd(s: String) = { import sys.process._ @@ -121,8 +110,25 @@ object TTY{ def sttyFailTolerant(s: String) = sttyCmd(s ++ " 2> /dev/null").! - def restore(initialConfig: String) = { - stty(initialConfig) + def withSttyOverride[A](setupStty: => Unit)(f: => A) = { + val initialConfig = stty("-g").trim + try { + setupStty + f + } finally { + stty(initialConfig) + } + } + + def readLineStty(): Unit = { + stty("-icanon min 1 -icrnl -inlcr -ixon") + sttyFailTolerant("dsusp undef") + stty("-echo") + stty("intr undef") + } + + def restoreSigInt(): Unit = { + stty("intr ^C") } }