lib/ionian/extension/io.rb in ionian-0.6.0 vs lib/ionian/extension/io.rb in ionian-0.6.1
- old
+ new
@@ -74,19 +74,26 @@
# buffer for the next #read_match cycle. This is helpful for protocols
# like RS232 that do not have packet boundries.
#
# kwargs:
# timeout: Timeout in seconds IO::select will block.
+ # expression: Override the expression match for this single
+ # method call.
+ # notify: Set to false to skip notifying match listener procs.
# skip_select: Skip over the IO::select statement. Use if you
# are calling IO::select ahead of this method.
# build_methods: Build accessor methods from named capture groups.
# Enabled by default.
def read_match(**kwargs, &block)
- timeout = kwargs.fetch :timeout, @ionian_timeout
- skip_select = kwargs.fetch :skip_select, @ionian_skip_select
- build_methods = kwargs.fetch :build_methods, @ionian_build_methods
+ timeout = kwargs.fetch :timeout, @ionian_timeout
+ notify = kwargs.fetch :notify, true
+ skip_select = kwargs.fetch :skip_select, @ionian_skip_select
+ build_methods = kwargs.fetch :build_methods, @ionian_build_methods
+ exp = kwargs.fetch :expression, @ionian_expression
+ exp = Regexp.new "(.*?)#{exp}" if exp.is_a? String
+
unless skip_select
return nil unless ::IO.select [self], nil, nil, timeout
end
# Read data from the IO buffer until it's empty.
@@ -95,11 +102,11 @@
break unless ::IO.select [self], nil, nil, 0
end
@matches = []
- while @ionian_buf =~ @ionian_expression
+ while @ionian_buf =~ exp
@matches << $~ # Match data.
yield $~ if block_given?
@ionian_buf = $' # Leave post match data in the buffer.
end
@@ -113,24 +120,25 @@
unless match.respond_to? symbol
}
end
end
+ # Notify on_match listeners.
+ @matches.each {|match| notify_listeners match} if notify
+
@matches
end
# Start a thread that checks for data and notifies listeners (do |match, socket|).
# Passes kwargs to #read_match.
# This method SHOULD NOT be used if #read_match is used.
def run_match(**kwargs)
@match_listener ||= Thread.new do
begin
while not closed? do
- matches = read_match kwargs
- matches.each {|match|
- @ionian_listeners.each {|listener| listener.call match, self}
- } if matches
+ matches = read_match **kwargs
+ matches.each {|match| notify_listeners match } if matches
end
rescue EOFError
rescue IOError
ensure
@match_listener = nil
@@ -162,9 +170,18 @@
# Unregister a block from being called when matched data is received.
def unregister_observer(&block)
@ionian_listeners.delete_if {|o| o == block}
block
+ end
+
+
+ private
+
+ # Send match to each of the registered observers. Includes self
+ # as the second block parameter.
+ def notify_listeners match
+ @ionian_listeners.each {|listener| listener.call match, self}
end
end
end
end
\ No newline at end of file