1 /**
2  * Copyright: Copyright (c) 2011-2012 Jacob Carlborg. All rights reserved.
3  * Authors: Jacob Carlborg
4  * Version: Initial created: Apr 3, 2011
5  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0)
6  */
7 
8 module mambo.arguments.Options;
9 
10 import std.conv;
11 
12 import mambo.core._;
13 import mambo.arguments.Arguments;
14 import Internal = mambo.arguments.internal.Arguments;
15 
16 struct Options
17 {
18 	alias arguments this;
19 
20 	private Arguments arguments;
21 
22 	package this (Arguments arguments)
23 	{
24 		this.arguments = arguments;
25 	}
26 
27 	Option!(T) opCall (T = string) (char shortOption, string longOption, string helpText)
28 	{
29 		return opIndex!(T)(longOption).aliased(shortOption).help(helpText);
30 	}
31 
32 	Option!(T) opCall (T = string) (string longOption, string helpText)
33 	{
34 		return opIndex!(T)(longOption).help(helpText);
35 	}
36 
37 	Option!(T) opCall (T = string) (char shortOption, string helpText)
38 	{
39 		return opIndex!(T)(shortOption.toString).help(helpText);
40 	}
41 
42 	template opDispatch (string name)
43 	{
44 		@property Option!(T) opDispatch (T = string) ()
45 		{
46 			return opIndex!(T)(name);
47 		}
48 	}
49 
50 	Option!(T) opIndex (T = string) (string name)
51 	{
52 		return Option!(T)(arguments.internalArguments[name]);
53 	}
54 
55 	package @property Option!(int)[] options ()
56 	{
57 		return arguments.internalArguments.args.map!((k, v) => Option!(int)(v))
58 			.filter!(e => e.name.any)
59 			.toArray;
60 	}
61 }
62 
63 struct Option (T)
64 {
65 	private Internal.Arguments.Argument argument;
66 
67 	alias value this;
68 
69 	this (Internal.Arguments.Argument argument)
70 	{
71 		this.argument = argument;
72 	}
73 
74 	@property T value ()
75 	{
76 		static if (is(T == bool))
77 			return argument.set;
78 
79 		else
80 			return as!(T);
81 	}
82 
83 	@property bool hasValue ()
84 	{
85 		return argument.assigned.any;
86 	}
87 
88 	@property U as (U) ()
89 	{
90 		assert(hasValue);
91 		return to!(U)(rawValue);
92 	}
93 
94 	@property string rawValue ()
95 	{
96 		auto value = argument.assigned;
97 		return value.any ? cast(string) value.first : "";
98 	}
99 
100 	@property string name ()
101 	{
102 		return cast(string) argument.name;
103 	}
104 
105 	@property char[] aliases ()
106 	{
107 		return argument.aliases;
108 	}
109 
110 	@property string helpText ()
111 	{
112 		return cast(string) argument.text;
113 	}
114 
115 	@property int error ()
116 	{
117 		return argument.error;
118 	}
119 
120 	@property bool isPresent ()
121 	{
122 		return argument.set;
123 	}
124 
125 	@property bool isSet ()
126 	{
127 		return isPresent;
128 	}
129 
130 	@property int min ()
131 	{
132 		return argument.min;
133 	}
134 
135 	@property int min (int value)
136 	{
137 		return argument.min = value;
138 	}
139 
140 	@property int max ()
141 	{
142 		return argument.max;
143 	}
144 
145 	@property int max (int value)
146 	{
147 		return argument.max = value;
148 	}
149 
150 	bool opCast (T : bool) ()
151 	{
152 		return isPresent;
153 	}
154 
155 	private T opCast (T) ()
156 	{
157 		return cast(T) this;
158 	}
159 
160 	Option aliased (char name)
161 	{
162 		argument.aliased(name);
163 		return this;
164 	}
165 
166 	Option help (string text)
167 	{
168 		argument.help(text);
169 		return this;
170 	}
171 
172 	Option defaults (string values)
173 	{
174 		argument.defaults(values);
175 		return this;
176 	}
177 
178 	Option defaults (scope string delegate () value)
179 	{
180 		argument.defaults(value);
181 		return this;
182 	}
183 
184 	Option params ()
185 	{
186 		argument.params();
187 		return this;
188 	}
189 
190 	Option params (int count)
191 	{
192 		argument.params(count);
193 		return this;
194 	}
195 
196 	Option params (int min, int max)
197 	{
198 		argument.params(min, max);
199 		return this;
200 	}
201 
202 	Option restrict (string[] options ...)
203 	{
204 		argument.restrict(options.dup);
205 		return this;
206 	}
207 
208 	Option on (scope void delegate (string value) dg)
209 	{
210 		alias Internal.Arguments.Argument.Inspector Inspector;
211 
212 		argument.bind(cast(Inspector) dg);
213 		return this;
214 	}
215 }