Skip to content

Commit

Permalink
Added pause prompt
Browse files Browse the repository at this point in the history
  • Loading branch information
allanmcarvalho committed Feb 8, 2024
1 parent e4a558f commit 3926f9e
Show file tree
Hide file tree
Showing 6 changed files with 233 additions and 0 deletions.
38 changes: 38 additions & 0 deletions playground/pause.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?php

use Laravel\Prompts\Prompt;
use function Laravel\Prompts\pause;

require __DIR__.'/../vendor/autoload.php';

Prompt::fallbackWhen(true);

$license = "Copyright (c) 2023 Laravel LCC
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the \"Software\"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.";

$continued = pause(
$license,
'MIT License',
hint: 'By pressing ENTER you accept the license!'
);

var_dump($continued);

echo str_repeat(PHP_EOL, 2);
3 changes: 3 additions & 0 deletions src/Concerns/Themes.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use Laravel\Prompts\MultiSelectPrompt;
use Laravel\Prompts\Note;
use Laravel\Prompts\PasswordPrompt;
use Laravel\Prompts\PausePrompt;
use Laravel\Prompts\Progress;
use Laravel\Prompts\SearchPrompt;
use Laravel\Prompts\SelectPrompt;
Expand All @@ -20,6 +21,7 @@
use Laravel\Prompts\Themes\Default\MultiSelectPromptRenderer;
use Laravel\Prompts\Themes\Default\NoteRenderer;
use Laravel\Prompts\Themes\Default\PasswordPromptRenderer;
use Laravel\Prompts\Themes\Default\PausePromptRenderer;
use Laravel\Prompts\Themes\Default\ProgressRenderer;
use Laravel\Prompts\Themes\Default\SearchPromptRenderer;
use Laravel\Prompts\Themes\Default\SelectPromptRenderer;
Expand Down Expand Up @@ -47,6 +49,7 @@ trait Themes
SelectPrompt::class => SelectPromptRenderer::class,
MultiSelectPrompt::class => MultiSelectPromptRenderer::class,
ConfirmPrompt::class => ConfirmPromptRenderer::class,
PausePrompt::class => PausePromptRenderer::class,
SearchPrompt::class => SearchPromptRenderer::class,
MultiSearchPrompt::class => MultiSearchPromptRenderer::class,
SuggestPrompt::class => SuggestPromptRenderer::class,
Expand Down
46 changes: 46 additions & 0 deletions src/PausePrompt.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<?php

namespace Laravel\Prompts;

class PausePrompt extends Prompt
{
/**
* Whether the prompt has been confirmed.
*/
public bool $confirmed = false;

/**
* Create a new PausePrompt instance.
*/
public function __construct(
public string $body,
public string $title = '',
public string $info = 'ENTER to continue or Ctrl+C to cancel',
public bool|string $required = 'Please, press ENTER to continue or Ctrl+C to cancel.',
public string $hint = '',
) {
$this->validate = null;
$this->on('key', fn ($key) => match ($key) {
default => $this->onKey($key),
});
}

/**
* Check key pressed to allow to continue case it's enter
*/
public function onKey(string $key): void
{
if ($key === Key::ENTER) {
$this->confirmed = true;
}
$this->submit();
}

/**
* Get the value of the prompt.
*/
public function value(): bool
{
return $this->confirmed;
}
}
75 changes: 75 additions & 0 deletions src/Themes/Default/PausePromptRenderer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
<?php

namespace Laravel\Prompts\Themes\Default;

use Laravel\Prompts\PausePrompt;

class PausePromptRenderer extends Renderer
{
use Concerns\DrawsBoxes;

/**
* Render the pause prompt.
*/
public function __invoke(PausePrompt $prompt): string
{
return match ($prompt->state) {
'submit' => $this
->box(
$this->dim($this->truncate($prompt->title, $prompt->terminal()->cols() - 6)),
$this->renderBody($prompt),
),

'cancel' => $this
->box(
$this->truncate($prompt->title, $prompt->terminal()->cols() - 6),
$this->renderBody($prompt),
color: 'red',
)
->error('Cancelled.'),

'error' => $this
->box(
$this->truncate($prompt->title, $prompt->terminal()->cols() - 6),
$this->renderBody($prompt),
color: 'yellow',
info: $this->truncate($prompt->info, $prompt->terminal()->cols() - 15),
)
->warning($this->truncate($prompt->error, $prompt->terminal()->cols() - 5)),

default => $this
->box(
$this->cyan($this->truncate($prompt->title, $prompt->terminal()->cols() - 6)),
$this->renderBody($prompt),
info: $this->magenta($this->truncate($prompt->info, $prompt->terminal()->cols() - 15)),
)
->when(
$prompt->hint,
fn () => $this->hint($prompt->hint),
fn () => $this->newLine() // Space for errors
),
};
}

/**
* Render the pause body.
*/
protected function renderBody(PausePrompt $prompt): string
{
$maxRowCols = $prompt->terminal()->cols() - 6;
$rows = [];
$currentRow = '';
$wordsArray = explode(' ', $prompt->body);
while (count($wordsArray) > 0) {
$word = ' ' . $wordsArray[array_key_first($wordsArray)];
if (mb_strlen($currentRow) + mb_strlen($word) <= $maxRowCols) {
$currentRow .= $word;
unset($wordsArray[array_key_first($wordsArray)]);
} else {
$rows[] = $currentRow;
$currentRow = '';
}
}
return implode("\n", $rows);
}
}
8 changes: 8 additions & 0 deletions src/helpers.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,14 @@ function confirm(string $label, bool $default = true, string $yes = 'Yes', strin
return (new ConfirmPrompt(...func_get_args()))->prompt();
}

/**
* Prompt the user to continue or cancel after pause.
*/
function pause(string $body, string $title = '', string $info = 'ENTER to continue or Ctrl+C to cancel', bool|string $required = 'Please, press ENTER to continue or Ctrl+C to cancel.', string $hint = ''): bool
{
return (new PausePrompt(...func_get_args()))->prompt();
}

/**
* Prompt the user for text input with auto-completion.
*
Expand Down
63 changes: 63 additions & 0 deletions tests/Feature/PausePromptTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
<?php

use Laravel\Prompts\ConfirmPrompt;
use Laravel\Prompts\Exceptions\NonInteractiveValidationException;
use Laravel\Prompts\Key;
use Laravel\Prompts\PausePrompt;
use Laravel\Prompts\Prompt;

use function Laravel\Prompts\confirm;
use function Laravel\Prompts\pause;

it('continues', function () {
Prompt::fake([Key::ENTER]);

$result = pause('This is a fake content.');

expect($result)->toBeTrue();
});

it('allows the title to be changed', function () {
Prompt::fake([Key::ENTER]);

$result = pause(
'teste',
'Leia com atenção!',
);

expect($result)->toBeTrue();

Prompt::assertOutputContains('Leia com atenção!');
});


it('can fall back', function () {
Prompt::fallbackWhen(true);

PausePrompt::fallbackUsing(function (PausePrompt $prompt) {
expect($prompt->body)->toBe('This is a fake content.')
->and($prompt->title)
->toBe('Warning...');

return true;
});

$result = pause('This is a fake content.', 'Warning...', false);

expect($result)->toBeTrue();
});

it('returns the default value when non-interactive', function () {
Prompt::interactive(false);
pause('This is a fake content.');
})->throws(NonInteractiveValidationException::class, 'Please, press ENTER to continue or Ctrl+C to cancel.');

it('validates the default value when non-interactive', function () {
Prompt::interactive(false);

pause(
'This is a fake content.',
required: true,
);
})->throws(NonInteractiveValidationException::class, 'Required.');

0 comments on commit 3926f9e

Please sign in to comment.