Class: Listen::Listener

Inherits:
Object
  • Object
show all
Defined in:
lib/listen/listener.rb

Constant Summary collapse

RELATIVE_PATHS_WITH_MULTIPLE_DIRECTORIES_WARNING_MESSAGE =
"The relative_paths option doesn't work when listening to multiple diretories."

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(*args) {|modified, added, removed| ... } ⇒ Listener

Initializes the directories listener.

Parameters:

  • directory (String)

    the directories to listen to

  • options (Hash)

    the listen options (see Listen::Listener::Options)

Yields:

  • (modified, added, removed)

    the changed files

Yield Parameters:

  • modified (Array<String>)

    the list of modified files

  • added (Array<String>)

    the list of added files

  • removed (Array<String>)

    the list of removed files



24
25
26
27
28
29
30
31
32
# File 'lib/listen/listener.rb', line 24

def initialize(*args, &block)
  @options     = _init_options(args.last.is_a?(Hash) ? args.pop : {})
  @directories = args.flatten.map { |path| Pathname.new(path).realpath }
  @changes     = []
  @block       = block
  @registry    = Celluloid::Registry.new
  @supervisor  = Celluloid::SupervisionGroup.run!(@registry)
  _init_debug
end

Instance Attribute Details

#blockObject

Returns the value of attribute block.



9
10
11
# File 'lib/listen/listener.rb', line 9

def block
  @block
end

#changesObject

Returns the value of attribute changes.



9
10
11
# File 'lib/listen/listener.rb', line 9

def changes
  @changes
end

#directoriesObject

Returns the value of attribute directories.



9
10
11
# File 'lib/listen/listener.rb', line 9

def directories
  @directories
end

#optionsObject

Returns the value of attribute options.



9
10
11
# File 'lib/listen/listener.rb', line 9

def options
  @options
end

#pausedObject

Returns the value of attribute paused.



9
10
11
# File 'lib/listen/listener.rb', line 9

def paused
  @paused
end

#registryObject

Returns the value of attribute registry.



10
11
12
# File 'lib/listen/listener.rb', line 10

def registry
  @registry
end

#stoppingObject

Returns the value of attribute stopping.



9
10
11
# File 'lib/listen/listener.rb', line 9

def stopping
  @stopping
end

#supervisorObject

Returns the value of attribute supervisor.



10
11
12
# File 'lib/listen/listener.rb', line 10

def supervisor
  @supervisor
end

#threadObject

Returns the value of attribute thread.



9
10
11
# File 'lib/listen/listener.rb', line 9

def thread
  @thread
end

Instance Method Details

#_init_actorsObject (private)



129
130
131
132
133
134
135
136
# File 'lib/listen/listener.rb', line 129

def _init_actors
  supervisor.add(Silencer, as: :silencer, args: self)
  supervisor.add(Record, as: :record, args: self)
  supervisor.pool(Change, as: :change_pool, args: self)

  adapter_class = Adapter.select(options)
  supervisor.add(adapter_class, as: :adapter, args: self)
end

#_init_debugObject (private)



121
122
123
124
125
126
127
# File 'lib/listen/listener.rb', line 121

def _init_debug
  if options[:debug]
    Celluloid.logger.level = Logger::INFO
  else
    Celluloid.logger = nil
  end
end

#_init_options(options = {}) ⇒ Object (private)



113
114
115
116
117
118
119
# File 'lib/listen/listener.rb', line 113

def _init_options(options = {})
  { debug: false,
    latency: nil,
    wait_for_delay: 0.1,
    force_polling: false,
    polling_fallback_message: nil }.merge(options)
end

#_pop_changesObject (private)



162
163
164
165
166
167
168
169
# File 'lib/listen/listener.rb', line 162

def _pop_changes
  changes = { modified: [], added: [], removed: [] }
  until @changes.empty?
    change = @changes.pop
    change.each { |k, v| changes[k] << v.to_s }
  end
  changes.each { |_, v| v.uniq! }
end

#_signals_trapObject (private)



138
139
140
141
142
143
# File 'lib/listen/listener.rb', line 138

def _signals_trap
  return if defined?(JRUBY_VERSION)
  if Signal.list.keys.include?('INT')
    Signal.trap('INT') { stop }
  end
end

#_wait_for_changesObject (private)



145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
# File 'lib/listen/listener.rb', line 145

def _wait_for_changes
  loop do
    break if @stopping || Listen.stopping

    changes = _pop_changes
    unless changes.all? { |_,v| v.empty? }
      block.call(changes[:modified], changes[:added], changes[:removed])
    end
    sleep options[:wait_for_delay]
  end

  supervisor.finalize
rescue => ex
  Kernel.warn "[Listen warning]: Change block raised an exception: #{$!}"
  Kernel.warn "Backtrace:\n\t#{ex.backtrace.join("\n\t")}"
end

#ignore(regexps) ⇒ Object

Adds ignore patterns to the existing one (See DEFAULT_IGNORED_DIRECTORIES and DEFAULT_IGNORED_EXTENSIONS in Listen::Silencer)

Parameters:

  • new (Regexp, Array<Regexp>)

    ignoring patterns.



87
88
89
90
# File 'lib/listen/listener.rb', line 87

def ignore(regexps)
  @options[:ignore] = [options[:ignore], regexps]
  registry[:silencer] = Silencer.new(self)
end

#ignore!(regexps) ⇒ Object

Overwrites ignore patterns (See DEFAULT_IGNORED_DIRECTORIES and DEFAULT_IGNORED_EXTENSIONS in Listen::Silencer)

Parameters:

  • new (Regexp, Array<Regexp>)

    ignoring patterns.



96
97
98
99
100
# File 'lib/listen/listener.rb', line 96

def ignore!(regexps)
  @options.delete(:ignore)
  @options[:ignore!] = regexps
  registry[:silencer] = Silencer.new(self)
end

#listen?Boolean

Returns true if Listener is neither paused nor stopped

Returns:

  • (Boolean)


79
80
81
# File 'lib/listen/listener.rb', line 79

def listen?
  @paused == false && @stopping == false
end

#only(regexps) ⇒ Object

Sets only patterns, to listen only to specific regexps

Parameters:

  • new (Regexp, Array<Regexp>)

    ignoring patterns.



106
107
108
109
# File 'lib/listen/listener.rb', line 106

def only(regexps)
  @options[:only] = regexps
  registry[:silencer] = Silencer.new(self)
end

#pauseObject

Pauses listening callback (adapter still running)



56
57
58
# File 'lib/listen/listener.rb', line 56

def pause
  @paused = true
end

#paused?Boolean

Returns true if Listener is paused

Returns:

  • (Boolean)


71
72
73
# File 'lib/listen/listener.rb', line 71

def paused?
  @paused == true
end

#startObject

Starts the listener by initializing the adapter and building the directory record concurrently, then it starts the adapter to watch for changes. The current thread is not blocked after starting.



38
39
40
41
42
43
44
45
# File 'lib/listen/listener.rb', line 38

def start
  _signals_trap
  _init_actors
  unpause
  @stopping = false
  registry[:adapter].async.start
  @thread = Thread.new { _wait_for_changes }
end

#stopObject

Terminates all Listen actors and kill the adapter.



49
50
51
52
# File 'lib/listen/listener.rb', line 49

def stop
  @stopping = true
  thread.join
end

#unpauseObject

Unpauses listening callback



62
63
64
65
# File 'lib/listen/listener.rb', line 62

def unpause
  registry[:record].build
  @paused = false
end