Skip to content

Commit 5bdd7ea

Browse files
authored
[Feat] Command Prompt Inputs (#123)
* feat: console prompt input * fix: default callback and return type * fix phpstan * formatting
1 parent c5cb487 commit 5bdd7ea

File tree

2 files changed

+159
-0
lines changed

2 files changed

+159
-0
lines changed

src/System/Console/Prompt.php

+119
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace System\Console;
6+
7+
use System\Console\Style\Style;
8+
9+
/**
10+
* Add costumize terminal style by adding trits:
11+
* - TraitCommand (optional).
12+
*
13+
* @property string $_ Get argument name
14+
*/
15+
class Prompt
16+
{
17+
/**
18+
* @var string|Style
19+
*/
20+
private $title;
21+
22+
/**
23+
* @var array<string, callable>
24+
*/
25+
private array $options;
26+
27+
private string $default;
28+
29+
/**
30+
* @var string[]|Style[]
31+
*/
32+
private array $selection;
33+
34+
/**
35+
* @param string|Style $title
36+
* @param array<string, callable> $options
37+
*/
38+
public function __construct($title, array $options = [], string $default = '')
39+
{
40+
$this->title = $title;
41+
$this->options = array_merge(['' => fn () => false], $options);
42+
$this->default = $default;
43+
$this->selection = array_keys($options);
44+
}
45+
46+
private function getInput(): string
47+
{
48+
$input = fgets(STDIN);
49+
50+
if ($input === false) {
51+
throw new \Exception('Cant read input');
52+
}
53+
54+
return trim($input);
55+
}
56+
57+
/**
58+
* @param string[]|Style[] $selection
59+
*/
60+
public function selection($selection): self
61+
{
62+
$this->selection = $selection;
63+
64+
return $this;
65+
}
66+
67+
public function option(): mixed
68+
{
69+
$style = new Style();
70+
$style->push($this->title)->push(' ');
71+
foreach ($this->selection as $option) {
72+
if ($option instanceof Style) {
73+
$style->tap($option);
74+
} else {
75+
$style->push("{$option} ");
76+
}
77+
}
78+
79+
$style->out();
80+
$input = $this->getInput();
81+
if (array_key_exists($input, $this->options)) {
82+
return ($this->options[$input])();
83+
}
84+
85+
return ($this->options[$this->default])();
86+
}
87+
88+
public function select(): mixed
89+
{
90+
$style = new Style();
91+
$style->push($this->title);
92+
$i = 0;
93+
foreach ($this->selection as $option) {
94+
if ($option instanceof Style) {
95+
$style->tap($option);
96+
} else {
97+
$style->new_lines()->push("> {$i} {$option}");
98+
}
99+
$i++;
100+
}
101+
102+
$style->out();
103+
$input = $this->getInput();
104+
$select = array_values($this->options);
105+
106+
if (array_key_exists($input, $select)) {
107+
return ($select[$input])();
108+
}
109+
110+
return ($this->options[$this->default])();
111+
}
112+
113+
public function text(callable $callable): mixed
114+
{
115+
(new Style($this->title))->out();
116+
117+
return ($callable)($this->getInput());
118+
}
119+
}

src/System/Console/helper.php

+40
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
namespace System\Console;
66

7+
use System\Console\Style\Style;
8+
79
if (!function_exists('style')) {
810
/**
911
* Render text with terminal style (chain way).
@@ -73,3 +75,41 @@ function ok($text)
7375
return \System\Console\Style\Alert::render()->ok($text);
7476
}
7577
}
78+
79+
if (!function_exists('option')) {
80+
/**
81+
* Command Prompt input option.
82+
*
83+
* @param string|Style $title
84+
* @param array<string, callable> $options
85+
*/
86+
function option($title, array $options): mixed
87+
{
88+
return (new Prompt($title, $options))->option();
89+
}
90+
}
91+
92+
if (!function_exists('select')) {
93+
/**
94+
* Command Prompt input selection.
95+
*
96+
* @param string|Style $title
97+
* @param array<string, callable> $options
98+
*/
99+
function select($title, array $options): mixed
100+
{
101+
return (new Prompt($title, $options))->select();
102+
}
103+
}
104+
105+
if (!function_exists('text')) {
106+
/**
107+
* Command Prompt input text.
108+
*
109+
* @param string|Style $title
110+
*/
111+
function text($title, callable $callable): mixed
112+
{
113+
return (new Prompt($title))->text($callable);
114+
}
115+
}

0 commit comments

Comments
 (0)