Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 26 additions & 3 deletions src/Helper/OutputHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@
namespace Ahc\Cli\Helper;

use Ahc\Cli\Input\Argument;
use Ahc\Cli\Input\Command;
use Ahc\Cli\Input\Option;
use Ahc\Cli\Input\Parser as Command;
use Ahc\Cli\Input\Parameter;
use Ahc\Cli\Output\Writer;

/**
Expand All @@ -27,6 +28,8 @@ public function __construct(Writer $writer = null)

/**
* @param Argument[] $arguments
* @param string $header
* @param string $footer
*
* @return self
*/
Expand All @@ -39,6 +42,8 @@ public function showArgumentsHelp(array $arguments, string $header = '', string

/**
* @param Option[] $options
* @param string $header
* @param string $footer
*
* @return self
*/
Expand All @@ -50,7 +55,9 @@ public function showOptionsHelp(array $options, string $header = '', string $foo
}

/**
* @param Command[] $options
* @param Command[] $commands
* @param string $header
* @param string $footer
*
* @return self
*/
Expand All @@ -63,6 +70,14 @@ public function showCommandsHelp(array $commands, string $header = '', string $f

/**
* Show help with headers and footers.
*
* @param string $for
* @param array $items
* @param int $space
* @param string $header
* @param string $footer
*
* @return void
*/
protected function showHelp(string $for, array $items, int $space, string $header = '', string $footer = '')
{
Expand All @@ -80,7 +95,8 @@ protected function showHelp(string $for, array $items, int $space, string $heade

foreach ($this->sortItems($items, $padLen) as $item) {
$name = $this->getName($item);
$this->writer->bold(' ' . \str_pad($name, $padLen + $space))->comment($item->desc(), true);
$this->writer->bold(' ' . \str_pad($name, $padLen + $space));
$this->writer->comment($item->desc(), true);
}

if ($footer) {
Expand All @@ -90,13 +106,20 @@ protected function showHelp(string $for, array $items, int $space, string $heade

/**
* Sort items by name. As a side effect sets max length of all names.
*
* @param Parameter[]|Command[] $items
* @param int $max
*
* @return array
*/
protected function sortItems(array $items, &$max = 0): array
{
$first = reset($items);
$max = \strlen($first->name());

\uasort($items, function ($a, $b) use (&$max) {
/** @var Parameter $b */
/** @var Parameter $a */
$max = \max(\strlen($a->name()), \strlen($b->name()), $max);

return $a->name() <=> $b->name();
Expand Down
150 changes: 142 additions & 8 deletions src/IO/Interactor.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,144 @@
* @license MIT
*
* @link https://github.com/adhocore/cli
*
* @method Writer bgBlack($text, $eol = false)
* @method Writer bgBlue($text, $eol = false)
* @method Writer bgCyan($text, $eol = false)
* @method Writer bgGreen($text, $eol = false)
* @method Writer bgPurple($text, $eol = false)
* @method Writer bgRed($text, $eol = false)
* @method Writer bgWhite($text, $eol = false)
* @method Writer bgYellow($text, $eol = false)
* @method Writer black($text, $eol = false)
* @method Writer blackBgBlue($text, $eol = false)
* @method Writer blackBgCyan($text, $eol = false)
* @method Writer blackBgGreen($text, $eol = false)
* @method Writer blackBgPurple($text, $eol = false)
* @method Writer blackBgRed($text, $eol = false)
* @method Writer blackBgWhite($text, $eol = false)
* @method Writer blackBgYellow($text, $eol = false)
* @method Writer blue($text, $eol = false)
* @method Writer blueBgBlack($text, $eol = false)
* @method Writer blueBgCyan($text, $eol = false)
* @method Writer blueBgGreen($text, $eol = false)
* @method Writer blueBgPurple($text, $eol = false)
* @method Writer blueBgRed($text, $eol = false)
* @method Writer blueBgWhite($text, $eol = false)
* @method Writer blueBgYellow($text, $eol = false)
* @method Writer bold($text, $eol = false)
* @method Writer boldBlack($text, $eol = false)
* @method Writer boldBlackBgBlue($text, $eol = false)
* @method Writer boldBlackBgCyan($text, $eol = false)
* @method Writer boldBlackBgGreen($text, $eol = false)
* @method Writer boldBlackBgPurple($text, $eol = false)
* @method Writer boldBlackBgRed($text, $eol = false)
* @method Writer boldBlackBgWhite($text, $eol = false)
* @method Writer boldBlackBgYellow($text, $eol = false)
* @method Writer boldBlue($text, $eol = false)
* @method Writer boldBlueBgBlack($text, $eol = false)
* @method Writer boldBlueBgCyan($text, $eol = false)
* @method Writer boldBlueBgGreen($text, $eol = false)
* @method Writer boldBlueBgPurple($text, $eol = false)
* @method Writer boldBlueBgRed($text, $eol = false)
* @method Writer boldBlueBgWhite($text, $eol = false)
* @method Writer boldBlueBgYellow($text, $eol = false)
* @method Writer boldCyan($text, $eol = false)
* @method Writer boldCyanBgBlack($text, $eol = false)
* @method Writer boldCyanBgBlue($text, $eol = false)
* @method Writer boldCyanBgGreen($text, $eol = false)
* @method Writer boldCyanBgPurple($text, $eol = false)
* @method Writer boldCyanBgRed($text, $eol = false)
* @method Writer boldCyanBgWhite($text, $eol = false)
* @method Writer boldCyanBgYellow($text, $eol = false)
* @method Writer boldGreen($text, $eol = false)
* @method Writer boldGreenBgBlack($text, $eol = false)
* @method Writer boldGreenBgBlue($text, $eol = false)
* @method Writer boldGreenBgCyan($text, $eol = false)
* @method Writer boldGreenBgPurple($text, $eol = false)
* @method Writer boldGreenBgRed($text, $eol = false)
* @method Writer boldGreenBgWhite($text, $eol = false)
* @method Writer boldGreenBgYellow($text, $eol = false)
* @method Writer boldPurple($text, $eol = false)
* @method Writer boldPurpleBgBlack($text, $eol = false)
* @method Writer boldPurpleBgBlue($text, $eol = false)
* @method Writer boldPurpleBgCyan($text, $eol = false)
* @method Writer boldPurpleBgGreen($text, $eol = false)
* @method Writer boldPurpleBgRed($text, $eol = false)
* @method Writer boldPurpleBgWhite($text, $eol = false)
* @method Writer boldPurpleBgYellow($text, $eol = false)
* @method Writer boldRed($text, $eol = false)
* @method Writer boldRedBgBlack($text, $eol = false)
* @method Writer boldRedBgBlue($text, $eol = false)
* @method Writer boldRedBgCyan($text, $eol = false)
* @method Writer boldRedBgGreen($text, $eol = false)
* @method Writer boldRedBgPurple($text, $eol = false)
* @method Writer boldRedBgWhite($text, $eol = false)
* @method Writer boldRedBgYellow($text, $eol = false)
* @method Writer boldWhite($text, $eol = false)
* @method Writer boldWhiteBgBlack($text, $eol = false)
* @method Writer boldWhiteBgBlue($text, $eol = false)
* @method Writer boldWhiteBgCyan($text, $eol = false)
* @method Writer boldWhiteBgGreen($text, $eol = false)
* @method Writer boldWhiteBgPurple($text, $eol = false)
* @method Writer boldWhiteBgRed($text, $eol = false)
* @method Writer boldWhiteBgYellow($text, $eol = false)
* @method Writer boldYellow($text, $eol = false)
* @method Writer boldYellowBgBlack($text, $eol = false)
* @method Writer boldYellowBgBlue($text, $eol = false)
* @method Writer boldYellowBgCyan($text, $eol = false)
* @method Writer boldYellowBgGreen($text, $eol = false)
* @method Writer boldYellowBgPurple($text, $eol = false)
* @method Writer boldYellowBgRed($text, $eol = false)
* @method Writer boldYellowBgWhite($text, $eol = false)
* @method Writer colors($text)
* @method Writer comment($text, $eol = false)
* @method Writer cyan($text, $eol = false)
* @method Writer cyanBgBlack($text, $eol = false)
* @method Writer cyanBgBlue($text, $eol = false)
* @method Writer cyanBgGreen($text, $eol = false)
* @method Writer cyanBgPurple($text, $eol = false)
* @method Writer cyanBgRed($text, $eol = false)
* @method Writer cyanBgWhite($text, $eol = false)
* @method Writer cyanBgYellow($text, $eol = false)
* @method Writer eol(int $n = 1)
* @method Writer error($text, $eol = false)
* @method Writer green($text, $eol = false)
* @method Writer greenBgBlack($text, $eol = false)
* @method Writer greenBgBlue($text, $eol = false)
* @method Writer greenBgCyan($text, $eol = false)
* @method Writer greenBgPurple($text, $eol = false)
* @method Writer greenBgRed($text, $eol = false)
* @method Writer greenBgWhite($text, $eol = false)
* @method Writer greenBgYellow($text, $eol = false)
* @method Writer info($text, $eol = false)
* @method Writer ok($text, $eol = false)
* @method Writer purple($text, $eol = false)
* @method Writer purpleBgBlack($text, $eol = false)
* @method Writer purpleBgBlue($text, $eol = false)
* @method Writer purpleBgCyan($text, $eol = false)
* @method Writer purpleBgGreen($text, $eol = false)
* @method Writer purpleBgRed($text, $eol = false)
* @method Writer purpleBgWhite($text, $eol = false)
* @method Writer purpleBgYellow($text, $eol = false)
* @method Writer red($text, $eol = false)
* @method Writer redBgBlack($text, $eol = false)
* @method Writer redBgBlue($text, $eol = false)
* @method Writer redBgCyan($text, $eol = false)
* @method Writer redBgGreen($text, $eol = false)
* @method Writer redBgPurple($text, $eol = false)
* @method Writer redBgWhite($text, $eol = false)
* @method Writer redBgYellow($text, $eol = false)
* @method Writer warn($text, $eol = false)
* @method Writer white($text, $eol = false)
* @method Writer yellow($text, $eol = false)
* @method Writer yellowBgBlack($text, $eol = false)
* @method Writer yellowBgBlue($text, $eol = false)
* @method Writer yellowBgCyan($text, $eol = false)
* @method Writer yellowBgGreen($text, $eol = false)
* @method Writer yellowBgPurple($text, $eol = false)
* @method Writer yellowBgRed($text, $eol = false)
* @method Writer yellowBgWhite($text, $eol = false)
*/
class Interactor
{
Expand Down Expand Up @@ -142,7 +280,7 @@ public function prompt(string $text, $default = null, callable $fn = null, int $
$error = $e->getMessage();
}

if ($retry > 0 && (isset($e) || \strlen($input) === 0)) {
if ($retry > 0 && (isset($e) || \strlen($input ?? '') === 0)) {
$this->writer->bgRed($error, true);

return $this->prompt($text, $default, $fn, $retry - 1);
Expand Down Expand Up @@ -190,17 +328,13 @@ protected function listOptions(array $choices, $default = null, bool $multi = fa
protected function promptOptions(array $choices, $default): self
{
$options = '';
$color = $this->writer->colorizer();

foreach ($choices as $choice) {
if (\in_array($choice, (array) $default)) {
$options .= '/' . $color->boldCyan($choice);
} else {
$options .= '/' . $color->cyan($choice);
}
$style = \in_array($choice, (array) $default) ? 'boldCyan' : 'cyan';
$options .= "/<$style>$choice</end>";
}

$this->writer->raw(' (' . ltrim($options, '/') . '): ');
$this->writer->colors(" ($options): ");

return $this;
}
Expand Down
45 changes: 28 additions & 17 deletions src/Input/Command.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

namespace Ahc\Cli\Input;

use Ahc\Cli\Application;
use Ahc\Cli\Application as App;
use Ahc\Cli\Helper\InflectsString;
use Ahc\Cli\Helper\OutputHelper;
use Ahc\Cli\IO\Interactor;
Expand Down Expand Up @@ -35,7 +35,7 @@ class Command extends Parser
/** @var string */
protected $_usage;

/** @var Application The cli app this command is bound to */
/** @var App The cli app this command is bound to */
protected $_app;

/** @var callable[] Events for options */
Expand All @@ -53,8 +53,9 @@ class Command extends Parser
* @param string $name
* @param string $desc
* @param bool $allowUnknown
* @param App $app
*/
public function __construct(string $name, string $desc = '', bool $allowUnknown = false, Application $app = null)
public function __construct(string $name, string $desc = '', bool $allowUnknown = false, App $app = null)
{
$this->_name = $name;
$this->_desc = $desc;
Expand All @@ -67,14 +68,14 @@ public function __construct(string $name, string $desc = '', bool $allowUnknown
/**
* Sets default options, actions and exit handler.
*
* @return void
* @return self
*/
protected function defaults(): self
{
$this->option('-h, --help', 'Show help')->on([$this, 'showHelp']);
$this->option('-V, --version', 'Show version')->on([$this, 'showVersion']);
$this->option('-v, --verbosity', 'Verbosity level', null, 0)->on(function () {
$this->set('verbosity', $this->verbosity + 1);
$this->set('verbosity', ($this->verbosity ?? 0) + 1);

return false;
});
Expand Down Expand Up @@ -125,7 +126,7 @@ public function desc(): string
/**
* Get the app this command belongs to.
*
* @return null|Application
* @return null|App
*/
public function app()
{
Expand All @@ -135,11 +136,11 @@ public function app()
/**
* Bind command to the app.
*
* @param Application|null $app
* @param App|null $app
*
* @return self
*/
public function bind(Application $app = null): self
public function bind(App $app = null): self
{
$this->_app = $app;

Expand Down Expand Up @@ -212,7 +213,7 @@ public function option(string $raw, string $desc = '', callable $filter = null,
/**
* Gets user options (i.e without defaults).
*
* @return string
* @return array
*/
public function userOptions(): array
{
Expand Down Expand Up @@ -301,20 +302,20 @@ protected function handleUnknown(string $arg, string $value = null)
*/
public function showHelp()
{
$writer = $this->writer();
$helper = new OutputHelper($writer);
$io = $this->io();
$helper = new OutputHelper($io->writer());

$writer
->bold("Command {$this->_name}, version {$this->_version}", true)->eol()
->comment($this->_desc, true)->eol()
->bold('Usage: ')->yellow("{$this->_name} [OPTIONS...] [ARGUMENTS...]", true);
$io->bold("Command {$this->_name}, version {$this->_version}", true)->eol();
$io->comment($this->_desc, true)->eol();
$io->bold('Usage: ')->yellow("{$this->_name} [OPTIONS...] [ARGUMENTS...]", true);

$helper
->showArgumentsHelp($this->allArguments())
->showOptionsHelp($this->allOptions(), '', 'Legend: <required> [optional]');

if ($this->_usage) {
$writer->eol()->greenBold('Usage Examples:', true)->raw(\trim($this->_usage))->eol();
$io->eol();
$io->boldGreen('Usage Examples:', true)->raw(\trim($this->_usage))->eol();
}

return $this->emit('_exit', 0);
Expand All @@ -338,7 +339,7 @@ public function showVersion()
public function emit(string $event, $value = null)
{
if (empty($this->_events[$event])) {
return;
return null;
}

return ($this->_events[$event])($value);
Expand Down Expand Up @@ -395,4 +396,14 @@ protected function writer(): Writer
{
return $this->_app ? $this->_app->io()->writer() : new Writer;
}

/**
* Get IO instance.
*
* @return Interactor
*/
protected function io(): Interactor
{
return $this->_app ? $this->_app->io() : new Interactor;
}
}
2 changes: 2 additions & 0 deletions src/Input/Option.php
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ public function short(): string
/**
* Test if this option matches given arg.
*
* @param string $arg
*
* @return bool
*/
public function is(string $arg): bool
Expand Down
Loading