module Guard

def _evaluate(options)

def _evaluate(options)
  evaluator = Guardfile::Evaluator.new(options)
  evaluator.evaluate
  UI.reset_and_clear
  msg = "No plugins found in Guardfile, please add at least one."
  UI.error msg if _pluginless_guardfile?
  if evaluator.inline?
    UI.info("Using inline Guardfile.")
  elsif evaluator.custom?
    UI.info("Using Guardfile at #{ evaluator.path }.")
  end
rescue Guardfile::Evaluator::NoPluginsError => e
  UI.error(e.message)
end

def _guardfile_deprecated_check(modified)

TODO: not tested because collides with ongoing refactoring
TODO: remove at some point
def _guardfile_deprecated_check(modified)
  modified.map!(&:to_s)
  regexp = %r{^(?:.+/)?Guardfile$}
  guardfiles = modified.select { |path| regexp.match(path) }
  return if guardfiles.empty?
  guardfile = Pathname("Guardfile").realpath
  real_guardfiles = guardfiles.detect do |path|
    /^Guardfile$/.match(path) || Pathname(path).expand_path == guardfile
  end
  return unless real_guardfiles
  UI.warning "Guardfile changed -- _guard-core will exit.\n"
  exit 2 # nonzero to break any while loop
end

def _listener_callback

def _listener_callback
  lambda do |modified, added, removed|
    relative_paths = {
      modified: _relative_pathnames(modified),
      added: _relative_pathnames(added),
      removed: _relative_pathnames(removed)
    }
    _guardfile_deprecated_check(relative_paths[:modified])
    async_queue_add(relative_paths) if _relevant_changes?(relative_paths)
  end
end

def _pluginless_guardfile?

TODO: obsoleted? (move to Dsl?)
def _pluginless_guardfile?
  state.session.plugins.all.empty?
end

def _relative_pathnames(paths)

def _relative_pathnames(paths)
  paths.map { |path| _relative_pathname(path) }
end

def _relevant_changes?(changes)

TODO: why iterate twice? reuse this info when running tasks
Check if any of the changes are actually watched for
def _relevant_changes?(changes)
  # TODO: no coverage!
  files = changes.values.flatten(1)
  scope = Guard.state.scope
  watchers = scope.grouped_plugins.map do |_group, plugins|
    plugins.map(&:watchers).flatten
  end.flatten
  watchers.any? { |watcher| files.any? { |file| watcher.match(file) } }
end

def async_queue_add(changes)

Other tags:
    Example: New style signals with args: -
    Example: Old style hash: -
def async_queue_add(changes)
  @queue << changes
  # Putting interactor in background puts guard into foreground
  # so it can handle change notifications
  Thread.new { interactor.background }
end

def init(cmdline_options)

def init(cmdline_options)
  @state = Internals::State.new(cmdline_options)
end

def setup(cmdline_options = {})

Returns:
  • (Guard) - the Guard singleton

Options Hash: (**options)
  • guardfile (String) -- the path to the Guardfile
  • watchdir (Array) -- the directories to watch
  • group (Array) -- the list of groups to start
  • debug (Boolean) -- if debug output should be shown
  • notify (Boolean) -- if system notifications should be shown
  • clear (Boolean) -- if auto clear the UI should be done
def setup(cmdline_options = {})
  init(cmdline_options)
  @queue = Internals::Queue.new(Guard)
  _evaluate(state.session.evaluator_options)
  # NOTE: this should be *after* evaluate so :directories can work
  # TODO: move listener setup to session?
  @listener = Listen.send(*state.session.listener_args, &_listener_callback)
  ignores = state.session.guardfile_ignore
  @listener.ignore(ignores) unless ignores.empty?
  ignores = state.session.guardfile_ignore_bang
  @listener.ignore!(ignores) unless ignores.empty?
  Notifier.connect(state.session.notify_options)
  traps = Internals::Traps
  traps.handle("USR1") { async_queue_add([:guard_pause, :paused]) }
  traps.handle("USR2") { async_queue_add([:guard_pause, :unpaused]) }
  @interactor = Interactor.new(state.session.interactor_name == :sleep)
  traps.handle("INT") { @interactor.handle_interrupt }
  self
end