Move the DSL describing logic from the CLI to the DSLDescriber.

This commit is contained in:
Michael Kessler 2011-10-04 09:04:50 +02:00
parent cba4e4c163
commit cdf0906614
3 changed files with 153 additions and 92 deletions

View File

@ -50,7 +50,7 @@ module Guard
:type => :boolean, :type => :boolean,
:default => false, :default => false,
:aliases => '-A', :aliases => '-A',
:banner => "Watch for all file modifications including moves and deletions" :banner => 'Watch for all file modifications including moves and deletions'
# Start Guard by initialize the defined Guards and watch the file system. # Start Guard by initialize the defined Guards and watch the file system.
# This is the default task, so calling `guard` is the same as calling `guard start`. # This is the default task, so calling `guard` is the same as calling `guard start`.
@ -66,37 +66,8 @@ module Guard
# List the Guards that are available for use in your system and marks # List the Guards that are available for use in your system and marks
# those that are currently used in your `Guardfile`. # those that are currently used in your `Guardfile`.
# #
# @example Guard list output
#
# Available guards:
# bundler *
# livereload
# ronn
# rspec *
# spork
#
# See also https://github.com/guard/guard/wiki/List-of-available-Guards
# * denotes ones already in your Guardfile
#
# @see Guard::DslDescriber
#
def list def list
Guard::DslDescriber.evaluate_guardfile(options) Guard::DslDescriber.list(options)
installed = Guard::DslDescriber.guardfile_structure.inject([]) do |installed, group|
group[:guards].each { |guard| installed << guard[:name] } if group[:guards]
installed
end
Guard::UI.info 'Available guards:'
Guard::guard_gem_names.sort.uniq.each do |name|
Guard::UI.info " #{ name } #{ installed.include?(name) ? '*' : '' }"
end
Guard::UI.info ' '
Guard::UI.info 'See also https://github.com/guard/guard/wiki/List-of-available-Guards'
Guard::UI.info '* denotes ones already in your Guardfile'
end end
desc 'version', 'Show the Guard version' desc 'version', 'Show the Guard version'
@ -138,40 +109,8 @@ module Guard
# Shows all Guards and their options that are defined in # Shows all Guards and their options that are defined in
# the `Guardfile`. # the `Guardfile`.
# #
# @example guard show output
#
# (global):
# bundler
# coffeescript: input => "app/assets/javascripts", noop => true
# jasmine
# rspec: cli => "--fail-fast --format Fuubar
#
# @see Guard::DslDescriber
#
def show def show
Guard::DslDescriber.evaluate_guardfile(options) Guard::DslDescriber.show(options)
Guard::DslDescriber.guardfile_structure.each do |group|
unless group[:guards].empty?
if group[:group]
Guard::UI.info "Group #{ group[:group] }:"
else
Guard::UI.info '(global):'
end
group[:guards].each do |guard|
line = " #{ guard[:name] }"
unless guard[:options].empty?
line += ": #{ guard[:options].collect { |k, v| "#{ k } => #{ v.inspect }" }.join(', ') }"
end
Guard::UI.info line
end
end
end
Guard::UI.info ''
end end
end end

View File

@ -2,6 +2,8 @@ require 'guard/dsl'
module Guard module Guard
autoload :UI, 'guard/ui'
# The DslDescriber overrides methods to create an internal structure # The DslDescriber overrides methods to create an internal structure
# of the Guardfile that is used in some inspection utility methods # of the Guardfile that is used in some inspection utility methods
# like the CLI commands `show` and `list`. # like the CLI commands `show` and `list`.
@ -11,10 +13,97 @@ module Guard
# #
class DslDescriber < Dsl class DslDescriber < Dsl
@@guardfile_structure = [ { :guards => [] } ]
class << self class << self
# Evaluate the DSL methods in the `Guardfile`.
#
# @option options [Array<Symbol,String>] groups the groups to evaluate
# @option options [String] guardfile the path to a valid Guardfile
# @option options [String] guardfile_contents a string representing the content of a valid Guardfile
# @raise [ArgumentError] when options are not a Hash
#
def evaluate_guardfile(options = {})
@@guardfile_structure = [{ :guards => [] }]
super options
end
# List the Guards that are available for use in your system and marks
# those that are currently used in your `Guardfile`.
#
# @example Guard list output
#
# Available guards:
# bundler *
# livereload
# ronn
# rspec *
# spork
#
# See also https://github.com/guard/guard/wiki/List-of-available-Guards
# * denotes ones already in your Guardfile
#
# @param [Hash] options the Guard options
#
def list(options)
evaluate_guardfile(options)
installed = guardfile_structure.inject([]) do |installed, group|
group[:guards].each { |guard| installed << guard[:name] } if group[:guards]
installed
end
UI.info 'Available guards:'
::Guard.guard_gem_names.sort.uniq.each do |name|
UI.info " #{ name }#{ installed.include?(name) ? '*' : '' }"
end
UI.info ''
UI.info 'See also https://github.com/guard/guard/wiki/List-of-available-Guards'
UI.info '* denotes ones already in your Guardfile'
end
# Shows all Guards and their options that are defined in
# the `Guardfile`.
#
# @example guard show output
#
# (global):
# bundler
# coffeescript: input => "app/assets/javascripts", noop => true
# jasmine
# rspec: cli => "--fail-fast --format Fuubar
#
# @param [Hash] options the Guard options
#
def show(options)
evaluate_guardfile(options)
guardfile_structure.each do |group|
unless group[:guards].empty?
if group[:group]
UI.info "Group #{ group[:group] }:"
else
UI.info '(global):'
end
group[:guards].each do |guard|
line = " #{ guard[:name] }"
unless guard[:options].empty?
line += ": #{ guard[:options].collect { |k, v| "#{ k } => #{ v.inspect }" }.join(', ') }"
end
UI.info line
end
end
end
UI.info ''
end
private
# Get the Guardfile structure. # Get the Guardfile structure.
# #
# @return [Array<Hash>] the structure # @return [Array<Hash>] the structure
@ -22,6 +111,7 @@ module Guard
def guardfile_structure def guardfile_structure
@@guardfile_structure @@guardfile_structure
end end
end end
private private
@ -50,7 +140,7 @@ module Guard
# #
# @see Guard::Dsl#guard # @see Guard::Dsl#guard
# #
def guard(name, options = {}) def guard(name, options = { })
node = (@group ? @@guardfile_structure.last : @@guardfile_structure.first) node = (@group ? @@guardfile_structure.last : @@guardfile_structure.first)
node[:guards] << { :name => name, :options => options } node[:guards] << { :name => name, :options => options }

View File

@ -1,38 +1,70 @@
require 'spec_helper' require 'spec_helper'
describe Guard::DslDescriber do describe Guard::DslDescriber do
before(:each) do
::Guard.stub!(:guards).and_return([mock('Guard')]) let(:describer) { ::Guard::DslDescriber }
user_config_path = File.expand_path(File.join('~', '.guard.rb'))
File.stub(:exist?).with(user_config_path) { false } let(:guardfile) do
<<-GUARD
guard 'test', :a => :b do
watch('c')
end
group :a do
guard 'test', :x => 1, :y => 2, :z => 3 do
watch('c')
end
end
group "b" do
guard 'another' do
watch('c')
end
end
GUARD
end end
it 'should evaluate a Guardfile and create the right structure' do before do
mixed_guardfile_string = <<-GUARD @output = ''
guard 'test', :a => :b do Guard::UI.stub(:info) { |msg| @output << msg + "\n" }
watch('c')
end
group :a do
guard 'test' do
watch('c')
end end
end
group "b" do after do
guard 'another' do Guard::UI.unstub(:info)
watch('c')
end end
end
GUARD
described_class.evaluate_guardfile(:guardfile_contents => mixed_guardfile_string) describe '.list' do
it 'lists the available Guards' do
Guard.stub(:guard_gem_names).and_return ['test', 'another', 'even', 'more']
describer.list(:guardfile_contents => guardfile)
@output.should eql <<OUTPUT
Using inline Guardfile.
Available guards:
another*
even
more
test*
described_class.guardfile_structure.should == [ See also https://github.com/guard/guard/wiki/List-of-available-Guards
{ :guards => [ { :name => 'test', :options => { :a => :b } } ] }, * denotes ones already in your Guardfile
{ :group => :a, :guards => [ { :name => 'test', :options => {} } ] }, OUTPUT
{ :group => :b, :guards => [ { :name => 'another', :options => {} } ] } end
] end
describe '.show' do
it 'shows the Guards and their options' do
describer.show(:guardfile_contents => guardfile)
@output.should eql <<OUTPUT
Using inline Guardfile.
(global):
test: a => :b
Group a:
test: x => 1, y => 2, z => 3
Group b:
another
OUTPUT
end
end end
end end