This repository has been archived on 2023-08-20. You can view files and clone it, but cannot push or open issues or pull requests.
symfony/src/Symfony/Component/Console/Style/SymfonyStyle.php
Nicolas Grekas c477c5b395 bug #14600 [Console] SymfonyStyle: fix block rpadding when escaping '<' (ogizanagi)
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 '<'
2015-05-15 12:18:14 +02:00

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;
}
}