[Console] allow answer to be trimmed by adding a flag

This commit is contained in:
Amrouche Hamza 2019-05-26 18:06:33 +02:00
parent 7207849037
commit 8f182d811e
No known key found for this signature in database
GPG Key ID: E45A3DA456145BC1
4 changed files with 101 additions and 9 deletions

View File

@ -1,6 +1,11 @@
CHANGELOG
=========
4.4.0
-----
* added `Question::setTrimmable` default to true to allow the answer to be trimmed or not
4.3.0
-----

View File

@ -64,7 +64,7 @@ class QuestionHelper extends Helper
$default = explode(',', $default);
foreach ($default as $k => $v) {
$v = trim($v);
$v = $question->isTrimmable() ? trim($v) : $v;
$default[$k] = isset($choices[$v]) ? $choices[$v] : $v;
}
}
@ -121,7 +121,8 @@ class QuestionHelper extends Helper
$ret = false;
if ($question->isHidden()) {
try {
$ret = trim($this->getHiddenResponse($output, $inputStream));
$hiddenResponse = $this->getHiddenResponse($output, $inputStream, $question->isTrimmable());
$ret = $question->isTrimmable() ? trim($hiddenResponse) : $hiddenResponse;
} catch (RuntimeException $e) {
if (!$question->isHiddenFallback()) {
throw $e;
@ -134,10 +135,13 @@ class QuestionHelper extends Helper
if (false === $ret) {
throw new RuntimeException('Aborted.');
}
$ret = trim($ret);
if ($question->isTrimmable()) {
$ret = trim($ret);
}
}
} else {
$ret = trim($this->autocomplete($output, $question, $inputStream, $autocomplete));
$autocomplete = $this->autocomplete($output, $question, $inputStream, $autocomplete);
$ret = $question->isTrimmable() ? trim($autocomplete) : $autocomplete;
}
if ($output instanceof ConsoleSectionOutput) {
@ -351,10 +355,11 @@ class QuestionHelper extends Helper
*
* @param OutputInterface $output An Output instance
* @param resource $inputStream The handler resource
* @param bool $trimmable Is the answer trimmable
*
* @throws RuntimeException In case the fallback is deactivated and the response cannot be hidden
*/
private function getHiddenResponse(OutputInterface $output, $inputStream): string
private function getHiddenResponse(OutputInterface $output, $inputStream, $trimmable = true): string
{
if ('\\' === \DIRECTORY_SEPARATOR) {
$exe = __DIR__.'/../Resources/bin/hiddeninput.exe';
@ -366,7 +371,8 @@ class QuestionHelper extends Helper
$exe = $tmpExe;
}
$value = rtrim(shell_exec($exe));
$sExec = shell_exec($exe);
$value = $trimmable ? rtrim($sExec) : $sExec;
$output->writeln('');
if (isset($tmpExe)) {
@ -386,8 +392,9 @@ class QuestionHelper extends Helper
if (false === $value) {
throw new RuntimeException('Aborted.');
}
$value = trim($value);
if ($trimmable) {
$value = trim($value);
}
$output->writeln('');
return $value;
@ -396,7 +403,8 @@ class QuestionHelper extends Helper
if (false !== $shell = $this->getShell()) {
$readCmd = 'csh' === $shell ? 'set mypassword = $<' : 'read -r mypassword';
$command = sprintf("/usr/bin/env %s -c 'stty -echo; %s; stty echo; echo \$mypassword'", $shell, $readCmd);
$value = rtrim(shell_exec($command));
$sCommand = shell_exec($command);
$value = $trimmable ? rtrim($sCommand) : $sCommand;
$output->writeln('');
return $value;

View File

@ -29,6 +29,7 @@ class Question
private $validator;
private $default;
private $normalizer;
private $trimmable = true;
/**
* @param string $question The question to ask to the user
@ -274,4 +275,19 @@ class Question
{
return (bool) \count(array_filter(array_keys($array), 'is_string'));
}
public function isTrimmable(): bool
{
return $this->trimmable;
}
/**
* @return $this
*/
public function setTrimmable(bool $trimmable): self
{
$this->trimmable = $trimmable;
return $this;
}
}

View File

@ -165,6 +165,20 @@ class QuestionHelperTest extends AbstractQuestionHelperTest
$this->assertEquals('What time is it?', stream_get_contents($output->getStream()));
}
public function testAskNonTrimmed()
{
$dialog = new QuestionHelper();
$inputStream = $this->getInputStream(' 8AM ');
$question = new Question('What time is it?', '2PM');
$question->setTrimmable(false);
$this->assertEquals(' 8AM ', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $output = $this->createOutputInterface(), $question));
rewind($output->getStream());
$this->assertEquals('What time is it?', stream_get_contents($output->getStream()));
}
public function testAskWithAutocomplete()
{
if (!$this->hasSttyAvailable()) {
@ -198,6 +212,40 @@ class QuestionHelperTest extends AbstractQuestionHelperTest
$this->assertEquals('FooBundle', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question));
}
public function testAskWithAutocompleteTrimmable()
{
if (!$this->hasSttyAvailable()) {
$this->markTestSkipped('`stty` is required to test autocomplete functionality');
}
// Acm<NEWLINE>
// Ac<BACKSPACE><BACKSPACE>s<TAB>Test<NEWLINE>
// <NEWLINE>
// <UP ARROW><UP ARROW><NEWLINE>
// <UP ARROW><UP ARROW><UP ARROW><UP ARROW><UP ARROW><TAB>Test<NEWLINE>
// <DOWN ARROW><NEWLINE>
// S<BACKSPACE><BACKSPACE><DOWN ARROW><DOWN ARROW><NEWLINE>
// F00<BACKSPACE><BACKSPACE>oo<TAB><NEWLINE>
$inputStream = $this->getInputStream("Acm\nAc\177\177s\tTest\n\n\033[A\033[A\n\033[A\033[A\033[A\033[A\033[A\tTest\n\033[B\nS\177\177\033[B\033[B\nF00\177\177oo\t\n");
$dialog = new QuestionHelper();
$helperSet = new HelperSet([new FormatterHelper()]);
$dialog->setHelperSet($helperSet);
$question = new Question('Please select a bundle', 'FrameworkBundle');
$question->setAutocompleterValues(['AcmeDemoBundle ', 'AsseticBundle', ' SecurityBundle ', 'FooBundle']);
$question->setTrimmable(false);
$this->assertEquals('AcmeDemoBundle ', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question));
$this->assertEquals('AsseticBundleTest', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question));
$this->assertEquals('FrameworkBundle', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question));
$this->assertEquals(' SecurityBundle ', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question));
$this->assertEquals('FooBundleTest', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question));
$this->assertEquals('AcmeDemoBundle ', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question));
$this->assertEquals('AsseticBundle', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question));
$this->assertEquals('FooBundle', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question));
}
public function testAskWithAutocompleteCallback()
{
if (!$this->hasSttyAvailable()) {
@ -373,6 +421,21 @@ class QuestionHelperTest extends AbstractQuestionHelperTest
$this->assertEquals('8AM', $dialog->ask($this->createStreamableInputInterfaceMock($this->getInputStream("8AM\n")), $this->createOutputInterface(), $question));
}
public function testAskHiddenResponseTrimmed()
{
if ('\\' === \DIRECTORY_SEPARATOR) {
$this->markTestSkipped('This test is not supported on Windows');
}
$dialog = new QuestionHelper();
$question = new Question('What time is it?');
$question->setHidden(true);
$question->setTrimmable(false);
$this->assertEquals(' 8AM', $dialog->ask($this->createStreamableInputInterfaceMock($this->getInputStream(' 8AM')), $this->createOutputInterface(), $question));
}
/**
* @dataProvider getAskConfirmationData
*/