Skip to content

Commit

Permalink
Enable arrow keys to browse matched autocomplete options
Browse files Browse the repository at this point in the history
  • Loading branch information
lmcd committed Jan 5, 2013
1 parent 31ff3db commit a4d711c
Showing 1 changed file with 61 additions and 60 deletions.
121 changes: 61 additions & 60 deletions src/Symfony/Component/Console/Helper/DialogHelper.php
Expand Up @@ -86,10 +86,13 @@ public function ask(OutputInterface $output, $question, $default = null, array $
}
$ret = trim($ret);
} else {
$i = 0;
$currentMatched = false;
$ret = '';

$i = 0;
$matches = array();
$numMatches = 0;
$ofs = 0;

// Disable icanon (so we can fread each keypress) and echo (we'll do echoing here instead)
shell_exec('stty -icanon -echo');

Expand All @@ -98,25 +101,9 @@ public function ask(OutputInterface $output, $question, $default = null, array $

// Read a keypress
while ($c = fread($inputStream, 1)) {
// Did we read an escape sequence?
if ("\033" === $c) {
$c .= fread($inputStream, 2);

// Escape sequences for arrow keys
if ('A' === $c[2] || 'B' === $c[2] || 'C' === $c[2] || 'D' === $c[2]) {
// todo
}

continue;
}

// Backspace Character
if ("\177" === $c) {
if ($i === 0) {
continue;
}

if (false === $currentMatched) {
if (0 === $numMatches && 0 !== $i) {
$i--;
// Move cursor backwards
$output->write("\033[1D");
Expand All @@ -126,63 +113,77 @@ public function ask(OutputInterface $output, $question, $default = null, array $
$output->write("\033[K");
$ret = substr($ret, 0, $i);

$currentMatched = false;
$matches = array();
$numMatches = 0;

continue;
}

if ("\t" === $c || "\n" === $c) {
if (false !== $currentMatched) {
// Echo out completed match
$output->write(substr($autocomplete[$currentMatched], strlen($ret)));
$ret = $autocomplete[$currentMatched];
$i = strlen($ret);
}
// Did we read an escape sequence?
if ("\033" === $c) {
$c .= fread($inputStream, 2);

if ('A' === $c[2] || 'B' === $c[2]) {
if (0 === $i) {
$matches = $autocomplete;
$numMatches = count($matches);
}

if ("\n" === $c) {
$output->write($c);
break;
if (0 === $numMatches) {
continue;
}

$ofs += ('A' === $c[2]) ? -1 : 1;
$ofs = ($numMatches + $ofs) % $numMatches;
}
} else if (ord($c) < 32) {
if ("\t" === $c || "\n" === $c) {
if ($numMatches > 0) {
$ret = $matches[$ofs];
// Echo out completed match
$output->write(substr($ret, $i));
$i = strlen($ret);
}

$currentMatched = false;
if ("\n" === $c) {
$output->write($c);
break;
}

continue;
}
$matches = array();
$numMatches = 0;
}

if (ord($c) < 32) {
continue;
}

$output->write($c);
$ret .= $c;
$i++;
} else {
$output->write($c);
$ret .= $c;
$i++;

// Erase characters from cursor to end of line
$output->write("\033[K");
$matches = array();
$numMatches = 0;
$ofs = 0;

foreach ($autocomplete as $j => $value) {
// Get a substring of the current autocomplete item based on number of chars typed (e.g. AcmeDemoBundle = Acme)
$matchTest = substr($value, 0, $i);
foreach ($autocomplete as $value) {
// Get a substring of the current autocomplete item based on number of chars typed (e.g. AcmeDemoBundle = Acme)
$matchTest = substr($value, 0, $i);

if ($ret === $matchTest) {
if ($i === strlen($value)) {
$currentMatched = false;
break;
if ($ret === $matchTest && $i !== strlen($value)) {
$matches[$numMatches++] = $value;
}

// Save cursor position
$output->write("\0337");

$output->write('<hl>' . substr($value, $i) . '</hl>');

// Restore cursor position
$output->write("\0338");

$currentMatched = $j;
break;
}
}

// Erase characters from cursor to end of line
$output->write("\033[K");

$currentMatched = false;
if ($numMatches > 0) {
// Save cursor position
$output->write("\0337");
// Write highlighted text
$output->write('<hl>' . substr($matches[$ofs], $i) . '</hl>');
// Restore cursor position
$output->write("\0338");
}
}

Expand Down

0 comments on commit a4d711c

Please sign in to comment.