guard 0.5.1 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,25 @@
1
+ ## 0.6.0 - August 13, 2011
2
+
3
+ ### Bugs fixes:
4
+
5
+ - Pull request [#107](https://github.com/guard/guard/pull/107): Small spelling fix. ([@dnagir][])
6
+ - Dir.glob now ignores files that don't need to be watched. ([@rymai][])
7
+
8
+ ### New features
9
+
10
+ - Pull request [#112](https://github.com/guard/guard/pull/112): Add `list` command to CLI. ([@docwhat][])
11
+
12
+ ### Improvements
13
+
14
+ - Pull request [#99](https://github.com/guard/guard/pull/99): [OS X] Switch from growl gem to growl_notify gem. ([@johnbintz][])
15
+ - Pull request [#115](https://github.com/guard/guard/pull/115): [Linux] Add ':transient => true' to default libnotify options. ([@zonque][])
16
+ - Pull request [#95](https://github.com/guard/guard/pull/95): Output system commands and options to be executed when in debug mode. ([@uk-ar][] and [@netzpirat][])
17
+ - `Guard::Dsl.revaluate_guardfile` has been renamed to `Guard::Dsl.reevaluate_guardfile`. ([@rymai][])
18
+ - New CLI options: ([@nestegg][])
19
+ - `watchdir`/`-w` to specify the directory in which Guard should watch for changes,
20
+ - `guardfile`/`-G` to specify an alternate location for the Guardfile to use.
21
+ - Pull request [#90](https://github.com/guard/guard/pull/90): Refactoring of color handling in the `Guard::UI`. ([@stereobooster][])
22
+
1
23
  ## 0.5.1 - July 2, 2011
2
24
 
3
25
  ### Bugs fixes:
@@ -6,12 +28,12 @@
6
28
 
7
29
  ## 0.5.0 - July 2, 2011
8
30
 
9
- ## New features
31
+ ### New features
10
32
 
11
33
  - Guard::Ego is now part of Guard, so Guardfile is automagically re-evaluated when modified. ([@thibaudgg][])
12
34
  - Pull request [#91](https://github.com/guard/guard/pull/91): Show Guards in Guardfile with the `guard -T`. ([@johnbintz][])
13
35
 
14
- ## Improvements
36
+ ### Improvements
15
37
 
16
38
  - Issue [#98](https://github.com/guard/guard/issues/98): Multiple calls per watch event on linux with rb-inotify. ([@jeffutter][] & [@netzpirat][])
17
39
  - Pull request [#94](https://github.com/guard/guard/pull/94): Show backtrace in terminal when a problem with a watch action occurs. ([@capotej][])
@@ -170,8 +192,10 @@
170
192
 
171
193
  [@anithri]: https://github.com/anithri
172
194
  [@brainopia]: https://github.com/brainopia
195
+ [@bronson]: https://github.com/bronson
173
196
  [@capotej]: https://github.com/capotej
174
197
  [@chrisberkhout]: https://github.com/chrisberkhout
198
+ [@dnagir]: https://github.com/dnagir
175
199
  [@etehtsea]: https://github.com/etehtsea
176
200
  [@fnichol]: https://github.com/fnichol
177
201
  [@Gazer]: https://github.com/Gazer
@@ -184,6 +208,7 @@
184
208
  [@koshigoe]: https://github.com/koshigoe
185
209
  [@mcmire]: https://github.com/mcmire
186
210
  [@mislav]: https://github.com/mislav
211
+ [@nestegg]: https://github.com/nestegg
187
212
  [@netzpirat]: https://github.com/netzpirat
188
213
  [@nicksieger]: https://github.com/nicksieger
189
214
  [@niklas]: https://github.com/niklas
@@ -196,6 +221,8 @@
196
221
  [@thierryhenrio]: https://github.com/thierryhenrio
197
222
  [@tinogomes]: https://github.com/tinogomes
198
223
  [@tpope]: https://github.com/tpope
224
+ [@uk-ar]: https://github.com/uk-ar
199
225
  [@veged]: https://github.com/veged
200
226
  [@wereHamster]: https://github.com/wereHamster
201
227
  [@yannlugrin]: https://github.com/yannlugrin
228
+ [@zonque]: https://github.com/zonque
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- Guard [![Build Status](http://travis-ci.org/guard/guard.png)](http://travis-ci.org/guard/guard)
1
+ Guard [![Build Status](https://secure.travis-ci.org/guard/guard.png)](http://travis-ci.org/guard/guard)
2
2
  =====
3
3
 
4
4
  Guard is a command line tool that easily handle events on files modifications.
@@ -50,17 +50,17 @@ Install the rb-fsevent gem for [FSEvent](http://en.wikipedia.org/wiki/FSEvents)
50
50
  $ gem install rb-fsevent
51
51
  ```
52
52
 
53
- Install the Growl gem if you want notification support:
53
+ Install the growl_notify gem if you want notification support:
54
54
 
55
55
  ``` bash
56
- $ gem install growl
56
+ $ gem install growl_notify
57
57
  ```
58
58
 
59
- And add them to your Gemfile:
59
+ And add it to your Gemfile:
60
60
 
61
61
  ``` ruby
62
62
  gem 'rb-fsevent'
63
- gem 'growl'
63
+ gem 'growl_notify'
64
64
  ```
65
65
 
66
66
  ### On Linux
@@ -92,6 +92,12 @@ Install the rb-fchange gem for [Directory Change Notification](http://msdn.micro
92
92
  $ gem install rb-fchange
93
93
  ```
94
94
 
95
+ Install the win32console gem if you want colors in your terminal:
96
+
97
+ ``` bash
98
+ $ gem install win32console
99
+ ```
100
+
95
101
  Install the Notifu gem if you want notification support:
96
102
 
97
103
  ``` bash
@@ -125,7 +131,7 @@ Guard will look for a Guardfile in your current directory. If it does not find o
125
131
  Command line options
126
132
  --------------------
127
133
 
128
- ### `--clear` option
134
+ ### `-c`/`--clear` option
129
135
 
130
136
  Shell can be cleared after each change:
131
137
 
@@ -134,7 +140,7 @@ $ guard --clear
134
140
  $ guard -c # shortcut
135
141
  ```
136
142
 
137
- ### `--notify` option
143
+ ### `-n`/`--notify` option
138
144
 
139
145
  Notifications (growl/libnotify) can be disabled:
140
146
 
@@ -145,7 +151,7 @@ $ guard -n f # shortcut
145
151
 
146
152
  Notifications can also be disabled globally by setting a `GUARD_NOTIFY` environment variable to `false`
147
153
 
148
- ### `--group` option
154
+ ### `-g`/`--group` option
149
155
 
150
156
  Only certain guards groups can be run (see the Guardfile DSL below for creating groups):
151
157
 
@@ -154,7 +160,7 @@ $ guard --group group_name another_group_name
154
160
  $ guard -g group_name another_group_name # shortcut
155
161
  ```
156
162
 
157
- ### `--debug` option
163
+ ### `-d`/`--debug` option
158
164
 
159
165
  Guard can be run in debug mode:
160
166
 
@@ -163,6 +169,24 @@ $ guard --debug
163
169
  $ guard -d # shortcut
164
170
  ```
165
171
 
172
+ ### `-w`/`--watchdir` option
173
+
174
+ Guard can watch in any directory (instead of the current directory):
175
+
176
+ ``` bash
177
+ $ guard --watchdir ~/your/fancy/project
178
+ $ guard -w ~/your/fancy/project # shortcut
179
+ ```
180
+
181
+ ### `-G`/`--guardfile` option
182
+
183
+ Guard can use a Guardfile not located in the current directory:
184
+
185
+ ``` bash
186
+ $ guard --guardfile ~/.your_global_guardfile
187
+ $ guard -G ~/.your_global_guardfile # shortcut
188
+ ```
189
+
166
190
  An exhaustive list of options is available with:
167
191
 
168
192
  ``` bash
@@ -193,6 +217,12 @@ Add it to your Gemfile (inside the `development` group):
193
217
  gem '<guard-name>'
194
218
  ```
195
219
 
220
+ You can list all guards installed on your system with:
221
+
222
+ ``` bash
223
+ $ guard list
224
+ ```
225
+
196
226
  Insert default guard's definition to your Guardfile by running this command:
197
227
 
198
228
  ``` bash
@@ -284,7 +314,7 @@ You can list the defined groups and guards for the current Guardfile from the co
284
314
  shell
285
315
  Group backend:
286
316
  bundler
287
- rspec: cli => "--color --format doc'
317
+ rspec: cli => "--color --format doc"
288
318
  Group frontend:
289
319
  coffeescript: output => "public/javascripts/compiled"
290
320
  livereload
@@ -14,28 +14,31 @@ module Guard
14
14
  # initialize this singleton
15
15
  def setup(options = {})
16
16
  @options = options
17
- @listener = Listener.select_and_init
17
+ @listener = Listener.select_and_init(@options[:watchdir] ? File.expand_path(@options[:watchdir]) : Dir.pwd)
18
18
  @guards = []
19
19
 
20
20
  @options[:notify] && ENV["GUARD_NOTIFY"] != 'false' ? Notifier.turn_on : Notifier.turn_off
21
21
 
22
+ UI.clear if @options[:clear]
23
+ debug_command_execution if @options[:debug]
24
+
22
25
  self
23
26
  end
24
27
 
25
28
  def start(options = {})
26
- UI.clear if options[:clear]
29
+ Interactor.init_signal_traps
30
+
27
31
  setup(options)
28
32
 
29
- Interactor.init_signal_traps
30
33
  Dsl.evaluate_guardfile(options)
31
34
 
32
35
  listener.on_change do |files|
33
- Dsl.revaluate_guardfile if Watcher.match_guardfile?(files)
36
+ Dsl.reevaluate_guardfile if Watcher.match_guardfile?(files)
34
37
 
35
38
  run { run_on_change_for_all_guards(files) } if Watcher.match_files?(guards, files)
36
39
  end
37
40
 
38
- UI.info "Guard is now watching at '#{Dir.pwd}'"
41
+ UI.info "Guard is now watching at '#{listener.directory}'"
39
42
  guards.each { |guard| supervised_task(guard, :start) }
40
43
  listener.start
41
44
  end
@@ -43,12 +46,14 @@ module Guard
43
46
  def run_on_change_for_all_guards(files)
44
47
  guards.each do |guard|
45
48
  paths = Watcher.match_files(guard, files)
46
- supervised_task(guard, :run_on_change, paths) unless paths.empty?
49
+ unless paths.empty?
50
+ UI.debug "#{guard.class.name}#run_on_change with #{paths.inspect}"
51
+ supervised_task(guard, :run_on_change, paths)
52
+ end
47
53
  end
48
54
 
49
55
  # Reparse the whole directory to catch new files modified during the guards run
50
- new_modified_files = listener.modified_files([Dir.pwd + '/'], :all => true)
51
- listener.update_last_event
56
+ new_modified_files = listener.modified_files([listener.directory], :all => true)
52
57
  if !new_modified_files.empty? && Watcher.match_files?(guards, new_modified_files)
53
58
  run { run_on_change_for_all_guards(new_modified_files) }
54
59
  end
@@ -98,8 +103,9 @@ module Guard
98
103
  else
99
104
  UI.error "Could not find class Guard::#{const_name.capitalize}"
100
105
  end
101
- rescue LoadError
106
+ rescue LoadError => loadError
102
107
  UI.error "Could not load 'guard/#{name.downcase}' or find class Guard::#{const_name.capitalize}"
108
+ UI.error loadError.to_s
103
109
  end
104
110
  end
105
111
 
@@ -113,5 +119,29 @@ module Guard
113
119
  UI.error "Could not find 'guard-#{name}' gem path."
114
120
  end
115
121
 
122
+ ##
123
+ # Returns a list of guard Gem names installed locally.
124
+ def guard_gem_names
125
+ if Gem::Version.create(Gem::VERSION) >= Gem::Version.create('1.8.0')
126
+ Gem::Specification.find_all.select { |x| x.name =~ /^guard-/ }
127
+ else
128
+ Gem.source_index.find_name(/^guard-/)
129
+ end.map { |x| x.name.sub /^guard-/, '' }
130
+ end
131
+
132
+ def debug_command_execution
133
+ Kernel.send(:alias_method, :original_system, :system)
134
+ Kernel.send(:define_method, :system) do |command, *args|
135
+ ::Guard::UI.debug "Command execution: #{command} #{args.join(' ')}"
136
+ original_system command, *args
137
+ end
138
+
139
+ Kernel.send(:alias_method, :original_backtick, :"`")
140
+ Kernel.send(:define_method, :"`") do |command|
141
+ ::Guard::UI.debug "Command execution: #{command}"
142
+ original_backtick command
143
+ end
144
+ end
145
+
116
146
  end
117
147
  end
@@ -5,16 +5,39 @@ module Guard
5
5
  class CLI < Thor
6
6
  default_task :start
7
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"
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"
12
14
 
13
15
  desc "start", "Starts Guard"
14
16
  def start
15
17
  ::Guard.start(options)
16
18
  end
17
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
+
18
41
  desc "version", "Prints Guard's version"
19
42
  def version
20
43
  ::Guard::UI.info "Guard version #{Guard::VERSION}"
@@ -12,7 +12,7 @@ module Guard
12
12
  UI.error "No guards found in Guardfile, please add at least one." if !::Guard.guards.nil? && ::Guard.guards.empty?
13
13
  end
14
14
 
15
- def revaluate_guardfile
15
+ def reevaluate_guardfile
16
16
  ::Guard.guards.clear
17
17
  Dsl.evaluate_guardfile(@@options)
18
18
  msg = "Guardfile has been re-evaluated."
@@ -45,11 +45,11 @@ module Guard
45
45
 
46
46
  def fetch_guardfile_contents
47
47
  # TODO: do we need .rc file interaction?
48
- if @@options.has_key?(:guardfile_contents)
48
+ if @@options[:guardfile_contents]
49
49
  UI.info "Using inline Guardfile."
50
50
  @@options[:guardfile_path] = 'Inline Guardfile'
51
51
 
52
- elsif @@options.has_key?(:guardfile)
52
+ elsif @@options[:guardfile]
53
53
  if File.exist?(@@options[:guardfile])
54
54
  read_guardfile(@@options[:guardfile])
55
55
  UI.info "Using Guardfile at #{@@options[:guardfile]}."
@@ -10,7 +10,7 @@ module Guard
10
10
  # Guardfile template needed inside guard gem
11
11
  def self.init(name)
12
12
  if ::Guard::Dsl.guardfile_include?(name)
13
- ::Guard::UI.info "Guardfile already include #{name} guard"
13
+ ::Guard::UI.info "Guardfile already includes #{name} guard"
14
14
  else
15
15
  content = File.read('Guardfile')
16
16
  guard = File.read("#{::Guard.locate_guard(name)}/lib/guard/#{name}/templates/Guardfile")
@@ -37,7 +37,7 @@ module Guard
37
37
  stop
38
38
  end
39
39
  else
40
- UI.info "Your system doesn't support INT signal, so Ctrl-C (stop) won't work"
40
+ UI.info "Your system doesn't support INT signal, so Ctrl-C (Stop) won't work"
41
41
  end
42
42
 
43
43
  # Reload (Ctrl-Z)
@@ -9,7 +9,8 @@ module Guard
9
9
  autoload :Polling, 'guard/listeners/polling'
10
10
 
11
11
  class Listener
12
- attr_reader :last_event, :sha1_checksums_hash, :directory, :callback
12
+
13
+ attr_reader :directory
13
14
 
14
15
  def self.select_and_init(*a)
15
16
  if mac? && Darwin.usable?
@@ -25,14 +26,14 @@ module Guard
25
26
  end
26
27
 
27
28
  def initialize(directory=Dir.pwd, options={})
28
- @directory = directory.to_s
29
+ @directory = directory.to_s
29
30
  @sha1_checksums_hash = {}
30
- @relativate_paths = options.fetch(:relativate_paths, true)
31
+ @relativize_paths = options.fetch(:relativize_paths, true)
31
32
  update_last_event
32
33
  end
33
34
 
34
35
  def start
35
- watch directory
36
+ watch(@directory)
36
37
  end
37
38
 
38
39
  def stop
@@ -46,9 +47,10 @@ module Guard
46
47
  @last_event = Time.now
47
48
  end
48
49
 
49
- def modified_files(dirs, options = {})
50
+ def modified_files(dirs, options={})
50
51
  files = potentially_modified_files(dirs, options).select { |path| file_modified?(path) }
51
- relativate_paths files
52
+ update_last_event
53
+ relativize_paths(files)
52
54
  end
53
55
 
54
56
  def worker
@@ -61,35 +63,48 @@ module Guard
61
63
  end
62
64
 
63
65
  def all_files
64
- potentially_modified_files [directory + '/'], :all => true
66
+ potentially_modified_files([@directory], :all => true)
65
67
  end
66
68
 
67
69
  # scopes all given paths to the current #directory
68
- def relativate_paths(paths)
69
- return paths unless relativate_paths?
70
+ def relativize_paths(paths)
71
+ return paths unless relativize_paths?
70
72
  paths.map do |path|
71
- path.gsub(%r~^#{directory}/~, '')
73
+ path.gsub(%r{^#{@directory}/}, '')
72
74
  end
73
75
  end
74
76
 
75
- attr_writer :relativate_paths
76
- def relativate_paths?
77
- !!@relativate_paths
77
+ def relativize_paths?
78
+ !!@relativize_paths
78
79
  end
79
80
 
80
81
  private
81
82
 
82
- def potentially_modified_files(dirs, options = {})
83
- match = options[:all] ? "**/*" : "*"
84
- Dir.glob(dirs.map { |dir| "#{dir}#{match}" }, File::FNM_DOTMATCH).select { |file| File.file?(file) }
83
+ def potentially_modified_files(dirs, options={})
84
+ paths = Dir.glob(dirs.map { |d| "#{d.sub(%r{/+$}, '')}/*" }, File::FNM_DOTMATCH).reject do |path|
85
+ %w[. .. .bundle .git log tmp vendor].include?(File.basename(path))
86
+ end
87
+
88
+ if options[:all]
89
+ paths.inject([]) do |array, path|
90
+ if File.file?(path)
91
+ array << path
92
+ else
93
+ array += Dir.glob("#{path}/**/*", File::FNM_DOTMATCH).select { |p| File.file?(p) }
94
+ end
95
+ array
96
+ end
97
+ else
98
+ paths.select { |path| File.file?(path) }
99
+ end
85
100
  end
86
101
 
87
102
  # Depending on the filesystem, mtime is probably only precise to the second, so round
88
103
  # both values down to the second for the comparison.
89
104
  def file_modified?(path)
90
- if File.mtime(path).to_i == last_event.to_i
105
+ if File.mtime(path).to_i == @last_event.to_i
91
106
  file_content_modified?(path, sha1_checksum(path))
92
- elsif File.mtime(path).to_i > last_event.to_i
107
+ elsif File.mtime(path).to_i > @last_event.to_i
93
108
  set_sha1_checksums_hash(path, sha1_checksum(path))
94
109
  true
95
110
  end
@@ -98,7 +113,7 @@ module Guard
98
113
  end
99
114
 
100
115
  def file_content_modified?(path, sha1_checksum)
101
- if sha1_checksums_hash[path] != sha1_checksum
116
+ if @sha1_checksums_hash[path] != sha1_checksum
102
117
  set_sha1_checksums_hash(path, sha1_checksum)
103
118
  true
104
119
  else
@@ -1,6 +1,5 @@
1
1
  module Guard
2
2
  class Darwin < Listener
3
- attr_reader :fsevent
4
3
 
5
4
  def initialize(*)
6
5
  super
@@ -13,12 +12,12 @@ module Guard
13
12
 
14
13
  def start
15
14
  super
16
- fsevent.run
15
+ worker.run
17
16
  end
18
17
 
19
18
  def stop
20
19
  super
21
- fsevent.stop
20
+ worker.stop
22
21
  end
23
22
 
24
23
  def self.usable?
@@ -38,10 +37,9 @@ module Guard
38
37
  private
39
38
 
40
39
  def watch(directory)
41
- worker.watch directory do |modified_dirs|
40
+ worker.watch(directory) do |modified_dirs|
42
41
  files = modified_files(modified_dirs)
43
- update_last_event
44
- callback.call(files)
42
+ @callback.call(files) unless files.empty?
45
43
  end
46
44
  end
47
45
 
@@ -1,6 +1,5 @@
1
1
  module Guard
2
2
  class Linux < Listener
3
- attr_reader :inotify, :files, :latency
4
3
 
5
4
  def initialize(*)
6
5
  super
@@ -19,7 +18,7 @@ module Guard
19
18
  def stop
20
19
  super
21
20
  @stop = true
22
- sleep latency
21
+ sleep(@latency)
23
22
  end
24
23
 
25
24
  def self.usable?
@@ -59,15 +58,14 @@ module Guard
59
58
  def watch_change
60
59
  @watch_change = true
61
60
  until @stop
62
- if RbConfig::CONFIG['build'] =~ /java/ || IO.select([inotify.to_io], [], [], latency)
61
+ if RbConfig::CONFIG['build'] =~ /java/ || IO.select([worker.to_io], [], [], @latency)
63
62
  break if @stop
64
63
 
65
- sleep latency
66
- inotify.process
64
+ sleep(@latency)
65
+ worker.process
67
66
 
68
- modified_files = modified_files(files.shift(files.size).map{|f| File.dirname(f) + '/' }.uniq)
69
- update_last_event
70
- callback.call(modified_files) unless modified_files.empty?
67
+ files = modified_files(@files.shift(@files.size).map { |f| File.dirname(f) }.uniq)
68
+ @callback.call(files) unless files.empty?
71
69
  end
72
70
  end
73
71
  @watch_change = false
@@ -1,6 +1,5 @@
1
1
  module Guard
2
2
  class Polling < Listener
3
- attr_reader :latency
4
3
 
5
4
  def initialize(*)
6
5
  super
@@ -23,10 +22,9 @@ module Guard
23
22
  def watch_change
24
23
  until @stop
25
24
  start = Time.now.to_f
26
- files = modified_files([Dir.pwd + '/'], :all => true)
27
- update_last_event
28
- callback.call(relativate_paths(files)) unless files.empty?
29
- nap_time = latency - (Time.now.to_f - start)
25
+ files = modified_files([@directory], :all => true)
26
+ @callback.call(files) unless files.empty?
27
+ nap_time = @latency - (Time.now.to_f - start)
30
28
  sleep(nap_time) if nap_time > 0
31
29
  end
32
30
  end
@@ -1,6 +1,5 @@
1
1
  module Guard
2
2
  class Windows < Listener
3
- attr_reader :fchange
4
3
 
5
4
  def initialize(*)
6
5
  super
@@ -10,12 +9,12 @@ module Guard
10
9
 
11
10
  def start
12
11
  super
13
- @fchange.run
12
+ worker.run
14
13
  end
15
14
 
16
15
  def stop
17
16
  super
18
- @fchange.stop
17
+ worker.stop
19
18
  end
20
19
 
21
20
  def self.usable?
@@ -34,10 +33,9 @@ module Guard
34
33
 
35
34
  def watch(directory)
36
35
  worker.watch(directory, :all_events, :recursive) do |event|
37
- paths = [File.expand_path(event.watcher.path) + '/']
38
- files = modified_files(paths, {:all => true})
39
- update_last_event
40
- callback.call(files)
36
+ paths = [File.expand_path(event.watcher.path)]
37
+ files = modified_files(paths, :all => true)
38
+ @callback.call(files) unless files.empty?
41
39
  end
42
40
  end
43
41
 
@@ -4,6 +4,7 @@ require 'guard/ui'
4
4
 
5
5
  module Guard
6
6
  module Notifier
7
+ APPLICATION_NAME = "Guard"
7
8
 
8
9
  def self.turn_off
9
10
  ENV["GUARD_NOTIFY"] = 'false'
@@ -45,13 +46,16 @@ module Guard
45
46
 
46
47
  def self.notify_mac(title, message, image, options)
47
48
  require_growl # need for guard-rspec formatter that is called out of guard scope
48
- default_options = { :title => title, :icon => image_path(image), :name => "Guard" }
49
- Growl.notify message, default_options.merge(options) if enabled?
49
+
50
+ options = { :description => message, :title => title, :icon => image_path(image), :application_name => APPLICATION_NAME }.merge(options)
51
+ options.delete(:name)
52
+
53
+ GrowlNotify.send_notification(options) if enabled?
50
54
  end
51
55
 
52
56
  def self.notify_linux(title, message, image, options)
53
57
  require_libnotify # need for guard-rspec formatter that is called out of guard scope
54
- default_options = { :body => message, :summary => title, :icon_path => image_path(image) }
58
+ default_options = { :body => message, :summary => title, :icon_path => image_path(image), :transient => true }
55
59
  Libnotify.show default_options.merge(options) if enabled?
56
60
  end
57
61
 
@@ -90,10 +94,17 @@ module Guard
90
94
  end
91
95
 
92
96
  def self.require_growl
93
- require 'growl'
97
+ require 'growl_notify'
98
+
99
+ if GrowlNotify.application_name != APPLICATION_NAME
100
+ GrowlNotify.config do |c|
101
+ c.notifications = c.default_notifications = [ APPLICATION_NAME ]
102
+ c.application_name = c.notifications.first
103
+ end
104
+ end
94
105
  rescue LoadError
95
106
  turn_off
96
- UI.info "Please install growl gem for Mac OS X notification support and add it to your Gemfile"
107
+ UI.info "Please install growl_notify gem for Mac OS X notification support and add it to your Gemfile"
97
108
  end
98
109
 
99
110
  def self.require_libnotify
@@ -1,32 +1,55 @@
1
1
  module Guard
2
2
  module UI
3
+
4
+ ANSI_ESCAPE_BRIGHT = "1"
5
+
6
+ ANSI_ESCAPE_BLACK = "30"
7
+ ANSI_ESCAPE_RED = "31"
8
+ ANSI_ESCAPE_GREEN = "32"
9
+ ANSI_ESCAPE_YELLOW = "33"
10
+ ANSI_ESCAPE_BLUE = "34"
11
+ ANSI_ESCAPE_MAGENTA = "35"
12
+ ANSI_ESCAPE_CYAN = "36"
13
+ ANSI_ESCAPE_WHITE = "37"
14
+
15
+ ANSI_ESCAPE_BGBLACK = "40"
16
+ ANSI_ESCAPE_BGRED = "41"
17
+ ANSI_ESCAPE_BGGREEN = "42"
18
+ ANSI_ESCAPE_BGYELLOW = "43"
19
+ ANSI_ESCAPE_BGBLUE = "44"
20
+ ANSI_ESCAPE_BGMAGENTA = "45"
21
+ ANSI_ESCAPE_BGCYAN = "46"
22
+ ANSI_ESCAPE_BGWHITE = "47"
23
+
3
24
  class << self
4
25
 
26
+ color_enabled = nil
27
+
5
28
  def info(message, options = {})
6
29
  unless ENV["GUARD_ENV"] == "test"
7
30
  reset_line if options[:reset]
8
- puts reset_color(message) if message != ''
31
+ puts color(message) if message != ''
9
32
  end
10
33
  end
11
34
 
12
35
  def error(message, options = {})
13
36
  unless ENV["GUARD_ENV"] == "test"
14
37
  reset_line if options[:reset]
15
- puts "#{color('ERROR:', ';31')} #{message}"
38
+ puts color('ERROR: ', :red) + message
16
39
  end
17
40
  end
18
41
 
19
42
  def deprecation(message, options = {})
20
43
  unless ENV["GUARD_ENV"] == "test"
21
44
  reset_line if options[:reset]
22
- puts "#{color('DEPRECATION:', ';31')} #{message}"
45
+ puts color('DEPRECATION: ', :red) + message
23
46
  end
24
47
  end
25
48
 
26
49
  def debug(message, options = {})
27
50
  unless ENV["GUARD_ENV"] == "test"
28
51
  reset_line if options[:reset]
29
- puts "DEBUG: #{message}" if ::Guard.options && ::Guard.options[:debug]
52
+ puts color("DEBUG (#{Time.now.strftime('%T')}): ", :yellow) + message if ::Guard.options && ::Guard.options[:debug]
30
53
  end
31
54
  end
32
55
 
@@ -40,29 +63,46 @@ module Guard
40
63
 
41
64
  private
42
65
 
66
+ # @deprecated
43
67
  def reset_color(text)
68
+ deprecation('UI.reset_color(text) is deprecated, please use color(text, "") instead.')
44
69
  color(text, "")
45
70
  end
46
71
 
47
- def color(text, color_code)
72
+ def color(text, *color_options)
73
+ color_code = ""
74
+ color_options.each do |color_option|
75
+ color_option = color_option.to_s
76
+ if color_option != ""
77
+ if !(color_option =~ /\d+/)
78
+ color_option = const_get("ANSI_ESCAPE_#{color_option.upcase}")
79
+ end
80
+ color_code += ";" + color_option
81
+ end
82
+ end
48
83
  color_enabled? ? "\e[0#{color_code}m#{text}\e[0m" : text
49
84
  end
50
85
 
51
86
  def color_enabled?
52
- @color_enabled ||= if RbConfig::CONFIG['target_os'] =~ /mswin|mingw/i
53
- unless ENV['ANSICON']
54
- begin
55
- require 'rubygems' unless ENV['NO_RUBYGEMS']
56
- require 'Win32/Console/ANSI'
57
- rescue LoadError
58
- @color_enabled = false
59
- info "You must 'gem install win32console' to use color on Windows"
60
- false
87
+ if @color_enabled.nil?
88
+ if RbConfig::CONFIG['target_os'] =~ /mswin|mingw/i
89
+ if ENV['ANSICON']
90
+ @color_enabled = true
91
+ else
92
+ begin
93
+ require 'rubygems' unless ENV['NO_RUBYGEMS']
94
+ require 'Win32/Console/ANSI'
95
+ @color_enabled = true
96
+ rescue LoadError
97
+ @color_enabled = false
98
+ info "You must 'gem install win32console' to use color on Windows"
99
+ end
61
100
  end
101
+ else
102
+ @color_enabled = true
62
103
  end
63
- else
64
- true
65
104
  end
105
+ @color_enabled
66
106
  end
67
107
 
68
108
  end
@@ -1,3 +1,3 @@
1
1
  module Guard
2
- VERSION = "0.5.1" unless defined? Guard::VERSION
2
+ VERSION = "0.6.0" unless defined? Guard::VERSION
3
3
  end
@@ -1,64 +1,130 @@
1
1
  .\" generated with Ronn/v0.7.3
2
2
  .\" http://github.com/rtomayko/ronn/tree/0.7.3
3
3
  .
4
- .TH "GUARD" "1" "June 2011" "" ""
4
+ .TH "GUARD" "1" "August 2011" "" ""
5
5
  .
6
6
  .SH "NAME"
7
7
  \fBguard\fR \- Guard keeps an eye on your file modifications\.
8
8
  .
9
+ .SH "DESCRIPTION"
10
+ Guard is a command line tool that easily handle events on files modifications\.
11
+ .
9
12
  .SH "SYNOPSIS"
10
13
  guard \fIcommand\fR \fIoptions\fR
11
14
  .
12
- .SH "DESCRIPTION"
13
- Guard is a command line tool that easily handle events on files modifications\.
15
+ .SH "COMMANDS"
14
16
  .
15
- .SH "HOMEPAGE"
16
- https://github\.com/guard/guard
17
+ .SS "start"
18
+ Starts Guard\. This is the default command if none is provided\.
17
19
  .
18
- .SH "OPTIONS"
20
+ .P
21
+ The following options are available:
19
22
  .
20
- .TP
21
- \fB\-c\fR, \fB\-\-clear\fR
22
- Clears the Shell after each change\.
23
+ .P
24
+ \fB\-c\fR/\fB\-\-clear\fR
23
25
  .
24
- .TP
25
- \fB\-n\fR \fIflag\fR, \fB\-\-notify\fR \fIflag\fR
26
- Disable notifications (Growl or Libnotify depending on your system)\. Note that notifications can also be disabled globally by setting a GUARD_NOTIFY environment variable to false\. The \fIflag\fR part can be passed to guard using true/false or t/f\.
26
+ .IP "" 4
27
27
  .
28
- .TP
29
- \fB\-g\fR \fIgroup\fR \.\.\., \fB\-\-group\fR \fIgroup\fR \.\.\.
30
- Runs only the groups specified\.
28
+ .nf
29
+
30
+ Clears the Shell after each change\.
31
31
  .
32
- .TP
33
- \fB\-d\fR, \fB\-\-debug\fR
34
- Runs Guard in debug mode\.
32
+ .fi
35
33
  .
36
- .TP
37
- \fB\-h\fR
38
- List all of Guard\'s available commands\.
34
+ .IP "" 0
39
35
  .
40
- .SH "COMMANDS"
36
+ .P
37
+ \fB\-n\fR/\fB\-\-notify\fR \fIflag\fR
41
38
  .
42
- .TP
43
- \fBstart\fR
44
- Starts Guard\. This is the default command if none is provided\.
39
+ .IP "" 4
45
40
  .
46
- .TP
47
- \fBinit\fR [guard]
41
+ .nf
42
+
43
+ Disable notifications (Growl or Libnotify depending on your system)\.
44
+ Note that notifications can also be disabled globally by setting a GUARD_NOTIFY environment variable to false\.
45
+ The <flag> part can be passed to guard using true/false or t/f\.
46
+ .
47
+ .fi
48
+ .
49
+ .IP "" 0
50
+ .
51
+ .P
52
+ \fB\-d\fR/\fB\-\-debug\fR
53
+ .
54
+ .IP "" 4
55
+ .
56
+ .nf
57
+
58
+ Runs Guard in debug mode\.
59
+ .
60
+ .fi
61
+ .
62
+ .IP "" 0
63
+ .
64
+ .P
65
+ \fB\-g\fR/\fB\-\-group\fR \fIgroup\fR \.\.\.
66
+ .
67
+ .IP "" 4
68
+ .
69
+ .nf
70
+
71
+ Runs only the groups specified\.
72
+ .
73
+ .fi
74
+ .
75
+ .IP "" 0
76
+ .
77
+ .P
78
+ \fB\-w\fR/\fB\-\-watchdir\fR \fIfolder\fR
79
+ .
80
+ .IP "" 4
81
+ .
82
+ .nf
83
+
84
+ Specify the directory to watch\.
85
+ .
86
+ .fi
87
+ .
88
+ .IP "" 0
89
+ .
90
+ .P
91
+ \fB\-G\fR/\fB\-\-guardfile\fR \fIfile\fR
92
+ .
93
+ .IP "" 4
94
+ .
95
+ .nf
96
+
97
+ Specify a Guardfile by giving its path\.
98
+ .
99
+ .fi
100
+ .
101
+ .IP "" 0
102
+ .
103
+ .SS "init [guard]"
48
104
  Add the requested guard\'s default Guardfile configuration to the current Guardfile\.
49
105
  .
50
- .TP
51
- \fBshow\fR, \fB\-T\fR
106
+ .SS "list"
107
+ Lists guards that can be used with the \fBinit\fR command\.
108
+ .
109
+ .SS "\-T/show"
52
110
  List defined groups and guards for the current Guardfile\.
53
111
  .
112
+ .SH "OPTIONS"
113
+ .
114
+ .TP
115
+ \fB\-h\fR
116
+ List all of Guard\'s available commands\.
117
+ .
118
+ .SS "start"
119
+ .
54
120
  .SH "EXAMPLES"
55
- \fB[bundle exec] guard \-\-clear \-\-group backend frontend \-\-notify false \-\-debug\fR
121
+ \fB[bundle exec] guard [start] \-\-watchdir ~/dev \-\-guardfile ~/env/Guardfile \-\-clear \-\-group backend frontend \-\-notify false \-\-debug\fR
56
122
  .
57
123
  .P
58
124
  or in a more concise way:
59
125
  .
60
126
  .P
61
- \fB[bundle exec] guard \-c \-g backend frontend \-n f \-d\fR
127
+ \fB[bundle exec] guard [start] \-w ~/dev \-G ~/env/Guardfile \-c \-g backend frontend \-n f \-d\fR
62
128
  .
63
129
  .SH "AUTHORS / CONTRIBUTORS"
64
130
  Thibaud Guillaume\-Gentil is the main author\.
@@ -68,3 +134,9 @@ A list of contributors based on all commits can be found here: https://github\.c
68
134
  .
69
135
  .P
70
136
  For an exhaustive list of all the contributors, please see the CHANGELOG: https://github\.com/guard/guard/blob/master/CHANGELOG\.md
137
+ .
138
+ .P
139
+ This manual has been written by Remy Coutable\.
140
+ .
141
+ .SH "WWW"
142
+ https://github\.com/guard/guard
@@ -54,13 +54,13 @@
54
54
 
55
55
  <div class='man-navigation' style='display:none'>
56
56
  <a href="#NAME">NAME</a>
57
- <a href="#SYNOPSIS">SYNOPSIS</a>
58
57
  <a href="#DESCRIPTION">DESCRIPTION</a>
59
- <a href="#HOMEPAGE">HOMEPAGE</a>
60
- <a href="#OPTIONS">OPTIONS</a>
58
+ <a href="#SYNOPSIS">SYNOPSIS</a>
61
59
  <a href="#COMMANDS">COMMANDS</a>
60
+ <a href="#OPTIONS">OPTIONS</a>
62
61
  <a href="#EXAMPLES">EXAMPLES</a>
63
62
  <a href="#AUTHORS-CONTRIBUTORS">AUTHORS / CONTRIBUTORS</a>
63
+ <a href="#WWW">WWW</a>
64
64
  </div>
65
65
 
66
66
  <ol class='man-decor man-head man head'>
@@ -74,47 +74,82 @@
74
74
  <code>guard</code> - <span class="man-whatis">Guard keeps an eye on your file modifications.</span>
75
75
  </p>
76
76
 
77
+ <h2 id="DESCRIPTION">DESCRIPTION</h2>
78
+
79
+ <p>Guard is a command line tool that easily handle events on files modifications.</p>
80
+
77
81
  <h2 id="SYNOPSIS">SYNOPSIS</h2>
78
82
 
79
83
  <p>guard <var>command</var> <var>options</var></p>
80
84
 
81
- <h2 id="DESCRIPTION">DESCRIPTION</h2>
85
+ <h2 id="COMMANDS">COMMANDS</h2>
82
86
 
83
- <p>Guard is a command line tool that easily handle events on files modifications.</p>
87
+ <h3 id="start">start</h3>
84
88
 
85
- <h2 id="HOMEPAGE">HOMEPAGE</h2>
89
+ <p> Starts Guard. This is the default command if none is provided.</p>
86
90
 
87
- <p>https://github.com/guard/guard</p>
91
+ <p>The following options are available:</p>
88
92
 
89
- <h2 id="OPTIONS">OPTIONS</h2>
93
+ <p> <code>-c</code>/<code>--clear</code></p>
90
94
 
91
- <dl>
92
- <dt><code>-c</code>, <code>--clear</code></dt><dd><p>Clears the Shell after each change.</p></dd>
93
- <dt><code>-n</code> <var>flag</var>, <code>--notify</code> <var>flag</var></dt><dd><p>Disable notifications (Growl or Libnotify depending on your system).
94
- Note that notifications can also be disabled globally by setting a GUARD_NOTIFY environment variable to false.
95
- The <var>flag</var> part can be passed to guard using true/false or t/f.</p></dd>
96
- <dt><code>-g</code> <var>group</var> ..., <code>--group</code> <var>group</var> ...</dt><dd><p>Runs only the groups specified.</p></dd>
97
- <dt><code>-d</code>, <code>--debug</code></dt><dd><p>Runs Guard in debug mode.</p></dd>
98
- <dt class="flush"><code>-h</code></dt><dd><p>List all of Guard's available commands.</p></dd>
99
- </dl>
95
+ <pre><code> Clears the Shell after each change.
96
+ </code></pre>
100
97
 
98
+ <p> <code>-n</code>/<code>--notify</code> <var>flag</var></p>
101
99
 
102
- <h2 id="COMMANDS">COMMANDS</h2>
100
+ <pre><code> Disable notifications (Growl or Libnotify depending on your system).
101
+ Note that notifications can also be disabled globally by setting a GUARD_NOTIFY environment variable to false.
102
+ The &lt;flag> part can be passed to guard using true/false or t/f.
103
+ </code></pre>
104
+
105
+ <p> <code>-d</code>/<code>--debug</code></p>
106
+
107
+ <pre><code> Runs Guard in debug mode.
108
+ </code></pre>
109
+
110
+ <p> <code>-g</code>/<code>--group</code> <var>group</var> ...</p>
111
+
112
+ <pre><code> Runs only the groups specified.
113
+ </code></pre>
114
+
115
+ <p> <code>-w</code>/<code>--watchdir</code> <var>folder</var></p>
116
+
117
+ <pre><code> Specify the directory to watch.
118
+ </code></pre>
119
+
120
+ <p> <code>-G</code>/<code>--guardfile</code> <var>file</var></p>
121
+
122
+ <pre><code> Specify a Guardfile by giving its path.
123
+ </code></pre>
124
+
125
+ <h3 id="init-guard-">init [guard]</h3>
126
+
127
+ <p> Add the requested guard's default Guardfile configuration to the current Guardfile.</p>
128
+
129
+ <h3 id="list">list</h3>
130
+
131
+ <p> Lists guards that can be used with the <code>init</code> command.</p>
132
+
133
+ <h3 id="-T-show">-T/show</h3>
134
+
135
+ <p> List defined groups and guards for the current Guardfile.</p>
136
+
137
+ <h2 id="OPTIONS">OPTIONS</h2>
103
138
 
104
139
  <dl>
105
- <dt class="flush"><code>start</code></dt><dd><p>Starts Guard. This is the default command if none is provided.</p></dd>
106
- <dt><code>init</code> [guard]</dt><dd><p>Add the requested guard's default Guardfile configuration to the current Guardfile.</p></dd>
107
- <dt><code>show</code>, <code>-T</code></dt><dd><p>List defined groups and guards for the current Guardfile.</p></dd>
140
+ <dt class="flush"><code>-h</code></dt><dd>List all of Guard's available commands.</dd>
108
141
  </dl>
109
142
 
110
143
 
144
+ <h3 id="start">start</h3>
145
+
111
146
  <h2 id="EXAMPLES">EXAMPLES</h2>
112
147
 
113
- <p><code>[bundle exec] guard --clear --group backend frontend --notify false --debug</code></p>
148
+ <p><code>[bundle exec] guard [start] --watchdir ~/dev --guardfile ~/env/Guardfile --clear --group backend frontend --notify false --debug</code></p>
114
149
 
115
150
  <p>or in a more concise way:</p>
116
151
 
117
- <p><code>[bundle exec] guard -c -g backend frontend -n f -d</code></p>
152
+ <p><code>[bundle exec] guard [start] -w ~/dev -G ~/env/Guardfile -c -g backend frontend -n f -d</code></p>
118
153
 
119
154
  <h2 id="AUTHORS-CONTRIBUTORS">AUTHORS / CONTRIBUTORS</h2>
120
155
 
@@ -126,10 +161,16 @@ https://github.com/guard/guard/contributors</p>
126
161
  <p>For an exhaustive list of all the contributors, please see the CHANGELOG:
127
162
  https://github.com/guard/guard/blob/master/CHANGELOG.md</p>
128
163
 
164
+ <p>This manual has been written by Remy Coutable.</p>
165
+
166
+ <h2 id="WWW">WWW</h2>
167
+
168
+ <p>https://github.com/guard/guard</p>
169
+
129
170
 
130
171
  <ol class='man-decor man-foot man foot'>
131
172
  <li class='tl'></li>
132
- <li class='tc'>June 2011</li>
173
+ <li class='tc'>August 2011</li>
133
174
  <li class='tr'>guard(1)</li>
134
175
  </ol>
135
176
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: guard
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.1
4
+ version: 0.6.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,12 +9,12 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-07-15 00:00:00.000000000 +02:00
12
+ date: 2011-08-13 00:00:00.000000000 +02:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: bundler
17
- requirement: &2152963700 !ruby/object:Gem::Requirement
17
+ requirement: &2151817180 !ruby/object:Gem::Requirement
18
18
  none: false
19
19
  requirements:
20
20
  - - ! '>='
@@ -22,10 +22,10 @@ dependencies:
22
22
  version: '0'
23
23
  type: :development
24
24
  prerelease: false
25
- version_requirements: *2152963700
25
+ version_requirements: *2151817180
26
26
  - !ruby/object:Gem::Dependency
27
27
  name: rspec
28
- requirement: &2152962700 !ruby/object:Gem::Requirement
28
+ requirement: &2151815560 !ruby/object:Gem::Requirement
29
29
  none: false
30
30
  requirements:
31
31
  - - ~>
@@ -33,10 +33,10 @@ dependencies:
33
33
  version: 2.6.0
34
34
  type: :development
35
35
  prerelease: false
36
- version_requirements: *2152962700
36
+ version_requirements: *2151815560
37
37
  - !ruby/object:Gem::Dependency
38
38
  name: guard-rspec
39
- requirement: &2152961760 !ruby/object:Gem::Requirement
39
+ requirement: &2151813940 !ruby/object:Gem::Requirement
40
40
  none: false
41
41
  requirements:
42
42
  - - ~>
@@ -44,10 +44,10 @@ dependencies:
44
44
  version: 0.3.1
45
45
  type: :development
46
46
  prerelease: false
47
- version_requirements: *2152961760
47
+ version_requirements: *2151813940
48
48
  - !ruby/object:Gem::Dependency
49
49
  name: thor
50
- requirement: &2152961140 !ruby/object:Gem::Requirement
50
+ requirement: &2151811280 !ruby/object:Gem::Requirement
51
51
  none: false
52
52
  requirements:
53
53
  - - ~>
@@ -55,7 +55,7 @@ dependencies:
55
55
  version: 0.14.6
56
56
  type: :runtime
57
57
  prerelease: false
58
- version_requirements: *2152961140
58
+ version_requirements: *2151811280
59
59
  description: Guard is a command line tool to easily handle events on file system modifications.
60
60
  email:
61
61
  - thibaud@thibaud.me