def watch(path, *flags, &callback)
      return Watcher.new(self, path, *flags, &callback) unless flags.include?(:recursive)

      dir = Dir.new(path)

      dir.each do |base|
        d = File.join(path, base)
        binary_d = d.respond_to?(:force_encoding) ? d.dup.force_encoding('BINARY') : d
        next if binary_d =~ /\/\.\.?$/ # Current or parent directory
        next if RECURSIVE_BLACKLIST.include?(d)
        next if flags.include?(:dont_follow) && File.symlink?(d)
        next if !File.directory?(d)

        watch(d, *flags, &callback)
      end

      dir.close

      rec_flags = [:create, :moved_to]
      return watch(path, *((flags - [:recursive]) | rec_flags)) do |event|
        callback.call(event) if flags.include?(:all_events) || !(flags & event.flags).empty?
        next if (rec_flags & event.flags).empty? || !event.flags.include?(:isdir)
        begin
          watch(event.absolute_name, *flags, &callback)
        rescue Errno::ENOENT
          # If the file has been deleted since the glob was run, we don't want to error out.
        end
      end
    end
def watch(path, *flags, &callback)
      return Watcher.new(self, path, *flags, &callback) unless flags.include?(:recursive)

      dir = Dir.new(path)

      dir.each do |base|
        d = File.join(path, base)
        binary_d = d.respond_to?(:force_encoding) ? d.dup.force_encoding('BINARY') : d
        next if binary_d =~ /\/\.\.?$/ # Current or parent directory
        next if RECURSIVE_BLACKLIST.include?(d)
        next if flags.include?(:dont_follow) && File.symlink?(d)
        next if !File.directory?(d)

        watch(d, *flags, &callback)
      end

      dir.close

      rec_flags = [:create, :moved_to]
      return watch(path, *((flags - [:recursive]) | rec_flags)) do |event|
        callback.call(event) if flags.include?(:all_events) || !(flags & event.flags).empty?
        next if (rec_flags & event.flags).empty? || !event.flags.include?(:isdir)
        begin
          watch(event.absolute_name, *flags, &callback)
        rescue Errno::ENOENT
          # If the file has been deleted since the glob was run, we don't want to error out.
        end
      end
    end
Watches a file or directory for changes,
 calling the callback when there are.
 This is only activated once \{#process} or \{#run} is called.

 **Note that by default, this does not recursively watch subdirectories
 of the watched directory**.
 To do so, use the `:recursive` flag.

 ## Flags

 `:access`
 : A file is accessed (that is, read).

 `:attrib`
 : A file's metadata is changed (e.g. permissions, timestamps, etc).

 `:close_write`
 : A file that was opened for writing is closed.

 `:close_nowrite`
 : A file that was not opened for writing is closed.

 `:modify`
 : A file is modified.

 `:open`
 : A file is opened.

 ### Directory-Specific Flags

 These flags only apply when a directory is being watched.

 `:moved_from`
 : A file is moved out of the watched directory.

 `:moved_to`
 : A file is moved into the watched directory.

 `:create`
 : A file is created in the watched directory.

 `:delete`
 : A file is deleted in the watched directory.

 `:delete_self`
 : The watched file or directory itself is deleted.

 `:move_self`
 : The watched file or directory itself is moved.

 ### Helper Flags

 These flags are just combinations of the flags above.

 `:close`
 : Either `:close_write` or `:close_nowrite` is activated.

 `:move`
 : Either `:moved_from` or `:moved_to` is activated.

 `:all_events`
 : Any event above is activated.

 ### Options Flags

 These flags don't actually specify events.
 Instead, they specify options for the watcher.

 `:onlydir`
 : Only watch the path if it's a directory.

 `:dont_follow`
 : Don't follow symlinks.

 `:mask_add`
 : Add these flags to the pre-existing flags for this path.

 `:oneshot`
 : Only send the event once, then shut down the watcher.

 `:recursive`
 : Recursively watch any subdirectories that are created.
   Note that this is a feature of rb-inotify,
   rather than of inotify itself, which can only watch one level of a directory.
   This means that the {Event#name} field
   will contain only the basename of the modified file.
   When using `:recursive`, {Event#absolute_name} should always be used.

 @param path [String] The path to the file or directory
 @param flags [Array<Symbol>] Which events to watch for
 @yield [event] A block that will be called
   whenever one of the specified events occur
 @yieldparam event [Event] The Event object containing information
   about the event that occured
 @return [Watcher] A Watcher set up to watch this path for these events
 @raise [SystemCallError] if the file or directory can't be watched,
   e.g. if the file isn't found, read access is denied,
   or the flags don't contain any events