tap 0.18.0 → 0.19.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|