tap 0.18.0 → 0.19.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/History +21 -0
- data/MIT-LICENSE +17 -15
- data/README +13 -30
- data/bin/tap +19 -24
- data/cmd/console.rb +1 -12
- data/cmd/manifest.rb +14 -19
- data/cmd/run.rb +96 -86
- data/doc/API +194 -54
- data/doc/Examples/Command Line +27 -1
- data/lib/tap.rb +2 -1
- data/lib/tap/app.rb +613 -166
- data/lib/tap/app/api.rb +115 -0
- data/lib/tap/app/queue.rb +36 -37
- data/lib/tap/app/state.rb +2 -1
- data/lib/tap/env.rb +454 -270
- data/lib/tap/env/constant.rb +83 -33
- data/lib/tap/env/context.rb +61 -0
- data/lib/tap/env/manifest.rb +140 -50
- data/lib/tap/env/minimap.rb +55 -39
- data/lib/tap/join.rb +71 -53
- data/lib/tap/joins/sync.rb +3 -1
- data/lib/tap/middleware.rb +4 -25
- data/lib/tap/middlewares/debugger.rb +75 -0
- data/lib/tap/parser.rb +268 -0
- data/lib/tap/prompt.rb +36 -0
- data/lib/tap/root.rb +3 -3
- data/lib/tap/signals.rb +26 -0
- data/lib/tap/signals/class_methods.rb +222 -0
- data/lib/tap/signals/help.rb +40 -0
- data/lib/tap/signals/module_methods.rb +20 -0
- data/lib/tap/signals/signal.rb +68 -0
- data/lib/tap/task.rb +28 -79
- data/lib/tap/tasks/dump.rb +6 -0
- data/lib/tap/tasks/load.rb +9 -37
- data/lib/tap/templater.rb +12 -1
- data/lib/tap/version.rb +1 -1
- metadata +22 -16
- data/doc/Class Reference +0 -330
- data/lib/tap/exe.rb +0 -130
- data/lib/tap/schema.rb +0 -374
- data/lib/tap/schema/parser.rb +0 -425
- data/lib/tap/schema/utils.rb +0 -56
data/lib/tap/parser.rb
ADDED
@@ -0,0 +1,268 @@
|
|
1
|
+
require 'shellwords'
|
2
|
+
|
3
|
+
module Tap
|
4
|
+
|
5
|
+
# A parser for workflows defined on the command line.
|
6
|
+
class Parser
|
7
|
+
class << self
|
8
|
+
def parse(argv=ARGV)
|
9
|
+
parse!(argv.dup)
|
10
|
+
end
|
11
|
+
|
12
|
+
def parse!(argv=ARGV)
|
13
|
+
argv = Shellwords.shellwords(argv) if argv.kind_of?(String)
|
14
|
+
sig, obj = argv.shift, nil
|
15
|
+
|
16
|
+
if sig =~ OBJECT
|
17
|
+
obj, sig = $1, $2
|
18
|
+
end
|
19
|
+
|
20
|
+
[obj, sig, argv]
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
# The escape begin argument
|
25
|
+
ESCAPE_BEGIN = "-."
|
26
|
+
|
27
|
+
# The escape end argument
|
28
|
+
ESCAPE_END = ".-"
|
29
|
+
|
30
|
+
# The parser end flag
|
31
|
+
END_FLAG = "---"
|
32
|
+
|
33
|
+
# Matches any breaking arg. Examples:
|
34
|
+
#
|
35
|
+
# --
|
36
|
+
# --:
|
37
|
+
# --[1,2][3]
|
38
|
+
# --@
|
39
|
+
# --/var
|
40
|
+
# --.
|
41
|
+
#
|
42
|
+
# After the match:
|
43
|
+
#
|
44
|
+
# $1:: The string after the break, or nil
|
45
|
+
# (ex: '--' => nil, '--:' => ':', '--[1,2][3,4]' => '[1,2][3,4]')
|
46
|
+
#
|
47
|
+
BREAK = /\A--(?:\z|([\:\[\/\.@].*?)\z)/
|
48
|
+
|
49
|
+
# The node modifier.
|
50
|
+
NODE_BREAK = nil
|
51
|
+
|
52
|
+
# The join modifier.
|
53
|
+
JOIN_BREAK = "."
|
54
|
+
|
55
|
+
# Matches a sequence break. After the match:
|
56
|
+
#
|
57
|
+
# $1:: The modifier string, or nil
|
58
|
+
# (ex: ':' => nil, ':i' => 'i')
|
59
|
+
#
|
60
|
+
SEQUENCE = /\A:(.+)?\z/
|
61
|
+
|
62
|
+
# Matches a generic join break. After the match:
|
63
|
+
#
|
64
|
+
# $1:: The inputs string.
|
65
|
+
# (ex: '[1,2,3][4,5,6]' => '1,2,3')
|
66
|
+
# $2:: The outputs string.
|
67
|
+
# (ex: '[1,2,3][4,5,6]' => '4,5,6')
|
68
|
+
# $3:: The modifier string, or nil
|
69
|
+
# (ex: '[][]is' => 'is')
|
70
|
+
#
|
71
|
+
JOIN = /\A\[(.*?)\]\[(.*?)\](.+)?\z/
|
72
|
+
|
73
|
+
# Matches a join modifier. After the match:
|
74
|
+
#
|
75
|
+
# $1:: The modifier flag string.
|
76
|
+
# (ex: 'is.sync' => 'is')
|
77
|
+
# $2:: The class string.
|
78
|
+
# (ex: 'is.sync' => 'sync')
|
79
|
+
#
|
80
|
+
JOIN_MODIFIER = /\A([A-z]*)(?:\.(.*))?\z/
|
81
|
+
|
82
|
+
# Matches an enque modifier. After the match:
|
83
|
+
#
|
84
|
+
# $1:: The modifier string, or nil
|
85
|
+
# (ex: '@var' => 'var')
|
86
|
+
#
|
87
|
+
ENQUE = /\A@(.+)?\z/
|
88
|
+
|
89
|
+
# Matches a signal break. After the match:
|
90
|
+
#
|
91
|
+
# $1:: The object string, or nil
|
92
|
+
# (ex: 'obj/sig' => 'obj')
|
93
|
+
# $2:: The signal string
|
94
|
+
# (ex: 'obj/sig' => 'sig')
|
95
|
+
#
|
96
|
+
SIGNAL = /\A\/(?:(.*)\/)?(.*)\z/
|
97
|
+
|
98
|
+
# Splits a signal into an object string and a signal string. If OBJECT
|
99
|
+
# doesn't match, then the string can be considered a signal, and the
|
100
|
+
# object is nil. After a match:
|
101
|
+
#
|
102
|
+
# $1:: The object string
|
103
|
+
# (ex: 'obj/sig' => 'obj')
|
104
|
+
# $2:: The signal string
|
105
|
+
# (ex: 'obj/sig' => 'sig')
|
106
|
+
#
|
107
|
+
OBJECT = /\A(.*)\/(.*)\z/
|
108
|
+
|
109
|
+
attr_reader :specs
|
110
|
+
|
111
|
+
def initialize(specs=[])
|
112
|
+
@specs = specs
|
113
|
+
end
|
114
|
+
|
115
|
+
def parse(argv)
|
116
|
+
argv = argv.dup unless argv.kind_of?(String)
|
117
|
+
parse!(argv)
|
118
|
+
end
|
119
|
+
|
120
|
+
# Same as parse, but removes parsed args from argv.
|
121
|
+
def parse!(argv)
|
122
|
+
argv = Shellwords.shellwords(argv) if argv.kind_of?(String)
|
123
|
+
return argv if argv.empty?
|
124
|
+
|
125
|
+
unless argv[0] =~ BREAK
|
126
|
+
argv.unshift("--")
|
127
|
+
end
|
128
|
+
|
129
|
+
@current_type = nil
|
130
|
+
@current_index = -1
|
131
|
+
@current = nil
|
132
|
+
escape = false
|
133
|
+
|
134
|
+
while !argv.empty?
|
135
|
+
arg = argv.shift
|
136
|
+
|
137
|
+
# if escaping, add escaped arguments
|
138
|
+
# until an escape-end argument
|
139
|
+
if escape
|
140
|
+
if arg == ESCAPE_END
|
141
|
+
escape = false
|
142
|
+
else
|
143
|
+
current << arg
|
144
|
+
end
|
145
|
+
next
|
146
|
+
end
|
147
|
+
|
148
|
+
# handle breaks and parser flags
|
149
|
+
case arg
|
150
|
+
when BREAK
|
151
|
+
begin
|
152
|
+
@current_type = nil
|
153
|
+
@current_index += 1
|
154
|
+
@current = parse_break($1)
|
155
|
+
rescue
|
156
|
+
raise "invalid break: #{arg} (#{$!.message})"
|
157
|
+
end
|
158
|
+
next
|
159
|
+
|
160
|
+
when ESCAPE_BEGIN
|
161
|
+
escape = true
|
162
|
+
next
|
163
|
+
|
164
|
+
when END_FLAG
|
165
|
+
break
|
166
|
+
|
167
|
+
end if arg[0] == ?-
|
168
|
+
|
169
|
+
# add all remaining args to the current argv
|
170
|
+
current << arg
|
171
|
+
end
|
172
|
+
|
173
|
+
@current_type = nil
|
174
|
+
@current_index = nil
|
175
|
+
@current = nil
|
176
|
+
|
177
|
+
argv
|
178
|
+
end
|
179
|
+
|
180
|
+
private
|
181
|
+
|
182
|
+
def spec(*argv) # :nodoc:
|
183
|
+
specs << argv
|
184
|
+
argv
|
185
|
+
end
|
186
|
+
|
187
|
+
# returns the current argv or a new spec argv for the current type/index
|
188
|
+
def current # :nodoc:
|
189
|
+
@current ||= spec(@current_type, nil, 'set', @current_index.to_s)
|
190
|
+
end
|
191
|
+
|
192
|
+
# determines the type of break and modifies self appropriately
|
193
|
+
def parse_break(one) # :nodoc:
|
194
|
+
case one
|
195
|
+
when NODE_BREAK
|
196
|
+
set_type(:node)
|
197
|
+
when JOIN_BREAK
|
198
|
+
set_type(:join)
|
199
|
+
when SEQUENCE
|
200
|
+
parse_sequence($1)
|
201
|
+
when JOIN
|
202
|
+
parse_join($1, $2, $3)
|
203
|
+
when ENQUE
|
204
|
+
parse_enque($1)
|
205
|
+
when SIGNAL
|
206
|
+
parse_signal($1, $2)
|
207
|
+
else
|
208
|
+
raise "invalid modifier"
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
# sets the type of the next spec
|
213
|
+
def set_type(type) # :nodoc:
|
214
|
+
@current_type = type
|
215
|
+
nil
|
216
|
+
end
|
217
|
+
|
218
|
+
# parses the match of a SEQUENCE regexp
|
219
|
+
def parse_sequence(one) # :nodoc:
|
220
|
+
unless @current_index > 0
|
221
|
+
raise "no prior entry"
|
222
|
+
end
|
223
|
+
|
224
|
+
@current_type = :node
|
225
|
+
@current = nil
|
226
|
+
argv = current
|
227
|
+
parse_join_spec(one, "#{@current_index - 1}", @current_index.to_s)
|
228
|
+
argv
|
229
|
+
end
|
230
|
+
|
231
|
+
# parses the match of a JOIN regexp
|
232
|
+
def parse_join(one, two, three) # :nodoc:
|
233
|
+
parse_join_spec(three, one, two)
|
234
|
+
end
|
235
|
+
|
236
|
+
# parses a join modifier string into an argv.
|
237
|
+
def parse_join_spec(modifier, inputs, outputs) # :nodoc:
|
238
|
+
argv = [:join, nil, 'set', nil]
|
239
|
+
|
240
|
+
case
|
241
|
+
when modifier.nil?
|
242
|
+
argv << 'tap:join'
|
243
|
+
argv << inputs
|
244
|
+
argv << outputs
|
245
|
+
when modifier =~ JOIN_MODIFIER
|
246
|
+
argv << ($2 || 'join')
|
247
|
+
argv << inputs
|
248
|
+
argv << outputs
|
249
|
+
$1.split("").each {|char| argv << "-#{char}"}
|
250
|
+
else
|
251
|
+
raise "invalid join modifier"
|
252
|
+
end
|
253
|
+
|
254
|
+
specs << argv
|
255
|
+
argv
|
256
|
+
end
|
257
|
+
|
258
|
+
# parses the match of an ENQUE regexp
|
259
|
+
def parse_enque(one) # :nodoc:
|
260
|
+
spec(:signal, nil, 'enque', one)
|
261
|
+
end
|
262
|
+
|
263
|
+
# parses the match of a SIGNAL regexp
|
264
|
+
def parse_signal(one, two) # :nodoc:
|
265
|
+
spec(:signal, one, two)
|
266
|
+
end
|
267
|
+
end
|
268
|
+
end
|
data/lib/tap/prompt.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'tap/app/api'
|
2
|
+
require 'readline'
|
3
|
+
|
4
|
+
module Tap
|
5
|
+
|
6
|
+
# :startdoc::prompt
|
7
|
+
#
|
8
|
+
# A prompt to signal a running app. Any signals that return app (ie /run
|
9
|
+
# /stop /terminate) will exit the prompt.
|
10
|
+
class Prompt < App::Api
|
11
|
+
|
12
|
+
def call
|
13
|
+
puts "starting prompt (help for help):"
|
14
|
+
loop do
|
15
|
+
begin
|
16
|
+
line = Readline.readline('--/', true).strip
|
17
|
+
next if line.empty?
|
18
|
+
|
19
|
+
args = Shellwords.shellwords(line)
|
20
|
+
"/#{args.shift}" =~ Tap::Parser::SIGNAL
|
21
|
+
|
22
|
+
result = app.call('obj' => $1, 'sig' => $2, 'args' => args)
|
23
|
+
if result == app
|
24
|
+
break
|
25
|
+
else
|
26
|
+
puts "=> #{result}"
|
27
|
+
end
|
28
|
+
rescue
|
29
|
+
puts $!.message
|
30
|
+
puts $!.backtrace if app.debug?
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
data/lib/tap/root.rb
CHANGED
@@ -54,14 +54,14 @@ module Tap
|
|
54
54
|
include Utils
|
55
55
|
|
56
56
|
# The root directory.
|
57
|
-
config_attr(:root, '.', :writer => false, :
|
57
|
+
config_attr(:root, '.', :writer => false, :init => false)
|
58
58
|
|
59
59
|
# A hash of (alias, relative path) pairs for aliased paths relative
|
60
60
|
# to root.
|
61
|
-
config_attr(:relative_paths, {}, :writer => false, :
|
61
|
+
config_attr(:relative_paths, {}, :writer => false, :init => false, :type => :hash)
|
62
62
|
|
63
63
|
# A hash of (alias, relative path) pairs for aliased absolute paths.
|
64
|
-
config_attr(:absolute_paths, {}, :reader => false, :writer => false, :
|
64
|
+
config_attr(:absolute_paths, {}, :reader => false, :writer => false, :init => false, :type => :hash)
|
65
65
|
|
66
66
|
# A hash of (alias, expanded path) pairs for expanded relative and
|
67
67
|
# absolute paths.
|
data/lib/tap/signals.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'tap/signals/module_methods'
|
2
|
+
|
3
|
+
module Tap
|
4
|
+
|
5
|
+
# Signals is a module providing signaling capbilities for objects. Signals
|
6
|
+
# are effectively bound to methods with pre-processing that allows inputs
|
7
|
+
# from the command line (ie an ARGV) or from interfaces like HTTP that
|
8
|
+
# commonly produce a parameters hash.
|
9
|
+
#
|
10
|
+
module Signals
|
11
|
+
def signal(sig, &block)
|
12
|
+
sig = sig.to_s
|
13
|
+
unless signal = self.class.signals[sig]
|
14
|
+
raise "unknown signal: #{sig} (#{self.class})"
|
15
|
+
end
|
16
|
+
|
17
|
+
signal.new(self, &block)
|
18
|
+
end
|
19
|
+
|
20
|
+
def signal?(sig)
|
21
|
+
sig = sig.to_s
|
22
|
+
self.class.signals.has_key?(sig.to_s)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
@@ -0,0 +1,222 @@
|
|
1
|
+
require 'tap/signals/signal'
|
2
|
+
|
3
|
+
module Tap
|
4
|
+
module Signals
|
5
|
+
module ClassMethods
|
6
|
+
SIGNALS_CLASS = Configurable::ClassMethods::CONFIGURATIONS_CLASS
|
7
|
+
|
8
|
+
# A hash of (key, Signal) pairs defining signals available to the class.
|
9
|
+
attr_reader :signal_registry
|
10
|
+
|
11
|
+
def self.initialize(base)
|
12
|
+
unless base.instance_variable_defined?(:@signal_registry)
|
13
|
+
base.instance_variable_set(:@signal_registry, SIGNALS_CLASS.new)
|
14
|
+
end
|
15
|
+
|
16
|
+
unless base.instance_variable_defined?(:@signals)
|
17
|
+
base.instance_variable_set(:@signals, nil)
|
18
|
+
end
|
19
|
+
|
20
|
+
unless base.instance_variable_defined?(:@use_signal_constants)
|
21
|
+
base.instance_variable_set(:@use_signal_constants, true)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# A hash of (key, Signal) pairs representing all signals defined on this
|
26
|
+
# class or inherited from ancestors. The signals hash is generated on
|
27
|
+
# each call to ensure it accurately reflects any signals added on
|
28
|
+
# ancestors. This slows down signal calls through instance.signal.
|
29
|
+
#
|
30
|
+
# Call cache_signals after all signals have been declared in order
|
31
|
+
# to prevent regeneration of signals and to significantly improve
|
32
|
+
# performance.
|
33
|
+
def signals
|
34
|
+
return @signals if @signals
|
35
|
+
|
36
|
+
signals = SIGNALS_CLASS.new
|
37
|
+
ancestors.reverse.each do |ancestor|
|
38
|
+
next unless ancestor.kind_of?(ClassMethods)
|
39
|
+
ancestor.signal_registry.each_pair do |key, value|
|
40
|
+
if value.nil?
|
41
|
+
signals.delete(key)
|
42
|
+
else
|
43
|
+
signals[key] = value
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
signals
|
49
|
+
end
|
50
|
+
|
51
|
+
# Caches the signals hash so as to improve peformance. Call with on set to
|
52
|
+
# false to turn off caching.
|
53
|
+
def cache_signals(on=true)
|
54
|
+
@signals = nil
|
55
|
+
@signals = self.signals if on
|
56
|
+
end
|
57
|
+
|
58
|
+
protected
|
59
|
+
|
60
|
+
def use_signal_constants(input=true)
|
61
|
+
@use_signal_constants = input
|
62
|
+
end
|
63
|
+
|
64
|
+
# Defines a signal to call a method using an argument vector. The argv
|
65
|
+
# is sent to the method using a splat, so any method may be signaled.
|
66
|
+
# A signature of keys may be specified to automatically generate an argv
|
67
|
+
# from a hash; values for the keys are collected in order.
|
68
|
+
#
|
69
|
+
# A block may also be provided to pre-process the argv before it is sent
|
70
|
+
# to the method; the block return is sent to the method (and so should
|
71
|
+
# be an argv).
|
72
|
+
def signal(sig, opts={}) # :yields: sig, argv
|
73
|
+
signature = opts[:signature] || []
|
74
|
+
remainder = opts[:remainder] || false
|
75
|
+
|
76
|
+
signal = define_signal(sig, opts) do |args|
|
77
|
+
argv = convert_to_array(args, signature, remainder)
|
78
|
+
block_given? ? yield(self, argv) : argv
|
79
|
+
end
|
80
|
+
|
81
|
+
register_signal(sig, signal, opts)
|
82
|
+
end
|
83
|
+
|
84
|
+
# Defines a signal to call a method that receives a single hash as an
|
85
|
+
# input. A signature may be specified to automatically generate a
|
86
|
+
# hash from an array input.
|
87
|
+
#
|
88
|
+
# A block may also be provided to pre-process the hash before it is sent
|
89
|
+
# to the method; the block return is sent to the method (and so should
|
90
|
+
# be a hash).
|
91
|
+
def signal_hash(sig, opts={}) # :yields: sig, argh
|
92
|
+
signature = opts[:signature] || []
|
93
|
+
remainder = opts[:remainder]
|
94
|
+
|
95
|
+
signal = define_signal(sig, opts) do |args|
|
96
|
+
argh = convert_to_hash(args, signature, remainder)
|
97
|
+
[block_given? ? yield(self, argh) : argh]
|
98
|
+
end
|
99
|
+
|
100
|
+
register_signal(sig, signal, opts)
|
101
|
+
end
|
102
|
+
|
103
|
+
def signal_class(sig, signal_class=Signal, opts={}, &block) # :yields: sig, argv
|
104
|
+
if block_given?
|
105
|
+
signal = Class.new(signal_class)
|
106
|
+
signal.class_eval(&block)
|
107
|
+
else
|
108
|
+
signal = signal_class
|
109
|
+
end
|
110
|
+
|
111
|
+
register_signal(sig, signal, opts)
|
112
|
+
end
|
113
|
+
|
114
|
+
# Removes a signal much like remove_method removes a method. The signal
|
115
|
+
# constant is likewise removed unless the :remove_const option is set to
|
116
|
+
# to true.
|
117
|
+
def remove_signal(sig, opts={})
|
118
|
+
sig = sig.to_s
|
119
|
+
unless signal_registry.has_key?(sig)
|
120
|
+
raise NameError.new("#{sig} is not a signal for #{self}")
|
121
|
+
end
|
122
|
+
|
123
|
+
unregister_signal(sig, opts)
|
124
|
+
end
|
125
|
+
|
126
|
+
# Undefines a signal much like undef_method undefines a method. The signal
|
127
|
+
# constant is likewise removed unless the :remove_const option is set to
|
128
|
+
# to true.
|
129
|
+
#
|
130
|
+
# ==== Implementation Note
|
131
|
+
#
|
132
|
+
# Signals are undefined by setting the key to nil in the registry. Deleting
|
133
|
+
# the signal is not sufficient because the registry needs to convey to self
|
134
|
+
# and subclasses to not inherit the signal from ancestors.
|
135
|
+
#
|
136
|
+
# This is unlike remove_signal where the signal is simply deleted from
|
137
|
+
# the signal_registry.
|
138
|
+
#
|
139
|
+
def undef_signal(sig, opts={})
|
140
|
+
# temporarily cache as an optimization
|
141
|
+
signals_cache = signals
|
142
|
+
sig = sig.to_s
|
143
|
+
unless signals_cache.has_key?(sig)
|
144
|
+
raise NameError.new("#{sig} is not a signal for #{self}")
|
145
|
+
end
|
146
|
+
|
147
|
+
unregister_signal(sig, opts)
|
148
|
+
signal_registry[sig] = nil
|
149
|
+
signals_cache[sig]
|
150
|
+
end
|
151
|
+
|
152
|
+
private
|
153
|
+
|
154
|
+
def inherited(base) # :nodoc:
|
155
|
+
ClassMethods.initialize(base)
|
156
|
+
|
157
|
+
unless base.instance_variable_defined?(:@use_signal_constants)
|
158
|
+
base.instance_variable_set(:@use_signal_constants, true)
|
159
|
+
end
|
160
|
+
|
161
|
+
super
|
162
|
+
end
|
163
|
+
|
164
|
+
def define_signal(sig, opts={}, &block) # :nodoc:
|
165
|
+
# generate a subclass of signal
|
166
|
+
klass = opts[:class] || Signal
|
167
|
+
signal = Class.new(klass)
|
168
|
+
|
169
|
+
# bind the new signal
|
170
|
+
method_name = opts.has_key?(:bind) ? opts[:bind] : sig
|
171
|
+
if method_name
|
172
|
+
signal.send(:define_method, :call) do |args|
|
173
|
+
args = process(args)
|
174
|
+
obj.send(method_name, *args, &self.block)
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
if block_given?
|
179
|
+
signal.send(:define_method, :process, &block)
|
180
|
+
end
|
181
|
+
|
182
|
+
signal
|
183
|
+
end
|
184
|
+
|
185
|
+
def register_signal(sig, signal, opts={}) # :nodoc:
|
186
|
+
if signal.respond_to?(:desc=)
|
187
|
+
signal.desc ||= Lazydoc.register_caller(Lazydoc::Trailer, 2)
|
188
|
+
end
|
189
|
+
|
190
|
+
signal_registry[sig.to_s] = signal
|
191
|
+
cache_signals(@signals != nil)
|
192
|
+
|
193
|
+
# set the new constant, if specified
|
194
|
+
if @use_signal_constants
|
195
|
+
const_name = opts.has_key?(:const_name) ? opts[:const_name] : sig.to_s.capitalize
|
196
|
+
const_name = const_name.to_s
|
197
|
+
|
198
|
+
if const_name =~ /\A[A-Z]\w*\z/ && !const_defined?(const_name)
|
199
|
+
const_set(const_name, signal)
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
signal
|
204
|
+
end
|
205
|
+
|
206
|
+
def unregister_signal(sig, opts={}) # :nodoc:
|
207
|
+
signal = signal_registry.delete(sig.to_s)
|
208
|
+
|
209
|
+
remove_const = opts.has_key?(:remove_const) ? opts[:remove_const] : true
|
210
|
+
if @use_signal_constants && remove_const
|
211
|
+
const_name = signal.to_s.split("::").pop.to_s
|
212
|
+
if const_name =~ /\A[A-Z]\w*\z/ && const_defined?(const_name)
|
213
|
+
remove_const(const_name)
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
cache_signals(@signals != nil)
|
218
|
+
signal
|
219
|
+
end
|
220
|
+
end
|
221
|
+
end
|
222
|
+
end
|