Skip to content

Commit 97ad9b4

Browse files
committed
up: more help logic to an trait class
1 parent 6f6a815 commit 97ad9b4

File tree

3 files changed

+388
-303
lines changed

3 files changed

+388
-303
lines changed

src/AbstractFlags.php

Lines changed: 5 additions & 303 deletions
Original file line numberDiff line numberDiff line change
@@ -3,39 +3,27 @@
33
namespace Toolkit\PFlag;
44

55
use Toolkit\Cli\Cli;
6-
use Toolkit\Cli\Color\ColorTag;
76
use Toolkit\Cli\Helper\FlagHelper;
7+
use Toolkit\PFlag\Concern\HelperRenderTrait;
88
use Toolkit\PFlag\Concern\RuleParserTrait;
99
use Toolkit\PFlag\Contract\ParserInterface;
10-
use Toolkit\PFlag\Contract\ValidatorInterface;
11-
use Toolkit\PFlag\Flag\Argument;
12-
use Toolkit\PFlag\Flag\Option;
13-
use Toolkit\Stdlib\Helper\DataHelper;
14-
use Toolkit\Stdlib\Helper\IntHelper;
1510
use Toolkit\Stdlib\Obj;
1611
use Toolkit\Stdlib\Obj\Traits\NameAliasTrait;
1712
use Toolkit\Stdlib\Obj\Traits\QuickInitTrait;
18-
use Toolkit\Stdlib\Str;
1913
use function array_merge;
2014
use function array_shift;
2115
use function array_values;
2216
use function basename;
23-
use function count;
2417
use function explode;
25-
use function is_object;
26-
use function ksort;
27-
use function method_exists;
28-
use function sprintf;
29-
use function strlen;
3018
use function strpos;
31-
use function trim;
3219

3320
/**
3421
* class AbstractFlags
3522
* abstract parser
3623
*/
3724
abstract class AbstractFlags implements ParserInterface
3825
{
26+
use HelperRenderTrait;
3927
use QuickInitTrait;
4028
use NameAliasTrait;
4129
use RuleParserTrait;
@@ -142,6 +130,9 @@ abstract class AbstractFlags implements ParserInterface
142130
'argNameLen' => 12,
143131
'optNameLen' => 12,
144132
'descNlOnOptLen' => self::OPT_MAX_WIDTH,
133+
// more settings
134+
'exampleHelp' => '',
135+
'moreHelp' => '',
145136
];
146137

147138
/**
@@ -208,29 +199,6 @@ abstract class AbstractFlags implements ParserInterface
208199
*/
209200
protected $strictCheckArgs = false;
210201

211-
// -------------------- settings for render help --------------------
212-
213-
/**
214-
* Auto render help on provide '-h', '--help'
215-
*
216-
* @var bool
217-
*/
218-
protected $autoRenderHelp = true;
219-
220-
/**
221-
* Show flag data type on render help
222-
*
223-
* @var bool
224-
*/
225-
protected $showTypeOnHelp = true;
226-
227-
/**
228-
* Custom help renderer.
229-
*
230-
* @var callable
231-
*/
232-
protected $helpRenderer;
233-
234202
/**
235203
* Class constructor.
236204
*
@@ -342,244 +310,10 @@ public function __toString(): string
342310
*/
343311
abstract public function buildHelp(bool $withColor = true): string;
344312

345-
/**
346-
* @param array $argDefines
347-
* @param array $optDefines
348-
* @param bool $withColor
349-
*
350-
* @return string
351-
*/
352-
protected function doBuildHelp(array $argDefines, array $optDefines, bool $withColor): string
353-
{
354-
$buf = Str\StrBuffer::new();
355-
356-
// ------- desc -------
357-
if ($title = $this->desc) {
358-
$buf->writeln(Str::ucfirst($title) . "\n");
359-
}
360-
361-
$hasArgs = count($argDefines) > 0;
362-
$hasOpts = count($optDefines) > 0;
363-
364-
// ------- usage -------
365-
$binName = $this->scriptName ?: FlagUtil::getBinName();
366-
if ($hasArgs || $hasOpts) {
367-
$buf->writeln("<ylw>Usage:</ylw> $binName [Options ...] -- [Arguments ...]\n");
368-
}
369-
370-
// ------- args -------
371-
$nameTag = 'info';
372-
$fmtArgs = $this->buildArgsForHelp($argDefines);
373-
374-
if ($hasArgs) {
375-
$buf->writeln('<ylw>Arguments:</ylw>');
376-
}
377-
378-
$nameLen = $this->settings['argNameLen'];
379-
foreach ($fmtArgs as $hName => $arg) {
380-
[$desc, $lines] = $this->formatDesc($arg);
381-
382-
// write to buffer.
383-
$hName = Str::padRight($hName, $nameLen);
384-
$buf->writef(" <%s>%s</%s> %s\n", $nameTag, $hName, $nameTag, $desc);
385-
386-
// remaining desc lines
387-
if ($lines) {
388-
$indent = Str::repeat(' ', $nameLen);
389-
foreach ($lines as $line) {
390-
$buf->writef(" %s%s\n", $indent, $line);
391-
}
392-
}
393-
}
394-
395-
$hasArgs && $buf->writeln('');
396-
397-
// ------- opts -------
398-
if ($hasOpts) {
399-
$buf->writeln('<ylw>Options:</ylw>');
400-
}
401-
402-
$nameTag = 'info';
403-
$fmtOpts = $this->buildOptsForHelp($optDefines);
404-
405-
$nameLen = $this->settings['optNameLen'];
406-
$maxWidth = $this->settings['descNlOnOptLen'];
407-
foreach ($fmtOpts as $hName => $opt) {
408-
[$desc, $lines] = $this->formatDesc($opt);
409-
410-
// need echo desc at newline.
411-
$hName = Str::padRight($hName, $nameLen);
412-
if (strlen($hName) > $maxWidth) {
413-
$buf->writef(" <%s>%s</%s>\n", $nameTag, $hName, $nameTag);
414-
$buf->writef(" %s%s\n", Str::repeat(' ', $nameLen), $desc);
415-
} else {
416-
$buf->writef(" <%s>%s</%s> %s\n", $nameTag, $hName, $nameTag, $desc);
417-
}
418-
419-
// remaining desc lines
420-
if ($lines) {
421-
$indent = Str::repeat(' ', $nameLen);
422-
foreach ($lines as $line) {
423-
$buf->writef(" %s%s\n", $indent, $line);
424-
}
425-
}
426-
}
427-
428-
return $withColor ? $buf->clear() : ColorTag::clear($buf->clear());
429-
}
430-
431-
/**
432-
* @param array|Option|Argument $define
433-
*
434-
* @return array
435-
* @see DEFINE_ITEM for array $define
436-
*/
437-
protected function formatDesc($define): array
438-
{
439-
$desc = $define['desc'];
440-
441-
if ($define['required']) {
442-
$desc = '<red1>*</red1>' . $desc;
443-
}
444-
445-
// validator limit
446-
if (!empty($define['validator'])) {
447-
$v = $define['validator'];
448-
449-
/** @see ValidatorInterface */
450-
if (is_object($v) && method_exists($v, '__toString')) {
451-
$limit = (string)$v;
452-
$desc .= $limit ? ' ' . $limit : '';
453-
}
454-
}
455-
456-
// default value.
457-
if (isset($define['default']) && $define['default'] !== null) {
458-
$desc .= sprintf('(default <mga>%s</mga>)', DataHelper::toString($define['default']));
459-
}
460-
461-
// desc has multi line
462-
$lines = [];
463-
if (strpos($desc, "\n") > 0) {
464-
$lines = explode("\n", $desc);
465-
$desc = array_shift($lines);
466-
}
467-
468-
return [$desc, $lines];
469-
}
470-
471-
/**
472-
* @param array $argDefines
473-
*
474-
* @return array
475-
*/
476-
protected function buildArgsForHelp(array $argDefines): array
477-
{
478-
$fmtArgs = [];
479-
$maxLen = $this->settings['argNameLen'];
480-
481-
/** @var array|Argument $arg {@see DEFINE_ITEM} */
482-
foreach ($argDefines as $arg) {
483-
$helpName = $arg['name'] ?: 'arg' . $arg['index'];
484-
if ($desc = $arg['desc']) {
485-
$desc = trim($desc);
486-
}
487-
488-
// ensure desc is not empty
489-
$arg['desc'] = $desc ? Str::ucfirst($desc) : "Argument $helpName";
490-
491-
$type = $arg['type'];
492-
if (FlagType::isArray($type)) {
493-
$helpName .= '...';
494-
}
495-
496-
if ($this->showTypeOnHelp) {
497-
$typeName = FlagType::getHelpName($type);
498-
$helpName .= $typeName ? " $typeName" : '';
499-
}
500-
501-
$maxLen = IntHelper::getMax($maxLen, strlen($helpName));
502-
503-
// append
504-
$fmtArgs[$helpName] = $arg;
505-
}
506-
507-
$this->settings['argNameLen'] = $maxLen;
508-
return $fmtArgs;
509-
}
510-
511-
/**
512-
* @param array $optDefines
513-
*
514-
* @return array
515-
*/
516-
protected function buildOptsForHelp(array $optDefines): array
517-
{
518-
if (!$optDefines) {
519-
return [];
520-
}
521-
522-
$fmtOpts = [];
523-
$nameLen = $this->settings['optNameLen'];
524-
ksort($optDefines);
525-
526-
/** @var array|Option $opt {@see DEFINE_ITEM} */
527-
foreach ($optDefines as $name => $opt) {
528-
$names = $opt['shorts'];
529-
/** @see Option support alias name. */
530-
if (isset($opt['alias']) && $opt['alias']) {
531-
$names[] = $opt['alias'];
532-
}
533-
// real name.
534-
$names[] = $name;
535-
536-
if ($desc = $opt['desc']) {
537-
$desc = trim($desc);
538-
}
539-
540-
// ensure desc is not empty
541-
$opt['desc'] = $desc ? Str::ucfirst($desc) : "Option $name";
542-
543-
$helpName = FlagUtil::buildOptHelpName($names);
544-
if ($this->showTypeOnHelp) {
545-
$typeName = FlagType::getHelpName($opt['type']);
546-
$helpName .= $typeName ? " $typeName" : '';
547-
}
548-
549-
$nameLen = IntHelper::getMax($nameLen, strlen($helpName));
550-
// append
551-
$fmtOpts[$helpName] = $opt;
552-
}
553-
554-
// limit option name width
555-
$maxLen = IntHelper::getMax($this->settings['descNlOnOptLen'], self::OPT_MAX_WIDTH);
556-
557-
$this->settings['descNlOnOptLen'] = $maxLen;
558-
// set opt name len
559-
$this->settings['optNameLen'] = IntHelper::getMin($nameLen, $maxLen);
560-
return $fmtOpts;
561-
}
562-
563313
/****************************************************************
564314
* getter/setter methods
565315
***************************************************************/
566316

567-
/**
568-
* @return callable
569-
*/
570-
public function getHelpRenderer(): callable
571-
{
572-
return $this->helpRenderer;
573-
}
574-
575-
/**
576-
* @param callable $helpRenderer
577-
*/
578-
public function setHelpRenderer(callable $helpRenderer): void
579-
{
580-
$this->helpRenderer = $helpRenderer;
581-
}
582-
583317
/**
584318
* @return array
585319
*/
@@ -790,36 +524,4 @@ public function setScriptName(string $scriptName): void
790524
{
791525
$this->scriptName = $scriptName;
792526
}
793-
794-
/**
795-
* @return bool
796-
*/
797-
public function isAutoRenderHelp(): bool
798-
{
799-
return $this->autoRenderHelp;
800-
}
801-
802-
/**
803-
* @param bool $autoRenderHelp
804-
*/
805-
public function setAutoRenderHelp(bool $autoRenderHelp): void
806-
{
807-
$this->autoRenderHelp = $autoRenderHelp;
808-
}
809-
810-
/**
811-
* @return bool
812-
*/
813-
public function isShowTypeOnHelp(): bool
814-
{
815-
return $this->showTypeOnHelp;
816-
}
817-
818-
/**
819-
* @param bool $showTypeOnHelp
820-
*/
821-
public function setShowTypeOnHelp(bool $showTypeOnHelp): void
822-
{
823-
$this->showTypeOnHelp = $showTypeOnHelp;
824-
}
825527
}

0 commit comments

Comments
 (0)