Fix ctrl+c handling on windows

In windows, it is necessary for the console mode to include the
ENABLE_PROCESS_INPUT flag in order for ctrl+c to be treated as a signal
rather than a character. In jline 2, the ENABLE_PROCESS_INPUT flag was
preserved whenever the console mode was changed but in jline 3, it was
not. It is easy enough to manually set the flag after entering and
exiting raw mode and setting attributes (which are the apis that change
the console mode on windows).
This commit is contained in:
Ethan Atkins 2020-10-06 13:17:12 -07:00
parent 6865526d3d
commit 1892f04211
2 changed files with 10 additions and 1 deletions

View File

@ -23,6 +23,7 @@ import org.jline.utils.OSUtils
import scala.collection.JavaConverters._
import scala.util.Try
import java.util.concurrent.LinkedBlockingQueue
import org.fusesource.jansi.internal.WindowsSupport
private[sbt] object JLine3 {
private[util] val initialAttributes = new AtomicReference[Attributes]
@ -207,6 +208,12 @@ private[sbt] object JLine3 {
term.setAttributes(newAttr)
prvAttr
}
// We need to set the ENABLE_PROCESS_INPUT flag for ctrl+c to be treated as a signal in windows
// https://docs.microsoft.com/en-us/windows/console/setconsolemode
private[this] val ENABLE_PROCESS_INPUT = 1
private[util] def setEnableProcessInput(): Unit = if (Util.isWindows) {
WindowsSupport.setConsoleMode(WindowsSupport.getConsoleMode | ENABLE_PROCESS_INPUT)
}
private[util] def enterRawMode(term: JTerminal): Unit = {
val prevAttr = initialAttributes.get
val newAttr = new Attributes(prevAttr)
@ -215,13 +222,14 @@ private[sbt] object JLine3 {
newAttr.setLocalFlags(EnumSet.of(LocalFlag.ICANON, LocalFlag.IEXTEN, LocalFlag.ECHO), false)
newAttr.setInputFlags(EnumSet.of(InputFlag.IXON, InputFlag.ICRNL, InputFlag.INLCR), false)
term.setAttributes(newAttr)
()
setEnableProcessInput()
}
private[util] def exitRawMode(term: JTerminal): Unit = {
val initAttr = initialAttributes.get
val newAttr = new Attributes(initAttr)
newAttr.setLocalFlags(EnumSet.of(LocalFlag.ICANON, LocalFlag.ECHO), true)
term.setAttributes(newAttr)
setEnableProcessInput()
}
private[util] def toMap(jattributes: Attributes): Map[String, String] = {
val result = new java.util.LinkedHashMap[String, String]

View File

@ -814,6 +814,7 @@ object Terminal {
Try(JLine3.toMap(system.getAttributes)).getOrElse(Map.empty)
override private[sbt] def setAttributes(attributes: Map[String, String]): Unit = {
system.setAttributes(JLine3.attributesFromMap(attributes))
JLine3.setEnableProcessInput()
}
override private[sbt] def setSize(width: Int, height: Int): Unit =
system.setSize(new org.jline.terminal.Size(width, height))