lib/rb-fsevent/fsevent.rb in rb-fsevent-0.3.10 vs lib/rb-fsevent/fsevent.rb in rb-fsevent-0.4.0
- old
+ new
@@ -1,65 +1,102 @@
class FSEvent
- attr_reader :paths, :callback, :pipe
+ class << self
+ class_eval <<-END
+ def root_path
+ "#{File.expand_path(File.join(File.dirname(__FILE__), '..', '..'))}"
+ end
+ END
+ class_eval <<-END
+ def watcher_path
+ "#{File.join(FSEvent.root_path, 'bin', 'fsevent_watch')}"
+ end
+ END
+ end
- def watch(paths, &callback)
- @paths = paths.kind_of?(Enumerable) ? paths : [paths]
- @callback = callback
+ attr_reader :paths, :callback
+
+ 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
def run
- launch_bin
- listen
+ while !pipe.eof?
+ if line = pipe.readline
+ modified_dir_paths = line.split(":").select { |dir| dir != "\n" }
+ callback.call(modified_dir_paths)
+ end
+ end
+ rescue Interrupt, IOError
+ ensure
+ stop
end
def stop
if pipe
Process.kill("KILL", pipe.pid)
pipe.close
end
rescue IOError
+ ensure
+ @pipe = false
end
-private
+ if RUBY_VERSION < '1.9'
+ def pipe
+ @pipe ||= IO.popen("#{self.class.watcher_path} #{options_string} #{shellescaped_paths}")
+ end
- def bin_path
- File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'bin'))
- end
+ private
- def launch_bin
- @pipe = IO.popen("#{bin_path}/fsevent_watch #{shellescaped_paths}")
- end
+ def options_string
+ @options.join(' ')
+ end
- def listen
- while !pipe.eof?
- if line = pipe.readline
- modified_dir_paths = line.split(":").select { |dir| dir != "\n" }
- callback.call(modified_dir_paths)
- end
+ def shellescaped_paths
+ @paths.map {|path| shellescape(path)}.join(' ')
end
- rescue Interrupt, IOError
- stop
- end
- def shellescaped_paths
- @paths.map {|path| shellescape(path)}.join(' ')
- end
+ # for Ruby 1.8.6 support
+ def shellescape(str)
+ # An empty argument will be skipped, so return empty quotes.
+ return "''" if str.empty?
- # for Ruby 1.8.6 support
- def shellescape(str)
- # An empty argument will be skipped, so return empty quotes.
- return "''" if str.empty?
+ str = str.dup
- 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")
- # 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'")
- # 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
+ else
+ def pipe
+ @pipe ||= IO.popen([self.class.watcher_path] + @options + @paths)
+ end
+ end
- return str
+ private
+
+ def parse_options(options={})
+ opts = []
+ 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]
+ # ruby 1.9's IO.popen(array-of-stuff) syntax requires all items to be strings
+ opts.map {|opt| "#{opt}"}
end
-end
\ No newline at end of file
+end