From eeff69a80c29ed242d37ba0f90f29a9435a6f846 Mon Sep 17 00:00:00 2001 From: Brian Greenacre Date: Fri, 12 Nov 2021 09:58:45 -0600 Subject: [PATCH 1/3] Add support for Single Shift 2 and Single Shift 3 sequences --- src/ControlCodeParser.php | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/ControlCodeParser.php b/src/ControlCodeParser.php index abbe400..a5fa2df 100644 --- a/src/ControlCodeParser.php +++ b/src/ControlCodeParser.php @@ -21,6 +21,8 @@ class ControlCodeParser extends EventEmitter implements ReadableStreamInterface * 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) + * followed by "N" means it's SS2 (Single Shift 2) + * followed by "O" means it's SS3 (Single Shift 3) * * Each of these will be parsed until the sequence ends and then emitted * under their respective name. @@ -39,6 +41,8 @@ class ControlCodeParser extends EventEmitter implements ReadableStreamInterface '_' => 'apc', 'P' => 'dps', '^' => 'pm', + 'N' => 'ss2', + 'O' => 'ss3', ); public function __construct(ReadableStreamInterface $input) @@ -171,6 +175,20 @@ public function handleData($data) break; } } + } else if ($type === 'ss2') { + // SS2 shift 2 bytes from buffer + $data = substr($this->buffer, 0, 2); + $this->buffer = (string) substr($this->buffer, 2); + + $this->emit($type, array($data)); + $found = true; + } else if ($type === 'ss3') { + // SS3 shift 3 bytes from buffer + $data = substr($this->buffer, 0, 3); + $this->buffer = (string) substr($this->buffer, 3); + + $this->emit($type, array($data)); + $found = true; } else { // all other types are terminated by ST // only OSC can also be terminted by BEL (whichever comes first) From 14c2dee712227526b9923da496c18411df4439a6 Mon Sep 17 00:00:00 2001 From: Brian Greenacre Date: Fri, 12 Nov 2021 13:43:46 -0600 Subject: [PATCH 2/3] Add new tests for ss2 and ss3 emits --- src/ControlCodeParser.php | 10 +--------- tests/ControlCodeParserTest.php | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 9 deletions(-) diff --git a/src/ControlCodeParser.php b/src/ControlCodeParser.php index a5fa2df..73f503c 100644 --- a/src/ControlCodeParser.php +++ b/src/ControlCodeParser.php @@ -175,15 +175,7 @@ public function handleData($data) break; } } - } else if ($type === 'ss2') { - // SS2 shift 2 bytes from buffer - $data = substr($this->buffer, 0, 2); - $this->buffer = (string) substr($this->buffer, 2); - - $this->emit($type, array($data)); - $found = true; - } else if ($type === 'ss3') { - // SS3 shift 3 bytes from buffer + } else if ($type === 'ss2' || $type === 'ss3') { $data = substr($this->buffer, 0, 3); $this->buffer = (string) substr($this->buffer, 3); diff --git a/tests/ControlCodeParserTest.php b/tests/ControlCodeParserTest.php index c94399e..ee08550 100644 --- a/tests/ControlCodeParserTest.php +++ b/tests/ControlCodeParserTest.php @@ -226,6 +226,38 @@ public function testDoesNotEmitDpsIfItDoesNotEndWithSt() $this->input->emit('data', array("\x1BPasd\x07")); } + public function testEmitsSs2AndData() + { + $this->parser->on('data', $this->expectCallableOnceWith('hello')); + $this->parser->on('ss2', $this->expectCallableOnceWith("\x1BNE")); + + $this->input->emit('data', array("\x1BNEhello")); + } + + public function testEmitsDataAndSs2() + { + $this->parser->on('data', $this->expectCallableOnceWith('hello')); + $this->parser->on('ss2', $this->expectCallableOnceWith("\x1BNE")); + + $this->input->emit('data', array("hello\x1BNE")); + } + + public function testEmitsSs3AndData() + { + $this->parser->on('data', $this->expectCallableOnceWith('hello')); + $this->parser->on('ss3', $this->expectCallableOnceWith("\x1BOP")); + + $this->input->emit('data', array("\x1BOPhello")); + } + + public function testEmitsDataAndSs3() + { + $this->parser->on('data', $this->expectCallableOnceWith('hello')); + $this->parser->on('ss3', $this->expectCallableOnceWith("\x1BOP")); + + $this->input->emit('data', array("hello\x1BOP")); + } + public function testEmitsUnknownC1AsOneChunk() { $this->parser->on('data', $this->expectCallableNever()); From 26669086b65c1021def5505787e90fd5e1d5870d Mon Sep 17 00:00:00 2001 From: Brian Greenacre Date: Fri, 12 Nov 2021 13:50:58 -0600 Subject: [PATCH 3/3] Update the readme to doc the ss2 and ss3 emits --- README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README.md b/README.md index ecb0a82..731b5a2 100644 --- a/README.md +++ b/README.md @@ -75,6 +75,12 @@ are supported as defined in [ISO/IEC 2022](https://en.wikipedia.org/wiki/ISO/IEC * PM (Privacy Message) +* SS2 (Single Shift 2) + this means select the following character form the G2 character set + +* SS3 (Single Shift 3) + this means select the following character form the G3 character set + Each code sequence gets emitted with a dedicated event with its raw byte sequence: ```php @@ -90,6 +96,8 @@ $stream->on('osc', function ($sequence) { … }); $stream->on('apc', function ($sequence) { … }); $stream->on('dps', function ($sequence) { … }); $stream->on('pm', function ($sequence) { … }); +$stream->on('ss2', function ($sequence) { … }); +$stream->on('ss3', function ($sequence) { … }); ``` Other lesser known [C1 control codes](https://en.wikipedia.org/wiki/C0_and_C1_control_codes#C1_set)