Skip to content

Commit

Permalink
Replace template parameters with function arguments in custom parsing (
Browse files Browse the repository at this point in the history
…#174)

* Replace template parameters with function arguments in custom parsing

* Update readme

* Update readme

* Update documentation
  • Loading branch information
andrey-zherikov authored Oct 30, 2024
1 parent b482fea commit 9326b70
Show file tree
Hide file tree
Showing 19 changed files with 1,358 additions and 1,048 deletions.
26 changes: 21 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,17 @@

### Breaking changes

* Custom error handler function (`Config.errorHandler`) now receives message text with ANSI styling if styling is enabled. One can use `argparse.ansi.getUnstyledText` function to remove any styling - this function returns a range of unstyled `string` objects which can be used as is or `join`'ed into a string if needed: `message.getUnstyledText.join`.
* Changes in `Config`:

* `Config.namedArgChar` is renamed to `Config.namedArgPrefix`.
* Custom error handler function (`Config.errorHandler`) now receives message text with ANSI styling if styling is enabled. One can use `argparse.ansi.getUnstyledText` function to remove any styling - this function returns a range of unstyled `string` objects which can be used as is or `join`'ed into a string if needed: `message.getUnstyledText.join`.

* `Config.endOfArgs` is renamed to `Config.endOfNamedArgs`.
* `Config.namedArgChar` is renamed to `Config.namedArgPrefix`.

* `Config.helpStyle` is renamed to `Config.styling`.
* `Config.endOfArgs` is renamed to `Config.endOfNamedArgs`.

* `Config.addHelp` is renamed to `Config.addHelpArgument`.
* `Config.helpStyle` is renamed to `Config.styling`.

* `Config.addHelp` is renamed to `Config.addHelpArgument`.

* `Style.namedArgumentName` is renamed to `Style.argumentName`.

Expand Down Expand Up @@ -57,6 +59,20 @@

* `@TrailingArguments` UDA is removed: all command line parameters that appear after double-dash `--` are considered as positional arguments. So if those parameters are to be parsed, use `@PositionalArgument` instead of `@TrailingArguments`.

* Functions for parsing customization (`PreValidation`, `Parse`, `Validation` and `Action`) now accept functions as runtime parameters instead of template arguments

For example, replace this
```d
.Parse !((string s) { return cast(char) s[1]; })
.Validation!((char v) { return v >= '0' && v <= '9'; })
```
with
```d
.Parse ((string s) { return cast(char) s[1]; })
.Validation((char v) { return v >= '0' && v <= '9'; })
```

* Dropped support for DMD-2.099.

### Enhancements and bug fixes

Expand Down
8 changes: 4 additions & 4 deletions docs/code_snippets/parsing_customization.d
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ import argparse;
struct T
{
@(NamedArgument
.PreValidation!((string s) { return s.length > 1 && s[0] == '!'; })
.Parse !((string s) { return s[1]; })
.Validation !((char v) { return v >= '0' && v <= '9'; })
.Action !((ref int a, char v) { a = v - '0'; })
.PreValidation((string s) { return s.length > 1 && s[0] == '!'; })
.Parse ((string s) { return cast(char) s[1]; })
.Validation ((char v) { return v >= '0' && v <= '9'; })
.Action ((ref int a, char v) { a = v - '0'; })
)
int a;
}
Expand Down
2 changes: 1 addition & 1 deletion docs/code_snippets/types_custom.d
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ struct Value
}
struct T
{
@(NamedArgument.Parse!((string s) { return Value(s); }))
@(NamedArgument.Parse((string s) { return Value(s); }))
Value s;
}

Expand Down
46 changes: 29 additions & 17 deletions docs/topics/Parsing-customization.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,16 +55,24 @@ Return value:
the following signatures:

- `ParseType parse(string value)`
- `ParseType parse(string[] value)`
- `ParseType parse(RawParam param)`
- `bool parse(ref ParseType receiver, RawParam param)`

`ParseType parse(string[] value)`

`ParseType parse(RawParam param)`

> `ParseType` is a type that a string value is supposed to be parsed to and it is not required be the same as
a type of destination - `argparse` tries to detect this type from provided function.
>
> `ParseType` must not be immutable or const.
>
{title="ParseType"}

- `void parse(ref ParseType receiver, RawParam param)`
- `Result parse(ref ParseType receiver, RawParam param)`

> `ParseType` is a type that a string value is supposed to be parsed to and it is not required be the same as
a type of destination - `argparse` tries to detect this type from provided function.
>
{title="ParseType"}
`bool parse(ref ParseType receiver, RawParam param)`

`Result parse(ref ParseType receiver, RawParam param)`


Parameters:

Expand All @@ -84,14 +92,14 @@ signatures:

`Result validate(ParseType value)`

- `bool validate(ParseType[] value)`

`Result validate(ParseType[] value)`

- `bool validate(Param!ParseType param)`

`Result validate(Param!ParseType param)`

> `ParseType` is a type that is used in `Parse` modifier or `string` if the latter is omitted.
>
{title="ParseType"}

Parameters:

- `value`/`param` contains a value returned from `Parse` step.
Expand All @@ -106,18 +114,22 @@ Return value:
`Action` modifier allows customizing a logic of how "destination" should be changed when argument has a value in
command line. It accepts a function with one of the following signatures:

- `bool action(ref T receiver, ParseType value)`

`void action(ref T receiver, ParseType value)`
- `void action(ref T receiver, ParseType value)`

- `Result action(ref T receiver, ParseType value)`
`bool action(ref T receiver, ParseType value)`

`bool action(ref T receiver, Param!ParseType param)`
`Result action(ref T receiver, ParseType value)`

- `void action(ref T receiver, Param!ParseType param)`

`bool action(ref T receiver, Param!ParseType param)`

`Result action(ref T receiver, Param!ParseType param)`

> `ParseType` is a type that is used in `Parse` modifier or `string` if the latter is omitted.
>
{title="ParseType"}

Parameters:

- `receiver` is a receiver (destination) which is supposed to be changed based on a `value`/`param`.
Expand Down
17 changes: 9 additions & 8 deletions docs/topics/reference/PositionalNamedArgument.md
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,7 @@ struct my_command
**Signature**
```C++
PreValidation(alias func)(auto ref ... argument)
PreValidation(auto ref ... argument, RETURN function(VALUE value) func)
```

**Parameters**
Expand All @@ -363,7 +363,7 @@ PreValidation(alias func)(auto ref ... argument)
```C++
struct my_command
{
@(NamedArgument.PreValidation!((string s) { return s.length > 0;}))
@(NamedArgument.PreValidation((string s) { return s.length > 0;}))
int a;
}
```
Expand All @@ -375,7 +375,8 @@ struct my_command
**Signature**
```C++
Parse(alias func)(auto ref ... argument)
Parse(auto ref ... argument, RECEIVER function(VALUE value) func)
Parse(auto ref ... argument, RETURN function(ref RECEIVER receiver, RawParam param) func)
```

**Parameters**
Expand All @@ -389,7 +390,7 @@ Parse(alias func)(auto ref ... argument)
```C++
struct my_command
{
@(NamedArgument.Parse!((string s) { return s[1]; }))
@(NamedArgument.Parse((string s) { return s[1]; }))
char a;
}
```
Expand All @@ -401,7 +402,7 @@ struct my_command
**Signature**
```C++
Validation(alias func)(auto ref ... argument)
Validation(auto ref ... argument, RETURN function(VALUE value) func)
```

**Parameters**
Expand All @@ -415,7 +416,7 @@ Validation(alias func)(auto ref ... argument)
```C++
struct my_command
{
@(NamedArgument.Validation!((int a) { return a >= 0 && a <= 9; }))
@(NamedArgument.Validation((int a) { return a >= 0 && a <= 9; }))
int a;
}
```
Expand All @@ -427,7 +428,7 @@ struct my_command
**Signature**
```C++
Action(alias func)(auto ref ... argument)
Action(auto ref ... argument, RETURN function(ref RECEIVER receiver, VALUE value) func)
```

**Parameters**
Expand All @@ -441,7 +442,7 @@ Action(alias func)(auto ref ... argument)
```C++
struct my_command
{
@(NamedArgument.Action!((ref int a, int v) { a += v; })
@(NamedArgument.Action((ref int a, int v) { a += v; })
int a;
}
```
30 changes: 15 additions & 15 deletions source/argparse/api/ansi.d
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ module argparse.api.ansi;
import argparse.config;
import argparse.param;
import argparse.api.argument: NamedArgument, Description, NumberOfValues, AllowedValues, Parse, Action, ActionNoValue;
import argparse.internal.parsehelpers: PassThrough;

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Public API for ANSI coloring
Expand All @@ -13,9 +12,9 @@ import argparse.internal.parsehelpers: PassThrough;
.Description("Colorize the output. If value is omitted then 'always' is used.")
.AllowedValues!(["always","auto","never"])
.NumberOfValues(0, 1)
.Parse!(PassThrough)
.Action!(AnsiStylingArgument.action)
.ActionNoValue!(AnsiStylingArgument.action)
.Parse((string _) => _)
.Action(AnsiStylingArgument.action)
.ActionNoValue(AnsiStylingArgument.actionNoValue)
)
private struct AnsiStylingArgument
{
Expand All @@ -26,39 +25,40 @@ private struct AnsiStylingArgument
return isEnabled;
}

private static void action(ref AnsiStylingArgument receiver, RawParam param)
private enum action = (ref AnsiStylingArgument receiver, Param!string param)
{
switch(param.value[0])
switch(param.value)
{
case "auto": isEnabled = param.config.stylingMode == Config.StylingMode.on; return;
case "always": isEnabled = true; return;
case "never": isEnabled = false; return;
default:
}
}
private static void action(ref AnsiStylingArgument receiver, Param!void param)
};

private enum actionNoValue = (ref AnsiStylingArgument receiver, Param!void param)
{
isEnabled = true;
}
};
}

unittest
{
AnsiStylingArgument arg;
AnsiStylingArgument.action(arg, Param!void.init);
AnsiStylingArgument.actionNoValue(arg, Param!void.init);
assert(arg);

AnsiStylingArgument.action(arg, RawParam(null, "", [""]));
AnsiStylingArgument.action(arg, Param!string(null, "", ""));
}

unittest
{
AnsiStylingArgument arg;

AnsiStylingArgument.action(arg, RawParam(null, "", ["always"]));
AnsiStylingArgument.action(arg, Param!string(null, "", "always"));
assert(arg);

AnsiStylingArgument.action(arg, RawParam(null, "", ["never"]));
AnsiStylingArgument.action(arg, Param!string(null, "", "never"));
assert(!arg);
}

Expand All @@ -68,11 +68,11 @@ unittest
AnsiStylingArgument arg;

config.stylingMode = Config.StylingMode.on;
AnsiStylingArgument.action(arg, RawParam(&config, "", ["auto"]));
AnsiStylingArgument.action(arg, Param!string(&config, "", "auto"));
assert(arg);

config.stylingMode = Config.StylingMode.off;
AnsiStylingArgument.action(arg, RawParam(&config, "", ["auto"]));
AnsiStylingArgument.action(arg, Param!string(&config, "", "auto"));
assert(!arg);
}

Expand Down
Loading

0 comments on commit 9326b70

Please sign in to comment.