Files

Guard

Guard is the main module for all Guard related modules and classes. Also Guard plugins should use this namespace.


Module for notifying test result to terminal title

Constants

DEV_NULL
GUARDFILE_TEMPLATE

The Guardfile template for `guard init`

HOME_TEMPLATES

The location of user defined templates

NO_VENDOR_DEPRECATION

Deprecation message for the `no_vendor` start option

VERSION

The current gem version of Guard

WATCH_ALL_MODIFICATIONS_DEPRECATION

Deprecation message for the `watch_all_modifications` start option

WINDOWS

Attributes

interactor[RW]
listener[RW]
lock[RW]
options[RW]
runner[RW]
running[RW]
scope[RW]

Public Class Methods

add_group(name, options = {}) click to toggle source

Add a Guard plugin group.

@param [String] name the group name @option options [Boolean] halt_on_fail if a task execution

should be halted for all Guard plugins in this group if one Guard throws `:task_has_failed`

@return [Guard::Group] the group added (or retrieved from the `@groups` variable if already present)

# File lib/guard.rb, line 367
def add_group(name, options = {})
  group = groups(name)
  if group.nil?
    group = ::Guard::Group.new(name, options)
    @groups << group
  end
  group
end
add_guard(name, watchers = [], callbacks = [], options = {}) click to toggle source

Add a Guard plugin to use.

@param [String] name the Guard name @param [Array<Watcher>] watchers the list of declared watchers @param [Array<Hash>] callbacks the list of callbacks @param [Hash] options the plugin options (see the given Guard documentation) @return [Guard::Guard] the added Guard plugin

# File lib/guard.rb, line 348
def add_guard(name, watchers = [], callbacks = [], options = {})
  if name.to_sym == :ego
    ::Guard::UI.deprecation('Guard::Ego is now part of Guard. You can remove it from your Guardfile.')
  else
    guard_class = get_guard_class(name)
    callbacks.each { |callback| Hook.add_callback(callback[:listener], guard_class, callback[:events]) }
    guard = guard_class.new(watchers, options)
    @guards << guard
    guard
  end
end
convert_scopes(scopes) click to toggle source

Convert the old scope format to the new scope format.

@example Convert old scopes

convert_scopes({ :guard => :rspec, :group => :backend })
=> { :plugins => [:rspec], :groups => [:backend] }
# File lib/guard.rb, line 514
def convert_scopes(scopes)
  if plugin = scopes.delete(:guard)
    scopes[:plugins] = [plugin]
  end

  if group = scopes.delete(:group)
    scopes[:groups] = [group]
  end

  scopes
end
debug_command_execution() click to toggle source

Adds a command logger in debug mode. This wraps common command execution functions and logs the executed command before execution.

# File lib/guard.rb, line 473
def debug_command_execution
  Kernel.send(:alias_method, :original_system, :system)
  Kernel.send(:define_method, :system) do |command, *args|
    ::Guard::UI.debug "Command execution: #{ command } #{ args.join(' ') }"
    original_system command, *args
  end

  Kernel.send(:alias_method, :original_backtick, :'`')
  Kernel.send(:define_method, :'`') do |command|
    ::Guard::UI.debug "Command execution: #{ command }"
    original_backtick command
  end
end
deprecated_options_warning() click to toggle source

Displays a warning for each deprecated options used.

# File lib/guard.rb, line 503
def deprecated_options_warning
  ::Guard::UI.deprecation(WATCH_ALL_MODIFICATIONS_DEPRECATION) if options[:watch_all_modifications]
  ::Guard::UI.deprecation(NO_VENDOR_DEPRECATION) if options[:no_vendor]
end
get_guard_class(name, fail_gracefully=false) click to toggle source

Tries to load the Guard plugin main class. This transforms the supplied Guard plugin name into a class name:

  • `guardname` will become `Guard::Guardname`

  • `dashed-guard-name` will become `Guard::DashedGuardName`

  • `underscore_guard_name` will become `Guard::UnderscoreGuardName`

When no class is found with the strict case sensitive rules, another try is made to locate the class without matching case:

  • `rspec` will find a class `Guard::RSpec`

@param [String] name the name of the Guard @param [Boolean] fail_gracefully whether error messages should not be printed @return [Class, nil] the loaded class

# File lib/guard.rb, line 414
def get_guard_class(name, fail_gracefully=false)
  name        = name.to_s
  try_require = false
  const_name  = name.gsub(/\/(.?)/) { "::#{ $1.upcase }" }.gsub(/(?:^|[_-])(.)/) { $1.upcase }
  begin
    require "guard/#{ name.downcase }" if try_require
    self.const_get(self.constants.find { |c| c.to_s == const_name } || self.constants.find { |c| c.to_s.downcase == const_name.downcase })
  rescue TypeError
    if try_require
      ::Guard::UI.error "Could not find class Guard::#{ const_name.capitalize }"
    else
      try_require = true
      retry
    end
  rescue LoadError => loadError
    unless fail_gracefully
      ::Guard::UI.error "Could not load 'guard/#{ name.downcase }' or find class Guard::#{ const_name.capitalize }"
      ::Guard::UI.error loadError.to_s
    end
  end
end
groups(filter = nil) click to toggle source

Smart accessor for retrieving a specific plugin group or several plugin groups at once.

@see Guard.guards

@example Filter groups by String or Symbol

Guard.groups('backend')
Guard.groups(:backend)

@example Filter groups by Regexp

Guard.groups(/(back|front)end/)

@param [String, Symbol, Regexp] filter the filter to apply to the Groups @return [Array<Group>] the filtered groups

# File lib/guard.rb, line 329
def groups(filter = nil)
  case filter
  when String, Symbol
    @groups.find { |group| group.name == filter.to_sym }
  when Regexp
    @groups.find_all { |group| group.name.to_s =~ filter }
  else
    @groups
  end
end
guard_gem_names() click to toggle source

Returns a list of Guard plugin Gem names installed locally.

@return [Array<String>] a list of Guard plugin gem names

# File lib/guard.rb, line 455
def guard_gem_names
  if Gem::Version.create(Gem::VERSION) >= Gem::Version.create('1.8.0')
    Gem::Specification.find_all.select do |x|
      if x.name =~ /^guard-/
        true
      elsif x.name != 'guard'
        guard_plugin_path = File.join(x.full_gem_path, "lib/guard/#{ x.name }.rb")
        File.exists?( guard_plugin_path )
      end
    end
  else
    Gem.source_index.find_name(/^guard-/)
  end.map { |x| x.name.sub(/^guard-/, '') }
end
guards(filter = nil) click to toggle source

Smart accessor for retrieving a specific Guard plugin or several Guard plugins at once.

@see Guard.groups

@example Filter Guard plugins by String or Symbol

Guard.guards('rspec')
Guard.guards(:rspec)

@example Filter Guard plugins by Regexp

Guard.guards(/rsp.+/)

@example Filter Guard plugins by Hash

Guard.guards({ :name => 'rspec', :group => 'backend' })

@param [String, Symbol, Regexp, Hash] filter the filter to apply to the Guard plugins @return [Array<Guard>] the filtered Guard plugins

# File lib/guard.rb, line 294
def guards(filter = nil)
  @guards ||= []

  case filter
  when String, Symbol
    @guards.find { |guard| guard.class.to_s.downcase.sub('guard::', '') == filter.to_s.downcase.gsub('-', '') }
  when Regexp
    @guards.find_all { |guard| guard.class.to_s.downcase.sub('guard::', '') =~ filter }
  when Hash
    filter.inject(@guards) do |matches, (k, v)|
      if k.to_sym == :name
        matches.find_all { |guard| guard.class.to_s.downcase.sub('guard::', '') == v.to_s.downcase.gsub('-', '') }
      else
        matches.find_all { |guard| guard.send(k).to_sym == v.to_sym }
      end
    end
  else
    @guards
  end
end
locate_guard(name) click to toggle source

Locate a path to a Guard plugin gem.

@param [String] name the name of the Guard plugin without the prefix `guard-` @return [String] the full path to the Guard gem

# File lib/guard.rb, line 441
def locate_guard(name)
  if Gem::Version.create(Gem::VERSION) >= Gem::Version.create('1.8.0')
    Gem::Specification.find_by_name("guard-#{ name }").full_gem_path
  else
    Gem.source_index.find_name("guard-#{ name }").last.full_gem_path
  end
rescue
  ::Guard::UI.error "Could not find 'guard-#{ name }' gem path."
end
pause() click to toggle source

Pause Guard listening to file changes.

# File lib/guard.rb, line 267
def pause
  if listener.paused?
    ::Guard::UI.info 'Un-paused files modification listening', :reset => true
    listener.unpause
  else
    ::Guard::UI.info 'Paused files modification listening', :reset => true
    listener.pause
  end
end
quit?() click to toggle source

Determine if Guard needs to quit. This checks for Ctrl-D pressed.

@return [Boolean] whether to quit or not

# File lib/guard.rb, line 531
def quit?
  STDIN.read_nonblock(1)
  false
rescue Errno::EINTR
  false
rescue Errno::EAGAIN
  false
rescue EOFError
  true
end
reload(scopes = {}) click to toggle source

Reload Guardfile and all Guard plugins currently enabled. If no scope is given, then the Guardfile will be re-evaluated, which results in a stop/start, which makes the reload obsolete.

@param [Hash] scopes hash with a Guard plugin or a group scope

# File lib/guard.rb, line 236
def reload(scopes = {})
  scopes = convert_scopes(scopes)

  within_preserved_state do
    ::Guard::UI.clear(:force => true)
    ::Guard::UI.action_with_scopes('Reload', scopes)

    if scopes.empty?
      ::Guard::Dsl.reevaluate_guardfile
    else
      runner.run(:reload, scopes)
    end
  end
end
run_all(scopes = {}) click to toggle source

Trigger `run_all` on all Guard plugins currently enabled.

@param [Hash] scopes hash with a Guard plugin or a group scope

# File lib/guard.rb, line 255
def run_all(scopes = {})
  scopes = convert_scopes(scopes)

  within_preserved_state do
    ::Guard::UI.clear(:force => true)
    ::Guard::UI.action_with_scopes('Run', scopes)
    runner.run(:run_all, scopes)
  end
end
setup(options = {}) click to toggle source

Initialize the Guard singleton:

  • Initialize the internal Guard state.

  • Create the interactor when necessary for user interaction.

  • Select and initialize the file change listener.

@option options [Boolean] clear if auto clear the UI should be done @option options [Boolean] notify if system notifications should be shown @option options [Boolean] debug if debug output should be shown @option options [Array<String>] group the list of groups to start @option options [Array<String>] watchdir the directories to watch @option options [String] guardfile the path to the Guardfile @deprecated @option options [Boolean] watch_all_modifications watches all file modifications if true @deprecated @option options [Boolean] no_vendor ignore vendored dependencies

# File lib/guard.rb, line 46
def setup(options = {})
  @running   = true
  @lock      = Mutex.new
  @options   = options.dup
  @runner    = ::Guard::Runner.new
  @scope     = { :plugins => [], :groups => [] }

  @watchdirs = [Dir.pwd]

  if options[:watchdir]
    # Ensure we have an array
    @watchdirs = Array(options[:watchdir]).map { |dir| File.expand_path dir }
  end

  ::Guard::UI.clear(:force => true)
  setup_debug
  deprecated_options_warning

  setup_groups
  setup_guards
  setup_listener
  setup_signal_traps
  setup_from_guardfile
  setup_scopes

  runner.deprecation_warning if options[:show_deprecations]

  setup_notifier
  setup_interactor

  self
end
setup_debug() click to toggle source
# File lib/guard.rb, line 79
def setup_debug
  if options[:debug]
    Thread.abort_on_exception = true
    ::Guard::UI.options[:level] = :debug
    debug_command_execution
  end
end
setup_from_guardfile() click to toggle source
# File lib/guard.rb, line 165
def setup_from_guardfile
  ::Guard::Dsl.evaluate_guardfile(options)
  ::Guard::UI.error 'No guards found in Guardfile, please add at least one.' if @guards.empty?
end
setup_groups() click to toggle source

Initialize the groups array with the `:default` group.

@see Guard.groups

# File lib/guard.rb, line 91
def setup_groups
  @groups = [Group.new(:default)]
end
setup_guards() click to toggle source

Initialize the guards array to an empty array.

@see Guard.guards

# File lib/guard.rb, line 99
def setup_guards
  @guards = []
end
setup_interactor() click to toggle source

Initializes the interactor unless the user has specified not to.

# File lib/guard.rb, line 183
def setup_interactor
  unless options[:no_interactions] || !::Guard::Interactor.enabled
    @interactor = ::Guard::Interactor.new
  end
end
setup_listener() click to toggle source

Initializes the listener and registers a callback for changes.

# File lib/guard.rb, line 105
def setup_listener
  listener_callback = lambda do |modified, added, removed|

    # Convert to relative paths (respective to the watchdir it came from)
    @watchdirs.each do |watchdir|
      [modified, added, removed].each do |paths|
        paths.map! do |path|
          if path.start_with? watchdir
            path.sub "#{watchdir}#{File::SEPARATOR}", ''
          else
            path
          end
        end
      end
    end
    ::Guard::Dsl.reevaluate_guardfile if ::Guard::Watcher.match_guardfile?(modified)

    ::Guard.within_preserved_state do
      runner.run_on_changes(modified, added, removed)
    end
  end

  listener_options = {}
  ]latency force_polling].each do |option|
    listener_options[option.to_sym] = options[option] if options.key?(option)
  end

  listen_args = @watchdirs + [listener_options]
  @listener = Listen.to(*listen_args).change(&listener_callback)
end
setup_notifier() click to toggle source

Enables or disables the notifier based on user's configurations.

# File lib/guard.rb, line 177
def setup_notifier
  options[:notify] && ENV['GUARD_NOTIFY'] != 'false' ? ::Guard::Notifier.turn_on : ::Guard::Notifier.turn_off
end
setup_scopes() click to toggle source
# File lib/guard.rb, line 170
def setup_scopes
  scope[:groups]  = options[:group].map { |g| ::Guard.groups(g) } if options[:group]
  scope[:plugins] = options[:plugin].map { |p| ::Guard.guards(p) } if options[:plugin]
end
setup_signal_traps() click to toggle source

Sets up traps to catch signals used to control Guard.

Currently two signals are caught:

  • `USR1` which pauses listening to changes.

  • `USR2` which resumes listening to changes.

  • 'INT' which is delegated to Pry if active, otherwise stops Guard.

# File lib/guard.rb, line 143
def setup_signal_traps
  unless defined?(JRUBY_VERSION)
    if Signal.list.keys.include?('USR1')
      Signal.trap('USR1') { ::Guard.pause unless listener.paused? }
    end

    if Signal.list.keys.include?('USR2')
      Signal.trap('USR2') { ::Guard.pause if listener.paused? }
    end

    if Signal.list.keys.include?('INT')
      Signal.trap('INT') do
        if interactor
          interactor.thread.raise(Interrupt)
        else
          ::Guard.stop
        end
      end
    end
  end
end
start(options = {}) click to toggle source

Start Guard by evaluating the `Guardfile`, initializing declared Guard plugins and starting the available file change listener. Main method for Guard that is called from the CLI when Guard starts.

  • Setup Guard internals

  • Evaluate the `Guardfile`

  • Configure Notifiers

  • Initialize the declared Guard plugins

  • Start the available file change listener

@option options [Boolean] clear if auto clear the UI should be done @option options [Boolean] notify if system notifications should be shown @option options [Boolean] debug if debug output should be shown @option options [Array<String>] group the list of groups to start @option options [String] watchdir the director to watch @option options [String] guardfile the path to the Guardfile

# File lib/guard.rb, line 206
def start(options = {})
  setup(options)

  within_preserved_state do
    ::Guard::UI.debug 'Guard starts all plugins'
    runner.run(:start)
    ::Guard::UI.info "Guard is now watching at '#{ @watchdirs.join "', '" }'"
    listener.start
  end
end
stop() click to toggle source

Stop Guard listening to file changes

# File lib/guard.rb, line 219
def stop
  within_preserved_state(false) do
    ::Guard::UI.debug 'Guard stops all plugins'
    runner.run(:stop)
    ::Guard::Notifier.turn_off
    ::Guard::UI.info 'Bye bye...', :reset => true
    listener.stop
    @running = false
  end
end
within_preserved_state(restart_interactor = true) click to toggle source

Runs a block where the interactor is blocked and execution is synchronized to avoid state inconsistency.

@param [Boolean] restart_interactor whether to restart the interactor or not @yield the block to run

# File lib/guard.rb, line 383
def within_preserved_state(restart_interactor = true)
  lock.synchronize do
    begin
      interactor.stop if interactor
      @result = yield
    rescue Interrupt
      # Bring back Pry when the block is halted with Ctrl-C
    end

    interactor.start if interactor && restart_interactor
  end

  @result
end

[Validate]

Generated with the Darkfish Rdoc Generator 2.