choice 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG ADDED
@@ -0,0 +1,2 @@
1
+ 0.1.0:
2
+ - First release
data/LICENSE ADDED
@@ -0,0 +1,18 @@
1
+ Copyright (c) 2006 Chris Wanstrath
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
4
+ this software and associated documentation files (the "Software"), to deal in
5
+ the Software without restriction, including without limitation the rights to
6
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
7
+ the Software, and to permit persons to whom the Software is furnished to do so,
8
+ subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in all
11
+ copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
15
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
16
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
17
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
18
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README ADDED
@@ -0,0 +1,347 @@
1
+ = Welcome to Choice
2
+
3
+ Choice is a small library for defining and parsing command line options. It
4
+ works awesomely with Highline[http://highline.rubyforge.org/] or other command
5
+ line interface libraries.
6
+
7
+ Choice was written by Chris Wanstrath as an exercise in test driving development
8
+ of a DSL. We hope you find it useful. If you don't, we'd love to hear why.
9
+ This project is still an infant: bugs are expected and tattling on them is
10
+ appreciated.
11
+
12
+ Installing is easy, with RubyGems. Give it a shot:
13
+ $ gem install choice
14
+
15
+ If you are lost, you can find Choice at http://choice.rubyforge.org or
16
+ http://rubyforge.org/projects/choice/. E-mail inquiries can be directed to
17
+ mailto:chris[at]ozmm[dot]org.
18
+
19
+ Of course, Choice is licensed under the MIT License, which you can find included
20
+ in the LICENSE file or by surfing your World Wide Web browser of choice towards
21
+ http://www.opensource.org/licenses/mit-license.php.
22
+
23
+ == Using Choice
24
+
25
+ An +examples+ directory is included with Choice, in which some contrived Ruby
26
+ programs utilizing the library have been placed. Here's a snippet:
27
+
28
+ === ftpd.rb
29
+
30
+ require 'choice'
31
+
32
+ PROGRAM_VERSION = 4
33
+
34
+ Choice.options do
35
+ header ''
36
+ header 'Specific options:'
37
+
38
+ option :host do
39
+ short '-h'
40
+ long '--host=HOST'
41
+ desc 'The hostname or ip of the host to bind to (default 127.0.0.1)'
42
+ default '127.0.0.1'
43
+ end
44
+
45
+ option :port do
46
+ short '-p'
47
+ long '--port=PORT'
48
+ desc 'The port to listen on (default 21)'
49
+ cast Integer
50
+ default 21
51
+ end
52
+
53
+ separator ''
54
+ separator 'Common options: '
55
+
56
+ option :help do
57
+ long '--help'
58
+ desc 'Show this message'
59
+ end
60
+
61
+ option :version do
62
+ short '-v'
63
+ long '--version'
64
+ desc 'Show version'
65
+ action do
66
+ puts "ftpd.rb FTP server v#{PROGRAM_VERSION}"
67
+ exit
68
+ end
69
+ end
70
+ end
71
+
72
+ puts 'port: ' + Choice.choices[:port]
73
+
74
+ Notice the last line. For free, you will be given a <tt>Choice.choices</tt>
75
+ hash which contain, at runtime, the options found and their values.
76
+
77
+ Because we gave option <tt>:port</tt> a default of 21,
78
+ <tt>Choice.choices[:port]</tt> should be 21 if we run ftpd.rb with no options.
79
+ Let's see.
80
+
81
+ $ ruby ftpd.rb
82
+ port: 21
83
+
84
+ Cool. On our system, port 21 is reserved. Let's use another port.
85
+
86
+ $ ruby ftpd.rb -p 2100
87
+ port: 2100
88
+
89
+ Alright. And, of course, there is the hard way of doing things.
90
+
91
+ $ ruby ftpd.rb --port=2100
92
+ port: 2100
93
+
94
+ That <tt>:version</tt> option looks pretty interesting, huh? I wonder what it
95
+ does...
96
+
97
+ $ ruby ftpd.rb -v
98
+ ftpd.rb FTP server v4
99
+
100
+ That's not all, though. We also get a <tt>--help</tt> option for free.
101
+
102
+ $ ruby ftpd.rb --help
103
+ Usage: ftpd.rb [-hpv]
104
+
105
+ Specific options:
106
+ -h, --host=HOST The hostname or ip of the host to bind to (default 127.0.0.1)
107
+ -p, --port=PORT The port to listen on (default 21)
108
+
109
+ Common options:
110
+ --help Show this message
111
+ -v, --version Show version
112
+
113
+
114
+ == The Choice.choices hash
115
+
116
+ For better or worse, the <tt>Choice.choices</tt> hash is a bit lazy. It does
117
+ not care how you access it. Using the above example, assume we have a
118
+ <tt>:port</tt> option and we replace the last line of our program with the
119
+ following three lines:
120
+
121
+ puts 'port: ' + Choice.choices[:port]
122
+ puts 'port: ' + Choice.choices['port']
123
+ puts 'port: ' + Choice.choices.port
124
+
125
+ Now, run it.
126
+
127
+ $ ftpd.rb -p 2100
128
+ port: 2100
129
+ port: 2100
130
+ port: 2100
131
+
132
+ Lazy, huh?
133
+
134
+ Keep in mind that your option's key in the <tt>Choice.choices</tt> hash is
135
+ defined by the first parameter passed to option statement. This is perfectly
136
+ legit, albeit somewhat confusing:
137
+
138
+ option :name do
139
+ short '-h'
140
+ long '--handle=NAME'
141
+ desc "Your handle."
142
+ end
143
+
144
+ You can access this option by using <tt>Choice.choices[:name]</tt>, not
145
+ <tt>:handle</tt>.
146
+
147
+ == Option options
148
+
149
+ Obviously, Choice revolves around the <tt>option</tt> statement, which receives
150
+ a block. Here are all the, er, options +option+ accepts. None of them are
151
+ required but +short+ or +long+ must be present for Choice to know what to do.
152
+
153
+ Options must be defined in the context of a <tt>Choice.options</tt> block, as
154
+ seen above. This context is assumed for the following explanations.
155
+
156
+ For the quick learners, here's the list:
157
+ * short
158
+ * long
159
+ * default
160
+ * desc
161
+ * cast
162
+ * validate (takes regex)
163
+ * filter (takes a block)
164
+ * action (ditto)
165
+
166
+ You can define these within your option in any order which pleases you.
167
+
168
+ === short
169
+
170
+ Defines the short switch for an option. Expected to be a dash and a single
171
+ character.
172
+
173
+ === long
174
+
175
+ Defines the long switch for an option. Expected to be a double dash followed by
176
+ a string, an equal sign, and another string. No spaces.
177
+
178
+ There are two variants: longs where a parameter is required and longs where a
179
+ parameter is optional, in which case the value will be +true+ if the option is
180
+ present.
181
+
182
+ *Optional*:
183
+ long '--debug=[LEVEL]'
184
+
185
+ Assuming our program defines Choices and ends with this line:
186
+ puts 'debug: ' + Choice.choices[:debug]
187
+
188
+ we can do this:
189
+
190
+ $ ruby ftpd.rb --debug
191
+ debug: true
192
+
193
+ $ ruby ftpd.rb --debug=1
194
+ debug: 1
195
+
196
+ *Required*:
197
+ long '--debug=LEVEL'
198
+
199
+ Assuming the same as above:
200
+
201
+ $ ruby ftpd.rb --debug=1
202
+ debug: 1
203
+
204
+ $ ruby ftpd.rb --debug
205
+ <help screen printed>
206
+
207
+ === default
208
+
209
+ You can define a default value for your option, if you'd like. If the option
210
+ is not present in the argument list, the default will be returned when trying
211
+ to access that element of the <tt>Choice.choices</tt> hash.
212
+
213
+ As with the above, assume our program prints <tt>Choice.choices[:debug]</tt>:
214
+
215
+ default 'info'
216
+
217
+ If we don't pass in <tt>--debug</tt>, the <tt>:debug</tt> element of our hash
218
+ will be 'info.'
219
+
220
+ $ ftpd.rb
221
+ debug: info
222
+
223
+ $ ftpd.rb --debug=warn
224
+ debug: warn
225
+
226
+ === desc
227
+
228
+ The description of this option. Fairly straightforward, with one little trick:
229
+ multiple +desc+ statements in a single option will be considered new desc lines.
230
+ The desc lines will be printed in the order they are defined. Like this:
231
+
232
+ desc "Your hostname."
233
+ desc "(default 'localhost')"
234
+
235
+ A snippet from your <tt>--help</tt> might then look like this:
236
+
237
+ -h, --host=HOST Your hostname.
238
+ (default 127.0.0.1)
239
+
240
+
241
+ === cast
242
+
243
+ By default, all members of the <tt>Choice.choices</tt> hash are strings. If
244
+ you want something different, like an Integer for a port number, you can use
245
+ the +cast+ statement.
246
+
247
+ Currently support +cast+ options:
248
+
249
+ * Integer
250
+ * String
251
+ * Float
252
+ * Symbol
253
+
254
+ We'll probably add Date, Time, and DateTime in the future, if people want them.
255
+
256
+ === validate
257
+
258
+ The +validate+ statement accepts a regular expression which it will test
259
+ against the value passed. If the test fails, the <tt>--help</tt> screen will
260
+ be printed. I love ports, so let's stick with that example:
261
+
262
+ validate /^\d+$/
263
+
264
+ Of course, 2100 matches this:
265
+
266
+ $ ruby ftpd.rb -p 2100
267
+ port: 21000
268
+
269
+ I like dogs. I wish dogs could be ports. Alas, Choice knows better (once
270
+ I've told it so):
271
+
272
+ $ ruby ftpd.rb -p labradoodle
273
+ <help screen printed>
274
+
275
+ === filter
276
+
277
+ The +filter+ statement lets you play with a value before it goes into the
278
+ <tt>Choice.choices</tt> hash. If you use +cast+, this will occur post-casting.
279
+
280
+ In this program we're defining a :name option and saying we don't want any
281
+ crazy characters in it, then printing that element of the
282
+ <tt>Choice.choices</tt>+ hash:
283
+
284
+ filter do |value|
285
+ value = value.gsub(/[^\w]/, '')
286
+ end
287
+
288
+ Now:
289
+
290
+ $ ruby ftpd.rb --name=c.hr.is
291
+ name: chris
292
+
293
+ You can probably think of better uses.
294
+
295
+ === action
296
+
297
+ A block passed to the +action+ statement will be run if that particular option
298
+ is passed. See the <tt>--version</tt> example earlier.
299
+
300
+ == Other options
301
+
302
+ These statements are purely aesthetic, used to help make your <tt>--help</tt>
303
+ screen a little more digestible.
304
+
305
+ Passing an empty string to any of these options will print a newline.
306
+
307
+ === banner
308
+
309
+ The banner is the first line printed when your program is called with
310
+ <tt>--help</tt>. By default, it will be something like this, based on the
311
+ options defined:
312
+
313
+ Usage: ftpd.rb [-hpv]
314
+
315
+ You can pass any string to the +banner+ statement to override what prints. This
316
+ might be useful if you're into ascii art.
317
+
318
+ === header
319
+
320
+ The header is what shows up after the banner but before your option definitions
321
+ are printed. Each header call is a newline. Check out the example above.
322
+
323
+ === separator
324
+
325
+ As in the example above, you can put separators between options to help display
326
+ the logical groupings of your options. Or whatever.
327
+
328
+ === footer
329
+
330
+ The footer is displayed after all your options are displayed. Nothing new
331
+ here, works like the other options above.
332
+
333
+ == It looks like poetry
334
+
335
+ That's it. Not much, I know. Maybe this will make handling your command
336
+ line options a bit easier. You can always use the option parser in the standard
337
+ Ruby library, but DSLs are just so cool. As one of my non-programmer friends
338
+ said of a Ruby DSL: "It looks like poetry."
339
+
340
+ == It's totally broken
341
+
342
+ Okay, I knew this would happen. Do me a favor, if you have time: run +rake+
343
+ from the Choice directory and send me the output (mailto:chris[at]ozmm[dot]org).
344
+ This'll run the unit tests. Also, if you would, send me a bit of information
345
+ on your platform. Choice was tested on OS X and RHEL with a 2.4 kernel but who
346
+ knows. Thanks a lot.
347
+
data/examples/ftpd.rb ADDED
@@ -0,0 +1,78 @@
1
+ $:.unshift "../lib"
2
+ require 'choice'
3
+
4
+ port = 21
5
+ PROGRAM_VERSION = 4
6
+
7
+ Choice.options do
8
+ #banner "Usage: ftpd.rb [options]"
9
+
10
+ header ""
11
+ header "Specific options:"
12
+
13
+ option :host do
14
+ short '-h'
15
+ long '--host=HOST'
16
+ desc "The hostname or ip of the host to bind to"
17
+ desc "(default 127.0.0.1)"
18
+ default '127.0.0.1'
19
+ end
20
+
21
+ option :port do
22
+ short '-p'
23
+ long '--port=PORT'
24
+ desc "The port to listen on (default 21)"
25
+ cast Integer
26
+ default port
27
+ end
28
+
29
+ option :clients do
30
+ short '-c'
31
+ long '--clients=NUM'
32
+ cast Integer
33
+ desc "The number of connections to allow at once (default 5)"
34
+ default 5
35
+ end
36
+
37
+ option :yaml_cfg do
38
+ long '--config=FILE'
39
+ desc 'Load configuration from YAML file'
40
+ end
41
+
42
+ option :sample do
43
+ long '--sample'
44
+ desc "See a sample YAML config file"
45
+ action do
46
+ puts "See!"
47
+ exit
48
+ end
49
+ end
50
+
51
+ option :debug do
52
+ short '-d'
53
+ long '--debug'
54
+ desc 'Turn on debugging mode'
55
+ end
56
+
57
+ separator ''
58
+ separator 'Common options: '
59
+
60
+ option :help do
61
+ long '--help'
62
+ desc 'Show this message'
63
+ end
64
+
65
+ option :version do
66
+ short '-v'
67
+ long '--version'
68
+ desc 'Show version'
69
+ action do
70
+ puts "ftpd.rb FTP server v#{PROGRAM_VERSION}"
71
+ exit
72
+ end
73
+ end
74
+
75
+ end
76
+
77
+ print "Choices: "
78
+ puts Choice.choices.inspect