Adapted project file structure to conform with composer standards.
This commit is contained in:
parent
4720c49a85
commit
9c90879777
|
|
@ -1,31 +0,0 @@
|
|||
{
|
||||
"name": "danmaku/console-writer",
|
||||
"type": "library",
|
||||
"description": "Easily adaptable console input/output writer for Symfony.",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Marvin Schreurs",
|
||||
"email": "fristi@danmaku.moe",
|
||||
"homepage": "https://fristi.danmaku.moe",
|
||||
"role": "Developer"
|
||||
}
|
||||
],
|
||||
"support": {
|
||||
"email": "fristi@danmaku.moe"
|
||||
},
|
||||
"keywords": [
|
||||
"console",
|
||||
"symfony"
|
||||
],
|
||||
"license": "MIT",
|
||||
"minimum-stability": "dev",
|
||||
"require": {
|
||||
"php": ">=7.2.0",
|
||||
"symfony/console": "^4.2"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Danmaku\\Console\\": "src/Console"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,485 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* InheritableQuestionHelper class source file.
|
||||
*
|
||||
* Contains the source code of the InheritableQuestionHelper class.
|
||||
*
|
||||
* PHP version 7.2
|
||||
*
|
||||
* @package Danmaku\Console\Helper
|
||||
* @author Marvin Schreurs <fristi@danmaku.moe>
|
||||
*/
|
||||
|
||||
namespace Danmaku\Console\Helper;
|
||||
|
||||
|
||||
use Symfony\Component\Console\Exception\RuntimeException;
|
||||
use Symfony\Component\Console\Formatter\OutputFormatter;
|
||||
use Symfony\Component\Console\Formatter\OutputFormatterStyle;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\StreamableInputInterface;
|
||||
use Symfony\Component\Console\Output\ConsoleOutputInterface;
|
||||
use Symfony\Component\Console\Output\ConsoleSectionOutput;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Question\ChoiceQuestion;
|
||||
use Symfony\Component\Console\Question\Question;
|
||||
|
||||
/**
|
||||
* Class InheritableQuestionHelper
|
||||
*
|
||||
* @package Danmaku\Console\Helper
|
||||
* @author Marvin Schreurs <fristi@danmaku.moe>
|
||||
*/
|
||||
class InheritableQuestionHelper extends \Symfony\Component\Console\Helper\QuestionHelper
|
||||
{
|
||||
protected $inputStream;
|
||||
protected static $shell;
|
||||
protected static $stty;
|
||||
|
||||
/**
|
||||
* Asks a question to the user.
|
||||
*
|
||||
* @return mixed The user answer
|
||||
*
|
||||
* @throws RuntimeException If there is no data to read in the input stream
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function ask(InputInterface $input, OutputInterface $output, Question $question)
|
||||
{
|
||||
if ($output instanceof ConsoleOutputInterface) {
|
||||
$output = $output->getErrorOutput();
|
||||
}
|
||||
|
||||
if (!$input->isInteractive()) {
|
||||
$default = $question->getDefault();
|
||||
|
||||
if (null === $default) {
|
||||
return $default;
|
||||
}
|
||||
|
||||
if ($validator = $question->getValidator()) {
|
||||
return \call_user_func($question->getValidator(), $default);
|
||||
} elseif ($question instanceof ChoiceQuestion) {
|
||||
$choices = $question->getChoices();
|
||||
|
||||
if (!$question->isMultiselect()) {
|
||||
return isset($choices[$default]) ? $choices[$default] : $default;
|
||||
}
|
||||
|
||||
$default = explode(',', $default);
|
||||
foreach ($default as $k => $v) {
|
||||
$v = trim($v);
|
||||
$default[$k] = isset($choices[$v]) ? $choices[$v] : $v;
|
||||
}
|
||||
}
|
||||
|
||||
return $default;
|
||||
}
|
||||
|
||||
if ($input instanceof StreamableInputInterface && $stream = $input->getStream()) {
|
||||
$this->inputStream = $stream;
|
||||
}
|
||||
|
||||
if (!$question->getValidator()) {
|
||||
return $this->doAsk($output, $question);
|
||||
}
|
||||
|
||||
$interviewer = function () use ($output, $question) {
|
||||
return $this->doAsk($output, $question);
|
||||
};
|
||||
|
||||
return $this->validateAttempts($interviewer, $output, $question);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return 'question';
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevents usage of stty.
|
||||
*/
|
||||
public static function disableStty()
|
||||
{
|
||||
static::$stty = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Asks the question to the user.
|
||||
*
|
||||
* @return bool|mixed|string|null
|
||||
*
|
||||
* @throws RuntimeException In case the fallback is deactivated and the response cannot be hidden
|
||||
*/
|
||||
protected function doAsk(OutputInterface $output, Question $question)
|
||||
{
|
||||
$this->writePrompt($output, $question);
|
||||
|
||||
$inputStream = $this->inputStream ?: STDIN;
|
||||
$autocomplete = $question->getAutocompleterCallback();
|
||||
|
||||
if (null === $autocomplete || !$this->hasSttyAvailable()) {
|
||||
$ret = false;
|
||||
if ($question->isHidden()) {
|
||||
try {
|
||||
$ret = trim($this->getHiddenResponse($output, $inputStream));
|
||||
} catch (RuntimeException $e) {
|
||||
if (!$question->isHiddenFallback()) {
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (false === $ret) {
|
||||
$ret = fgets($inputStream, 4096);
|
||||
if (false === $ret) {
|
||||
throw new RuntimeException('Aborted.');
|
||||
}
|
||||
$ret = trim($ret);
|
||||
}
|
||||
} else {
|
||||
$ret = trim($this->autocomplete($output, $question, $inputStream, $autocomplete));
|
||||
}
|
||||
|
||||
if ($output instanceof ConsoleSectionOutput) {
|
||||
$output->addContent($ret);
|
||||
}
|
||||
|
||||
$ret = \strlen($ret) > 0 ? $ret : $question->getDefault();
|
||||
|
||||
if ($normalizer = $question->getNormalizer()) {
|
||||
return $normalizer($ret);
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Outputs the question prompt.
|
||||
*/
|
||||
protected function writePrompt(OutputInterface $output, Question $question)
|
||||
{
|
||||
$message = $question->getQuestion();
|
||||
|
||||
if ($question instanceof ChoiceQuestion) {
|
||||
$maxWidth = max(array_map([$this, 'strlen'], array_keys($question->getChoices())));
|
||||
|
||||
$messages = (array) $question->getQuestion();
|
||||
foreach ($question->getChoices() as $key => $value) {
|
||||
$width = $maxWidth - $this->strlen($key);
|
||||
$messages[] = ' [<info>'.$key.str_repeat(' ', $width).'</info>] '.$value;
|
||||
}
|
||||
|
||||
$output->writeln($messages);
|
||||
|
||||
$message = $question->getPrompt();
|
||||
}
|
||||
|
||||
$output->write($message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Outputs an error message.
|
||||
*/
|
||||
protected function writeError(OutputInterface $output, \Exception $error)
|
||||
{
|
||||
if (null !== $this->getHelperSet() && $this->getHelperSet()->has('formatter')) {
|
||||
$message = $this->getHelperSet()->get('formatter')->formatBlock($error->getMessage(), 'error');
|
||||
} else {
|
||||
$message = '<error>'.$error->getMessage().'</error>';
|
||||
}
|
||||
|
||||
$output->writeln($message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Autocompletes a question.
|
||||
*
|
||||
* @param resource $inputStream
|
||||
* @return string
|
||||
*/
|
||||
private function autocomplete(OutputInterface $output, Question $question, $inputStream, callable $autocomplete): string
|
||||
{
|
||||
$fullChoice = '';
|
||||
$ret = '';
|
||||
|
||||
$i = 0;
|
||||
$ofs = -1;
|
||||
$matches = $autocomplete($ret);
|
||||
$numMatches = \count($matches);
|
||||
|
||||
$sttyMode = shell_exec('stty -g');
|
||||
|
||||
// Disable icanon (so we can fread each keypress) and echo (we'll do echoing here instead)
|
||||
shell_exec('stty -icanon -echo');
|
||||
|
||||
// Add highlighted text style
|
||||
$output->getFormatter()->setStyle('hl', new OutputFormatterStyle('black', 'white'));
|
||||
|
||||
// Read a keypress
|
||||
while (!feof($inputStream)) {
|
||||
$c = fread($inputStream, 1);
|
||||
|
||||
// as opposed to fgets(), fread() returns an empty string when the stream content is empty, not false.
|
||||
if (false === $c || ('' === $ret && '' === $c && null === $question->getDefault())) {
|
||||
shell_exec(sprintf('stty %s', $sttyMode));
|
||||
throw new RuntimeException('Aborted.');
|
||||
} elseif ("\177" === $c) { // Backspace Character
|
||||
if (0 === $numMatches && 0 !== $i) {
|
||||
--$i;
|
||||
$fullChoice = substr($fullChoice, 0, -1);
|
||||
// Move cursor backwards
|
||||
$output->write("\033[1D");
|
||||
}
|
||||
|
||||
if (0 === $i) {
|
||||
$ofs = -1;
|
||||
$matches = $autocomplete($ret);
|
||||
$numMatches = \count($matches);
|
||||
} else {
|
||||
$numMatches = 0;
|
||||
}
|
||||
|
||||
// Pop the last character off the end of our string
|
||||
$ret = substr($ret, 0, $i);
|
||||
} elseif ("\033" === $c) {
|
||||
// Did we read an escape sequence?
|
||||
$c .= fread($inputStream, 2);
|
||||
|
||||
// A = Up Arrow. B = Down Arrow
|
||||
if (isset($c[2]) && ('A' === $c[2] || 'B' === $c[2])) {
|
||||
if ('A' === $c[2] && -1 === $ofs) {
|
||||
$ofs = 0;
|
||||
}
|
||||
|
||||
if (0 === $numMatches) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$ofs += ('A' === $c[2]) ? -1 : 1;
|
||||
$ofs = ($numMatches + $ofs) % $numMatches;
|
||||
}
|
||||
} elseif (\ord($c) < 32) {
|
||||
if ("\t" === $c || "\n" === $c) {
|
||||
if ($numMatches > 0 && -1 !== $ofs) {
|
||||
$ret = (string) $matches[$ofs];
|
||||
// Echo out remaining chars for current match
|
||||
$remainingCharacters = substr($ret, \strlen(trim($this->mostRecentlyEnteredValue($fullChoice))));
|
||||
$output->write($remainingCharacters);
|
||||
$fullChoice .= $remainingCharacters;
|
||||
$i = \strlen($fullChoice);
|
||||
|
||||
$matches = array_filter(
|
||||
$autocomplete($ret),
|
||||
function ($match) use ($ret) {
|
||||
return '' === $ret || 0 === strpos($match, $ret);
|
||||
}
|
||||
);
|
||||
$numMatches = \count($matches);
|
||||
$ofs = -1;
|
||||
}
|
||||
|
||||
if ("\n" === $c) {
|
||||
$output->write($c);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
continue;
|
||||
} else {
|
||||
if ("\x80" <= $c) {
|
||||
$c .= fread($inputStream, ["\xC0" => 1, "\xD0" => 1, "\xE0" => 2, "\xF0" => 3][$c & "\xF0"]);
|
||||
}
|
||||
|
||||
$output->write($c);
|
||||
$ret .= $c;
|
||||
$fullChoice .= $c;
|
||||
++$i;
|
||||
|
||||
$tempRet = $ret;
|
||||
|
||||
if ($question instanceof ChoiceQuestion && $question->isMultiselect()) {
|
||||
$tempRet = $this->mostRecentlyEnteredValue($fullChoice);
|
||||
}
|
||||
|
||||
$numMatches = 0;
|
||||
$ofs = 0;
|
||||
|
||||
foreach ($autocomplete($ret) as $value) {
|
||||
// If typed characters match the beginning chunk of value (e.g. [AcmeDe]moBundle)
|
||||
if (0 === strpos($value, $tempRet)) {
|
||||
$matches[$numMatches++] = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Erase characters from cursor to end of line
|
||||
$output->write("\033[K");
|
||||
|
||||
if ($numMatches > 0 && -1 !== $ofs) {
|
||||
// Save cursor position
|
||||
$output->write("\0337");
|
||||
// Write highlighted text, complete the partially entered response
|
||||
$charactersEntered = \strlen(trim($this->mostRecentlyEnteredValue($fullChoice)));
|
||||
$output->write('<hl>'.OutputFormatter::escapeTrailingBackslash(substr($matches[$ofs], $charactersEntered)).'</hl>');
|
||||
// Restore cursor position
|
||||
$output->write("\0338");
|
||||
}
|
||||
}
|
||||
|
||||
// Reset stty so it behaves normally again
|
||||
shell_exec(sprintf('stty %s', $sttyMode));
|
||||
|
||||
return $fullChoice;
|
||||
}
|
||||
|
||||
private function mostRecentlyEnteredValue($entered)
|
||||
{
|
||||
// Determine the most recent value that the user entered
|
||||
if (false === strpos($entered, ',')) {
|
||||
return $entered;
|
||||
}
|
||||
|
||||
$choices = explode(',', $entered);
|
||||
if (\strlen($lastChoice = trim($choices[\count($choices) - 1])) > 0) {
|
||||
return $lastChoice;
|
||||
}
|
||||
|
||||
return $entered;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a hidden response from user.
|
||||
*
|
||||
* @param OutputInterface $output An Output instance
|
||||
* @param resource $inputStream The handler resource
|
||||
*
|
||||
* @return string
|
||||
* @throws RuntimeException In case the fallback is deactivated and the response cannot be hidden
|
||||
*/
|
||||
private function getHiddenResponse(OutputInterface $output, $inputStream): string
|
||||
{
|
||||
if ('\\' === \DIRECTORY_SEPARATOR) {
|
||||
$exe = __DIR__.'/../Resources/bin/hiddeninput.exe';
|
||||
|
||||
// handle code running from a phar
|
||||
if ('phar:' === substr(__FILE__, 0, 5)) {
|
||||
$tmpExe = sys_get_temp_dir().'/hiddeninput.exe';
|
||||
copy($exe, $tmpExe);
|
||||
$exe = $tmpExe;
|
||||
}
|
||||
|
||||
$value = rtrim(shell_exec($exe));
|
||||
$output->writeln('');
|
||||
|
||||
if (isset($tmpExe)) {
|
||||
unlink($tmpExe);
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
if ($this->hasSttyAvailable()) {
|
||||
$sttyMode = shell_exec('stty -g');
|
||||
|
||||
shell_exec('stty -echo');
|
||||
$value = fgets($inputStream, 4096);
|
||||
shell_exec(sprintf('stty %s', $sttyMode));
|
||||
|
||||
if (false === $value) {
|
||||
throw new RuntimeException('Aborted.');
|
||||
}
|
||||
|
||||
$value = trim($value);
|
||||
$output->writeln('');
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
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));
|
||||
$output->writeln('');
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
throw new RuntimeException('Unable to hide the response.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates an attempt.
|
||||
*
|
||||
* @param callable $interviewer A callable that will ask for a question and return the result
|
||||
* @param OutputInterface $output An Output instance
|
||||
* @param Question $question A Question instance
|
||||
*
|
||||
* @return mixed The validated response
|
||||
*
|
||||
* @throws \Exception In case the max number of attempts has been reached and no valid response has been given
|
||||
*/
|
||||
protected function validateAttempts(callable $interviewer, OutputInterface $output, Question $question)
|
||||
{
|
||||
$error = null;
|
||||
$attempts = $question->getMaxAttempts();
|
||||
while (null === $attempts || $attempts--) {
|
||||
if (null !== $error) {
|
||||
$this->writeError($output, $error);
|
||||
}
|
||||
|
||||
try {
|
||||
return $question->getValidator()($interviewer());
|
||||
} catch (RuntimeException $e) {
|
||||
throw $e;
|
||||
} catch (\Exception $error) {
|
||||
}
|
||||
}
|
||||
|
||||
throw $error;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a valid unix shell.
|
||||
*
|
||||
* @return string|bool The valid shell name, false in case no valid shell is found
|
||||
*/
|
||||
protected function getShell()
|
||||
{
|
||||
if (null !== static::$shell) {
|
||||
return static::$shell;
|
||||
}
|
||||
|
||||
static::$shell = false;
|
||||
|
||||
if (file_exists('/usr/bin/env')) {
|
||||
// handle other OSs with bash/zsh/ksh/csh if available to hide the answer
|
||||
$test = "/usr/bin/env %s -c 'echo OK' 2> /dev/null";
|
||||
foreach (['bash', 'zsh', 'ksh', 'csh'] as $sh) {
|
||||
if ('OK' === rtrim(shell_exec(sprintf($test, $sh)))) {
|
||||
static::$shell = $sh;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return static::$shell;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether Stty is available or not.
|
||||
*/
|
||||
protected function hasSttyAvailable(): bool
|
||||
{
|
||||
if (null !== static::$stty) {
|
||||
return static::$stty;
|
||||
}
|
||||
|
||||
exec('stty 2>&1', $output, $exitcode);
|
||||
|
||||
return static::$stty = 0 === $exitcode;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,149 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* QuestionHelper class source file.
|
||||
*
|
||||
* Contains the source code of the QuestionHelper class.
|
||||
*
|
||||
* PHP version 7.2
|
||||
*
|
||||
* @package Danmaku\Console\Helper
|
||||
* @author Marvin Schreurs <fristi@danmaku.moe>
|
||||
*/
|
||||
|
||||
namespace Danmaku\Console\Helper;
|
||||
|
||||
|
||||
use Symfony\Component\Console\Exception\RuntimeException;
|
||||
use Symfony\Component\Console\Formatter\OutputFormatter;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\StreamableInputInterface;
|
||||
use Symfony\Component\Console\Output\ConsoleOutputInterface;
|
||||
use Symfony\Component\Console\Output\ConsoleSectionOutput;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Question\ChoiceQuestion;
|
||||
use Symfony\Component\Console\Question\ConfirmationQuestion;
|
||||
use Symfony\Component\Console\Question\Question;
|
||||
use Symfony\Component\Console\Style\SymfonyStyle;
|
||||
|
||||
/**
|
||||
* Class QuestionHelper
|
||||
*
|
||||
* @package Danmaku\Console\Helper
|
||||
* @author Marvin Schreurs <fristi@danmaku.moe>
|
||||
*/
|
||||
class QuestionHelper extends InheritableQuestionHelper
|
||||
{
|
||||
public function ask(InputInterface $input, OutputInterface $output, Question $question)
|
||||
{
|
||||
if ($output instanceof ConsoleOutputInterface) {
|
||||
$output = $output->getErrorOutput();
|
||||
}
|
||||
|
||||
if (!$input->isInteractive()) {
|
||||
$default = $question->getDefault();
|
||||
|
||||
if (null === $default) {
|
||||
return $default;
|
||||
}
|
||||
|
||||
if ($validator = $question->getValidator()) {
|
||||
return \call_user_func($question->getValidator(), $default);
|
||||
} elseif ($question instanceof ChoiceQuestion) {
|
||||
if (!$question->isMultiselect()) {
|
||||
return $default;
|
||||
}
|
||||
|
||||
$default = explode(',', $default);
|
||||
foreach ($default as $k => $v) {
|
||||
$v = trim($v);
|
||||
$default[$k] = $v;
|
||||
}
|
||||
}
|
||||
|
||||
return $default;
|
||||
}
|
||||
|
||||
if ($input instanceof StreamableInputInterface && $stream = $input->getStream()) {
|
||||
$this->inputStream = $stream;
|
||||
}
|
||||
|
||||
if (!$question->getValidator()) {
|
||||
return $this->doAsk($output, $question);
|
||||
}
|
||||
|
||||
$interviewer = function () use ($output, $question) {
|
||||
return $this->doAsk($output, $question);
|
||||
};
|
||||
|
||||
return $this->validateAttempts($interviewer, $output, $question);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function writePrompt(OutputInterface $output, Question $question)
|
||||
{
|
||||
$text = OutputFormatter::escapeTrailingBackslash($question->getQuestion());
|
||||
$default = $question->getDefault();
|
||||
|
||||
switch (true) {
|
||||
case null === $default:
|
||||
$text = sprintf(' <question>%s</question>:', $text);
|
||||
|
||||
break;
|
||||
|
||||
case $question instanceof ConfirmationQuestion:
|
||||
$text = sprintf(' <question>%s</question> <info>(yes/no)</info> [<answer>%s</answer>]:', $text, $default ? 'yes' : 'no');
|
||||
|
||||
break;
|
||||
|
||||
case $question instanceof ChoiceQuestion && $question->isMultiselect():
|
||||
$choices = $question->getChoices();
|
||||
$default = explode(',', $default);
|
||||
|
||||
foreach ($default as $key => $value) {
|
||||
$default[$key] = $choices[trim($value)];
|
||||
}
|
||||
|
||||
$text = sprintf(' <question>%s</question> [<answer>%s</answer>]:', $text, OutputFormatter::escape(implode(', ', $default)));
|
||||
|
||||
break;
|
||||
|
||||
case $question instanceof ChoiceQuestion:
|
||||
$choices = $question->getChoices();
|
||||
$text = sprintf(' <question>%s</question> [<answer>%s</answer>]:', $text, OutputFormatter::escape(isset($choices[$default]) ? $choices[$default] : $default));
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
$text = sprintf(' <question>%s</question> [<answer>%s</answer>]:', $text, OutputFormatter::escape($default));
|
||||
}
|
||||
|
||||
$output->writeln($text);
|
||||
|
||||
if ($question instanceof ChoiceQuestion) {
|
||||
$width = max(array_map('strlen', array_keys($question->getChoices())));
|
||||
|
||||
foreach ($question->getChoices() as $key => $value) {
|
||||
$output->writeln(sprintf(" [<choice>%-${width}s</choice>] %s", $key, $value));
|
||||
}
|
||||
}
|
||||
|
||||
$output->write(' > ');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function writeError(OutputInterface $output, \Exception $error)
|
||||
{
|
||||
if ($output instanceof SymfonyStyle) {
|
||||
$output->newLine();
|
||||
$output->error($error->getMessage());
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
parent::writeError($output, $error);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* ChoiceQuestion class source file.
|
||||
*
|
||||
* Contains the source code of the ChoiceQuestion class.
|
||||
*
|
||||
* PHP version 7.2
|
||||
*
|
||||
* @package Danmaku\Console\Question
|
||||
* @author Marvin Schreurs <fristi@danmaku.moe>
|
||||
*/
|
||||
|
||||
namespace Danmaku\Console\Question;
|
||||
|
||||
|
||||
use Symfony\Component\Console\Exception\InvalidArgumentException;
|
||||
use Symfony\Component\Console\Question\ChoiceQuestion as SymfonyChoiceQuestion;
|
||||
|
||||
/**
|
||||
* Class ChoiceQuestion
|
||||
*
|
||||
* @package Danmaku\Console\Question
|
||||
* @author Marvin Schreurs <fristi@danmaku.moe>
|
||||
*/
|
||||
class ChoiceQuestion extends SymfonyChoiceQuestion
|
||||
{
|
||||
protected function isAssoc($array)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* ConfirmationQuestion class source file.
|
||||
*
|
||||
* Contains the source code of the ConfirmationQuestion class.
|
||||
*
|
||||
* PHP version 7.2
|
||||
*
|
||||
* @package Danmaku\Console\Question
|
||||
* @author Marvin Schreurs <fristi@danmaku.moe>
|
||||
*/
|
||||
|
||||
namespace Danmaku\Console\Question;
|
||||
|
||||
|
||||
use Symfony\Component\Console\Question\ConfirmationQuestion as SymfonyConfirmationQuestion;
|
||||
|
||||
/**
|
||||
* Class ConfirmationQuestion
|
||||
*
|
||||
* @package Danmaku\Console\Question
|
||||
* @author Marvin Schreurs <fristi@danmaku.moe>
|
||||
*/
|
||||
class ConfirmationQuestion extends SymfonyConfirmationQuestion
|
||||
{
|
||||
protected function isAssoc($array)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* Question class source file.
|
||||
*
|
||||
* Contains the source code of the Question class.
|
||||
*
|
||||
* PHP version 7.2
|
||||
*
|
||||
* @package Danmaku\Console\Question
|
||||
* @author Marvin Schreurs <fristi@danmaku.moe>
|
||||
*/
|
||||
|
||||
namespace Danmaku\Console\Question;
|
||||
|
||||
|
||||
use Symfony\Component\Console\Question\Question as SymfonyQuestion;
|
||||
|
||||
/**
|
||||
* Class Question
|
||||
*
|
||||
* @package Danmaku\Console\Question
|
||||
* @author Marvin Schreurs <fristi@danmaku.moe>
|
||||
*/
|
||||
class Question extends SymfonyQuestion
|
||||
{
|
||||
protected function isAssoc($array)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,546 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* DefaultOutputWriter class source file.
|
||||
*
|
||||
* Contains the source code of the DefaultOutputWriter class.
|
||||
*
|
||||
* PHP version 7.2
|
||||
*
|
||||
* @package Danmaku\Console\Writer
|
||||
* @author Marvin Schreurs <fristi@danmaku.moe>
|
||||
*/
|
||||
|
||||
namespace Danmaku\Console\Writer;
|
||||
|
||||
|
||||
use Danmaku\LaravelConsoleWriter\Console\Helper\QuestionHelper;
|
||||
use Danmaku\LaravelConsoleWriter\Console\Question\ChoiceQuestion;
|
||||
use Danmaku\LaravelConsoleWriter\Console\Question\ConfirmationQuestion;
|
||||
use Danmaku\LaravelConsoleWriter\Console\Question\Question;
|
||||
use Symfony\Component\Console\Exception\RuntimeException;
|
||||
use Symfony\Component\Console\Formatter\OutputFormatter;
|
||||
use Symfony\Component\Console\Formatter\OutputFormatterStyle;
|
||||
use Symfony\Component\Console\Helper\Helper;
|
||||
use Symfony\Component\Console\Helper\ProgressBar;
|
||||
use Symfony\Component\Console\Helper\SymfonyQuestionHelper;
|
||||
use Symfony\Component\Console\Helper\Table;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\BufferedOutput;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Question\Question as SymfonyQuestion;
|
||||
use Symfony\Component\Console\Terminal;
|
||||
|
||||
/**
|
||||
* Class DefaultOutputWriter
|
||||
*
|
||||
* @package Danmaku\Console\Writer
|
||||
* @author Marvin Schreurs <fristi@danmaku.moe>
|
||||
*/
|
||||
class DefaultOutputWriter implements OutputWriterInterface
|
||||
{
|
||||
/**
|
||||
* Console input interface.
|
||||
*
|
||||
* @var InputInterface $input
|
||||
*/
|
||||
protected $input;
|
||||
|
||||
/**
|
||||
* Console output interface.
|
||||
*
|
||||
* @var OutputInterface $output
|
||||
*/
|
||||
protected $output;
|
||||
|
||||
/**
|
||||
* ProgressBar instance.
|
||||
*
|
||||
* @var ProgressBar $progressBar
|
||||
*/
|
||||
protected $progressBar;
|
||||
|
||||
/**
|
||||
* Output buffer.
|
||||
*
|
||||
* @var BufferedOutput $bufferedOutput
|
||||
*/
|
||||
protected $bufferedOutput;
|
||||
|
||||
/**
|
||||
* Helper instance for handling questions.
|
||||
*
|
||||
* @var SymfonyQuestionHelper $questionHelper
|
||||
*/
|
||||
protected $questionHelper;
|
||||
|
||||
/**
|
||||
* Calculated line length that will be used in the console.
|
||||
*
|
||||
* @var int $lineLength
|
||||
*/
|
||||
protected $lineLength;
|
||||
|
||||
/**
|
||||
* The list of available output styles with their settings.
|
||||
*
|
||||
* @var array $styles
|
||||
*/
|
||||
protected $styles = [
|
||||
'comment' => ['white', 'black'],
|
||||
'info' => ['cyan', 'black'],
|
||||
'warning' => ['yellow', 'black'],
|
||||
'danger' => ['red', 'black'],
|
||||
'success' => ['green', 'black'],
|
||||
'debug' => ['black', 'white'],
|
||||
'comment-bg' => ['black', 'white'],
|
||||
'info-bg' => ['black', 'cyan'],
|
||||
'warning-bg' => ['black', 'yellow'],
|
||||
'danger-bg' => ['white', 'red'],
|
||||
'success-bg' => ['black', 'green'],
|
||||
'debug-bg' => ['black', 'white'],
|
||||
'title' => ['green', 'black'],
|
||||
'section' => ['white', 'black'],
|
||||
'question'=> ['green', 'black'],
|
||||
'answer' => ['yellow', 'black'],
|
||||
'choice' => ['yellow', 'black'],
|
||||
];
|
||||
|
||||
/**
|
||||
* The maximum length of lines to use for console ouput.
|
||||
*
|
||||
* @var int $maxLineLength
|
||||
*/
|
||||
protected $maxLineLength = 120;
|
||||
|
||||
/**
|
||||
* BaseOutputStyler constructor.
|
||||
*
|
||||
* @param InputInterface $input
|
||||
* @param OutputInterface $output
|
||||
*/
|
||||
public function __construct(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
//Set input and output interface
|
||||
$this->input = $input;
|
||||
$this->output = $output;
|
||||
|
||||
//Set additional output styles
|
||||
foreach($this->styles as $style => $values) {
|
||||
$formatter = new OutputFormatterStyle($values[0], $values[1]);
|
||||
$output->getFormatter()->setStyle($style, $formatter);
|
||||
}
|
||||
|
||||
$this->bufferedOutput = new BufferedOutput($output->getVerbosity(), false, clone $output->getFormatter());
|
||||
// Windows cmd wraps lines as soon as the terminal width is reached, whether there are following chars or not.
|
||||
$width = (new Terminal())->getWidth() ?: $this->maxLineLength;
|
||||
$this->lineLength = min($width - (int) (\DIRECTORY_SEPARATOR === '\\'), $this->maxLineLength);
|
||||
}
|
||||
|
||||
public function title(string $title): void
|
||||
{
|
||||
$this->autoPrependBlock();
|
||||
$this->writeln([
|
||||
sprintf('<title>%s</>', OutputFormatter::escapeTrailingBackslash($title)),
|
||||
sprintf('<title>%s</>', str_repeat('=', Helper::strlenWithoutDecoration($this->output->getFormatter(), $title))),
|
||||
]);
|
||||
$this->newLine();
|
||||
}
|
||||
|
||||
public function section(string $heading): void
|
||||
{
|
||||
$this->autoPrependBlock();
|
||||
$this->writeln([
|
||||
sprintf('<section>%s</>', OutputFormatter::escapeTrailingBackslash($heading)),
|
||||
sprintf('<section>%s</>', str_repeat('-', Helper::strlenWithoutDecoration($this->output->getFormatter(), $heading))),
|
||||
]);
|
||||
$this->newLine();
|
||||
}
|
||||
|
||||
public function table(array $headers, array $rows): void
|
||||
{
|
||||
$style = clone Table::getStyleDefinition('symfony-style-guide');
|
||||
$style->setCellHeaderFormat('<info>%s</info>');
|
||||
|
||||
$table = new Table($this->output);
|
||||
$table->setHeaders($headers);
|
||||
$table->setRows($rows);
|
||||
$table->setStyle($style);
|
||||
|
||||
$table->render();
|
||||
$this->newLine();
|
||||
}
|
||||
|
||||
public function list(array $items, bool $dictionary = false): void
|
||||
{
|
||||
$this->autoPrependText();
|
||||
|
||||
if($dictionary) {
|
||||
$width = $this->_getColumnWidth(array_keys($items));
|
||||
$this->newLine();
|
||||
foreach($items as $item => $description) {
|
||||
//Format line
|
||||
$spacingWidth = $width - Helper::strlen($item);
|
||||
$line = sprintf(' %s%s%s', $item, str_repeat(' ', $spacingWidth), $description);
|
||||
$this->writeln($line);
|
||||
}
|
||||
} else {
|
||||
$items = array_map(function ($item) {
|
||||
return sprintf(' * %s', $item);
|
||||
}, $items);
|
||||
$this->writeln($items);
|
||||
}
|
||||
|
||||
$this->newLine();
|
||||
}
|
||||
|
||||
public function text($message, string $style = null, $verbosity = OutputInterface::VERBOSITY_NORMAL): void
|
||||
{
|
||||
$this->autoPrependText();
|
||||
|
||||
$messages = \is_array($message) ? array_values($message) : [$message];
|
||||
foreach ($messages as $message) {
|
||||
if(!empty($style)){
|
||||
$message = sprintf(" <$style>%s</>", $message);
|
||||
}
|
||||
|
||||
$this->writeln(sprintf(' %s', $message), $verbosity);
|
||||
}
|
||||
}
|
||||
|
||||
public function success($message, bool $padding = false): void
|
||||
{
|
||||
if(!$this->output->isQuiet()) {
|
||||
$style = $padding ? 'success-bg' : 'success';
|
||||
$this->block($message, 'OK', $style, ' ', $padding);
|
||||
}
|
||||
}
|
||||
|
||||
public function error($message, bool $padding = false): void
|
||||
{
|
||||
if(!$this->output->isQuiet()) {
|
||||
$style = $padding ? 'danger-bg' : 'danger';
|
||||
$this->block($message, 'ERROR', $style, ' ', $padding);
|
||||
}
|
||||
}
|
||||
|
||||
public function warning($message, bool $padding = false): void
|
||||
{
|
||||
if(!$this->output->isQuiet()) {
|
||||
$style = $padding ? 'warning-bg' : 'warning';
|
||||
$this->block($message, 'WARN', $style, ' ', $padding);
|
||||
}
|
||||
}
|
||||
|
||||
public function comment($message, bool $padding = false): void
|
||||
{
|
||||
if($this->output->isVeryVerbose()) {
|
||||
$style = $padding ? 'comment-bg' : 'comment';
|
||||
$this->block($message, null, $style, " // ", $padding, false);
|
||||
}
|
||||
}
|
||||
|
||||
public function info($message, bool $padding = false): void
|
||||
{
|
||||
if($this->output->isVeryVerbose()) {
|
||||
$style = $padding ? 'info-bg' : 'info';
|
||||
$this->block($message, 'INFO', $style, ' ', $padding);
|
||||
}
|
||||
}
|
||||
|
||||
public function debug($message, bool $padding = false): void
|
||||
{
|
||||
if($this->output->isDebug()) {
|
||||
$style = $padding ? 'debug-bg' : 'debug';
|
||||
$this->block($message, 'DEBUG', $style, ' ', $padding);
|
||||
}
|
||||
}
|
||||
|
||||
public function exception(\Throwable $throwable, string $message = null): void
|
||||
{
|
||||
$this->error([
|
||||
$message ?? 'An exception has occurred!',
|
||||
sprintf('In %s on line %s:', $throwable->getFile(), $throwable->getLine()),
|
||||
$throwable->getMessage()
|
||||
], true);
|
||||
}
|
||||
|
||||
public function ask(string $question, $default = null, $validator = null)
|
||||
{
|
||||
$question = new Question($question, $default);
|
||||
$question->setValidator($validator);
|
||||
|
||||
return $this->askQuestion($question);
|
||||
}
|
||||
|
||||
public function password(string $question, $validator = null)
|
||||
{
|
||||
$question = new Question($question);
|
||||
|
||||
$question->setHidden(true);
|
||||
$question->setValidator($validator);
|
||||
|
||||
return $this->askQuestion($question);
|
||||
}
|
||||
|
||||
public function confirm(string $question, $default = true): bool
|
||||
{
|
||||
return $this->askQuestion(new ConfirmationQuestion($question, $default));
|
||||
}
|
||||
|
||||
public function choice(string $question, array $choices, $default = null)
|
||||
{
|
||||
return $this->askQuestion(new ChoiceQuestion($question, $choices, $default));
|
||||
}
|
||||
|
||||
public function startProgress(int $max = 0): void
|
||||
{
|
||||
$this->progressBar = $this->createProgress($max);
|
||||
$this->progressBar->start();
|
||||
}
|
||||
|
||||
public function advanceProgress(int $step = 1): void
|
||||
{
|
||||
$this->getProgressBar()->advance($step);
|
||||
}
|
||||
|
||||
public function finishProgress(): void
|
||||
{
|
||||
$this->getProgressBar()->finish();
|
||||
$this->newLine(2);
|
||||
$this->progressBar = null;
|
||||
}
|
||||
|
||||
public function createProgress(int $max = 0): ProgressBar
|
||||
{
|
||||
$progressBar = new ProgressBar($this->output, $max);
|
||||
|
||||
$progressBar->setBarCharacter('<success>=</>');
|
||||
$progressBar->setEmptyBarCharacter('<danger> </>');
|
||||
$progressBar->setProgressCharacter('<warning>></>');
|
||||
$progressBar->setBarWidth(60);
|
||||
$progressBar->setFormat(
|
||||
" %status%\n %current%/%max% [%bar%] %percent:3s%%\n 🏁 %estimated:-50s% %memory:20s%"
|
||||
);
|
||||
|
||||
return $progressBar;
|
||||
}
|
||||
|
||||
public function newLine($count = 1): void
|
||||
{
|
||||
$this->output->write(str_repeat(PHP_EOL, $count));
|
||||
$this->bufferedOutput->write(str_repeat("\n", $count));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $messages
|
||||
* @param int $type
|
||||
*/
|
||||
protected function writeln($messages, $type = OutputInterface::OUTPUT_NORMAL)
|
||||
{
|
||||
if (!is_iterable($messages)) {
|
||||
$messages = [$messages];
|
||||
}
|
||||
|
||||
foreach ($messages as $message) {
|
||||
$this->output->writeln($message, $type);
|
||||
$this->writeBuffer($message, true, $type);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $messages
|
||||
* @param bool $newline
|
||||
* @param int $type
|
||||
*/
|
||||
protected function write($messages, $newline = false, $type = OutputInterface::OUTPUT_NORMAL)
|
||||
{
|
||||
if (!is_iterable($messages)) {
|
||||
$messages = [$messages];
|
||||
}
|
||||
|
||||
foreach ($messages as $message) {
|
||||
$this->output->write($message, $newline, $type);
|
||||
$this->writeBuffer($message, $newline, $type);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param SymfonyQuestion $question
|
||||
* @return mixed
|
||||
* @throws \Exception
|
||||
*/
|
||||
protected function askQuestion(SymfonyQuestion $question)
|
||||
{
|
||||
if ($this->input->isInteractive()) {
|
||||
$this->autoPrependBlock();
|
||||
}
|
||||
|
||||
if (!$this->questionHelper) {
|
||||
$this->questionHelper = new QuestionHelper();
|
||||
}
|
||||
|
||||
$answer = $this->questionHelper->ask($this->input, $this->output, $question);
|
||||
|
||||
if ($this->input->isInteractive()) {
|
||||
$this->newLine();
|
||||
$this->bufferedOutput->write("\n");
|
||||
}
|
||||
|
||||
return $answer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepend a new line for an upcoming block.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function autoPrependBlock(): void
|
||||
{
|
||||
$chars = substr(str_replace(PHP_EOL, "\n", $this->bufferedOutput->fetch()), -2);
|
||||
|
||||
if (!isset($chars[0])) {
|
||||
$this->newLine(); //empty history, so we should start with a new line.
|
||||
|
||||
return;
|
||||
}
|
||||
//Prepend new line for each non LF chars (This means no blank line was output before)
|
||||
$this->newLine(2 - substr_count($chars, "\n"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepend a new line for upcoming text.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function autoPrependText(): void
|
||||
{
|
||||
$fetched = $this->bufferedOutput->fetch();
|
||||
//Prepend new line if last char isn't EOL:
|
||||
if ("\n" !== substr($fetched, -1)) {
|
||||
$this->newLine();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $message
|
||||
* @param bool $newLine
|
||||
* @param int $type
|
||||
*/
|
||||
protected function writeBuffer(string $message, bool $newLine, int $type): void
|
||||
{
|
||||
// We need to know if the two last chars are PHP_EOL
|
||||
// Preserve the last 4 chars inserted (PHP_EOL on windows is two chars) in the history buffer
|
||||
$this->bufferedOutput->write(substr($message, -4), $newLine, $type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats a message as a block of text.
|
||||
*
|
||||
* @param string|array $messages The message to write in the block
|
||||
* @param string|null $type The block type (added in [] on first line)
|
||||
* @param string|null $style The style to apply to the whole block
|
||||
* @param string $prefix The prefix for the block
|
||||
* @param bool $padding Whether to add vertical padding
|
||||
* @param bool $escape Whether to escape the message
|
||||
* @param int $verbosity
|
||||
*/
|
||||
protected function block($messages, $type = null, $style = null, $prefix = ' ', $padding = false, $escape = true, $verbosity = OutputInterface::OUTPUT_NORMAL)
|
||||
{
|
||||
$messages = \is_array($messages) ? array_values($messages) : [$messages];
|
||||
|
||||
if($padding) {
|
||||
$this->autoPrependBlock();
|
||||
} else {
|
||||
$this->autoPrependText();
|
||||
}
|
||||
|
||||
$this->writeln($this->createBlock($messages, $type, $style, $prefix, $padding, $escape), $verbosity);
|
||||
|
||||
if($padding) {
|
||||
$this->newLine();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Format a set of messages as a block.
|
||||
*
|
||||
* @param iterable $messages
|
||||
* @param string|null $type
|
||||
* @param string|null $style
|
||||
* @param string $prefix
|
||||
* @param bool $padding
|
||||
* @param bool $escape
|
||||
* @return array
|
||||
*/
|
||||
private function createBlock(iterable $messages, string $type = null, string $style = null, string $prefix = ' ', bool $padding = false, bool $escape = false)
|
||||
{
|
||||
$indentLength = 0;
|
||||
$prefixLength = Helper::strlenWithoutDecoration($this->output->getFormatter(), $prefix);
|
||||
$lines = [];
|
||||
|
||||
if (null !== $type) {
|
||||
$type = sprintf('[%s] ', $type);
|
||||
$indentLength = \strlen($type);
|
||||
$lineIndentation = str_repeat(' ', $indentLength);
|
||||
}
|
||||
|
||||
// wrap and add newlines for each element
|
||||
foreach ($messages as $key => $message) {
|
||||
if ($escape) {
|
||||
$message = OutputFormatter::escape($message);
|
||||
}
|
||||
|
||||
$lines = array_merge($lines, explode(PHP_EOL, wordwrap($message, $this->lineLength - $prefixLength - $indentLength, PHP_EOL, true)));
|
||||
|
||||
if (\count($messages) > 1 && $key < \count($messages) - 1) {
|
||||
$lines[] = '';
|
||||
}
|
||||
}
|
||||
|
||||
$firstLineIndex = 0;
|
||||
if ($padding && $this->output->isDecorated()) {
|
||||
$firstLineIndex = 1;
|
||||
array_unshift($lines, '');
|
||||
$lines[] = '';
|
||||
}
|
||||
|
||||
foreach ($lines as $i => &$line) {
|
||||
if (null !== $type) {
|
||||
$line = $firstLineIndex === $i ? $type.$line : $lineIndentation.$line;
|
||||
}
|
||||
|
||||
$line = $prefix.$line;
|
||||
$line .= str_repeat(' ', $this->lineLength - Helper::strlenWithoutDecoration($this->output->getFormatter(), $line));
|
||||
|
||||
if ($style) {
|
||||
$line = sprintf('<%s>%s</>', $style, $line);
|
||||
}
|
||||
}
|
||||
|
||||
return $lines;
|
||||
}
|
||||
|
||||
protected function getProgressBar(): ProgressBar
|
||||
{
|
||||
if (!$this->progressBar) {
|
||||
throw new RuntimeException('The ProgressBar is not started.');
|
||||
}
|
||||
|
||||
return $this->progressBar;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the column width that fits all items.
|
||||
*
|
||||
* @param array $items
|
||||
* @return int
|
||||
*/
|
||||
private function _getColumnWidth(array $items): int
|
||||
{
|
||||
$widths = [];
|
||||
foreach ($items as $item) {
|
||||
$widths[] = Helper::strlen($item);
|
||||
}
|
||||
return $widths ? max($widths) + 2 : 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,206 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* OutputWriterInterface interface source file.
|
||||
*
|
||||
* Contains the source code of the OutputWriterInterface interface.
|
||||
*
|
||||
* PHP version 7.2
|
||||
*
|
||||
* @package Danmaku\Console\Writer
|
||||
* @author Marvin Schreurs <fristi@danmaku.moe>
|
||||
*/
|
||||
|
||||
namespace Danmaku\Console\Writer;
|
||||
|
||||
|
||||
use Symfony\Component\Console\Helper\ProgressBar;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
/**
|
||||
* Interface OutputWriterInterface
|
||||
*
|
||||
* @package Danmaku\Console\Writer
|
||||
* @author Marvin Schreurs <fristi@danmaku.moe>
|
||||
*/
|
||||
interface OutputWriterInterface
|
||||
{
|
||||
/**
|
||||
* Formats a command title.
|
||||
*
|
||||
* @param string $title The title text to display.
|
||||
* @return void
|
||||
*/
|
||||
public function title(string $title): void;
|
||||
|
||||
/**
|
||||
* Formats a command section.
|
||||
*
|
||||
* @param string $heading The section heading to display.
|
||||
* @return void
|
||||
*/
|
||||
public function section(string $heading): void;
|
||||
|
||||
/**
|
||||
* Formats a table.
|
||||
*
|
||||
* @param array $headers A list of column headers.
|
||||
* @param array $rows A list of rows with cells.
|
||||
* @return void
|
||||
*/
|
||||
public function table(array $headers, array $rows): void;
|
||||
|
||||
/**
|
||||
* Formats a list.
|
||||
*
|
||||
* @param array $items A list of items.
|
||||
* @param bool $dictionary Print the list as key/value pairs.
|
||||
* @return void
|
||||
*/
|
||||
public function list(array $items, bool $dictionary = false): void;
|
||||
|
||||
/**
|
||||
* Writes an unformatted line of text.
|
||||
*
|
||||
* @param string|array $message Message to display.
|
||||
* @param string|null $style Style to apply to the message.
|
||||
* @param int $verbosity Verbosity level at which this message should be printed.
|
||||
* @return void
|
||||
*/
|
||||
public function text($message, string $style = null, $verbosity = OutputInterface::VERBOSITY_NORMAL): void;
|
||||
|
||||
/**
|
||||
* Formats a success message.
|
||||
*
|
||||
* @param string|array $message Message to display.
|
||||
* @param bool $padding Render the message in a padded box.
|
||||
* @return void
|
||||
*/
|
||||
public function success($message, bool $padding = false): void;
|
||||
|
||||
/**
|
||||
* Formats an error message.
|
||||
*
|
||||
* @param string|array $message Message to display.
|
||||
* @param bool $padding Render the message in a padded box.
|
||||
* @return void
|
||||
*/
|
||||
public function error($message, bool $padding = false): void;
|
||||
|
||||
/**
|
||||
* Formats a warning message.
|
||||
*
|
||||
* @param string|array $message Message to display.
|
||||
* @param bool $padding Render the message in a padded box.
|
||||
* @return void
|
||||
*/
|
||||
public function warning($message, bool $padding = false): void;
|
||||
|
||||
/**
|
||||
* Formats a comment message.
|
||||
*
|
||||
* @param string|array $message Message to display.
|
||||
* @param bool $padding Render the message in a padded box.
|
||||
* @return void
|
||||
*/
|
||||
public function comment($message, bool $padding = false): void;
|
||||
|
||||
/**
|
||||
* Formats an information message.
|
||||
*
|
||||
* @param string|array $message Message to display.
|
||||
* @param bool $padding Render the message in a padded box.
|
||||
* @return void
|
||||
*/
|
||||
public function info($message, bool $padding = false): void;
|
||||
|
||||
/**
|
||||
* Formats a debug message.
|
||||
*
|
||||
* @param string|array $message Message to display.
|
||||
* @param bool $padding Render the message in a padded box.
|
||||
* @return void
|
||||
*/
|
||||
public function debug($message, bool $padding = false): void;
|
||||
|
||||
/**
|
||||
* Formats an exception.
|
||||
*
|
||||
* @param \Throwable $throwable A throwable instance to report.
|
||||
* @param string|null $message Message to display with the exception.
|
||||
* @return void
|
||||
*/
|
||||
public function exception(\Throwable $throwable, string $message = null): void;
|
||||
|
||||
/**
|
||||
* Asks the user for input.
|
||||
*
|
||||
* @param string $question Question to display.
|
||||
* @param mixed|null $default Default value for input.
|
||||
* @param callable|null $validator Callable used to validate input.
|
||||
* @return mixed The user's input.
|
||||
*/
|
||||
public function ask(string $question, $default = null, $validator = null);
|
||||
|
||||
/**
|
||||
* Ask the user for input, the input will be hidden.
|
||||
*
|
||||
* @param string $question Question to display.
|
||||
* @param callable|null $validator Callable used to validate input.
|
||||
* @return mixed The user's input.
|
||||
*/
|
||||
public function password(string $question, $validator = null);
|
||||
|
||||
/**
|
||||
* Ask the user for confirmation (yes or no).
|
||||
*
|
||||
* @param string $question Question to display.
|
||||
* @param bool $default Default value for input.
|
||||
* @return bool The user's input.
|
||||
*/
|
||||
public function confirm(string $question, $default = true): bool;
|
||||
|
||||
/**
|
||||
* Ask the user for input using a list of choices.
|
||||
*
|
||||
* @param string $question Question to display.
|
||||
* @param array $choices List of choices.
|
||||
* @param mixed|null $default Default value for input.
|
||||
* @return mixed The user's input.
|
||||
*/
|
||||
public function choice(string $question, array $choices, $default = null);
|
||||
|
||||
/**
|
||||
* Start a progressbar.
|
||||
*
|
||||
* @param int $max Maximum steps (0 if unknown).
|
||||
*/
|
||||
public function startProgress(int $max = 0): void;
|
||||
|
||||
/**
|
||||
* Advance the progressbar by the given number of steps.
|
||||
*
|
||||
* @param int $step Amount of steps to advance.
|
||||
*/
|
||||
public function advanceProgress(int $step = 1): void;
|
||||
|
||||
/**
|
||||
* Stop the progressbar.
|
||||
*/
|
||||
public function finishProgress(): void;
|
||||
|
||||
/**
|
||||
* Create a ProgressBar instance.
|
||||
*
|
||||
* @param int $max Maximum steps (0 if unknown).
|
||||
* @return ProgressBar The ProgressBar instance.
|
||||
*/
|
||||
public function createProgress(int $max = 0): ProgressBar;
|
||||
|
||||
/**
|
||||
* Add newlines.
|
||||
*
|
||||
* @param int $count
|
||||
* @return void
|
||||
*/
|
||||
public function newLine(int $count = 1): void;
|
||||
}
|
||||
Loading…
Reference in a new issue