Skip to content

Commit

Permalink
Helper for Progress bar
Browse files Browse the repository at this point in the history
  • Loading branch information
SmetDenis committed Nov 8, 2021
1 parent 1f584a7 commit 498764f
Show file tree
Hide file tree
Showing 9 changed files with 971 additions and 80 deletions.
2 changes: 1 addition & 1 deletion composer.json
Expand Up @@ -29,7 +29,7 @@
},

"require-dev" : {
"jbzoo/toolbox-dev" : "^3.0.0"
"jbzoo/toolbox-dev" : "^3.1.0"
},

"autoload" : {
Expand Down
84 changes: 9 additions & 75 deletions src/CliCommand.php
Expand Up @@ -17,7 +17,6 @@

namespace JBZoo\Cli;

use DateTimeInterface;
use JBZoo\Utils\Arr;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
Expand Down Expand Up @@ -48,28 +47,23 @@ abstract class CliCommand extends Command
protected $input;

/**
* @var OutputInterface
* @var OutputInterface|ConsoleOutput
* @psalm-suppress PropertyNotSetInConstructor
*/
protected $output;

/**
* @var OutputInterface
*/
private $errOutput;

/**
* @var bool
*/
private $outputHasErrors = false;

protected $errOutput;

/**
* @inheritDoc
*/
protected function configure(): void
{
$this
->addOption('no-progress', 'p', InputOption::VALUE_NONE, "Disable progress bar rendering")
->addOption(
'mute-errors',
null,
Expand Down Expand Up @@ -98,15 +92,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int
$this->helper = new CliHelper($input, $output);
$this->input = $this->helper->getInput();
$this->output = $this->helper->getOutput();

if ($this->getOptBool('stdout-only')) {
$this->errOutput = $this->helper->getOutput();
if ($this->output instanceof ConsoleOutput) {
$this->output->setErrorOutput($this->output);
}
} else {
$this->errOutput = $this->helper->getErrOutput();
}
$this->errOutput = $this->helper->getErrOutput();

$exitCode = 0;
try {
Expand All @@ -123,7 +109,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int
}
}

if ($this->outputHasErrors && $this->getOptBool('strict')) {
if ($this->helper->isOutputHasErrors() && $this->getOptBool('strict')) {
$exitCode = 1;
}

Expand All @@ -134,6 +120,8 @@ protected function execute(InputInterface $input, OutputInterface $output): int
$exitCode = 0;
}

$this->_("Exit Code is \"{$exitCode}\"", 'debug');

return $exitCode;
}

Expand Down Expand Up @@ -232,67 +220,13 @@ protected static function getStdIn(): ?string
*
* @param string|array $messages
* @param string $verboseLevel
* @param bool $newline
* @return void
*
* @SuppressWarnings(PHPMD.CamelCaseMethodName)
*/
protected function _($messages, string $verboseLevel = '', bool $newline = true): void
protected function _($messages, string $verboseLevel = ''): void
{
$verboseLevel = \strtolower(\trim($verboseLevel));

if (is_array($messages)) {
foreach ($messages as $message) {
$this->_($message, $verboseLevel, $newline);
}
return;
}

$profilePrefix = '';

if ($this->getOptBool('timestamp')) {
$timestamp = (new \DateTimeImmutable())->format(DateTimeInterface::RFC3339);
$profilePrefix .= "<green>[</green>{$timestamp}<green>]</green> ";
}

if ($this->isProfile()) {
[$totalTime, $curMemory] = $this->helper->getProfileDate();
$profilePrefix .= "<green>[</green>{$curMemory}<green>/</green>{$totalTime}s<green>]</green> ";
}

if ($verboseLevel === '') {
$this->output->write($profilePrefix . $messages, $newline, OutputInterface::VERBOSITY_NORMAL);
} elseif ($verboseLevel === 'v') {
$this->output->write($profilePrefix . $messages, $newline, OutputInterface::VERBOSITY_VERBOSE);
} elseif ($verboseLevel === 'vv') {
$this->output->write($profilePrefix . $messages, $newline, OutputInterface::VERBOSITY_VERY_VERBOSE);
} elseif ($verboseLevel === 'vvv') {
$this->output->write($profilePrefix . $messages, $newline, OutputInterface::VERBOSITY_DEBUG);
} elseif ($verboseLevel === 'q') { // Show ALWAYS!
$this->output->write($profilePrefix . $messages, $newline, OutputInterface::VERBOSITY_QUIET);
} elseif ($verboseLevel === 'debug') {
$this->_('<magenta>Debug:</magenta> ' . $messages, 'vvv', $newline);
} elseif ($verboseLevel === 'warning') {
$this->_('<yellow>Warning:</yellow> ' . $messages, 'vv', $newline);
} elseif ($verboseLevel === 'info') {
$this->_('<blue>Info:</blue> ' . $messages, 'v', $newline);
} elseif ($verboseLevel === 'error') {
$this->outputHasErrors = true;
$this->errOutput->write(
$profilePrefix . '<bg-red>Error:</bg-red> ' . $messages,
$newline,
OutputInterface::VERBOSITY_NORMAL
);
} elseif ($verboseLevel === 'exception') {
$this->outputHasErrors = true;
$this->errOutput->write(
$profilePrefix . '<bg-red>Exception:</bg-red> ' . $messages,
$newline,
OutputInterface::VERBOSITY_NORMAL
);
} else {
throw new Exception("Undefined mode: \"{$verboseLevel}\"");
}
$this->helper->_($messages, $verboseLevel);
}

/**
Expand Down
131 changes: 127 additions & 4 deletions src/CliHelper.php
Expand Up @@ -18,9 +18,10 @@
namespace JBZoo\Cli;

use JBZoo\Utils\Env;
use JBZoo\Utils\Sys;
use JBZoo\Utils\FS;
use Symfony\Component\Console\Formatter\OutputFormatterStyle;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\ConsoleOutput;
use Symfony\Component\Console\Output\ConsoleOutputInterface;
use Symfony\Component\Console\Output\OutputInterface;

Expand Down Expand Up @@ -55,6 +56,11 @@ class CliHelper
*/
private $startTimer;

/**
* @var bool
*/
private $outputHasErrors = false;

/**
* @param InputInterface $input
* @param OutputInterface $output
Expand All @@ -66,7 +72,16 @@ public function __construct(InputInterface $input, OutputInterface $output)
$this->output = self::addOutputStyles($output);

$errOutput = $output instanceof ConsoleOutputInterface ? $output->getErrorOutput() : $output;
$this->errOutput = self::addOutputStyles($errOutput);
$errOutput = self::addOutputStyles($errOutput);

if ($this->input->getOption('stdout-only')) {
$this->errOutput = $this->output;
if ($this->output instanceof ConsoleOutput) {
$this->output->setErrorOutput($this->output);
}
} else {
$this->errOutput = $errOutput;
}

self::$instance = $this;
}
Expand Down Expand Up @@ -157,8 +172,116 @@ public function getProfileDate(): array
{
return [
number_format(microtime(true) - $this->startTimer, 3),
Sys::getMemory(false),
Sys::getMemory(true)
FS::format(memory_get_usage(false)),
FS::format(memory_get_peak_usage(false)),
];
}

/**
* Alias to write new line in std output
*
* @param string|array $messages
* @param string $verboseLevel
* @return void
*
* @SuppressWarnings(PHPMD.CamelCaseMethodName)
*/
public function _($messages, string $verboseLevel = ''): void
{
$verboseLevel = \strtolower(\trim($verboseLevel));

if (is_array($messages)) {
foreach ($messages as $message) {
$this->_($message, $verboseLevel);
}
return;
}

$profilePrefix = '';

if ($this->input->getOption('timestamp')) {
$timestamp = (new \DateTimeImmutable())->format(\DateTimeInterface::RFC3339);
$profilePrefix .= "<green>[</green>{$timestamp}<green>]</green> ";
}

if ($this->input->getOption('profile')) {
[$totalTime, $curMemory] = $this->getProfileDate();
$profilePrefix .= "<green>[</green>{$curMemory}<green>/</green>{$totalTime}s<green>]</green> ";
}

$vNormal = OutputInterface::VERBOSITY_NORMAL;

if ($verboseLevel === '') {
$this->output->writeln($profilePrefix . $messages, $vNormal);
} elseif ($verboseLevel === 'v') {
$this->output->writeln($profilePrefix . $messages, OutputInterface::VERBOSITY_VERBOSE);
} elseif ($verboseLevel === 'vv') {
$this->output->writeln($profilePrefix . $messages, OutputInterface::VERBOSITY_VERY_VERBOSE);
} elseif ($verboseLevel === 'vvv') {
$this->output->writeln($profilePrefix . $messages, OutputInterface::VERBOSITY_DEBUG);
} elseif ($verboseLevel === 'q') {
$this->output->writeln($profilePrefix . $messages, OutputInterface::VERBOSITY_QUIET); // Show ALWAYS!
} elseif ($verboseLevel === 'debug') {
$this->_('<magenta>Debug:</magenta> ' . $messages, 'vvv');
} elseif ($verboseLevel === 'warning') {
$this->_('<yellow>Warning:</yellow> ' . $messages, 'vv');
} elseif ($verboseLevel === 'info') {
$this->_('<blue>Info:</blue> ' . $messages, 'v');
} elseif ($verboseLevel === 'error') {
$this->outputHasErrors = true;
$this->errOutput->writeln($profilePrefix . '<bg-red>Error:</bg-red> ' . $messages, $vNormal);
} elseif ($verboseLevel === 'exception') {
$this->outputHasErrors = true;
$this->errOutput->writeln($profilePrefix . '<bg-red>Exception:</bg-red> ' . $messages, $vNormal);
} else {
throw new Exception("Undefined verbose level: \"{$verboseLevel}\"");
}
}

/**
* @return bool
*/
public function isOutputHasErrors(): bool
{
return $this->outputHasErrors;
}

/**
* @param array $items
* @return int
*/
public static function findMaxLength(array $items): int
{
$result = 0;
foreach ($items as $item) {
$tmpMax = strlen($item);
if ($result < $tmpMax) {
$result = $tmpMax;
}
}

return $result;
}

/**
* @param array $metrics
* @return string
*/
public static function renderList(array $metrics): string
{
$maxLength = self::findMaxLength(array_keys($metrics));
$lines = [];

foreach ($metrics as $metricKey => $metricTmpl) {
$currentLength = strlen($metricKey);
$lines[] = implode('', [
$metricKey,
str_repeat(' ', $maxLength - $currentLength),
': ',
implode('; ', (array)$metricTmpl)
]);
}

return implode("\n", array_filter($lines)) . "\n";
}
}

0 comments on commit 498764f

Please sign in to comment.