Skip to content
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

Add support for outputting 256 colors and also add documentation about default command functionality #110

Merged
merged 61 commits into from
Nov 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
61 commits
Select commit Hold shift + click to select a range
c354406
Add support for 256 colors
kodie Nov 25, 2024
e59800f
Add documentation about default command functionality
kodie Nov 25, 2024
57b0ddc
Use 256 colors in test_custom_style test
kodie Nov 25, 2024
3099286
Add Color::bg256 and Color::fg256
kodie Nov 26, 2024
d9c947c
Add periods to bg256 and fg256 descriptions
kodie Nov 26, 2024
d69720e
Add mising A to fg256 example in readme
kodie Nov 26, 2024
9d758dc
Add return types for bg256 and fg256 functions
kodie Nov 26, 2024
6e08fdb
Make bg256 and fg256 functions static
kodie Nov 26, 2024
7bca2a3
Use PHP comments in Default command example in readme instead of Bash…
kodie Nov 26, 2024
1d306be
Make all written text built-in styles so that their styles can be cus…
kodie Nov 25, 2024
6c1c1ae
Put back Interactor Writer method definitions
kodie Nov 25, 2024
4753bdb
Put back eol and table method definitions for Interactor
kodie Nov 25, 2024
eff6243
Put this blank line back? I'm not sure how that happened
kodie Nov 25, 2024
1b7c236
Remove un-needed space
kodie Nov 25, 2024
9bdeea2
Hopefully fix issue with test
kodie Nov 25, 2024
c85ad40
Put factory color functions back
kodie Nov 26, 2024
6574e93
Prevent users from making factory functions invisible
kodie Nov 26, 2024
bc39541
Shorten a couple lines
kodie Nov 26, 2024
8a8dba0
Update invisible_built_in_style expected exception message
kodie Nov 26, 2024
52c02c2
Add new method definitions for Writer and Interactor classes
kodie Nov 26, 2024
3c04803
Make logo a built-in style
kodie Nov 26, 2024
a1cd34f
Make help_description into help_description_even/odd and make help_it…
kodie Nov 26, 2024
2bd83f4
Fix indentation
kodie Nov 26, 2024
9604577
Add support for custom help screens
kodie Nov 26, 2024
e661fd5
Fix identation
kodie Nov 26, 2024
1053704
Hopefully fix issues with tests
kodie Nov 26, 2024
f0ac531
Tests don't like variables starting with underscores in the application
kodie Nov 26, 2024
0439020
Add example to readme showing how you can get colors working in a cus…
kodie Nov 26, 2024
639aeb5
Just pass the colorizer as the help parameter in the custom help read…
kodie Nov 26, 2024
fd794a7
Rename custom_help to help
kodie Nov 26, 2024
a6d6be1
Make all written text built-in styles so that their styles can be cus…
kodie Nov 25, 2024
9e32278
Put back Interactor Writer method definitions
kodie Nov 25, 2024
84c19f8
Put back eol and table method definitions for Interactor
kodie Nov 25, 2024
2c908c4
Put this blank line back? I'm not sure how that happened
kodie Nov 25, 2024
360eb14
Remove un-needed space
kodie Nov 25, 2024
f852324
Hopefully fix issue with test
kodie Nov 25, 2024
0bb1d31
Put factory color functions back
kodie Nov 26, 2024
346c0f7
Prevent users from making factory functions invisible
kodie Nov 26, 2024
274abbb
Shorten a couple lines
kodie Nov 26, 2024
0fdd4e6
Update invisible_built_in_style expected exception message
kodie Nov 26, 2024
f2d8922
Add new method definitions for Writer and Interactor classes
kodie Nov 26, 2024
8ea5a65
Make logo a built-in style
kodie Nov 26, 2024
a128794
Make help_description into help_description_even/odd and make help_it…
kodie Nov 26, 2024
d3e7e76
Fix indentation
kodie Nov 26, 2024
2c9858c
Add support for custom help screens
kodie Nov 26, 2024
87f723d
Fix identation
kodie Nov 26, 2024
34dd521
Hopefully fix issues with tests
kodie Nov 26, 2024
88b224e
Tests don't like variables starting with underscores in the application
kodie Nov 26, 2024
ef29727
Add example to readme showing how you can get colors working in a cus…
kodie Nov 26, 2024
86ecf30
Just pass the colorizer as the help parameter in the custom help read…
kodie Nov 26, 2024
bc70bff
Rename custom_help to help
kodie Nov 26, 2024
21d49f7
Add support for 256 colors
kodie Nov 25, 2024
96c51fe
Add documentation about default command functionality
kodie Nov 25, 2024
5fc43fb
Use 256 colors in test_custom_style test
kodie Nov 25, 2024
45ae4cd
Add Color::bg256 and Color::fg256
kodie Nov 26, 2024
8f8f9c4
Add periods to bg256 and fg256 descriptions
kodie Nov 26, 2024
e45892f
Add mising A to fg256 example in readme
kodie Nov 26, 2024
2e9d028
Add return types for bg256 and fg256 functions
kodie Nov 26, 2024
d608baa
Make bg256 and fg256 functions static
kodie Nov 26, 2024
65caea5
Use PHP comments in Default command example in readme instead of Bash…
kodie Nov 26, 2024
f4ead85
Merge branch 'kodie/allow-256-colors' of github.com:kodie/adhocore-ph…
kodie Nov 26, 2024
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
59 changes: 58 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -170,11 +170,15 @@ class InitCommand extends Ahc\Cli\Input\Command
{
parent::__construct('init', 'Init something');

$help = '<cyan>Custom help screen</end>';
$writer = new Ahc\Cli\Output\Writer();

$this
->argument('<arrg>', 'The Arrg')
->argument('[arg2]', 'The Arg2')
->option('-a --apple', 'The Apple')
->option('-b --ball', 'The ball')
->help($writer->colorizer()->colors($help))
// Usage examples:
->usage(
// append details or explanation of given example with ` ## ` so they will be uniformly aligned when shown
Expand Down Expand Up @@ -243,6 +247,9 @@ $app->add(new OtherCommand, 'o');
// Set logo
$app->logo('Ascii art logo of your app');

// Custom help screen
$app->help('Custom help screen (if omitted one will be generated)');

$app->handle($_SERVER['argv']); // if argv[1] is `i` or `init` it executes InitCommand
```

Expand All @@ -267,6 +274,21 @@ $app->add((new ConfigListCommand)->inGroup('Config'));
...
```

#### Default command

By default, running your CLI app without any arguments will show the help screen. However you can set the default action to run one of your commands either by setting the third parameter of the `add` function to `true` or by using the `defaultCommand` function.

```php
$app->add(new InitCommand, 'i', true);

// Alternatively
$app->command('init', 'Init something', 'i');
$app->defaultCommand('init');

// Retrieve the name of the default command
$default_command = $app->getDefaultCommand();
```

#### Exception handler

Set a custom exception handler as callback. The callback receives exception & exit code. The callback may rethrow exception or may exit the program or just log exception and do nothing else.
Expand Down Expand Up @@ -443,13 +465,48 @@ echo $color->ok('This is ok msg');
```php
Ahc\Cli\Output\Color::style('mystyle', [
'bg' => Ahc\Cli\Output\Color::CYAN,
'fg' => Ahc\Cli\Output\Color::WHITE,
'fg' => Ahc\Cli\Output\Color::fg256(57), // 256 colors can be used as well
'bold' => 1, // You can experiment with 0, 1, 2, 3 ... as well
]);

echo $color->mystyle('My text');
```

#### Built-in styles

There are a number of pre-defined built-in styles that allows you granular customization to different output conditions such as help and prompts:

- answer
- choice
- comment
- error
- help_category
- help_description_even
- help_description_odd
- help_example
- help_footer
- help_group
- help_header
- help_item_even
- help_item_odd
- help_summary
- help_text
- info
- logo
- ok
- question
- version
- warn

Overriding a built-in style works the same way as defining a new style:

```php
Ahc\Cli\Output\Color::style('error', [
'fg' => Ahc\Cli\Output\Color::RED,
'bold' => 1,
]);
```

### Cursor

Move cursor around, erase line up or down, clear screen.
Expand Down
41 changes: 39 additions & 2 deletions src/Application.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ class Application
/** @var string Ascii art logo */
protected string $logo = '';

/** @var string Custom help screen */
protected string $help = '';

/** @var string Name of default command */
protected string $default = '__default__';

/** @var null|Interactor */
Expand Down Expand Up @@ -344,16 +348,49 @@ protected function aliasesFor(Command $command): array
}

/**
* Show help of all commands.
* Sets or gets the custom help screen contents.
*
* @param string|null $help
*
* @return string|self
*/
public function help(?string $help = null): mixed
{
if (func_num_args() === 0) {
return $this->help;
}

$this->help = $help;

return $this;
}

/**
* Show custom help screen if one is set, otherwise shows the default one.
*/
public function showHelp(): mixed
{
if ($help = $this->help()) {
$writer = $this->io()->writer();
$writer->write($help, true);

return ($this->onExit)();
}

return $this->showDefaultHelp();
}

/**
* Shows command help then aborts.
*/
public function showDefaultHelp(): mixed
{
$writer = $this->io()->writer();
$header = "{$this->name}, version {$this->version}";
$footer = 'Run `<command> --help` for specific help';

if ($this->logo) {
$writer->write($this->logo, true);
$writer->logo($this->logo, true);
}

$this->outputHelper()->showCommandsHelp($this->commands(), $header, $footer);
Expand Down
25 changes: 15 additions & 10 deletions src/Helper/OutputHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -182,13 +182,13 @@ public function showCommandsHelp(array $commands, string $header = '', string $f
protected function showHelp(string $for, array $items, string $header = '', string $footer = ''): void
{
if ($header) {
$this->writer->bold($header, true);
$this->writer->help_header($header, true);
}

$this->writer->eol()->boldGreen($for . ':', true);
$this->writer->eol()->help_category($for . ':', true);

if (empty($items)) {
$this->writer->bold(' (n/a)', true);
$this->writer->help_text(' (n/a)', true);

return;
}
Expand All @@ -197,20 +197,25 @@ protected function showHelp(string $for, array $items, string $header = '', stri
$group = $lastGroup = null;

$withDefault = $for === 'Options' || $for === 'Arguments';
foreach ($this->sortItems($items, $padLen, $for) as $item) {
foreach (array_values($this->sortItems($items, $padLen, $for)) as $idx => $item) {
$name = $this->getName($item);
if ($for === 'Commands' && $lastGroup !== $group = $item->group()) {
$this->writer->boldYellow($group ?: '*', true);
$this->writer->help_group($group ?: '*', true);
$lastGroup = $group;
}
$desc = str_replace(["\r\n", "\n"], str_pad("\n", $padLen + $space + 3), $item->desc($withDefault));

$this->writer->bold(' ' . str_pad($name, $padLen + $space));
$this->writer->comment($desc, true);
if ($idx % 2 == 0) {
$this->writer->help_item_even(' ' . str_pad($name, $padLen + $space));
$this->writer->help_description_even($desc, true);
} else {
$this->writer->help_item_odd(' ' . str_pad($name, $padLen + $space));
$this->writer->help_description_odd($desc, true);
}
}

if ($footer) {
$this->writer->eol()->yellow($footer, true);
$this->writer->eol()->help_footer($footer, true);
}
}

Expand All @@ -224,7 +229,7 @@ public function showUsage(string $usage): self
$usage = str_replace('$0', $_SERVER['argv'][0] ?? '[cmd]', $usage);

if (!str_contains($usage, ' ## ')) {
$this->writer->eol()->boldGreen('Usage Examples:', true)->colors($usage)->eol();
$this->writer->eol()->help_category('Usage Examples:', true)->colors($usage)->eol();

return $this;
}
Expand All @@ -241,7 +246,7 @@ public function showUsage(string $usage): self
return str_pad('# ', $maxlen - array_shift($lines), ' ', STR_PAD_LEFT);
}, $usage);

$this->writer->eol()->boldGreen('Usage Examples:', true)->colors($usage)->eol();
$this->writer->eol()->help_category('Usage Examples:', true)->colors($usage)->eol();

return $this;
}
Expand Down
30 changes: 23 additions & 7 deletions src/IO/Interactor.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
*
* @link https://github.com/adhocore/cli
*
* @method Writer answer($text, $eol = false)
* @method Writer bgBlack($text, $eol = false)
* @method Writer bgBlue($text, $eol = false)
* @method Writer bgCyan($text, $eol = false)
Expand Down Expand Up @@ -127,6 +128,7 @@
* @method Writer boldYellowBgPurple($text, $eol = false)
* @method Writer boldYellowBgRed($text, $eol = false)
* @method Writer boldYellowBgWhite($text, $eol = false)
* @method Writer choice($text, $eol = false)
* @method Writer colors($text)
* @method Writer comment($text, $eol = false)
* @method Writer cyan($text, $eol = false)
Expand All @@ -147,7 +149,19 @@
* @method Writer greenBgRed($text, $eol = false)
* @method Writer greenBgWhite($text, $eol = false)
* @method Writer greenBgYellow($text, $eol = false)
* @method Writer help_category($text, $eol = false)
* @method Writer help_description_even($text, $eol = false)
* @method Writer help_description_odd($text, $eol = false)
* @method Writer help_example($text, $eol = false)
* @method Writer help_footer($text, $eol = false)
* @method Writer help_group($text, $eol = false)
* @method Writer help_header($text, $eol = false)
* @method Writer help_item_even($text, $eol = false)
* @method Writer help_item_odd($text, $eol = false)
* @method Writer help_summary($text, $eol = false)
* @method Writer help_text($text, $eol = false)
* @method Writer info($text, $eol = false)
* @method Writer logo($text, $eol = false)
* @method Writer ok($text, $eol = false)
* @method Writer purple($text, $eol = false)
* @method Writer purpleBgBlack($text, $eol = false)
Expand All @@ -157,6 +171,7 @@
* @method Writer purpleBgRed($text, $eol = false)
* @method Writer purpleBgWhite($text, $eol = false)
* @method Writer purpleBgYellow($text, $eol = false)
* @method Writer question($text, $eol = false)
* @method Writer red($text, $eol = false)
* @method Writer redBgBlack($text, $eol = false)
* @method Writer redBgBlue($text, $eol = false)
Expand All @@ -166,6 +181,7 @@
* @method Writer redBgWhite($text, $eol = false)
* @method Writer redBgYellow($text, $eol = false)
* @method Writer table(array $rows, array $styles = [])
* @method Writer version($text, $eol = false)
* @method Writer warn($text, $eol = false)
* @method Writer white($text, $eol = false)
* @method Writer yellow($text, $eol = false)
Expand Down Expand Up @@ -241,7 +257,7 @@ public function confirm(string $text, string $default = 'y'): bool
*/
public function choice(string $text, array $choices, $default = null, bool $case = false): mixed
{
$this->writer->yellow($text);
$this->writer->question($text);

$this->listOptions($choices, $default, false);

Expand All @@ -262,7 +278,7 @@ public function choice(string $text, array $choices, $default = null, bool $case
*/
public function choices(string $text, array $choices, $default = null, bool $case = false): mixed
{
$this->writer->yellow($text);
$this->writer->question($text);

$this->listOptions($choices, $default, true);

Expand Down Expand Up @@ -300,7 +316,7 @@ public function prompt(string $text, $default = null, ?callable $fn = null, int
$hidden = func_get_args()[4] ?? false;
$readFn = ['read', 'readHidden'][(int) $hidden];

$this->writer->yellow($text)->comment(null !== $default ? " [$default]: " : ': ');
$this->writer->question($text)->answer(null !== $default ? " [$default]: " : ': ');

try {
$input = $this->reader->{$readFn}($default, $fn);
Expand All @@ -310,7 +326,7 @@ public function prompt(string $text, $default = null, ?callable $fn = null, int
}

if ($retry > 0 && $input === '') {
$this->writer->bgRed($error, true);
$this->writer->error($error, true);

return $this->prompt($text, $default, $fn, $retry - 1, $hidden);
}
Expand Down Expand Up @@ -351,12 +367,12 @@ protected function listOptions(array $choices, $default = null, bool $multi = fa
$maxLen = max(array_map('strlen', array_keys($choices)));

foreach ($choices as $choice => $desc) {
$this->writer->eol()->cyan(str_pad(" [$choice]", $maxLen + 6))->comment($desc);
$this->writer->eol()->choice(str_pad(" [$choice]", $maxLen + 6))->answer($desc);
}

$label = $multi ? 'Choices (comma separated)' : 'Choice';

$this->writer->eol()->yellow($label);
$this->writer->eol()->question($label);

return $this->promptOptions(array_keys($choices), $default);
}
Expand All @@ -369,7 +385,7 @@ protected function promptOptions(array $choices, mixed $default): self
$options = '';

foreach ($choices as $choice) {
$style = in_array($choice, (array) $default) ? 'boldCyan' : 'cyan';
$style = in_array($choice, (array) $default) ? 'boldChoice' : 'choice';
$options .= "/<$style>$choice</end>";
}

Expand Down
Loading