Skip to content

Commit d932a66

Browse files
committed
Updated documentation. Added information on auto-binding.
1 parent a556e33 commit d932a66

File tree

5 files changed

+137
-22
lines changed

5 files changed

+137
-22
lines changed

J4JCommandLine.sln

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "docs", "docs", "{473DDAC4-C
2626
README.md = README.md
2727
docs\terminology.md = docs\terminology.md
2828
docs\text-converters.md = docs\text-converters.md
29-
docs\usage.md = docs\usage.md
29+
docs\usage-auto.md = docs\usage-auto.md
30+
docs\usage-explicit.md = docs\usage-explicit.md
3031
docs\validators.md = docs\validators.md
3132
EndProjectSection
3233
EndProject
@@ -41,7 +42,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "StaticPropertyExample", "ex
4142
EndProject
4243
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "InstancePropertyExample", "examples\InstancePropertyExample\InstancePropertyExample.csproj", "{6DA4542E-A31A-422C-815F-ABEFB4F00295}"
4344
EndProject
44-
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AutoBindExample", "examples\AutoBindExample\AutoBindExample.csproj", "{C5400387-BD0A-4E24-80B7-C532A8D1A216}"
45+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AutoBindExample", "examples\AutoBindExample\AutoBindExample.csproj", "{C5400387-BD0A-4E24-80B7-C532A8D1A216}"
4546
EndProject
4647
Global
4748
GlobalSection(SolutionConfigurationPlatforms) = preSolution

README.md

Lines changed: 9 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -16,23 +16,13 @@ builder.Prefixes( "-", "--", "/" )
1616
.Quotes( '\'', '"' )
1717
.HelpKeys( "h", "?" );
1818
19-
// create an instance of BindingTarget
20-
var binder = builder.Build<Program>(null);
19+
var binder = builder.AutoBind<Program>();
2120
if (binder == null)
22-
throw new NullReferenceException( nameof(Program) );
21+
throw new NullReferenceException(nameof(Program));
2322
24-
// define your options (here they're bound to public static properties)
25-
// there are fluent calls you can make to add default values,
26-
// validators, descriptions, etc.
27-
binder.Bind( x => Program.IntValue, "i" );
28-
binder.Bind( x => Program.TextValue, "t" );
23+
binder.Options[ "i" ]!.SetValidator( OptionInRange<int>.GreaterThan( 0 ) );
2924
30-
// bind the unkeyed parameters -- command line arguments that are
31-
// not options -- if you want to retrieve them (optional but commonly done)
32-
binder.BindUnkeyed( x => Program.Unkeyed );
33-
34-
// parse the command line
35-
if( !binder.Parse( args ) )
25+
if (!binder.Parse(args))
3626
{
3727
Environment.ExitCode = 1;
3828
return;
@@ -41,16 +31,18 @@ if( !binder.Parse( args ) )
4131
Console.WriteLine($"IntValue is {IntValue}");
4232
Console.WriteLine($"TextValue is {TextValue}");
4333
44-
Console.WriteLine( Unkeyed.Count == 0
34+
Console.WriteLine(Unkeyed.Count == 0
4535
? "No unkeyed parameters"
46-
: $"Unkeyed parameters: {string.Join( ", ", Unkeyed )}" );
36+
: $"Unkeyed parameters: {string.Join(", ", Unkeyed)}");
4737
```
4838

4939
### Table of Contents
5040

5141
- [Goal and Concept](docs/goal-concept.md)
5242
- [Terminology](docs/terminology.md)
53-
- [Usage](docs/usage.md)
43+
- Usage
44+
- [Autobinding](docs/usage-auto.md)
45+
- [Explicit binding](docs/usage-explicit.md)
5446
- [How Command Lines Are Allocated](docs/allocation.md)
5547
- Examples
5648
- [Binding to static properties](docs/example-static.md)

docs/usage-auto.md

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
### Usage: Automatic Binding
2+
3+
Automatic binding has the framework discover the properties you want to
4+
bind to options. You indicate the bound properties by decorating them
5+
with an `OptionKeys` attribute. Either static or instance properties can
6+
be used, provided they are publicly read/write and there is an ITextConverter
7+
type defined in the framework which supports their type.
8+
9+
There are other attributes you can use to provide additional information
10+
to the framework, to configure the bound options the way you want.
11+
12+
Here's an example, from the AutoBindExample project:
13+
14+
```
15+
using System;
16+
using System.Collections.Generic;
17+
using System.ComponentModel;
18+
using Autofac;
19+
using Autofac.Extensions.DependencyInjection;
20+
using J4JSoftware.CommandLine;
21+
using Microsoft.Extensions.DependencyInjection;
22+
23+
namespace AutoBindExample
24+
{
25+
class Program
26+
{
27+
static void Main(string[] args)
28+
{
29+
InitializeServiceProvider();
30+
31+
var builder = ServiceProvider.GetRequiredService<BindingTargetBuilder>();
32+
33+
builder.Prefixes("-", "--", "/")
34+
.Quotes('\'', '"')
35+
.HelpKeys("h", "?")
36+
.Description("a test program for exercising J4JCommandLine")
37+
.ProgramName($"{nameof(Program)}.exe");
38+
39+
var binder = builder.AutoBind<Program>();
40+
if (binder == null)
41+
throw new NullReferenceException(nameof(Program));
42+
43+
var intOption = binder.Options[ "i" ];
44+
if( intOption != null )
45+
intOption.SetValidator( OptionInRange<int>.GreaterThan( 0 ) );
46+
47+
if (!binder.Parse(args))
48+
{
49+
Environment.ExitCode = 1;
50+
return;
51+
}
52+
53+
Console.WriteLine($"IntValue is {IntValue}");
54+
Console.WriteLine($"TextValue is {TextValue}");
55+
56+
Console.WriteLine(Unkeyed.Count == 0
57+
? "No unkeyed parameters"
58+
: $"Unkeyed parameters: {string.Join(", ", Unkeyed)}");
59+
}
60+
61+
public static IServiceProvider ServiceProvider { get; set; }
62+
63+
[OptionKeys("i")]
64+
[DefaultValue(5)]
65+
[Description("some integer value")]
66+
public static int IntValue { get; set; }
67+
68+
[OptionKeys("t")]
69+
[DefaultValue("abc")]
70+
[Description("some text value")]
71+
public static string TextValue { get; set; }
72+
73+
[OptionKeys()]
74+
public static List<string> Unkeyed { get; set; }
75+
76+
private static void InitializeServiceProvider()
77+
{
78+
var builder = new ContainerBuilder();
79+
80+
builder.RegisterType<FancyConsole>()
81+
.AsImplementedInterfaces();
82+
83+
builder.AddJ4JCommandLine();
84+
85+
ServiceProvider = new AutofacServiceProvider(builder.Build());
86+
}
87+
}
88+
}
89+
```
90+
91+
All you do is create an instance of `BindingTargetBuilder` and then
92+
call `AutoBind<>` on it.
93+
94+
The attributes you can use to configure the bindings are:
95+
96+
| Attribute | Capability | Comments |
97+
| --------- | ---------- | -------- |
98+
| OptionKeys | defines the key(s) for the binding | **required** |
99+
| OptionRequired | makes the binding required or optional | optional |
100+
| DefaultValue | specifies a default value | optional |
101+
| Description | supplies a description | optional |
102+
103+
**Note**: *Because option validators are derived from a generic abstract
104+
base class you cannot specify validators through attributes*.
105+
106+
Instead, you must retrieve the option you want to validate from the
107+
binder's Options collection and then specify a validator for it. In the
108+
example this is done in the following lines:
109+
```
110+
var intOption = binder.Options[ "i" ];
111+
if( intOption != null )
112+
intOption.SetValidator( OptionInRange<int>.GreaterThan( 0 ) );
113+
```
114+
115+
There's a default/basic help/error display engine in the core library.
116+
But there's also one that produces fancier output defined in the
117+
FancyHelpError project. Here's what the output looks like:
118+
119+
![Fancy Help output](assets/fancy-help.png)

docs/usage.md renamed to docs/usage-explicit.md

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

3-
Using the library is straightforward. Here's the code from the
3+
With explicit binding you have to declare which properties are bound
4+
to which properties in your startup code. Here's an example, from the
45
StaticPropertyExample project:
56

67
```

examples/AutoBindExample/Program.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,9 @@ static void Main(string[] args)
2626
if (binder == null)
2727
throw new NullReferenceException(nameof(Program));
2828

29-
binder.Options[ "i" ]!.SetValidator( OptionInRange<int>.GreaterThan( 0 ) );
29+
var intOption = binder.Options[ "i" ];
30+
if( intOption != null )
31+
intOption.SetValidator( OptionInRange<int>.GreaterThan( 0 ) );
3032

3133
if (!binder.Parse(args))
3234
{

0 commit comments

Comments
 (0)