From cd1773d5ae4a526185ce3e9566b764d69789bd62 Mon Sep 17 00:00:00 2001 From: Guido van Rossum <guido@python.org> Date: Mon, 29 Jan 2001 21:09:42 +0000 Subject: [PATCH] Implement revised TAL language: - z:omit is gone - new, separate command to loop over a subtree: <tag z:repeat="var expr"> - remove syntactic sugar from z:define (no "as"), z:attributes (no "=") - refactored a bit to accommodate this --- lib/python/TAL/TALVisitor.py | 121 ++++++++++++++++++----------------- 1 file changed, 61 insertions(+), 60 deletions(-) diff --git a/lib/python/TAL/TALVisitor.py b/lib/python/TAL/TALVisitor.py index 1052af688..b7600737a 100644 --- a/lib/python/TAL/TALVisitor.py +++ b/lib/python/TAL/TALVisitor.py @@ -131,11 +131,6 @@ class TALVisitor(CopyingDOMVisitor): if slotNode: self.visitElement(slotNode) return - if node.hasAttributeNS(ZOPE_TAL_NS, "omit"): - # XXX Question: should 'omit' be done before or after - # 'define'? (I.e., is it a shortcut for - # z:condition:"false" or is it stronger?) - return defines = node.getAttributeNS(ZOPE_TAL_NS, "define") if defines: self.engine.beginScope() @@ -155,18 +150,24 @@ class TALVisitor(CopyingDOMVisitor): attrDict = parseAttributeReplacements(attributes) insert = node.getAttributeNS(ZOPE_TAL_NS, "insert") replace = node.getAttributeNS(ZOPE_TAL_NS, "replace") - if not (insert or replace): - done = 0 - else: - if insert and replace: - print "Warning: z:insert overrides z:replace on the same node" - # XXX check for replace on documentElement - done = self.doModify(node, insert, insert or replace, attrDict) - if not done: - self.copyElement(node) - self.copyAttributes(node, attrDict) - self.visitAllChildren(node) - self.backUp() + repeat = node.getAttributeNS(ZOPE_TAL_NS, "repeat") + n = 0 + if insert: n = n+1 + if replace: n = n+1 + if repeat: n = n+1 + if n > 1: + print "Please use only one of z:insert, z:replace, z:repeat" + ok = 0 + if insert: + ok = self.doInsert(node, insert, attrDict) + if not ok and replace: + # XXX Check that this isn't the documentElement + ok = self.doReplace(node, replace, attrDict) + if not ok and repeat: + # XXX Check that this isn't the documentElement + ok = self.doRepeat(node, repeat, attrDict) + if not ok: + self.copySubtree(node, attrDict) def findMacro(self, macroName): # XXX This is not written for speed :-) @@ -191,7 +192,7 @@ class TALVisitor(CopyingDOMVisitor): def doDefine(self, arg): for part in splitParts(arg): m = re.match( - r"\s*(?:(global|local)\s+)?(%s)\s+as\s+(.*)" % NAME_RE, part) + r"\s*(?:(global|local)\s+)?(%s)\s+(.*)" % NAME_RE, part) if not m: print "Bad syntax in z:define argument:", `part` else: @@ -203,62 +204,33 @@ class TALVisitor(CopyingDOMVisitor): else: self.engine.setGlobal(name, value) - def doModify(self, node, inserting, arg, attrDict): - m = re.match( - r"(?:\s*(text|structure|for\s+(%s)\s+in)\s+)?(.*)" % NAME_RE, arg) - if not m: - print "Bad syntax in z:insert/replace:", `arg` - return 0 - key, name, expr = m.group(1, 2, 3) + def doInsert(self, node, arg, attrDict): + key, expr = parseSubstitution(arg) if not key: - key = "text" - saveNode = self.curNode - if key[:3] == "for": - if inserting: - rv = self.doInsertLoop(node, name, expr, attrDict) - else: - rv = self.doReplaceLoop(node, name, expr, attrDict) - else: - rv = self.doNonLoop(node, inserting, key, expr, attrDict) - self.curNode = saveNode - return rv - - def doInsertLoop(self, node, name, expr, attrDict): - sequence = self.engine.evaluateSequence(expr) + return 0 self.copyElement(node) self.copyAttributes(node, attrDict) - for item in sequence: - self.engine.setLocal(name, item) - self.visitAllChildren(node) + self.doSubstitution(key, expr, {}) self.backUp() return 1 - def doReplaceLoop(self, node, name, expr, attrDict): - if not self.newDocument: - print "Can't have a z:replace for loop on the documentElement" + def doReplace(self, node, arg, attrDict): + key, expr = parseSubstitution(arg) + if not key: return 0 - sequence = self.engine.evaluateSequence(expr) - for item in sequence: - self.engine.setLocal(name, item) - self.copyElement(node) - self.copyAttributes(node, attrDict) - self.visitAllChildren(node) - self.backUp() + self.doSubstitution(key, expr, attrDict) return 1 - def doNonLoop(self, node, inserting, key, expr, attrDict): - if inserting: - self.copyElement(node) - self.copyAttributes(node, attrDict) + def doSubstitution(self, key, expr, attrDict): if key == "text": - if attrDict and not inserting: + if attrDict: print "Warning: z:attributes unused for text replacement" data = self.engine.evaluateText(expr) newChild = self.newDocument.createTextNode(str(data)) self.curNode.appendChild(newChild) - if key == "structure": + elif key == "structure": data = self.engine.evaluateStructure(expr) - attrDone = inserting or not attrDict + attrDone = not attrDict for newChild in data: self.curNode.appendChild(newChild) if not attrDone and newChild.nodeType == Node.ELEMENT_NODE: @@ -267,8 +239,27 @@ class TALVisitor(CopyingDOMVisitor): if not attrDone: # Apparently no element nodes were inserted print "Warning: z:attributes unused for struct replacement" + + def doRepeat(self, node, arg, attrDict): + if not self.newDocument: + print "Can't have z:repeat on the documentElement" + return 0 + m = re.match("\s*(%s)\s+(.*)" % NAME_RE, arg) + if not m: + print "Bad syntax in z:repeat:", `arg` + return 0 + name, expr = m.group(1, 2) + iterator = self.engine.setupLoop(name, expr) + while iterator.next(): + self.copySubtree(node, attrDict) return 1 + def copySubtree(self, node, attrDict): + self.copyElement(node) + self.copyAttributes(node, attrDict) + self.visitAllChildren(node) + self.backUp() + def copyAttributes(self, node, attrDict): for attr in node.attributes.values(): namespaceURI = attr.namespaceURI @@ -294,7 +285,7 @@ class TALVisitor(CopyingDOMVisitor): def parseAttributeReplacements(arg): dict = {} for part in splitParts(arg): - m = re.match(r"\s*([^\s=]+)\s*=\s*(.*)", part) + m = re.match(r"\s*([^\s]+)\s*(.*)", part) if not m: print "Bad syntax in z:attributes:", `part` continue @@ -305,6 +296,16 @@ def parseAttributeReplacements(arg): dict[name] = expr return dict +def parseSubstitution(arg): + m = re.match(r"\s*(?:(text|structure)\s+)?(.*)", arg) + if not m: + print "Bad syntax in z:insert/replace:", `arg` + return None, None + key, expr = m.group(1, 2) + if not key: + key = "text" + return key, expr + def splitParts(arg): # Break in pieces at undoubled semicolons and # change double semicolons to singles: -- 2.30.9