From e3ec4c01071eb2eb3864e1f9eca998035c92def3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20L=C3=BCck?= Date: Thu, 2 Nov 2017 11:38:25 +0100 Subject: [PATCH] Optionally use `ext-readline` to enable raw input mode if available --- README.md | 7 +++++++ src/Stdin.php | 20 +++++++++++++++++++- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 196ee6b..a39476f 100644 --- a/README.md +++ b/README.md @@ -567,6 +567,13 @@ If this extension is missing, then this library will use a slighty slower Regex work-around that should otherwise work equally well. Installing `ext-mbstring` is highly recommended. +Internally, it will use the `ext-readline` to enable raw terminal input mode. +If this extension is missing, then this library will manually set the required +TTY settings on start and will try to restore previous settings on exit. +Input line editing is handled entirely within this library and does not rely on +`ext-readline`. +Installing `ext-readline` is entirely optional. + Note that *Microsoft Windows is not supported*. Due to platform inconsistencies, PHP does not provide support for reading from standard console input without blocking. diff --git a/src/Stdin.php b/src/Stdin.php index c42bdfc..b1301cf 100644 --- a/src/Stdin.php +++ b/src/Stdin.php @@ -10,6 +10,10 @@ class Stdin extends Stream { private $oldMode = null; + /** + * @param LoopInterface $loop + * @codeCoverageIgnore this is covered by functional tests with/without ext-readline + */ public function __construct(LoopInterface $loop) { // STDIN not defined ("php -a") or already closed (`fclose(STDIN)`) @@ -26,6 +30,14 @@ public function __construct(LoopInterface $loop) return $this->close(); } + if (function_exists('readline_callback_handler_install')) { + // Prefer `ext-readline` to install dummy handler to turn on raw input mode. + // We will nevery actually feed the readline handler and instead + // handle all input in our `Readline` implementation. + readline_callback_handler_install('', function () { }); + return; + } + if ($this->isTty()) { $this->oldMode = shell_exec('stty -g'); @@ -49,9 +61,15 @@ public function __destruct() $this->restore(); } + /** + * @codeCoverageIgnore this is covered by functional tests with/without ext-readline + */ private function restore() { - if ($this->oldMode !== null && $this->isTty()) { + if (function_exists('readline_callback_handler_remove')) { + // remove dummy readline handler to turn to default input mode + readline_callback_handler_remove(); + } elseif ($this->oldMode !== null && $this->isTty()) { // Reset stty so it behaves normally again shell_exec(sprintf('stty %s', $this->oldMode)); $this->oldMode = null;