Skip to content

Commit

Permalink
Remove all empty methods from guard/guard
Browse files Browse the repository at this point in the history
Guard methods  need to be now implemented but no more overwritten like
before, logic move to the runner class
  • Loading branch information
thibaudgg committed May 20, 2012
1 parent bf2e0f5 commit 95d9cd1
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 167 deletions.
55 changes: 22 additions & 33 deletions lib/guard/guard.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,13 @@ 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.
# Guard will trigger the `start`, `stop`, `reload`, `run_all` and `run_on_changes`
# (`run_on_additions`, `run_on_modifications` and `run_on_removals`) task methods
# depending on user interaction and file modification.
#
# `run_on_changes` could be implemented to handle all the changes task case (additions,
# modifications, removals) in once, or each task can be implemented separatly with a
# specific behavior.
#
# 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
Expand Down Expand Up @@ -81,85 +86,69 @@ def to_s
# @raise [:task_has_failed] when start has failed
# @return [Object] the task result
#
def start
end
# 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
# 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
# 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
# def run_all
# end

# Default behavious on file(s) changes that the Guard watches.
#
# @param [Array<String>] paths the changes files or paths
# @raise [:task_has_failed] when run_on_change has failed
# @return [Object] the task result
#
def run_on_changes(paths)
raise NotImplementedError
end
# def run_on_changes(paths)
# end

# Called on file(s) additions that the Guard watches.
#
# @param [Array<String>] paths the changes files or paths
# @raise [:task_has_failed] when run_on_change has failed
# @return [Object] the task result
#
def run_on_additions(paths)
run_on_changes(paths)
end
# def run_on_additions(paths)
# end

# Called on file(s) modifications that the Guard watches.
#
# @param [Array<String>] paths the changes files or paths
# @raise [:task_has_failed] when run_on_change has failed
# @return [Object] the task result
#
def run_on_modifications(paths)
run_on_changes(paths)
end
# def run_on_modifications(paths)
# end

# Called on file(s) removals that the Guard watches.
#
# @param [Array<String>] paths the changes files or paths
# @raise [:task_has_failed] when run_on_change has failed
# @return [Object] the task result
#
def run_on_removals(paths)
run_on_changes(paths)
end

# @deprecated Use #run_on_modifications or #run_on_additions instead
#
# def run_on_change(paths)
# raise NotImplementedError
# end

# @deprecated Use #run_on_removals instead
#
# def run_on_deletion(paths)
# raise NotImplementedError
# def run_on_removals(paths)
# end

end
Expand Down
57 changes: 32 additions & 25 deletions lib/guard/runner.rb
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ def run(task, scopes = {})
end
end

MODIFICATION_TASKS = [:run_on_modifications, :run_on_changes, :run_on_change]
ADDITION_TASKS = [:run_on_additions, :run_on_changes, :run_on_change]
REMOVAL_TASKS = [:run_on_removals, :run_on_changes, :run_on_deletion]

# Runs the appropriate tasks on all registered guards
# based on the passed changes.
#
Expand All @@ -61,19 +65,11 @@ def run_on_changes(modified, added, removed)
added_paths = Watcher.match_files(guard, added)
removed_paths = Watcher.match_files(guard, removed)

if !modified_paths.empty? || !added_paths.empty? || !removed_paths.empty?
UI.clear
UI.clear if clearable?(guard, modified_paths, added_paths, removed_paths)

unless modified_paths.empty?
run_first_task_found(guard, [:run_on_modifications, :run_on_change], modified_paths)
end
unless added_paths.empty?
run_first_task_found(guard, [:run_on_additions, :run_on_change], added_paths)
end
unless removed_paths.empty?
run_first_task_found(guard, [:run_on_removals, :run_on_deletion], removed_paths)
end
end
run_first_task_found(guard, MODIFICATION_TASKS, modified_paths) unless modified_paths.empty?
run_first_task_found(guard, ADDITION_TASKS, added_paths) unless added_paths.empty?
run_first_task_found(guard, REMOVAL_TASKS, removed_paths) unless removed_paths.empty?
end
end

Expand All @@ -97,8 +93,8 @@ def run_supervised_task(guard, task, *args)
result
end

rescue NotImplementedError => ex
raise ex
rescue NoMethodError
# Do nothing
rescue Exception => ex
UI.error("#{ guard.class.name } failed to achieve its <#{ task.to_s }>, exception was:" +
"\n#{ ex.class }: #{ ex.message }\n#{ ex.backtrace.join("\n") }")
Expand Down Expand Up @@ -129,7 +125,7 @@ def self.stopping_symbol_for(guard)
group.options[:halt_on_fail] ? :no_catch : :task_has_failed
end

private
private

# Tries to run the first implemented task by a given guard
# from a collection of tasks.
Expand All @@ -139,16 +135,13 @@ def self.stopping_symbol_for(guard)
# @param [Object] task_param the param to pass to each task
#
def run_first_task_found(guard, tasks, task_param)
enum = tasks.to_enum

begin
task = enum.next
UI.debug "Trying to run #{ guard.class.name }##{ task.to_s } with #{ task_param.inspect }"
run_supervised_task(guard, task, task_param)
rescue StopIteration
# Do nothing
rescue NotImplementedError
retry
tasks.each do |task|
if guard.respond_to?(task)
run_supervised_task(guard, task, task_param)
break
else
UI.debug "Trying to run #{ guard.class.name }##{ task.to_s } with #{ task_param.inspect }"
end
end
end

Expand All @@ -175,5 +168,19 @@ def scoped_guards(scopes = {})
end
end

# Logic to know if the UI can be cleared or not in the run_on_changes method
# based on the guard and the changes.
#
# @param [Guard::Guard] guard the guard where run_on_changes is called
# @param [Array<String>] modified_paths the modified paths.
# @param [Array<String>] added_paths the added paths.
# @param [Array<String>] removed_paths the removed paths.
#
def clearable?(guard, modified_paths, added_paths, removed_paths)
(MODIFICATION_TASKS.any? { |task| guard.respond_to?(task) } && !modified_paths.empty?) ||
(ADDITION_TASKS.any? { |task| guard.respond_to?(task) } && !added_paths.empty?) ||
(REMOVAL_TASKS.any? { |task| guard.respond_to?(task) } && !removed_paths.empty?)
end

end
end
Loading

0 comments on commit 95d9cd1

Please sign in to comment.