From 20c89783f536924df71bf40cfec4039c997a244e Mon Sep 17 00:00:00 2001 From: Rodrigo Primo Date: Wed, 21 May 2025 16:48:08 -0300 Subject: [PATCH 1/2] Refactor FeatureComplete code for color support and formatting help text This commit moves the code related to checking color and formatting the help text to a new helper class. This way it can be reused when the new DocCodeExamples script is introduced. Tests were added for the new HelpTextFormatter::format() method. --- Scripts/FeatureComplete/Config.php | 108 +------------------- Scripts/Utils/HelpTextFormatter.php | 137 ++++++++++++++++++++++++++ Tests/Utils/HelpTextFormatterTest.php | 114 +++++++++++++++++++++ phpunit.xml.dist | 1 + phpunitlte9.xml.dist | 1 + 5 files changed, 257 insertions(+), 104 deletions(-) create mode 100644 Scripts/Utils/HelpTextFormatter.php create mode 100644 Tests/Utils/HelpTextFormatterTest.php diff --git a/Scripts/FeatureComplete/Config.php b/Scripts/FeatureComplete/Config.php index 3ee24e2..3d64677 100644 --- a/Scripts/FeatureComplete/Config.php +++ b/Scripts/FeatureComplete/Config.php @@ -10,6 +10,7 @@ namespace PHPCSDevTools\Scripts\FeatureComplete; +use PHPCSDevTools\Scripts\Utils\HelpTextFormatter; use PHPCSDevTools\Scripts\Utils\Writer; use RuntimeException; @@ -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. * @@ -284,7 +271,7 @@ protected function processCliCommand() if (empty($args)) { // No options set. - $this->showColored = $this->isColorSupported(); + $this->showColored = HelpTextFormatter::isColorSupported(); return; } @@ -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']) @@ -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. * @@ -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); } } diff --git a/Scripts/Utils/HelpTextFormatter.php b/Scripts/Utils/HelpTextFormatter.php new file mode 100644 index 0000000..2be4a18 --- /dev/null +++ b/Scripts/Utils/HelpTextFormatter.php @@ -0,0 +1,137 @@ +>> $helpTexts The help texts to format. + * @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() + { + // 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; + } +} diff --git a/Tests/Utils/HelpTextFormatterTest.php b/Tests/Utils/HelpTextFormatterTest.php new file mode 100644 index 0000000..195a3c3 --- /dev/null +++ b/Tests/Utils/HelpTextFormatterTest.php @@ -0,0 +1,114 @@ +>> $helpTexts The help texts to format. + * @param string $expected The expected formatted output. + * @param bool $useColor Whether to use colored output. + * + * @return void + */ + public function testFormat(array $helpTexts, $expected, $useColor) + { + $this->assertSame($expected, HelpTextFormatter::format($helpTexts, $useColor)); + } + + /** + * Data provider for testing the format() method. + * + * @return array>>|string|bool>> + */ + public static function dataFormat() + { + return [ + 'empty help texts' => [ + 'helpTexts' => [], + 'expected' => '', + 'useColor' => false, + ], + 'empty section' => [ + 'helpTexts' => [ + 'Empty Section' => [], + ], + 'expected' => 'Empty Section:' . PHP_EOL . PHP_EOL, + 'useColor' => false, + ], + 'without color' => [ + 'helpTexts' => [ + 'Usage' => [ + [ + 'text' => 'Command [options]', + ], + ], + 'Options' => [ + [ + 'arg' => '--help', + 'desc' => 'Display this help message.', + ], + [ + 'arg' => '--version', + 'desc' => 'Display version information.', + ], + [ + 'arg' => '', + 'desc' => 'The file to process. This is a test with multiple sentences. Each sentence should be properly wrapped.', + ], + ], + ], + 'expected' => 'Usage:' . PHP_EOL . + ' Command [options]' . PHP_EOL . PHP_EOL . + 'Options:' . PHP_EOL . + ' --help Display this help message.' . PHP_EOL . + ' --version Display version information.' . PHP_EOL . + ' The file to process.' . PHP_EOL . + ' This is a test with multiple sentences.' . PHP_EOL . + ' Each sentence should be properly wrapped.' . PHP_EOL . PHP_EOL, + 'useColor' => false, + ], + 'with color' => [ + 'helpTexts' => [ + 'Usage' => [ + [ + 'text' => 'Command [options]', + ], + ], + 'Options' => [ + [ + 'arg' => '--help', + 'desc' => 'Display this help message.', + ], + ], + ], + 'expected' => "\033[33mUsage:\033[0m" . PHP_EOL . + " Command \033[36m[options]\033[0m" . PHP_EOL . PHP_EOL . + "\033[33mOptions:\033[0m" . PHP_EOL . + " \033[32m--help\033[0m Display this help message." . PHP_EOL . PHP_EOL, + 'useColor' => true, + ], + ]; + } +} diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 1e48290..ed1e1a0 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -28,6 +28,7 @@ ./Tests/DocsXsd/ ./Tests/FeatureComplete/ + ./Tests/Utils/ diff --git a/phpunitlte9.xml.dist b/phpunitlte9.xml.dist index 047630d..7a37473 100644 --- a/phpunitlte9.xml.dist +++ b/phpunitlte9.xml.dist @@ -19,6 +19,7 @@ ./Tests/DocsXsd/ ./Tests/FeatureComplete/ + ./Tests/Utils/ From 96a0c874e61e975cafff44571a60457d3dfbc0f1 Mon Sep 17 00:00:00 2001 From: Rodrigo Primo Date: Fri, 4 Jul 2025 17:02:57 -0300 Subject: [PATCH 2/2] Keep isColorSupported() on the Config class Partially reverts the previous commit to keep isColorSupported() on the Config class as discussed during the PR review. --- Scripts/FeatureComplete/Config.php | 39 +++++++++++++++++++++++++++-- Scripts/Utils/HelpTextFormatter.php | 37 +-------------------------- 2 files changed, 38 insertions(+), 38 deletions(-) diff --git a/Scripts/FeatureComplete/Config.php b/Scripts/FeatureComplete/Config.php index 3d64677..2e5acfe 100644 --- a/Scripts/FeatureComplete/Config.php +++ b/Scripts/FeatureComplete/Config.php @@ -271,7 +271,7 @@ protected function processCliCommand() if (empty($args)) { // No options set. - $this->showColored = HelpTextFormatter::isColorSupported(); + $this->showColored = $this->isColorSupported(); return; } @@ -283,7 +283,7 @@ protected function processCliCommand() } elseif (isset($argsFlipped['--colors'])) { $this->showColored = true; } else { - $this->showColored = HelpTextFormatter::isColorSupported(); + $this->showColored = $this->isColorSupported(); } if (isset($argsFlipped['-h']) @@ -360,6 +360,41 @@ 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. * diff --git a/Scripts/Utils/HelpTextFormatter.php b/Scripts/Utils/HelpTextFormatter.php index 2be4a18..b5683aa 100644 --- a/Scripts/Utils/HelpTextFormatter.php +++ b/Scripts/Utils/HelpTextFormatter.php @@ -11,7 +11,7 @@ namespace PHPCSDevTools\Scripts\Utils; /** - * Helper class for formatting help text and detecting color support. + * Helper class for formatting help text. * * --------------------------------------------------------------------------------------------- * This class is not part of the public API. Backward compatibility is not guaranteed. @@ -99,39 +99,4 @@ public static function format(array $helpTexts, $showColored) return $output; } - - /** - * Detect whether or not the CLI supports colored output. - * - * @codeCoverageIgnore - * - * @return bool - */ - public static 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; - } }