summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEevee (Alex Munroe) <eevee.git@veekun.com>2014-08-26 18:08:49 -0700
committerEevee (Alex Munroe) <eevee.git@veekun.com>2014-08-26 18:08:49 -0700
commit6a8efa934d9a91c0916ecbc6659f275e25858bc6 (patch)
treeb5d490339631d2ffa144eeb26d81b66ee128883f
parent9f0c60e02e76d0fb06538160eb0b36df72abca1a (diff)
downloadpyscss-6a8efa934d9a91c0916ecbc6659f275e25858bc6.tar.gz
Partial support for slurpy named arguments.
-rw-r--r--scss/compiler.py14
-rw-r--r--scss/functions/core.py9
-rw-r--r--scss/src/grammar/grammar.g4
-rw-r--r--scss/tests/files/general/slurpy-keyword-args.css5
-rw-r--r--scss/tests/files/general/slurpy-keyword-args.scss12
-rw-r--r--scss/types.py17
6 files changed, 55 insertions, 6 deletions
diff --git a/scss/compiler.py b/scss/compiler.py
index 2394258..fa25e7e 100644
--- a/scss/compiler.py
+++ b/scss/compiler.py
@@ -30,11 +30,12 @@ from scss.rule import SassRule
from scss.rule import UnparsedBlock
from scss.selector import Selector
from scss.source import SourceFile
-from scss.types import Number
+from scss.types import Arglist
from scss.types import Boolean
-from scss.types import String
from scss.types import List
from scss.types import Null
+from scss.types import Number
+from scss.types import String
from scss.types import Undefined
from scss.types import Url
from scss.util import dequote
@@ -518,10 +519,15 @@ class Compilation(object):
if callee_argspec.slurp:
# Slurpy var gets whatever is left
+ # TODO should preserve the order of extra kwargs
+ sass_kwargs = []
+ for key, value in kwargs.items():
+ sass_kwargs.append((String(key[1:]), value))
callee_namespace.set_variable(
callee_argspec.slurp.name,
- List(args, use_comma=True))
+ Arglist(args, sass_kwargs))
args = []
+ kwargs = {}
elif callee_argspec.inject:
# Callee namespace gets all the extra kwargs whether declared or
# not
@@ -595,6 +601,8 @@ class Compilation(object):
ancestry=rule.ancestry,
nested=rule.nested,
)
+ # TODO supposed to throw an error if there's a slurpy arg
+ # but keywords() is never called on it
try:
self.manage_children(_rule, scope)
except SassReturn as e:
diff --git a/scss/functions/core.py b/scss/functions/core.py
index 1f6d30a..1fc830b 100644
--- a/scss/functions/core.py
+++ b/scss/functions/core.py
@@ -11,7 +11,7 @@ import math
from six.moves import xrange
from scss.functions.library import FunctionLibrary
-from scss.types import Boolean, Color, List, Null, Number, String, Map, expect_type
+from scss.types import Arglist, Boolean, Color, List, Null, Number, String, Map, expect_type
log = logging.getLogger(__name__)
@@ -783,6 +783,13 @@ def comparable(number1, number2):
and left.unit_denom == right.unit_denom)
+@register('keywords', 1)
+def keywords(value):
+ """Extract named arguments, as a map, from an argument list."""
+ expect_type(value, Arglist)
+ return value.extract_keywords()
+
+
# ------------------------------------------------------------------------------
# Miscellaneous
diff --git a/scss/src/grammar/grammar.g b/scss/src/grammar/grammar.g
index 870822e..6ef9262 100644
--- a/scss/src/grammar/grammar.g
+++ b/scss/src/grammar/grammar.g
@@ -52,8 +52,8 @@ parser SassExpression:
rule goal_argspec: argspec END {{ return argspec }}
# Arguments:
- # Note that at the moment, named arguments and slurpy arguments appear to
- # be incompatible.
+ # TODO should support multiple slurpies, and enforce (probably not in the
+ # parser) that positional args come first
rule argspec:
[
argspec_items {{ args, slurpy = argspec_items }}
diff --git a/scss/tests/files/general/slurpy-keyword-args.css b/scss/tests/files/general/slurpy-keyword-args.css
new file mode 100644
index 0000000..ce36647
--- /dev/null
+++ b/scss/tests/files/general/slurpy-keyword-args.css
@@ -0,0 +1,5 @@
+p {
+ left: 5px;
+ right: 10px;
+ leftovers: red, blue;
+}
diff --git a/scss/tests/files/general/slurpy-keyword-args.scss b/scss/tests/files/general/slurpy-keyword-args.scss
new file mode 100644
index 0000000..87f0b5e
--- /dev/null
+++ b/scss/tests/files/general/slurpy-keyword-args.scss
@@ -0,0 +1,12 @@
+@mixin accepts-basically-anything($args...) {
+ @each $key, $value in keywords($args) {
+ #{$key}: $value;
+ }
+ @if length($args) {
+ leftovers: $args;
+ }
+}
+
+p {
+ @include accepts-basically-anything(red, blue, $left: 5px, $right: 10px);
+}
diff --git a/scss/types.py b/scss/types.py
index 05973fe..5803b24 100644
--- a/scss/types.py
+++ b/scss/types.py
@@ -733,6 +733,23 @@ class List(Value):
return List([-item for item in self], use_comma=self.use_comma)
+class Arglist(List):
+ """An argument list. Acts mostly like a list, with keyword arguments sort
+ of tacked on separately, and only accessible via Python (or the Sass
+ `keywords` function).
+ """
+ sass_type_name = 'arglist'
+ keywords_retrieved = False
+
+ def __init__(self, args, kwargs):
+ self._kwargs = Map(kwargs)
+ super(Arglist, self).__init__(args, use_comma=True)
+
+ def extract_keywords(self):
+ self.keywords_retrieved = True
+ return self._kwargs
+
+
def _constrain(value, lb=0, ub=1):
"""Helper for Color constructors. Constrains a value to a range."""
if value < lb: