class Guard::Dsl

The Dsl class provides the methods that are used in each `Guardfile` to describe the behaviour of Guard.

The main keywords of the DSL are {#guard} and {#watch}. These are necessary to define the used Guard plugins and the file changes they are watching.

You can optionally group the Guard plugins with the {#group} keyword and ignore and filter certain paths with the {#ignore} and {#filter} keywords.

You can set your preferred system notification library with {#notification} and pass some optional configuration options for the library. If you don't configure a library, Guard will automatically pick one with default options (if you don't want notifications, specify `:off` as library). Please see {Notifier} for more information about the supported libraries.

A more advanced DSL use is the {#callback} keyword that allows you to execute arbitrary code before or after any of the {Plugin#start}, {Plugin#stop}, {Plugin#reload}, {Plugin#run_all}, {Plugin#run_on_changes}, {Plugin#run_on_additions}, {Plugin#run_on_modifications} and {Plugin#run_on_removals} Guard plugins method. You can even insert more hooks inside these methods. Please [checkout the Wiki page](github.com/guard/guard/wiki/Hooks-and-callbacks) for more details.

The DSL will also evaluate normal Ruby code.

There are two possible locations for the `Guardfile`:

In addition, if a user configuration `.guard.rb` in your home directory is found, it will be appended to the current project `Guardfile`.

@see github.com/guard/guard/wiki/Guardfile-examples

Constants

WARN_INVALID_LOG_LEVEL
WARN_INVALID_LOG_OPTIONS

Public Instance Methods

callback(*args, &block) click to toggle source

Defines a callback to execute arbitrary code before or after any of the `start`, `stop`, `reload`, `run_all`, `run_on_changes`, `run_on_additions`, `run_on_modifications` and `run_on_removals` plugin method.

@example Add callback before the `reload` action.

callback(:reload_begin) { puts "Let's reload!" }

@example Add callback before the `start` and `stop` actions.

my_lambda = lambda do |plugin, event, *args|
  puts "Let's #{event} #{plugin} with #{args}!"
end

callback(my_lambda, [:start_begin, :start_end])

@param [Array] args the callback arguments @yield a callback block

# File lib/guard/dsl.rb, line 245
def callback(*args, &block)
  @plugin_options ||= nil
  fail "callback must be called within a guard block" unless @plugin_options

  block, events = if args.size > 1
                    # block must be the first argument in that case, the
                    # yielded block is ignored
                    args
                  else
                    [block, args[0]]
                  end
  @plugin_options[:callbacks] << { events: events, listener: block }
end
clearing(on) click to toggle source

Sets Guard to clear the screen before every task is run

@example switching clearing the screen on

clearing(:on)

@param [Symbol] on ':on' to turn on, ':off' (default) to turn off

# File lib/guard/dsl.rb, line 407
def clearing(on)
  Guard.state.session.clearing(on == :on)
end
directories(directories) click to toggle source

Sets the directories to pass to Listen

@example watch only given directories

directories %w(lib specs)

@param [Array] directories directories for Listen to watch

# File lib/guard/dsl.rb, line 393
def directories(directories)
  directories.each do |dir|
    fail "Directory #{dir.inspect} does not exist!" unless Dir.exist?(dir)
  end
  Guard.state.session.watchdirs = directories
end
evaluate(contents, filename, lineno) click to toggle source
# File lib/guard/dsl.rb, line 376
def evaluate(contents, filename, lineno) # :nodoc
  instance_eval(contents, filename.to_s, lineno)
rescue StandardError, ScriptError => e
  prefix = "\n\t(dsl)> "
  cleaned_backtrace = _cleanup_backtrace(e.backtrace)
  backtrace = "#{prefix}#{cleaned_backtrace.join(prefix)}"
  msg = "Invalid Guardfile, original error is: \n\n%s, \nbacktrace: %s"
  raise Error, format(msg, e, backtrace)
end
filter(*regexps)

TODO: deprecate

Alias for: ignore
filter!(*regexps)

TODO: deprecate

Alias for: ignore!
group(*args) { || ... } click to toggle source

Declares a group of Guard plugins to be run with `guard start –group

group_name`.

@example Declare two groups of Guard plugins

group :backend do
  guard :spork
  guard :rspec
end

group :frontend do
  guard :passenger
  guard :livereload
end

@param [Symbol, String, Array<Symbol, String>] name the group name called

from the CLI

@param [Hash] options the options accepted by the group @yield a block where you can declare several Guard plugins

@see Group @see Guard.add_group @see guard

# File lib/guard/dsl.rb, line 123
def group(*args)
  options = args.last.is_a?(Hash) ? args.pop : {}
  groups = args

  groups.each do |group|
    next unless group.to_sym == :all
    fail ArgumentError, "'all' is not an allowed group name!"
  end

  if block_given?
    groups.each do |group|
      # TODO: let groups be added *after* evaluation
      Guard.state.session.groups.add(group, options)
    end

    @current_groups ||= []
    @current_groups.push(groups)

    yield

    @current_groups.pop
  else
    UI.error \
      "No Guard plugins found in the group '#{ groups.join(', ') }',"\
      " please add at least one."
  end
end
guard(name, options = {}) { || ... } click to toggle source

Declares a Guard plugin to be used when running `guard start`.

The name parameter is usually the name of the gem without the 'guard-' prefix.

The available options are different for each Guard implementation.

@example Declare a Guard without `watch` patterns

guard :rspec

@example Declare a Guard with a `watch` pattern

guard :rspec do
  watch %r{.*_spec.rb}
end

@param [String] name the Guard plugin name @param [Hash] options the options accepted by the Guard plugin @yield a block where you can declare several watch patterns and actions

@see Plugin @see Guard.add_plugin @see watch @see group

# File lib/guard/dsl.rb, line 175
def guard(name, options = {})
  @plugin_options = options.merge(watchers: [], callbacks: [])

  yield if block_given?

  @current_groups ||= []
  groups = @current_groups && @current_groups.last || [:default]
  groups.each do |group|
    opts = @plugin_options.merge(group: group)
    # TODO: let plugins be added *after* evaluation
    Guard.state.session.plugins.add(name, opts)
  end

  @plugin_options = nil
end
ignore(*regexps) click to toggle source

Ignores certain paths globally.

@example Ignore some paths

ignore %r{^ignored/path/}, /man/

@param [Regexp] regexps a pattern (or list of patterns) for ignoring paths

# File lib/guard/dsl.rb, line 266
def ignore(*regexps)
  # TODO: use guardfile results class
  Guard.state.session.guardfile_ignore = regexps
end
Also aliased as: filter
ignore!(*regexps) click to toggle source

Replaces ignored paths globally

@example Ignore only these paths

ignore! %r{^ignored/path/}, /man/

@param [Regexp] regexps a pattern (or list of patterns) for ignoring paths

# File lib/guard/dsl.rb, line 281
def ignore!(*regexps)
  @ignore_regexps ||= []
  @ignore_regexps << regexps
  # TODO: use guardfile results class
  Guard.state.session.guardfile_ignore_bang = @ignore_regexps
end
Also aliased as: filter!
interactor(options) click to toggle source

Sets the interactor options or disable the interactor.

@example Pass options to the interactor

interactor option1: 'value1', option2: 'value2'

@example Turn off interactions

interactor :off

@param [Symbol, Hash] options either `:off` or a Hash with interactor

options
# File lib/guard/dsl.rb, line 90
def interactor(options)
  # TODO: remove dependency on Interactor (let session handle this)
  case options
  when :off
    Interactor.enabled = false
  when Hash
    Interactor.options = options
  end
end
logger(options) click to toggle source

Configures the Guard logger.

  • Log level must be either `:debug`, `:info`, `:warn` or `:error`.

  • Template supports the following placeholders: `:time`, `:severity`, `:progname`, `:pid`, `:unit_of_work_id` and `:message`.

  • Time format directives are the same as `Time#strftime` or `:milliseconds`.

  • The `:only` and `:except` options must be a `RegExp`.

@example Set the log level

logger level: :warn

@example Set a custom log template

logger template: '[Guard - :severity - :progname - :time] :message'

@example Set a custom time format

logger time_format: '%h'

@example Limit logging to a Guard plugin

logger only: :jasmine

@example Log all but not the messages from a specific Guard plugin

logger except: :jasmine

@param [Hash] options the log options @option options [String, Symbol] level the log level @option options [String] template the logger template @option options [String, Symbol] time_format the time format @option options [Regexp] only show only messages from the matching Guard

plugin

@option options [Regexp] except does not show messages from the matching

Guard plugin
# File lib/guard/dsl.rb, line 324
def logger(options)
  if options[:level]
    options[:level] = options[:level].to_sym

    unless [:debug, :info, :warn, :error].include? options[:level]
      UI.warning(format(WARN_INVALID_LOG_LEVEL, options[:level]))
      options.delete :level
    end
  end

  if options[:only] && options[:except]
    UI.warning WARN_INVALID_LOG_OPTIONS

    options.delete :only
    options.delete :except
  end

  # Convert the :only and :except options to a regular expression
  [:only, :except].each do |name|
    next unless options[name]

    list = [].push(options[name]).flatten.map do |plugin|
      Regexp.escape(plugin.to_s)
    end

    options[name] = Regexp.new(list.join("|"), Regexp::IGNORECASE)
  end

  UI.options = UI.options.merge(options)
end
notification(notifier, opts = {}) click to toggle source

Set notification options for the system notifications. You can set multiple notifications, which allows you to show local system notifications and remote notifications with separate libraries. You can also pass `:off` as library to turn off notifications.

@example Define multiple notifications

notification :ruby_gntp
notification :ruby_gntp, host: '192.168.1.5'

@param [Symbol, String] notifier the name of the notifier to use @param [Hash] options the notification library options

@see Guard::Notifier for available notifier and its options.

# File lib/guard/dsl.rb, line 75
def notification(notifier, opts = {})
  Guard.state.session.guardfile_notification = { notifier.to_sym => opts }
end
scope(scope = {}) click to toggle source

Sets the default scope on startup

@example Scope Guard to a single group

scope group: :frontend

@example Scope Guard to multiple groups

scope groups: [:specs, :docs]

@example Scope Guard to a single plugin

scope plugin: :test

@example Scope Guard to multiple plugins

scope plugins: [:jasmine, :rspec]

@param [Hash] scopes the scope for the groups and plugins

# File lib/guard/dsl.rb, line 371
def scope(scope = {})
  # TODO: use a Guardfile::Results class
  Guard.state.session.guardfile_scope(scope)
end
watch(pattern, &action) click to toggle source

Defines a pattern to be watched in order to run actions on file modification.

@example Declare watchers for a Guard

guard :rspec do
  watch('spec/spec_helper.rb')
  watch(%r{^.+_spec.rb})
  watch(%r{^app/controllers/(.+).rb}) do |m|
    'spec/acceptance/#{m[1]}s_spec.rb'
  end
end

@example Declare global watchers outside of a Guard

watch(%r{^(.+)$}) { |m| puts "#{m[1]} changed." }

@param [String, Regexp] pattern the pattern that Guard must watch for modification

@yield a block to be run when the pattern is matched @yieldparam [MatchData] m matches of the pattern @yieldreturn a directory, a filename, an array of

directories / filenames, or nothing (can be an arbitrary command)

@see Guard::Watcher @see guard

# File lib/guard/dsl.rb, line 217
def watch(pattern, &action)
  # Allow watches in the global scope (to execute arbitrary commands) by
  # building a generic Guard::Plugin.
  @plugin_options ||= nil
  return guard(:plugin) { watch(pattern, &action) } unless @plugin_options

  @plugin_options[:watchers] << Watcher.new(pattern, action)
end

Private Instance Methods

_cleanup_backtrace(backtrace) click to toggle source
# File lib/guard/dsl.rb, line 413
def _cleanup_backtrace(backtrace)
  dirs = { File.realpath(Dir.pwd) => ".", }

  gem_env = ENV["GEM_HOME"] || ""
  dirs[gem_env] = "$GEM_HOME" unless gem_env.empty?

  gem_paths = (ENV["GEM_PATH"] || "").split(File::PATH_SEPARATOR)
  gem_paths.each_with_index do |path, index|
    dirs[path] = "$GEM_PATH[#{index}]"
  end

  backtrace.dup.map do |raw_line|
    path = nil
    symlinked_path = raw_line.split(":").first
    begin
      path = raw_line.sub(symlinked_path, File.realpath(symlinked_path))
      dirs.detect { |dir, name| path.sub!(File.realpath(dir), name) }
      path
    rescue Errno::ENOENT
      path || symlinked_path
    end
  end
end