From 8e8b6786599f2939ff68d9a53d67571360792c74 Mon Sep 17 00:00:00 2001 From: AJ Alt Date: Mon, 2 Sep 2024 18:27:12 +0000 Subject: [PATCH] In raw mode, return Escape immediately. (#224) --- CHANGELOG.md | 1 + docs/input.md | 6 +----- .../terminal/terminalinterface/PosixEventParser.kt | 10 +++++++--- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d7350b70..b0a9dd1a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ - **Breaking Change** Moved `Terminal.info.width` and `height` to `Terminal.size.width` and `height`. - **Breaking Change** `TerminalInterface.info` is now a method with parameters instead of a property. - **Breaking Change** Moved `Markdown` widget to separate `mordant-markdown` module, which is not included by default. If you use markdown rendering, you need to add that module to you dependencies. +- In raw mode on POSIX systems, pressing the escape key once will now immediately return an `Escape` event. [(#193)](https://github.com/ajalt/mordant/issues/193) ### Removed - Removed constructor overloads for `Terminal`. There is now one constructor with all default parameters. diff --git a/docs/input.md b/docs/input.md index 74001ef1..d0bbc656 100644 --- a/docs/input.md +++ b/docs/input.md @@ -159,11 +159,7 @@ app and operating system. Some things to keep in mind: other than Windows. - Some key combinations aren't reported because they're intercepted by the terminal app to perform actions like switching tabs or closing the window. -- On Linux and macOS, the Escape key isn't reported as a key press; instead, it begins a "VTI escape - sequence" that the terminal uses to report key presses. For example if you press `Escape`, then `[`, - then `d`, the terminal will report that as the left arrow key being pressed. It's up to you whether - you consider this a feature or a limitation. -- Raw mode is supported on JS or wasmJS targets on Node.js only. You can also use Node.js's +- For JS or wasmJS targets, raw mode is supported on Node.js only. You can also use Node.js's `readline` module to read input with callbacks instead of blocking, or in the browser you can use the `keydown` and `mousedown` events. diff --git a/mordant/src/commonMain/kotlin/com/github/ajalt/mordant/terminal/terminalinterface/PosixEventParser.kt b/mordant/src/commonMain/kotlin/com/github/ajalt/mordant/terminal/terminalinterface/PosixEventParser.kt index 5bcd1f2c..190e6b84 100644 --- a/mordant/src/commonMain/kotlin/com/github/ajalt/mordant/terminal/terminalinterface/PosixEventParser.kt +++ b/mordant/src/commonMain/kotlin/com/github/ajalt/mordant/terminal/terminalinterface/PosixEventParser.kt @@ -5,6 +5,7 @@ import com.github.ajalt.mordant.input.KeyboardEvent import com.github.ajalt.mordant.input.MouseEvent import com.github.ajalt.mordant.internal.codepointToString import com.github.ajalt.mordant.internal.readBytesAsUtf8 +import kotlin.time.Duration import kotlin.time.Duration.Companion.milliseconds import kotlin.time.TimeMark import kotlin.time.TimeSource @@ -36,8 +37,8 @@ internal class PosixEventParser( val s = StringBuilder() var ch: Char - fun read(): Char? { - ch = readRawByte(timeout)?.toChar() ?: return null + fun read(t:TimeMark = timeout): Char? { + ch = readRawByte(t)?.toChar() ?: return null s.append(ch) return ch } @@ -51,7 +52,10 @@ internal class PosixEventParser( if (ch == ESC) { escaped = true - read() ?: return KeyboardEvent("Escape") + // If there's nothing else in the buffer, return "Escape" immediately. This means that + // you can't manually type in escape sequences, but that's a pretty rare use case + // compared to just pressing escape. + read(TimeSource.Monotonic.markNow() + 5.milliseconds) ?: return KeyboardEvent("Escape") if (ch == ESC) { return KeyboardEvent("Escape") }