ThiagoLelis-backgroundjob 1.0.3 → 1.0.4
Sign up to get free protection for your applications and to get access to all the features.
- data/HISTORY +7 -62
- data/README +63 -229
- data/Rakefile +22 -0
- data/background.gemspec +18 -0
- data/init.rb +33 -0
- data/install.rb +85 -200
- data/lib/arrayfields.rb +435 -0
- data/lib/attributes.rb +118 -0
- data/lib/bj.rb +1 -1
- data/lib/bj/runner.rb +7 -7
- data/lib/bj/table.rb +45 -25
- data/lib/bj/util.rb +4 -0
- data/lib/fattr.rb +153 -0
- data/lib/main.rb +60 -0
- data/lib/main/base.rb +515 -0
- data/lib/main/cast.rb +100 -0
- data/lib/main/factories.rb +20 -0
- data/lib/main/getoptlong.rb +470 -0
- data/lib/main/logger.rb +51 -0
- data/lib/main/mode.rb +42 -0
- data/lib/main/parameter.rb +685 -0
- data/lib/main/softspoken.rb +12 -0
- data/lib/main/stdext.rb +38 -0
- data/lib/main/usage.rb +211 -0
- data/lib/main/util.rb +91 -0
- data/lib/orderedautohash.rb +25 -0
- data/lib/orderedhash.rb +189 -0
- data/lib/systemu.rb +299 -0
- data/script/bj +55 -0
- data/tasks/bj_tasks.rake +4 -0
- data/test/bj_test.rb +8 -0
- data/uninstall.rb +1 -0
- metadata +44 -14
- data/TODO +0 -40
- data/rakefile +0 -3
data/lib/main/stdext.rb
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
class Object
|
2
|
+
def singleton_class object = self, &block
|
3
|
+
sc =
|
4
|
+
class << object
|
5
|
+
self
|
6
|
+
end
|
7
|
+
block ? sc.module_eval(&block) : sc
|
8
|
+
end
|
9
|
+
|
10
|
+
end
|
11
|
+
|
12
|
+
module SaneAbort
|
13
|
+
def abort message = nil
|
14
|
+
if message
|
15
|
+
message = message.to_s
|
16
|
+
message.singleton_class{ fattr 'abort' => true }
|
17
|
+
STDERR.puts message
|
18
|
+
end
|
19
|
+
exit 1
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def abort message = nil
|
24
|
+
if message
|
25
|
+
message = message.to_s
|
26
|
+
message.singleton_class{ fattr 'abort' => true }
|
27
|
+
STDERR.puts message
|
28
|
+
end
|
29
|
+
exit 1
|
30
|
+
end
|
31
|
+
def Process.abort message = nil
|
32
|
+
if message
|
33
|
+
message = message.to_s
|
34
|
+
message.singleton_class{ fattr 'abort' => true }
|
35
|
+
STDERR.puts message
|
36
|
+
end
|
37
|
+
exit 1
|
38
|
+
end
|
data/lib/main/usage.rb
ADDED
@@ -0,0 +1,211 @@
|
|
1
|
+
module Main
|
2
|
+
class Usage < ::Array
|
3
|
+
fattr 'chunkname'
|
4
|
+
fattr 'upcase'
|
5
|
+
fattr 'eos'
|
6
|
+
|
7
|
+
def initialize opts={}
|
8
|
+
self.fields=[]
|
9
|
+
self.chunkname = lambda{|chunkname| chunkname.to_s.strip.upcase}
|
10
|
+
self.upcase = true
|
11
|
+
self.eos = "\n\n"
|
12
|
+
if opts.has_key?(:upcase) or opts.has_key?('upcase')
|
13
|
+
self.upcase = opts[:upcase] || opts['optcase']
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def clear
|
18
|
+
super
|
19
|
+
ensure
|
20
|
+
fields.clear
|
21
|
+
end
|
22
|
+
|
23
|
+
def delete_at key
|
24
|
+
self[key] = nil
|
25
|
+
end
|
26
|
+
alias_method 'delete', 'delete_at'
|
27
|
+
|
28
|
+
def self.default_synopsis main
|
29
|
+
# build up synopsis
|
30
|
+
s = "#{ main.name }"
|
31
|
+
|
32
|
+
# mode info
|
33
|
+
if main.mode_name != 'main'
|
34
|
+
s << " #{ main.fully_qualified_mode.join ' ' }"
|
35
|
+
end
|
36
|
+
|
37
|
+
unless main.modes.empty?
|
38
|
+
modes = main.modes.keys.join('|')
|
39
|
+
s << " (#{ modes })"
|
40
|
+
end
|
41
|
+
|
42
|
+
# argument info
|
43
|
+
main.parameters.each do |p|
|
44
|
+
if p.type == :argument
|
45
|
+
if(p.required? and p.arity != -1)
|
46
|
+
if p.arity > 0
|
47
|
+
p.arity.times{ s << " #{ p.name }" }
|
48
|
+
else
|
49
|
+
(p.arity.abs - 1).times{ s << " #{ p.name }" }
|
50
|
+
s << " #{ p.name }*"
|
51
|
+
end
|
52
|
+
else
|
53
|
+
#s << " [#{ p.name }]"
|
54
|
+
if p.arity > 0
|
55
|
+
a = []
|
56
|
+
p.arity.times{ a << "#{ p.name }" }
|
57
|
+
s << " [#{ a.join ' ' }]"
|
58
|
+
else
|
59
|
+
a = []
|
60
|
+
(p.arity.abs - 1).times{ a << "#{ p.name }" }
|
61
|
+
a << "#{ p.name }*"
|
62
|
+
s << " [#{ a.join ' ' }]"
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
# keyword info
|
69
|
+
main.parameters.each do |p|
|
70
|
+
if p.type == :keyword
|
71
|
+
if p.required?
|
72
|
+
s << " #{ p.name }=#{ p.name }"
|
73
|
+
else
|
74
|
+
s << " [#{ p.name }=#{ p.name }]"
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
# option info
|
80
|
+
n = 0
|
81
|
+
main.parameters.each do |p|
|
82
|
+
if p.type == :option
|
83
|
+
if p.required?
|
84
|
+
case p.argument
|
85
|
+
when :required
|
86
|
+
s << " --#{ p.name }=#{ p.name }"
|
87
|
+
when :optional
|
88
|
+
s << " --#{ p.name }=[#{ p.name }]"
|
89
|
+
else
|
90
|
+
s << " --#{ p.name }"
|
91
|
+
end
|
92
|
+
else
|
93
|
+
n += 1
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
if n > 0
|
98
|
+
s << " [options]+"
|
99
|
+
end
|
100
|
+
|
101
|
+
# help info
|
102
|
+
=begin
|
103
|
+
if main.modes.size > 0
|
104
|
+
modes = main.modes.keys.join('|')
|
105
|
+
s << "\n#{ main.name } (#{ modes }) help"
|
106
|
+
end
|
107
|
+
if main.mode_name != 'main'
|
108
|
+
s << "\n#{ main.name } #{ main.fully_qualified_mode.join ' ' } help"
|
109
|
+
else
|
110
|
+
s << "\n#{ main.name } help"
|
111
|
+
end
|
112
|
+
=end
|
113
|
+
|
114
|
+
s
|
115
|
+
end
|
116
|
+
|
117
|
+
def name_section
|
118
|
+
if main.version?
|
119
|
+
"#{ main.name } v#{ main.version }"
|
120
|
+
else
|
121
|
+
"#{ main.name }"
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
def synopsis_section
|
126
|
+
main.synopsis
|
127
|
+
end
|
128
|
+
|
129
|
+
def description_section
|
130
|
+
main.description if main.description?
|
131
|
+
end
|
132
|
+
|
133
|
+
def parameters_section
|
134
|
+
arguments = main.parameters.select{|p| p.type == :argument}
|
135
|
+
keywords = main.parameters.select{|p| p.type == :keyword}
|
136
|
+
options = main.parameters.select{|p| p.type == :option}
|
137
|
+
environment = main.parameters.select{|p| p.type == :environment}
|
138
|
+
|
139
|
+
help, nothelp = options.partition{|p| p.name == 'help'}
|
140
|
+
options = nothelp + help
|
141
|
+
|
142
|
+
parameters = arguments + keywords + options + environment
|
143
|
+
|
144
|
+
s =
|
145
|
+
parameters.map do |p|
|
146
|
+
ps = ''
|
147
|
+
ps << Util.columnize("#{ p.synopsis }", :indent => 2, :width => 78)
|
148
|
+
#ps << Util.columnize("* #{ p.synopsis }", :indent => 2, :width => 78)
|
149
|
+
#ps << "\n"
|
150
|
+
if p.description?
|
151
|
+
ps << "\n"
|
152
|
+
ps << Util.columnize("#{ p.description }", :indent => 6, :width => 78)
|
153
|
+
#ps << Util.columnize(p.description, :indent => 6, :width => 78)
|
154
|
+
#ps << "\n"
|
155
|
+
end
|
156
|
+
#ps << "\n"
|
157
|
+
unless(p.examples.nil? or p.examples.empty?)
|
158
|
+
p.examples.each do |example|
|
159
|
+
ps << "\n"
|
160
|
+
ps << Util.columnize("#{ example }", :indent => 8, :width => 78)
|
161
|
+
end
|
162
|
+
end
|
163
|
+
ps
|
164
|
+
end.join("\n")
|
165
|
+
end
|
166
|
+
|
167
|
+
def author_section
|
168
|
+
main.author
|
169
|
+
end
|
170
|
+
|
171
|
+
class << self
|
172
|
+
def default_usage main
|
173
|
+
usage = new
|
174
|
+
usage.main = main
|
175
|
+
# HACK
|
176
|
+
%w( name synopsis description parameters author ).each do |key|
|
177
|
+
usage[key] = nil
|
178
|
+
end
|
179
|
+
usage
|
180
|
+
end
|
181
|
+
|
182
|
+
alias_method "default", "default_usage"
|
183
|
+
end
|
184
|
+
|
185
|
+
fattr "main"
|
186
|
+
|
187
|
+
def set_defaults!
|
188
|
+
usage = self
|
189
|
+
usage['name'] ||= name_section
|
190
|
+
usage['synopsis'] ||= synopsis_section
|
191
|
+
usage['description'] ||= description_section
|
192
|
+
usage['parameters'] ||= parameters_section unless main.parameters.empty?
|
193
|
+
usage['author'] ||= author_section if main.author?
|
194
|
+
end
|
195
|
+
|
196
|
+
def to_s
|
197
|
+
set_defaults!
|
198
|
+
s = ''
|
199
|
+
each_pair do |key, value|
|
200
|
+
next unless(key and value)
|
201
|
+
up, down = key.to_s.upcase, key.to_s.downcase
|
202
|
+
if value
|
203
|
+
s << (upcase ? up : down) << "\n"
|
204
|
+
s << Util.indent(Util.unindent(value.to_s), 2)
|
205
|
+
s << eos
|
206
|
+
end
|
207
|
+
end
|
208
|
+
s
|
209
|
+
end
|
210
|
+
end
|
211
|
+
end
|
data/lib/main/util.rb
ADDED
@@ -0,0 +1,91 @@
|
|
1
|
+
module Main
|
2
|
+
module Util
|
3
|
+
module ClassMethods
|
4
|
+
end
|
5
|
+
|
6
|
+
module InstanceMethods
|
7
|
+
end
|
8
|
+
|
9
|
+
module Methods
|
10
|
+
def mcp obj
|
11
|
+
Marshal.load(Marshal.dump(obj))
|
12
|
+
end
|
13
|
+
|
14
|
+
def indent chunk, n = 2
|
15
|
+
lines = chunk.split %r/\n/
|
16
|
+
re = nil
|
17
|
+
s = ' ' * n
|
18
|
+
lines.map! do |line|
|
19
|
+
unless re
|
20
|
+
margin = line[%r/^\s*/]
|
21
|
+
re = %r/^#{ margin }/
|
22
|
+
end
|
23
|
+
line.gsub re, s
|
24
|
+
end.join("\n")
|
25
|
+
end
|
26
|
+
|
27
|
+
def unindent chunk
|
28
|
+
lines = chunk.split %r/\n/
|
29
|
+
indent = nil
|
30
|
+
re = %r/^/
|
31
|
+
lines.map! do |line|
|
32
|
+
unless indent
|
33
|
+
indent = line[%r/^\s*/]
|
34
|
+
re = %r/^#{ indent }/
|
35
|
+
end
|
36
|
+
line.gsub re, ''
|
37
|
+
end.join("\n")
|
38
|
+
end
|
39
|
+
|
40
|
+
def columnize buf, opts = {}
|
41
|
+
width = Util.getopt 'width', opts, 80
|
42
|
+
indent = Util.getopt 'indent', opts
|
43
|
+
indent = Fixnum === indent ? (' ' * indent) : "#{ indent }"
|
44
|
+
column = []
|
45
|
+
words = buf.split %r/\s+/o
|
46
|
+
row = "#{ indent }"
|
47
|
+
while((word = words.shift))
|
48
|
+
if((row.size + word.size) < (width - 1))
|
49
|
+
row << word
|
50
|
+
else
|
51
|
+
column << row
|
52
|
+
row = "#{ indent }"
|
53
|
+
row << word
|
54
|
+
end
|
55
|
+
row << ' ' unless row.size == (width - 1)
|
56
|
+
end
|
57
|
+
column << row unless row.strip.empty?
|
58
|
+
column.join "\n"
|
59
|
+
end
|
60
|
+
|
61
|
+
def getopt opt, hash, default = nil
|
62
|
+
keys = opt.respond_to?('each') ? opt : [opt]
|
63
|
+
|
64
|
+
keys.each do |key|
|
65
|
+
return hash[key] if hash.has_key? key
|
66
|
+
key = "#{ key }"
|
67
|
+
return hash[key] if hash.has_key? key
|
68
|
+
key = key.intern
|
69
|
+
return hash[key] if hash.has_key? key
|
70
|
+
end
|
71
|
+
|
72
|
+
return default
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
BLESS = lambda do |other|
|
77
|
+
other.module_eval{
|
78
|
+
include Methods
|
79
|
+
include InstanceMethods
|
80
|
+
extend Methods
|
81
|
+
extend ClassMethods
|
82
|
+
}
|
83
|
+
end
|
84
|
+
|
85
|
+
def self.included other
|
86
|
+
BLESS[ other ]
|
87
|
+
end
|
88
|
+
|
89
|
+
BLESS[ self ]
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
#
|
2
|
+
# auto vivifying ordered hash that dumps as yaml nicely
|
3
|
+
#
|
4
|
+
require 'orderedhash' unless defined? OrderedHash
|
5
|
+
|
6
|
+
class AutoOrderedHash < OrderedHash
|
7
|
+
def initialize(*args)
|
8
|
+
super(*args){|a,k| a[k] = __class__.new(*args)}
|
9
|
+
end
|
10
|
+
def class # for nice yaml
|
11
|
+
Hash
|
12
|
+
end
|
13
|
+
def __class__
|
14
|
+
AutoOrderedHash
|
15
|
+
end
|
16
|
+
end # class AutoOrderedHash
|
17
|
+
|
18
|
+
OrderedAutoHash = AutoOrderedHash
|
19
|
+
|
20
|
+
def OrderedAutoHash(*a, &b)
|
21
|
+
OrderedAutoHash.new(*a, &b)
|
22
|
+
end
|
23
|
+
def AutoOrderedHash(*a, &b)
|
24
|
+
AutoOrderedHash.new(*a, &b)
|
25
|
+
end
|
data/lib/orderedhash.rb
ADDED
@@ -0,0 +1,189 @@
|
|
1
|
+
|
2
|
+
# AUTHOR
|
3
|
+
# jan molic /mig/at/1984/dot/cz/
|
4
|
+
#
|
5
|
+
# DESCRIPTION
|
6
|
+
# Hash with preserved order and some array-like extensions
|
7
|
+
# Public domain.
|
8
|
+
#
|
9
|
+
# THANKS
|
10
|
+
# Andrew Johnson for his suggestions and fixes of Hash[],
|
11
|
+
# merge, to_a, inspect and shift
|
12
|
+
class OrderedHash < ::Hash
|
13
|
+
attr_accessor :order
|
14
|
+
|
15
|
+
class << self
|
16
|
+
def [] *args
|
17
|
+
hsh = OrderedHash.new
|
18
|
+
if Hash === args[0]
|
19
|
+
hsh.replace args[0]
|
20
|
+
elsif (args.size % 2) != 0
|
21
|
+
raise ArgumentError, "odd number of elements for Hash"
|
22
|
+
else
|
23
|
+
0.step(args.size - 1, 2) do |a|
|
24
|
+
b = a + 1
|
25
|
+
hsh[args[a]] = args[b]
|
26
|
+
end
|
27
|
+
end
|
28
|
+
hsh
|
29
|
+
end
|
30
|
+
end
|
31
|
+
def initialize(*a, &b)
|
32
|
+
super
|
33
|
+
@order = []
|
34
|
+
end
|
35
|
+
def store_only a,b
|
36
|
+
store a,b
|
37
|
+
end
|
38
|
+
alias orig_store store
|
39
|
+
def store a,b
|
40
|
+
@order.push a unless has_key? a
|
41
|
+
super a,b
|
42
|
+
end
|
43
|
+
alias []= store
|
44
|
+
def == hsh2
|
45
|
+
return false if @order != hsh2.order
|
46
|
+
super hsh2
|
47
|
+
end
|
48
|
+
def clear
|
49
|
+
@order = []
|
50
|
+
super
|
51
|
+
end
|
52
|
+
def delete key
|
53
|
+
@order.delete key
|
54
|
+
super
|
55
|
+
end
|
56
|
+
def each_key
|
57
|
+
@order.each { |k| yield k }
|
58
|
+
self
|
59
|
+
end
|
60
|
+
def each_value
|
61
|
+
@order.each { |k| yield self[k] }
|
62
|
+
self
|
63
|
+
end
|
64
|
+
def each
|
65
|
+
@order.each { |k| yield k,self[k] }
|
66
|
+
self
|
67
|
+
end
|
68
|
+
alias each_pair each
|
69
|
+
def delete_if
|
70
|
+
@order.clone.each { |k|
|
71
|
+
delete k if yield(k)
|
72
|
+
}
|
73
|
+
self
|
74
|
+
end
|
75
|
+
def values
|
76
|
+
ary = []
|
77
|
+
@order.each { |k| ary.push self[k] }
|
78
|
+
ary
|
79
|
+
end
|
80
|
+
def keys
|
81
|
+
@order
|
82
|
+
end
|
83
|
+
def invert
|
84
|
+
hsh2 = Hash.new
|
85
|
+
@order.each { |k| hsh2[self[k]] = k }
|
86
|
+
hsh2
|
87
|
+
end
|
88
|
+
def reject &block
|
89
|
+
self.dup.delete_if &block
|
90
|
+
end
|
91
|
+
def reject! &block
|
92
|
+
hsh2 = reject &block
|
93
|
+
self == hsh2 ? nil : hsh2
|
94
|
+
end
|
95
|
+
def replace hsh2
|
96
|
+
@order = hsh2.keys
|
97
|
+
super hsh2
|
98
|
+
end
|
99
|
+
def shift
|
100
|
+
key = @order.first
|
101
|
+
key ? [key,delete(key)] : super
|
102
|
+
end
|
103
|
+
def unshift k,v
|
104
|
+
unless self.include? k
|
105
|
+
@order.unshift k
|
106
|
+
orig_store(k,v)
|
107
|
+
true
|
108
|
+
else
|
109
|
+
false
|
110
|
+
end
|
111
|
+
end
|
112
|
+
def push k,v
|
113
|
+
unless self.include? k
|
114
|
+
@order.push k
|
115
|
+
orig_store(k,v)
|
116
|
+
true
|
117
|
+
else
|
118
|
+
false
|
119
|
+
end
|
120
|
+
end
|
121
|
+
def pop
|
122
|
+
key = @order.last
|
123
|
+
key ? [key,delete(key)] : nil
|
124
|
+
end
|
125
|
+
def to_a
|
126
|
+
ary = []
|
127
|
+
each { |k,v| ary << [k,v] }
|
128
|
+
ary
|
129
|
+
end
|
130
|
+
def to_s
|
131
|
+
self.to_a.to_s
|
132
|
+
end
|
133
|
+
def inspect
|
134
|
+
ary = []
|
135
|
+
each {|k,v| ary << k.inspect + "=>" + v.inspect}
|
136
|
+
'{' + ary.join(", ") + '}'
|
137
|
+
end
|
138
|
+
def update hsh2
|
139
|
+
hsh2.each { |k,v| self[k] = v }
|
140
|
+
self
|
141
|
+
end
|
142
|
+
alias :merge! update
|
143
|
+
def merge hsh2
|
144
|
+
self.dup update(hsh2)
|
145
|
+
end
|
146
|
+
def select
|
147
|
+
ary = []
|
148
|
+
each { |k,v| ary << [k,v] if yield k,v }
|
149
|
+
ary
|
150
|
+
end
|
151
|
+
def class
|
152
|
+
Hash
|
153
|
+
end
|
154
|
+
def __class__
|
155
|
+
OrderedHash
|
156
|
+
end
|
157
|
+
|
158
|
+
attr_accessor "to_yaml_style"
|
159
|
+
def yaml_inline= bool
|
160
|
+
if respond_to?("to_yaml_style")
|
161
|
+
self.to_yaml_style = :inline
|
162
|
+
else
|
163
|
+
unless defined? @__yaml_inline_meth
|
164
|
+
@__yaml_inline_meth =
|
165
|
+
lambda {|opts|
|
166
|
+
YAML::quick_emit(object_id, opts) {|emitter|
|
167
|
+
emitter << '{ ' << map{|kv| kv.join ': '}.join(', ') << ' }'
|
168
|
+
}
|
169
|
+
}
|
170
|
+
class << self
|
171
|
+
def to_yaml opts = {}
|
172
|
+
begin
|
173
|
+
@__yaml_inline ? @__yaml_inline_meth[ opts ] : super
|
174
|
+
rescue
|
175
|
+
@to_yaml_style = :inline
|
176
|
+
super
|
177
|
+
end
|
178
|
+
end
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
182
|
+
@__yaml_inline = bool
|
183
|
+
end
|
184
|
+
def yaml_inline!() self.yaml_inline = true end
|
185
|
+
end # class OrderedHash
|
186
|
+
|
187
|
+
def OrderedHash(*a, &b)
|
188
|
+
OrderedHash.new(*a, &b)
|
189
|
+
end
|