sass 3.2.0.alpha.104 → 3.2.0.alpha.236
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.
- data/REVISION +1 -1
- data/Rakefile +2 -2
- data/VERSION +1 -1
- data/lib/sass/engine.rb +8 -1
- data/lib/sass/exec.rb +2 -2
- data/lib/sass/plugin/compiler.rb +51 -43
- data/lib/sass/script/color.rb +4 -9
- data/lib/sass/script/funcall.rb +11 -2
- data/lib/sass/script/functions.rb +16 -30
- data/lib/sass/script/lexer.rb +7 -1
- data/lib/sass/script/list.rb +2 -2
- data/lib/sass/script/literal.rb +8 -0
- data/lib/sass/script/null.rb +34 -0
- data/lib/sass/script/operation.rb +4 -0
- data/lib/sass/script/parser.rb +4 -2
- data/lib/sass/scss/parser.rb +1 -5
- data/lib/sass/scss/rx.rb +1 -1
- data/lib/sass/tree/directive_node.rb +5 -0
- data/lib/sass/tree/media_node.rb +3 -0
- data/lib/sass/tree/prop_node.rb +7 -3
- data/lib/sass/tree/visitors/base.rb +1 -1
- data/lib/sass/tree/visitors/check_nesting.rb +21 -18
- data/lib/sass/tree/visitors/convert.rb +1 -0
- data/lib/sass/tree/visitors/perform.rb +3 -2
- data/lib/sass/tree/visitors/to_css.rb +1 -0
- data/lib/sass/util.rb +28 -0
- data/test/sass/conversion_test.rb +33 -0
- data/test/sass/engine_test.rb +118 -3
- data/test/sass/functions_test.rb +56 -24
- data/test/sass/script_test.rb +60 -4
- data/test/sass/scss/scss_test.rb +10 -0
- data/vendor/listen/CHANGELOG.md +19 -1
- data/vendor/listen/README.md +27 -12
- data/vendor/listen/lib/listen/adapter.rb +9 -1
- data/vendor/listen/lib/listen/adapters/linux.rb +18 -7
- data/vendor/listen/lib/listen/adapters/windows.rb +7 -8
- data/vendor/listen/lib/listen/directory_record.rb +108 -48
- data/vendor/listen/lib/listen/listener.rb +28 -11
- data/vendor/listen/lib/listen/multi_listener.rb +6 -6
- data/vendor/listen/lib/listen/version.rb +1 -1
- data/vendor/listen/spec/listen/adapters/linux_spec.rb +11 -0
- data/vendor/listen/spec/listen/directory_record_spec.rb +268 -41
- data/vendor/listen/spec/listen/listener_spec.rb +8 -4
- data/vendor/listen/spec/listen/multi_listener_spec.rb +9 -4
- data/vendor/listen/spec/support/adapter_helper.rb +178 -0
- data/vendor/listen/spec/support/directory_record_helper.rb +24 -4
- data/vendor/listen/spec/support/listeners_helper.rb +11 -0
- metadata +11 -11
- data/lib/sass/plugin/listener.rb +0 -61
data/test/sass/functions_test.rb
CHANGED
@@ -76,7 +76,7 @@ class SassFunctionTest < Test::Unit::TestCase
|
|
76
76
|
|
77
77
|
def test_hsl_checks_bounds
|
78
78
|
assert_error_message("Saturation -114 must be between 0% and 100% for `hsl'", "hsl(10, -114, 12)");
|
79
|
-
assert_error_message("Lightness 256 must be between 0% and 100% for `hsl'", "hsl(10, 10, 256%)");
|
79
|
+
assert_error_message("Lightness 256% must be between 0% and 100% for `hsl'", "hsl(10, 10, 256%)");
|
80
80
|
end
|
81
81
|
|
82
82
|
def test_hsl_checks_types
|
@@ -94,7 +94,7 @@ class SassFunctionTest < Test::Unit::TestCase
|
|
94
94
|
|
95
95
|
def test_hsla_checks_bounds
|
96
96
|
assert_error_message("Saturation -114 must be between 0% and 100% for `hsla'", "hsla(10, -114, 12, 1)");
|
97
|
-
assert_error_message("Lightness 256 must be between 0% and 100% for `hsla'", "hsla(10, 10, 256%, 0)");
|
97
|
+
assert_error_message("Lightness 256% must be between 0% and 100% for `hsla'", "hsla(10, 10, 256%, 0)");
|
98
98
|
assert_error_message("Alpha channel -0.1 must be between 0 and 1 for `hsla'", "hsla(10, 10, 10, -0.1)");
|
99
99
|
assert_error_message("Alpha channel 1.1 must be between 0 and 1 for `hsla'", "hsla(10, 10, 10, 1.1)");
|
100
100
|
end
|
@@ -189,24 +189,24 @@ class SassFunctionTest < Test::Unit::TestCase
|
|
189
189
|
end
|
190
190
|
|
191
191
|
def test_rgb_tests_bounds
|
192
|
-
assert_error_message("Color value 256 must be between 0 and 255
|
192
|
+
assert_error_message("Color value 256 must be between 0 and 255 for `rgb'",
|
193
193
|
"rgb(256, 1, 1)")
|
194
|
-
assert_error_message("Color value 256 must be between 0 and 255
|
194
|
+
assert_error_message("Color value 256 must be between 0 and 255 for `rgb'",
|
195
195
|
"rgb(1, 256, 1)")
|
196
|
-
assert_error_message("Color value 256 must be between 0 and 255
|
196
|
+
assert_error_message("Color value 256 must be between 0 and 255 for `rgb'",
|
197
197
|
"rgb(1, 1, 256)")
|
198
|
-
assert_error_message("Color value 256 must be between 0 and 255
|
198
|
+
assert_error_message("Color value 256 must be between 0 and 255 for `rgb'",
|
199
199
|
"rgb(1, 256, 257)")
|
200
|
-
assert_error_message("Color value -1 must be between 0 and 255
|
200
|
+
assert_error_message("Color value -1 must be between 0 and 255 for `rgb'",
|
201
201
|
"rgb(-1, 1, 1)")
|
202
202
|
end
|
203
203
|
|
204
204
|
def test_rgb_test_percent_bounds
|
205
|
-
assert_error_message("Color value 100.1% must be between 0% and 100%
|
205
|
+
assert_error_message("Color value 100.1% must be between 0% and 100% for `rgb'",
|
206
206
|
"rgb(100.1%, 0, 0)")
|
207
|
-
assert_error_message("Color value -0.1% must be between 0% and 100%
|
207
|
+
assert_error_message("Color value -0.1% must be between 0% and 100% for `rgb'",
|
208
208
|
"rgb(0, -0.1%, 0)")
|
209
|
-
assert_error_message("Color value 101% must be between 0% and 100%
|
209
|
+
assert_error_message("Color value 101% must be between 0% and 100% for `rgb'",
|
210
210
|
"rgb(0, 0, 101%)")
|
211
211
|
end
|
212
212
|
|
@@ -224,19 +224,19 @@ class SassFunctionTest < Test::Unit::TestCase
|
|
224
224
|
end
|
225
225
|
|
226
226
|
def test_rgb_tests_bounds
|
227
|
-
assert_error_message("Color value 256 must be between 0 and 255
|
227
|
+
assert_error_message("Color value 256 must be between 0 and 255 for `rgba'",
|
228
228
|
"rgba(256, 1, 1, 0.3)")
|
229
|
-
assert_error_message("Color value 256 must be between 0 and 255
|
229
|
+
assert_error_message("Color value 256 must be between 0 and 255 for `rgba'",
|
230
230
|
"rgba(1, 256, 1, 0.3)")
|
231
|
-
assert_error_message("Color value 256 must be between 0 and 255
|
231
|
+
assert_error_message("Color value 256 must be between 0 and 255 for `rgba'",
|
232
232
|
"rgba(1, 1, 256, 0.3)")
|
233
|
-
assert_error_message("Color value 256 must be between 0 and 255
|
233
|
+
assert_error_message("Color value 256 must be between 0 and 255 for `rgba'",
|
234
234
|
"rgba(1, 256, 257, 0.3)")
|
235
|
-
assert_error_message("Color value -1 must be between 0 and 255
|
235
|
+
assert_error_message("Color value -1 must be between 0 and 255 for `rgba'",
|
236
236
|
"rgba(-1, 1, 1, 0.3)")
|
237
|
-
assert_error_message("Alpha channel -0.2 must be between 0 and 1
|
237
|
+
assert_error_message("Alpha channel -0.2 must be between 0 and 1 for `rgba'",
|
238
238
|
"rgba(1, 1, 1, -0.2)")
|
239
|
-
assert_error_message("Alpha channel 1.2 must be between 0 and 1
|
239
|
+
assert_error_message("Alpha channel 1.2 must be between 0 and 1 for `rgba'",
|
240
240
|
"rgba(1, 1, 1, 1.2)")
|
241
241
|
end
|
242
242
|
|
@@ -733,15 +733,15 @@ class SassFunctionTest < Test::Unit::TestCase
|
|
733
733
|
|
734
734
|
def test_change_color_argument_errors
|
735
735
|
# Range
|
736
|
-
assert_error_message("Saturation must be between 0 and 100 for `change-color'",
|
736
|
+
assert_error_message("Saturation 101% must be between 0% and 100% for `change-color'",
|
737
737
|
"change-color(blue, $saturation: 101%)")
|
738
|
-
assert_error_message("Lightness must be between 0 and 100 for `change-color'",
|
738
|
+
assert_error_message("Lightness 101% must be between 0% and 100% for `change-color'",
|
739
739
|
"change-color(blue, $lightness: 101%)")
|
740
|
-
assert_error_message("Red value must be between 0 and 255 for `change-color'",
|
740
|
+
assert_error_message("Red value -1 must be between 0 and 255 for `change-color'",
|
741
741
|
"change-color(blue, $red: -1)")
|
742
|
-
assert_error_message("Green value must be between 0 and 255 for `change-color'",
|
742
|
+
assert_error_message("Green value 256 must be between 0 and 255 for `change-color'",
|
743
743
|
"change-color(blue, $green: 256)")
|
744
|
-
assert_error_message("Blue value must be between 0 and 255 for `change-color'",
|
744
|
+
assert_error_message("Blue value 500 must be between 0 and 255 for `change-color'",
|
745
745
|
"change-color(blue, $blue: 500)")
|
746
746
|
|
747
747
|
# Unknown argument
|
@@ -871,6 +871,7 @@ MSG
|
|
871
871
|
assert_equal("bool", evaluate("type-of(true)"))
|
872
872
|
assert_equal("color", evaluate("type-of(#fff)"))
|
873
873
|
assert_equal("color", evaluate("type-of($value: #fff)"))
|
874
|
+
assert_equal("null", evaluate("type-of(null)"))
|
874
875
|
end
|
875
876
|
|
876
877
|
def test_unit
|
@@ -1011,6 +1012,7 @@ MSG
|
|
1011
1012
|
def test_if
|
1012
1013
|
assert_equal("1px", evaluate("if(true, 1px, 2px)"))
|
1013
1014
|
assert_equal("2px", evaluate("if(false, 1px, 2px)"))
|
1015
|
+
assert_equal("2px", evaluate("if(null, 1px, 2px)"))
|
1014
1016
|
end
|
1015
1017
|
|
1016
1018
|
def test_keyword_args_rgb
|
@@ -1023,23 +1025,47 @@ MSG
|
|
1023
1025
|
end
|
1024
1026
|
|
1025
1027
|
def test_keyword_args_rgba_with_extra_args
|
1026
|
-
|
1028
|
+
evaluate("rgba($red: 255, $green: 255, $blue: 255, $alpha: 0.5, $extra: error)")
|
1029
|
+
flunk("Expected exception")
|
1027
1030
|
rescue Sass::SyntaxError => e
|
1028
|
-
assert_equal("Function rgba doesn't
|
1031
|
+
assert_equal("Function rgba doesn't have an argument named $extra", e.message)
|
1029
1032
|
end
|
1030
1033
|
|
1031
1034
|
def test_keyword_args_must_have_signature
|
1032
1035
|
evaluate("no-kw-args($fake: value)")
|
1036
|
+
flunk("Expected exception")
|
1033
1037
|
rescue Sass::SyntaxError => e
|
1034
1038
|
assert_equal("Function no_kw_args doesn't support keyword arguments", e.message)
|
1035
1039
|
end
|
1036
1040
|
|
1037
1041
|
def test_keyword_args_with_missing_argument
|
1038
1042
|
evaluate("rgb($red: 255, $green: 255)")
|
1043
|
+
flunk("Expected exception")
|
1039
1044
|
rescue Sass::SyntaxError => e
|
1040
1045
|
assert_equal("Function rgb requires an argument named $blue", e.message)
|
1041
1046
|
end
|
1042
1047
|
|
1048
|
+
def test_keyword_args_with_extra_argument
|
1049
|
+
evaluate("rgb($red: 255, $green: 255, $blue: 255, $purple: 255)")
|
1050
|
+
flunk("Expected exception")
|
1051
|
+
rescue Sass::SyntaxError => e
|
1052
|
+
assert_equal("Function rgb doesn't have an argument named $purple", e.message)
|
1053
|
+
end
|
1054
|
+
|
1055
|
+
def test_keyword_args_with_positional_and_keyword_argument
|
1056
|
+
evaluate("rgb(255, 255, 255, $red: 255)")
|
1057
|
+
flunk("Expected exception")
|
1058
|
+
rescue Sass::SyntaxError => e
|
1059
|
+
assert_equal("Function rgb was passed argument $red both by position and by name", e.message)
|
1060
|
+
end
|
1061
|
+
|
1062
|
+
def test_keyword_args_with_keyword_before_positional_argument
|
1063
|
+
evaluate("rgb($red: 255, 255, 255)")
|
1064
|
+
flunk("Expected exception")
|
1065
|
+
rescue Sass::SyntaxError => e
|
1066
|
+
assert_equal("Positional arguments must come before keyword arguments", e.message)
|
1067
|
+
end
|
1068
|
+
|
1043
1069
|
def test_only_var_args
|
1044
1070
|
assert_equal "only-var-args(2px, 3px, 4px)", evaluate("only-var-args(1px, 2px, 3px)")
|
1045
1071
|
end
|
@@ -1048,6 +1074,12 @@ MSG
|
|
1048
1074
|
assert_equal "only-kw-args(a, b, c)", evaluate("only-kw-args($a: 1, $b: 2, $c: 3)")
|
1049
1075
|
end
|
1050
1076
|
|
1077
|
+
## Regression Tests
|
1078
|
+
|
1079
|
+
def test_saturation_bounds
|
1080
|
+
assert_equal "#fbfdff", evaluate("hsl(hue(#fbfdff), saturation(#fbfdff), lightness(#fbfdff))")
|
1081
|
+
end
|
1082
|
+
|
1051
1083
|
private
|
1052
1084
|
|
1053
1085
|
def evaluate(value)
|
data/test/sass/script_test.rb
CHANGED
@@ -21,13 +21,13 @@ class SassScriptTest < Test::Unit::TestCase
|
|
21
21
|
include Sass::Script
|
22
22
|
|
23
23
|
def test_color_checks_input
|
24
|
-
assert_raise_message(ArgumentError, "Blue value must be between 0 and 255") {Color.new([1, 2, -1])}
|
25
|
-
assert_raise_message(ArgumentError, "Red value must be between 0 and 255") {Color.new([256, 2, 3])}
|
24
|
+
assert_raise_message(ArgumentError, "Blue value -1 must be between 0 and 255") {Color.new([1, 2, -1])}
|
25
|
+
assert_raise_message(ArgumentError, "Red value 256 must be between 0 and 255") {Color.new([256, 2, 3])}
|
26
26
|
end
|
27
27
|
|
28
28
|
def test_color_checks_rgba_input
|
29
|
-
assert_raise_message(ArgumentError, "Alpha channel must be between 0 and 1") {Color.new([1, 2, 3, 1.1])}
|
30
|
-
assert_raise_message(ArgumentError, "Alpha channel must be between 0 and 1") {Color.new([1, 2, 3, -0.1])}
|
29
|
+
assert_raise_message(ArgumentError, "Alpha channel 1.1 must be between 0 and 1") {Color.new([1, 2, 3, 1.1])}
|
30
|
+
assert_raise_message(ArgumentError, "Alpha channel -0.1 must be between 0 and 1") {Color.new([1, 2, 3, -0.1])}
|
31
31
|
end
|
32
32
|
|
33
33
|
def test_string_escapes
|
@@ -263,6 +263,10 @@ SASS
|
|
263
263
|
assert_equal "false", resolve("false")
|
264
264
|
end
|
265
265
|
|
266
|
+
def test_null
|
267
|
+
assert_equal "", resolve("null")
|
268
|
+
end
|
269
|
+
|
266
270
|
def test_boolean_ops
|
267
271
|
assert_equal "true", resolve("true and true")
|
268
272
|
assert_equal "true", resolve("false or true")
|
@@ -281,6 +285,18 @@ SASS
|
|
281
285
|
assert_equal "false", resolve("false and 1")
|
282
286
|
assert_equal "2", resolve("2 or 3")
|
283
287
|
assert_equal "3", resolve("2 and 3")
|
288
|
+
|
289
|
+
assert_equal "true", resolve("null or true")
|
290
|
+
assert_equal "true", resolve("true or null")
|
291
|
+
assert_equal "", resolve("null or null")
|
292
|
+
assert_equal "", resolve("null and true")
|
293
|
+
assert_equal "", resolve("true and null")
|
294
|
+
assert_equal "", resolve("null and null")
|
295
|
+
|
296
|
+
assert_equal "true", resolve("not null")
|
297
|
+
|
298
|
+
assert_equal "1", resolve("null or 1")
|
299
|
+
assert_equal "", resolve("null and 1")
|
284
300
|
end
|
285
301
|
|
286
302
|
def test_arithmetic_ops
|
@@ -326,6 +342,37 @@ SASS
|
|
326
342
|
assert_equal "false", resolve("3 <= 2")
|
327
343
|
end
|
328
344
|
|
345
|
+
def test_null_ops
|
346
|
+
assert_raise_message(Sass::SyntaxError,
|
347
|
+
'Invalid null operation: "null plus 1".') {eval("null + 1")}
|
348
|
+
assert_raise_message(Sass::SyntaxError,
|
349
|
+
'Invalid null operation: "null minus 1".') {eval("null - 1")}
|
350
|
+
assert_raise_message(Sass::SyntaxError,
|
351
|
+
'Invalid null operation: "null times 1".') {eval("null * 1")}
|
352
|
+
assert_raise_message(Sass::SyntaxError,
|
353
|
+
'Invalid null operation: "null div 1".') {eval("null / 1")}
|
354
|
+
assert_raise_message(Sass::SyntaxError,
|
355
|
+
'Invalid null operation: "null mod 1".') {eval("null % 1")}
|
356
|
+
assert_raise_message(Sass::SyntaxError,
|
357
|
+
'Invalid null operation: "1 plus null".') {eval("1 + null")}
|
358
|
+
assert_raise_message(Sass::SyntaxError,
|
359
|
+
'Invalid null operation: "1 minus null".') {eval("1 - null")}
|
360
|
+
assert_raise_message(Sass::SyntaxError,
|
361
|
+
'Invalid null operation: "1 times null".') {eval("1 * null")}
|
362
|
+
assert_raise_message(Sass::SyntaxError,
|
363
|
+
'Invalid null operation: "1 div null".') {eval("1 / null")}
|
364
|
+
assert_raise_message(Sass::SyntaxError,
|
365
|
+
'Invalid null operation: "1 mod null".') {eval("1 % null")}
|
366
|
+
assert_raise_message(Sass::SyntaxError,
|
367
|
+
'Invalid null operation: "1 gt null".') {eval("1 > null")}
|
368
|
+
assert_raise_message(Sass::SyntaxError,
|
369
|
+
'Invalid null operation: "null lt 1".') {eval("null < 1")}
|
370
|
+
assert_raise_message(Sass::SyntaxError,
|
371
|
+
'Invalid null operation: "null plus null".') {eval("null + null")}
|
372
|
+
assert_raise_message(Sass::SyntaxError,
|
373
|
+
'Invalid null operation: ""foo" plus null".') {eval("foo + null")}
|
374
|
+
end
|
375
|
+
|
329
376
|
def test_equals
|
330
377
|
assert_equal("true", resolve('"foo" == $foo', {},
|
331
378
|
env("foo" => Sass::Script::String.new("foo"))))
|
@@ -424,6 +471,15 @@ SASS
|
|
424
471
|
assert_raise_message(Sass::SyntaxError, "() isn't a valid CSS value.") {resolve("nth(append((), ()), 1)")}
|
425
472
|
end
|
426
473
|
|
474
|
+
def test_list_with_nulls
|
475
|
+
assert_equal "1, 2, 3", resolve("1, 2, null, 3")
|
476
|
+
assert_equal "1 2 3", resolve("1 2 null 3")
|
477
|
+
assert_equal "1, 2, 3", resolve("1, 2, 3, null")
|
478
|
+
assert_equal "1 2 3", resolve("1 2 3 null")
|
479
|
+
assert_equal "1, 2, 3", resolve("null, 1, 2, 3")
|
480
|
+
assert_equal "1 2 3", resolve("null 1 2 3")
|
481
|
+
end
|
482
|
+
|
427
483
|
def test_deep_argument_error_not_unwrapped
|
428
484
|
assert_raise_message(ArgumentError, 'wrong number of arguments (0 for 1)') {resolve("arg-error()")}
|
429
485
|
end
|
data/test/sass/scss/scss_test.rb
CHANGED
@@ -850,6 +850,16 @@ $zzz: zzz;
|
|
850
850
|
SCSS
|
851
851
|
end
|
852
852
|
|
853
|
+
def test_selector_interpolation_at_attr_end
|
854
|
+
assert_equal <<CSS, render(<<SCSS)
|
855
|
+
[foo=zzz] {
|
856
|
+
a: b; }
|
857
|
+
CSS
|
858
|
+
$zzz: zzz;
|
859
|
+
[foo=\#{$zzz}] { a: b; }
|
860
|
+
SCSS
|
861
|
+
end
|
862
|
+
|
853
863
|
def test_selector_interpolation_at_dashes
|
854
864
|
assert_equal <<CSS, render(<<SCSS)
|
855
865
|
div {
|
data/vendor/listen/CHANGELOG.md
CHANGED
@@ -1,8 +1,23 @@
|
|
1
|
+
## 0.4.2 - May 1, 2012
|
2
|
+
|
3
|
+
### Bug fixes
|
4
|
+
|
5
|
+
- [#21](https://github.com/guard/listen/issues/21): Issues when listening to changes in relative paths. (reported by [@akerbos][], fixed by [@Maher4Ever][])
|
6
|
+
- [#27](https://github.com/guard/listen/issues/27): Wrong reports for files modifications. (reported by [@cobychapple][], fixed by [@Maher4Ever][])
|
7
|
+
- Fix segmentation fault when profiling on Windows. ([@Maher4Ever][])
|
8
|
+
- Fix redundant watchers on Windows. ([@Maher4Ever][])
|
9
|
+
|
10
|
+
### Improvements
|
11
|
+
|
12
|
+
- [#17](https://github.com/guard/listen/issues/17): Use regexp-patterns with the `ignore` method instead of supplying paths. (reported by [@fny][], added by [@Maher4Ever][])
|
13
|
+
- Speed improvement when listening to changes in directories with ignored paths. ([@Maher4Ever][])
|
14
|
+
- Added `.rbx` and `.svn` to ignored directories. ([@Maher4Ever][])
|
15
|
+
|
1
16
|
## 0.4.1 - April 15, 2012
|
2
17
|
|
3
18
|
### Bug fixes
|
4
19
|
|
5
|
-
- [#18](https://github.com/guard/listen/issues/18): Listener crashes when removing directories with nested paths (reported by [@daemonza][], fixed by [@Maher4Ever][])
|
20
|
+
- [#18]((https://github.com/guard/listen/issues/18): Listener crashes when removing directories with nested paths. (reported by [@daemonza][], fixed by [@Maher4Ever][])
|
6
21
|
|
7
22
|
## 0.4.0 - April 9, 2012
|
8
23
|
|
@@ -70,3 +85,6 @@
|
|
70
85
|
[@thibaudgg]: https://github.com/thibaudgg
|
71
86
|
[@Maher4Ever]: https://github.com/Maher4Ever
|
72
87
|
[@daemonza]: https://github.com/daemonza
|
88
|
+
[@akerbos]: https://github.com/akerbos
|
89
|
+
[@fny]: https://github.com/fny
|
90
|
+
[@cobychapple]: https://github.com/cobychapple
|
data/vendor/listen/README.md
CHANGED
@@ -10,7 +10,7 @@ The Listen gem listens to file modifications and notifies you about the changes.
|
|
10
10
|
* Automatic fallback to polling if OS-specific adapter doesn't work.
|
11
11
|
* Detects files modification, addidation and removal.
|
12
12
|
* Checksum comparaison for modifications made under the same second.
|
13
|
-
* Allows
|
13
|
+
* Allows supplying regexp-patterns to ignore and filter paths for better results.
|
14
14
|
* Tested on all Ruby environments via [travis-ci](http://travis-ci.org/guard/listen).
|
15
15
|
|
16
16
|
## Install
|
@@ -26,18 +26,18 @@ There are **two ways** to use Listen:
|
|
26
26
|
1. Call `Listen.to` with either a single directory or multiple directories, then define the `change` callback in a block.
|
27
27
|
2. Create a `listener` object and use it in an (ARel style) chainable way.
|
28
28
|
|
29
|
-
Feel free to give your feeback via [Listen issues](https://github.com/guard/
|
29
|
+
Feel free to give your feeback via [Listen issues](https://github.com/guard/listen/issues)
|
30
30
|
|
31
31
|
### Block API
|
32
32
|
|
33
33
|
``` ruby
|
34
34
|
# Listen to a single directory.
|
35
|
-
Listen.to('dir/path/to/listen', filter:
|
35
|
+
Listen.to('dir/path/to/listen', filter: /\.rb$/, ignore: %r{ignored/path/}) do |modified, added, removed|
|
36
36
|
# ...
|
37
37
|
end
|
38
38
|
|
39
39
|
# Listen to multiple directories.
|
40
|
-
Listen.to('dir/to/awesome_app', 'dir/to/other_app', filter:
|
40
|
+
Listen.to('dir/to/awesome_app', 'dir/to/other_app', filter: /\.rb$/, latency: 0.1) do |modified, added, removed|
|
41
41
|
# ...
|
42
42
|
end
|
43
43
|
```
|
@@ -46,8 +46,8 @@ end
|
|
46
46
|
|
47
47
|
``` ruby
|
48
48
|
listener = Listen.to('dir/path/to/listen')
|
49
|
-
listener = listener.ignore(
|
50
|
-
listener = listener.filter(
|
49
|
+
listener = listener.ignore(%r{^ignored/path/})
|
50
|
+
listener = listener.filter(/\.rb$/)
|
51
51
|
listener = listener.latency(0.5)
|
52
52
|
listener = listener.force_polling(true)
|
53
53
|
listener = listener.polling_fallback_message(false)
|
@@ -59,8 +59,8 @@ listener.start # blocks execution!
|
|
59
59
|
|
60
60
|
``` ruby
|
61
61
|
Listen.to('dir/path/to/listen')
|
62
|
-
.ignore(
|
63
|
-
.filter(
|
62
|
+
.ignore(%r{^ignored/path/})
|
63
|
+
.filter(/\.rb$/)
|
64
64
|
.latency(0.5)
|
65
65
|
.force_polling(true)
|
66
66
|
.polling_fallback_message('custom message')
|
@@ -99,7 +99,7 @@ For an easier access, the `Listen.to` method can also be used to create a multi-
|
|
99
99
|
|
100
100
|
``` ruby
|
101
101
|
listener = Listen.to('app/css', 'app/js')
|
102
|
-
.ignore(
|
102
|
+
.ignore(%r{^vendor/}) # both js/vendor and css/vendor will be ignored
|
103
103
|
.change(&assets_callback)
|
104
104
|
|
105
105
|
listener.start # blocks execution!
|
@@ -184,15 +184,18 @@ end
|
|
184
184
|
These options can be set through `Listen.to` params or via methods (see the "Object" API)
|
185
185
|
|
186
186
|
```ruby
|
187
|
-
:filter =>
|
187
|
+
:filter => /\.rb$/, /\.coffee$/ # Filter files to listen to via a regexps list.
|
188
188
|
# default: none
|
189
189
|
|
190
|
-
:ignore =>
|
191
|
-
# default:
|
190
|
+
:ignore => %r{app/CMake/}, /\.pid$/ # Ignore a list of paths (root directory or sub-dir)
|
191
|
+
# default: See DEFAULT_IGNORED_DIRECTORIES and DEFAULT_IGNORED_EXTENSIONS in Listen::DirectoryRecord
|
192
192
|
|
193
193
|
:latency => 0.5 # Set the delay (**in seconds**) between checking for changes
|
194
194
|
# default: 0.1 sec (1.0 sec for polling)
|
195
195
|
|
196
|
+
:relative_paths => true # Enable the use of relative paths in the callback.
|
197
|
+
# default: false
|
198
|
+
|
196
199
|
:force_polling => true # Force the use of the polling adapter
|
197
200
|
# default: none
|
198
201
|
|
@@ -200,6 +203,18 @@ These options can be set through `Listen.to` params or via methods (see the "Obj
|
|
200
203
|
# default: "WARNING: Listen fallen back to polling, learn more at https://github.com/guard/listen#fallback."
|
201
204
|
```
|
202
205
|
|
206
|
+
### The patterns for filtering and ignoring paths
|
207
|
+
|
208
|
+
Just like the unix convention of beginning absolute paths with the
|
209
|
+
directory-separator (forward slash `/` in unix) and with no prefix for relative paths,
|
210
|
+
Listen doesn't prefix relative paths (to the watched directory) with a directory-separator.
|
211
|
+
|
212
|
+
Therefore make sure _NOT_ to prefix your regexp-patterns for filtering or ignoring paths
|
213
|
+
with a directory-separator, otherwise they won't work as expected.
|
214
|
+
|
215
|
+
As an example: to ignore the `build` directory in a C-project, use `%r{build/}`
|
216
|
+
and not `%r{/build/}`.
|
217
|
+
|
203
218
|
### Non-blocking listening to changes
|
204
219
|
|
205
220
|
Starting a listener blocks the current thread by default. That means any code after the
|
@@ -83,6 +83,14 @@ module Listen
|
|
83
83
|
@turnstile.signal # ensure no thread is blocked
|
84
84
|
end
|
85
85
|
|
86
|
+
# Returns whether the adapter is statred or not
|
87
|
+
#
|
88
|
+
# @return [Boolean] whether the adapter is started or not
|
89
|
+
#
|
90
|
+
def started?
|
91
|
+
@stop.nil? ? false : !@stop
|
92
|
+
end
|
93
|
+
|
86
94
|
# Blocks the main thread until the poll thread
|
87
95
|
# calls the callback.
|
88
96
|
#
|
@@ -129,7 +137,7 @@ module Listen
|
|
129
137
|
ensure
|
130
138
|
Thread.kill(t) if t
|
131
139
|
FileUtils.rm(test_file) if File.exists?(test_file)
|
132
|
-
adapter.stop
|
140
|
+
adapter.stop if adapter && adapter.started?
|
133
141
|
end
|
134
142
|
|
135
143
|
private
|
@@ -1,22 +1,33 @@
|
|
1
1
|
module Listen
|
2
2
|
module Adapters
|
3
3
|
|
4
|
-
# Watched INotify EVENTS
|
5
|
-
#
|
6
|
-
# @see http://www.tin.org/bin/man.cgi?section=7&topic=inotify
|
7
|
-
# @see https://github.com/nex3/rb-inotify/blob/master/lib/rb-inotify/notifier.rb#L99-L177
|
8
|
-
#
|
9
|
-
EVENTS = %w[recursive attrib close modify move create delete delete_self move_self]
|
10
|
-
|
11
4
|
# Listener implementation for Linux `inotify`.
|
12
5
|
#
|
13
6
|
class Linux < Adapter
|
14
7
|
|
8
|
+
# Watched inotify events
|
9
|
+
#
|
10
|
+
# @see http://www.tin.org/bin/man.cgi?section=7&topic=inotify
|
11
|
+
# @see https://github.com/nex3/rb-inotify/blob/master/lib/rb-inotify/notifier.rb#L99-L177
|
12
|
+
#
|
13
|
+
EVENTS = %w[recursive attrib close modify move create delete delete_self move_self]
|
14
|
+
|
15
|
+
# The message to show when the limit of inotify watchers is not enough
|
16
|
+
#
|
17
|
+
INOTIFY_LIMIT_MESSAGE = <<-EOS.gsub(/^\s*/, '')
|
18
|
+
Listen error: unable to monitor directories for changes.
|
19
|
+
|
20
|
+
Please head to https://github.com/guard/listen/wiki/Increasing-the-amount-of-inotify-watchers
|
21
|
+
for information on how to solve this issue.
|
22
|
+
EOS
|
23
|
+
|
15
24
|
# Initializes the Adapter. See {Listen::Adapter#initialize} for more info.
|
16
25
|
#
|
17
26
|
def initialize(directories, options = {}, &callback)
|
18
27
|
super
|
19
28
|
@worker = init_worker
|
29
|
+
rescue Errno::ENOSPC
|
30
|
+
abort(INOTIFY_LIMIT_MESSAGE)
|
20
31
|
end
|
21
32
|
|
22
33
|
# Starts the adapter.
|