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`:
-
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`.
Constants
- WARN_INVALID_LOG_LEVEL
- WARN_INVALID_LOG_OPTIONS
Public Instance Methods
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
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
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
# 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
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
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
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
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
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
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
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
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
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
# 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