module Guard # Base class that every Guard implementation must inherit from. # # Guard will trigger the `start`, `stop`, `reload`, `run_all`, `run_on_change` and # `run_on_deletion` task methods depending on user interaction and file modification. # # In each of these Guard task methods you have to implement some work when you want to # support this kind of task. The return value of each Guard task method is not evaluated # by Guard, but I'll be passed to the "_end" hook for further evaluation. You can # throw `:task_has_failed` to indicate that your Guard method was not successful, # and successive guard tasks will be aborted when the group has set the `:halt_on_fail` # option. # # @see Guard::Hook # @see Guard::Group # # @example Throw :task_has_failed # # def run_all # if !runner.run(['all']) # throw :task_has_failed # end # end # # Each Guard should provide a template Guardfile located within the Gem # at `lib/guard/guard-name/templates/Guardfile`. # # By default all watchers for a Guard are returning strings of paths to the # Guard, but if your Guard want to allow any return value from a watcher, # you can set the `any_return` option to true. # # If one of those methods raise an exception other than `:task_has_failed`, # the Guard::GuardName instance will be removed from the active guards. # class Guard include Hook attr_accessor :watchers, :options, :group # Initialize a Guard. # # @param [Array] watchers the Guard file watchers # @param [Hash] options the custom Guard options # @option options [Symbol] group the group this Guard belongs to # @option options [Boolean] any_return allow any object to be returned from a watcher # def initialize(watchers = [], options = {}) @group = options[:group] ? options.delete(:group).to_sym : :default @watchers, @options = watchers, options end # Initialize the Guard. This will copy the Guardfile template inside the Guard gem. # The template Guardfile must be located within the Gem at `lib/guard/guard-name/templates/Guardfile`. # # @param [String] name the name of the Guard # def self.init(name) if ::Guard::Dsl.guardfile_include?(name) ::Guard::UI.info "Guardfile already includes #{ name } guard" else content = File.read('Guardfile') guard = File.read("#{ ::Guard.locate_guard(name) }/lib/guard/#{ name }/templates/Guardfile") File.open('Guardfile', 'wb') do |f| f.puts(content) f.puts("") f.puts(guard) end ::Guard::UI.info "#{ name } guard added to Guardfile, feel free to edit it" end end # Call once when Guard starts. Please override initialize method to init stuff. # # @raise [:task_has_failed] when start has failed # @return [Object] the task result # def start end # Called when `stop|quit|exit|s|q|e + enter` is pressed (when Guard quits). # # @raise [:task_has_failed] when stop has failed # @return [Object] the task result # def stop end # Called when `reload|r|z + enter` is pressed. # This method should be mainly used for "reload" (really!) actions like reloading passenger/spork/bundler/... # # @raise [:task_has_failed] when reload has failed # @return [Object] the task result # def reload end # Called when just `enter` is pressed # This method should be principally used for long action like running all specs/tests/... # # @raise [:task_has_failed] when run_all has failed # @return [Object] the task result # def run_all end # Called on file(s) modifications that the Guard watches. # # @param [Array] paths the changes files or paths # @raise [:task_has_failed] when run_on_change has failed # @return [Object] the task result # def run_on_change(paths) end # Called on file(s) deletions that the Guard watches. # # @param [Array] paths the deleted files or paths # @raise [:task_has_failed] when run_on_change has failed # @return [Object] the task result # def run_on_deletion(paths) end end end