c477c5b395
This PR was merged into the 2.7 branch.
Discussion
----------
[Console] SymfonyStyle: fix block rpadding when escaping '<'
| Q | A
| ------------- | ---
| Bug fix? | yes
| New feature? | no
| BC breaks? | no
| Deprecations? | no
| Tests pass? | yes
| Fixed tickets | -
| License | MIT
| Doc PR | -
![screenshot 2015-05-10 a 20 37 46](https://cloud.githubusercontent.com/assets/2211145/7555745/4dfbfd58-f755-11e4-98c4-3c42bb71abd3.PNG)
Commits
-------
80fc341
[Console] SymfonyStyle: fix block rpadding when escaping '<'
324 lines
8.0 KiB
PHP
324 lines
8.0 KiB
PHP
<?php
|
|
|
|
/*
|
|
* This file is part of the Symfony package.
|
|
*
|
|
* (c) Fabien Potencier <fabien@symfony.com>
|
|
*
|
|
* For the full copyright and license information, please view the LICENSE
|
|
* file that was distributed with this source code.
|
|
*/
|
|
|
|
namespace Symfony\Component\Console\Style;
|
|
|
|
use Symfony\Component\Console\Application;
|
|
use Symfony\Component\Console\Formatter\OutputFormatter;
|
|
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\OutputInterface;
|
|
use Symfony\Component\Console\Question\ChoiceQuestion;
|
|
use Symfony\Component\Console\Question\ConfirmationQuestion;
|
|
use Symfony\Component\Console\Question\Question;
|
|
|
|
/**
|
|
* Output decorator helpers for the Symfony Style Guide.
|
|
*
|
|
* @author Kevin Bond <kevinbond@gmail.com>
|
|
*/
|
|
class SymfonyStyle extends OutputStyle
|
|
{
|
|
const MAX_LINE_LENGTH = 120;
|
|
|
|
private $input;
|
|
private $questionHelper;
|
|
private $progressBar;
|
|
private $lineLength;
|
|
|
|
/**
|
|
* @param InputInterface $input
|
|
* @param OutputInterface $output
|
|
*/
|
|
public function __construct(InputInterface $input, OutputInterface $output)
|
|
{
|
|
$this->input = $input;
|
|
$this->lineLength = min($this->getTerminalWidth(), self::MAX_LINE_LENGTH);
|
|
|
|
parent::__construct($output);
|
|
}
|
|
|
|
/**
|
|
* 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
|
|
*/
|
|
public function block($messages, $type = null, $style = null, $prefix = ' ', $padding = false)
|
|
{
|
|
$messages = array_values((array) $messages);
|
|
$lines = array();
|
|
|
|
// add type
|
|
if (null !== $type) {
|
|
$messages[0] = sprintf('[%s] %s', $type, $messages[0]);
|
|
}
|
|
|
|
// wrap and add newlines for each element
|
|
foreach ($messages as $key => $message) {
|
|
$message = OutputFormatter::escape($message);
|
|
$lines = array_merge($lines, explode("\n", wordwrap($message, $this->lineLength - Helper::strlen($prefix))));
|
|
|
|
if (count($messages) > 1 && $key < count($messages) - 1) {
|
|
$lines[] = '';
|
|
}
|
|
}
|
|
|
|
if ($padding && $this->isDecorated()) {
|
|
array_unshift($lines, '');
|
|
$lines[] = '';
|
|
}
|
|
|
|
foreach ($lines as &$line) {
|
|
$line = sprintf('%s%s', $prefix, $line);
|
|
$line .= str_repeat(' ', $this->lineLength - Helper::strlenWithoutDecoration($this->getFormatter(), $line));
|
|
|
|
if ($style) {
|
|
$line = sprintf('<%s>%s</>', $style, $line);
|
|
}
|
|
}
|
|
|
|
$this->writeln(implode("\n", $lines)."\n");
|
|
}
|
|
|
|
/**
|
|
* {@inheritdoc}
|
|
*/
|
|
public function title($message)
|
|
{
|
|
$this->writeln(sprintf("\n<comment>%s</>\n<comment>%s</>\n", $message, str_repeat('=', strlen($message))));
|
|
}
|
|
|
|
/**
|
|
* {@inheritdoc}
|
|
*/
|
|
public function section($message)
|
|
{
|
|
$this->writeln(sprintf("<comment>%s</>\n<comment>%s</>\n", $message, str_repeat('-', strlen($message))));
|
|
}
|
|
|
|
/**
|
|
* {@inheritdoc}
|
|
*/
|
|
public function listing(array $elements)
|
|
{
|
|
$elements = array_map(function ($element) {
|
|
return sprintf(' * %s', $element);
|
|
},
|
|
$elements
|
|
);
|
|
|
|
$this->writeln(implode("\n", $elements)."\n");
|
|
}
|
|
|
|
/**
|
|
* {@inheritdoc}
|
|
*/
|
|
public function text($message)
|
|
{
|
|
if (!is_array($message)) {
|
|
$this->writeln(sprintf(' // %s', $message));
|
|
|
|
return;
|
|
}
|
|
|
|
foreach ($message as $element) {
|
|
$this->text($element);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* {@inheritdoc}
|
|
*/
|
|
public function success($message)
|
|
{
|
|
$this->block($message, 'OK', 'fg=white;bg=green', ' ', true);
|
|
}
|
|
|
|
/**
|
|
* {@inheritdoc}
|
|
*/
|
|
public function error($message)
|
|
{
|
|
$this->block($message, 'ERROR', 'fg=white;bg=red', ' ', true);
|
|
}
|
|
|
|
/**
|
|
* {@inheritdoc}
|
|
*/
|
|
public function warning($message)
|
|
{
|
|
$this->block($message, 'WARNING', 'fg=white;bg=red', ' ', true);
|
|
}
|
|
|
|
/**
|
|
* {@inheritdoc}
|
|
*/
|
|
public function note($message)
|
|
{
|
|
$this->block($message, 'NOTE', 'fg=yellow', ' ! ');
|
|
}
|
|
|
|
/**
|
|
* {@inheritdoc}
|
|
*/
|
|
public function caution($message)
|
|
{
|
|
$this->block($message, 'CAUTION', 'fg=white;bg=red', ' ! ', true);
|
|
}
|
|
|
|
/**
|
|
* {@inheritdoc}
|
|
*/
|
|
public function table(array $headers, array $rows)
|
|
{
|
|
$headers = array_map(function ($value) { return sprintf('<info>%s</>', $value); }, $headers);
|
|
|
|
$table = new Table($this);
|
|
$table->setHeaders($headers);
|
|
$table->setRows($rows);
|
|
$table->setStyle('symfony-style-guide');
|
|
|
|
$table->render();
|
|
$this->newLine();
|
|
}
|
|
|
|
/**
|
|
* {@inheritdoc}
|
|
*/
|
|
public function ask($question, $default = null, $validator = null)
|
|
{
|
|
$question = new Question($question, $default);
|
|
$question->setValidator($validator);
|
|
|
|
return $this->askQuestion($question, $validator);
|
|
}
|
|
|
|
/**
|
|
* {@inheritdoc}
|
|
*/
|
|
public function askHidden($question, $validator = null)
|
|
{
|
|
$question = new Question($question);
|
|
$question->setHidden(true);
|
|
|
|
return $this->askQuestion($question, $validator);
|
|
}
|
|
|
|
/**
|
|
* {@inheritdoc}
|
|
*/
|
|
public function confirm($question, $default = true)
|
|
{
|
|
return $this->askQuestion(new ConfirmationQuestion($question, $default));
|
|
}
|
|
|
|
/**
|
|
* {@inheritdoc}
|
|
*/
|
|
public function choice($question, array $choices, $default = null)
|
|
{
|
|
if (null !== $default) {
|
|
$values = array_flip($choices);
|
|
$default = $values[$default];
|
|
}
|
|
|
|
return $this->askQuestion(new ChoiceQuestion($question, $choices, $default));
|
|
}
|
|
|
|
/**
|
|
* {@inheritdoc}
|
|
*/
|
|
public function progressStart($max = 0)
|
|
{
|
|
$this->progressBar = $this->createProgressBar($max);
|
|
$this->progressBar->start();
|
|
}
|
|
|
|
/**
|
|
* {@inheritdoc}
|
|
*/
|
|
public function progressAdvance($step = 1)
|
|
{
|
|
$this->getProgressBar()->advance($step);
|
|
}
|
|
|
|
/**
|
|
* {@inheritdoc}
|
|
*/
|
|
public function progressFinish()
|
|
{
|
|
$this->getProgressBar()->finish();
|
|
$this->newLine(2);
|
|
$this->progressBar = null;
|
|
}
|
|
|
|
/**
|
|
* {@inheritdoc}
|
|
*/
|
|
public function createProgressBar($max = 0)
|
|
{
|
|
$progressBar = parent::createProgressBar($max);
|
|
|
|
if ('\\' === DIRECTORY_SEPARATOR) {
|
|
$progressBar->setEmptyBarCharacter('░'); // light shade character \u2591
|
|
$progressBar->setProgressCharacter('');
|
|
$progressBar->setBarCharacter('▓'); // dark shade character \u2593
|
|
}
|
|
|
|
return $progressBar;
|
|
}
|
|
|
|
/**
|
|
* @param Question $question
|
|
*
|
|
* @return string
|
|
*/
|
|
public function askQuestion(Question $question)
|
|
{
|
|
if (!$this->questionHelper) {
|
|
$this->questionHelper = new SymfonyQuestionHelper();
|
|
}
|
|
|
|
$answer = $this->questionHelper->ask($this->input, $this, $question);
|
|
|
|
$this->newLine();
|
|
|
|
return $answer;
|
|
}
|
|
|
|
/**
|
|
* @return ProgressBar
|
|
*/
|
|
private function getProgressBar()
|
|
{
|
|
if (!$this->progressBar) {
|
|
throw new \RuntimeException('The ProgressBar is not started.');
|
|
}
|
|
|
|
return $this->progressBar;
|
|
}
|
|
|
|
private function getTerminalWidth()
|
|
{
|
|
$application = new Application();
|
|
$dimensions = $application->getTerminalDimensions();
|
|
|
|
return $dimensions[0] ?: self::MAX_LINE_LENGTH;
|
|
}
|
|
}
|