Compare commits
2 Commits
6d771ed88f
...
9070bf3862
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9070bf3862 | ||
|
|
d08d1f0fe7 |
@ -56,7 +56,9 @@ class CliMiddleware implements MiddlewareInterface
|
|||||||
$request = $request->withAttribute('cli.command', $command)
|
$request = $request->withAttribute('cli.command', $command)
|
||||||
->withAttribute('cli.request', $cliRequest);
|
->withAttribute('cli.request', $cliRequest);
|
||||||
|
|
||||||
return $this->container->make($class)->{$method}($request, []);
|
$cliRequest->parseOptions($command);
|
||||||
|
|
||||||
|
return $this->container->make($class)->{$method}($request, $this->commands->arguments, $command->options, $cliRequest->rest);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -79,6 +81,7 @@ class CliMiddleware implements MiddlewareInterface
|
|||||||
|
|
||||||
private function printCommand(Command $command) : ResponseInterface
|
private function printCommand(Command $command) : ResponseInterface
|
||||||
{
|
{
|
||||||
|
# @TODO !
|
||||||
$text = [
|
$text = [
|
||||||
$command->description, "",
|
$command->description, "",
|
||||||
"#[color: rgb(145;130;195), format: bold]Usage:[#]",
|
"#[color: rgb(145;130;195), format: bold]Usage:[#]",
|
||||||
@ -93,6 +96,7 @@ class CliMiddleware implements MiddlewareInterface
|
|||||||
$text = ( new AsciiFormatter() )->parse($text);
|
$text = ( new AsciiFormatter() )->parse($text);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# @TODO => plug httpfactory here !
|
||||||
return new TextResponse( implode(PHP_EOL, $text) );
|
return new TextResponse( implode(PHP_EOL, $text) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -10,9 +10,9 @@ class CliRequest
|
|||||||
|
|
||||||
public array $options = [];
|
public array $options = [];
|
||||||
|
|
||||||
protected string $shortOptions;
|
public mixed $rest = "";
|
||||||
|
|
||||||
protected array $longOptions;
|
protected array $unparsedOptions;
|
||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
public ServerRequestInterface $request
|
public ServerRequestInterface $request
|
||||||
@ -20,22 +20,6 @@ class CliRequest
|
|||||||
$this->parseCommandLine();
|
$this->parseCommandLine();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function matchOptions(string ... $options) : bool
|
|
||||||
{
|
|
||||||
foreach($options as $opt) {
|
|
||||||
if ( $this->matchOption($opt) ) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function matchOption(string $option) : bool
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function parseCommandLine() : void
|
protected function parseCommandLine() : void
|
||||||
{
|
{
|
||||||
$executionString = $this->argv();
|
$executionString = $this->argv();
|
||||||
@ -43,11 +27,67 @@ class CliRequest
|
|||||||
# Removing execution's path
|
# Removing execution's path
|
||||||
array_shift($executionString);
|
array_shift($executionString);
|
||||||
|
|
||||||
foreach($executionString as $cmd) {
|
while ( $cmd = array_shift($executionString) ) {
|
||||||
|
if (str_starts_with($cmd, '-')) {
|
||||||
|
array_unshift($executionString, $cmd);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
$this->command[] = $cmd;
|
$this->command[] = $cmd;
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->command = $executionString;
|
$this->unparsedOptions = $executionString;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Replaces the limited getopt() method which do not allow for parameters to be passed after multiple command arguments
|
||||||
|
*
|
||||||
|
* @param Command $command Matched command found using parseCommandLine
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function parseOptions(Command $command) : void
|
||||||
|
{
|
||||||
|
$this->getopt($command->options);
|
||||||
|
|
||||||
|
/*
|
||||||
|
if ( false !== $options ) {
|
||||||
|
if ($restIndex !== null) {
|
||||||
|
$this->rest = $this->argv()[$restIndex];
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->options = $options;
|
||||||
|
}*/
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getopt(OptionStack $options) :void
|
||||||
|
{
|
||||||
|
$currentOption = false;
|
||||||
|
|
||||||
|
while ( $argument = array_shift($this->unparsedOptions) ) {
|
||||||
|
#if ($currentOption !== false) {
|
||||||
|
$currentOption = $options->matchOption($argument);
|
||||||
|
|
||||||
|
if ($currentOption === false) {
|
||||||
|
$this->rest = implode(' ', $this->unparsedOptions);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*elseif (is_array($currentOption)) {
|
||||||
|
foreach($currentOption as $matchingOption) {
|
||||||
|
$matchingOption->handle();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
|
||||||
|
}*/
|
||||||
|
# }
|
||||||
|
#else {
|
||||||
|
|
||||||
|
# }
|
||||||
|
}
|
||||||
|
|
||||||
|
# dump($options);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function argv() : array
|
protected function argv() : array
|
||||||
|
|||||||
@ -4,17 +4,33 @@ namespace Mcnd\CLI;
|
|||||||
|
|
||||||
class Command
|
class Command
|
||||||
{
|
{
|
||||||
|
public array $arguments;
|
||||||
|
|
||||||
|
public readonly OptionStack $options;
|
||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
public readonly string $name,
|
public readonly string $name,
|
||||||
public string $description,
|
public string $description,
|
||||||
public array $options = [],
|
array $options = [],
|
||||||
public null|Command $parent = null,
|
public null|Command $parent = null,
|
||||||
public \Closure|string|null $callback = null,
|
public \Closure|string|null $callback = null,
|
||||||
public bool $isRoot = false,
|
public bool $isRoot = false,
|
||||||
) {}
|
) {
|
||||||
|
$this->options = new OptionStack($options);
|
||||||
|
}
|
||||||
|
|
||||||
public function pushOption(Option|array $option) : void
|
public function pushOption(Option|array $option) : void
|
||||||
{
|
{
|
||||||
$this->options[] = array_merge($this->options, $option);
|
if (is_array($option)) {
|
||||||
|
$this->options->merge($option);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$this->options->append($option);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setArguments(array $arguments) : void
|
||||||
|
{
|
||||||
|
$this->arguments = $arguments;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -4,10 +4,10 @@ namespace Mcnd\CLI;
|
|||||||
|
|
||||||
class CommandStack
|
class CommandStack
|
||||||
{
|
{
|
||||||
public array $commands = [];
|
public function __construct(
|
||||||
|
public array $commands = [],
|
||||||
public function __construct()
|
public array $arguments = []
|
||||||
{}
|
) {}
|
||||||
|
|
||||||
public function merge(CommandStack $stack) : void
|
public function merge(CommandStack $stack) : void
|
||||||
{
|
{
|
||||||
@ -28,16 +28,20 @@ class CommandStack
|
|||||||
*/
|
*/
|
||||||
public function matchCommand(array $commands) : null|Command
|
public function matchCommand(array $commands) : null|Command
|
||||||
{
|
{
|
||||||
|
$arguments = [];
|
||||||
|
|
||||||
while ($commands) {
|
while ($commands) {
|
||||||
$cmd = implode(' ', $commands);
|
$cmd = implode(' ', $commands);
|
||||||
|
|
||||||
foreach ($this->commands as $command) {
|
foreach ($this->commands as $command) {
|
||||||
if ($command->name === $cmd) {
|
if ($command->name === $cmd) {
|
||||||
|
$this->arguments = array_reverse($arguments);
|
||||||
|
|
||||||
return $command;
|
return $command;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
array_pop($commands);
|
$arguments[] = array_pop($commands);
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
109
src/Option.php
109
src/Option.php
@ -2,20 +2,113 @@
|
|||||||
|
|
||||||
namespace Mcnd\CLI;
|
namespace Mcnd\CLI;
|
||||||
|
|
||||||
|
use Mcnd\CLI\Option\{CountOption, ParsedOption, ToggleOption, ValueOption, KeyValueOption};
|
||||||
|
|
||||||
class Option
|
class Option
|
||||||
{
|
{
|
||||||
public const ARGUMENT_NONE = 0;
|
protected ParsedOption $parsed;
|
||||||
|
|
||||||
public const ARGUMENT_OPTIONAL = 1;
|
|
||||||
|
|
||||||
public const ARGUMENT_REQUIRED = 2;
|
|
||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
public array|string $toggle,
|
public array|string $switch,
|
||||||
public string $description = "",
|
public string $description = "",
|
||||||
public int $argument = self::ARGUMENT_NONE,
|
|
||||||
public mixed $default = null,
|
public mixed $default = null,
|
||||||
public mixed $awaiting = null,
|
public mixed $awaiting = null,
|
||||||
) {}
|
public OptionValueTypeEnum $value = OptionValueTypeEnum::NoValue,
|
||||||
|
) {
|
||||||
|
$this->setParsedOption();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getParsedOption() : ParsedOption
|
||||||
|
{
|
||||||
|
return $this->parsed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setParsedOption() : void
|
||||||
|
{
|
||||||
|
if ($this->value === OptionValueTypeEnum::NoValue) {
|
||||||
|
$this->parsed = new ToggleOption($this);
|
||||||
|
}
|
||||||
|
elseif ($this->value === OptionValueTypeEnum::OptionalValue || $this->value === OptionValueTypeEnum::RequiredValue ) {
|
||||||
|
$this->parsed = new ValueOption($this);
|
||||||
|
}
|
||||||
|
elseif ($this->value === OptionValueTypeEnum::KeyValue) {
|
||||||
|
$this->parsed = new KeyValueOption($this);
|
||||||
|
}
|
||||||
|
elseif ($this->value === OptionValueTypeEnum::CountValue) {
|
||||||
|
$this->parsed = new CountOption($this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function awaitingValue() : bool
|
||||||
|
{
|
||||||
|
return match($this->value) {
|
||||||
|
OptionValueTypeEnum::NoValue => false,
|
||||||
|
OptionValueTypeEnum::CountValue => false,
|
||||||
|
OptionValueTypeEnum::RequiredValue => $this->parsed->getValue() === null,
|
||||||
|
OptionValueTypeEnum::OptionalValue => $this->parsed->getValue() === null,
|
||||||
|
OptionValueTypeEnum::MultipleValue => true,
|
||||||
|
OptionValueTypeEnum::KeyValue => true,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public function matchShortSwitch(string $switch) : bool
|
||||||
|
{
|
||||||
|
$switch = strtolower($switch);
|
||||||
|
|
||||||
|
foreach((array) $this->switch as $item) {
|
||||||
|
if ( ! str_starts_with($item, '--') && substr($item, 0, 1) === '-' ) {
|
||||||
|
$singleItem = substr($item, 1, 1);
|
||||||
|
|
||||||
|
if (substr($item, 1, 1) === $switch) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function matchLongSwitch(string $switch) : bool
|
||||||
|
{
|
||||||
|
list($key, $value) = array_pad(explode('=', $switch, 2), 2, null);
|
||||||
|
|
||||||
|
foreach((array) $this->switch as $item) {
|
||||||
|
if ( str_starts_with($item, '--') ) {
|
||||||
|
if (strtolower(substr($item, 2)) === strtolower($key)) {
|
||||||
|
if ($value !== null) {
|
||||||
|
$this->value($value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function toggle() : void
|
||||||
|
{
|
||||||
|
match ($this->value) {
|
||||||
|
OptionValueTypeEnum::NoValue => $this->parsed->toggle(),
|
||||||
|
OptionValueTypeEnum::CountValue => $this->parsed->toggle(),
|
||||||
|
OptionValueTypeEnum::OptionalValue => $this->parsed->setValue(true),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public function value(mixed $value = null) : mixed
|
||||||
|
{
|
||||||
|
if ($value === null) {
|
||||||
|
return $this->parsed->getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
return match ($this->value) {
|
||||||
|
OptionValueTypeEnum::MultipleValue => $this->parsed->addValue($value),
|
||||||
|
OptionValueTypeEnum::RequiredValue => $this->parsed->setValue($value),
|
||||||
|
OptionValueTypeEnum::OptionalValue => $this->parsed->setValue($value),
|
||||||
|
OptionValueTypeEnum::KeyValue => $this->parsed->setRawValue($value),
|
||||||
|
OptionValueTypeEnum::NoValue => throw new \RuntimeException(sprintf("A value was given to an option (%s) which was not awaiting any", implode(', ', (array) $this->switch))),
|
||||||
|
OptionValueTypeEnum::CountValue => is_numeric($value) ? $this->parsed->setValue($value) : throw new \RuntimeException(sprintf("A value was given to an option (%s) which is countable", implode(', ', (array) $this->switch))),
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
23
src/Option/CountOption.php
Normal file
23
src/Option/CountOption.php
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Mcnd\CLI\Option;
|
||||||
|
|
||||||
|
class CountOption extends ParsedOption
|
||||||
|
{
|
||||||
|
protected int $count = 0;
|
||||||
|
|
||||||
|
public function toggle() : void
|
||||||
|
{
|
||||||
|
$this->count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getValue() : null|int
|
||||||
|
{
|
||||||
|
return $this->count ?: null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setValue(int $value) : void
|
||||||
|
{
|
||||||
|
$this->count = $value;
|
||||||
|
}
|
||||||
|
}
|
||||||
29
src/Option/KeyValueOption.php
Normal file
29
src/Option/KeyValueOption.php
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Mcnd\CLI\Option;
|
||||||
|
|
||||||
|
class KeyValueOption extends ParsedOption
|
||||||
|
{
|
||||||
|
protected array $values = [];
|
||||||
|
|
||||||
|
public function setValue(string $key, string $value) : void
|
||||||
|
{
|
||||||
|
$this->values[$key] = $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setRawValue(string $value) : void
|
||||||
|
{
|
||||||
|
if (! str_contains($value, '=')) {
|
||||||
|
throw new \RuntimeException(sprintf("A key=value notation was awaited, received %s instead", $value));
|
||||||
|
}
|
||||||
|
|
||||||
|
list($key, $value) = explode('=', trim($value), 2);
|
||||||
|
|
||||||
|
$this->setValue($key, $value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getValue() : null|array
|
||||||
|
{
|
||||||
|
return $this->values ?: null;
|
||||||
|
}
|
||||||
|
}
|
||||||
23
src/Option/MultipleValueOption.php
Normal file
23
src/Option/MultipleValueOption.php
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Mcnd\CLI\Option;
|
||||||
|
|
||||||
|
class MultipleValueOption extends ParsedOption
|
||||||
|
{
|
||||||
|
protected array $value;
|
||||||
|
|
||||||
|
public function addValue(string $value) : void
|
||||||
|
{
|
||||||
|
$this->value[] = $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setValue(array $value) : void
|
||||||
|
{
|
||||||
|
$this->value = $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getValue() : null|array
|
||||||
|
{
|
||||||
|
return $this->value ?? null;
|
||||||
|
}
|
||||||
|
}
|
||||||
14
src/Option/ParsedOption.php
Normal file
14
src/Option/ParsedOption.php
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Mcnd\CLI\Option;
|
||||||
|
|
||||||
|
use Mcnd\CLI\Option;
|
||||||
|
|
||||||
|
abstract class ParsedOption
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
public readonly Option $attribute,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
public abstract function getValue() : mixed;
|
||||||
|
}
|
||||||
23
src/Option/ToggleOption.php
Normal file
23
src/Option/ToggleOption.php
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Mcnd\CLI\Option;
|
||||||
|
|
||||||
|
class ToggleOption extends ParsedOption
|
||||||
|
{
|
||||||
|
protected bool $value = false;
|
||||||
|
|
||||||
|
public function toggle() : void
|
||||||
|
{
|
||||||
|
$this->value = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getValue() : null|true
|
||||||
|
{
|
||||||
|
return $this->value ?: null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function toggled() : bool
|
||||||
|
{
|
||||||
|
return (bool) $this->getValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
18
src/Option/ValueOption.php
Normal file
18
src/Option/ValueOption.php
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Mcnd\CLI\Option;
|
||||||
|
|
||||||
|
class ValueOption extends ParsedOption
|
||||||
|
{
|
||||||
|
protected string $value;
|
||||||
|
|
||||||
|
public function setValue(string $value) : void
|
||||||
|
{
|
||||||
|
$this->value = $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getValue() : null|string
|
||||||
|
{
|
||||||
|
return $this->value ?? null;
|
||||||
|
}
|
||||||
|
}
|
||||||
92
src/OptionStack.php
Normal file
92
src/OptionStack.php
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Mcnd\CLI;
|
||||||
|
|
||||||
|
class OptionStack
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
public array $options = []
|
||||||
|
) {}
|
||||||
|
|
||||||
|
public function merge(OptionStack|array $stack) : void
|
||||||
|
{
|
||||||
|
$this->options = array_merge($this->options, is_array($stack) ? $stack : $stack->options);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function append(Option $option) : void
|
||||||
|
{
|
||||||
|
$this->options[] = $option;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function get(string $switch) : Option|false
|
||||||
|
{
|
||||||
|
foreach($this->options as $option) {
|
||||||
|
if ($option->matchShortSwitch($switch) || $option->matchLongSwitch($switch)) {
|
||||||
|
return $option;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Matches the exact option (short or long switch) found from the stack
|
||||||
|
*
|
||||||
|
* @param string $switch
|
||||||
|
* @return Option|null
|
||||||
|
*/
|
||||||
|
public function matchOption(string $switch) : bool|Option
|
||||||
|
{
|
||||||
|
$matched = false;
|
||||||
|
|
||||||
|
# Long switch
|
||||||
|
if (str_starts_with($switch, '--')) {
|
||||||
|
$switch = substr($switch, 2);
|
||||||
|
|
||||||
|
foreach($this->options as $option) {
|
||||||
|
if ( $option->matchLongSwitch($switch) ) {
|
||||||
|
$matched = true;
|
||||||
|
|
||||||
|
if ( $option->awaitingValue() ) {
|
||||||
|
return $option;
|
||||||
|
}
|
||||||
|
# matching --switch
|
||||||
|
else {
|
||||||
|
$option->toggle();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} # Short switch
|
||||||
|
elseif (substr($switch, 0, 1) === '-') {
|
||||||
|
$switch = substr($switch, 1);
|
||||||
|
$split = str_split($switch);
|
||||||
|
|
||||||
|
foreach($split as $index => $singleSwitch) {
|
||||||
|
foreach ($this->options as $option) {
|
||||||
|
if ( $option->matchShortSwitch($singleSwitch) ) {
|
||||||
|
$matched = true;
|
||||||
|
|
||||||
|
if ( $option->awaitingValue() ) {
|
||||||
|
# matching -abcValueOfC
|
||||||
|
if ( $index < count($split) - 1 ) {
|
||||||
|
$option->value(substr($switch, $index + 1));
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
# matching -abc
|
||||||
|
else {
|
||||||
|
return $option;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$option->toggle();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $matched;
|
||||||
|
}
|
||||||
|
}
|
||||||
13
src/OptionValueTypeEnum.php
Normal file
13
src/OptionValueTypeEnum.php
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Mcnd\CLI;
|
||||||
|
|
||||||
|
enum OptionValueTypeEnum
|
||||||
|
{
|
||||||
|
case NoValue; # -s
|
||||||
|
case RequiredValue; # -s value / -svalue
|
||||||
|
case OptionalValue; # -s value / -svalue
|
||||||
|
case MultipleValue; # -s value1 -s value2 -svalue3 -sothervalue4 / --var value1 --var value2
|
||||||
|
case KeyValue; # -s key=value / --var key=value
|
||||||
|
case CountValue; # -ssss / -s 4 / --var 4
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user