guard 0.7.0.rc1 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
data/bin/guard CHANGED
@@ -1,6 +1,6 @@
1
- #!/usr/bin/env ruby
2
-
3
- require 'guard'
4
- require 'guard/cli'
5
-
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'guard'
4
+ require 'guard/cli'
5
+
6
6
  Guard::CLI.start
data/lib/guard.rb CHANGED
@@ -1,186 +1,186 @@
1
- module Guard
2
-
3
- autoload :UI, 'guard/ui'
4
- autoload :Dsl, 'guard/dsl'
5
- autoload :DslDescriber, 'guard/dsl_describer'
6
- autoload :Interactor, 'guard/interactor'
7
- autoload :Listener, 'guard/listener'
8
- autoload :Watcher, 'guard/watcher'
9
- autoload :Notifier, 'guard/notifier'
10
- autoload :Hook, 'guard/hook'
11
-
12
- class << self
13
- attr_accessor :options, :guards, :groups, :interactor, :listener
14
-
15
- # initialize this singleton
16
- def setup(options = {})
17
- @options = options
18
- @guards = []
19
- @groups = [:default]
20
- @interactor = Interactor.new
21
- @listener = Listener.select_and_init(@options[:watchdir] ? File.expand_path(@options[:watchdir]) : Dir.pwd)
22
-
23
- @options[:notify] && ENV["GUARD_NOTIFY"] != 'false' ? Notifier.turn_on : Notifier.turn_off
24
-
25
- UI.clear if @options[:clear]
26
- debug_command_execution if @options[:debug]
27
-
28
- self
29
- end
30
-
31
- def start(options = {})
32
- setup(options)
33
-
34
- Dsl.evaluate_guardfile(options)
35
-
36
- listener.on_change do |files|
37
- Dsl.reevaluate_guardfile if Watcher.match_guardfile?(files)
38
- listener.changed_files += files if Watcher.match_files?(guards, files)
39
- end
40
-
41
- UI.info "Guard is now watching at '#{listener.directory}'"
42
- guards.each { |guard| supervised_task(guard, :start) }
43
-
44
- interactor.start
45
- listener.start
46
- end
47
-
48
- def stop
49
- UI.info "Bye bye...", :reset => true
50
- listener.stop
51
- guards.each { |guard| supervised_task(guard, :stop) }
52
- abort
53
- end
54
-
55
- def reload
56
- run do
57
- guards.each { |guard| supervised_task(guard, :reload) }
58
- end
59
- end
60
-
61
- def run_all
62
- run do
63
- guards.each { |guard| supervised_task(guard, :run_all) }
64
- end
65
- end
66
-
67
- def pause
68
- if listener.locked
69
- UI.info "Un-paused files modification listening", :reset => true
70
- listener.clear_changed_files
71
- listener.unlock
72
- else
73
- UI.info "Paused files modification listening", :reset => true
74
- listener.lock
75
- end
76
- end
77
-
78
- def run_on_change(files)
79
- run do
80
- guards.each do |guard|
81
- paths = Watcher.match_files(guard, files)
82
- unless paths.empty?
83
- UI.debug "#{guard.class.name}#run_on_change with #{paths.inspect}"
84
- supervised_task(guard, :run_on_change, paths)
85
- end
86
- end
87
- end
88
- end
89
-
90
- def run
91
- listener.lock
92
- interactor.lock
93
- UI.clear if options[:clear]
94
- begin
95
- yield
96
- rescue Interrupt
97
- end
98
- interactor.unlock
99
- listener.unlock
100
- end
101
-
102
- # Let a guard execute its task but
103
- # fire it if his work leads to a system failure
104
- def supervised_task(guard, task_to_supervise, *args)
105
- guard.hook("#{task_to_supervise}_begin", *args)
106
- result = guard.send(task_to_supervise, *args)
107
- guard.hook("#{task_to_supervise}_end", result)
108
- result
109
- rescue Exception => ex
110
- UI.error("#{guard.class.name} failed to achieve its <#{task_to_supervise.to_s}>, exception was:" +
111
- "\n#{ex.class}: #{ex.message}\n#{ex.backtrace.join("\n")}")
112
- guards.delete guard
113
- UI.info("\n#{guard.class.name} has just been fired")
114
- return ex
115
- end
116
-
117
- def add_guard(name, watchers = [], callbacks = [], options = {})
118
- if name.to_sym == :ego
119
- UI.deprecation("Guard::Ego is now part of Guard. You can remove it from your Guardfile.")
120
- else
121
- guard_class = get_guard_class(name)
122
- callbacks.each { |callback| Hook.add_callback(callback[:listener], guard_class, callback[:events]) }
123
- @guards << guard_class.new(watchers, options)
124
- end
125
- end
126
-
127
- def add_group(name)
128
- @groups << name.to_sym unless name.nil?
129
- end
130
-
131
- def get_guard_class(name)
132
- name = name.to_s
133
- try_require = false
134
- const_name = name.downcase.gsub('-', '')
135
- begin
136
- require "guard/#{name.downcase}" if try_require
137
- self.const_get(self.constants.find { |c| c.to_s.downcase == const_name })
138
- rescue TypeError
139
- unless try_require
140
- try_require = true
141
- retry
142
- else
143
- UI.error "Could not find class Guard::#{const_name.capitalize}"
144
- end
145
- rescue LoadError => loadError
146
- UI.error "Could not load 'guard/#{name.downcase}' or find class Guard::#{const_name.capitalize}"
147
- UI.error loadError.to_s
148
- end
149
- end
150
-
151
- def locate_guard(name)
152
- if Gem::Version.create(Gem::VERSION) >= Gem::Version.create('1.8.0')
153
- Gem::Specification.find_by_name("guard-#{name}").full_gem_path
154
- else
155
- Gem.source_index.find_name("guard-#{name}").last.full_gem_path
156
- end
157
- rescue
158
- UI.error "Could not find 'guard-#{name}' gem path."
159
- end
160
-
161
- ##
162
- # Returns a list of guard Gem names installed locally.
163
- def guard_gem_names
164
- if Gem::Version.create(Gem::VERSION) >= Gem::Version.create('1.8.0')
165
- Gem::Specification.find_all.select { |x| x.name =~ /^guard-/ }
166
- else
167
- Gem.source_index.find_name(/^guard-/)
168
- end.map { |x| x.name.sub /^guard-/, '' }
169
- end
170
-
171
- def debug_command_execution
172
- Kernel.send(:alias_method, :original_system, :system)
173
- Kernel.send(:define_method, :system) do |command, *args|
174
- ::Guard::UI.debug "Command execution: #{command} #{args.join(' ')}"
175
- original_system command, *args
176
- end
177
-
178
- Kernel.send(:alias_method, :original_backtick, :"`")
179
- Kernel.send(:define_method, :"`") do |command|
180
- ::Guard::UI.debug "Command execution: #{command}"
181
- original_backtick command
182
- end
183
- end
184
-
185
- end
186
- end
1
+ module Guard
2
+
3
+ autoload :UI, 'guard/ui'
4
+ autoload :Dsl, 'guard/dsl'
5
+ autoload :DslDescriber, 'guard/dsl_describer'
6
+ autoload :Interactor, 'guard/interactor'
7
+ autoload :Listener, 'guard/listener'
8
+ autoload :Watcher, 'guard/watcher'
9
+ autoload :Notifier, 'guard/notifier'
10
+ autoload :Hook, 'guard/hook'
11
+
12
+ class << self
13
+ attr_accessor :options, :guards, :groups, :interactor, :listener
14
+
15
+ # initialize this singleton
16
+ def setup(options = {})
17
+ @options = options
18
+ @guards = []
19
+ @groups = [:default]
20
+ @interactor = Interactor.new
21
+ @listener = Listener.select_and_init(@options[:watchdir] ? File.expand_path(@options[:watchdir]) : Dir.pwd)
22
+
23
+ @options[:notify] && ENV["GUARD_NOTIFY"] != 'false' ? Notifier.turn_on : Notifier.turn_off
24
+
25
+ UI.clear if @options[:clear]
26
+ debug_command_execution if @options[:debug]
27
+
28
+ self
29
+ end
30
+
31
+ def start(options = {})
32
+ setup(options)
33
+
34
+ Dsl.evaluate_guardfile(options)
35
+
36
+ listener.on_change do |files|
37
+ Dsl.reevaluate_guardfile if Watcher.match_guardfile?(files)
38
+ listener.changed_files += files if Watcher.match_files?(guards, files)
39
+ end
40
+
41
+ UI.info "Guard is now watching at '#{listener.directory}'"
42
+ guards.each { |guard| supervised_task(guard, :start) }
43
+
44
+ interactor.start
45
+ listener.start
46
+ end
47
+
48
+ def stop
49
+ UI.info "Bye bye...", :reset => true
50
+ listener.stop
51
+ guards.each { |guard| supervised_task(guard, :stop) }
52
+ abort
53
+ end
54
+
55
+ def reload
56
+ run do
57
+ guards.each { |guard| supervised_task(guard, :reload) }
58
+ end
59
+ end
60
+
61
+ def run_all
62
+ run do
63
+ guards.each { |guard| supervised_task(guard, :run_all) }
64
+ end
65
+ end
66
+
67
+ def pause
68
+ if listener.locked
69
+ UI.info "Un-paused files modification listening", :reset => true
70
+ listener.clear_changed_files
71
+ listener.unlock
72
+ else
73
+ UI.info "Paused files modification listening", :reset => true
74
+ listener.lock
75
+ end
76
+ end
77
+
78
+ def run_on_change(files)
79
+ run do
80
+ guards.each do |guard|
81
+ paths = Watcher.match_files(guard, files)
82
+ unless paths.empty?
83
+ UI.debug "#{guard.class.name}#run_on_change with #{paths.inspect}"
84
+ supervised_task(guard, :run_on_change, paths)
85
+ end
86
+ end
87
+ end
88
+ end
89
+
90
+ def run
91
+ listener.lock
92
+ interactor.lock
93
+ UI.clear if options[:clear]
94
+ begin
95
+ yield
96
+ rescue Interrupt
97
+ end
98
+ interactor.unlock
99
+ listener.unlock
100
+ end
101
+
102
+ # Let a guard execute its task but
103
+ # fire it if his work leads to a system failure
104
+ def supervised_task(guard, task_to_supervise, *args)
105
+ guard.hook("#{task_to_supervise}_begin", *args)
106
+ result = guard.send(task_to_supervise, *args)
107
+ guard.hook("#{task_to_supervise}_end", result)
108
+ result
109
+ rescue Exception => ex
110
+ UI.error("#{guard.class.name} failed to achieve its <#{task_to_supervise.to_s}>, exception was:" +
111
+ "\n#{ex.class}: #{ex.message}\n#{ex.backtrace.join("\n")}")
112
+ guards.delete guard
113
+ UI.info("\n#{guard.class.name} has just been fired")
114
+ return ex
115
+ end
116
+
117
+ def add_guard(name, watchers = [], callbacks = [], options = {})
118
+ if name.to_sym == :ego
119
+ UI.deprecation("Guard::Ego is now part of Guard. You can remove it from your Guardfile.")
120
+ else
121
+ guard_class = get_guard_class(name)
122
+ callbacks.each { |callback| Hook.add_callback(callback[:listener], guard_class, callback[:events]) }
123
+ @guards << guard_class.new(watchers, options)
124
+ end
125
+ end
126
+
127
+ def add_group(name)
128
+ @groups << name.to_sym unless name.nil?
129
+ end
130
+
131
+ def get_guard_class(name)
132
+ name = name.to_s
133
+ try_require = false
134
+ const_name = name.downcase.gsub('-', '')
135
+ begin
136
+ require "guard/#{name.downcase}" if try_require
137
+ self.const_get(self.constants.find { |c| c.to_s.downcase == const_name })
138
+ rescue TypeError
139
+ unless try_require
140
+ try_require = true
141
+ retry
142
+ else
143
+ UI.error "Could not find class Guard::#{const_name.capitalize}"
144
+ end
145
+ rescue LoadError => loadError
146
+ UI.error "Could not load 'guard/#{name.downcase}' or find class Guard::#{const_name.capitalize}"
147
+ UI.error loadError.to_s
148
+ end
149
+ end
150
+
151
+ def locate_guard(name)
152
+ if Gem::Version.create(Gem::VERSION) >= Gem::Version.create('1.8.0')
153
+ Gem::Specification.find_by_name("guard-#{name}").full_gem_path
154
+ else
155
+ Gem.source_index.find_name("guard-#{name}").last.full_gem_path
156
+ end
157
+ rescue
158
+ UI.error "Could not find 'guard-#{name}' gem path."
159
+ end
160
+
161
+ ##
162
+ # Returns a list of guard Gem names installed locally.
163
+ def guard_gem_names
164
+ if Gem::Version.create(Gem::VERSION) >= Gem::Version.create('1.8.0')
165
+ Gem::Specification.find_all.select { |x| x.name =~ /^guard-/ }
166
+ else
167
+ Gem.source_index.find_name(/^guard-/)
168
+ end.map { |x| x.name.sub /^guard-/, '' }
169
+ end
170
+
171
+ def debug_command_execution
172
+ Kernel.send(:alias_method, :original_system, :system)
173
+ Kernel.send(:define_method, :system) do |command, *args|
174
+ ::Guard::UI.debug "Command execution: #{command} #{args.join(' ')}"
175
+ original_system command, *args
176
+ end
177
+
178
+ Kernel.send(:alias_method, :original_backtick, :"`")
179
+ Kernel.send(:define_method, :"`") do |command|
180
+ ::Guard::UI.debug "Command execution: #{command}"
181
+ original_backtick command
182
+ end
183
+ end
184
+
185
+ end
186
+ end
data/lib/guard/cli.rb CHANGED
@@ -1,90 +1,90 @@
1
- require 'thor'
2
- require 'guard/version'
3
-
4
- module Guard
5
- class CLI < Thor
6
- default_task :start
7
-
8
- method_option :clear, :type => :boolean, :default => false, :aliases => '-c', :banner => "Auto clear shell before each change/run_all/reload"
9
- method_option :notify, :type => :boolean, :default => true, :aliases => '-n', :banner => "Notifications feature (growl/libnotify)"
10
- method_option :debug, :type => :boolean, :default => false, :aliases => '-d', :banner => "Print debug messages"
11
- method_option :group, :type => :array, :default => [], :aliases => '-g', :banner => "Run only the passed groups"
12
- method_option :watchdir, :type => :string, :aliases => '-w', :banner => "Specify the directory to watch"
13
- method_option :guardfile, :type => :string, :aliases => '-G', :banner => "Specify a Guardfile"
14
-
15
- desc "start", "Starts Guard"
16
- def start
17
- ::Guard.start(options)
18
- end
19
-
20
- desc "list", "Lists guards that can be used with init"
21
- def list
22
- ::Guard::DslDescriber.evaluate_guardfile(options)
23
- installed = []
24
- ::Guard::DslDescriber.guardfile_structure.each do |group|
25
- group[:guards].each {|x| installed << x[:name]} if group[:guards]
26
- end
27
-
28
- ::Guard::UI.info "Available guards:"
29
- ::Guard::guard_gem_names.sort.each do |name|
30
- if installed.include? name
31
- ::Guard::UI.info " #{name} *"
32
- else
33
- ::Guard::UI.info " #{name}"
34
- end
35
- end
36
- ::Guard::UI.info ' '
37
- ::Guard::UI.info "See also https://github.com/guard/guard/wiki/List-of-available-Guards"
38
- ::Guard::UI.info "* denotes ones already in your Guardfile"
39
- end
40
-
41
- desc "version", "Prints Guard's version"
42
- def version
43
- ::Guard::UI.info "Guard version #{Guard::VERSION}"
44
- end
45
- map %w(-v --version) => :version
46
-
47
- desc "init [GUARD]", "Generates a Guardfile into the current working directory, or insert the given GUARD in an existing Guardfile"
48
- def init(guard_name = nil)
49
- if !File.exist?("Guardfile")
50
- puts "Writing new Guardfile to #{Dir.pwd}/Guardfile"
51
- FileUtils.cp(File.expand_path('../templates/Guardfile', __FILE__), 'Guardfile')
52
- elsif guard_name.nil?
53
- ::Guard::UI.error "Guardfile already exists at #{Dir.pwd}/Guardfile"
54
- exit 1
55
- end
56
-
57
- if guard_name
58
- guard_class = ::Guard.get_guard_class(guard_name)
59
- guard_class.init(guard_name)
60
- end
61
- end
62
-
63
- desc "show", "Show all defined Guards and their options"
64
- def show
65
- ::Guard::DslDescriber.evaluate_guardfile(options)
66
-
67
- ::Guard::DslDescriber.guardfile_structure.each do |group|
68
- if !group[:guards].empty?
69
- if group[:group]
70
- ::Guard::UI.info "Group #{group[:group]}:"
71
- else
72
- ::Guard::UI.info "(global):"
73
- end
74
-
75
- group[:guards].each do |guard|
76
- line = " #{guard[:name]}"
77
-
78
- if !guard[:options].empty?
79
- line += ": #{guard[:options].collect { |k, v| "#{k} => #{v.inspect}" }.join(", ")}"
80
- end
81
- ::Guard::UI.info line
82
- end
83
- end
84
- end
85
-
86
- ::Guard::UI.info ''
87
- end
88
- map %w(-T) => :show
89
- end
90
- end
1
+ require 'thor'
2
+ require 'guard/version'
3
+
4
+ module Guard
5
+ class CLI < Thor
6
+ default_task :start
7
+
8
+ method_option :clear, :type => :boolean, :default => false, :aliases => '-c', :banner => "Auto clear shell before each change/run_all/reload"
9
+ method_option :notify, :type => :boolean, :default => true, :aliases => '-n', :banner => "Notifications feature (growl/libnotify)"
10
+ method_option :debug, :type => :boolean, :default => false, :aliases => '-d', :banner => "Print debug messages"
11
+ method_option :group, :type => :array, :default => [], :aliases => '-g', :banner => "Run only the passed groups"
12
+ method_option :watchdir, :type => :string, :aliases => '-w', :banner => "Specify the directory to watch"
13
+ method_option :guardfile, :type => :string, :aliases => '-G', :banner => "Specify a Guardfile"
14
+
15
+ desc "start", "Starts Guard"
16
+ def start
17
+ ::Guard.start(options)
18
+ end
19
+
20
+ desc "list", "Lists guards that can be used with init"
21
+ def list
22
+ ::Guard::DslDescriber.evaluate_guardfile(options)
23
+ installed = []
24
+ ::Guard::DslDescriber.guardfile_structure.each do |group|
25
+ group[:guards].each {|x| installed << x[:name]} if group[:guards]
26
+ end
27
+
28
+ ::Guard::UI.info "Available guards:"
29
+ ::Guard::guard_gem_names.sort.each do |name|
30
+ if installed.include? name
31
+ ::Guard::UI.info " #{name} *"
32
+ else
33
+ ::Guard::UI.info " #{name}"
34
+ end
35
+ end
36
+ ::Guard::UI.info ' '
37
+ ::Guard::UI.info "See also https://github.com/guard/guard/wiki/List-of-available-Guards"
38
+ ::Guard::UI.info "* denotes ones already in your Guardfile"
39
+ end
40
+
41
+ desc "version", "Prints Guard's version"
42
+ def version
43
+ ::Guard::UI.info "Guard version #{Guard::VERSION}"
44
+ end
45
+ map %w(-v --version) => :version
46
+
47
+ desc "init [GUARD]", "Generates a Guardfile into the current working directory, or insert the given GUARD in an existing Guardfile"
48
+ def init(guard_name = nil)
49
+ if !File.exist?("Guardfile")
50
+ puts "Writing new Guardfile to #{Dir.pwd}/Guardfile"
51
+ FileUtils.cp(File.expand_path('../templates/Guardfile', __FILE__), 'Guardfile')
52
+ elsif guard_name.nil?
53
+ ::Guard::UI.error "Guardfile already exists at #{Dir.pwd}/Guardfile"
54
+ exit 1
55
+ end
56
+
57
+ if guard_name
58
+ guard_class = ::Guard.get_guard_class(guard_name)
59
+ guard_class.init(guard_name)
60
+ end
61
+ end
62
+
63
+ desc "show", "Show all defined Guards and their options"
64
+ def show
65
+ ::Guard::DslDescriber.evaluate_guardfile(options)
66
+
67
+ ::Guard::DslDescriber.guardfile_structure.each do |group|
68
+ if !group[:guards].empty?
69
+ if group[:group]
70
+ ::Guard::UI.info "Group #{group[:group]}:"
71
+ else
72
+ ::Guard::UI.info "(global):"
73
+ end
74
+
75
+ group[:guards].each do |guard|
76
+ line = " #{guard[:name]}"
77
+
78
+ if !guard[:options].empty?
79
+ line += ": #{guard[:options].collect { |k, v| "#{k} => #{v.inspect}" }.join(", ")}"
80
+ end
81
+ ::Guard::UI.info line
82
+ end
83
+ end
84
+ end
85
+
86
+ ::Guard::UI.info ''
87
+ end
88
+ map %w(-T) => :show
89
+ end
90
+ end