| require 'English' |
| |
| require 'listen/version' |
| |
| require 'listen/backend' |
| |
| require 'listen/silencer' |
| require 'listen/silencer/controller' |
| |
| require 'listen/queue_optimizer' |
| |
| require 'listen/fsm' |
| |
| require 'listen/event/loop' |
| require 'listen/event/queue' |
| require 'listen/event/config' |
| |
| require 'listen/listener/config' |
| |
| module Listen |
| class Listener |
| include Listen::FSM |
| |
| # Initializes the directories listener. |
| # |
| # @param [String] directory the directories to listen to |
| # @param [Hash] options the listen options (see Listen::Listener::Options) |
| # |
| # @yield [modified, added, removed] the changed files |
| # @yieldparam [Array<String>] modified the list of modified files |
| # @yieldparam [Array<String>] added the list of added files |
| # @yieldparam [Array<String>] removed the list of removed files |
| # |
| def initialize(*dirs, &block) |
| options = dirs.last.is_a?(Hash) ? dirs.pop : {} |
| |
| @config = Config.new(options) |
| |
| eq_config = Event::Queue::Config.new(@config.relative?) |
| queue = Event::Queue.new(eq_config) { @processor.wakeup_on_event } |
| |
| silencer = Silencer.new |
| rules = @config.silencer_rules |
| @silencer_controller = Silencer::Controller.new(silencer, rules) |
| |
| @backend = Backend.new(dirs, queue, silencer, @config) |
| |
| optimizer_config = QueueOptimizer::Config.new(@backend, silencer) |
| |
| pconfig = Event::Config.new( |
| self, |
| queue, |
| QueueOptimizer.new(optimizer_config), |
| @backend.min_delay_between_events, |
| &block) |
| |
| @processor = Event::Loop.new(pconfig) |
| |
| super() # FSM |
| end |
| |
| default_state :initializing |
| |
| state :initializing, to: [:backend_started, :stopped] |
| |
| state :backend_started, to: [:frontend_ready, :stopped] do |
| backend.start |
| end |
| |
| state :frontend_ready, to: [:processing_events, :stopped] do |
| processor.setup |
| end |
| |
| state :processing_events, to: [:paused, :stopped] do |
| processor.resume |
| end |
| |
| state :paused, to: [:processing_events, :stopped] do |
| processor.pause |
| end |
| |
| state :stopped, to: [:backend_started] do |
| backend.stop # should be before processor.teardown to halt events ASAP |
| processor.teardown |
| end |
| |
| # Starts processing events and starts adapters |
| # or resumes invoking callbacks if paused |
| def start |
| transition :backend_started if state == :initializing |
| transition :frontend_ready if state == :backend_started |
| transition :processing_events if state == :frontend_ready |
| transition :processing_events if state == :paused |
| end |
| |
| # Stops both listening for events and processing them |
| def stop |
| transition :stopped |
| end |
| |
| # Stops invoking callbacks (messages pile up) |
| def pause |
| transition :paused |
| end |
| |
| # processing means callbacks are called |
| def processing? |
| state == :processing_events |
| end |
| |
| def paused? |
| state == :paused |
| end |
| |
| def ignore(regexps) |
| @silencer_controller.append_ignores(regexps) |
| end |
| |
| def ignore!(regexps) |
| @silencer_controller.replace_with_bang_ignores(regexps) |
| end |
| |
| def only(regexps) |
| @silencer_controller.replace_with_only(regexps) |
| end |
| |
| private |
| |
| attr_reader :processor |
| attr_reader :backend |
| end |
| end |