diff --git a/lib/guard.rb b/lib/guard.rb index 37653fb..6916f90 100644 --- a/lib/guard.rb +++ b/lib/guard.rb @@ -14,7 +14,7 @@ module Guard autoload :Hook, 'guard/hook' class << self - attr_accessor :options, :guards, :groups, :interactor, :listener + attr_accessor :options, :interactor, :listener # Initialize the Guard singleton. # @@ -41,6 +41,46 @@ module Guard self end + # Smart accessor for retrieving a specific guard or several guards at once. + # + # @param [Object] filter an optional filter to retrieve specific guard(s). + # @option filter [String, Symbol] return the guard with the given name, or nil if not found + # @option filter [Regexp] returns all guards matching the Regexp, or [] if no guard match + # @option filter [NilClass] returns all guards + # + def guards(filter = nil) + case filter + when String, Symbol + @guards.find { |guard| guard.class.to_s.downcase.sub('guard::', '') == filter.to_s.downcase.gsub('-', '') } + when Regexp + @guards.find_all { |guard| guard.class.to_s.downcase.sub('guard::', '') =~ filter } + when Hash + filter.inject(@guards) do |matches, (k, v)| + matches.find_all { |guard| guard.send(k).to_sym == v.to_sym } + end + else + @guards + end + end + + # Smart accessor for retrieving a specific group or several groups at once. + # + # @param [Object] filter an optional filter to retrieve specific group(s). + # @option filter [String, Symbol] return the group with the given name, or nil if not found + # @option filter [Regexp] returns all groups matching the Regexp, or [] if no group match + # @option filter [NilClass] returns all groups + # + def groups(filter = nil) + case filter + when String, Symbol + @groups.find { |group| group.name == filter.to_sym } + when Regexp + @groups.find_all { |group| group.name =~ filter } + else + @groups + end + end + # Start Guard by evaluate the `Guardfile`, initialize the declared Guards # and start the available file change listener. # @@ -141,9 +181,9 @@ module Guard # @param [Array] files the list of files to pass to the task # def execute_supervised_task_for_all_guards(task, files = nil) - guards.find_all { |guard| guard.group == group_hash[:name] }.each do |guard| groups.each do |group| catch group.options[:halt_on_fail] == true ? :task_has_failed : :no_catch do + guards(:group => group.name).each do |guard| if task == :run_on_change paths = Watcher.match_files(guard, files) UI.debug "#{guard.class.name}##{task} with #{paths.inspect}" diff --git a/spec/guard_spec.rb b/spec/guard_spec.rb index 714df2c..080dd97 100644 --- a/spec/guard_spec.rb +++ b/spec/guard_spec.rb @@ -15,7 +15,8 @@ describe Guard do end it "initializes @groups" do - Guard.groups.should eql [{ :name => :default, :options => {} }] + described_class.groups[0].name.should eql :default + described_class.groups[0].options.should == {} end it "initializes the options" do @@ -55,6 +56,99 @@ describe Guard do end end + describe ".guards" do + + class Guard::FooBar < Guard::Guard; end + class Guard::FooBaz < Guard::Guard; end + + subject do + guard = ::Guard.setup + @guard_foo_bar = Guard::FooBar.new([], { :group => 'backend' }) + @guard_foo_baz = Guard::FooBaz.new([], { :group => 'frontend' }) + guard.instance_variable_get("@guards").push(@guard_foo_bar) + guard.instance_variable_get("@guards").push(@guard_foo_baz) + guard + end + + it "return @guards without any argument" do + subject.guards.should eql subject.instance_variable_get("@guards") + end + + describe "find a guard by as string/symbol" do + it "find a guard by a string" do + subject.guards('foo-bar').should eql @guard_foo_bar + end + + it "find a guard by a symbol" do + subject.guards(:'foo-bar').should eql @guard_foo_bar + end + + it "returns nil if guard is not found" do + subject.guards('foo-foo').should be_nil + end + end + + describe "find guards matching a regexp" do + it "with matches" do + subject.guards(/^foo/).should eql [@guard_foo_bar, @guard_foo_baz] + end + + it "without matches" do + subject.guards(/foo$/).should eql [] + end + end + + describe "find guards by their group" do + it "group name is a string" do + subject.guards(:group => 'backend').should eql [@guard_foo_bar] + end + it "group name is a symbol" do + subject.guards(:group => :frontend).should eql [@guard_foo_baz] + end + + it "returns [] if guard is not found" do + subject.guards(:group => :unknown).should eql [] + end + end + end + + describe ".groups" do + subject do + guard = ::Guard.setup + @group_backend = guard.add_group(:backend) + @group_backflip = guard.add_group(:backflip) + guard + end + + it "return @groups without any argument" do + subject.groups.should eql subject.instance_variable_get("@groups") + end + + describe "find a group by as string/symbol" do + it "find a group by a string" do + subject.groups('backend').should eql @group_backend + end + + it "find a group by a symbol" do + subject.groups(:backend).should eql @group_backend + end + + it "returns nil if group is not found" do + subject.groups(:foo).should be_nil + end + end + + describe "find groups matching a regexp" do + it "with matches" do + subject.groups(/^back/).should eql [@group_backend, @group_backflip] + end + + it "without matches" do + subject.groups(/back$/).should eql [] + end + end + end + describe ".start" do it "basic check that core methods are called" do opts = { :my_opts => true, :guardfile => File.join(@fixture_path, "Guardfile") } @@ -135,19 +229,22 @@ describe Guard do it "accepts group name as string" do subject.add_group('backend') - subject.groups.should eql [{ :name => :default, :options => {} }, { :name => :backend, :options => {} }] + subject.groups[0].name.should eql :default + subject.groups[1].name.should eql :backend end it "accepts group name as symbol" do subject.add_group(:backend) - subject.groups.should eql [{ :name => :default, :options => {} }, { :name => :backend, :options => {} }] + subject.groups[0].name.should eql :default + subject.groups[1].name.should eql :backend end it "accepts options" do subject.add_group(:backend, { :halt_on_fail => true }) - subject.groups.should eql [{ :name => :default, :options => {} }, { :name => :backend, :options => { :halt_on_fail => true } }] + subject.groups[0].options.should == {} + subject.groups[1].options.should == { :halt_on_fail => true } end end @@ -282,7 +379,7 @@ describe Guard do before do @g = mock(Guard::Guard).as_null_object subject.guards.push(@g) - subject.groups.push({ :name => :foo, :options => { :halt_on_fail => true } }) + subject.add_group(:foo, { :halt_on_fail => true }) end context "with a task that succeed" do