Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
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
108 changes: 4 additions & 104 deletions Scripts/FeatureComplete/Config.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

namespace PHPCSDevTools\Scripts\FeatureComplete;

use PHPCSDevTools\Scripts\Utils\HelpTextFormatter;
use PHPCSDevTools\Scripts\Utils\Writer;
use RuntimeException;

Expand All @@ -35,20 +36,6 @@
final class Config
{

/**
* Max width for help text.
*
* @var int
*/
const MAX_WIDTH = 80;

/**
* Margin for help options.
*
* @var string
*/
const LEFT_MARGIN = ' ';

/**
* Writer for sending output.
*
Expand Down Expand Up @@ -284,7 +271,7 @@ protected function processCliCommand()

if (empty($args)) {
// No options set.
$this->showColored = $this->isColorSupported();
$this->showColored = HelpTextFormatter::isColorSupported();

return;
}
Expand All @@ -296,7 +283,7 @@ protected function processCliCommand()
} elseif (isset($argsFlipped['--colors'])) {
$this->showColored = true;
} else {
$this->showColored = $this->isColorSupported();
$this->showColored = HelpTextFormatter::isColorSupported();
}

if (isset($argsFlipped['-h'])
Expand Down Expand Up @@ -373,41 +360,6 @@ static function ($subdir) {
}
}

/**
* Detect whether or not the CLI supports colored output.
*
* @codeCoverageIgnore
*
* @return bool
*/
protected function isColorSupported()
{
// Windows.
if (\DIRECTORY_SEPARATOR === '\\') {
if (\getenv('ANSICON') !== false || \getenv('ConEmuANSI') === 'ON') {
return true;
}

if (\function_exists('sapi_windows_vt100_support')) {
// phpcs:ignore PHPCompatibility.FunctionUse.NewFunctions.sapi_windows_vt100_supportFound
return @\sapi_windows_vt100_support(\STDOUT);
}

return false;
}

if (\getenv('GITHUB_ACTIONS')) {
return true;
}

// Linux/MacOS.
if (\function_exists('posix_isatty')) {
return @\posix_isatty(\STDOUT);
}

return false;
}

/**
* Retrieve the version number of this script.
*
Expand All @@ -429,58 +381,6 @@ public function getVersion()
*/
private function getHelp()
{
$output = '';
foreach ($this->helpTexts as $section => $options) {
$longestOptionLength = 0;
foreach ($options as $option) {
if (isset($option['arg'])) {
$longestOptionLength = \max($longestOptionLength, \strlen($option['arg']));
}
}

if ($this->showColored === true) {
$output .= "\033[33m{$section}:\033[0m" . \PHP_EOL;
} else {
$output .= "{$section}:" . \PHP_EOL;
}

$descWidth = (self::MAX_WIDTH - ($longestOptionLength + 1 + \strlen(self::LEFT_MARGIN)));
$descBreak = \PHP_EOL . self::LEFT_MARGIN . \str_pad(' ', ($longestOptionLength + 1));

foreach ($options as $option) {
if (isset($option['text'])) {
$text = $option['text'];
if ($this->showColored === true) {
$text = \preg_replace('`(\[[^\]]+\])`', "\033[36m" . '$1' . "\033[0m", $text);
}
$output .= self::LEFT_MARGIN . $text . \PHP_EOL;
}

if (isset($option['arg'])) {
$arg = \str_pad($option['arg'], $longestOptionLength);
if ($this->showColored === true) {
$arg = \preg_replace('`(<[^>]+>)`', "\033[0m\033[36m" . '$1', $arg);
$arg = "\033[32m{$arg}\033[0m";
}

$descText = \wordwrap($option['desc'], $descWidth, $descBreak);
$desc = \explode('. ', $option['desc']);
if (\count($desc) > 1) {
$descText = '';
foreach ($desc as $key => $sentence) {
$descText .= ($key === 0) ? '' : $descBreak;
$descText .= \wordwrap($sentence, $descWidth, $descBreak);
$descText = \rtrim($descText, '.') . '.';
}
}

$output .= self::LEFT_MARGIN . $arg . ' ' . $descText . \PHP_EOL;
}
}

$output .= \PHP_EOL;
}

return $output;
return HelpTextFormatter::format($this->helpTexts, $this->showColored);
}
}
137 changes: 137 additions & 0 deletions Scripts/Utils/HelpTextFormatter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
<?php
/**
* PHPCSDevTools, tools for PHP_CodeSniffer sniff developers.
*
* @package PHPCSDevTools
* @copyright 2019 PHPCSDevTools Contributors
* @license https://opensource.org/licenses/LGPL-3.0 LGPL3
* @link https://github.com/PHPCSStandards/PHPCSDevTools
*/

namespace PHPCSDevTools\Scripts\Utils;

/**
* Helper class for formatting help text and detecting color support.
*
* ---------------------------------------------------------------------------------------------
* This class is not part of the public API. Backward compatibility is not guaranteed.
* ---------------------------------------------------------------------------------------------
*
* @since 2.0.0
*/
class HelpTextFormatter
{
/**
* Max width for help text.
*
* @var int
*/
const MAX_WIDTH = 80;

/**
* Margin for help options.
*
* @var string
*/
const LEFT_MARGIN = ' ';

/**
* Format help text from a structured array of options.
*
* @param array<string, array<array<string, string>>> $helpTexts The help texts to format.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As the formatter is now in a separate class, I think the expected format for the $helpTexts array needs to be documented in more detail.

The class docblock might even be a better place than this function docblock.

* @param bool $showColored Whether to use colored output.
*
* @return string The formatted help text.
*/
public static function format(array $helpTexts, $showColored)
{
$output = '';
foreach ($helpTexts as $section => $options) {
$longestOptionLength = 0;
foreach ($options as $option) {
if (isset($option['arg'])) {
$longestOptionLength = \max($longestOptionLength, \strlen($option['arg']));
}
}

if ($showColored === true) {
$output .= "\033[33m{$section}:\033[0m" . \PHP_EOL;
} else {
$output .= "{$section}:" . \PHP_EOL;
}

$descWidth = (self::MAX_WIDTH - ($longestOptionLength + 1 + \strlen(self::LEFT_MARGIN)));
$descBreak = \PHP_EOL . self::LEFT_MARGIN . \str_pad(' ', ($longestOptionLength + 1));

foreach ($options as $option) {
if (isset($option['text'])) {
$text = $option['text'];
if ($showColored === true) {
$text = \preg_replace('`(\[[^\]]+\])`', "\033[36m" . '$1' . "\033[0m", $text);
}
$output .= self::LEFT_MARGIN . $text . \PHP_EOL;
}

if (isset($option['arg'])) {
$arg = \str_pad($option['arg'], $longestOptionLength);
if ($showColored === true) {
$arg = \preg_replace('`(<[^>]+>)`', "\033[0m\033[36m" . '$1', $arg);
$arg = "\033[32m{$arg}\033[0m";
}

$descText = \wordwrap($option['desc'], $descWidth, $descBreak);
$desc = \explode('. ', $option['desc']);
if (\count($desc) > 1) {
$descText = '';
foreach ($desc as $key => $sentence) {
$descText .= ($key === 0) ? '' : $descBreak;
$descText .= \wordwrap($sentence, $descWidth, $descBreak);
$descText = \rtrim($descText, '.') . '.';
}
}

$output .= self::LEFT_MARGIN . $arg . ' ' . $descText . \PHP_EOL;
}
}

$output .= \PHP_EOL;
}

return $output;
}

/**
* Detect whether or not the CLI supports colored output.
*
* @codeCoverageIgnore
*
* @return bool
*/
public static function isColorSupported()
Copy link
Member

@jrfnl jrfnl Jun 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this method belongs in the HelpTextFormatter class as this is also used to determine whether the non-help output of the CLI command(s) should be colorized or not...

I have a feeling this should be in a separate class, which maybe should also contain some "colorize" helper methods.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As we discussed in a call, I will update this PR to remove isColorSupported() and then look into potentially creating a separate PR to add https://github.com/php-parallel-lint/PHP-Console-Color/ as a dependency and use it in this package.

{
// Windows.
if (\DIRECTORY_SEPARATOR === '\\') {
if (\getenv('ANSICON') !== false || \getenv('ConEmuANSI') === 'ON') {
return true;
}

if (\function_exists('sapi_windows_vt100_support')) {
// phpcs:ignore PHPCompatibility.FunctionUse.NewFunctions.sapi_windows_vt100_supportFound
return @\sapi_windows_vt100_support(\STDOUT);
}

return false;
}

if (\getenv('GITHUB_ACTIONS')) {
return true;
}

// Linux/MacOS.
if (\function_exists('posix_isatty')) {
return @\posix_isatty(\STDOUT);
}

return false;
}
}
Loading