From 5e42001109a14a544002eef62c53430e504408ec Mon Sep 17 00:00:00 2001 From: Joshua Hawxwell Date: Thu, 15 Dec 2011 13:27:41 +0000 Subject: [PATCH 1/5] Add the ability to load user defined templates. The templates are loaded from ~/.guard/templates/[name] by calling 'guard init [name]' as you would to load a guard's template file. --- lib/guard.rb | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/lib/guard.rb b/lib/guard.rb index 368d5aab2..c09fb0736 100644 --- a/lib/guard.rb +++ b/lib/guard.rb @@ -17,6 +17,8 @@ module Guard # The Guardfile template for `guard init` GUARDFILE_TEMPLATE = File.expand_path('../guard/templates/Guardfile', __FILE__) + # The location of user defined templates + HOME_TEMPLATES = File.expand_path('~/.guard/templates') class << self attr_accessor :options, :interactor, :listener, :lock @@ -38,8 +40,21 @@ def initialize_template(guard_name = nil) end if guard_name - guard_class = ::Guard.get_guard_class(guard_name) - guard_class.init(guard_name) + guard_class = ::Guard.get_guard_class(guard_name, true) + if guard_class + guard_class.init(guard_name) + elsif File.exist?(File.join(HOME_TEMPLATES, guard_name)) + content = File.read('Guardfile') + template = File.read(File.join(HOME_TEMPLATES, guard_name)) + + File.open('Guardfile', 'wb') do |f| + f.puts(content) + f.puts("") + f.puts(template) + end + + ::Guard::UI.info "#{ guard_name } template added to Guardfile, feel free to edit it" + end end end @@ -395,7 +410,7 @@ def add_group(name, options = {}) # @param [String] name the name of the Guard # @return [Class, nil] the loaded class # - def get_guard_class(name) + def get_guard_class(name, fail_gracefully=false) name = name.to_s try_require = false const_name = name.downcase.gsub('-', '') @@ -410,8 +425,10 @@ def get_guard_class(name) UI.error "Could not find class Guard::#{ const_name.capitalize }" end rescue LoadError => loadError - UI.error "Could not load 'guard/#{ name.downcase }' or find class Guard::#{ const_name.capitalize }" - UI.error loadError.to_s + unless fail_gracefully + UI.error "Could not load 'guard/#{ name.downcase }' or find class Guard::#{ const_name.capitalize }" + UI.error loadError.to_s + end end end From 6001b19a0cd8e28dddecc55ae0ab12644364bcd7 Mon Sep 17 00:00:00 2001 From: Joshua Hawxwell Date: Thu, 15 Dec 2011 13:36:29 +0000 Subject: [PATCH 2/5] Errors are printed if guard template can't be found --- lib/guard.rb | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/guard.rb b/lib/guard.rb index c09fb0736..0edb7135f 100644 --- a/lib/guard.rb +++ b/lib/guard.rb @@ -54,6 +54,9 @@ def initialize_template(guard_name = nil) end ::Guard::UI.info "#{ guard_name } template added to Guardfile, feel free to edit it" + else + const_name = guard_name.downcase.gsub('-', '') + UI.error "Could not load 'guard/#{ guard_name.downcase }' or '~/.guard/templates/#{ guard_name.downcase }' or find class Guard::#{ const_name.capitalize }" end end end From a6e70f210cdf3af48645f88d4c28e5bf62acca9f Mon Sep 17 00:00:00 2001 From: Joshua Hawxwell Date: Fri, 23 Dec 2011 13:52:14 +0000 Subject: [PATCH 3/5] Added tests for loading user defined guard templates. --- spec/guard_spec.rb | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/spec/guard_spec.rb b/spec/guard_spec.rb index 57f3e61eb..8ec73e65e 100644 --- a/spec/guard_spec.rb +++ b/spec/guard_spec.rb @@ -33,6 +33,25 @@ class Guard::Foo < Guard::Guard Guard.initialize_template('foo') end end + + context "with a user defined template" do + let(:template) { File.join(Guard::HOME_TEMPLATES, '/bar') } + + before { + File.should_receive(:exist?).with('Guardfile').and_return false + File.should_receive(:exist?).with(template).and_return true + } + + it "copies the Guardfile template and initializes the Guard" do + FileUtils.should_receive(:cp).with(an_instance_of(String), 'Guardfile') + File.should_receive(:read).with('Guardfile').and_return 'Guardfile content' + File.should_receive(:read).with(template).and_return 'Template content' + io = StringIO.new + File.should_receive(:open).with('Guardfile', 'wb').and_yield io + Guard.initialize_template('bar') + io.string.should eql "Guardfile content\n\nTemplate content\n" + end + end end context "without a Guard name" do @@ -406,6 +425,13 @@ class Inline < Guard Guard.get_guard_class('inline').should == Guard::Inline end end + + context 'when set to fail gracefully' do + it 'does not print error messages on fail' do + ::Guard::UI.should_not_receive(:error) + Guard.get_guard_class('notAGuardClass', true).should be_nil + end + end end describe ".locate_guard" do From d1e630c2969a2a97f88465f3eba022e2a20de71d Mon Sep 17 00:00:00 2001 From: Joshua Hawxwell Date: Fri, 23 Dec 2011 13:59:09 +0000 Subject: [PATCH 4/5] Documented changes --- lib/guard.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/guard.rb b/lib/guard.rb index 0edb7135f..e73a8162c 100644 --- a/lib/guard.rb +++ b/lib/guard.rb @@ -28,7 +28,7 @@ class << self # # @see Guard::Guard.init # - # @param [String] guard_name the name of the Guard to initialize + # @param [String] guard_name the name of the Guard or template to initialize # def initialize_template(guard_name = nil) if !File.exist?('Guardfile') @@ -411,6 +411,7 @@ def add_group(name, options = {}) # Tries to load the Guard main class. # # @param [String] name the name of the Guard + # @param [Boolean] fail_gracefully whether error messages should not be printed # @return [Class, nil] the loaded class # def get_guard_class(name, fail_gracefully=false) From 4910828cf7c3eee2e91762e14b89451a18798b54 Mon Sep 17 00:00:00 2001 From: Joshua Hawxwell Date: Fri, 23 Dec 2011 14:03:59 +0000 Subject: [PATCH 5/5] Added description of new init functionality to README --- README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/README.md b/README.md index 5cb636fec..7542a48c2 100644 --- a/README.md +++ b/README.md @@ -218,6 +218,13 @@ In addition, the `init` task can be used to append a supplied Guard template fro $ guard init ``` +You can also define your own templates in `~/.guard/templates/` which can be appended in the same way to your existing +`Guardfile`: + +```bash +$ guard init +``` + ### Start Just launch Guard inside your Ruby or Rails project with: