class FSEvent
Constants
- VERSION
Attributes
callback[R]
paths[R]
Public Class Methods
new(args = nil, &block)
click to toggle source
# File lib/rb-fsevent/fsevent.rb, line 20 def initialize args = nil, &block watch(args, &block) unless args.nil? end
Public Instance Methods
open_pipe()
click to toggle source
# File lib/rb-fsevent/fsevent.rb, line 106 def open_pipe IO.popen("'#{self.class.watcher_path}' #{options_string} #{shellescaped_paths}") end
options_string()
click to toggle source
# File lib/rb-fsevent/fsevent.rb, line 112 def options_string @options.join(' ') end
process_running?(pid)
click to toggle source
# File lib/rb-fsevent/fsevent.rb, line 96 def process_running?(pid) begin Process.kill(0, pid) true rescue Errno::ESRCH false end end
run()
click to toggle source
# File lib/rb-fsevent/fsevent.rb, line 37 def run @pipe = open_pipe @running = true # please note the use of IO::select() here, as it is used specifically to # preserve correct signal handling behavior in ruby 1.8. while @running && IO::select([@pipe], nil, nil, nil) # managing the IO ourselves allows us to be careful and never pass an # incomplete message to OTNetstring.parse() message = "" length = "" byte = nil reading_length = true found_length = false while reading_length byte = @pipe.read_nonblock(1) if "#{byte}" =~ /\d/ length << byte found_length = true elsif found_length == false next else reading_length = false end end length = Integer(length, 10) type = byte message << "#{length}#{type}" message << @pipe.read(length) decoded = OTNetstring.parse(message) modified_paths = decoded["events"].map {|event| event["path"]} # passing the full info as a second block param feels icky, but such is # the trap of backward compatibility. case callback.arity when 1 callback.call(modified_paths) when 2 callback.call(modified_paths, decoded) end end rescue Interrupt, IOError, Errno::EBADF ensure stop end
shellescape(str)
click to toggle source
for Ruby 1.8.6 support
# File lib/rb-fsevent/fsevent.rb, line 121 def shellescape(str) # An empty argument will be skipped, so return empty quotes. return "''" if str.empty? str = str.dup # Process as a single byte sequence because not all shell # implementations are multibyte aware. str.gsub!(/([^A-Za-z0-9_\-.,:\/@\n])/n, "\\\\\\1") # A LF cannot be escaped with a backslash because a backslash + LF # combo is regarded as line continuation and simply ignored. str.gsub!(/\n/, "'\n'") return str end
shellescaped_paths()
click to toggle source
# File lib/rb-fsevent/fsevent.rb, line 116 def shellescaped_paths @paths.map {|path| shellescape(path)}.join(' ') end
stop()
click to toggle source
# File lib/rb-fsevent/fsevent.rb, line 86 def stop unless @pipe.nil? Process.kill('KILL', @pipe.pid) if process_running?(@pipe.pid) @pipe.close end rescue IOError ensure @running = false end
watch(watch_paths, options=nil, &block)
click to toggle source
# File lib/rb-fsevent/fsevent.rb, line 24 def watch(watch_paths, options=nil, &block) @paths = watch_paths.kind_of?(Array) ? watch_paths : [watch_paths] @callback = block if options.kind_of?(Hash) @options = parse_options(options) elsif options.kind_of?(Array) @options = options else @options = [] end end
Private Instance Methods
parse_options(options={})
click to toggle source
# File lib/rb-fsevent/fsevent.rb, line 145 def parse_options(options={}) opts = ['--format=otnetstring'] opts.concat(['--since-when', options[:since_when]]) if options[:since_when] opts.concat(['--latency', options[:latency]]) if options[:latency] opts.push('--no-defer') if options[:no_defer] opts.push('--watch-root') if options[:watch_root] opts.push('--file-events') if options[:file_events] # ruby 1.9's IO.popen(array-of-stuff) syntax requires all items to be strings opts.map {|opt| "#{opt}"} end