Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Add support for decrementing for-loops #923

Merged
merged 1 commit into from

3 participants

@robinroestenburg

PR to implement decrementing for-loops as discussed in issue #691 (sorry, couldn't get Hub to attach the pull-request to the issue directly).

From the CHANGELOG:

It is now possible to create decrementing loops using the default @for-directive. For example:

    .foo {
      @for $var from 5 through 1 { a: $var }
    }

Produces:

    .foo {
      a: 5;
      a: 4;
      a: 3;
      a: 2;
      a: 1; }

I did not add the by part to the @for loop as suggested by @chriseppstein in issue #691. I'd be happy to implement this in another PR.

I am a bit unsure about adding the constants to the ForNode, they seem a bit out of place there. At first I was going to calculate the direction of the loop in the ForNode as well, but you can't do that because the environment can change the values of from and to later on, right?

Let me know what you think!

@chriseppstein

This breaks in ruby 1.8.7

@chriseppstein

Thanks for the patch, it needs to be reworked before we can accept it. Please address the comments from the code review.

@robinroestenburg

I have addressed the various comments from your code review, thanks for that.
Just let me know if you have any other comments.

@chriseppstein

Looks good to me. All merges are currently blocked pending #850.

@nex3 nex3 referenced this pull request from a commit
@nex3 nex3 Merge branch 'decrementing-loops'
Conflicts:
	doc-src/SASS_CHANGELOG.md

Closes #923
Closes #691
64ce155
@nex3 nex3 merged commit d284a26 into from
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Sep 19, 2013
  1. @robinroestenburg
This page is out of date. Refresh to see the latest.
View
21 doc-src/SASS_CHANGELOG.md
@@ -5,6 +5,27 @@
## 3.3.0 (Unreleased)
+### Decrementing for-loops
+
+It is now possible to create decrementing loops using the default `@for`
+directive by having the `from` number be larger than the `to` number. For
+example:
+
+ .foo {
+ @for $var from 5 through 1 { a: $var }
+ }
+
+Produces:
+
+ .foo {
+ a: 5;
+ a: 4;
+ a: 3;
+ a: 2;
+ a: 1; }
+
+Thanks to [Robin Roestenburg](http://twitter.com/robinroest).
+
### Using `&` in SassScript
For a long time, Sass has supported a special
View
3  doc-src/SASS_REFERENCE.md
@@ -1903,7 +1903,8 @@ counter variable is used to adjust the output. The directive has two forms:
`@for $var from <start> through <end>` and `@for $var from <start> to <end>`.
Note the difference in the keywords `through` and `to`. `$var` can be any
variable name, like `$i`; `<start>` and `<end>` are SassScript expressions that
-should return integers.
+should return integers. When `<start>` is greater than `<end>` the counter will
+decrement instead of increment.
The `@for` statement sets `$var` to each successive number in the specified
range and each time outputs the nested styles using that value of `$var`. For
View
2  lib/sass/script/value/number.rb
@@ -15,7 +15,7 @@ class Number < Base
# A list of units in the numerator of the number.
# For example, `1px*em/in*cm` would return `["px", "em"]`
- # @return [Array<String>]
+ # @return [Array<String>]
attr_reader :numerator_units
# A list of units in the denominator of the number.
View
7 lib/sass/tree/visitors/perform.rb
@@ -185,13 +185,14 @@ def visit_for(node)
to.assert_int!
to = to.coerce(from.numerator_units, from.denominator_units)
- range = Range.new(from.to_i, to.to_i, node.exclusive)
+ direction = from.to_i > to.to_i ? -1 : 1
+ range = Range.new(direction * from.to_i, direction * to.to_i, node.exclusive)
with_environment Sass::Environment.new(@environment) do
range.map do |i|
@environment.set_local_var(node.var,
- Sass::Script::Value::Number.new(i, from.numerator_units, from.denominator_units))
- node.children.map {|c| visit(c)}
+ Sass::Script::Value::Number.new(direction * i, from.numerator_units, from.denominator_units))
+ node.children.map { |c| visit(c) }
end.flatten
end
end
View
41 test/sass/scss/scss_test.rb
@@ -161,6 +161,47 @@ def test_for_directive
@for $var from 1 through 5 {a: $var;}
}
SCSS
+
+ assert_equal <<CSS, render(<<SCSS)
+CSS
+.foo {
+ @for $var from 1 to 1 {a: $var;}
+}
+SCSS
+
+ assert_equal <<CSS, render(<<SCSS)
+.foo {
+ a: 1; }
+CSS
+.foo {
+ @for $var from 1 through 1 {a: $var;}
+}
+SCSS
+
+ assert_equal <<CSS, render(<<SCSS)
+.foo {
+ a: 5;
+ a: 4;
+ a: 3;
+ a: 2;
+ a: 1; }
+CSS
+.foo {
+ @for $var from 5 through 1 {a: $var;}
+}
+SCSS
+
+ assert_equal <<CSS, render(<<SCSS)
+.foo {
+ a: 5;
+ a: 4;
+ a: 3;
+ a: 2; }
+CSS
+.foo {
+ @for $var from 5 to 1 {a: $var;}
+}
+SCSS
end
def test_if_directive
Something went wrong with that request. Please try again.