Commit 0fc919bd authored by Guido van Rossum's avatar Guido van Rossum

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 "=")

TALInterpreter needed no change.

Note that TALCompiler doesn't yet emit proper xmlns attributes.
parent 1d87aed7
...@@ -99,6 +99,7 @@ from DOMVisitor import DOMVisitor ...@@ -99,6 +99,7 @@ from DOMVisitor import DOMVisitor
from TALVisitor import ZOPE_TAL_NS, ZOPE_METAL_NS, NAME_RE from TALVisitor import ZOPE_TAL_NS, ZOPE_METAL_NS, NAME_RE
from TALVisitor import macroIndexer, slotIndexer from TALVisitor import macroIndexer, slotIndexer
from TALVisitor import splitParts, parseAttributeReplacements from TALVisitor import splitParts, parseAttributeReplacements
from TALVisitor import parseSubstitution
class TALCompiler(DOMVisitor): class TALCompiler(DOMVisitor):
...@@ -178,11 +179,6 @@ class TALCompiler(DOMVisitor): ...@@ -178,11 +179,6 @@ class TALCompiler(DOMVisitor):
self.compileElement(node) self.compileElement(node)
def compileElement(self, node): def compileElement(self, node):
if node.getAttributeNodeNS(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") defines = node.getAttributeNS(ZOPE_TAL_NS, "define")
if defines: if defines:
self.emit("beginScope") self.emit("beginScope")
...@@ -195,7 +191,7 @@ class TALCompiler(DOMVisitor): ...@@ -195,7 +191,7 @@ class TALCompiler(DOMVisitor):
def emitDefines(self, defines): def emitDefines(self, defines):
for part in splitParts(defines): for part in splitParts(defines):
m = re.match( 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: if not m:
print "Bad syntax in z:define argument:", `part` print "Bad syntax in z:define argument:", `part`
else: else:
...@@ -219,66 +215,63 @@ class TALCompiler(DOMVisitor): ...@@ -219,66 +215,63 @@ class TALCompiler(DOMVisitor):
def modifyingElement(self, node): def modifyingElement(self, node):
insert = node.getAttributeNS(ZOPE_TAL_NS, "insert") insert = node.getAttributeNS(ZOPE_TAL_NS, "insert")
replace = node.getAttributeNS(ZOPE_TAL_NS, "replace") replace = node.getAttributeNS(ZOPE_TAL_NS, "replace")
if not (insert or replace): repeat = node.getAttributeNS(ZOPE_TAL_NS, "repeat")
done = 0 n = 0
else: if insert: n = n+1
if insert and replace: if replace: n = n+1
print "Warning: z:insert overrides z:replace on the same node" if repeat: n = n+1
# XXX Check for z:replace in documentElement if n > 1:
done = self.doModify(node, insert, insert or replace) print "Please use only one of z:insert, z:replace, z:repeat"
if not done: ok = 0
if insert:
ok = self.doInsert(node, insert)
if not ok and replace:
# XXX Check that this isn't the documentElement
ok = self.doReplace(node, replace)
if not ok and repeat:
# XXX Check that this isn't the documentElement
ok = self.doRepeat(node, repeat)
if not ok:
self.emitElement(node) self.emitElement(node)
def doModify(self, node, inserting, arg): def doInsert(self, node, arg):
m = re.match( key, expr = parseSubstitution(arg)
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)
if not key: if not key:
key = "text" return 0
if key[:3] == "for":
if inserting:
self.doInsertLoop(node, name, expr)
else:
self.doReplaceLoop(node, name, expr)
else:
self.doNonLoop(node, inserting, key, expr)
return 1
def doInsertLoop(self, node, name, expr):
self.emitStartTag(node)
self.pushProgram()
self.visitAllChildren(node)
block = self.popProgram()
self.emit("loop", name, expr, block)
self.emitEndTag(node)
def doReplaceLoop(self, node, name, expr):
self.pushProgram()
self.emitElement(node)
block = self.popProgram()
self.emit("loop", name, expr, block)
def doNonLoop(self, node, inserting, key, expr):
if inserting:
self.emitStartTag(node) self.emitStartTag(node)
self.doInsert(node, key, expr) self.doSubstitution(key, expr, {})
self.emitEndTag(node) self.emitEndTag(node)
else: return 1
self.doInsert(node, key, expr)
def doInsert(self, node, key, expr): def doReplace(self, node, arg):
key, expr = parseSubstitution(arg)
if not key:
return 0
attrDict = getAttributeReplacements(node) attrDict = getAttributeReplacements(node)
self.doSubstitution(key, expr, attrDict)
return 1
def doSubstitution(self, key, expr, attrDict):
if key == "text": if key == "text":
if attrDict and not inserting: if attrDict:
print "Warning: z:attributes unused for text replacement" print "Warning: z:attributes unused for text replacement"
self.emit("insertText", expr) self.emit("insertText", expr)
else: else:
assert key == "structure" assert key == "structure"
self.emit("insertStructure", expr, attrDict) self.emit("insertStructure", expr, attrDict)
def doRepeat(self, node, arg):
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)
self.pushProgram()
self.emitElement(node)
block = self.popProgram()
self.emit("loop", name, expr, block)
return 1
def emitElement(self, node): def emitElement(self, node):
if not node.hasChildNodes(): if not node.hasChildNodes():
self.emitStartEndTag(node) self.emitStartEndTag(node)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment