Skip to content

Commit 584410f

Browse files
committed
Support for options flags
1 parent b701ba5 commit 584410f

File tree

7 files changed

+107
-19
lines changed

7 files changed

+107
-19
lines changed

README.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,13 @@ $router = new cmdr\Cmdr();
2525
//All command functions will have Request as the last argument
2626
#[cmdr\attributes\Cmd("example", "altname")] //define as many cmds for this function as you want
2727
#[cmdr\attributes\Syntax("<required> [optional]")]
28+
#[cmdr\attributes\Options("--option", "--anotheroption")]
2829
function exampleFunc($additonal, $arguments, cmdr\Request $request) {
2930
echo $request->args["required"];
30-
if(isset($request->args["optional"])
31+
if(isset($request->args["optional"]))
3132
echo $request->args["optional"];
33+
if($request->getOpt('--option'))
34+
echo "--option was used";
3235
}
3336

3437
//Do this AFTER all functions you want to load are defined

src/Args.php

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
*/
1414
class Args implements \ArrayAccess, \Countable
1515
{
16-
public string $syntax;
1716
/**
1817
* @var Arg[] $args
1918
*/
@@ -24,14 +23,20 @@ class Args implements \ArrayAccess, \Countable
2423
*/
2524
protected array $parsed = Array();
2625

26+
/**
27+
* @var array $parsedOpts
28+
*/
29+
protected array $parsedOpts = Array();
30+
2731
/**
2832
* constructor.
2933
* @param string $syntax
34+
* @param array $opts
3035
* @throws SyntaxException Will throw if syntax is invalid
3136
*/
32-
function __construct(string $syntax)
37+
function __construct(public string $syntax, protected array $opts = [])
3338
{
34-
$this->syntax = $syntax;
39+
$this->opts = array_map('\strtolower', $this->opts);
3540
$argv = array_filter(explode(' ', $syntax));
3641
if (count($argv) == 0) {
3742
return;
@@ -82,6 +87,17 @@ function __construct(string $syntax)
8287
* @throws ParseException throws exception if required args arent provided
8388
*/
8489
public function parse(string $msg) : Args {
90+
$this->parsedOpts = [];
91+
$msg = explode(' ', $msg);
92+
$msgb = [];
93+
foreach ($msg as $w) {
94+
if(in_array($w, $this->opts))
95+
$this->parsedOpts[$w] = $w;
96+
else
97+
$msgb[] = $w;
98+
}
99+
$msg = implode(' ', $msgb);
100+
85101
$this->parsed = [];
86102
foreach ($this->args as $k => $v)
87103
$this->parsed[$k] = clone $v;
@@ -102,6 +118,14 @@ public function parse(string $msg) : Args {
102118
return clone $this;
103119
}
104120

121+
public function getOpts() {
122+
return $this->parsedOpts;
123+
}
124+
125+
public function getOpt($name) : bool {
126+
return isset($this->parsedOpts[strtolower($name)]);
127+
}
128+
105129
public function getArg(string $name): ?Arg {
106130
foreach ($this->parsed as &$arg) {
107131
if ($arg->name == $name) {

src/Cmd.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,13 @@ public function __construct(
1111
public $method,
1212
public array $preArgs,
1313
public array $postArgs,
14-
public string $syntax
14+
public string $syntax,
15+
public array $opts
1516
)
1617
{
1718
if(!is_callable($this->method)) {
1819
throw new \Exception("Method argument to Cmd isn't callable (" . print_r($method, 1) .")");
1920
}
20-
$this->cmdArgs = new Args($syntax);
21+
$this->cmdArgs = new Args($syntax, $opts);
2122
}
2223
}

src/Cmdr.php

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,14 @@ public function __construct()
1212
$this->cmds = new CIArray();
1313
}
1414

15-
function add(string $command, callable $method, array $preArgs = [], array $postArgs = [], string $syntax = '') {
15+
function add(string $command, callable $method, array $preArgs = [], array $postArgs = [], string $syntax = '', array $opts = []) {
1616
if (str_contains($command, '#')) {
1717
throw new \Exception('Command name cannot contain #');
1818
}
1919
if(isset($this->cmds[$command])) {
2020
throw new \Exception('Command already exists');
2121
}
22-
$this->cmds[$command] = new Cmd($command, $method, $preArgs, $postArgs, $syntax);
22+
$this->cmds[$command] = new Cmd($command, $method, $preArgs, $postArgs, $syntax, $opts);
2323
}
2424

2525
function get(string $command, string $text) : Request|false {
@@ -52,18 +52,22 @@ protected function attrAddCmd($rf, $f) {
5252
$sa = $syntaxAttr[0]->newInstance();
5353
$syntax = $sa->syntax;
5454
}
55+
5556
$callWrapAttr = $rf->getAttributes(attributes\CallWrap::class);
56-
if (isset($callWrapAttr[0])) {
57-
$cw = $callWrapAttr[0]->newInstance();
58-
$callWrapper = $cw->caller;
59-
$callWrapperPre = $cw->preArgs;
57+
if ($cw = ($callWrapAttr[0]??null)?->newInstance()) {
58+
$callWrapperPre = [...$cw->preArgs, $f];
59+
$f = $cw->caller;
6060
$callWrapperPost = $cw->postArgs;
6161
}
62+
63+
$optionsAttr = $rf->getAttributes(attributes\Options::class);
64+
$opts = [];
65+
if(isset($optionsAttr[0]))
66+
$opts = $optionsAttr[0]->newInstance()->options;
67+
68+
6269
foreach ($cmdAttr->args as $command) {
63-
if ($callWrapper != null)
64-
$this->cmds[$command] = new Cmd($command, $callWrapper, [...$callWrapperPre, $f], $callWrapperPost, $syntax);
65-
else
66-
$this->cmds[$command] = new Cmd($command, $f, $callWrapperPre, $callWrapperPost, $syntax);
70+
$this->cmds[$command] = new Cmd($command, $f, $callWrapperPre, $callWrapperPost, $syntax, $opts);
6771
}
6872
}
6973

src/attributes/Options.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?php
2+
3+
4+
namespace knivey\cmdr\attributes;
5+
6+
#[\Attribute]
7+
class Options
8+
{
9+
public array $options;
10+
public function __construct(string ...$options)
11+
{
12+
$this->options = $options;
13+
}
14+
}

tests/ArgsTest.php

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,4 +255,42 @@ function testArgWhenNotReq()
255255
$args->parse('moo boo poo woo');
256256
$this->assertCount(0, $args);
257257
}
258+
259+
260+
function testOptions()
261+
{
262+
$args = new Args('<foo>...', ['--nes']);
263+
$args->parse('moo boo poo');
264+
$this->assertEquals('moo boo poo', $args[0]);
265+
$this->assertEmpty($args->getOpts());
266+
$args->parse('moo --nes poo');
267+
$this->assertEquals('moo poo', $args[0]);
268+
$this->assertEquals(['--nes'=>'--nes'], $args->getOpts());
269+
270+
$args = new Args('<foo>', ['--nes']);
271+
$args->parse('moo boo poo');
272+
$this->assertEquals('moo', $args[0]);
273+
$this->assertEmpty($args->getOpts());
274+
$args->parse('moo --nes poo');
275+
$this->assertEquals('moo', $args[0]);
276+
$this->assertEquals(['--nes'=>'--nes'], $args->getOpts());
277+
278+
$args = new Args('[foo]', ['--nes']);
279+
$args->parse('moo boo poo');
280+
$this->assertEquals('moo', $args[0]);
281+
$this->assertEmpty($args->getOpts());
282+
$args->parse('--nes moo');
283+
$this->assertEquals('moo', $args[0]);
284+
$this->assertTrue($args->getOpt('--nes'));
285+
286+
$args = new Args('[foo]', ['--nes', '--bar']);
287+
$args->parse('moo --nes boo poo');
288+
$this->assertEquals('moo', $args[0]);
289+
$this->assertTrue($args->getOpt('--nes'));
290+
$this->assertFalse($args->getOpt('--bar'));
291+
$args->parse('--nes moo --bar');
292+
$this->assertEquals('moo', $args[0]);
293+
$this->assertTrue($args->getOpt('--nes'));
294+
$this->assertTrue($args->getOpt('--bar'));
295+
}
258296
}

tests/CmdrTest.php

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace knivey\cmdr\test;
44

5+
use knivey\cmdr\attributes\Options;
56
use knivey\cmdr\Cmdr;
67
use knivey\cmdr\Request;
78
use knivey\cmdr\attributes\Cmd;
@@ -44,10 +45,11 @@ public function testUsingAdd()
4445
$lol = function ($req) use(&$cnt) {
4546
$this->assertInstanceOf(Request::class, $req);
4647
$this->assertEquals('abc def', $req->args['stuff']);
48+
$this->assertEquals(['--bar'], $req->args->getOpts());
4749
$cnt++;
4850
};
49-
$cmdr->add('test', $lol, syntax: '<stuff>...');
50-
$cmdr->call('test', 'abc def');
51+
$cmdr->add('test', $lol, syntax: '<stuff>...', opts: ['--bar']);
52+
$cmdr->call('test', 'abc def --bar');
5153
$this->assertEquals(1, $cnt);
5254
}
5355

@@ -91,10 +93,11 @@ public function testLoadFuncs()
9193
$testFunc =
9294
function ($req) use(&$cnt) {
9395
$this->assertEquals('abc def', $req->args['foo']);
96+
$this->assertTrue($req->args->getOpt('--bar'));
9497
$cnt++;
9598
};
9699
$cmdr->loadFuncs();
97-
$cmdr->call('testattrs', 'abc def');
100+
$cmdr->call('testattrs', 'abc --bar def');
98101
$cmdr->call('noexist', 'abc def');
99102
$this->assertEquals(1, $cnt);
100103
}
@@ -167,6 +170,7 @@ public function testCallWrapAttribute()
167170

168171
#[Cmd("testAttrs")]
169172
#[Syntax("<foo>...")]
173+
#[Options("--bar")]
170174
function testAttrs(...$args) {
171175
global $testFunc;
172176
$testFunc(...$args);

0 commit comments

Comments
 (0)