guard 0.5.1 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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