Skip to content

Commit 3f2e53f

Browse files
committed
Merge pull request #11 from clue-labs/echo
Support echo replacements (asterisk for password prompts)
2 parents e937348 + bdf2daf commit 3f2e53f

File tree

3 files changed

+51
-13
lines changed

3 files changed

+51
-13
lines changed

examples/login.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
$stdio->on('line', function ($line) use ($stdio, &$first, &$username, &$password) {
1818
if ($first) {
1919
$stdio->getReadline()->setPrompt('Password: ');
20-
$stdio->getReadline()->setEcho(false);
20+
$stdio->getReadline()->setEcho('*');
2121
$username = $line;
2222
$first = false;
2323
} else {

src/Readline.php

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -75,13 +75,28 @@ public function setPrompt($prompt)
7575
}
7676

7777
/**
78-
* whether or not to echo input
78+
* sets whether/how to echo text input
7979
*
80-
* disabling echo output is a good idea for password prompts. Will redraw
81-
* the current prompt and only echo the current input buffer according to
82-
* the new setting.
80+
* The default setting is `true`, which means that every character will be
81+
* echo'ed as-is, i.e. you can see what you're typing.
82+
* For example: Typing "test" shows "test".
8383
*
84-
* @param boolean $echo
84+
* You can turn this off by supplying `false`, which means that *nothing*
85+
* will be echo'ed while you're typing. This could be a good idea for
86+
* password prompts. Note that this could be confusing for users, so using
87+
* a character replacement as following is often preferred.
88+
* For example: Typing "test" shows "" (nothing).
89+
*
90+
* Alternative, you can supply a single character replacement character
91+
* that will be echo'ed for each character in the text input. This could
92+
* be a good idea for password prompts, where an asterisk character ("*")
93+
* is often used to indicate typing activity and password length.
94+
* For example: Typing "test" shows "****" (with asterisk replacement)
95+
*
96+
* Changing this setting will redraw the current prompt and echo the current
97+
* input buffer according to the new setting.
98+
*
99+
* @param boolean|string $echo echo can be turned on (boolean true) or off (boolean true), or you can supply a single character replacement string
85100
* @return self
86101
* @uses self::redraw()
87102
*/
@@ -91,7 +106,7 @@ public function setEcho($echo)
91106
return $this;
92107
}
93108

94-
$this->echo = !!$echo;
109+
$this->echo = $echo;
95110

96111
// only redraw if there is any input
97112
if ($this->linebuffer !== '') {
@@ -153,7 +168,7 @@ public function setInput($input)
153168
$this->linepos = $this->strlen($this->linebuffer);
154169

155170
// only redraw if input should be echo'ed (i.e. is not hidden anyway)
156-
if ($this->echo) {
171+
if ($this->echo !== false) {
157172
$this->redraw();
158173
}
159174

@@ -219,8 +234,12 @@ public function redraw()
219234
{
220235
// Erase characters from cursor to end of line
221236
$output = "\r\033[K" . $this->prompt;
222-
if ($this->echo) {
223-
$output .= $this->linebuffer;
237+
if ($this->echo !== false) {
238+
if ($this->echo === true) {
239+
$output .= $this->linebuffer;
240+
} else {
241+
$output .= str_repeat($this->echo, $this->strlen($this->linebuffer));
242+
}
224243

225244
$len = $this->strlen($this->linebuffer);
226245
if ($this->linepos !== $len) {
@@ -237,7 +256,7 @@ public function redraw()
237256

238257
public function clear()
239258
{
240-
if ($this->prompt !== '' || ($this->echo && $this->linebuffer !== '')) {
259+
if ($this->prompt !== '' || ($this->echo !== false && $this->linebuffer !== '')) {
241260
$this->write("\r\033[K");
242261
}
243262
// $output = str_repeat("\x09 \x09", strlen($this->prompt . $this->linebuffer));
@@ -275,7 +294,7 @@ public function onKeyTab()
275294

276295
public function onKeyEnter()
277296
{
278-
if ($this->echo) {
297+
if ($this->echo !== false) {
279298
$this->write("\n");
280299
}
281300
$this->processLine();

tests/ReadlineTest.php

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,16 @@ public function testSettingEchoOnWithInputDoesRedraw()
8080
$this->assertSame($this->readline, $this->readline->setEcho(true));
8181
}
8282

83+
public function testSettingEchoAsteriskWithInputDoesRedraw()
84+
{
85+
$this->readline->setPrompt('> ');
86+
$this->readline->setInput('test');
87+
88+
$this->output->expects($this->once())->method('write')->with($this->equalTo("\r\033[K" . "> " . "****"));
89+
90+
$this->assertSame($this->readline, $this->readline->setEcho('*'));
91+
}
92+
8393
public function testSettingEchoOffWithInputDoesRedraw()
8494
{
8595
$this->readline->setEcho(true);
@@ -101,7 +111,16 @@ public function testSettingEchoWithoutInputDoesNotNeedToRedraw()
101111

102112
public function testSettingInputDoesRedraw()
103113
{
104-
$this->output->expects($this->once())->method('write');
114+
$this->output->expects($this->once())->method('write')->with($this->equalTo("\r\033[K" . "test"));
115+
$this->assertSame($this->readline, $this->readline->setInput('test'));
116+
}
117+
118+
public function testSettingInputWithEchoAsteriskDoesRedraw()
119+
{
120+
$this->readline->setEcho('*');
121+
122+
$this->output->expects($this->once())->method('write')->with($this->equalTo("\r\033[K" . "****"));
123+
105124
$this->assertSame($this->readline, $this->readline->setInput('test'));
106125
}
107126

0 commit comments

Comments
 (0)