From 84379359f5759c735f7c4e1f2b8069e3940ad567 Mon Sep 17 00:00:00 2001 From: jtm Date: Sun, 18 Mar 2012 10:08:36 +0000 Subject: [PATCH] checkpoint mixins --- lesscpy/lessc/parser.py | 43 ++++++++++++++++------------- lesscpy/lessc/scope.py | 1 + lesscpy/lessc/utility.py | 21 +++++++++++--- lesscpy/plib/block.py | 15 ++++++---- lesscpy/plib/mixin.py | 13 +++++++-- lesscpy/test/less/mixin-args.less | 14 ++++++++++ lesscpy/test/less/mixin-blocks.less | 2 +- 7 files changed, 78 insertions(+), 31 deletions(-) diff --git a/lesscpy/lessc/parser.py b/lesscpy/lessc/parser.py index fcc7a36..12b7dc5 100644 --- a/lesscpy/lessc/parser.py +++ b/lesscpy/lessc/parser.py @@ -18,6 +18,18 @@ from . import utility from .scope import Scope from .color import Color from lesscpy.plib import * + +class Deferred(object): + def __init__(self, mixin, args): + """ + """ + self.mixin = mixin + self.args = args + + def parse(self, scope): + """ + """ + return self.mixin.call(scope, self.args) class LessParser(object): precedence = ( @@ -82,21 +94,7 @@ class LessParser(object): def scopemap(self): """ Output scopemap. """ - if self.result: - self._scopemap_aux(self.result) - - def _scopemap_aux(self, ll, lvl=0): - pad = ''.join(['\t.'] * lvl) - t = type(ll) - if t is list: - for p in ll: - self._scopemap_aux(p, lvl) - elif hasattr(ll, 'tokens'): - if t is Block: - print(pad, ll.name) - else: - print(pad, t) - self._scopemap_aux(list(utility.flatten(ll.tokens)), lvl+1) + utility.debug_print(self.result) # # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -178,7 +176,8 @@ class LessParser(object): """ try: block = Block(list(p)[1:-1], p.lineno(3)) - block.parse(self.scope) + if not self.scope.in_mixin: + block.parse(self.scope) p[0] = block except SyntaxError as e: self.handle_error(e, p.lineno(3)) @@ -201,7 +200,7 @@ class LessParser(object): except SyntaxError as e: self.handle_error(e, p.lineno(2)) else: - self.handle_error('Call unknown mixin `%s`' % p[1], p.lineno(2)) + self.handle_error('Call unknown block `%s`' % m.raw(), p.lineno(2)) def p_block_open(self, p): """ block_open : identifier brace_open @@ -224,6 +223,7 @@ class LessParser(object): """ self.scope.add_mixin(Mixin(list(p)[1:], p.lineno(3)).parse(self.scope)) self.scope.pop() + self.scope.in_mixin = False p[0] = None def p_open_mixin(self, p): @@ -231,6 +231,7 @@ class LessParser(object): | id t_popen mixin_args t_pclose brace_open """ p[0] = [p[1][0], p[3]] + self.scope.in_mixin = True def p_call_mixin(self, p): """ call_mixin : class t_popen mixin_args t_pclose ';' @@ -239,7 +240,10 @@ class LessParser(object): mixin = self.scope.mixins(p[1][0]) if mixin: try: - p[0] = mixin.call(self.scope, p[3]) + if self.scope.in_mixin: + p[0] = Deferred(mixin, p[3]) + else: + p[0] = mixin.call(self.scope, p[3]) except SyntaxError as e: self.handle_error(e, p.lineno(2)) else: @@ -309,7 +313,7 @@ class LessParser(object): v.parse(self.scope) self.scope.add_variable(v) except SyntaxError as e: - self.handle_error(e, p) + self.handle_error(e, p.lineno(2)) p[0] = None # @@ -702,6 +706,7 @@ class LessParser(object): @param Parser token: Parser token @param string: Error level """ +# print(e.trace()) if self.verbose: color = '\x1b[31m' if t == 'E' else '\x1b[33m' print("%s%s: line: %d: %s\n" % (color, t, line, e), end='\x1b[0m') diff --git a/lesscpy/lessc/scope.py b/lesscpy/lessc/scope.py index 6a104d5..0ca70ce 100644 --- a/lesscpy/lessc/scope.py +++ b/lesscpy/lessc/scope.py @@ -7,6 +7,7 @@ class Scope(list): super().__init__() self._mixins = {} if init: self.push() + self.in_mixin = False def push(self): """ diff --git a/lesscpy/lessc/utility.py b/lesscpy/lessc/utility.py index 0182099..0fc320d 100644 --- a/lesscpy/lessc/utility.py +++ b/lesscpy/lessc/utility.py @@ -31,7 +31,7 @@ def pairwise(lst): yield lst[i], lst[i+1] yield lst[-1], None -def rename(ll, fr, scope): +def rename(ll, scope): """ Rename all sub-blocks moved under another block. (mixins) """ @@ -40,16 +40,29 @@ def rename(ll, fr, scope): p.name.parse(scope) scope.push() scope.current = p.name - if p.inner: rename(p.inner, fr, scope) + if p.inner: rename(p.inner, scope) def blocksearch(block, name): """ Recursive search for name in block """ for b in block.inner: - return (b if b.raw() == name - else blocksearch(b, name)) + b = (b if b.raw() == name + else blocksearch(b, name)) + if b: return b return False +def debug_print(ll, lvl=0): + """ + """ + pad = ''.join(['\t.'] * lvl) + t = type(ll) + if t is list: + for p in ll: + debug_print(p, lvl) + elif hasattr(ll, 'tokens'): + print(pad, t) + debug_print(list(flatten(ll.tokens)), lvl+1) + def destring(v): """ Strip quotes @param string: value diff --git a/lesscpy/plib/block.py b/lesscpy/plib/block.py index 404bc05..4b98563 100644 --- a/lesscpy/plib/block.py +++ b/lesscpy/plib/block.py @@ -19,13 +19,18 @@ class Block(Node): self.inner = [] else: self. inner = [p for p in inner - if p and type(p) is type(self)] + if p and type(p) is type(self)] if self.inner: self.inner = [p.parse(scope) for p in self.inner] return self def raw(self): - return self.name.raw() + """ + """ + try: + return self.name.raw() + except AttributeError: + pass def fmt(self, fills): """ @@ -58,9 +63,9 @@ class Block(Node): """ """ if self.tokens[1]: - tokens = copy.deepcopy(self.tokens) + tokens = copy.deepcopy(self.tokens[1]) scope = copy.deepcopy(scope) - out = [p for p in tokens[1] if p] - utility.rename(out, self.name, scope) + out = [p for p in tokens if p] + utility.rename(out, scope) return out return None diff --git a/lesscpy/plib/mixin.py b/lesscpy/plib/mixin.py index b00e2ed..a5c6083 100644 --- a/lesscpy/plib/mixin.py +++ b/lesscpy/plib/mixin.py @@ -28,7 +28,9 @@ class Mixin(Node): args = args if type(args) is list else [args] vars = [] for arg, var in itertools.zip_longest([a for a in args if a != ','], parsed): - if type(var) is Variable: + if arg == var and utility.is_variable(arg): + continue + elif type(var) is Variable: if arg: var.value = arg elif utility.is_variable(arg): tmp = scope.variables(arg) @@ -55,6 +57,13 @@ class Mixin(Node): """ scope = copy.deepcopy(scope) body = copy.deepcopy(self.body) + self.parse_args(args, scope) scope.update([self.scope], -1) - return body.parse(scope).copy(scope) + + body.parse(scope) + r = list(utility.flatten([body.parsed, body.inner])) + + utility.rename(r, scope) + + return r diff --git a/lesscpy/test/less/mixin-args.less b/lesscpy/test/less/mixin-args.less index e40b83f..51c8b18 100644 --- a/lesscpy/test/less/mixin-args.less +++ b/lesscpy/test/less/mixin-args.less @@ -106,4 +106,18 @@ } .arguments4 { .arguments_empty(1px solid red); +} +// +// filter mixins +// +.placeholder(@color: #000) { + :-moz-placeholder { + color: @color; + } + &::-webkit-input-placeholder { + color: @color; + } +} +.div { + .placeholder(#fff); } \ No newline at end of file diff --git a/lesscpy/test/less/mixin-blocks.less b/lesscpy/test/less/mixin-blocks.less index 11b02e3..bf4f25a 100644 --- a/lesscpy/test/less/mixin-blocks.less +++ b/lesscpy/test/less/mixin-blocks.less @@ -91,4 +91,4 @@ div.nest { } .secure-zone { #namespace .biohazard .man; -} +} \ No newline at end of file