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 Guards and the file changes they are watching.

You can optionally group the Guards with the ‘group` keyword and ignore certain paths with the `ignore_paths` keyword.

A more advanced DSL use is the ‘callback` keyword that allows you to execute arbitrary code before or after any of the `start`, `stop`, `reload`, `run_all` and `run_on_change` Guards’ 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` 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`.

Examples:

A sample of a complex Guardfile


group 'frontend' do
  guard 'passenger', :ping => true do
    watch('config/application.rb')
    watch('config/environment.rb')
    watch(%r{^config/environments/.+\.rb})
    watch(%r{^config/initializers/.+\.rb})
  end

  guard 'livereload', :apply_js_live => false do
    watch(%r{^app/.+\.(erb|haml)})
    watch(%r{^app/helpers/.+\.rb})
    watch(%r{^public/javascripts/.+\.js})
    watch(%r{^public/stylesheets/.+\.css})
    watch(%r{^public/.+\.html})
    watch(%r{^config/locales/.+\.yml})
  end
end

group 'backend' do
  # Reload the bundle when the Gemfile is modified
  guard 'bundler' do
    watch('Gemfile')
  end

  # for big project you can fine tune the "timeout" before Spork's launch is considered failed
  guard 'spork', :wait => 40 do
    watch('Gemfile')
    watch('config/application.rb')
    watch('config/environment.rb')
    watch(%r{^config/environments/.+\.rb})
    watch(%r{^config/initializers/.+\.rb})
    watch('spec/spec_helper.rb')
  end

  # use RSpec 2, from the system's gem and with some direct RSpec CLI options
  guard 'rspec', :version => 2, :cli => "--color --drb -f doc", :bundler => false do
    watch('spec/spec_helper.rb')                                  { "spec" }
    watch('app/controllers/application_controller.rb')            { "spec/controllers" }
    watch('config/routes.rb')                                     { "spec/routing" }
    watch(%r{^spec/support/(controllers|acceptance)_helpers\.rb}) { |m| "spec/#{m[1]}" }
    watch(%r{^spec/.+_spec\.rb})

    watch(%r{^app/controllers/(.+)_(controller)\.rb}) { |m| ["spec/routing/#{m[1]}_routing_spec.rb", "spec/#{m[2]}s/#{m[1]}_#{m[2]}_spec.rb", "spec/acceptance/#{m[1]}_spec.rb"] }

    watch(%r{^app/(.+)\.rb}) { |m| "spec/#{m[1]}_spec.rb" }
    watch(%r{^lib/(.+)\.rb}) { |m| "spec/lib/#{m[1]}_spec.rb" }
  end
end

Direct Known Subclasses

DslDescriber

Constant Summary collapse

@@options =
nil

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.evaluate_guardfile(options = {}) ⇒ Object

Evaluate the DSL methods in the ‘Guardfile`.

Parameters:

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

    a customizable set of options

Options Hash (options):

  • groups (Array<Symbol,String>)

    the groups to evaluate

  • guardfile (String)

    the path to a valid Guardfile

  • guardfile_contents (String)

    a string representing the content of a valid Guardfile

Raises:

  • (ArgumentError)

    when options are not a Hash



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

def evaluate_guardfile(options = {})
  raise ArgumentError.new('No option hash passed to evaluate_guardfile!') unless options.is_a?(Hash)

  @@options = options.dup

  fetch_guardfile_contents
  instance_eval_guardfile(guardfile_contents_with_user_config)

  UI.error 'No guards found in Guardfile, please add at least one.' if !::Guard.guards.nil? && ::Guard.guards.empty?
end

.fetch_guardfile_contentsObject

Get the content to evaluate and stores it into the options as ‘:guardfile_contents`.



147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
# File 'lib/guard/dsl.rb', line 147

def fetch_guardfile_contents
  if @@options[:guardfile_contents]
    UI.info 'Using inline Guardfile.'
    @@options[:guardfile_path] = 'Inline Guardfile'

  elsif @@options[:guardfile]
    if File.exist?(@@options[:guardfile])
      read_guardfile(@@options[:guardfile])
      UI.info "Using Guardfile at #{ @@options[:guardfile] }."
    else
      UI.error "No Guardfile exists at #{ @@options[:guardfile] }."
      exit 1
    end

  else
    if File.exist?(guardfile_default_path)
      read_guardfile(guardfile_default_path)
    else
      UI.error 'No Guardfile found, please create one with `guard init`.'
      exit 1
    end
  end

  unless guardfile_contents_usable?
    UI.error "The command file(#{ @@options[:guardfile] }) seems to be empty."
    exit 1
  end
end

.guardfile_contentsString

Get the content of the ‘Guardfile`.

Returns:

  • (String)

    the Guardfile content



180
181
182
# File 'lib/guard/dsl.rb', line 180

def guardfile_contents
  @@options ? @@options[:guardfile_contents] : ''
end

.guardfile_contents_usable?Boolean

Tests if the current ‘Guardfile` content is usable.

Returns:

  • (Boolean)

    if the Guardfile is usable



208
209
210
# File 'lib/guard/dsl.rb', line 208

def guardfile_contents_usable?
  guardfile_contents && guardfile_contents.size >= 'guard :a'.size # Smallest Guard definition
end

.guardfile_contents_with_user_configString

Get the content of the ‘Guardfile` and the global user configuration file.

Returns:

  • (String)

    the Guardfile content

See Also:

  • #user_config_path


191
192
193
194
# File 'lib/guard/dsl.rb', line 191

def guardfile_contents_with_user_config
  config = File.read(user_config_path) if File.exist?(user_config_path)
  [guardfile_contents, config].join("\n")
end

.guardfile_default_pathString

Gets the default path of the ‘Guardfile`. This returns the `Guardfile` from the current directory when existing, or the global `.Guardfile` at the home directory.

Returns:

  • (String)

    the path to the Guardfile



218
219
220
# File 'lib/guard/dsl.rb', line 218

def guardfile_default_path
  File.exist?(local_guardfile_path) ? local_guardfile_path : home_guardfile_path
end

.guardfile_include?(guard_name) ⇒ Boolean

Test if the current ‘Guardfile` contains a specific Guard.

Parameters:

  • guard_name (String)

    the name of the Guard

Returns:

  • (Boolean)

    whether the Guard has been declared



128
129
130
# File 'lib/guard/dsl.rb', line 128

def guardfile_include?(guard_name)
  guardfile_contents.match(/^guard\s*\(?\s*['":]#{ guard_name }['"]?/)
end

.guardfile_pathString

Get the file path to the project ‘Guardfile`.

Returns:

  • (String)

    the path to the Guardfile



200
201
202
# File 'lib/guard/dsl.rb', line 200

def guardfile_path
  @@options ? @@options[:guardfile_path] : ''
end

.instance_eval_guardfile(contents) ⇒ Object

Evaluate the content of the ‘Guardfile`.

Parameters:

  • contents (String)

    the content to evaluate.



116
117
118
119
120
121
# File 'lib/guard/dsl.rb', line 116

def instance_eval_guardfile(contents)
  new.instance_eval(contents, @@options[:guardfile_path], 1)
rescue
  UI.error "Invalid Guardfile, original error is:\n#{ $! }"
  exit 1
end

.read_guardfile(guardfile_path) ⇒ Object

Read the current ‘Guardfile` content.

Parameters:

  • the (String)

    path to the Guardfile



136
137
138
139
140
141
142
# File 'lib/guard/dsl.rb', line 136

def read_guardfile(guardfile_path)
  @@options[:guardfile_path]     = guardfile_path
  @@options[:guardfile_contents] = File.read(guardfile_path)
rescue
  UI.error("Error reading file #{ guardfile_path }")
  exit 1
end

.reevaluate_guardfileObject

Re-evaluate the ‘Guardfile` to update the current Guard configuration.



102
103
104
105
106
107
108
109
110
# File 'lib/guard/dsl.rb', line 102

def reevaluate_guardfile
  ::Guard.guards.clear
  ::Guard.reset_groups
  @@options.delete(:guardfile_contents)
  Dsl.evaluate_guardfile(@@options)
  msg = 'Guardfile has been re-evaluated.'
  UI.info(msg)
  Notifier.notify(msg)
end

Instance Method Details

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

Define a callback to execute arbitrary code before or after any of the ‘start`, `stop`, `reload`, `run_all` and `run_on_change` guards’ method.

Parameters:

  • args (Array)

    the callback arguments

Yields:

  • a block with listeners

See Also:



350
351
352
353
# File 'lib/guard/dsl.rb', line 350

def callback(*args, &listener)
  listener, events = args.size > 1 ? args : [listener, args[0]]
  @callbacks << { :events => events, :listener => listener }
end

#group(name, options = {}) { ... } ⇒ Object

Declares a group of guards to be run with ‘guard start –group group_name`.

Examples:

Declare two groups of Guards


group 'backend' do
  guard 'spork'
  guard 'rspec'
end

group 'frontend' do
  guard 'passenger'
  guard 'livereload'
end

Parameters:

  • name (Symbol, String)

    the group’s name called from the CLI

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

    the options accepted by the group

Yields:

  • a block where you can declare several guards

See Also:



275
276
277
278
279
280
281
282
283
284
285
286
287
# File 'lib/guard/dsl.rb', line 275

def group(name, options = {})
  @groups = @@options[:group] || []
  name    = name.to_sym

  if block_given? && (@groups.empty? || @groups.map(&:to_sym).include?(name))
    ::Guard.add_group(name.to_s.downcase, options)
    @current_group = name

    yield if block_given?

    @current_group = nil
  end
end

#guard(name, options = {}) { ... } ⇒ Object

Declare a guard 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


guard 'rspec' do
end

Parameters:

  • name (String)

    the Guard name

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

    the options accepted by the Guard

Yields:

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

See Also:



310
311
312
313
314
315
316
317
318
# File 'lib/guard/dsl.rb', line 310

def guard(name, options = {})
  @watchers  = []
  @callbacks = []

  yield if block_given?

  options.update(:group => (@current_group || :default))
  ::Guard.add_guard(name.to_s.downcase, @watchers, @callbacks, options)
end

#ignore_paths(*paths) ⇒ Object

Ignore certain paths globally.

Examples:

Ignore some paths

ignore_paths ".git", ".svn"

Parameters:

  • paths (Array)

    the list of paths to ignore

See Also:



364
365
366
367
# File 'lib/guard/dsl.rb', line 364

def ignore_paths(*paths)
  UI.info "Ignoring paths: #{ paths.join(', ') }"
  ::Guard.listener.ignore_paths.push(*paths)
end

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

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

Examples:

Declare watchers for a Guard


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

Parameters:

  • pattern (String, Regexp)

    the pattern to be watched by the guard

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:



338
339
340
# File 'lib/guard/dsl.rb', line 338

def watch(pattern, &action)
  @watchers << ::Guard::Watcher.new(pattern, action)
end