clip 0.0.1 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/History.txt +6 -2
- data/README.txt +20 -20
- data/bin/sample_parser +3 -1
- data/lib/clip.rb +29 -12
- data/spec/clip_spec.rb +22 -0
- metadata +3 -3
data/History.txt
CHANGED
@@ -1,4 +1,8 @@
|
|
1
|
-
=== 0.0.1 / 2008-04-
|
1
|
+
=== 0.0.1 / 2008-04-10
|
2
2
|
|
3
|
-
* Initial release for y'all to throw rotten veggies at
|
3
|
+
* Initial release for y'all to throw rotten veggies at.
|
4
4
|
|
5
|
+
=== 0.0.2 / 2008-05-20
|
6
|
+
|
7
|
+
* Cleaned up README
|
8
|
+
* Added support for late-binding option processing with blocks
|
data/README.txt
CHANGED
@@ -12,12 +12,12 @@ Cheers!
|
|
12
12
|
== FEATURES
|
13
13
|
|
14
14
|
You like command-line parsing, but you hate all of the bloat. Why
|
15
|
-
should you have to create a Hash, then create a parser,
|
16
|
-
|
17
|
-
|
18
|
-
|
15
|
+
should you have to create a Hash, then create a parser, fill the Hash
|
16
|
+
out then throw the parser away (unless you want to print out a usage
|
17
|
+
message) and deal with a Hash? Why, for Pete's sake, should the parser
|
18
|
+
and the parsed values be handled by two different objects?
|
19
19
|
|
20
|
-
|
20
|
+
Introducing Clip...
|
21
21
|
|
22
22
|
== SYNOPSIS:
|
23
23
|
|
@@ -26,31 +26,38 @@ And it goes a little something like this...
|
|
26
26
|
require "rubygems"
|
27
27
|
require "clip"
|
28
28
|
|
29
|
-
|
29
|
+
options = Clip do |p|
|
30
30
|
p.optional 's', 'server', :desc => 'The server name', :default => 'localhost'
|
31
|
-
p.optional 'p', 'port', :desc => 'The port', :default => 8080
|
31
|
+
p.optional 'p', 'port', :desc => 'The port', :default => 8080 do |v|
|
32
|
+
v.to_i # always deal with integers
|
33
|
+
end
|
32
34
|
p.required 'f', 'files', :multi => true, :desc => 'Files to send'
|
33
35
|
p.flag 'v', 'verbose', :desc => 'Make it chatty'
|
34
36
|
end
|
35
37
|
|
36
|
-
if
|
37
|
-
if
|
38
|
-
puts
|
39
|
-
puts
|
38
|
+
if options.valid?
|
39
|
+
if options.verbose?
|
40
|
+
puts options.host
|
41
|
+
puts options.port
|
40
42
|
puts 'files:'
|
41
|
-
|
43
|
+
options.files.each do |f|
|
42
44
|
puts "\t#{f}"
|
43
45
|
end
|
44
46
|
end
|
45
47
|
else
|
46
48
|
# print error message(s) and usage
|
47
|
-
$stderr.puts
|
49
|
+
$stderr.puts options.to_s
|
48
50
|
end
|
49
51
|
|
50
52
|
The names of the options and flags that you declare in the block are accessible
|
51
53
|
as methods on the returned object, reducing the amount of objects you have to
|
52
54
|
deal with when you're parsing command-line parameters.
|
53
55
|
|
56
|
+
You can optionally process parsed arguments by passing a block to the
|
57
|
+
<tt>required</tt> or <tt>optional</tt> methods which will set the value of the
|
58
|
+
option to the result of the block. The block will receive the parsed value and
|
59
|
+
should return whatever transformed value that is appropriate to your use case.
|
60
|
+
|
54
61
|
Simply invoking the <tt>to_s</tt> method on a parser instance will dump both the
|
55
62
|
correct usage and any errors encountered during parsing. No need for you to manage
|
56
63
|
the state of what's required and what isn't by yourself. Also, '--help' and '-h'
|
@@ -61,13 +68,6 @@ a named option or flag. Whatever remains on the command line that doesn't fit
|
|
61
68
|
either a flag or an option/value pair will be made available via the
|
62
69
|
<tt>remainder</tt> method of the returned object.
|
63
70
|
|
64
|
-
== PROBLEMS/DEFICIENCIES:
|
65
|
-
|
66
|
-
OK, some of your favorite <tt>OptionParser</tt> features are simply not here.
|
67
|
-
You know that cool thing you can do where you tell <tt>OptionParser</tt> the
|
68
|
-
class of the kind of object you would like to get for a particular argument?
|
69
|
-
Do you like that one? Well, too bad. We don't have that one. Deal with it.
|
70
|
-
|
71
71
|
== LICENSE:
|
72
72
|
|
73
73
|
(The MIT License)
|
data/bin/sample_parser
CHANGED
@@ -6,7 +6,9 @@ require File.join(File.dirname(__FILE__), "../lib/clip")
|
|
6
6
|
# This is a very simple example of how to use Clip
|
7
7
|
p = Clip do |c|
|
8
8
|
c.optional 's', 'server', :desc => 'The server name', :default => 'localhost'
|
9
|
-
c.optional 'p', 'port', :desc => 'The port', :default => 8080
|
9
|
+
c.optional 'p', 'port', :desc => 'The port', :default => 8080 do |v|
|
10
|
+
v.to_i
|
11
|
+
end
|
10
12
|
c.optional 'f', 'files', :desc => 'Files to upload', :multi => true
|
11
13
|
c.flag 'v', 'verbose', :desc => 'Make it verbose, man'
|
12
14
|
end
|
data/lib/clip.rb
CHANGED
@@ -13,7 +13,7 @@ def Clip(args=ARGV)
|
|
13
13
|
end
|
14
14
|
|
15
15
|
module Clip
|
16
|
-
VERSION = "0.0.
|
16
|
+
VERSION = "0.0.2"
|
17
17
|
|
18
18
|
##
|
19
19
|
# Indicates that the parser was incorrectly configured in the
|
@@ -27,6 +27,12 @@ module Clip
|
|
27
27
|
# because they were neither flags or option/value pairs
|
28
28
|
attr_reader :remainder
|
29
29
|
|
30
|
+
##
|
31
|
+
# Set the usage 'banner' displayed when calling <tt>to_s</tt> to
|
32
|
+
# display the usage message. If not set, the default will be used.
|
33
|
+
# If the value is set this completely replaces the default
|
34
|
+
attr_accessor :banner
|
35
|
+
|
30
36
|
##
|
31
37
|
# Declare an optional parameter for your parser. This creates an accessor
|
32
38
|
# method matching the <tt>long</tt> parameter. The <tt>short</tt> parameter
|
@@ -42,25 +48,31 @@ module Clip
|
|
42
48
|
# * <tt>desc</tt>: a helpful description (used for printing usage)
|
43
49
|
# * <tt>default</tt>: a default value to provide if one is not given
|
44
50
|
# * <tt>multi</tt>: indicates that mulitple values are okay for this param.
|
51
|
+
# * <tt>block</tt>: an optional block to process the parsed value
|
45
52
|
#
|
46
53
|
# Note that specifying the <tt>:multi</tt> option means that the parameter
|
47
54
|
# can be specified several times with different values, or that a single
|
48
55
|
# comma-separated value can be specified which will then be broken up into
|
49
56
|
# separate tokens.
|
50
|
-
def optional(short, long, options={})
|
57
|
+
def optional(short, long, options={}, &block)
|
51
58
|
short = short.to_sym
|
52
59
|
long = long.to_sym
|
53
60
|
check_args(short, long)
|
54
61
|
|
55
|
-
|
56
|
-
|
57
|
-
|
62
|
+
var_name = "@#{long}".to_sym
|
63
|
+
if block
|
64
|
+
self.class.send(:define_method, "#{long}=".to_sym) do |v|
|
65
|
+
instance_variable_set(var_name, block.call(v))
|
58
66
|
end
|
59
|
-
|
60
|
-
|
61
|
-
|
67
|
+
else
|
68
|
+
self.class.send(:define_method, "#{long}=".to_sym) do |v|
|
69
|
+
instance_variable_set(var_name, v)
|
62
70
|
end
|
63
|
-
|
71
|
+
end
|
72
|
+
|
73
|
+
self.class.send(:define_method, long.to_sym) do
|
74
|
+
instance_variable_get(var_name)
|
75
|
+
end
|
64
76
|
|
65
77
|
self.options[long] = Option.new(short, long, options)
|
66
78
|
self.options[short] = self.options[long]
|
@@ -75,8 +87,8 @@ module Clip
|
|
75
87
|
# will be invalid (i.e. where valid? returns <tt>false</tt>).
|
76
88
|
#
|
77
89
|
# This method takes the same options as the optional method.
|
78
|
-
def required(short, long, options={})
|
79
|
-
optional(short, long, options.merge({ :required => true }))
|
90
|
+
def required(short, long, options={}, &block)
|
91
|
+
optional(short, long, options.merge({ :required => true }), &block)
|
80
92
|
end
|
81
93
|
|
82
94
|
alias_method :req, :required
|
@@ -195,7 +207,12 @@ module Clip
|
|
195
207
|
# Returns a formatted <tt>String</tt> indicating the usage of the parser
|
196
208
|
def help
|
197
209
|
out = ""
|
198
|
-
|
210
|
+
if banner
|
211
|
+
out << "#{banner}\n"
|
212
|
+
else
|
213
|
+
out << "Usage:\n"
|
214
|
+
end
|
215
|
+
|
199
216
|
order.each do |option|
|
200
217
|
out << "#{option.usage}\n"
|
201
218
|
end
|
data/spec/clip_spec.rb
CHANGED
@@ -174,6 +174,16 @@ describe Clip do
|
|
174
174
|
out[1].should match(/missing required.*files/i)
|
175
175
|
out[2..-1].join("\n").strip.should == parser.help.strip
|
176
176
|
end
|
177
|
+
|
178
|
+
it "should support declaring a banner" do
|
179
|
+
opts = Clip('-v') do |p|
|
180
|
+
p.banner = "USAGE foo bar baz"
|
181
|
+
p.flag 'v', 'verbose', :desc => 'Provide verbose output'
|
182
|
+
end
|
183
|
+
|
184
|
+
out = opts.to_s.split("\n")
|
185
|
+
out[0].should == 'USAGE foo bar baz'
|
186
|
+
end
|
177
187
|
end
|
178
188
|
|
179
189
|
describe "Additional arguments" do
|
@@ -266,4 +276,16 @@ describe Clip do
|
|
266
276
|
end
|
267
277
|
end
|
268
278
|
end
|
279
|
+
|
280
|
+
describe "when specifying a block for a parameter" do
|
281
|
+
it "should run the block" do
|
282
|
+
opts = Clip("-v 123") do |c|
|
283
|
+
c.req 'v', 'value', :desc => 'The value' do |v|
|
284
|
+
v.to_i
|
285
|
+
end
|
286
|
+
end
|
287
|
+
|
288
|
+
opts.value.should == 123
|
289
|
+
end
|
290
|
+
end
|
269
291
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: clip
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Alex Vollmer
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2008-
|
12
|
+
date: 2008-05-20 00:00:00 -07:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -21,7 +21,7 @@ dependencies:
|
|
21
21
|
- !ruby/object:Gem::Version
|
22
22
|
version: 1.5.1
|
23
23
|
version:
|
24
|
-
description:
|
24
|
+
description: You like command-line parsing, but you hate all of the bloat. Why should you have to create a Hash, then create a parser, fill the Hash out then throw the parser away (unless you want to print out a usage message) and deal with a Hash? Why, for Pete's sake, should the parser and the parsed values be handled by two different objects?
|
25
25
|
email:
|
26
26
|
- alex.vollmer@gmail.com
|
27
27
|
executables:
|