Skip to content

Commit

Permalink
rename tty listener to TtyObserver
Browse files Browse the repository at this point in the history
  • Loading branch information
tflori committed Aug 24, 2018
1 parent b8b773b commit 4ffdf4d
Show file tree
Hide file tree
Showing 3 changed files with 120 additions and 2 deletions.
118 changes: 118 additions & 0 deletions src/Input/TTyObserver.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
<?php

namespace Hugga\Input;

class TTyObserver
{
protected $stdin;

protected $charHandler = [];

protected $handler = [];

protected $stop = true;

public static function isCompatible($stdin)
{
return is_executable('/bin/stty') && function_exists('posix_isatty') && posix_isatty($stdin);
}

public function __construct($stdin)
{
$this->stdin = $stdin;
}

public function start()
{
$this->stop = false;

// change tty settings
$sttySettings = preg_replace('#.*; ?#s', '', $this->ttySettings('--all'));
$this->ttySettings('cbreak -echo');

while (!$this->stop) {
$c = '';
do {
$c .= fgetc($this->stdin);
$input = [$this->stdin];
} while (stream_select($input, $output, $error, 0) && in_array($this->stdin, $input));

$this->handle($c);
}

// reset tty settings
$this->ttySettings($sttySettings);

return;
}

public function stop()
{
$this->stop = true;
}

protected function handle(string $char)
{
$event = (object)[
'type' => 'keyUp',
'char' => $char,
'stopPropagation' => false,
];

$handlers = array_reverse($this->handler);
if (isset($this->charHandler[$char])) {
array_unshift($handlers, ...array_reverse($this->charHandler[$char]));
}
foreach ($handlers as $handler) {
$handler($event);
if ($event->stopPropagation) {
return;
}
}
}

public function on(string $char, callable $callback)
{
if (!isset($this->charHandler[$char])) {
$this->charHandler[$char] = [];
}

$this->charHandler[$char][] = $callback;
return $this;
}

public function addHandler(callable $callback)
{
$this->handler[] = $callback;
return $this;
}

public function off(string $char, callable $callback)
{
if (!isset($this->charHandler[$char])) {
return $this;
}

if ($pos = array_search($callback, $this->charHandler[$char])) {
array_splice($this->charHandler[$char], $pos, 1);
}
return $this;
}

public function removeHandler(callable $callback)
{
if ($pos = array_search($callback, $this->charHandler[$char])) {
array_splice($this->charHandler[$char], $pos, 1);
}
return $this;
}

protected function ttySettings($options)
{
exec($cmd = "/bin/stty $options", $output, $returnValue);
if ($returnValue) {
throw new \Exception('Failed to change tty settings');
}
return implode(' ', $output);
}
}
2 changes: 1 addition & 1 deletion src/Output/ResourceHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,6 @@ public function deleteLine()
} else {
$this->delete(strlen($tail));
}
} while($i > 0);
} while ($i > 0);
}
}
2 changes: 1 addition & 1 deletion tests/QuestionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public function returnsDefault()
$this->console->shouldReceive('waitLine')->with()
->once()->andReturn(PHP_EOL)->ordered();

$answer = (new Question('What is your name?' , 'John Doe'))->ask($this->console);
$answer = (new Question('What is your name?', 'John Doe'))->ask($this->console);

self::assertSame('John Doe', $answer);
}
Expand Down

0 comments on commit 4ffdf4d

Please sign in to comment.