Skip to content

Commit

Permalink
Allow negative indices in nth list function
Browse files Browse the repository at this point in the history
Allow negative indices between -1 and (-1 * list length) in the `nth`
function.
  • Loading branch information
ggilder committed Jun 17, 2013
1 parent 9c8ae29 commit 2f83fec
Show file tree
Hide file tree
Showing 3 changed files with 14 additions and 10 deletions.
2 changes: 2 additions & 0 deletions doc-src/SASS_CHANGELOG.md
Expand Up @@ -59,6 +59,8 @@ Thanks to Alexander Pavlov for implementing this.
* Add a function \{Sass::Script::Function#unique\_id `unique-id()`} that will
return a CSS identifier that is unique within the scope of a single CSS file.

* Allow negative indices into lists when using `nth()`.

### Backwards Incompatibilities -- Must Read!

* Sass will now throw an error when `@extend` is used to extend a selector
Expand Down
14 changes: 7 additions & 7 deletions lib/sass/script/functions.rb
Expand Up @@ -1486,23 +1486,23 @@ def length(list)
# @example
# nth(10px 20px 30px, 1) => 10px
# nth((Helvetica, Arial, sans-serif), 3) => sans-serif
# nth((red, green, blue), -2) => green

This comment has been minimized.

Copy link
@nex3

nex3 Jun 17, 2013

This needs to be described in the main body of the documentation. It's not going to be obvious to most people that the -1st item in the list is the last one.

# @param list [Value] The list
# @param n [Sass::Script::Value::Number] The index into the list
# @return [Sass::Script::Value::Base] The nth item in the list
# @raise [ArgumentError] If `n` isn't an integer between 1 and the list's length.
# @raise [ArgumentError] If `n` isn't an integer whose absolute value is between 1 and the list's length.
def nth(list, n)
assert_type n, :Number
if !n.int?
raise ArgumentError.new("List index #{n} must be an integer")
elsif n.to_i < 1
raise ArgumentError.new("List index #{n} must be greater than or equal to 1")
if !n.int? || n.to_i == 0
raise ArgumentError.new("List index #{n} must be a non-zero integer")
elsif list.to_a.size == 0
raise ArgumentError.new("List index is #{n} but list has no items")
elsif n.to_i > (size = list.to_a.size)
elsif n.to_i.abs > (size = list.to_a.size)
raise ArgumentError.new("List index is #{n} but list is only #{size} item#{'s' if size != 1} long")
end

list.to_a[n.to_i - 1]
index = n.to_i > 0 ? n.to_i - 1 : n.to_i
list.to_a[index]
end
declare :nth, [:list, :n]

Expand Down
8 changes: 5 additions & 3 deletions test/sass/functions_test.rb
Expand Up @@ -1017,12 +1017,14 @@ def test_length
def test_nth
assert_equal("1", evaluate("nth(1 2 3, 1)"))
assert_equal("2", evaluate("nth(1 2 3, 2)"))
assert_equal("3", evaluate("nth(1 2 3, -1)"))
assert_equal("1", evaluate("nth(1 2 3, -3)"))
assert_equal("3", evaluate("nth((1, 2, 3), 3)"))
assert_equal("foo", evaluate("nth(foo, 1)"))
assert_equal("bar baz", evaluate("nth(foo (bar baz) bang, 2)"))
assert_error_message("List index 0 must be greater than or equal to 1 for `nth'", "nth(foo, 0)")
assert_error_message("List index -10 must be greater than or equal to 1 for `nth'", "nth(foo, -10)")
assert_error_message("List index 1.5 must be an integer for `nth'", "nth(foo, 1.5)")
assert_error_message("List index 0 must be a non-zero integer for `nth'", "nth(foo, 0)")
assert_error_message("List index is -10 but list is only 1 item long for `nth'", "nth(foo, -10)")
assert_error_message("List index 1.5 must be a non-zero integer for `nth'", "nth(foo, 1.5)")
assert_error_message("List index is 5 but list is only 4 items long for `nth'", "nth(1 2 3 4, 5)")
assert_error_message("List index is 2 but list is only 1 item long for `nth'", "nth(foo, 2)")
assert_error_message("List index is 1 but list has no items for `nth'", "nth((), 1)")
Expand Down

0 comments on commit 2f83fec

Please sign in to comment.