Skip to content

Commit

Permalink
Update prompts (#267)
Browse files Browse the repository at this point in the history
* Update prompts

* Improve text fallback default display

* Update prompts version

* Validate project name

* Update constraints to meet prompts requirements
  • Loading branch information
jessarcher authored Jul 31, 2023
1 parent eab05df commit 4033cbf
Show file tree
Hide file tree
Showing 5 changed files with 289 additions and 145 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:
strategy:
fail-fast: true
matrix:
php: [7.3, 7.4, '8.0', 8.1, 8.2]
php: [8.1, 8.2]

name: PHP ${{ matrix.php }}

Expand Down Expand Up @@ -44,7 +44,7 @@ jobs:
strategy:
fail-fast: true
matrix:
php: [7.3, 7.4, '8.0', 8.1, 8.2]
php: [8.1, 8.2]

name: PHP ${{ matrix.php }} - Windows

Expand Down
9 changes: 5 additions & 4 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,14 @@
}
],
"require": {
"php": "^7.3|^8.0",
"symfony/console": "^4.0|^5.0|^6.0",
"symfony/process": "^4.2|^5.0|^6.0"
"php": "^8.1",
"laravel/prompts": "^0.1",
"symfony/console": "^6.0",
"symfony/process": "^6.0"
},
"require-dev": {
"phpstan/phpstan": "^1.10",
"phpunit/phpunit": "^8.0|^9.3"
"phpunit/phpunit": "^9.3"
},
"bin": [
"bin/laravel"
Expand Down
132 changes: 132 additions & 0 deletions src/Concerns/ConfiguresPrompts.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
<?php

namespace Laravel\Installer\Console\Concerns;

use Laravel\Prompts\ConfirmPrompt;
use Laravel\Prompts\MultiSelectPrompt;
use Laravel\Prompts\PasswordPrompt;
use Laravel\Prompts\Prompt;
use Laravel\Prompts\SelectPrompt;
use Laravel\Prompts\SuggestPrompt;
use Laravel\Prompts\TextPrompt;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Question\Question;
use Symfony\Component\Console\Style\SymfonyStyle;

trait ConfiguresPrompts
{
/**
* Configure the prompt fallbacks.
*
* @param \Symfony\Component\Console\Input\InputInterface $input
* @param \Symfony\Component\Console\Output\OutputInterface $output
* @return void
*/
protected function configurePrompts(InputInterface $input, OutputInterface $output)
{
Prompt::fallbackWhen(! $input->isInteractive() || PHP_OS_FAMILY === 'Windows');

TextPrompt::fallbackUsing(fn (TextPrompt $prompt) => $this->promptUntilValid(
fn () => (new SymfonyStyle($input, $output))->ask($prompt->label, $prompt->default ?: null) ?? '',
$prompt->required,
$prompt->validate,
$output
));

PasswordPrompt::fallbackUsing(fn (PasswordPrompt $prompt) => $this->promptUntilValid(
fn () => (new SymfonyStyle($input, $output))->askHidden($prompt->label) ?? '',
$prompt->required,
$prompt->validate,
$output
));

ConfirmPrompt::fallbackUsing(fn (ConfirmPrompt $prompt) => $this->promptUntilValid(
fn () => (new SymfonyStyle($input, $output))->confirm($prompt->label, $prompt->default),
$prompt->required,
$prompt->validate,
$output
));

SelectPrompt::fallbackUsing(fn (SelectPrompt $prompt) => $this->promptUntilValid(
fn () => (new SymfonyStyle($input, $output))->choice($prompt->label, $prompt->options, $prompt->default),
false,
$prompt->validate,
$output
));

MultiSelectPrompt::fallbackUsing(function (MultiSelectPrompt $prompt) use ($input, $output) {
if ($prompt->default !== []) {
return $this->promptUntilValid(
fn () => (new SymfonyStyle($input, $output))->choice($prompt->label, $prompt->options, implode(',', $prompt->default), true),
$prompt->required,
$prompt->validate,
$output
);
}

return $this->promptUntilValid(
fn () => collect((new SymfonyStyle($input, $output))->choice(
$prompt->label,
array_is_list($prompt->options)
? ['None', ...$prompt->options]
: ['none' => 'None', ...$prompt->options],
'None',
true)
)->reject(array_is_list($prompt->options) ? 'None' : 'none')->all(),
$prompt->required,
$prompt->validate,
$output
);
});

SuggestPrompt::fallbackUsing(fn (SuggestPrompt $prompt) => $this->promptUntilValid(
function () use ($prompt, $input, $output) {
$question = new Question($prompt->label, $prompt->default);

is_callable($prompt->options)
? $question->setAutocompleterCallback($prompt->options)
: $question->setAutocompleterValues($prompt->options);

return (new SymfonyStyle($input, $output))->askQuestion($question);
},
$prompt->required,
$prompt->validate,
$output
));
}

/**
* Prompt the user until the given validation callback passes.
*
* @param \Closure $prompt
* @param bool|string $required
* @param \Closure|null $validate
* @param \Symfony\Component\Console\Output\OutputInterface $output
* @return mixed
*/
protected function promptUntilValid($prompt, $required, $validate, $output)
{
while (true) {
$result = $prompt();

if ($required && ($result === '' || $result === [] || $result === false)) {
$output->writeln('<error>'.(is_string($required) ? $required : 'Required.').'</error>');

continue;
}

if ($validate) {
$error = $validate($result);

if (is_string($error) && strlen($error) > 0) {
$output->writeln("<error>{$error}</error>");

continue;
}
}

return $result;
}
}
}
Loading

0 comments on commit 4033cbf

Please sign in to comment.