cryptopunks 2.1.0 → 3.0.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.
@@ -1,381 +1,382 @@
1
-
2
- module Cryptopunks
3
-
4
-
5
- class Tool
6
- def run( args )
7
- Toolii.run( args )
8
- end
9
- end
10
-
11
-
12
-
13
- class Opts
14
- def merge_gli_options!( options = {} )
15
- # puts " update options:"
16
- # puts options.inspect
17
-
18
- @file = options[:file] if options[:file]
19
- @outdir = options[:dir] if options[:dir]
20
-
21
- @zoom = options[:zoom] if options[:zoom]
22
- @offset = options[:offset] if options[:offset]
23
-
24
- @seed = options[:seed] if options[:seed]
25
-
26
- @verbose = true if options[:verbose] == true
27
- end
28
-
29
-
30
- def verbose=(boolean) # add: alias for debug ??
31
- @verbose = boolean
32
- end
33
-
34
- def verbose?
35
- return false if @verbose.nil? # default verbose/debug flag is false
36
- @verbose == true
37
- end
38
-
39
- def file() @file || './punks.png'; end
40
- def file?() @file; end ## note: let's you check if file is set (or "untouched")
41
-
42
- def zoom() @zoom || 1; end
43
- def zoom?() @zoom; end
44
-
45
- def offset() @offset || 0; end
46
- def offset?() @offset; end
47
-
48
- def outdir() @outdir || '.'; end
49
- def outdir?() @outdir; end
50
-
51
- ### use a standard (default) seed - why? why not?
52
- def seed() @seed || 4142; end
53
- def seed?() @seed; end
54
-
55
-
56
-
57
- end # class Opts
58
-
59
-
60
-
61
- ## note: use gli "dsl" inside a class / namespace
62
- class Toolii
63
- extend GLI::App
64
-
65
- opts = Opts.new
66
-
67
-
68
- program_desc 'punk (or cryptopunk) command line tool'
69
-
70
- version Cryptopunks::VERSION
71
-
72
-
73
- desc "Zoom factor x2, x4, x8, etc."
74
- arg_name 'ZOOM'
75
- default_value opts.zoom
76
- flag [:z, :zoom], type: Integer
77
-
78
- desc "Start counting at offset"
79
- arg_name 'NUM'
80
- default_value opts.offset
81
- flag [:offset], type: Integer
82
-
83
-
84
- desc "Seed for random number generation / shuffle"
85
- arg_name 'NUM'
86
- default_value opts.seed
87
- flag [:seed], type: Integer
88
-
89
-
90
-
91
- desc "Output directory"
92
- arg_name 'DIR'
93
- default_value opts.outdir
94
- flag [:d, :dir,
95
- :o, :out, :outdir], type: String
96
-
97
-
98
- ### todo/check: move option to -t/--tile command only - why? why not?
99
- desc "True Official Genuine CryptoPunks™ all-in-one composite image"
100
- arg_name 'FILE'
101
- default_value opts.file
102
- flag [:f, :file], type: String
103
-
104
-
105
-
106
- ### global option (required)
107
- ## todo: add check that path is valid?? possible?
108
- desc '(Debug) Show debug messages'
109
- switch [:verbose], negatable: false ## todo: use -w for short form? check ruby interpreter if in use too?
110
-
111
-
112
-
113
- desc "Flip (vertically) all punk characters in all-in-one punk series composite (#{opts.file})"
114
- command [:f, :flip] do |c|
115
- c.action do |g,o,args|
116
- puts "==> reading >#{opts.file}<..."
117
- punks = ImageComposite.read( opts.file )
118
-
119
- ## note: for now always assume 24x24
120
- cols = punks.width / 24
121
- rows = punks.height / 24
122
- tile_width = 24
123
- tile_height = 24
124
-
125
- phunks = ImageComposite.new( cols, rows,
126
- width: tile_width,
127
- height: tile_height )
128
-
129
- punks.each do |punk|
130
- phunks << punk.flip_vertically
131
- end
132
-
133
- ## make sure outdir exits (default is current working dir e.g. .)
134
- FileUtils.mkdir_p( opts.outdir ) unless Dir.exist?( opts.outdir )
135
-
136
- ## note: allways assume .png extension for now
137
- basename = File.basename( opts.file, File.extname( opts.file ) )
138
- path = "#{opts.outdir}/#{basename}-flipped.png"
139
- puts "==> saving phunks flipped one-by-one by hand to >#{path}<..."
140
-
141
- phunks.save( path )
142
- puts 'Done.'
143
- end # action
144
- end # command flip
145
-
146
-
147
- desc "Shuffle all punk characters (randomly) in all-in-one punk series composite (#{opts.file})"
148
- command [:s, :shuffle] do |c|
149
- c.action do |g,o,args|
150
- puts "==> reading >#{opts.file}<..."
151
- punks = ImageComposite.read( opts.file )
152
-
153
- ## note: for now always assume 24x24
154
- cols = punks.width / 24
155
- rows = punks.height / 24
156
- tile_width = 24
157
- tile_height = 24
158
-
159
- phunks = ImageComposite.new( cols, rows,
160
- width: tile_width,
161
- height: tile_height )
162
-
163
- tiles = cols * rows
164
- indexes = (0..tiles-1).to_a
165
- srand( opts.seed ) ## note: for new reset **global** random seed and use (builtin) Array#shuffle
166
- puts " using random generation number seed >#{opts.seed}< for shuffle"
167
- indexes = indexes.shuffle
168
-
169
- ###
170
- # seed 4142 ends in [..., 7566, 828, 8987, 9777]
171
- # 333 ends in [..., 6067, 9635, 973, 8172]
172
-
173
-
174
- indexes.each_with_index do |old_index,new_index|
175
- puts " ##{old_index} now ##{new_index}"
176
- phunks << punks[old_index]
177
- end
178
-
179
- puts " all #{tiles} old index numbers (zero-based) for reference using seed #{opts.seed}:"
180
- puts indexes.inspect
181
-
182
- ## make sure outdir exits (default is current working dir e.g. .)
183
- FileUtils.mkdir_p( opts.outdir ) unless Dir.exist?( opts.outdir )
184
-
185
- ## note: allways assume .png extension for now
186
- basename = File.basename( opts.file, File.extname( opts.file ) )
187
- path = "#{opts.outdir}/#{basename}-#{opts.seed}.png"
188
- puts "==> saving p(h)unks shuffled one-by-one by hand to >#{path}<..."
189
-
190
- phunks.save( path )
191
- puts 'Done.'
192
- end # action
193
- end # command shuffle
194
-
195
-
196
-
197
-
198
-
199
-
200
-
201
- desc "Get punk characters via image tiles from all-in-one punk series composite (#{opts.file}) - for IDs use 0 to 9999"
202
- command [:t, :tile] do |c|
203
- c.action do |g,o,args|
204
-
205
- # puts "opts:"
206
- # puts opts.inspect
207
-
208
- puts "==> reading >#{opts.file}<..."
209
- punks = ImageComposite.read( opts.file )
210
-
211
-
212
- puts " setting zoom to #{opts.zoom}x" if opts.zoom != 1
213
-
214
- ## make sure outdir exits (default is current working dir e.g. .)
215
- FileUtils.mkdir_p( opts.outdir ) unless Dir.exist?( opts.outdir )
216
-
217
- args.each_with_index do |arg,index|
218
- punk_index = arg.to_i( 10 ) ## assume base 10 decimal
219
-
220
- punk = punks[ punk_index ]
221
-
222
- punk_name = "punk-" + "%04d" % (punk_index + opts.offset)
223
-
224
- ## if zoom - add x2,x4 or such
225
- if opts.zoom != 1
226
- punk = punk.zoom( opts.zoom )
227
- punk_name << "@#{opts.zoom}x"
228
- end
229
-
230
- path = "#{opts.outdir}/#{punk_name}.png"
231
- puts "==> (#{index+1}/#{args.size}) saving punk ##{punk_index+opts.offset} to >#{path}<..."
232
-
233
- punk.save( path )
234
- end
235
- puts 'Done.'
236
- end # action
237
- end # command tile
238
-
239
-
240
-
241
- desc 'Generate punk characters from text attributes (from scratch / zero) via builtin punk spritesheet'
242
- command [:g, :gen, :generate] do |c|
243
- c.action do |g,o,args|
244
-
245
- puts "==> generating >#{args.join( ' + ' )}<..."
246
- punk = Image.generate( *args )
247
-
248
- puts " setting zoom to #{opts.zoom}x" if opts.zoom != 1
249
-
250
- ## make sure outdir exits (default is current working dir e.g. .)
251
- FileUtils.mkdir_p( opts.outdir ) unless Dir.exist?( opts.outdir )
252
-
253
- punk_index = 0 ## assume base 10 decimal
254
- punk_name = "punk-" + "%04d" % (punk_index + opts.offset)
255
-
256
- ## if zoom - add x2,x4 or such
257
- if opts.zoom != 1
258
- punk = punk.zoom( opts.zoom )
259
- punk_name << "@#{opts.zoom}x"
260
- end
261
-
262
- path = "#{opts.outdir}/#{punk_name}.png"
263
- puts "==> saving punk ##{punk_index+opts.offset} to >#{path}<..."
264
-
265
- punk.save( path )
266
- puts 'Done.'
267
- end # action
268
- end # command generate
269
-
270
-
271
- desc 'Query (builtin off-chain) punk contract for punk text attributes by IDs - use 0 to 9999'
272
- command [:q, :query] do |c|
273
- c.action do |g,o,args|
274
-
275
- # puts "opts:"
276
- # puts opts.inspect
277
-
278
- args.each_with_index do |arg,index|
279
- punk_index = arg.to_i( 10 ) ## assume base 10 decimal
280
-
281
- puts "==> (#{index+1}/#{args.size}) punk ##{punk_index}..."
282
-
283
- attribute_names = CryptopunksData.punk_attributes( punk_index )
284
- ## downcase name and change spaces to underscore
285
- attribute_names = attribute_names.map do |name|
286
- name.downcase.gsub( ' ', '_' )
287
- end
288
-
289
- print " "
290
- print attribute_names.join( ' ' )
291
- print "\n"
292
- end
293
- puts 'Done.'
294
- end
295
- end
296
-
297
-
298
-
299
- desc 'List all punk archetype and attribute names from builtin punk spritesheet'
300
- command [:l, :ls, :list] do |c|
301
- c.action do |g,o,args|
302
-
303
- generator = Cryptopunks.generator
304
-
305
- puts "==> Archetypes"
306
- generator.meta.each do |rec|
307
- next unless rec.archetype?
308
-
309
- print " "
310
- print "%-30s" % "#{rec.name} / (#{rec.gender})"
311
- print " - #{rec.type}"
312
- print "\n"
313
- end
314
-
315
- puts ""
316
- puts "==> Attributes"
317
- generator.meta.each do |rec|
318
- next unless rec.attribute?
319
-
320
- print " "
321
- print "%-30s" % "#{rec.name} / (#{rec.gender})"
322
- print " - #{rec.type}"
323
- print "\n"
324
- end
325
-
326
- puts ""
327
- puts " See github.com/cryptopunksnotdead/punks.spritesheet for more."
328
- puts ""
329
-
330
- puts 'Done.'
331
- end # action
332
- end # command list
333
-
334
-
335
-
336
- pre do |g,c,o,args|
337
- opts.merge_gli_options!( g )
338
- opts.merge_gli_options!( o )
339
-
340
- if opts.verbose?
341
- ## LogUtils::Logger.root.level = :debug
342
- end
343
-
344
- ## logger.debug "Executing #{c.name}"
345
- true
346
- end
347
-
348
- post do |global,c,o,args|
349
- ## logger.debug "Executed #{c.name}"
350
- true
351
- end
352
-
353
-
354
- on_error do |e|
355
-
356
- if opts.verbose?
357
- puts e.backtrace
358
- end
359
-
360
- if e.is_a?( SystemExit )
361
- puts
362
- puts "*** error: system exit with status code ( #{e.status} )"
363
- exit( e.status ) ## try exit again to make sure error code gets passed along!!!
364
- else
365
- puts
366
- puts "*** error: #{e.message}"
367
- end
368
-
369
- ## note: was false # skip default error handling
370
-
371
- ## note: try true - false WILL SWALLOW exit codes and such
372
- ## - looks like it's still returning 0 (e.g. on unknown option or such)!!!!
373
- true
374
- end
375
-
376
-
377
- ### exit run(ARGV) ## note: use Toolii.run( ARGV ) outside of class
378
- end # class Toolii
379
- end # module Cryptopunks
380
-
381
-
1
+
2
+ module Punk
3
+
4
+
5
+ class Tool
6
+ def run( args )
7
+ Toolii.run( args )
8
+ end
9
+ end
10
+
11
+
12
+
13
+ class Opts
14
+ def merge_gli_options!( options = {} )
15
+ # puts " update options:"
16
+ # puts options.inspect
17
+
18
+ @file = options[:file] if options[:file]
19
+ @outdir = options[:dir] if options[:dir]
20
+
21
+ @zoom = options[:zoom] if options[:zoom]
22
+ @offset = options[:offset] if options[:offset]
23
+
24
+ @seed = options[:seed] if options[:seed]
25
+
26
+ @verbose = true if options[:verbose] == true
27
+ end
28
+
29
+
30
+ def verbose=(boolean) # add: alias for debug ??
31
+ @verbose = boolean
32
+ end
33
+
34
+ def verbose?
35
+ return false if @verbose.nil? # default verbose/debug flag is false
36
+ @verbose == true
37
+ end
38
+
39
+ def file() @file || './punks.png'; end
40
+ def file?() @file; end ## note: let's you check if file is set (or "untouched")
41
+
42
+ def zoom() @zoom || 1; end
43
+ def zoom?() @zoom; end
44
+
45
+ def offset() @offset || 0; end
46
+ def offset?() @offset; end
47
+
48
+ def outdir() @outdir || '.'; end
49
+ def outdir?() @outdir; end
50
+
51
+ ### use a standard (default) seed - why? why not?
52
+ def seed() @seed || 4142; end
53
+ def seed?() @seed; end
54
+
55
+
56
+
57
+ end # class Opts
58
+
59
+
60
+
61
+ ## note: use gli "dsl" inside a class / namespace
62
+ class Toolii
63
+ extend GLI::App
64
+
65
+ opts = Opts.new
66
+
67
+
68
+ program_desc 'punk (or cryptopunk) command line tool'
69
+
70
+ version Pixelart::Module::Cryptopunks::VERSION
71
+
72
+
73
+ desc "Zoom factor x2, x4, x8, etc."
74
+ arg_name 'ZOOM'
75
+ default_value opts.zoom
76
+ flag [:z, :zoom], type: Integer
77
+
78
+ desc "Start counting at offset"
79
+ arg_name 'NUM'
80
+ default_value opts.offset
81
+ flag [:offset], type: Integer
82
+
83
+
84
+ desc "Seed for random number generation / shuffle"
85
+ arg_name 'NUM'
86
+ default_value opts.seed
87
+ flag [:seed], type: Integer
88
+
89
+
90
+
91
+ desc "Output directory"
92
+ arg_name 'DIR'
93
+ default_value opts.outdir
94
+ flag [:d, :dir,
95
+ :o, :out, :outdir], type: String
96
+
97
+
98
+ ### todo/check: move option to -t/--tile command only - why? why not?
99
+ # desc "True Official Genuine CryptoPunks™ all-in-one composite image"
100
+ desc "All-in-one composite image"
101
+ arg_name 'FILE'
102
+ default_value opts.file
103
+ flag [:f, :file], type: String
104
+
105
+
106
+
107
+ ### global option (required)
108
+ ## todo: add check that path is valid?? possible?
109
+ desc '(Debug) Show debug messages'
110
+ switch [:verbose], negatable: false ## todo: use -w for short form? check ruby interpreter if in use too?
111
+
112
+
113
+
114
+ desc "Flip (vertically) all punk characters in all-in-one punk series composite (#{opts.file})"
115
+ command [:f, :flip] do |c|
116
+ c.action do |g,o,args|
117
+ puts "==> reading >#{opts.file}<..."
118
+ punks = ImageComposite.read( opts.file )
119
+
120
+ ## note: for now always assume 24x24
121
+ cols = punks.width / 24
122
+ rows = punks.height / 24
123
+ tile_width = 24
124
+ tile_height = 24
125
+
126
+ phunks = ImageComposite.new( cols, rows,
127
+ width: tile_width,
128
+ height: tile_height )
129
+
130
+ punks.each do |punk|
131
+ phunks << punk.flip_vertically
132
+ end
133
+
134
+ ## make sure outdir exits (default is current working dir e.g. .)
135
+ FileUtils.mkdir_p( opts.outdir ) unless Dir.exist?( opts.outdir )
136
+
137
+ ## note: allways assume .png extension for now
138
+ basename = File.basename( opts.file, File.extname( opts.file ) )
139
+ path = "#{opts.outdir}/#{basename}-flipped.png"
140
+ puts "==> saving phunks flipped one-by-one by hand to >#{path}<..."
141
+
142
+ phunks.save( path )
143
+ puts 'Done.'
144
+ end # action
145
+ end # command flip
146
+
147
+
148
+ desc "Shuffle all punk characters (randomly) in all-in-one punk series composite (#{opts.file})"
149
+ command [:s, :shuffle] do |c|
150
+ c.action do |g,o,args|
151
+ puts "==> reading >#{opts.file}<..."
152
+ punks = ImageComposite.read( opts.file )
153
+
154
+ ## note: for now always assume 24x24
155
+ cols = punks.width / 24
156
+ rows = punks.height / 24
157
+ tile_width = 24
158
+ tile_height = 24
159
+
160
+ phunks = ImageComposite.new( cols, rows,
161
+ width: tile_width,
162
+ height: tile_height )
163
+
164
+ tiles = cols * rows
165
+ indexes = (0..tiles-1).to_a
166
+ srand( opts.seed ) ## note: for new reset **global** random seed and use (builtin) Array#shuffle
167
+ puts " using random generation number seed >#{opts.seed}< for shuffle"
168
+ indexes = indexes.shuffle
169
+
170
+ ###
171
+ # seed 4142 ends in [..., 7566, 828, 8987, 9777]
172
+ # 333 ends in [..., 6067, 9635, 973, 8172]
173
+
174
+
175
+ indexes.each_with_index do |old_index,new_index|
176
+ puts " ##{old_index} now ##{new_index}"
177
+ phunks << punks[old_index]
178
+ end
179
+
180
+ puts " all #{tiles} old index numbers (zero-based) for reference using seed #{opts.seed}:"
181
+ puts indexes.inspect
182
+
183
+ ## make sure outdir exits (default is current working dir e.g. .)
184
+ FileUtils.mkdir_p( opts.outdir ) unless Dir.exist?( opts.outdir )
185
+
186
+ ## note: allways assume .png extension for now
187
+ basename = File.basename( opts.file, File.extname( opts.file ) )
188
+ path = "#{opts.outdir}/#{basename}-#{opts.seed}.png"
189
+ puts "==> saving p(h)unks shuffled one-by-one by hand to >#{path}<..."
190
+
191
+ phunks.save( path )
192
+ puts 'Done.'
193
+ end # action
194
+ end # command shuffle
195
+
196
+
197
+
198
+
199
+
200
+
201
+
202
+ desc "Get punk characters via image tiles from all-in-one punk series composite (#{opts.file}) - for IDs use 0 to 9999"
203
+ command [:t, :tile] do |c|
204
+ c.action do |g,o,args|
205
+
206
+ # puts "opts:"
207
+ # puts opts.inspect
208
+
209
+ puts "==> reading >#{opts.file}<..."
210
+ punks = ImageComposite.read( opts.file )
211
+
212
+
213
+ puts " setting zoom to #{opts.zoom}x" if opts.zoom != 1
214
+
215
+ ## make sure outdir exits (default is current working dir e.g. .)
216
+ FileUtils.mkdir_p( opts.outdir ) unless Dir.exist?( opts.outdir )
217
+
218
+ args.each_with_index do |arg,index|
219
+ punk_index = arg.to_i( 10 ) ## assume base 10 decimal
220
+
221
+ punk = punks[ punk_index ]
222
+
223
+ punk_name = "punk-" + "%04d" % (punk_index + opts.offset)
224
+
225
+ ## if zoom - add x2,x4 or such
226
+ if opts.zoom != 1
227
+ punk = punk.zoom( opts.zoom )
228
+ punk_name << "@#{opts.zoom}x"
229
+ end
230
+
231
+ path = "#{opts.outdir}/#{punk_name}.png"
232
+ puts "==> (#{index+1}/#{args.size}) saving punk ##{punk_index+opts.offset} to >#{path}<..."
233
+
234
+ punk.save( path )
235
+ end
236
+ puts 'Done.'
237
+ end # action
238
+ end # command tile
239
+
240
+
241
+
242
+ desc 'Generate punk characters from text attributes (from scratch / zero) via builtin punk spritesheet'
243
+ command [:g, :gen, :generate] do |c|
244
+ c.action do |g,o,args|
245
+
246
+ puts "==> generating >#{args.join( ' + ' )}<..."
247
+ punk = Image.generate( *args )
248
+
249
+ puts " setting zoom to #{opts.zoom}x" if opts.zoom != 1
250
+
251
+ ## make sure outdir exits (default is current working dir e.g. .)
252
+ FileUtils.mkdir_p( opts.outdir ) unless Dir.exist?( opts.outdir )
253
+
254
+ punk_index = 0 ## assume base 10 decimal
255
+ punk_name = "punk-" + "%04d" % (punk_index + opts.offset)
256
+
257
+ ## if zoom - add x2,x4 or such
258
+ if opts.zoom != 1
259
+ punk = punk.zoom( opts.zoom )
260
+ punk_name << "@#{opts.zoom}x"
261
+ end
262
+
263
+ path = "#{opts.outdir}/#{punk_name}.png"
264
+ puts "==> saving punk ##{punk_index+opts.offset} to >#{path}<..."
265
+
266
+ punk.save( path )
267
+ puts 'Done.'
268
+ end # action
269
+ end # command generate
270
+
271
+
272
+ desc 'Query (builtin off-chain) punk contract for punk text attributes by IDs - use 0 to 9999'
273
+ command [:q, :query] do |c|
274
+ c.action do |g,o,args|
275
+
276
+ # puts "opts:"
277
+ # puts opts.inspect
278
+
279
+ args.each_with_index do |arg,index|
280
+ punk_index = arg.to_i( 10 ) ## assume base 10 decimal
281
+
282
+ puts "==> (#{index+1}/#{args.size}) punk ##{punk_index}..."
283
+
284
+ attribute_names = CryptopunksData.punk_attributes( punk_index )
285
+ ## downcase name and change spaces to underscore
286
+ attribute_names = attribute_names.map do |name|
287
+ name.downcase.gsub( ' ', '_' )
288
+ end
289
+
290
+ print " "
291
+ print attribute_names.join( ' ' )
292
+ print "\n"
293
+ end
294
+ puts 'Done.'
295
+ end
296
+ end
297
+
298
+
299
+
300
+ desc 'List all punk archetype and attribute names from builtin punk spritesheet'
301
+ command [:l, :ls, :list] do |c|
302
+ c.action do |g,o,args|
303
+
304
+ generator = Image.generator
305
+
306
+ puts "==> Archetypes"
307
+ generator.meta.each do |rec|
308
+ next unless rec.archetype?
309
+
310
+ print " "
311
+ print "%-30s" % "#{rec.name} / (#{rec.gender})"
312
+ print " - #{rec.type}"
313
+ print "\n"
314
+ end
315
+
316
+ puts ""
317
+ puts "==> Attributes"
318
+ generator.meta.each do |rec|
319
+ next unless rec.attribute?
320
+
321
+ print " "
322
+ print "%-30s" % "#{rec.name} / (#{rec.gender})"
323
+ print " - #{rec.type}"
324
+ print "\n"
325
+ end
326
+
327
+ puts ""
328
+ puts " See github.com/cryptopunksnotdead/punks.spritesheet for more."
329
+ puts ""
330
+
331
+ puts 'Done.'
332
+ end # action
333
+ end # command list
334
+
335
+
336
+
337
+ pre do |g,c,o,args|
338
+ opts.merge_gli_options!( g )
339
+ opts.merge_gli_options!( o )
340
+
341
+ if opts.verbose?
342
+ ## LogUtils::Logger.root.level = :debug
343
+ end
344
+
345
+ ## logger.debug "Executing #{c.name}"
346
+ true
347
+ end
348
+
349
+ post do |global,c,o,args|
350
+ ## logger.debug "Executed #{c.name}"
351
+ true
352
+ end
353
+
354
+
355
+ on_error do |e|
356
+
357
+ if opts.verbose?
358
+ puts e.backtrace
359
+ end
360
+
361
+ if e.is_a?( SystemExit )
362
+ puts
363
+ puts "*** error: system exit with status code ( #{e.status} )"
364
+ exit( e.status ) ## try exit again to make sure error code gets passed along!!!
365
+ else
366
+ puts
367
+ puts "*** error: #{e.message}"
368
+ end
369
+
370
+ ## note: was false # skip default error handling
371
+
372
+ ## note: try true - false WILL SWALLOW exit codes and such
373
+ ## - looks like it's still returning 0 (e.g. on unknown option or such)!!!!
374
+ true
375
+ end
376
+
377
+
378
+ ### exit run(ARGV) ## note: use Toolii.run( ARGV ) outside of class
379
+ end # class Toolii
380
+ end # module Punk
381
+
382
+