feature #15382 [Console] Use readline for user input when available #DX (michaelperrin)

This PR was merged into the 2.8 branch.

Discussion
----------

[Console] Use readline for user input when available #DX

| Q             | A
| ------------- | ---
| Bug fix?      | no
| New feature?  | no
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets |
| License       | MIT
| Doc PR        |

Given I am entering data in an user input
When I use left and right keys to make some changes in what I have typed
Then the cursor should move accordingly instead of adding characters at the end of the line

To make it simple: using the arrow keys (←  →)  to make changes to what I already typed would be much handier than getting `^[[D` and `^[[C` characters in the terminal and having to delete all chars to type everything again.

I could not add any extra tests to this as the STDIN can't be used during tests. But they are not breaking and I tried again all types of questions (text, choices, hidden) by myself.

Note that `readline` can't be used for hidden questions, as `stty -echo` is not taken into account.

Commits
-------

0534899 [Console] Fix Symfony coding standards violations
8b63d62 [Console] Use readline for user input when available
This commit is contained in:
Fabien Potencier 2015-08-01 13:59:20 +02:00
commit c856a010a2
2 changed files with 35 additions and 9 deletions

View File

@ -1,6 +1,12 @@
CHANGELOG CHANGELOG
========= =========
2.8.0
-----
* use readline for user input in the question helper when available to allow
the use of arrow keys
2.6.0 2.6.0
----- -----

View File

@ -77,7 +77,7 @@ class QuestionHelper extends Helper
} }
/** /**
* Returns the helper's input stream * Returns the helper's input stream.
* *
* @return resource * @return resource
*/ */
@ -127,11 +127,7 @@ class QuestionHelper extends Helper
} }
if (false === $ret) { if (false === $ret) {
$ret = fgets($inputStream, 4096); $ret = $this->readFromInput($inputStream);
if (false === $ret) {
throw new \RuntimeException('Aborted');
}
$ret = trim($ret);
} }
} else { } else {
$ret = trim($this->autocomplete($output, $question, $inputStream)); $ret = trim($this->autocomplete($output, $question, $inputStream));
@ -150,7 +146,7 @@ class QuestionHelper extends Helper
* Outputs the question prompt. * Outputs the question prompt.
* *
* @param OutputInterface $output * @param OutputInterface $output
* @param Question $question * @param Question $question
*/ */
protected function writePrompt(OutputInterface $output, Question $question) protected function writePrompt(OutputInterface $output, Question $question)
{ {
@ -222,7 +218,7 @@ class QuestionHelper extends Helper
// Backspace Character // Backspace Character
if ("\177" === $c) { if ("\177" === $c) {
if (0 === $numMatches && 0 !== $i) { if (0 === $numMatches && 0 !== $i) {
$i--; --$i;
// Move cursor backwards // Move cursor backwards
$output->write("\033[1D"); $output->write("\033[1D");
} }
@ -275,7 +271,7 @@ class QuestionHelper extends Helper
} else { } else {
$output->write($c); $output->write($c);
$ret .= $c; $ret .= $c;
$i++; ++$i;
$numMatches = 0; $numMatches = 0;
$ofs = 0; $ofs = 0;
@ -423,6 +419,30 @@ class QuestionHelper extends Helper
return self::$shell; return self::$shell;
} }
/**
* Reads user input.
*
* @param resource $stream The input stream
*
* @return string User input
*
* @throws \RuntimeException
*/
private function readFromInput($stream)
{
if (STDIN === $stream && function_exists('readline')) {
$ret = readline();
} else {
$ret = fgets($stream, 4096);
if (false === $ret) {
throw new \RuntimeException('Aborted');
}
}
return trim($ret);
}
/** /**
* Returns whether Stty is available or not. * Returns whether Stty is available or not.
* *