summaryrefslogtreecommitdiffstats
path: root/vendor/clue/term-react
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-13 11:31:45 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-13 11:31:45 +0000
commit4e393913a4b1f06509da4341f0f58a41adac9117 (patch)
tree9c27e3eb77d109dff5fd031502311c5616adab04 /vendor/clue/term-react
parentInitial commit. (diff)
downloadicinga-php-thirdparty-4e393913a4b1f06509da4341f0f58a41adac9117.tar.xz
icinga-php-thirdparty-4e393913a4b1f06509da4341f0f58a41adac9117.zip
Adding upstream version 0.12.1+ds.upstream/0.12.1+dsupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/clue/term-react')
-rw-r--r--vendor/clue/term-react/CHANGELOG.md63
-rw-r--r--vendor/clue/term-react/LICENSE21
-rw-r--r--vendor/clue/term-react/README.md171
-rw-r--r--vendor/clue/term-react/composer.json27
-rw-r--r--vendor/clue/term-react/src/ControlCodeParser.php223
5 files changed, 505 insertions, 0 deletions
diff --git a/vendor/clue/term-react/CHANGELOG.md b/vendor/clue/term-react/CHANGELOG.md
new file mode 100644
index 0000000..b3d521d
--- /dev/null
+++ b/vendor/clue/term-react/CHANGELOG.md
@@ -0,0 +1,63 @@
+# Changelog
+
+## 1.3.0 (2020-11-06)
+
+* Improve test suite and add `.gitattributes` to exclude dev files from export.
+ Prepare PHP 8 support, update to PHPUnit 9 and simplify test matrix.
+ (#29 and #30 by @SimonFrings)
+
+## 1.2.0 (2018-07-09)
+
+* Feature: Forward compatiblity with EventLoop v0.5 and upcoming v1.0.
+ (#28 by @clue)
+
+* Improve test suite by updating Travis config to test against legacy PHP 5.3 through PHP 7.2.
+ (#27 by @clue)
+
+* Update project homepage.
+ (#26 by @clue)
+
+## 1.1.0 (2017-07-06)
+
+* Feature: Forward compatibility with Stream v1.0 and v0.7 (while keeping BC)
+ (#22 by @Yoshi2889 and #23 by @WyriHaximus)
+
+* Improve test suite by fixing HHVM builds and ignoring future errors
+ (#24 by @clue)
+
+## 1.0.0 (2017-04-06)
+
+* First stable release, now following SemVer
+
+ > Contains no other changes, so it's actually fully compatible with the v0.1 releases.
+
+## 0.1.3 (2017-04-06)
+
+* Feature: Forward compatibility with Stream v0.6 and v0.5 (while keeping BC)
+ (#18 and #20 by @clue)
+
+* Improve test suite by adding PHPUnit to require-dev
+ (#19 by @clue)
+
+## 0.1.2 (2016-06-14)
+
+* Fix: Fix processing events when input writes during data event
+ (#15 by @clue)
+
+* Fix: Stop emitting events when closing stream during event handler
+ (#16 by @clue)
+
+* Fix: Remove all event listeners when either stream closes
+ (#17 by @clue)
+
+## 0.1.1 (2016-06-13)
+
+* Fix: Continue parsing after a `c0` code in the middle of a stream
+ (#13 by @clue)
+
+* Add more examples
+ (#14 by @clue)
+
+## 0.1.0 (2016-06-03)
+
+* First tagged release
diff --git a/vendor/clue/term-react/LICENSE b/vendor/clue/term-react/LICENSE
new file mode 100644
index 0000000..7baae8e
--- /dev/null
+++ b/vendor/clue/term-react/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2016 Christian Lück
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is furnished
+to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/vendor/clue/term-react/README.md b/vendor/clue/term-react/README.md
new file mode 100644
index 0000000..1768474
--- /dev/null
+++ b/vendor/clue/term-react/README.md
@@ -0,0 +1,171 @@
+# clue/reactphp-term [![Build Status](https://travis-ci.org/clue/reactphp-term.svg?branch=master)](https://travis-ci.org/clue/reactphp-term)
+
+Streaming terminal emulator, built on top of [ReactPHP](https://reactphp.org/).
+
+**Table of Contents**
+
+* [Support us](#support-us)
+* [Usage](#usage)
+ * [ControlCodeParser](#controlcodeparser)
+* [Install](#install)
+* [Tests](#tests)
+* [License](#license)
+* [More](#more)
+
+## Support us
+
+We invest a lot of time developing, maintaining and updating our awesome
+open-source projects. You can help us sustain this high-quality of our work by
+[becoming a sponsor on GitHub](https://github.com/sponsors/clue). Sponsors get
+numerous benefits in return, see our [sponsoring page](https://github.com/sponsors/clue)
+for details.
+
+Let's take these projects to the next level together! 🚀
+
+## Usage
+
+### ControlCodeParser
+
+The `ControlCodeParser(ReadableStreamInterface $input)` class can be used to
+parse any control code byte sequences (ANSI / VT100) when reading from an input stream and it
+only returns its plain data stream.
+It wraps a given `ReadableStreamInterface` and exposes its plain data through
+the same interface.
+
+```php
+$stdin = new ReadableResourceStream(STDIN, $loop);
+
+$stream = new ControlCodeParser($stdin);
+
+$stream->on('data', function ($chunk) {
+ var_dump($chunk);
+});
+```
+
+As such, you can be sure the resulting `data` events never include any control
+code byte sequences and it can be processed like a normal plain data stream.
+
+React's streams emit chunks of data strings and make no assumption about any
+byte sequences.
+These chunks do not necessarily represent complete control code byte sequences,
+as a sequence may be broken up into multiple chunks.
+This class reassembles these sequences by buffering incomplete ones.
+
+The following [C1 control codes](https://en.wikipedia.org/wiki/C0_and_C1_control_codes#C1_set)
+are supported as defined in [ISO/IEC 2022](https://en.wikipedia.org/wiki/ISO/IEC_2022):
+
+* [CSI (Control Sequence Introducer)](https://en.wikipedia.org/wiki/ANSI_escape_code#CSI_codes)
+ is one of the most common forms of control code sequences.
+ For example, CSI is used to print colored console output, also known as
+ "ANSI color codes" or the more technical term
+ [SGR (Select Graphic Rendition)](https://en.wikipedia.org/wiki/ANSI_escape_code#graphics).
+ CSI codes also appear on `STDIN`, for example when the user hits special keys,
+ such as the cursor, `HOME`, `END` etc. keys.
+
+* OSC (Operating System Command)
+ is another common form of control code sequences.
+ For example, OSC is used to change the window title or window icon.
+
+* APC (Application Program-Control)
+
+* DPS (Device-Control string)
+
+* PM (Privacy Message)
+
+Each code sequence gets emitted with a dedicated event with its raw byte sequence:
+
+```php
+$stream->on('csi', function ($sequence) {
+ if ($sequence === "\x1B[A") {
+ echo 'cursor UP pressed';
+ } else if ($sequence === "\x1B[B") {
+ echo 'cursor DOWN pressed';
+ }
+});
+
+$stream->on('osc', function ($sequence) { … });
+$stream->on('apc', function ($sequence) { … });
+$stream->on('dps', function ($sequence) { … });
+$stream->on('pm', function ($sequence) { … });
+```
+
+Other lesser known [C1 control codes](https://en.wikipedia.org/wiki/C0_and_C1_control_codes#C1_set)
+not listed above are supported by just emitting their 2-byte sequence.
+Each generic C1 code gets emitted as an `c1` event with its raw 2-byte sequence:
+
+```php
+$stream->on('c1', function ($sequence) { … });
+```
+
+All other [C0 control codes](https://en.wikipedia.org/wiki/C0_and_C1_control_codes#C0_.28ASCII_and_derivatives.29),
+also known as [ASCII control codes](https://en.wikipedia.org/wiki/ASCII#ASCII_control_code_chart),
+are supported by just emitting their single-byte value.
+Each generic C0 code gets emitted as an `c0` event with its raw single-byte value:
+
+```php
+$stream->on('c0', function ($code) {
+ if ($code === "\n") {
+ echo 'ENTER pressed';
+ }
+});
+```
+
+## Install
+
+The recommended way to install this library is [through Composer](https://getcomposer.org).
+[New to Composer?](https://getcomposer.org/doc/00-intro.md)
+
+This project follows [SemVer](https://semver.org/).
+This will install the latest supported version:
+
+```bash
+$ composer require clue/term-react:^1.3
+
+```
+
+See also the [CHANGELOG](CHANGELOG.md) for details about version upgrades.
+
+This project aims to run on any platform and thus does not require any PHP
+extensions and supports running on legacy PHP 5.3 through current PHP 7+ and
+HHVM.
+It's *highly recommended to use PHP 7+* for this project.
+
+## Tests
+
+To run the test suite, you first need to clone this repo and then install all
+dependencies [through Composer](https://getcomposer.org):
+
+```bash
+$ composer install
+```
+
+To run the test suite, go to the project root and run:
+
+```bash
+$ php vendor/bin/phpunit
+```
+
+## License
+
+This project is released under the permissive [MIT license](LICENSE).
+
+> Did you know that I offer custom development services and issuing invoices for
+ sponsorships of releases and for contributions? Contact me (@clue) for details.
+
+## More
+
+* If you want to learn more about processing streams of data, refer to the documentation of
+ the underlying [react/stream](https://github.com/reactphp/stream) component.
+
+* If you want to process UTF-8 encoded console input, you may
+ want to use [clue/reactphp-utf8](https://github.com/clue/reactphp-utf8) on the resulting
+ plain data stream.
+
+* If you want to to display or inspect the control codes, you may
+ want to use either [clue/hexdump](https://github.com/clue/php-hexdump) or
+ [clue/caret-notation](https://github.com/clue/php-caret-notation) on the emitted
+ control byte sequences.
+
+* If you want to process standard input and output (STDIN and STDOUT) from a TTY, you may
+ want to use [clue/reactphp-stdio](https://github.com/clue/reactphp-stdio) instead of
+ using this low-level library.
diff --git a/vendor/clue/term-react/composer.json b/vendor/clue/term-react/composer.json
new file mode 100644
index 0000000..d1b3ce5
--- /dev/null
+++ b/vendor/clue/term-react/composer.json
@@ -0,0 +1,27 @@
+{
+ "name": "clue/term-react",
+ "description": "Streaming terminal emulator, built on top of ReactPHP.",
+ "keywords": ["terminal", "control codes", "xterm", "ANSI", "ASCII", "VT100", "csi", "osc", "apc", "dps", "pm", "C1", "C0", "streaming", "ReactPHP"],
+ "homepage": "https://github.com/clue/reactphp-term",
+ "license": "MIT",
+ "authors": [
+ {
+ "name": "Christian Lück",
+ "email": "christian@clue.engineering"
+ }
+ ],
+ "autoload": {
+ "psr-4": { "Clue\\React\\Term\\": "src/" }
+ },
+ "autoload-dev": {
+ "psr-4": { "Clue\\Tests\\React\\Term\\": "tests/" }
+ },
+ "require": {
+ "php": ">=5.3",
+ "react/stream": "^1.0 || ^0.7"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^9.3 || ^5.7 || ^4.8",
+ "react/event-loop": "^1.0 || ^0.5 || ^0.4 || ^0.3"
+ }
+}
diff --git a/vendor/clue/term-react/src/ControlCodeParser.php b/vendor/clue/term-react/src/ControlCodeParser.php
new file mode 100644
index 0000000..abbe400
--- /dev/null
+++ b/vendor/clue/term-react/src/ControlCodeParser.php
@@ -0,0 +1,223 @@
+<?php
+
+namespace Clue\React\Term;
+
+use Evenement\EventEmitter;
+use React\Stream\ReadableStreamInterface;
+use React\Stream\WritableStreamInterface;
+use React\Stream\Util;
+
+class ControlCodeParser extends EventEmitter implements ReadableStreamInterface
+{
+ private $input;
+ private $closed = false;
+ private $buffer = '';
+
+ /**
+ * we know about the following C1 types (7 bit only)
+ *
+ * followed by "[" means it's CSI (Control Sequence Introducer)
+ * followed by "]" means it's OSC (Operating System Controls)
+ * followed by "_" means it's APC (Application Program-Control)
+ * followed by "P" means it's DPS (Device-Control string)
+ * followed by "^" means it's PM (Privacy Message)
+ *
+ * Each of these will be parsed until the sequence ends and then emitted
+ * under their respective name.
+ *
+ * All other C1 types will be emitted under the "c1" name without any
+ * further processing.
+ *
+ * C1 types in 8 bit are currently not supported, as they require special
+ * care with regards to whether UTF-8 mode is enabled. So far this has
+ * turned out to be a non-issue because most terminal emulators *accept*
+ * boths formats, but usually *send* in 7 bit mode exclusively.
+ */
+ private $types = array(
+ '[' => 'csi',
+ ']' => 'osc',
+ '_' => 'apc',
+ 'P' => 'dps',
+ '^' => 'pm',
+ );
+
+ public function __construct(ReadableStreamInterface $input)
+ {
+ $this->input = $input;
+
+ if (!$this->input->isReadable()) {
+ return $this->close();
+ }
+
+ $this->input->on('data', array($this, 'handleData'));
+ $this->input->on('end', array($this, 'handleEnd'));
+ $this->input->on('error', array($this, 'handleError'));
+ $this->input->on('close', array($this, 'close'));
+ }
+
+ public function isReadable()
+ {
+ return !$this->closed && $this->input->isReadable();
+ }
+
+ public function pause()
+ {
+ $this->input->pause();
+ }
+
+ public function resume()
+ {
+ $this->input->resume();
+ }
+
+ public function pipe(WritableStreamInterface $dest, array $options = array())
+ {
+ Util::pipe($this, $dest, $options);
+
+ return $dest;
+ }
+
+ public function close()
+ {
+ if ($this->closed) {
+ return;
+ }
+
+ $this->closed = true;
+ $this->buffer = '';
+
+ $this->input->close();
+
+ $this->emit('close');
+ $this->removeAllListeners();
+ }
+
+ /** @internal */
+ public function handleData($data)
+ {
+ $this->buffer .= $data;
+
+ while ($this->buffer !== '') {
+ // search for first control character (C0 and DEL)
+ $c0 = false;
+ for ($i = 0; isset($this->buffer[$i]); ++$i) {
+ $code = ord($this->buffer[$i]);
+ if ($code < 0x20 || $code === 0x7F) {
+ $c0 = $i;
+ break;
+ }
+ }
+
+ // no C0 found, emit whole buffer as data
+ if ($c0 === false) {
+ $data = $this->buffer;
+ $this->buffer = '';
+
+ $this->emit('data', array($data));
+ return;
+ }
+
+ // C0 found somewhere inbetween, emit everything before C0 as data
+ if ($c0 !== 0) {
+ $data = substr($this->buffer, 0, $c0);
+ $this->buffer = substr($this->buffer, $c0);
+
+ $this->emit('data', array($data));
+ continue;
+ }
+
+ // C0 is now at start of buffer
+ // check if this is a normal C0 code or an ESC (\x1B = \033)
+ // normal C0 will be emitted, ESC will be parsed further
+ if ($this->buffer[0] !== "\x1B") {
+ $data = $this->buffer[0];
+ $this->buffer = (string)substr($this->buffer, 1);
+
+ $this->emit('c0', array($data));
+ continue;
+ }
+
+ // check following byte to determine type
+ if (!isset($this->buffer[1])) {
+ // type currently unknown, wait for next data chunk
+ break;
+ }
+
+ // if this is an unknown type, just emit as "c1" without further parsing
+ if (!isset($this->types[$this->buffer[1]])) {
+ $data = substr($this->buffer, 0, 2);
+ $this->buffer = (string)substr($this->buffer, 2);
+
+ $this->emit('c1', array($data));
+ continue;
+ }
+
+ // this is known type, check for the sequence end
+ $type = $this->types[$this->buffer[1]];
+ $found = false;
+
+ if ($type === 'csi') {
+ // CSI is now at the start of the buffer, search final character
+ for ($i = 2; isset($this->buffer[$i]); ++$i) {
+ $code = ord($this->buffer[$i]);
+
+ // final character between \x40-\x7E
+ if ($code >= 64 && $code <= 126) {
+ $data = substr($this->buffer, 0, $i + 1);
+ $this->buffer = (string)substr($this->buffer, $i + 1);
+
+ $this->emit($type, array($data));
+ $found = true;
+ break;
+ }
+ }
+ } else {
+ // all other types are terminated by ST
+ // only OSC can also be terminted by BEL (whichever comes first)
+ $st = strpos($this->buffer, "\x1B\\");
+ $bel = ($type === 'osc') ? strpos($this->buffer, "\x07") : false;
+
+ if ($st !== false && ($bel === false || $bel > $st)) {
+ // ST comes before BEL or no BEL found
+ $data = substr($this->buffer, 0, $st + 2);
+ $this->buffer = (string)substr($this->buffer, $st + 2);
+
+ $this->emit($type, array($data));
+ $found = true;
+ } elseif ($bel !== false) {
+ // BEL comes before ST or no ST found
+ $data = substr($this->buffer, 0, $bel + 1);
+ $this->buffer = (string)substr($this->buffer, $bel + 1);
+
+ $this->emit($type, array($data));
+ $found = true;
+ }
+ }
+
+ // no final character found => wait for next data chunk
+ if (!$found) {
+ break;
+ }
+ }
+ }
+
+ /** @internal */
+ public function handleEnd()
+ {
+ if (!$this->closed) {
+ if ($this->buffer === '') {
+ $this->emit('end');
+ } else {
+ $this->emit('error', array(new \RuntimeException('Stream ended with incomplete control code sequence in buffer')));
+ }
+ $this->close();
+ }
+ }
+
+ /** @internal */
+ public function handleError(\Exception $e)
+ {
+ $this->emit('error', array($e));
+ $this->close();
+ }
+}