main 2.1.0 → 2.2.0

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/README CHANGED
@@ -370,6 +370,26 @@ DOCS
370
370
  API section below
371
371
 
372
372
  HISTORY
373
+ 2.2.0
374
+ - added ability for parameter dsl error handlers to accept an argument,
375
+ this will be passed the current error. for example
376
+
377
+ argument(:x) do
378
+ arity 42
379
+
380
+ error do |e|
381
+ case e
382
+ when Parameter::Arity
383
+ ...
384
+ end
385
+ end
386
+
387
+ - refined the mode parsing a bit: modes can now be abbreviated to uniqness
388
+ and, when the mode is ambiuous, a nice error message is printed, for
389
+ example:
390
+
391
+ ambiguous mode: in = (inflate or install)?
392
+
373
393
  2.1.0
374
394
  - added custom error handling dsl for parameters, this includes the ability
375
395
  to prepend, append, or replace the standard error handlers:
@@ -186,6 +186,26 @@ DOCS
186
186
  API section below
187
187
 
188
188
  HISTORY
189
+ 2.2.0
190
+ - added ability for parameter dsl error handlers to accept an argument,
191
+ this will be passed the current error. for example
192
+
193
+ argument(:x) do
194
+ arity 42
195
+
196
+ error do |e|
197
+ case e
198
+ when Parameter::Arity
199
+ ...
200
+ end
201
+ end
202
+
203
+ - refined the mode parsing a bit: modes can now be abbreviated to uniqness
204
+ and, when the mode is ambiuous, a nice error message is printed, for
205
+ example:
206
+
207
+ ambiguous mode: in = (inflate or install)?
208
+
189
209
  2.1.0
190
210
  - added custom error handling dsl for parameters, this includes the ability
191
211
  to prepend, append, or replace the standard error handlers:
data/a.rb CHANGED
@@ -1,20 +1,18 @@
1
1
  require 'main'
2
2
 
3
- puts Main.version
4
-
5
3
  Main {
6
4
  argument 'x' do
7
- error :before do
5
+ arity 2
6
+
7
+ error :before do |e|
8
+ p e
8
9
  puts 'this fires *before* normal error handling using #instance_eval...'
9
10
  end
10
11
 
11
- error do
12
+ error do |e|
13
+ p e
12
14
  puts 'this fires *instead of* normal error handling using #instance_eval...'
13
15
  end
14
-
15
- error :after do
16
- puts 'this fires *after* normal error handling using #instance_eval...'
17
- end
18
16
  end
19
17
 
20
18
  run(){ p param['x'].given? }
@@ -2,7 +2,7 @@ module Main
2
2
  #
3
3
  # top level constants
4
4
  #
5
- Main::VERSION = '2.1.0' unless
5
+ Main::VERSION = '2.2.0' unless
6
6
  defined? Main::VERSION
7
7
  def self.version() Main::VERSION end
8
8
 
@@ -318,15 +318,25 @@ module Main
318
318
  def post_run() :hook end
319
319
 
320
320
  def mode_given?
321
- self.class.modes.find_by_mode argv.first, :quiet => true if argv.first
321
+ begin
322
+ modes.size > 0 and
323
+ argv.size > 0 and
324
+ modes.find_by_mode(argv.first)
325
+ rescue Mode::Ambiguous
326
+ true
327
+ end
322
328
  end
323
-
324
329
  def mode_run!
325
- mode = self.class.modes.find_by_mode argv.shift
326
- klass = self.class.modes[mode] or abort "bad mode <#{ mode }>"
330
+ mode = modes.find_by_mode argv.shift
331
+ klass = modes[mode] or abort "bad mode <#{ mode }>"
327
332
  main = klass.new @argv, @env, @opts
333
+ main.mode = mode
328
334
  main.run
329
335
  end
336
+ def modes
337
+ self.class.modes
338
+ end
339
+ attribute 'mode'
330
340
 
331
341
  def help! status = 0
332
342
  print usage.to_s
@@ -334,12 +344,12 @@ module Main
334
344
  end
335
345
 
336
346
  def handle_exception e
337
- if e.respond_to?(:before_handler)
338
- fcall(e, :before_handler, self)
347
+ if e.respond_to?(:error_handler_before)
348
+ fcall(e, :error_handler_before, self)
339
349
  end
340
350
 
341
- if e.respond_to?(:handler)
342
- fcall(e, :handler, self)
351
+ if e.respond_to?(:error_handler_instead)
352
+ fcall(e, :error_handler_instead, self)
343
353
  else
344
354
  if e.respond_to? :status
345
355
  exit_status(( e.status ))
@@ -352,8 +362,8 @@ module Main
352
362
  end
353
363
  end
354
364
 
355
- if e.respond_to?(:after_handler)
356
- fcall(e, :after_handler, self)
365
+ if e.respond_to?(:error_handler_after)
366
+ fcall(e, :error_handler_after, self)
357
367
  end
358
368
 
359
369
  exit_status(( exit_failure )) if exit_status == exit_success
@@ -376,5 +386,22 @@ module Main
376
386
  def handle_throw status
377
387
  exit(( Integer(status) rescue 0 ))
378
388
  end
389
+
390
+ %w[ before instead after ].each do |which|
391
+ module_eval <<-code
392
+ def error_handler_#{ which } *argv, &block
393
+ block.call *argv
394
+ end
395
+ code
396
+ end
397
+
398
+ def instance_eval_block *argv, &block
399
+ sc =
400
+ class << self
401
+ self
402
+ end
403
+ sc.module_eval{ define_method '__instance_eval_block', &block }
404
+ fcall self, '__instance_eval_block', *argv, &block
405
+ end
379
406
  end
380
407
  end
@@ -1,7 +1,7 @@
1
1
  class Mode < ::String
2
2
  class Error < ::StandardError; end
3
3
  class Duplicate < Error; end
4
- class Ambigous < Error
4
+ class Ambiguous < Error
5
5
  include Main::Softspoken
6
6
  end
7
7
 
@@ -31,7 +31,7 @@ class Mode < ::String
31
31
  when 1
32
32
  candidates.first
33
33
  else
34
- quiet ? nil : raise(Ambigous, m)
34
+ raise Ambiguous, "ambiguous mode: #{ m } = (#{ candidates.sort.join ' or ' })?"
35
35
  end
36
36
  end
37
37
  end
@@ -69,9 +69,9 @@ module Main
69
69
  attribute 'arity' => 1
70
70
  attribute 'required' => false
71
71
 
72
- attribute 'before_handler'
73
- attribute 'error_handler'
74
- attribute 'after_handler'
72
+ attribute 'error_handler_before'
73
+ attribute 'error_handler_instead'
74
+ attribute 'error_handler_after'
75
75
 
76
76
  def initialize name, *names, &block
77
77
  @names = Cast.list_of_string name, *names
@@ -189,28 +189,23 @@ module Main
189
189
  end
190
190
 
191
191
  def add_handlers e
192
- sc =
192
+ esc =
193
193
  class << e
194
194
  self
195
195
  end
196
196
 
197
197
  this = self
198
198
 
199
- if before_handler?
200
- sc.module_eval do
201
- define_method(:before_handler){|main| main.instance_eval &this.before_handler}
202
- end
203
- end
204
-
205
- if error_handler?
206
- sc.module_eval do
207
- define_method(:handler){|main| main.instance_eval &this.error_handler}
208
- end
209
- end
210
-
211
- if after_handler?
212
- sc.module_eval do
213
- define_method(:after_handler){|main| main.instance_eval &this.after_handler}
199
+ %w[ before instead after ].each do |which|
200
+ getter = "error_handler_#{ which }"
201
+ query = "error_handler_#{ which }?"
202
+ if send(query)
203
+ handler = send getter
204
+ esc.module_eval do
205
+ define_method(getter) do |main|
206
+ main.instance_eval_block self, &handler
207
+ end
208
+ end
214
209
  end
215
210
  end
216
211
  end
@@ -561,8 +556,8 @@ module Main
561
556
  p.arity?
562
557
  end
563
558
 
564
- def error which = :error, &block
565
- p.send "#{ which }_handler=", block
559
+ def error which = :instead, &block
560
+ p.send "error_handler_#{ which }=", block
566
561
  end
567
562
  end
568
563
 
@@ -83,6 +83,19 @@ module Main
83
83
  s << " [options]+"
84
84
  end
85
85
 
86
+ # help info
87
+ =begin
88
+ if main.modes.size > 0
89
+ modes = main.modes.keys.join('|')
90
+ s << "\n#{ main.name } (#{ modes }) help"
91
+ end
92
+ if main.mode_name != 'main'
93
+ s << "\n#{ main.name } #{ main.fully_qualified_mode.join ' ' } help"
94
+ else
95
+ s << "\n#{ main.name } help"
96
+ end
97
+ =end
98
+
86
99
  s
87
100
  end
88
101
 
File without changes
metadata CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.9.2
3
3
  specification_version: 1
4
4
  name: main
5
5
  version: !ruby/object:Gem::Version
6
- version: 2.1.0
7
- date: 2007-10-20 00:00:00 -06:00
6
+ version: 2.2.0
7
+ date: 2007-10-24 00:00:00 -06:00
8
8
  summary: main
9
9
  require_paths:
10
10
  - lib
@@ -34,7 +34,6 @@ files:
34
34
  - gen_readme.rb
35
35
  - install.rb
36
36
  - lib
37
- - lib/arrayfields.rb
38
37
  - lib/main
39
38
  - lib/main/arrayfields.rb
40
39
  - lib/main/attributes.rb
@@ -50,7 +49,7 @@ files:
50
49
  - lib/main/usage.rb
51
50
  - lib/main/util.rb
52
51
  - lib/main.rb
53
- - main-2.0.0.gem
52
+ - main-2.2.0.gem
54
53
  - README
55
54
  - README.tmpl
56
55
  - samples
@@ -1,434 +0,0 @@
1
- #
2
- # The ArrayFields module implements methods which allow an Array to be indexed
3
- # by String or Symbol. It is not required to manually use this module to
4
- # extend Arrays - they are auto-extended on a per-object basis when
5
- # Array#fields= is called
6
- #
7
- module ArrayFields
8
- self::VERSION = '4.5.0' unless defined? self::VERSION
9
- def self.version() VERSION end
10
- #
11
- # multiton cache of fields - wraps fields and fieldpos map to save memory
12
- #
13
- class FieldSet
14
- class << self
15
- def new fields
16
- @sets[fields] ||= super
17
- end
18
- def init_sets
19
- @sets = {}
20
- end
21
- end
22
-
23
- init_sets
24
-
25
- attr :fields
26
- attr :fieldpos
27
- def initialize fields
28
- raise ArgumentError, "<#{ fields.inspect }> not inject-able" unless
29
- fields.respond_to? :inject
30
-
31
- @fieldpos =
32
- fields.inject({}) do |h, f|
33
- unless String === f or Symbol === f
34
- raise ArgumentError, "<#{ f.inspect }> neither String nor Symbol"
35
- end
36
- h[f] = h.size
37
- h
38
- end
39
-
40
- @fields = fields
41
- end
42
- def pos f
43
- return @fieldpos[f] if @fieldpos.has_key? f
44
- f = f.to_s
45
- return @fieldpos[f] if @fieldpos.has_key? f
46
- f = f.intern
47
- return @fieldpos[f] if @fieldpos.has_key? f
48
- nil
49
- end
50
- end
51
- #
52
- # methods redefined to work with fields as well as numeric indexes
53
- #
54
- def [] idx, *args
55
- if @fieldset and (String === idx or Symbol === idx)
56
- pos = @fieldset.pos idx
57
- return nil unless pos
58
- super(pos, *args)
59
- else
60
- super
61
- end
62
- end
63
- def slice idx, *args
64
- if @fieldset and (String === idx or Symbol === idx)
65
- pos = @fieldset.pos idx
66
- return nil unless pos
67
- super(pos, *args)
68
- else
69
- super
70
- end
71
- end
72
-
73
- def []=(idx, *args)
74
- if @fieldset and (String === idx or Symbol === idx)
75
- pos = @fieldset.pos idx
76
- unless pos
77
- @fieldset.fields << idx
78
- @fieldset.fieldpos[idx] = pos = size
79
- end
80
- super(pos, *args)
81
- else
82
- super
83
- end
84
- end
85
- def at idx
86
- if @fieldset and (String === idx or Symbol === idx)
87
- pos = @fieldset.pos idx
88
- return nil unless pos
89
- super pos
90
- else
91
- super
92
- end
93
- end
94
- def delete_at idx
95
- if @fieldset and (String === idx or Symbol === idx)
96
- pos = @fieldset.pos idx
97
- return nil unless pos
98
- super pos
99
- else
100
- super
101
- end
102
- end
103
- def fill(obj, *args)
104
- idx = args.first
105
- if idx and @fieldset and (String === idx or Symbol === idx)
106
- idx = args.shift
107
- pos = @fieldset.pos idx
108
- super(obj, pos, *args)
109
- else
110
- super
111
- end
112
- end
113
-
114
- def values_at(*idxs)
115
- idxs.flatten!
116
- if @fieldset
117
- idxs.map!{|i| (String === i or Symbol === i) ? @fieldset.pos(i) : i}
118
- end
119
- super(*idxs)
120
- end
121
- def indices(*idxs)
122
- idxs.flatten!
123
- if @fieldset
124
- idxs.map!{|i| (String === i or Symbol === i) ? @fieldset.pos(i) : i}
125
- end
126
- super(*idxs)
127
- end
128
- def indexes(*idxs)
129
- idxs.flatten!
130
- if @fieldset
131
- idxs.map!{|i| (String === i or Symbol === i) ? @fieldset.pos(i) : i}
132
- end
133
- super(*idxs)
134
- end
135
-
136
- def slice!(*args)
137
- ret = self[*args]
138
- self[*args] = nil
139
- ret
140
- end
141
- def each_with_field
142
- each_with_index do |elem, i|
143
- yield elem, @fieldset.fields[i]
144
- end
145
- end
146
- #
147
- # methods which give a hash-like interface
148
- #
149
- def each_pair
150
- each_with_index do |elem, i|
151
- yield @fieldset.fields[i], elem
152
- end
153
- end
154
- def each_key
155
- @fieldset.each{|field| yield field}
156
- end
157
- def each_value *args, &block
158
- each *args, &block
159
- end
160
- def fetch key
161
- self[key] or raise IndexError, 'key not found'
162
- end
163
-
164
- def has_key? key
165
- @fieldset.fields.include? key
166
- end
167
- def member? key
168
- @fieldset.fields.include? key
169
- end
170
- def key? key
171
- @fieldset.fields.include? key
172
- end
173
-
174
- def has_value? value
175
- if respond_to? 'include?'
176
- self.include? value
177
- else
178
- a = []
179
- each{|val| a << val}
180
- a.include? value
181
- end
182
- end
183
- def value? value
184
- if respond_to? 'include?'
185
- self.include? value
186
- else
187
- a = []
188
- each{|val| a << val}
189
- a.include? value
190
- end
191
- end
192
-
193
- def keys
194
- fields
195
- end
196
- def store key, value
197
- self[key] = value
198
- end
199
- def values
200
- if respond_to? 'to_ary'
201
- self.to_ary
202
- else
203
- a = []
204
- each{|val| a << val}
205
- a
206
- end
207
- end
208
-
209
- def to_hash
210
- if respond_to? 'to_ary'
211
- h = {}
212
- @fieldset.fields.zip(to_ary){|f,e| h[f] = e}
213
- h
214
- else
215
- a = []
216
- each{|val| a << val}
217
- h = {}
218
- @fieldset.fields.zip(a){|f,e| h[f] = e}
219
- h
220
- end
221
- end
222
- def to_h
223
- if respond_to? 'to_ary'
224
- h = {}
225
- @fieldset.fields.zip(to_ary){|f,e| h[f] = e}
226
- h
227
- else
228
- a = []
229
- each{|val| a << val}
230
- h = {}
231
- @fieldset.fields.zip(a){|f,e| h[f] = e}
232
- h
233
- end
234
- end
235
-
236
- def update other
237
- other.each{|k,v| self[k] = v}
238
- to_hash
239
- end
240
- def replace other
241
- Hash === other ? update(other) : super
242
- end
243
- def invert
244
- to_hash.invert
245
- end
246
-
247
- def to_pairs
248
- fields.zip values
249
- end
250
- alias_method 'pairs', 'to_pairs'
251
-
252
- def copy
253
- cp = clone
254
- cp.fields = fields.clone
255
- cp
256
- end
257
-
258
- alias_method 'dup', 'copy'
259
- alias_method 'clone', 'copy'
260
-
261
- def deepcopy
262
- cp = Marshal.load(Marshal.dump(self))
263
- cp.fields = Marshal.load(Marshal.dump(self.fields))
264
- cp
265
- end
266
- end
267
- Arrayfields = ArrayFields
268
-
269
- module Arrayfields
270
- def self.new *pairs
271
- pairs = pairs.map{|pair| Enumerable === pair ? pair.to_a : pair}.flatten
272
- raise ArgumentError, "pairs must be evenly sized" unless(pairs.size % 2 == 0)
273
- (( array = [] )).fields = []
274
- 0.step(pairs.size - 2, 2) do |a|
275
- b = a + 1
276
- array[ pairs[a] ] = pairs[b]
277
- end
278
- array
279
- end
280
- def self.[] *pairs
281
- new *pairs
282
- end
283
- end
284
- def Arrayfields(*a, &b) Arrayfields.new(*a, &b) end
285
- #
286
- # Fieldable encapsulates methods in common for classes which may have their
287
- # fields set and subsequently be auto-extended by ArrayFields
288
- #
289
- module Fieldable
290
- #
291
- # sets fields an dynamically extends this Array instance with methods for
292
- # keyword access
293
- #
294
- def fields= fields
295
- extend ArrayFields unless ArrayFields === self
296
-
297
- @fieldset =
298
- if ArrayFields::FieldSet === fields
299
- fields
300
- else
301
- ArrayFields::FieldSet.new fields
302
- end
303
- end
304
- #
305
- # access to fieldset
306
- #
307
- attr_reader :fieldset
308
- #
309
- # access to field list
310
- #
311
- def fields
312
- @fieldset and @fieldset.fields
313
- end
314
- end
315
- #
316
- # Array instances are extened with two methods only: Fieldable#fields= and
317
- # Fieldable#fields. only when Fieldable#fields= is called will the full set
318
- # of ArrayFields methods auto-extend the Array instance. the Array class also
319
- # has added a class generator when the fields are known apriori.
320
- #
321
- class Array
322
- include Fieldable
323
-
324
- class << self
325
- def struct *fields
326
- fields = fields.flatten
327
- Class.new(self) do
328
- include ArrayFields
329
- const_set :FIELDS, ArrayFields::FieldSet.new(fields)
330
- fields.each do |field|
331
- field = field.to_s
332
- if field =~ %r/^[a-zA-Z_][a-zA-Z0-9_]*$/
333
- begin
334
- module_eval <<-code
335
- def #{ field } *a
336
- a.size == 0 ? self['#{ field }'] : (self.#{ field } = a.shift)
337
- end
338
- def #{ field }= value
339
- self['#{ field }'] = value
340
- end
341
- code
342
- rescue SyntaxError
343
- :by_ignoring_it
344
- end
345
- end
346
- end
347
- def initialize *a, &b
348
- super
349
- ensure
350
- @fieldset = self.class.const_get :FIELDS
351
- end
352
- def self.[] *elements
353
- array = new
354
- array.replace elements
355
- array
356
- end
357
- end
358
- end
359
- def fields *fields, &block
360
- (( array = new(&block) )).fields = fields.map{|x| Enumerable === x ? x.to_a : x}.flatten
361
- array
362
- end
363
- end
364
- end
365
- #
366
- # proxy class that allows an array to be wrapped in a way that still allows #
367
- # keyword access. also facilitate usage of ArrayFields with arraylike objects.
368
- # thnx to Sean O'Dell for the suggestion.
369
- #
370
- # sample usage
371
- #
372
- # fa = FieldedArray.new %w(zero one two), [0,1,2]
373
- # p fa['zero'] #=> 0
374
- #
375
- #
376
- class FieldedArray
377
- include Fieldable
378
- class << self
379
- def [](*pairs)
380
- pairs.flatten!
381
- raise ArgumentError, "argument must be key/val pairs" unless
382
- (pairs.size % 2 == 0)
383
- fields, elements = [], []
384
- while((f = pairs.shift) and (e = pairs.shift))
385
- fields << f and elements << e
386
- end
387
- new fields, elements
388
- end
389
- end
390
- def initialize fields = [], array = []
391
- @a = array
392
- self.fields = fields
393
- end
394
- def method_missing(meth, *args, &block)
395
- @a.send(meth, *args, &block)
396
- end
397
- delegates =
398
- %w(
399
- to_s
400
- to_str
401
- inspect
402
- )
403
- delegates.each do |meth|
404
- class_eval "def #{ meth }(*a,&b); @a.#{ meth }(*a,&b);end"
405
- end
406
- end
407
- Fieldedarray = FieldedArray
408
-
409
- class PseudoHash < ::Array
410
- class << self
411
- def [](*pairs)
412
- pairs.flatten!
413
- raise ArgumentError, "argument must be key/val pairs" unless
414
- (pairs.size % 2 == 0 and pairs.size >= 2)
415
- keys, values = [], []
416
- while((k = pairs.shift) and (v = pairs.shift))
417
- keys << k and values << v
418
- end
419
- new keys, values
420
- end
421
- end
422
- def initialize keys = [], values = []
423
- self.fields = keys
424
- self.replace values
425
- end
426
- def to_yaml opts = {}
427
- YAML::quick_emit object_id, opts do |out|
428
- out.map taguri, to_yaml_style do |map|
429
- each_pair{|f,v| map.add f,v}
430
- end
431
- end
432
- end
433
- end
434
- Pseudohash = PseudoHash
Binary file