main 4.3.0 → 4.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README +105 -0
- data/README.erb +79 -1
- data/TODO +17 -19
- data/a.rb +29 -2
- data/lib/main.rb +2 -1
- data/lib/main/cast.rb +46 -3
- data/lib/main/parameter.rb +22 -1
- data/lib/main/program/class_methods.rb +94 -6
- data/lib/main/program/instance_methods.rb +27 -8
- data/lib/main/util.rb +14 -0
- data/main.gemspec +1 -1
- data/samples/j.rb +25 -8
- data/test/main.rb +1 -1
- metadata +4 -4
data/README
CHANGED
@@ -450,6 +450,48 @@ SAMPLES
|
|
450
450
|
"forty-two"
|
451
451
|
|
452
452
|
|
453
|
+
<========< samples/j.rb >========>
|
454
|
+
|
455
|
+
~ > cat samples/j.rb
|
456
|
+
|
457
|
+
#!/usr/bin/env ruby
|
458
|
+
|
459
|
+
require 'open-uri'
|
460
|
+
|
461
|
+
require 'main'
|
462
|
+
require 'digest/sha2'
|
463
|
+
|
464
|
+
# you have access to a sequel/amalgalite/sqlite db for free
|
465
|
+
#
|
466
|
+
|
467
|
+
Main {
|
468
|
+
name :i_can_haz_db
|
469
|
+
|
470
|
+
db {
|
471
|
+
create_table(:mp3s) do
|
472
|
+
primary_key :id
|
473
|
+
String :url
|
474
|
+
String :sha
|
475
|
+
end unless table_exists?(:mp3s)
|
476
|
+
}
|
477
|
+
|
478
|
+
def run
|
479
|
+
url = 'http://s3.amazonaws.com/drawohara.com.mp3/ween-voodoo_lady.mp3'
|
480
|
+
mp3 = open(url){|fd| fd.read}
|
481
|
+
sha = Digest::SHA2.hexdigest(mp3)
|
482
|
+
|
483
|
+
db[:mp3s].insert(:url => url, :sha => sha)
|
484
|
+
p db[:mp3s].all
|
485
|
+
p db
|
486
|
+
end
|
487
|
+
}
|
488
|
+
|
489
|
+
~ > ruby samples/j.rb
|
490
|
+
|
491
|
+
[{:url=>"http://s3.amazonaws.com/drawohara.com.mp3/ween-voodoo_lady.mp3", :sha=>"54c99ac7588dcfce1e70540b734805e9c69ff98dcca001e6f2bdec140fb0f9dc", :id=>1}, {:url=>"http://s3.amazonaws.com/drawohara.com.mp3/ween-voodoo_lady.mp3", :sha=>"54c99ac7588dcfce1e70540b734805e9c69ff98dcca001e6f2bdec140fb0f9dc", :id=>2}]
|
492
|
+
#<Sequel::Amalgalite::Database: "amalgalite://Users/ahoward/.i_can_haz_db/db.sqlite">
|
493
|
+
|
494
|
+
|
453
495
|
|
454
496
|
DOCS
|
455
497
|
test/main.rb
|
@@ -457,6 +499,69 @@ DOCS
|
|
457
499
|
API section below
|
458
500
|
|
459
501
|
HISTORY
|
502
|
+
4.4.0
|
503
|
+
- support for automatic sequel/sqlite/amalgalite dbs for persistent state
|
504
|
+
across invocations
|
505
|
+
|
506
|
+
Main {
|
507
|
+
db {
|
508
|
+
create_table :foo do
|
509
|
+
String key
|
510
|
+
String val
|
511
|
+
end unless table_exists? :foo
|
512
|
+
}
|
513
|
+
|
514
|
+
def run
|
515
|
+
db[:foo].create(:key => 'using', :val => 'amalgalite')
|
516
|
+
end
|
517
|
+
}
|
518
|
+
|
519
|
+
- support for automatic config files with auto populated template data
|
520
|
+
|
521
|
+
Main {
|
522
|
+
config :email => 'your.addy@gmail.com', :password => 'pa$$word'
|
523
|
+
|
524
|
+
def run
|
525
|
+
email = config[:email]
|
526
|
+
end
|
527
|
+
}
|
528
|
+
|
529
|
+
- new paramter types :pathname, :path, :slug, :input, and :output
|
530
|
+
|
531
|
+
- input/output parameters. can be filenames or '-' to supply
|
532
|
+
stdin/stdout respectively
|
533
|
+
|
534
|
+
Main {
|
535
|
+
input :i
|
536
|
+
output :o
|
537
|
+
|
538
|
+
def run
|
539
|
+
i = params[:i].value
|
540
|
+
o = params[:o].value
|
541
|
+
|
542
|
+
line = i.gets
|
543
|
+
o.puts line
|
544
|
+
end
|
545
|
+
}
|
546
|
+
|
547
|
+
- clean up warnings running with 'ruby -w'
|
548
|
+
|
549
|
+
- fix a failing test
|
550
|
+
|
551
|
+
- ability to ignore parameters in sub modes
|
552
|
+
|
553
|
+
Main {
|
554
|
+
argument :foo
|
555
|
+
argument :bar
|
556
|
+
|
557
|
+
def run
|
558
|
+
p param[:bar].value
|
559
|
+
end
|
560
|
+
|
561
|
+
mode :ignoring do
|
562
|
+
params[:foo].ignore!
|
563
|
+
end
|
564
|
+
}
|
460
565
|
4.0.0
|
461
566
|
- avoid duping ios. new methods Main.push_ios! and Main.pop_ios! are
|
462
567
|
utilized for testing. this was done to make it simple to wrap
|
data/README.erb
CHANGED
@@ -5,9 +5,9 @@ SYNOPSIS
|
|
5
5
|
a class factory and dsl for generating command line programs real quick
|
6
6
|
|
7
7
|
URI
|
8
|
+
http://github.com/ahoward/main
|
8
9
|
http://codeforpeople.com/lib/ruby/
|
9
10
|
http://rubyforge.org/projects/codeforpeople/
|
10
|
-
http://github.com/ahoward/main
|
11
11
|
|
12
12
|
INSTALL
|
13
13
|
gem install main
|
@@ -26,6 +26,8 @@ DESCRIPTION
|
|
26
26
|
- parsing user defined ARGV and ENV
|
27
27
|
- zero requirements for understanding the obtuse apis of *any* command
|
28
28
|
line option parsers
|
29
|
+
- built-in support for persistent state via sqlite/sequel/amalgalite
|
30
|
+
- built-in support for yaml config files
|
29
31
|
- leather pants
|
30
32
|
|
31
33
|
in short main.rb aims to drastically lower the barrier to writing uniform
|
@@ -186,6 +188,82 @@ DOCS
|
|
186
188
|
API section below
|
187
189
|
|
188
190
|
HISTORY
|
191
|
+
4.4.0
|
192
|
+
- app storage under a dotdir. for example
|
193
|
+
|
194
|
+
Main {
|
195
|
+
name :foobar
|
196
|
+
}
|
197
|
+
|
198
|
+
will have a ~/.foobar/ directory available for storing db/config/etc.
|
199
|
+
|
200
|
+
- support for automatic sequel/sqlite/amalgalite dbs for persistent state
|
201
|
+
across invocations. the db is automatically created under the main
|
202
|
+
programs dotdir (~/.$appname/db.sqlite)
|
203
|
+
|
204
|
+
Main {
|
205
|
+
db {
|
206
|
+
create_table :foo do
|
207
|
+
String key
|
208
|
+
String val
|
209
|
+
end unless table_exists? :foo
|
210
|
+
}
|
211
|
+
|
212
|
+
def run
|
213
|
+
db[:foo].create(:key => 'using', :val => 'amalgalite')
|
214
|
+
end
|
215
|
+
}
|
216
|
+
|
217
|
+
- support for automatic config files with auto populated template data.
|
218
|
+
the first time the program is run the user's editor will be invoked on a
|
219
|
+
config file pre-populate with the same config. subsequent invocations
|
220
|
+
will use the user configured values. the config file is stored at
|
221
|
+
~/.$appname/config.yml
|
222
|
+
|
223
|
+
Main {
|
224
|
+
config :email => 'your.addy@gmail.com', :password => 'pa$$word'
|
225
|
+
|
226
|
+
def run
|
227
|
+
email = config[:email]
|
228
|
+
end
|
229
|
+
}
|
230
|
+
|
231
|
+
- new paramter types :pathname, :path, :slug, :input, and :output
|
232
|
+
|
233
|
+
- input/output parameters. can be filenames or '-' to supply
|
234
|
+
stdin/stdout respectively
|
235
|
+
|
236
|
+
Main {
|
237
|
+
input :i
|
238
|
+
output :o
|
239
|
+
|
240
|
+
def run
|
241
|
+
i = params[:i].value
|
242
|
+
o = params[:o].value
|
243
|
+
|
244
|
+
line = i.gets
|
245
|
+
o.puts line
|
246
|
+
end
|
247
|
+
}
|
248
|
+
|
249
|
+
- clean up warnings running with 'ruby -w'
|
250
|
+
|
251
|
+
- fix a failing test
|
252
|
+
|
253
|
+
- ability to ignore parameters in sub modes
|
254
|
+
|
255
|
+
Main {
|
256
|
+
argument :foo
|
257
|
+
argument :bar
|
258
|
+
|
259
|
+
def run
|
260
|
+
p param[:bar].value
|
261
|
+
end
|
262
|
+
|
263
|
+
mode :ignoring do
|
264
|
+
params[:foo].ignore!
|
265
|
+
end
|
266
|
+
}
|
189
267
|
4.0.0
|
190
268
|
- avoid duping ios. new methods Main.push_ios! and Main.pop_ios! are
|
191
269
|
utilized for testing. this was done to make it simple to wrap
|
data/TODO
CHANGED
@@ -1,20 +1,18 @@
|
|
1
|
+
todo:
|
2
|
+
- examples of new features
|
3
|
+
- use map.rb
|
1
4
|
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
X calls to abort sometimes lead to STDERR prining twice ;-(
|
17
|
-
X main's' with modes, but no run do not operate properly - add default run w/wrap_run!
|
18
|
-
X usage fubar when extra chunks are set
|
19
|
-
X usage of arguments is fubar when negative arities are used
|
20
|
-
X add sanity checks at parameter contruction completion
|
5
|
+
done:
|
6
|
+
- clean up warnings under 'ruby -w'
|
7
|
+
- intput/output arguments
|
8
|
+
- support io cast '-' (:input, :output)
|
9
|
+
- slug casts
|
10
|
+
- support uri casts
|
11
|
+
- dotdir support (based on name)
|
12
|
+
- db support
|
13
|
+
- configuration/configfile file support
|
14
|
+
- calls to abort sometimes lead to STDERR prining twice ;-(
|
15
|
+
- main's' with modes, but no run do not operate properly - add default run w/wrap_run!
|
16
|
+
- usage fubar when extra chunks are set
|
17
|
+
- usage of arguments is fubar when negative arities are used
|
18
|
+
- add sanity checks at parameter contruction completion
|
data/a.rb
CHANGED
@@ -1,6 +1,33 @@
|
|
1
1
|
require 'main'
|
2
2
|
|
3
3
|
Main {
|
4
|
-
|
5
|
-
|
4
|
+
|
5
|
+
name :foobar
|
6
|
+
|
7
|
+
db {
|
8
|
+
create_table(:foo) do
|
9
|
+
primary_key :id
|
10
|
+
String :name
|
11
|
+
Float :price
|
12
|
+
end unless table_exists?(:foo)
|
13
|
+
}
|
14
|
+
|
15
|
+
config(
|
16
|
+
:email => 'your.addy@gmail.com',
|
17
|
+
:password => 'yourPa$$word'
|
18
|
+
)
|
19
|
+
|
20
|
+
io
|
21
|
+
|
22
|
+
|
23
|
+
def run
|
24
|
+
#p input.path
|
25
|
+
#p output.path
|
26
|
+
p params.map{|param| param.name}
|
27
|
+
output.puts(:foobar)
|
28
|
+
end
|
29
|
+
|
30
|
+
mode :foo do
|
31
|
+
params[:input].ignore!
|
32
|
+
end
|
6
33
|
}
|
data/lib/main.rb
CHANGED
@@ -2,7 +2,7 @@ module Main
|
|
2
2
|
#
|
3
3
|
# top level constants
|
4
4
|
#
|
5
|
-
Main::VERSION = '4.
|
5
|
+
Main::VERSION = '4.4.0' unless
|
6
6
|
defined? Main::VERSION
|
7
7
|
def self.version() Main::VERSION end
|
8
8
|
|
@@ -13,6 +13,7 @@ module Main
|
|
13
13
|
Main::EXIT_SUCCESS = 0 unless defined? Main::EXIT_SUCCESS
|
14
14
|
Main::EXIT_FAILURE = 1 unless defined? Main::EXIT_FAILURE
|
15
15
|
Main::EXIT_WARN = 42 unless defined? Main::EXIT_WARN
|
16
|
+
Main::EXIT_WARNING = 42 unless defined? Main::EXIT_WARNING
|
16
17
|
#
|
17
18
|
# built-in
|
18
19
|
#
|
data/lib/main/cast.rb
CHANGED
@@ -25,7 +25,7 @@ module Main
|
|
25
25
|
end
|
26
26
|
|
27
27
|
cast :integer do |obj|
|
28
|
-
|
28
|
+
Float(obj).to_i
|
29
29
|
end
|
30
30
|
|
31
31
|
cast :float do |obj|
|
@@ -45,7 +45,7 @@ module Main
|
|
45
45
|
end
|
46
46
|
|
47
47
|
cast :uri do |obj|
|
48
|
-
require 'uri'
|
48
|
+
require 'uri' unless defined?(::URI)
|
49
49
|
::URI.parse obj.to_s
|
50
50
|
end
|
51
51
|
|
@@ -55,10 +55,53 @@ module Main
|
|
55
55
|
end
|
56
56
|
|
57
57
|
cast :date do |obj|
|
58
|
-
require 'date'
|
58
|
+
require 'date' unless defined?(::Date)
|
59
59
|
::Date.parse obj.to_s
|
60
60
|
end
|
61
61
|
|
62
|
+
cast :pathname do |obj|
|
63
|
+
require 'pathname' unless defined?(::Pathname)
|
64
|
+
Pathname.new(obj.to_s)
|
65
|
+
end
|
66
|
+
|
67
|
+
cast :path do |obj|
|
68
|
+
File.expand_path(obj.to_s)
|
69
|
+
end
|
70
|
+
|
71
|
+
cast :input do |obj|
|
72
|
+
case obj.to_s
|
73
|
+
when '-'
|
74
|
+
io = STDIN.dup
|
75
|
+
io.fattr(:path){ '/dev/stdin' }
|
76
|
+
io
|
77
|
+
else
|
78
|
+
io = open(obj.to_s, 'r+')
|
79
|
+
at_exit{ io.close }
|
80
|
+
io
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
cast :output do |obj|
|
85
|
+
case obj.to_s
|
86
|
+
when '-'
|
87
|
+
io = STDOUT.dup
|
88
|
+
io.fattr(:path){ '/dev/stdout' }
|
89
|
+
io
|
90
|
+
else
|
91
|
+
io = open(obj.to_s, 'w+')
|
92
|
+
at_exit{ io.close }
|
93
|
+
io
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
cast :slug do |obj|
|
98
|
+
string = [obj].flatten.compact.join('-')
|
99
|
+
words = string.to_s.scan(%r/\w+/)
|
100
|
+
words.map!{|word| word.gsub %r/[^0-9a-zA-Z_-]/, ''}
|
101
|
+
words.delete_if{|word| word.nil? or word.strip.empty?}
|
102
|
+
String(words.join('-').downcase)
|
103
|
+
end
|
104
|
+
|
62
105
|
cast :list do |*objs|
|
63
106
|
[*objs].flatten.join(',').split(/,/)
|
64
107
|
end
|
data/lib/main/parameter.rb
CHANGED
@@ -109,10 +109,15 @@ module Main
|
|
109
109
|
names.first
|
110
110
|
end
|
111
111
|
|
112
|
-
def default
|
112
|
+
def default(*values)
|
113
|
+
defaults(values) unless values.empty?
|
113
114
|
defaults.first
|
114
115
|
end
|
115
116
|
|
117
|
+
def default=(value)
|
118
|
+
default(value)
|
119
|
+
end
|
120
|
+
|
116
121
|
def typename
|
117
122
|
prefix = '--' if type.to_s =~ %r/option/
|
118
123
|
"#{ type }(#{ prefix }#{ name })"
|
@@ -248,6 +253,13 @@ module Main
|
|
248
253
|
end
|
249
254
|
end
|
250
255
|
|
256
|
+
def remove
|
257
|
+
main.parameters.delete(self)
|
258
|
+
end
|
259
|
+
alias_method('remove!', 'remove')
|
260
|
+
alias_method('ignore', 'remove')
|
261
|
+
alias_method('ignore!', 'ignore')
|
262
|
+
|
251
263
|
class Argument < Parameter
|
252
264
|
fattr 'required' => true
|
253
265
|
|
@@ -527,6 +539,15 @@ module Main
|
|
527
539
|
delete(*a)
|
528
540
|
super
|
529
541
|
end
|
542
|
+
|
543
|
+
def [](*index)
|
544
|
+
first = index.first
|
545
|
+
if(index.size == 1 and (first.is_a?(String) or first.is_a?(Symbol)))
|
546
|
+
first = first.to_s
|
547
|
+
return detect{|param| param.name == first}
|
548
|
+
end
|
549
|
+
return super
|
550
|
+
end
|
530
551
|
end
|
531
552
|
|
532
553
|
class DSL
|
@@ -21,11 +21,11 @@ module Main
|
|
21
21
|
fattr('exit_success'){ Main::EXIT_SUCCESS }
|
22
22
|
fattr('exit_failure'){ Main::EXIT_FAILURE }
|
23
23
|
fattr('exit_warn'){ Main::EXIT_WARN }
|
24
|
+
fattr('exit_warning'){ Main::EXIT_WARNING }
|
24
25
|
fattr('parameters'){ Main::Parameter::List[] }
|
25
26
|
fattr('can_has_hash'){ Hash.new }
|
26
27
|
fattr('mixin_table'){ Hash.new }
|
27
28
|
|
28
|
-
fattr('factory')
|
29
29
|
fattr('argv')
|
30
30
|
fattr('env')
|
31
31
|
fattr('opts')
|
@@ -35,6 +35,10 @@ module Main
|
|
35
35
|
end
|
36
36
|
alias_method 'create', 'factory'
|
37
37
|
|
38
|
+
def factory=(factory)
|
39
|
+
@factory = factory
|
40
|
+
end
|
41
|
+
|
38
42
|
class Factory
|
39
43
|
def initialize(&block)
|
40
44
|
@block = block || lambda{}
|
@@ -84,6 +88,10 @@ module Main
|
|
84
88
|
instance
|
85
89
|
end
|
86
90
|
|
91
|
+
def params
|
92
|
+
parameters
|
93
|
+
end
|
94
|
+
|
87
95
|
def evaluate(&block)
|
88
96
|
module_eval(&block)
|
89
97
|
end
|
@@ -182,23 +190,23 @@ module Main
|
|
182
190
|
end
|
183
191
|
|
184
192
|
def parameter(*a, &b)
|
185
|
-
(parameters << Parameter.create(:parameter, self, *a, &b)).last
|
193
|
+
(parameters << Parameter.create(:parameter, main=self, *a, &b)).last
|
186
194
|
end
|
187
195
|
|
188
196
|
def argument(*a, &b)
|
189
|
-
(parameters << Parameter.create(:argument, self, *a, &b)).last
|
197
|
+
(parameters << Parameter.create(:argument, main=self, *a, &b)).last
|
190
198
|
end
|
191
199
|
|
192
200
|
def option(*a, &b)
|
193
|
-
(parameters << Parameter.create(:option, self, *a, &b)).last
|
201
|
+
(parameters << Parameter.create(:option, main=self, *a, &b)).last
|
194
202
|
end
|
195
203
|
|
196
204
|
def keyword(*a, &b)
|
197
|
-
(parameters << Parameter.create(:keyword, self, *a, &b)).last
|
205
|
+
(parameters << Parameter.create(:keyword, main=self, *a, &b)).last
|
198
206
|
end
|
199
207
|
|
200
208
|
def environment(*a, &b)
|
201
|
-
(parameters << Parameter.create(:environment, self, *a, &b)).last
|
209
|
+
(parameters << Parameter.create(:environment, main=self, *a, &b)).last
|
202
210
|
end
|
203
211
|
|
204
212
|
def default_options!
|
@@ -259,6 +267,86 @@ module Main
|
|
259
267
|
block ||= lambda{}
|
260
268
|
define_method(:run, &block) if block
|
261
269
|
end
|
270
|
+
|
271
|
+
def dotdir(*dotdir, &block)
|
272
|
+
@dotdir = File.join(Util.home, ".#{ name }") unless defined?(@dotdir)
|
273
|
+
|
274
|
+
@dotdir = dotdir.join('/') unless dotdir.empty?
|
275
|
+
|
276
|
+
if block
|
277
|
+
require 'fileutils' unless defined?(FileUtils)
|
278
|
+
FileUtils.mkdir_p(@dotdir) unless test(?d, @dotdir)
|
279
|
+
Dir.chdir(&block)
|
280
|
+
else
|
281
|
+
@dotdir
|
282
|
+
end
|
283
|
+
end
|
284
|
+
|
285
|
+
def db(*args, &block)
|
286
|
+
unless defined?(@db)
|
287
|
+
require 'sequel' unless defined?(Sequel)
|
288
|
+
require 'amalgalite' unless defined?(Amalgalite)
|
289
|
+
@db = dotdir{ Sequel.amalgalite(db_path) }
|
290
|
+
@db.instance_eval(&block) if block
|
291
|
+
end
|
292
|
+
@db
|
293
|
+
end
|
294
|
+
|
295
|
+
def db_path(*db_path)
|
296
|
+
@db_path = File.join(dotdir, 'db.sqlite') unless defined?(@db_path)
|
297
|
+
@db_path = File.join(*db_path) unless db_path.empty?
|
298
|
+
@db_path
|
299
|
+
end
|
300
|
+
|
301
|
+
def config(*args, &block)
|
302
|
+
unless defined?(@config)
|
303
|
+
require 'yaml' unless defined?(YAML)
|
304
|
+
if test(?s, config_path)
|
305
|
+
@config = YAML.load(IO.read(config_path))
|
306
|
+
else
|
307
|
+
config = args.last.is_a?(Hash) ? args.last : {}
|
308
|
+
lines = config.to_yaml.split(/\n/)
|
309
|
+
dash = lines.shift
|
310
|
+
open(config_path, 'w') do |fd|
|
311
|
+
fd.puts '### you may need to edit this config!'
|
312
|
+
fd.puts
|
313
|
+
fd.puts lines
|
314
|
+
end
|
315
|
+
editor = ENV['EDITOR'] || ENV['EDIT'] || 'vi'
|
316
|
+
system("#{ editor.inspect } #{ config_path }")
|
317
|
+
@config = YAML.load(IO.read(config_path))
|
318
|
+
end
|
319
|
+
end
|
320
|
+
@config
|
321
|
+
end
|
322
|
+
|
323
|
+
def config_path(*config_path)
|
324
|
+
@config_path = File.join(dotdir, 'config.yml') unless defined?(@config_path)
|
325
|
+
@config_path = File.join(*config_path) unless config_path.empty?
|
326
|
+
@config_path
|
327
|
+
end
|
328
|
+
|
329
|
+
def input(*args, &block)
|
330
|
+
first = args.first
|
331
|
+
args.push(:input) unless(first.is_a?(Symbol) or first.is_a?(String))
|
332
|
+
param = argument(*args, &block)
|
333
|
+
param.cast(:input)
|
334
|
+
param
|
335
|
+
end
|
336
|
+
|
337
|
+
def output(*args, &block)
|
338
|
+
first = args.first
|
339
|
+
args.push(:output) unless(first.is_a?(Symbol) or first.is_a?(String))
|
340
|
+
param = argument(*args, &block)
|
341
|
+
param.cast(:output)
|
342
|
+
param
|
343
|
+
end
|
344
|
+
|
345
|
+
def io(*args)
|
346
|
+
i = input(*[args.shift].compact).default('-')
|
347
|
+
o = output(*[args.shift].compact).default('-')
|
348
|
+
[i, o]
|
349
|
+
end
|
262
350
|
end
|
263
351
|
|
264
352
|
extend ClassMethods
|
@@ -16,7 +16,7 @@ module Main
|
|
16
16
|
|
17
17
|
%w(
|
18
18
|
program name synopsis description author version
|
19
|
-
exit_status exit_success exit_failure exit_warn
|
19
|
+
exit_status exit_success exit_failure exit_warn exit_warning
|
20
20
|
logger_level
|
21
21
|
usage
|
22
22
|
).each{|a| fattr(a){ self.class.send a}}
|
@@ -31,9 +31,9 @@ module Main
|
|
31
31
|
end
|
32
32
|
|
33
33
|
%w( debug info warn fatal error ).each do |m|
|
34
|
-
module_eval <<-code
|
35
|
-
def #{ m }
|
36
|
-
logger.#{ m }
|
34
|
+
module_eval <<-code, __FILE__, __LINE__
|
35
|
+
def #{ m }(*a, &b)
|
36
|
+
logger.#{ m }(*a, &b)
|
37
37
|
end
|
38
38
|
code
|
39
39
|
end
|
@@ -87,7 +87,6 @@ module Main
|
|
87
87
|
end
|
88
88
|
|
89
89
|
def setup_io_restoration
|
90
|
-
return
|
91
90
|
@finalizers ||= []
|
92
91
|
[STDIN, STDOUT, STDERR].each do |io|
|
93
92
|
dup = io.dup
|
@@ -250,9 +249,9 @@ module Main
|
|
250
249
|
end
|
251
250
|
|
252
251
|
%w[ before instead after ].each do |which|
|
253
|
-
module_eval <<-code
|
254
|
-
def error_handler_#{ which }
|
255
|
-
block.call
|
252
|
+
module_eval <<-code, __FILE__, __LINE__
|
253
|
+
def error_handler_#{ which }(*argv, &block)
|
254
|
+
block.call(*argv)
|
256
255
|
end
|
257
256
|
code
|
258
257
|
end
|
@@ -265,6 +264,26 @@ module Main
|
|
265
264
|
singleton_class.module_eval{ define_method('__instance_eval_block', &block) }
|
266
265
|
fcall(self, '__instance_eval_block', *argv, &block)
|
267
266
|
end
|
267
|
+
|
268
|
+
def dotdir(&block)
|
269
|
+
self.class.dotdir(&block)
|
270
|
+
end
|
271
|
+
|
272
|
+
def db(&block)
|
273
|
+
self.class.db(&block)
|
274
|
+
end
|
275
|
+
|
276
|
+
def config(&block)
|
277
|
+
self.class.config(&block)
|
278
|
+
end
|
279
|
+
|
280
|
+
def input
|
281
|
+
@input ||= params[:input].value if params[:input]
|
282
|
+
end
|
283
|
+
|
284
|
+
def output
|
285
|
+
@output ||= params[:output].value if params[:output]
|
286
|
+
end
|
268
287
|
end
|
269
288
|
|
270
289
|
include InstanceMethods
|
data/lib/main/util.rb
CHANGED
@@ -71,6 +71,20 @@ module Main
|
|
71
71
|
|
72
72
|
return default
|
73
73
|
end
|
74
|
+
|
75
|
+
def home
|
76
|
+
home =
|
77
|
+
catch :home do
|
78
|
+
["HOME", "USERPROFILE"].each do |key|
|
79
|
+
throw(:home, ENV[key]) if ENV[key]
|
80
|
+
end
|
81
|
+
if ENV["HOMEDRIVE"] and ENV["HOMEPATH"]
|
82
|
+
throw(:home, "#{ ENV['HOMEDRIVE'] }:#{ ENV['HOMEPATH'] }")
|
83
|
+
end
|
84
|
+
File.expand_path("~") rescue(File::ALT_SEPARATOR ? "C:/" : "/")
|
85
|
+
end
|
86
|
+
File.expand_path(home)
|
87
|
+
end
|
74
88
|
end
|
75
89
|
|
76
90
|
BLESS = lambda do |other|
|
data/main.gemspec
CHANGED
data/samples/j.rb
CHANGED
@@ -1,14 +1,31 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'open-uri'
|
4
|
+
|
2
5
|
require 'main'
|
6
|
+
require 'digest/sha2'
|
7
|
+
|
8
|
+
# you have access to a sequel/amalgalite/sqlite db for free
|
9
|
+
#
|
3
10
|
|
4
11
|
Main {
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
12
|
+
name :i_can_haz_db
|
13
|
+
|
14
|
+
db {
|
15
|
+
create_table(:mp3s) do
|
16
|
+
primary_key :id
|
17
|
+
String :url
|
18
|
+
String :sha
|
19
|
+
end unless table_exists?(:mp3s)
|
13
20
|
}
|
21
|
+
|
22
|
+
def run
|
23
|
+
url = 'http://s3.amazonaws.com/drawohara.com.mp3/ween-voodoo_lady.mp3'
|
24
|
+
mp3 = open(url){|fd| fd.read}
|
25
|
+
sha = Digest::SHA2.hexdigest(mp3)
|
26
|
+
|
27
|
+
db[:mp3s].insert(:url => url, :sha => sha)
|
28
|
+
p db[:mp3s].all
|
29
|
+
p db
|
30
|
+
end
|
14
31
|
}
|
data/test/main.rb
CHANGED
@@ -258,7 +258,7 @@ class T < Test::Unit::TestCase
|
|
258
258
|
}
|
259
259
|
option('y'){
|
260
260
|
argument_required
|
261
|
-
|
261
|
+
cast{|*values| values.join.split(',').map{|value| value.upcase}}
|
262
262
|
}
|
263
263
|
define_method('run'){ param = params }
|
264
264
|
}
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: main
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 47
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 4
|
8
|
-
-
|
8
|
+
- 4
|
9
9
|
- 0
|
10
|
-
version: 4.
|
10
|
+
version: 4.4.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Ara T. Howard
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2010-11-
|
18
|
+
date: 2010-11-25 00:00:00 -07:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|