Skip to content

Commit 274bb86

Browse files
committed
feat: add terminal normalizer for more native command structures
1 parent 58191ea commit 274bb86

2 files changed

Lines changed: 86 additions & 27 deletions

File tree

src/Sprout/App.php

Lines changed: 83 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,71 @@ public function register($command)
6161
return $command;
6262
}
6363

64+
protected function normalizeCommandInput(string $input): array
65+
{
66+
$tokens = preg_split('/\s+/', trim($input));
67+
$result = [
68+
'command' => null,
69+
'args' => [],
70+
'options' => []
71+
];
72+
73+
$i = 0;
74+
$len = count($tokens);
75+
76+
if ($len > 0) {
77+
$result['command'] = $tokens[$i++];
78+
}
79+
80+
while ($i < $len) {
81+
$token = $tokens[$i];
82+
83+
// Long option: --option or --option=value
84+
if (strpos($token, '--') === 0) {
85+
$option = substr($token, 2);
86+
if (strpos($option, '=') !== false) {
87+
[$name, $value] = explode('=', $option, 2);
88+
$result['options'][$name] = strpos($value, ',') !== false ? explode(',', $value) : $value;
89+
} elseif (isset($tokens[$i + 1]) && strpos($tokens[$i + 1], '-') !== 0) {
90+
// --option value
91+
$value = [];
92+
while (isset($tokens[$i + 1]) && strpos($tokens[$i + 1], '-') !== 0) {
93+
$value[] = $tokens[++$i];
94+
}
95+
$result['options'][$option] = count($value) === 1 ? $value[0] : $value;
96+
} else {
97+
// --option (boolean true)
98+
$result['options'][$option] = true;
99+
}
100+
}
101+
102+
// Short option: -a or -abc or -k value
103+
elseif (strpos($token, '-') === 0 && strlen($token) > 1) {
104+
$flags = substr($token, 1);
105+
106+
// Handle -k value
107+
if (strlen($flags) === 1 && isset($tokens[$i + 1]) && strpos($tokens[$i + 1], '-') !== 0) {
108+
$result['options'][$flags] = $tokens[++$i];
109+
} else {
110+
// Handle -abc => a=true, b=true, c=true
111+
foreach (str_split($flags) as $flag) {
112+
$result['options'][$flag] = true;
113+
}
114+
}
115+
}
116+
117+
// Normal argument
118+
else {
119+
$result['args'][] = $token;
120+
}
121+
122+
$i++;
123+
}
124+
125+
return $result;
126+
}
127+
128+
64129
/**
65130
* Run your sprout app
66131
* @return void
@@ -71,7 +136,10 @@ public function run()
71136
$arguments = [];
72137

73138
$argv = (array) $_SERVER['argv'];
139+
74140
$commandName = $argv[1] ?? '';
141+
$commandString = join(' ', array_slice($argv, 1));
142+
$commandData = $this->normalizeCommandInput($commandString);
75143

76144
if ($commandName === '' || $commandName === 'list') {
77145
$this->renderListView();
@@ -84,38 +152,27 @@ public function run()
84152
}
85153

86154
$command = $this->config['commands'][$commandName]['handler'];
87-
$argumentNames = $this->config['commands'][$commandName]['arguments'];
88-
89-
foreach (array_slice($argv, 2) as $arg) {
90-
$parts = explode('=', $arg);
91-
92-
if (strpos($parts[0], '-') === 0 && strpos($parts[0], '--') === false) {
93-
$paramName = array_filter($command->getHelp()['params'], function ($param) use ($parts) {
94-
return $param['short'] === ltrim($parts[0], '-');
95-
});
96155

97-
if (!empty($paramName)) {
98-
$parts[0] = '--' . (array_values($paramName)[0]['long']);
99-
}
100-
}
101-
102-
if (count($parts) >= 2) {
103-
$params[substr($parts[0], 2)] = join('=', array_slice($parts, 1));
104-
continue;
105-
}
156+
foreach (array_values($command->getHelp()['params']) as $paramData) {
157+
$params[$paramData['long']] = (
158+
isset($commandData['options'][$paramData['long']]) ||
159+
isset($commandData['options'][$paramData['short']])
160+
) ?
161+
($commandData['options'][$paramData['long']] ?? $commandData['options'][$paramData['short']] ?? null) :
162+
$paramData['default'] ?? null;
106163

107-
if (strpos($parts[0], '--') === 0) {
108-
$params[substr($parts[0], 2)] = true;
109-
continue;
164+
if ($paramData['optional'] === false && $params[$paramData['long']] === null) {
165+
die("Argument --{$paramData['long']} is required\n");
110166
}
167+
}
111168

112-
while (null !== ($part = array_shift($argumentNames))) {
113-
$part = str_replace(['{', '}'], '', $part);
114-
115-
$arguments[$part] = $arg;
116-
169+
foreach ($this->config['commands'][$commandName]['arguments'] as $index => $arg) {
170+
if ($command->getHelp()['arguments'][$arg]['type'] ?? null === 'array') {
171+
$arguments[$arg] = array_slice($commandData['args'], $index);
117172
break;
118173
}
174+
175+
$arguments[$arg] = $commandData['args'][$index] ?? null;
119176
}
120177

121178
$command->setParams($params);

src/Sprout/Command.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,9 @@ public function __construct()
3131
public function argument(string $argument)
3232
{
3333
if ($this->help['arguments'][$argument]['type'] === 'array') {
34-
return explode(',', $this->arguments[$argument] ?? '');
34+
if (is_string($this->arguments[$argument])) {
35+
return explode(',', $this->arguments[$argument] ?? '');
36+
}
3537
}
3638

3739
return $this->arguments[$argument] ?? null;

0 commit comments

Comments
 (0)