clip 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
data/History.txt CHANGED
@@ -1,4 +1,8 @@
1
- === 0.0.1 / 2008-04-03
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, then fill
16
- that Hash out then throw the parser away (unless you want to print
17
- out a usage message) and deal with a Hash? Why, for Pete's sake, should
18
- the parser and the parsed values be handled by two different objects?
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
- Well, now they don't...
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
- parser = Clip do |p|
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 parser.valid?
37
- if parser.verbose?
38
- puts parser.host
39
- puts parser.port
38
+ if options.valid?
39
+ if options.verbose?
40
+ puts options.host
41
+ puts options.port
40
42
  puts 'files:'
41
- parser.files.each do |f|
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 parser.to_s
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.1"
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
- eval <<-EOF
56
- def #{long}=(val)
57
- @#{long} = val
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
- def #{long}
61
- @#{long}
67
+ else
68
+ self.class.send(:define_method, "#{long}=".to_sym) do |v|
69
+ instance_variable_set(var_name, v)
62
70
  end
63
- EOF
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
- out << "Usage:\n"
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.1
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-04-10 00:00:00 -07:00
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: Command-line parsing made short and sweet
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: