merged branch fabpot/console-select (PR #6343)

This PR was merged into the master branch.

Commits
-------

008dc8f [Console] tweaked the select() method in the dialog helper to be more consistent with other method in the same class
692b0f4 [Console] added select() method for DialogHelper

Discussion
----------

[Console] Add ability to select values interactively

This is a slightly modified version of #5417

Adds ability to select from value list:

    $values = array('One', 'Two', 'Three');
    $pick = $this->getHelper('dialog')->select($output, 'Pick a bundle:', $values, 2);
    var_dump($pick);

... would give the following CLI output:

    Pick a bundle:
      0   One
      1   Two
      2   Three
    > 1
    1

---------------------------------------------------------------------------

by Seldaek at 2012-12-14T09:07:40Z

Maybe the default value should be shown somehow?

---------------------------------------------------------------------------

by fabpot at 2012-12-14T09:28:42Z

@Seldaek: It's up to you to display it (probably in the question). That's how the other `ask*` methods work.

---------------------------------------------------------------------------

by Tobion at 2012-12-14T09:38:40Z

Would be nice to also add the ability to select multiple values (probably other PR).
So one can select each option individually to toggle it's selection. And one can select multiple with a range like `2-7` (as in the git console with `git add -i`).

---------------------------------------------------------------------------

by fabpot at 2012-12-14T09:45:10Z

@Tobion That's indeed something that should be done in another PR.
This commit is contained in:
Fabien Potencier 2012-12-14 10:45:33 +01:00
commit f070e54c05
3 changed files with 60 additions and 0 deletions

View File

@ -6,6 +6,7 @@ CHANGELOG
* added support for colorization on Windows via ConEmu
* add a method to Dialog Helper to ask for a question and hide the response
* added support for interactive selections in console (DialogHelper::select())
2.1.0
-----

View File

@ -24,6 +24,40 @@ class DialogHelper extends Helper
private static $shell;
private static $stty;
/**
* Asks the user to select a value.
*
* @param OutputInterface $output An Output instance
* @param string|array $question The question to ask
* @param array $choices List of choices to pick from
* @param Boolean $default The default answer if the user enters nothing
* @param integer|false $attempts Max number of times to ask before giving up (false by default, which means infinite)
* @param string $errorMessage Message which will be shown if invalid value from choice list would be picked
*
* @return integer|string The selected value (the key of the choices array)
*/
public function select(OutputInterface $output, $question, $choices, $default = null, $attempts = false, $errorMessage = 'Value "%s" is invalid')
{
$width = max(array_map('strlen', array_keys($choices)));
$messages = (array) $question;
foreach ($choices as $key => $value) {
$messages[] = sprintf(" [<info>%-${width}s</info>] %s", $key, $value);
}
$output->writeln($messages);
$result = $this->askAndValidate($output, '> ', function ($picked) use ($choices, $errorMessage) {
if (empty($choices[$picked])) {
throw new \InvalidArgumentException(sprintf($errorMessage, $picked));
}
return $picked;
}, $attempts, $default);
return $result;
}
/**
* Asks a question to the user.
*

View File

@ -18,6 +18,31 @@ use Symfony\Component\Console\Output\StreamOutput;
class DialogHelperTest extends \PHPUnit_Framework_TestCase
{
public function testSelect()
{
$dialog = new DialogHelper();
$helperSet = new HelperSet(array(new FormatterHelper()));
$dialog->setHelperSet($helperSet);
$heroes = array('Superman', 'Batman', 'Spiderman');
$dialog->setInputStream($this->getInputStream("\n1\nFabien\n1\nFabien\nFabien\n"));
$this->assertEquals('2', $dialog->select($this->getOutputStream(), 'What is your favorite superhero?', $heroes, '2'));
$this->assertEquals('1', $dialog->select($this->getOutputStream(), 'What is your favorite superhero?', $heroes));
$this->assertEquals('1', $dialog->select($output = $this->getOutputStream(), 'What is your favorite superhero?', $heroes, null, false, 'Input "%s" is not a superhero!'));
rewind($output->getStream());
$this->assertContains('Input "Fabien" is not a superhero!', stream_get_contents($output->getStream()));
try {
$this->assertEquals('1', $dialog->select($output = $this->getOutputStream(), 'What is your favorite superhero?', $heroes, null, 1));
$this->fail();
} catch (\InvalidArgumentException $e) {
$this->assertEquals('Value "Fabien" is invalid', $e->getMessage());
}
}
public function testAsk()
{
$dialog = new DialogHelper();