Skip to content

Refactor FeatureComplete code for formatting help text #189

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
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
69 changes: 2 additions & 67 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 @@ -429,58 +416,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);
}
}
102 changes: 102 additions & 0 deletions Scripts/Utils/HelpTextFormatter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
<?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.
*
* ---------------------------------------------------------------------------------------------
* 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;
}
}
114 changes: 114 additions & 0 deletions Tests/Utils/HelpTextFormatterTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
<?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\Tests\Utils;

use PHPCSDevTools\Scripts\Utils\HelpTextFormatter;
use Yoast\PHPUnitPolyfills\TestCases\XTestCase;

/**
* Test the HelpTextFormatter class.
*
* @covers \PHPCSDevTools\Scripts\Utils\HelpTextFormatter
*/
class HelpTextFormatterTest extends XTestCase
{

/**
* Test the format() method with various inputs.
*
* @dataProvider dataFormat
*
* @param array<string, array<array<string, string>>> $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, array<array<string, array<array<string, string>>>|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' => '<file>',
'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 .
' <file> 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,
],
];
}
}
1 change: 1 addition & 0 deletions phpunit.xml.dist
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
<testsuite name="DevTools">
<directory suffix="Test.php">./Tests/DocsXsd/</directory>
<directory suffix="Test.php">./Tests/FeatureComplete/</directory>
<directory suffix="Test.php">./Tests/Utils/</directory>
</testsuite>
</testsuites>
</phpunit>
1 change: 1 addition & 0 deletions phpunitlte9.xml.dist
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
<testsuite name="DevTools">
<directory suffix="Test.php">./Tests/DocsXsd/</directory>
<directory suffix="Test.php">./Tests/FeatureComplete/</directory>
<directory suffix="Test.php">./Tests/Utils/</directory>
</testsuite>
</testsuites>
</phpunit>