diff --git a/CHANGELOG.md b/CHANGELOG.md index 98d380bc..e15215eb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,11 @@ # Changelog ## Unreleased -## Changed -- `Terminal.rawPrint` now takes a `CharSequence` instead of a `String` +### Changed +- `Terminal.rawPrint` now takes a `CharSequence` instead of a `String` [(#255)](https://github.com/ajalt/mordant/issues/255) + +### Fixed +- Fixed `Terminal.read*OrNull` throwing an exception on timeout on Windows. [(#256)](https://github.com/ajalt/mordant/issues/256) ## 3.0.1 ### Fixed diff --git a/mordant-jvm-ffm/src/jvmMain/kotlin/com/github/ajalt/mordant/terminal/terminalinterface/ffm/TerminalInterface.ffm.windows.kt b/mordant-jvm-ffm/src/jvmMain/kotlin/com/github/ajalt/mordant/terminal/terminalinterface/ffm/TerminalInterface.ffm.windows.kt index e49cd0cf..c2cf67fd 100644 --- a/mordant-jvm-ffm/src/jvmMain/kotlin/com/github/ajalt/mordant/terminal/terminalinterface/ffm/TerminalInterface.ffm.windows.kt +++ b/mordant-jvm-ffm/src/jvmMain/kotlin/com/github/ajalt/mordant/terminal/terminalinterface/ffm/TerminalInterface.ffm.windows.kt @@ -1,6 +1,7 @@ package com.github.ajalt.mordant.terminal.terminalinterface.ffm import com.github.ajalt.mordant.rendering.Size +import com.github.ajalt.mordant.terminal.TimeoutException import com.github.ajalt.mordant.terminal.terminalinterface.TerminalInterfaceWindows import java.lang.foreign.* @@ -279,7 +280,7 @@ internal class TerminalInterfaceFfmWindows : TerminalInterfaceWindows() { val stdin = stdinHandle val waitResult = kernel.WaitForSingleObject(stdin, dwMilliseconds) if (waitResult != 0) { - throw RuntimeException("Timeout reading from console input") + throw TimeoutException() } val inputEvents = arena.allocate(WinKernel32Library.INPUT_RECORD.Layout.layout, 1) val eventsReadSeg = arena.allocateInt() diff --git a/mordant/api/mordant.api b/mordant/api/mordant.api index db31c4c0..a6d5b9a4 100644 --- a/mordant/api/mordant.api +++ b/mordant/api/mordant.api @@ -1260,6 +1260,10 @@ public final class com/github/ajalt/mordant/terminal/TerminalRecorder : com/gith public final fun stdout ()Ljava/lang/String; } +public final class com/github/ajalt/mordant/terminal/TimeoutException : java/lang/RuntimeException { + public fun ()V +} + public final class com/github/ajalt/mordant/terminal/YesNoPrompt : com/github/ajalt/mordant/terminal/Prompt { public fun (Ljava/lang/String;Lcom/github/ajalt/mordant/terminal/Terminal;Ljava/lang/Boolean;ZZLjava/util/List;Ljava/lang/String;Ljava/lang/String;)V public synthetic fun (Ljava/lang/String;Lcom/github/ajalt/mordant/terminal/Terminal;Ljava/lang/Boolean;ZZLjava/util/List;Ljava/lang/String;Ljava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V diff --git a/mordant/src/commonMain/kotlin/com/github/ajalt/mordant/input/RawMode.kt b/mordant/src/commonMain/kotlin/com/github/ajalt/mordant/input/RawMode.kt index fb378089..df43b53e 100644 --- a/mordant/src/commonMain/kotlin/com/github/ajalt/mordant/input/RawMode.kt +++ b/mordant/src/commonMain/kotlin/com/github/ajalt/mordant/input/RawMode.kt @@ -1,6 +1,7 @@ package com.github.ajalt.mordant.input import com.github.ajalt.mordant.terminal.Terminal +import com.github.ajalt.mordant.terminal.TimeoutException import kotlin.time.Duration import kotlin.time.TimeSource @@ -102,11 +103,13 @@ class RawModeScope internal constructor( timeout: Duration, skip: (InputEvent) -> Boolean, ): InputEvent? { val t = TimeSource.Monotonic.markNow() + timeout - do { - val event = terminal.terminalInterface.readInputEvent(t, mouseTracking) ?: continue - if (event is MouseEvent && mouseTracking == MouseTracking.Off || skip(event)) continue - return event - } while (t.hasNotPassedNow()) + try { + do { + val event = terminal.terminalInterface.readInputEvent(t, mouseTracking) ?: continue + if (event is MouseEvent && mouseTracking == MouseTracking.Off || skip(event)) continue + return event + } while (t.hasNotPassedNow()) + } catch (_: TimeoutException) {} return null } diff --git a/mordant/src/commonMain/kotlin/com/github/ajalt/mordant/terminal/TerminalInterface.kt b/mordant/src/commonMain/kotlin/com/github/ajalt/mordant/terminal/TerminalInterface.kt index cab2c16a..3c1337ac 100644 --- a/mordant/src/commonMain/kotlin/com/github/ajalt/mordant/terminal/TerminalInterface.kt +++ b/mordant/src/commonMain/kotlin/com/github/ajalt/mordant/terminal/TerminalInterface.kt @@ -88,3 +88,5 @@ data class PrintRequest( */ val stderr: Boolean, ) + +class TimeoutException : RuntimeException("Timeout waiting for input")