guard 0.8.4 → 0.8.5

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,60 +1,150 @@
1
- require 'guard/dsl'
2
-
3
- module Guard
4
-
5
- # The DslDescriber overrides methods to create an internal structure
6
- # of the Guardfile that is used in some inspection utility methods
7
- # like the CLI commands `show` and `list`.
8
- #
9
- # @see Guard::Dsl
10
- # @see Guard::CLI
11
- #
12
- class DslDescriber < Dsl
13
-
14
- @@guardfile_structure = [ { :guards => [] } ]
15
-
16
- class << self
17
-
18
- # Get the Guardfile structure.
19
- #
20
- # @return [Array<Hash>] the structure
21
- #
22
- def guardfile_structure
23
- @@guardfile_structure
24
- end
25
- end
26
-
27
- private
28
-
29
- # Declares a group of guards.
30
- #
31
- # @param [String] name the group's name called from the CLI
32
- # @yield a block where you can declare several guards
33
- #
34
- # @see Guard::Dsl#group
35
- #
36
- def group(name)
37
- @@guardfile_structure << { :group => name.to_sym, :guards => [] }
38
- @group = true
39
-
40
- yield if block_given?
41
-
42
- @group = false
43
- end
44
-
45
- # Declares a Guard.
46
- #
47
- # @param [String] name the Guard name
48
- # @param [Hash] options the options accepted by the Guard
49
- # @yield a block where you can declare several watch patterns and actions
50
- #
51
- # @see Guard::Dsl#guard
52
- #
53
- def guard(name, options = {})
54
- node = (@group ? @@guardfile_structure.last : @@guardfile_structure.first)
55
-
56
- node[:guards] << { :name => name, :options => options }
57
- end
58
-
59
- end
60
- end
1
+ require 'guard/dsl'
2
+
3
+ module Guard
4
+
5
+ autoload :UI, 'guard/ui'
6
+
7
+ # The DslDescriber overrides methods to create an internal structure
8
+ # of the Guardfile that is used in some inspection utility methods
9
+ # like the CLI commands `show` and `list`.
10
+ #
11
+ # @see Guard::Dsl
12
+ # @see Guard::CLI
13
+ #
14
+ class DslDescriber < Dsl
15
+
16
+ class << self
17
+
18
+ # Evaluate the DSL methods in the `Guardfile`.
19
+ #
20
+ # @option options [Array<Symbol,String>] groups the groups to evaluate
21
+ # @option options [String] guardfile the path to a valid Guardfile
22
+ # @option options [String] guardfile_contents a string representing the content of a valid Guardfile
23
+ # @raise [ArgumentError] when options are not a Hash
24
+ #
25
+ def evaluate_guardfile(options = {})
26
+ @@guardfile_structure = [{ :guards => [] }]
27
+ super options
28
+ end
29
+
30
+ # List the Guards that are available for use in your system and marks
31
+ # those that are currently used in your `Guardfile`.
32
+ #
33
+ # @example Guard list output
34
+ #
35
+ # Available guards:
36
+ # bundler *
37
+ # livereload
38
+ # ronn
39
+ # rspec *
40
+ # spork
41
+ #
42
+ # See also https://github.com/guard/guard/wiki/List-of-available-Guards
43
+ # * denotes ones already in your Guardfile
44
+ #
45
+ # @param [Hash] options the Guard options
46
+ #
47
+ def list(options)
48
+ evaluate_guardfile(options)
49
+
50
+ installed = guardfile_structure.inject([]) do |installed, group|
51
+ group[:guards].each { |guard| installed << guard[:name] } if group[:guards]
52
+ installed
53
+ end
54
+
55
+ UI.info 'Available guards:'
56
+
57
+ ::Guard.guard_gem_names.sort.uniq.each do |name|
58
+ UI.info " #{ name }#{ installed.include?(name) ? '*' : '' }"
59
+ end
60
+
61
+ UI.info ''
62
+ UI.info 'See also https://github.com/guard/guard/wiki/List-of-available-Guards'
63
+ UI.info '* denotes ones already in your Guardfile'
64
+ end
65
+
66
+ # Shows all Guards and their options that are defined in
67
+ # the `Guardfile`.
68
+ #
69
+ # @example guard show output
70
+ #
71
+ # (global):
72
+ # bundler
73
+ # coffeescript: input => "app/assets/javascripts", noop => true
74
+ # jasmine
75
+ # rspec: cli => "--fail-fast --format Fuubar
76
+ #
77
+ # @param [Hash] options the Guard options
78
+ #
79
+ def show(options)
80
+ evaluate_guardfile(options)
81
+
82
+ guardfile_structure.each do |group|
83
+ unless group[:guards].empty?
84
+ if group[:group]
85
+ UI.info "Group #{ group[:group] }:"
86
+ else
87
+ UI.info '(global):'
88
+ end
89
+
90
+ group[:guards].each do |guard|
91
+ line = " #{ guard[:name] }"
92
+
93
+ unless guard[:options].empty?
94
+ line += ": #{ guard[:options].sort.collect { |k, v| "#{ k } => #{ v.inspect }" }.join(', ') }"
95
+ end
96
+
97
+ UI.info line
98
+ end
99
+ end
100
+ end
101
+
102
+ UI.info ''
103
+ end
104
+
105
+ private
106
+
107
+ # Get the Guardfile structure.
108
+ #
109
+ # @return [Array<Hash>] the structure
110
+ #
111
+ def guardfile_structure
112
+ @@guardfile_structure
113
+ end
114
+
115
+ end
116
+
117
+ private
118
+
119
+ # Declares a group of guards.
120
+ #
121
+ # @param [String] name the group's name called from the CLI
122
+ # @yield a block where you can declare several guards
123
+ #
124
+ # @see Guard::Dsl#group
125
+ #
126
+ def group(name)
127
+ @@guardfile_structure << { :group => name.to_sym, :guards => [] }
128
+ @group = true
129
+
130
+ yield if block_given?
131
+
132
+ @group = false
133
+ end
134
+
135
+ # Declares a Guard.
136
+ #
137
+ # @param [String] name the Guard name
138
+ # @param [Hash] options the options accepted by the Guard
139
+ # @yield a block where you can declare several watch patterns and actions
140
+ #
141
+ # @see Guard::Dsl#guard
142
+ #
143
+ def guard(name, options = { })
144
+ node = (@group ? @@guardfile_structure.last : @@guardfile_structure.first)
145
+
146
+ node[:guards] << { :name => name, :options => options }
147
+ end
148
+
149
+ end
150
+ end
data/lib/guard/group.rb CHANGED
@@ -1,37 +1,37 @@
1
- module Guard
2
-
3
- # A group of Guards. There are two reasons why you want to group your guards:
4
- #
5
- # - You can start only certain Groups from the command line by passing the `--group` option.
6
- # - Abort task execution chain on failure within a group.
7
- #
8
- # @example Group that aborts on failure
9
- #
10
- # group :frontend, :halt_on_fail => true do
11
- # guard 'coffeescript', :input => 'spec/coffeescripts', :output => 'spec/javascripts'
12
- # guard 'jasmine-headless-webkit' do
13
- # watch(%r{^spec/javascripts/(.*)\..*}) { |m| newest_js_file("spec/javascripts/#{m[1]}_spec") }
14
- # end
15
- # end
16
- #
17
- # @see Guard::CLI
18
- #
19
- class Group
20
-
21
- attr_accessor :name, :options
22
-
23
- # Initialize a Group.
24
- #
25
- # @param [String] name the name of the group
26
- # @param [Hash] options the group options
27
- # @option options [Boolean] halt_on_fail if a task execution
28
- # should be halted for all Guards in this group if one Guard throws `:task_has_failed`
29
- #
30
- def initialize(name, options = {})
31
- @name = name.to_sym
32
- @options = options
33
- end
34
-
35
- end
36
-
37
- end
1
+ module Guard
2
+
3
+ # A group of Guards. There are two reasons why you want to group your guards:
4
+ #
5
+ # - You can start only certain Groups from the command line by passing the `--group` option.
6
+ # - Abort task execution chain on failure within a group.
7
+ #
8
+ # @example Group that aborts on failure
9
+ #
10
+ # group :frontend, :halt_on_fail => true do
11
+ # guard 'coffeescript', :input => 'spec/coffeescripts', :output => 'spec/javascripts'
12
+ # guard 'jasmine-headless-webkit' do
13
+ # watch(%r{^spec/javascripts/(.*)\..*}) { |m| newest_js_file("spec/javascripts/#{m[1]}_spec") }
14
+ # end
15
+ # end
16
+ #
17
+ # @see Guard::CLI
18
+ #
19
+ class Group
20
+
21
+ attr_accessor :name, :options
22
+
23
+ # Initialize a Group.
24
+ #
25
+ # @param [String] name the name of the group
26
+ # @param [Hash] options the group options
27
+ # @option options [Boolean] halt_on_fail if a task execution
28
+ # should be halted for all Guards in this group if one Guard throws `:task_has_failed`
29
+ #
30
+ def initialize(name, options = {})
31
+ @name = name.to_sym
32
+ @options = options
33
+ end
34
+
35
+ end
36
+
37
+ end
data/lib/guard/guard.rb CHANGED
@@ -1,113 +1,129 @@
1
- module Guard
2
-
3
- # Main class that every Guard implementation must subclass.
4
- #
5
- # Guard will trigger the `start`, `stop`, `reload`, `run_all`, `run_on_change` and
6
- # `run_on_deletion` methods depending on user interaction and file modification.
7
- #
8
- # In each of these Guard methods you have to implement some work when you want to
9
- # support this kind of task. The return value of each Guard method is ignored, but
10
- # you can throw `:task_has_failed` to indicate that your Guard method was
11
- # not successful. When `:task_has_failed` is thrown, successive guard tasks
12
- # can be aborted when the group has set the `:halt_on_fail` option.
13
- #
14
- # @see Guard::Group
15
- #
16
- # @example Throw :task_has_failed
17
- #
18
- # def run_all
19
- # if !runner.run(['all'])
20
- # throw :task_has_failed
21
- # end
22
- # end
23
- #
24
- # Each Guard should provide a template Guardfile located within the Gem
25
- # at `lib/guard/guard-name/templates/Guardfile`.
26
- #
27
- # If one of those methods raise an exception other than `:task_has_failed`,
28
- # the Guard::GuardName instance will be removed from the active guards.
29
- #
30
- class Guard
31
- include Hook
32
-
33
- attr_accessor :watchers, :options, :group
34
-
35
- # Initialize a Guard.
36
- #
37
- # @param [Array<Guard::Watcher>] watchers the Guard file watchers
38
- # @param [Hash] options the custom Guard options
39
- #
40
- def initialize(watchers = [], options = {})
41
- @group = options[:group] ? options.delete(:group).to_sym : :default
42
- @watchers, @options = watchers, options
43
- end
44
-
45
- # Initialize the Guard. This will copy the Guardfile template inside the Guard gem.
46
- # The template Guardfile must be located within the Gem at `lib/guard/guard-name/templates/Guardfile`.
47
- #
48
- # @param [String] name the name of the Guard
49
- #
50
- def self.init(name)
51
- if ::Guard::Dsl.guardfile_include?(name)
52
- ::Guard::UI.info "Guardfile already includes #{ name } guard"
53
- else
54
- content = File.read('Guardfile')
55
- guard = File.read("#{ ::Guard.locate_guard(name) }/lib/guard/#{ name }/templates/Guardfile")
56
- File.open('Guardfile', 'wb') do |f|
57
- f.puts(content)
58
- f.puts("")
59
- f.puts(guard)
60
- end
61
- ::Guard::UI.info "#{name} guard added to Guardfile, feel free to edit it"
62
- end
63
- end
64
-
65
- # Call once when Guard starts. Please override initialize method to init stuff.
66
- #
67
- # @raise [:task_has_failed] when start has failed
68
- #
69
- def start
70
- end
71
-
72
- # Called when `stop|quit|exit|s|q|e + enter` is pressed (when Guard quits).
73
- #
74
- # @raise [:task_has_failed] when stop has failed
75
- #
76
- def stop
77
- end
78
-
79
- # Called when `reload|r|z + enter` is pressed.
80
- # This method should be mainly used for "reload" (really!) actions like reloading passenger/spork/bundler/...
81
- #
82
- # @raise [:task_has_failed] when reload has failed
83
- #
84
- def reload
85
- end
86
-
87
- # Called when just `enter` is pressed
88
- # This method should be principally used for long action like running all specs/tests/...
89
- #
90
- # @raise [:task_has_failed] when run_all has failed
91
- #
92
- def run_all
93
- end
94
-
95
- # Called on file(s) modifications that the Guard watches.
96
- #
97
- # @param [Array<String>] paths the changes files or paths
98
- # @raise [:task_has_failed] when run_on_change has failed
99
- #
100
- def run_on_change(paths)
101
- end
102
-
103
- # Called on file(s) deletions that the Guard watches.
104
- #
105
- # @param [Array<String>] paths the deleted files or paths
106
- # @raise [:task_has_failed] when run_on_change has failed
107
- #
108
- def run_on_deletion(paths)
109
- end
110
-
111
- end
112
-
113
- end
1
+ module Guard
2
+
3
+ # Base class that every Guard implementation must inherit from.
4
+ #
5
+ # Guard will trigger the `start`, `stop`, `reload`, `run_all`, `run_on_change` and
6
+ # `run_on_deletion` task methods depending on user interaction and file modification.
7
+ #
8
+ # In each of these Guard task methods you have to implement some work when you want to
9
+ # support this kind of task. The return value of each Guard task method is not evaluated
10
+ # by Guard, but I'll be passed to the "_end" hook for further evaluation. You can
11
+ # throw `:task_has_failed` to indicate that your Guard method was not successful,
12
+ # and successive guard tasks will be aborted when the group has set the `:halt_on_fail`
13
+ # option.
14
+ #
15
+ # @see Guard::Hook
16
+ # @see Guard::Group
17
+ #
18
+ # @example Throw :task_has_failed
19
+ #
20
+ # def run_all
21
+ # if !runner.run(['all'])
22
+ # throw :task_has_failed
23
+ # end
24
+ # end
25
+ #
26
+ # Each Guard should provide a template Guardfile located within the Gem
27
+ # at `lib/guard/guard-name/templates/Guardfile`.
28
+ #
29
+ # By default all watchers for a Guard are returning strings of paths to the
30
+ # Guard, but if your Guard want to allow any return value from a watcher,
31
+ # you can set the `any_return` option to true.
32
+ #
33
+ # If one of those methods raise an exception other than `:task_has_failed`,
34
+ # the Guard::GuardName instance will be removed from the active guards.
35
+ #
36
+ class Guard
37
+ include Hook
38
+
39
+ attr_accessor :watchers, :options, :group
40
+
41
+ # Initialize a Guard.
42
+ #
43
+ # @param [Array<Guard::Watcher>] watchers the Guard file watchers
44
+ # @param [Hash] options the custom Guard options
45
+ # @options [Symbol] group the group this Guard belongs to
46
+ # @options [Boolean] any_return allow any object to be returned from a watcher
47
+ #
48
+ def initialize(watchers = [], options = {})
49
+ @group = options[:group] ? options.delete(:group).to_sym : :default
50
+ @watchers, @options = watchers, options
51
+ end
52
+
53
+ # Initialize the Guard. This will copy the Guardfile template inside the Guard gem.
54
+ # The template Guardfile must be located within the Gem at `lib/guard/guard-name/templates/Guardfile`.
55
+ #
56
+ # @param [String] name the name of the Guard
57
+ #
58
+ def self.init(name)
59
+ if ::Guard::Dsl.guardfile_include?(name)
60
+ ::Guard::UI.info "Guardfile already includes #{ name } guard"
61
+ else
62
+ content = File.read('Guardfile')
63
+ guard = File.read("#{ ::Guard.locate_guard(name) }/lib/guard/#{ name }/templates/Guardfile")
64
+
65
+ File.open('Guardfile', 'wb') do |f|
66
+ f.puts(content)
67
+ f.puts("")
68
+ f.puts(guard)
69
+ end
70
+
71
+ ::Guard::UI.info "#{ name } guard added to Guardfile, feel free to edit it"
72
+ end
73
+ end
74
+
75
+ # Call once when Guard starts. Please override initialize method to init stuff.
76
+ #
77
+ # @raise [:task_has_failed] when start has failed
78
+ # @return [Object] the task result
79
+ #
80
+ def start
81
+ end
82
+
83
+ # Called when `stop|quit|exit|s|q|e + enter` is pressed (when Guard quits).
84
+ #
85
+ # @raise [:task_has_failed] when stop has failed
86
+ # @return [Object] the task result
87
+ #
88
+ def stop
89
+ end
90
+
91
+ # Called when `reload|r|z + enter` is pressed.
92
+ # This method should be mainly used for "reload" (really!) actions like reloading passenger/spork/bundler/...
93
+ #
94
+ # @raise [:task_has_failed] when reload has failed
95
+ # @return [Object] the task result
96
+ #
97
+ def reload
98
+ end
99
+
100
+ # Called when just `enter` is pressed
101
+ # This method should be principally used for long action like running all specs/tests/...
102
+ #
103
+ # @raise [:task_has_failed] when run_all has failed
104
+ # @return [Object] the task result
105
+ #
106
+ def run_all
107
+ end
108
+
109
+ # Called on file(s) modifications that the Guard watches.
110
+ #
111
+ # @param [Array<String>] paths the changes files or paths
112
+ # @raise [:task_has_failed] when run_on_change has failed
113
+ # @return [Object] the task result
114
+ #
115
+ def run_on_change(paths)
116
+ end
117
+
118
+ # Called on file(s) deletions that the Guard watches.
119
+ #
120
+ # @param [Array<String>] paths the deleted files or paths
121
+ # @raise [:task_has_failed] when run_on_change has failed
122
+ # @return [Object] the task result
123
+ #
124
+ def run_on_deletion(paths)
125
+ end
126
+
127
+ end
128
+
129
+ end