Class: FunWith::Files::Watcher

Inherits:
Object
  • Object
show all
Defined in:
lib/fun_with/files/watcher.rb

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(paths) ⇒ Watcher

Returns a new instance of Watcher.



73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/fun_with/files/watcher.rb', line 73

def initialize( paths )
  @sleep_interval = 1.0
  @notice_filters = []
  @ignore_filters = []
  
  # Create a watcher for every single thing that we're
  # asking it to watch
  @watchers = paths.inject({}) do |watchers, path|
    watchers[path.fwf_filepath] = self.class.factory( path )
    watchers
  end
end

Class Method Details

.factory(path) ⇒ Object



59
60
61
62
63
64
65
66
67
68
69
70
71
# File 'lib/fun_with/files/watcher.rb', line 59

def self.factory( path )
  path = path.fwf_filepath
  
  if path.exist?
    if path.directory?
      Watchers::DirectoryWatcher.new( path )
    elsif path.file?
      Watchers::FileWatcher.new( path )
    end
  else
    Watchers::MissingWatcher.new( path )
  end
end

.watch(*paths, interval: 1.0, notice: [], ignore: [], &block) ⇒ Object



49
50
51
52
53
54
55
56
57
# File 'lib/fun_with/files/watcher.rb', line 49

def self.watch( *paths, interval: 1.0, notice: [], ignore: [], &block )
  watcher = self.new( paths ).sleep_interval( interval ).filter( notice: notice, ignore: ignore )
  
  if block_given?
    watcher.watch( &block )
  else
    watcher
  end
end

Instance Method Details

#apply_filters(changes) ⇒ Object



133
134
135
136
137
# File 'lib/fun_with/files/watcher.rb', line 133

def apply_filters( changes )
  apply_notice_filters( changes )
  apply_ignore_filters( changes )
  changes
end

#apply_ignore_filters(changes) ⇒ Object



147
148
149
150
151
152
153
# File 'lib/fun_with/files/watcher.rb', line 147

def apply_ignore_filters( changes )
  for filter in @ignore_filters
    for path in changes.keys
      changes.delete( path ) if path =~ filter
    end
  end
end

#apply_notice_filters(changes) ⇒ Object



139
140
141
142
143
144
145
# File 'lib/fun_with/files/watcher.rb', line 139

def apply_notice_filters( changes )
  for filter in @notice_filters
    for path in changes.keys
      changes.delete( path ) if path !~ filter
    end
  end
end

#filter(notice: [], ignore: []) ⇒ Object



98
99
100
101
102
103
# File 'lib/fun_with/files/watcher.rb', line 98

def filter( notice: [], ignore: [] )
  @notice_filters += [notice].flatten
  @ignore_filters += [ignore].flatten
  
  self
end

#replace_watcher(path, change) ⇒ Object



123
124
125
126
127
128
129
130
# File 'lib/fun_with/files/watcher.rb', line 123

def replace_watcher( path, change )
  case change
  when nil
    # didn't change
  when :deleted, :created
    @watchers[path] = self.class.factory( path )
  end
end

#sleep_interval(i) ⇒ Object



86
87
88
89
# File 'lib/fun_with/files/watcher.rb', line 86

def sleep_interval( i )
  @sleep_interval = i
  self
end

#updateObject

returns a hash of the changes that have happened in the file system being monitored,



106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
# File 'lib/fun_with/files/watcher.rb', line 106

def update
  {}.tap do |changes|
    for path, watcher in @watchers
      changes.merge!( watcher.update )
      replace_watcher( path, changes[path] )  # a DirectoryWatcher might need to be replaced with a MissingWatcher, for example, or vice-versa
      
      # corner case: if a directory is created, everything created under the directory
      # is deemed to have also been created at the same time
      if path.directory? && changes[path] == :created
        changes.merge!( path.glob(:all).inject({}){ |memo,path| memo[path] = :created ; memo } )
      end
    end
    
    apply_filters( changes )
  end
end

#watch(&block) ⇒ Object



91
92
93
94
95
96
# File 'lib/fun_with/files/watcher.rb', line 91

def watch( &block )
  while true
    sleep( @sleep_interval )
    yield self.update
  end
end