Class: Guard::Dsl

Inherits:
Object
  • Object
show all
Defined in:
lib/guard/dsl.rb

Overview

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`:

  • The `Guardfile` or `guardfile.rb` in the current directory where Guard has been started

  • The `.Guardfile` in your home directory.

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

Direct Known Subclasses

DslReader

Defined Under Namespace

Classes: Error

Constant Summary collapse

WARN_INVALID_LOG_LEVEL =
"Invalid log level `%s` ignored. "\
"Please use either :debug, :info, :warn or :error."
WARN_INVALID_LOG_OPTIONS =
"You cannot specify the logger options"\
" :only and :except at the same time."

Instance Method Summary collapse

Instance Method Details

#callback(*args) { ... } ⇒ Object

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.

Examples:

Add callback before the `reload` action.

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

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])

Parameters:

  • args (Array)

    the callback arguments

Yields:

  • a callback block


246
247
248
249
250
251
252
253
254
255
256
257
258
# File 'lib/guard/dsl.rb', line 246

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) ⇒ Object

Sets Guard to clear the screen before every task is run

Examples:

switching clearing the screen on

clearing(:on)

Parameters:

  • on (Symbol)

    ':on' to turn on, ':off' (default) to turn off


408
409
410
# File 'lib/guard/dsl.rb', line 408

def clearing(on)
  Guard.state.session.clearing(on == :on)
end

#directories(directories) ⇒ Object

Sets the directories to pass to Listen

Examples:

watch only given directories

directories %w(lib specs)

Parameters:

  • directories (Array)

    directories for Listen to watch


394
395
396
397
398
399
# File 'lib/guard/dsl.rb', line 394

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) ⇒ Object

:nodoc


377
378
379
380
381
382
383
384
385
# File 'lib/guard/dsl.rb', line 377

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

#group(*args) { ... } ⇒ Object

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

group_name`.

Examples:

Declare two groups of Guard plugins

group :backend do
  guard :spork
  guard :rspec
end

group :frontend do
  guard :passenger
  guard :livereload
end

Parameters:

  • name (Symbol, String, Array<Symbol, String>)

    the group name called from the CLI

  • options (Hash)

    the options accepted by the group

Yields:

  • a block where you can declare several Guard plugins

See Also:


124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
# File 'lib/guard/dsl.rb', line 124

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 = {}) { ... } ⇒ Object

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.

Examples:

Declare a Guard without `watch` patterns

guard :rspec

Declare a Guard with a `watch` pattern

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

Parameters:

  • name (String)

    the Guard plugin name

  • options (Hash) (defaults to: {})

    the options accepted by the Guard plugin

Yields:

  • a block where you can declare several watch patterns and actions

See Also:


176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
# File 'lib/guard/dsl.rb', line 176

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) ⇒ Object Also known as: filter

Ignores certain paths globally.

Examples:

Ignore some paths

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

Parameters:

  • regexps (Regexp)

    a pattern (or list of patterns) for ignoring paths


267
268
269
270
# File 'lib/guard/dsl.rb', line 267

def ignore(*regexps)
  # TODO: use guardfile results class
  Guard.state.session.guardfile_ignore = regexps
end

#ignore!(*regexps) ⇒ Object Also known as: filter!

Replaces ignored paths globally

Examples:

Ignore only these paths

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

Parameters:

  • regexps (Regexp)

    a pattern (or list of patterns) for ignoring paths


282
283
284
285
286
287
# File 'lib/guard/dsl.rb', line 282

def ignore!(*regexps)
  @ignore_regexps ||= []
  @ignore_regexps << regexps
  # TODO: use guardfile results class
  Guard.state.session.guardfile_ignore_bang = @ignore_regexps
end

#interactor(options) ⇒ Object

Sets the interactor options or disable the interactor.

Examples:

Pass options to the interactor

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

Turn off interactions

interactor :off

Parameters:

  • options (Symbol, Hash)

    either `:off` or a Hash with interactor options


91
92
93
94
95
96
97
98
99
# File 'lib/guard/dsl.rb', line 91

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) ⇒ Object

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`.

Examples:

Set the log level

logger level: :warn

Set a custom log template

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

Set a custom time format

logger time_format: '%h'

Limit logging to a Guard plugin

logger only: :jasmine

Log all but not the messages from a specific Guard plugin

logger except: :jasmine

Parameters:

  • options (Hash)

    the log options

Options Hash (options):

  • level (String, Symbol)

    the log level

  • template (String)

    the logger template

  • time_format (String, Symbol)

    the time format

  • only (Regexp)

    show only messages from the matching Guard plugin

  • except (Regexp)

    does not show messages from the matching Guard plugin


325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
# File 'lib/guard/dsl.rb', line 325

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 = {}) ⇒ Object

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.

Examples:

Define multiple notifications

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

Parameters:

  • notifier (Symbol, String)

    the name of the notifier to use

  • opts (Hash) (defaults to: {})

    the notification library options

See Also:


76
77
78
# File 'lib/guard/dsl.rb', line 76

def notification(notifier, opts = {})
  Guard.state.session.guardfile_notification = { notifier.to_sym => opts }
end

#scope(scope = {}) ⇒ Object

Sets the default scope on startup

Examples:

Scope Guard to a single group

scope group: :frontend

Scope Guard to multiple groups

scope groups: [:specs, :docs]

Scope Guard to a single plugin

scope plugin: :test

Scope Guard to multiple plugins

scope plugins: [:jasmine, :rspec]

Parameters:

  • scope (Hash) (defaults to: {})

    the scope for the groups and plugins


372
373
374
375
# File 'lib/guard/dsl.rb', line 372

def scope(scope = {})
  # TODO: use a Guardfile::Results class
  Guard.state.session.guardfile_scope(scope)
end

#watch(pattern) {|m| ... } ⇒ Object

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

modification

Examples:

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

Declare global watchers outside of a Guard

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

Parameters:

  • pattern (String, Regexp)

    the pattern that Guard must watch for

Yields:

  • a block to be run when the pattern is matched

Yield Parameters:

  • m (MatchData)

    matches of the pattern

Yield Returns:

  • a directory, a filename, an array of directories / filenames, or nothing (can be an arbitrary command)

See Also:


218
219
220
221
222
223
224
225
# File 'lib/guard/dsl.rb', line 218

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