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