Skip to content

Commit b2bd501

Browse files
committed
Parse all escape sequences through external term parser
1 parent 2563ad3 commit b2bd501

File tree

2 files changed

+41
-52
lines changed

2 files changed

+41
-52
lines changed

composer.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@
1414
"php": ">=5.3",
1515
"react/event-loop": "0.3.*|0.4.*",
1616
"react/stream": "^0.4.2",
17-
"clue/utf8-react": "^0.1"
17+
"clue/utf8-react": "^0.1",
18+
"clue/term-react": "^0.1"
1819
},
1920
"autoload": {
2021
"psr-4": { "Clue\\React\\Stdio\\": "src/" }

src/Readline.php

Lines changed: 39 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -7,26 +7,10 @@
77
use React\Stream\WritableStreamInterface;
88
use React\Stream\Util;
99
use Clue\React\Utf8\Sequencer as Utf8Sequencer;
10-
use React\Stream\ReadableStream;
10+
use Clue\React\Term\ControlCodeParser;
1111

1212
class Readline extends EventEmitter implements ReadableStreamInterface
1313
{
14-
const KEY_BACKSPACE = "\x7f";
15-
const KEY_ENTER = "\n";
16-
const KEY_TAB = "\t";
17-
18-
const ESC_SEQUENCE = "\033[";
19-
const ESC_LEFT = "D";
20-
const ESC_RIGHT = "C";
21-
const ESC_UP = "A";
22-
const ESC_DOWN = "B";
23-
const ESC_HOME = "1~";
24-
const ESC_INS = "2~";
25-
const ESC_DEL = "3~";
26-
const ESC_END = "4~";
27-
28-
const ESC_F10 = "20~";
29-
3014
private $prompt = '';
3115
private $linebuffer = '';
3216
private $linepos = 0;
@@ -50,42 +34,46 @@ public function __construct(ReadableStreamInterface $input, WritableStreamInterf
5034
return $this->close();
5135
}
5236

53-
$this->sequencer = new Sequencer();
54-
$this->sequencer->addSequence(self::KEY_ENTER, array($this, 'onKeyEnter'));
55-
$this->sequencer->addSequence(self::KEY_BACKSPACE, array($this, 'onKeyBackspace'));
56-
$this->sequencer->addSequence(self::KEY_TAB, array($this, 'onKeyTab'));
57-
58-
$this->sequencer->addSequence(self::ESC_SEQUENCE . self::ESC_LEFT, array($this, 'onKeyLeft'));
59-
$this->sequencer->addSequence(self::ESC_SEQUENCE . self::ESC_RIGHT, array($this, 'onKeyRight'));
60-
$this->sequencer->addSequence(self::ESC_SEQUENCE . self::ESC_UP, array($this, 'onKeyUp'));
61-
$this->sequencer->addSequence(self::ESC_SEQUENCE . self::ESC_DOWN, array($this, 'onKeyDown'));
62-
$this->sequencer->addSequence(self::ESC_SEQUENCE . self::ESC_HOME, array($this, 'onKeyHome'));
63-
$this->sequencer->addSequence(self::ESC_SEQUENCE . self::ESC_INS, array($this, 'onKeyInsert'));
64-
$this->sequencer->addSequence(self::ESC_SEQUENCE . self::ESC_DEL, array($this, 'onKeyDelete'));
65-
$this->sequencer->addSequence(self::ESC_SEQUENCE . self::ESC_END, array($this, 'onKeyEnd'));
66-
67-
// push input into sequencer
68-
$input->on('data', array($this->sequencer, 'push'));
69-
70-
// push sequencer output through utf8sequencer
71-
$readable = new ReadableStream();
72-
$this->sequencer->addFallback('', function ($data) use ($readable) {
73-
$readable->emit('data', array($data));
74-
});
75-
76-
// push utf8sequences as input
77-
$utf8 = new Utf8Sequencer($readable);
78-
$utf8->on('data', array($this, 'onFallback'));
37+
// push input through control code parser
38+
$parser = new ControlCodeParser($input);
39+
40+
$that = $this;
41+
$codes = array(
42+
"\n" => 'onKeyEnter',
43+
"\x7f" => 'onKeyBackspace',
44+
"\t" => 'onKeyTab',
45+
46+
"\033[A" => 'onKeyUp',
47+
"\033[B" => 'onKeyDown',
48+
"\033[C" => 'onKeyRight',
49+
"\033[D" => 'onKeyLeft',
50+
51+
"\033[1~" => 'onKeyHome',
52+
"\033[2~" => 'onKeyInsert',
53+
"\033[3~" => 'onKeyDelete',
54+
"\033[4~" => 'onKeyEnd',
55+
56+
// "\033[20~" => 'onKeyF10',
57+
);
58+
$decode = function ($code) use ($codes, $that) {
59+
if (isset($codes[$code])) {
60+
$method = $codes[$code];
61+
$that->$method($code);
62+
return;
63+
}
64+
};
7965

80-
$this->sequencer->addFallback(self::ESC_SEQUENCE, function ($bytes) {
81-
echo 'unknown sequence: ' . ord($bytes) . PHP_EOL;
82-
});
66+
$parser->on('csi', $decode);
67+
$parser->on('c0', $decode);
68+
69+
// push resulting data through utf8 sequencer
70+
$utf8 = new Utf8Sequencer($parser);
71+
$utf8->on('data', array($this, 'onFallback'));
8372

84-
// input data emits a single char into readline
85-
$input->on('data', array($this->sequencer, 'push'));
86-
$input->on('end', array($this, 'handleEnd'));
87-
$input->on('error', array($this, 'handleError'));
88-
$input->on('close', array($this, 'close'));
73+
// process all stream events (forwarded from input stream)
74+
$utf8->on('end', array($this, 'handleEnd'));
75+
$utf8->on('error', array($this, 'handleError'));
76+
$utf8->on('close', array($this, 'close'));
8977
}
9078

9179
/**

0 commit comments

Comments
 (0)