Mercurial > genshi > genshi-test
comparison markup/template.py @ 65:5c024cf58ecb
Support the use of directives as elements to reduce the need for using `py:strip`.
author | cmlenz |
---|---|
date | Sun, 09 Jul 2006 15:23:26 +0000 |
parents | 33c2702cf6da |
children | 822089ae65ce |
comparison
equal
deleted
inserted
replaced
64:c612c73ae4ec | 65:5c024cf58ecb |
---|---|
29 * py:match directives use (basic) XPath expressions to match against input | 29 * py:match directives use (basic) XPath expressions to match against input |
30 nodes, making match templates more powerful while keeping the syntax simple | 30 nodes, making match templates more powerful while keeping the syntax simple |
31 | 31 |
32 Todo items: | 32 Todo items: |
33 * Improved error reporting | 33 * Improved error reporting |
34 * Support for using directives as elements and not just as attributes, reducing | |
35 the need for wrapper elements with py:strip="" | |
36 * Support for list comprehensions and generator expressions in expressions | 34 * Support for list comprehensions and generator expressions in expressions |
37 | 35 |
38 Random thoughts: | 36 Random thoughts: |
39 * Is there any need to support py:extends and/or py:layout? | 37 * Is there any need to support py:extends and/or py:layout? |
40 * Could we generate byte code from expressions? | 38 * Could we generate byte code from expressions? |
307 </p> | 305 </p> |
308 </div> | 306 </div> |
309 """ | 307 """ |
310 __slots__ = ['name', 'args', 'defaults', 'stream', 'directives'] | 308 __slots__ = ['name', 'args', 'defaults', 'stream', 'directives'] |
311 | 309 |
310 ATTRIBUTE = 'function' | |
311 | |
312 def __init__(self, args): | 312 def __init__(self, args): |
313 Directive.__init__(self, None) | 313 Directive.__init__(self, None) |
314 ast = compiler.parse(args, 'eval').node | 314 ast = compiler.parse(args, 'eval').node |
315 self.args = [] | 315 self.args = [] |
316 self.defaults = {} | 316 self.defaults = {} |
361 <li>1</li><li>2</li><li>3</li> | 361 <li>1</li><li>2</li><li>3</li> |
362 </ul> | 362 </ul> |
363 """ | 363 """ |
364 __slots__ = ['targets'] | 364 __slots__ = ['targets'] |
365 | 365 |
366 ATTRIBUTE = 'each' | |
367 | |
366 def __init__(self, value): | 368 def __init__(self, value): |
367 targets, value = value.split(' in ', 1) | 369 targets, value = value.split(' in ', 1) |
368 self.targets = [str(name.strip()) for name in targets.split(',')] | 370 self.targets = [str(name.strip()) for name in targets.split(',')] |
369 Directive.__init__(self, value) | 371 Directive.__init__(self, value) |
370 | 372 |
401 <b>Hello</b> | 403 <b>Hello</b> |
402 </div> | 404 </div> |
403 """ | 405 """ |
404 __slots__ = [] | 406 __slots__ = [] |
405 | 407 |
408 ATTRIBUTE = 'test' | |
409 | |
406 def __call__(self, stream, ctxt, directives): | 410 def __call__(self, stream, ctxt, directives): |
407 if self.expr.evaluate(ctxt): | 411 if self.expr.evaluate(ctxt): |
408 return self._apply_directives(stream, ctxt, directives) | 412 return self._apply_directives(stream, ctxt, directives) |
409 return [] | 413 return [] |
410 | 414 |
424 Hello Dude | 428 Hello Dude |
425 </span> | 429 </span> |
426 </div> | 430 </div> |
427 """ | 431 """ |
428 __slots__ = ['path', 'stream'] | 432 __slots__ = ['path', 'stream'] |
433 | |
434 ATTRIBUTE = 'path' | |
429 | 435 |
430 def __init__(self, value): | 436 def __init__(self, value): |
431 Directive.__init__(self, None) | 437 Directive.__init__(self, None) |
432 self.path = Path(value) | 438 self.path = Path(value) |
433 self.stream = [] | 439 self.stream = [] |
563 `py:when` or `py:otherwise` block. Behavior is also undefined if a | 569 `py:when` or `py:otherwise` block. Behavior is also undefined if a |
564 `py:otherwise` occurs before `py:when` blocks. | 570 `py:otherwise` occurs before `py:when` blocks. |
565 """ | 571 """ |
566 __slots__ = ['matched', 'value'] | 572 __slots__ = ['matched', 'value'] |
567 | 573 |
574 ATTRIBUTE = 'test' | |
575 | |
568 def __call__(self, stream, ctxt, directives): | 576 def __call__(self, stream, ctxt, directives): |
569 if self.expr: | 577 if self.expr: |
570 self.value = self.expr.evaluate(ctxt) | 578 self.value = self.expr.evaluate(ctxt) |
571 self.matched = False | 579 self.matched = False |
572 ctxt.push(_choose=self) | 580 ctxt.push(_choose=self) |
579 """Implementation of the `py:when` directive for nesting in a parent with | 587 """Implementation of the `py:when` directive for nesting in a parent with |
580 the `py:choose` directive. | 588 the `py:choose` directive. |
581 | 589 |
582 See the documentation of `py:choose` for usage. | 590 See the documentation of `py:choose` for usage. |
583 """ | 591 """ |
592 | |
593 ATTRIBUTE = 'test' | |
594 | |
584 def __call__(self, stream, ctxt, directives): | 595 def __call__(self, stream, ctxt, directives): |
585 choose = ctxt['_choose'] | 596 choose = ctxt['_choose'] |
586 if choose.matched: | 597 if choose.matched: |
587 return [] | 598 return [] |
588 value = self.expr.evaluate(ctxt) | 599 value = self.expr.evaluate(ctxt) |
685 | 696 |
686 elif kind is Stream.START: | 697 elif kind is Stream.START: |
687 # Record any directive attributes in start tags | 698 # Record any directive attributes in start tags |
688 tag, attrib = data | 699 tag, attrib = data |
689 directives = [] | 700 directives = [] |
701 strip = False | |
702 | |
703 if tag in self.NAMESPACE: | |
704 cls = self._dir_by_name.get(tag.localname) | |
705 if cls is None: | |
706 raise BadDirectiveError(tag, pos[0], pos[1]) | |
707 directives.append(cls(attrib.get(getattr(cls, 'ATTRIBUTE', None), ''))) | |
708 strip = True | |
709 | |
690 new_attrib = [] | 710 new_attrib = [] |
691 for name, value in attrib: | 711 for name, value in attrib: |
692 if name in self.NAMESPACE: | 712 if name in self.NAMESPACE: |
693 cls = self._dir_by_name.get(name.localname) | 713 cls = self._dir_by_name.get(name.localname) |
694 if cls is None: | 714 if cls is None: |
695 raise BadDirectiveError(name, self.filename, pos[1]) | 715 raise BadDirectiveError(name, pos[0], pos[1]) |
696 else: | 716 directives.append(cls(value)) |
697 directives.append(cls(value)) | |
698 else: | 717 else: |
699 value = list(self._interpolate(value, *pos)) | 718 value = list(self._interpolate(value, *pos)) |
700 new_attrib.append((name, value)) | 719 new_attrib.append((name, value)) |
720 | |
701 if directives: | 721 if directives: |
702 directives.sort(lambda a, b: cmp(self._dir_order.index(a.__class__), | 722 directives.sort(lambda a, b: cmp(self._dir_order.index(a.__class__), |
703 self._dir_order.index(b.__class__))) | 723 self._dir_order.index(b.__class__))) |
704 dirmap[(depth, tag)] = (directives, len(stream)) | 724 dirmap[(depth, tag)] = (directives, len(stream), strip) |
705 | 725 |
706 stream.append((kind, (tag, Attributes(new_attrib)), pos)) | 726 stream.append((kind, (tag, Attributes(new_attrib)), pos)) |
707 depth += 1 | 727 depth += 1 |
708 | 728 |
709 elif kind is Stream.END: | 729 elif kind is Stream.END: |
711 stream.append((kind, data, pos)) | 731 stream.append((kind, data, pos)) |
712 | 732 |
713 # If there have have directive attributes with the corresponding | 733 # If there have have directive attributes with the corresponding |
714 # start tag, move the events inbetween into a "subprogram" | 734 # start tag, move the events inbetween into a "subprogram" |
715 if (depth, data) in dirmap: | 735 if (depth, data) in dirmap: |
716 directives, start_offset = dirmap.pop((depth, data)) | 736 directives, start_offset, strip = dirmap.pop((depth, data)) |
717 substream = stream[start_offset:] | 737 substream = stream[start_offset:] |
738 if strip: | |
739 substream = substream[1:-1] | |
718 stream[start_offset:] = [(Template.SUB, | 740 stream[start_offset:] = [(Template.SUB, |
719 (directives, substream), pos)] | 741 (directives, substream), pos)] |
720 | 742 |
721 elif kind is Stream.TEXT: | 743 elif kind is Stream.TEXT: |
722 for kind, data, pos in self._interpolate(data, *pos): | 744 for kind, data, pos in self._interpolate(data, *pos): |