diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-13 11:31:45 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-13 11:31:45 +0000 |
commit | 4e393913a4b1f06509da4341f0f58a41adac9117 (patch) | |
tree | 9c27e3eb77d109dff5fd031502311c5616adab04 /vendor/clue/term-react | |
parent | Initial commit. (diff) | |
download | icinga-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.md | 63 | ||||
-rw-r--r-- | vendor/clue/term-react/LICENSE | 21 | ||||
-rw-r--r-- | vendor/clue/term-react/README.md | 171 | ||||
-rw-r--r-- | vendor/clue/term-react/composer.json | 27 | ||||
-rw-r--r-- | vendor/clue/term-react/src/ControlCodeParser.php | 223 |
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 [](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(); + } +} |