Skip to content

Commit 011c0c7

Browse files
authored
Merge pull request #79 from clue-labs/crlf
Accept CR as an alias for LF to support more platforms
2 parents 5da4d99 + 27e6d2c commit 011c0c7

File tree

2 files changed

+39
-6
lines changed

2 files changed

+39
-6
lines changed

src/Readline.php

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,10 @@ public function __construct(ReadableStreamInterface $input, WritableStreamInterf
4444

4545
$that = $this;
4646
$codes = array(
47-
"\n" => 'onKeyEnter',
48-
"\x7f" => 'onKeyBackspace',
49-
"\t" => 'onKeyTab',
50-
51-
"\x04" => 'handleEnd', // CTRL+D
47+
"\n" => 'onKeyEnter', // ^J
48+
"\x7f" => 'onKeyBackspace', // ^?
49+
"\t" => 'onKeyTab', // ^I
50+
"\x04" => 'handleEnd', // ^D
5251

5352
"\033[A" => 'onKeyUp',
5453
"\033[B" => 'onKeyDown',
@@ -63,6 +62,16 @@ public function __construct(ReadableStreamInterface $input, WritableStreamInterf
6362
// "\033[20~" => 'onKeyF10',
6463
);
6564
$decode = function ($code) use ($codes, $that) {
65+
// The user confirms input with enter key which should usually
66+
// generate a NL (`\n`) character. Common terminals also seem to
67+
// accept a CR (`\r`) character in place and handle this just like a
68+
// NL. Similarly `ext-readline` uses different `icrnl` and `igncr`
69+
// TTY settings on some platforms, so we also accept CR as an alias
70+
// for NL here. This implies key binding for NL will also trigger.
71+
if ($code === "\r") {
72+
$code = "\n";
73+
}
74+
6675
if ($that->listeners($code)) {
6776
$that->emit($code, array($code));
6877
return;

tests/ReadlineTest.php

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -228,13 +228,20 @@ public function testMovingCursorWithoutEchoDoesNotNeedToRedraw()
228228
$this->assertSame($this->readline, $this->readline->moveCursorBy(2));
229229
}
230230

231-
public function testDataEventWillBeEmittedForCompleteLine()
231+
public function testDataEventWillBeEmittedForCompleteLineWithNl()
232232
{
233233
$this->readline->on('data', $this->expectCallableOnceWith("hello\n"));
234234

235235
$this->input->emit('data', array("hello\n"));
236236
}
237237

238+
public function testDataEventWillBeEmittedWithNlAlsoForCompleteLineWithCr()
239+
{
240+
$this->readline->on('data', $this->expectCallableOnceWith("hello\n"));
241+
242+
$this->input->emit('data', array("hello\r"));
243+
}
244+
238245
public function testDataEventWillNotBeEmittedForIncompleteLineButWillStayInInputBuffer()
239246
{
240247
$this->readline->on('data', $this->expectCallableNever());
@@ -981,6 +988,23 @@ public function testBindCustomFunctionCanOverwriteAutocompleteBehavior()
981988
$this->input->emit('data', array("\t"));
982989
}
983990

991+
public function testBindCustomFunctionToNlOverwritesDataEvent()
992+
{
993+
$this->readline->on("\n", $this->expectCallableOnceWith("\n"));
994+
$this->readline->on('line', $this->expectCallableNever());
995+
996+
$this->input->emit('data', array("hello\n"));
997+
}
998+
999+
public function testBindCustomFunctionToNlFiresOnCr()
1000+
{
1001+
$this->readline->on("\n", $this->expectCallableOnceWith("\n"));
1002+
$this->readline->on("\r", $this->expectCallableNever());
1003+
$this->readline->on('line', $this->expectCallableNever());
1004+
1005+
$this->input->emit('data', array("hello\r"));
1006+
}
1007+
9841008
public function testEmitEmptyInputOnEnter()
9851009
{
9861010
$this->readline->on('data', $this->expectCallableOnceWith("\n"));

0 commit comments

Comments
 (0)