punchblock 1.9.4 → 2.0.0.beta1

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.
Files changed (142) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.travis.yml +1 -2
  4. data/CHANGELOG.md +17 -0
  5. data/Gemfile +1 -0
  6. data/Guardfile +4 -0
  7. data/README.markdown +6 -0
  8. data/Rakefile +16 -0
  9. data/benchmarks/ami_event_name_comparison.rb +14 -0
  10. data/benchmarks/channel.rb +27 -0
  11. data/lib/punchblock/client.rb +2 -6
  12. data/lib/punchblock/command/accept.rb +3 -24
  13. data/lib/punchblock/command/answer.rb +3 -24
  14. data/lib/punchblock/command/dial.rb +24 -76
  15. data/lib/punchblock/command/hangup.rb +3 -19
  16. data/lib/punchblock/command/join.rb +21 -70
  17. data/lib/punchblock/command/mute.rb +3 -3
  18. data/lib/punchblock/command/redirect.rb +6 -39
  19. data/lib/punchblock/command/reject.rb +14 -54
  20. data/lib/punchblock/command/unjoin.rb +8 -40
  21. data/lib/punchblock/command/unmute.rb +3 -3
  22. data/lib/punchblock/command_node.rb +0 -17
  23. data/lib/punchblock/component/asterisk/agi/command.rb +20 -127
  24. data/lib/punchblock/component/asterisk/ami/action.rb +30 -117
  25. data/lib/punchblock/component/component_node.rb +1 -1
  26. data/lib/punchblock/component/input.rb +89 -268
  27. data/lib/punchblock/component/output.rb +106 -154
  28. data/lib/punchblock/component/prompt.rb +51 -0
  29. data/lib/punchblock/component/record.rb +41 -130
  30. data/lib/punchblock/component.rb +1 -0
  31. data/lib/punchblock/connection/asterisk.rb +31 -4
  32. data/lib/punchblock/connection/xmpp.rb +6 -14
  33. data/lib/punchblock/core_ext/blather/stanza.rb +1 -1
  34. data/lib/punchblock/event/active_speaker.rb +2 -10
  35. data/lib/punchblock/event/answered.rb +3 -3
  36. data/lib/punchblock/event/asterisk/ami/event.rb +15 -47
  37. data/lib/punchblock/event/complete.rb +26 -48
  38. data/lib/punchblock/event/dtmf.rb +3 -13
  39. data/lib/punchblock/event/end.rb +10 -11
  40. data/lib/punchblock/event/joined.rb +5 -25
  41. data/lib/punchblock/event/offer.rb +4 -25
  42. data/lib/punchblock/event/ringing.rb +3 -3
  43. data/lib/punchblock/event/unjoined.rb +5 -25
  44. data/lib/punchblock/event.rb +0 -10
  45. data/lib/punchblock/has_headers.rb +20 -26
  46. data/lib/punchblock/rayo_node.rb +46 -23
  47. data/lib/punchblock/ref.rb +39 -18
  48. data/lib/punchblock/translator/asterisk/agi_app.rb +15 -0
  49. data/lib/punchblock/translator/asterisk/agi_command.rb +3 -1
  50. data/lib/punchblock/translator/asterisk/ami_error_converter.rb +20 -0
  51. data/lib/punchblock/translator/asterisk/call.rb +60 -39
  52. data/lib/punchblock/translator/asterisk/channel.rb +41 -0
  53. data/lib/punchblock/translator/asterisk/component/asterisk/agi_command.rb +4 -1
  54. data/lib/punchblock/translator/asterisk/component/asterisk/ami_action.rb +4 -4
  55. data/lib/punchblock/translator/asterisk/component/composed_prompt.rb +62 -0
  56. data/lib/punchblock/translator/asterisk/component/input.rb +1 -0
  57. data/lib/punchblock/translator/asterisk/component/mrcp_native_prompt.rb +56 -0
  58. data/lib/punchblock/translator/asterisk/component/mrcp_prompt.rb +53 -0
  59. data/lib/punchblock/translator/asterisk/component/mrcp_recog_prompt.rb +99 -0
  60. data/lib/punchblock/translator/asterisk/component/output.rb +30 -22
  61. data/lib/punchblock/translator/asterisk/component/record.rb +8 -6
  62. data/lib/punchblock/translator/asterisk/component.rb +6 -5
  63. data/lib/punchblock/translator/asterisk/unimrcp_app.rb +26 -0
  64. data/lib/punchblock/translator/asterisk.rb +24 -28
  65. data/lib/punchblock/translator/dtmf_recognizer.rb +39 -20
  66. data/lib/punchblock/translator/freeswitch/call.rb +15 -14
  67. data/lib/punchblock/translator/freeswitch/component/abstract_output.rb +5 -4
  68. data/lib/punchblock/translator/freeswitch/component/flite_output.rb +1 -1
  69. data/lib/punchblock/translator/freeswitch/component/input.rb +5 -0
  70. data/lib/punchblock/translator/freeswitch/component/output.rb +2 -2
  71. data/lib/punchblock/translator/freeswitch/component/record.rb +19 -13
  72. data/lib/punchblock/translator/freeswitch/component/tts_output.rb +2 -2
  73. data/lib/punchblock/translator/freeswitch/component.rb +2 -5
  74. data/lib/punchblock/translator/freeswitch.rb +2 -2
  75. data/lib/punchblock/translator/input_component.rb +33 -13
  76. data/lib/punchblock/uri_list.rb +21 -0
  77. data/lib/punchblock/version.rb +1 -1
  78. data/lib/punchblock.rb +4 -3
  79. data/punchblock.gemspec +7 -3
  80. data/spec/punchblock/client/component_registry_spec.rb +1 -1
  81. data/spec/punchblock/client_spec.rb +10 -26
  82. data/spec/punchblock/command/accept_spec.rb +41 -7
  83. data/spec/punchblock/command/answer_spec.rb +51 -7
  84. data/spec/punchblock/command/dial_spec.rb +56 -14
  85. data/spec/punchblock/command/hangup_spec.rb +41 -7
  86. data/spec/punchblock/command/join_spec.rb +53 -11
  87. data/spec/punchblock/command/mute_spec.rb +19 -4
  88. data/spec/punchblock/command/redirect_spec.rb +40 -10
  89. data/spec/punchblock/command/reject_spec.rb +43 -11
  90. data/spec/punchblock/command/unjoin_spec.rb +40 -9
  91. data/spec/punchblock/command/unmute_spec.rb +19 -4
  92. data/spec/punchblock/command_node_spec.rb +0 -4
  93. data/spec/punchblock/component/asterisk/agi/command_spec.rb +16 -39
  94. data/spec/punchblock/component/asterisk/ami/action_spec.rb +50 -53
  95. data/spec/punchblock/component/component_node_spec.rb +3 -5
  96. data/spec/punchblock/component/input_spec.rb +194 -61
  97. data/spec/punchblock/component/output_spec.rb +194 -62
  98. data/spec/punchblock/component/prompt_spec.rb +132 -0
  99. data/spec/punchblock/component/record_spec.rb +70 -32
  100. data/spec/punchblock/connection/asterisk_spec.rb +17 -3
  101. data/spec/punchblock/connection/freeswitch_spec.rb +4 -4
  102. data/spec/punchblock/connection/xmpp_spec.rb +20 -38
  103. data/spec/punchblock/event/answered_spec.rb +12 -10
  104. data/spec/punchblock/event/asterisk/ami/event_spec.rb +27 -22
  105. data/spec/punchblock/event/complete_spec.rb +15 -19
  106. data/spec/punchblock/event/dtmf_spec.rb +5 -6
  107. data/spec/punchblock/event/end_spec.rb +20 -10
  108. data/spec/punchblock/event/joined_spec.rb +8 -7
  109. data/spec/punchblock/event/offer_spec.rb +41 -12
  110. data/spec/punchblock/event/ringing_spec.rb +12 -10
  111. data/spec/punchblock/event/started_speaking_spec.rb +5 -6
  112. data/spec/punchblock/event/stopped_speaking_spec.rb +5 -6
  113. data/spec/punchblock/event/unjoined_spec.rb +7 -7
  114. data/spec/punchblock/ref_spec.rb +86 -9
  115. data/spec/punchblock/translator/asterisk/call_spec.rb +317 -154
  116. data/spec/punchblock/translator/asterisk/component/asterisk/agi_command_spec.rb +28 -5
  117. data/spec/punchblock/translator/asterisk/component/asterisk/ami_action_spec.rb +15 -13
  118. data/spec/punchblock/translator/asterisk/component/composed_prompt_spec.rb +237 -0
  119. data/spec/punchblock/translator/asterisk/component/input_spec.rb +171 -14
  120. data/spec/punchblock/translator/asterisk/component/mrcp_native_prompt_spec.rb +652 -0
  121. data/spec/punchblock/translator/asterisk/component/mrcp_prompt_spec.rb +646 -0
  122. data/spec/punchblock/translator/asterisk/component/output_spec.rb +127 -77
  123. data/spec/punchblock/translator/asterisk/component/record_spec.rb +17 -8
  124. data/spec/punchblock/translator/asterisk/component/stop_by_redirect_spec.rb +2 -2
  125. data/spec/punchblock/translator/asterisk/component_spec.rb +3 -7
  126. data/spec/punchblock/translator/asterisk_spec.rb +20 -24
  127. data/spec/punchblock/translator/freeswitch/call_spec.rb +103 -99
  128. data/spec/punchblock/translator/freeswitch/component/flite_output_spec.rb +17 -8
  129. data/spec/punchblock/translator/freeswitch/component/input_spec.rb +26 -14
  130. data/spec/punchblock/translator/freeswitch/component/output_spec.rb +30 -52
  131. data/spec/punchblock/translator/freeswitch/component/record_spec.rb +23 -19
  132. data/spec/punchblock/translator/freeswitch/component/tts_output_spec.rb +18 -8
  133. data/spec/punchblock/translator/freeswitch/component_spec.rb +4 -8
  134. data/spec/punchblock/translator/freeswitch_spec.rb +11 -14
  135. data/spec/punchblock/uri_list_spec.rb +49 -0
  136. data/spec/punchblock_spec.rb +11 -1
  137. data/spec/spec_helper.rb +7 -11
  138. data/spec/support/mock_connection_with_event_handler.rb +1 -1
  139. metadata +104 -24
  140. data/lib/punchblock/header.rb +0 -9
  141. data/lib/punchblock/key_value_pair_node.rb +0 -51
  142. data/spec/punchblock/header_spec.rb +0 -11
@@ -3,158 +3,40 @@
3
3
  module Punchblock
4
4
  module Component
5
5
  class Input < ComponentNode
6
- register :input, :input
6
+ NLSML_NAMESPACE = 'http://www.ietf.org/xml/ns/mrcpv2'
7
7
 
8
- ##
9
- # Create a input command
10
- #
11
- # @param [Hash] options
12
- # @option options [Grammar, Hash] :grammar the grammar to activate
13
- # @option options [Integer, optional] :max_silence the amount of time in milliseconds that an input command will wait until considered that a silence becomes a NO-MATCH
14
- # @option options [Float, optional] :min_confidence with which to consider a response acceptable
15
- # @option options [Symbol, optional] :mode by which to accept input. Can be :speech, :dtmf or :any
16
- # @option options [String, optional] :recognizer to use for speech recognition
17
- # @option options [String, optional] :terminator by which to signal the end of input
18
- # @option options [Float, optional] :sensitivity Indicates how sensitive the interpreter should be to loud versus quiet input. Higher values represent greater sensitivity.
19
- # @option options [Integer, optional] :initial_timeout Indicates the amount of time preceding input which may expire before a timeout is triggered.
20
- # @option options [Integer, optional] :inter_digit_timeout Indicates (in the case of DTMF input) the amount of time between input digits which may expire before a timeout is triggered.
21
- #
22
- # @return [Command::Input] a formatted Rayo input command
23
- #
24
- # @example
25
- # input :grammar => {:value => '[5 DIGITS]', :content_type => 'application/grammar+voxeo'},
26
- # :mode => :speech,
27
- # :recognizer => 'es-es'
28
- #
29
- # returns:
30
- # <input xmlns="urn:xmpp:rayo:input:1" mode="speech" recognizer="es-es">
31
- # <grammar content-type="application/grammar+voxeo">[5 DIGITS]</choices>
32
- # </input>
33
- #
34
- def self.new(options = {})
35
- super().tap do |new_node|
36
- options.each_pair { |k,v| new_node.send :"#{k}=", v }
37
- end
38
- end
8
+ register :input, :input
39
9
 
40
- ##
41
10
  # @return [Integer] the amount of time in milliseconds that an input command will wait until considered that a silence becomes a NO-MATCH
42
- #
43
- def max_silence
44
- read_attr :'max-silence', :to_i
45
- end
11
+ attribute :max_silence, Integer
46
12
 
47
- ##
48
- # @param [Integer] other the amount of time in milliseconds that an input command will wait until considered that a silence becomes a NO-MATCH
49
- #
50
- def max_silence=(other)
51
- write_attr :'max-silence', other, :to_i
52
- end
53
-
54
- ##
55
13
  # @return [Float] Confidence with which to consider a response acceptable
56
- #
57
- def min_confidence
58
- read_attr 'min-confidence', :to_f
59
- end
14
+ attribute :min_confidence, Float
60
15
 
61
- ##
62
- # @param [Float] min_confidence with which to consider a response acceptable
63
- #
64
- def min_confidence=(min_confidence)
65
- write_attr 'min-confidence', min_confidence, :to_f
66
- end
16
+ # @return [Symbol] mode by which to accept input. Can be :voice, :dtmf or :any
17
+ attribute :mode, Symbol, default: :dtmf
67
18
 
68
- ##
69
- # @return [Symbol] mode by which to accept input. Can be :speech, :dtmf or :any
70
- #
71
- def mode
72
- read_attr :mode, :to_sym
73
- end
74
-
75
- ##
76
- # @param [Symbol] mode by which to accept input. Can be :speech, :dtmf or :any
77
- #
78
- def mode=(mode)
79
- write_attr :mode, mode
80
- end
81
-
82
- ##
83
19
  # @return [String] recognizer to use for speech recognition
84
- #
85
- def recognizer
86
- read_attr :recognizer
87
- end
20
+ attribute :recognizer, String
88
21
 
89
- ##
90
- # @param [String] recognizer to use for speech recognition
91
- #
92
- def recognizer=(recognizer)
93
- write_attr :recognizer, recognizer
94
- end
22
+ # @return [String] language to use for speech recognition
23
+ attribute :language, String
95
24
 
96
- ##
97
25
  # @return [String] terminator by which to signal the end of input
98
- #
99
- def terminator
100
- read_attr :terminator
101
- end
102
-
103
- ##
104
- # @param [String] terminator by which to signal the end of input
105
- #
106
- def terminator=(terminator)
107
- write_attr :terminator, terminator
108
- end
26
+ attribute :terminator, String
109
27
 
110
- ##
111
28
  # @return [Float] Indicates how sensitive the interpreter should be to loud versus quiet input. Higher values represent greater sensitivity.
112
- #
113
- def sensitivity
114
- read_attr :sensitivity, :to_f
115
- end
116
-
117
- ##
118
- # @param [Float] other Indicates how sensitive the interpreter should be to loud versus quiet input. Higher values represent greater sensitivity.
119
- #
120
- def sensitivity=(other)
121
- write_attr :sensitivity, other, :to_f
122
- end
29
+ attribute :sensitivity, Float
123
30
 
124
- ##
125
31
  # @return [Integer] Indicates the amount of time preceding input which may expire before a timeout is triggered.
126
- #
127
- def initial_timeout
128
- read_attr :'initial-timeout', :to_i
129
- end
130
-
131
- ##
132
- # @param [Integer] timeout Indicates the amount of time preceding input which may expire before a timeout is triggered.
133
- #
134
- def initial_timeout=(other)
135
- write_attr :'initial-timeout', other, :to_i
136
- end
32
+ attribute :initial_timeout, Integer
137
33
 
138
- ##
139
34
  # @return [Integer] Indicates (in the case of DTMF input) the amount of time between input digits which may expire before a timeout is triggered.
140
- #
141
- def inter_digit_timeout
142
- read_attr :'inter-digit-timeout', :to_i
143
- end
144
-
145
- ##
146
- # @param [Integer] timeout Indicates (in the case of DTMF input) the amount of time between input digits which may expire before a timeout is triggered.
147
- #
148
- def inter_digit_timeout=(other)
149
- write_attr :'inter-digit-timeout', other, :to_i
150
- end
35
+ attribute :inter_digit_timeout, Integer
151
36
 
152
- ##
153
- # @return [Grammar] the grammar to activate
154
- #
155
- def grammar
156
- node = find_first 'ns:grammar', :ns => self.class.registered_ns
157
- Grammar.new node if node
37
+ attribute :grammars, Array, default: []
38
+ def grammars=(others)
39
+ super others.map { |other| Grammar.new(other) }
158
40
  end
159
41
 
160
42
  ##
@@ -164,174 +46,113 @@ module Punchblock
164
46
  # @option other [String] :url the url from which to fetch the grammar
165
47
  #
166
48
  def grammar=(other)
167
- return unless other
168
- remove_children :grammar
169
- grammar = Grammar.new(other) unless other.is_a?(Grammar)
170
- self << grammar
49
+ self.grammars = [other].compact
171
50
  end
172
51
 
173
- def inspect_attributes # :nodoc:
174
- [:mode, :terminator, :recognizer, :initial_timeout, :inter_digit_timeout, :sensitivity, :min_confidence, :grammar] + super
52
+ def inherit(xml_node)
53
+ grammar_nodes = xml_node.xpath('ns:grammar', ns: self.class.registered_ns)
54
+ self.grammars = grammar_nodes.to_a.map { |grammar_node| Grammar.from_xml(grammar_node)}
55
+ super
175
56
  end
176
57
 
177
- class Grammar < RayoNode
178
- ##
179
- # @param [Hash] options
180
- # @option options [String] :content_type the document content type
181
- # @option options [String] :value the grammar document
182
- # @option options [String] :url the url from which to fetch the grammar
183
- #
184
- def self.new(options = {})
185
- super(:grammar).tap do |new_node|
186
- case options
187
- when Nokogiri::XML::Node
188
- new_node.inherit options
189
- when Hash
190
- new_node.content_type = options[:content_type]
191
- new_node.value = options[:value]
192
- new_node.url = options[:url]
193
- end
194
- end
195
- end
58
+ def rayo_attributes
59
+ {
60
+ 'max-silence' => max_silence,
61
+ 'min-confidence' => min_confidence,
62
+ 'mode' => mode,
63
+ 'recognizer' => recognizer,
64
+ 'language' => language,
65
+ 'terminator' => terminator,
66
+ 'sensitivity' => sensitivity,
67
+ 'initial-timeout' => initial_timeout,
68
+ 'inter-digit-timeout' => inter_digit_timeout
69
+ }
70
+ end
196
71
 
197
- ##
198
- # @return [String] the document content type
199
- #
200
- def content_type
201
- read_attr 'content-type'
72
+ def rayo_children(root)
73
+ grammars.each do |grammar|
74
+ grammar.to_rayo(root)
202
75
  end
76
+ super
77
+ end
203
78
 
204
- ##
205
- # @param [String] content_type Defaults to GRXML
206
- #
207
- def content_type=(content_type)
208
- return unless content_type
209
- write_attr 'content-type', content_type
210
- end
79
+ class Grammar < RayoNode
80
+ register :grammar, :input
211
81
 
212
- ##
213
- # @return [String, RubySpeech::GRXML::Grammar] the grammar document
214
- def value
215
- return nil unless content.present?
216
- if grxml?
217
- RubySpeech::GRXML.import content
218
- else
219
- content
220
- end
221
- end
82
+ GRXML_CONTENT_TYPE = 'application/srgs+xml'
222
83
 
223
- ##
224
- # @param [String, RubySpeech::GRXML::Grammar] value the grammar document
225
- def value=(value)
226
- return unless value
227
- self.content_type = grxml_content_type unless self.content_type
228
- if grxml? && !value.is_a?(RubySpeech::GRXML::Element)
229
- value = RubySpeech::GRXML.import value
230
- end
231
- Nokogiri::XML::Builder.with(self) do |xml|
232
- xml.cdata " #{value} "
233
- end
234
- end
84
+ attribute :value
85
+ attribute :content_type, String, default: ->(grammar, attribute) { grammar.url ? nil : GRXML_CONTENT_TYPE }
86
+ attribute :url
235
87
 
236
- ##
237
- # @return [String] the URL from which the fetch the grammar
238
- #
239
- def url
240
- read_attr 'url'
88
+ def inherit(xml_node)
89
+ self.value = xml_node.content.strip
90
+ super
241
91
  end
242
92
 
243
- ##
244
- # @param [String] other the URL from which the fetch the grammar
245
- #
246
- def url=(other)
247
- write_attr 'url', other
93
+ def rayo_attributes
94
+ {
95
+ 'url' => url,
96
+ 'content-type' => content_type
97
+ }
248
98
  end
249
99
 
250
- def inspect_attributes # :nodoc:
251
- [:content_type, :value, :url] + super
100
+ def rayo_children(root)
101
+ root.cdata value
252
102
  end
253
103
 
254
104
  private
255
105
 
256
- def grxml_content_type
257
- 'application/srgs+xml'
258
- end
259
-
260
106
  def grxml?
261
- content_type == grxml_content_type
107
+ content_type == GRXML_CONTENT_TYPE
262
108
  end
263
- end # Choices
109
+ end
264
110
 
265
111
  class Complete
266
- class Success < Event::Complete::Reason
267
- register :success, :input_complete
268
-
269
- ##
270
- # @return [Symbol] the mode by which the question was answered. May be :speech or :dtmf
271
- #
272
- def mode
273
- read_attr :mode, :to_sym
112
+ class Match < Event::Complete::Reason
113
+ register :match, :input_complete
114
+
115
+ attribute :content_type, String, default: 'application/nlsml+xml'
116
+
117
+ attribute :nlsml
118
+ def nlsml=(other)
119
+ doc = case other
120
+ when Nokogiri::XML::Element, Nokogiri::XML::Document
121
+ RubySpeech::NLSML::Document.new(other)
122
+ else
123
+ other
124
+ end
125
+ super doc
274
126
  end
275
127
 
276
- def mode=(other)
277
- write_attr :mode, other
128
+ def mode
129
+ nlsml.best_interpretation[:input][:mode]
278
130
  end
279
131
 
280
- ##
281
- # @return [Float] A measure of the confidence of the result, between 0-1
282
- #
283
132
  def confidence
284
- read_attr :confidence, :to_f
133
+ nlsml.best_interpretation[:confidence]
285
134
  end
286
135
 
287
- def confidence=(other)
288
- write_attr :confidence, other
289
- end
290
-
291
- ##
292
- # @return [String] An intelligent interpretation of the meaning of the response.
293
- #
294
- def interpretation
295
- interpretation_node.text
296
- end
297
-
298
- def interpretation=(other)
299
- interpretation_node.content = other
300
- end
301
-
302
- ##
303
- # @return [String] The exact response gained
304
- #
305
136
  def utterance
306
- utterance_node.text
137
+ nlsml.best_interpretation[:input][:content]
307
138
  end
308
139
 
309
- def utterance=(other)
310
- utterance_node.content = other
140
+ def interpretation
141
+ nlsml.best_interpretation[:instance]
311
142
  end
312
143
 
313
- def inspect_attributes # :nodoc:
314
- [:mode, :confidence, :interpretation, :utterance] + super
144
+ def inherit(xml_node)
145
+ self.nlsml = result_node(xml_node)
146
+ super
315
147
  end
316
148
 
317
149
  private
318
150
 
319
- def interpretation_node
320
- child_node_with_name 'interpretation'
321
- end
322
-
323
- def utterance_node
324
- child_node_with_name 'utterance'
325
- end
326
-
327
- def child_node_with_name(name)
328
- node = find_first "ns:#{name}", :ns => self.class.registered_ns
329
-
330
- unless node
331
- self << (node = RayoNode.new(name, self.document))
332
- node.namespace = self.class.registered_ns
333
- end
334
- node
151
+ def result_node(xml)
152
+ directly_nested = xml.at_xpath 'ns:result', ns: NLSML_NAMESPACE
153
+ return directly_nested if directly_nested
154
+ document = Nokogiri::XML.parse xml.text, nil, nil, Nokogiri::XML::ParseOptions::NOBLANKS
155
+ document.at_xpath 'ns:result', ns: NLSML_NAMESPACE or raise "Couldn't find the NLSML node"
335
156
  end
336
157
  end
337
158
 
@@ -342,7 +163,7 @@ module Punchblock
342
163
  class NoInput < Event::Complete::Reason
343
164
  register :noinput, :input_complete
344
165
  end
345
- end # Complete
346
- end # Input
347
- end # Component
348
- end # Punchblock
166
+ end
167
+ end
168
+ end
169
+ end