From: Chuck E. <ec...@mi...> - 2001-04-06 21:52:29
|
What if you took DTML and did this to it? * Change <dtml-...> convention to [...] convention. Reasons: - Instructions in square brackets will never be munged by HTML Editors. - The HTML designer can preview the template in a web page and see where things are (something my designers have requested). - "[]" is less typing than "<dtml->" - "[]" is rarely, if ever, used in regular text, filenames or HTML. * With regards to namespace stacking, and the default means of using these templates in WebKit: don't stack the name spaces. The default namespace would be app, request, response, servlet, session. Using dotted notation (provided by NamedValueAccess), you could go from there. Using custom subclasses of Page, you could add more names to the space, like "user". Reason: Keep things simple. Avoid strange substitutions resulting from a big namespace stack. * Remove general expressions. And hence, the distinction between a dtml name and a dtml expression. Reason: Don't need this for a simple templating language for designers. * Remove most of the programmatic commands like: if, raise, return, sql*, try, with Reason: Keep programming in Python objects where it belongs. * Regarding WebKit integration, follow PSP's lead and allow the template to optionally specify its superclass and method. What's left after this is something that is easy to learn and use and discourages "programming in HTML". There are a lot of nice options for dtml-var and dtml-in. Also, those options come in an HTML style (foo=bar baz=biz) that HTML designers already know. Here's the DTML reference: http://www.zope.org/Members/michel/ZB/AppendixA.dtml What do you think of this approach from a design point of view? -Chuck |
From: Tavis R. <ta...@ca...> - 2001-04-07 20:23:13
|
> r"[^%]*%\[([^\]]+)\]" > (Tavis-- this is copied from TemplateFiller.py, but it > looks like the last "]" before the "+" doesn't belong > there, no?) Actually the entire thing, could be simplified to: r"[^%]*%\[(.+)\]" > We will ship with alternate regexes to handle > %(key)s > [key] > {key} How would we escape [] and {}. I'm not very good with regexs... Maybe we could search the template for the as yet unused startDelimEscaped and endDelimEscape strings, replace them with placeholders like <startDelimEscaped>, and <endDelimEscaped>, do the delimeter substitution, then swap the placeholders back to their original values. I think escaping the startDelim should handle almost everything, so we could ignore the placeholder swap for None value like this. _templateSettings = { 'customDelims': { 'custom1': { 'startDelim': r'%[', 'startDelimEscaped': r'%\[', 'endDelim': r']', 'endDelimEscaped': None, 'placeholderRE': ... r"[^%]*%\[(.+)\]" }, 'custom2': { 'startDelim': r'{', 'startDelimEscaped': r'\{', 'endDelim': r'}', 'endDelimEscaped': None, 'placeholderRE': ... r"[^{]*{(.+)}" } }, I left out the re.compile bit to avoid line-wrapping in the email version of this. > For the escaped forms, I suggest either doubling the > first character or prepending a backslash. The settings above should handle both. > > So like PSP, there would likely be a custom servlet > > factory. > Tavis, can you handle this part? Working display logic blocks is my first priority, but I'll get around to this eventually. |
From: Tavis R. <ta...@ca...> - 2001-04-07 21:28:05
|
On Saturday 07 April 2001 13:34, I wrote: > > r"[^%]*%\[([^\]]+)\]" > > (Tavis-- this is copied from TemplateFiller.py, but it > > looks like the last "]" before the "+" doesn't belong > > there, no?) > > Actually the entire thing, could be simplified to: > r"[^%]*%\[(.+)\]" Actually, I'm wrong. I remembered the reason I added [^\]] to the regex. %[name] - %[name2] would be read as one tag without it! |
From: Geoff T. <gta...@na...> - 2001-04-06 22:35:50
|
At 05:49 PM 4/6/01 -0400, Chuck Esterbrook wrote: >* Remove most of the programmatic commands like: > if, raise, return, sql*, try, with > >Reason: Keep programming in Python objects where it belongs. What if I need to display a page based on a database table, and I need to display certain fields in bold. Let's say a particular field needs to be rendered in bold if it is greater than 100. How would I express that in DTML-Lite without an "if" construct? -- - Geoff Talvola gtalvola@NameConnector.com |
From: Chuck E. <ec...@mi...> - 2001-04-07 14:29:27
|
At 06:36 PM 4/6/2001 -0400, Geoff Talvola wrote: >At 05:49 PM 4/6/01 -0400, Chuck Esterbrook wrote: >>* Remove most of the programmatic commands like: >> if, raise, return, sql*, try, with >> >>Reason: Keep programming in Python objects where it belongs. > >What if I need to display a page based on a database table, and I need to >display certain fields in bold. Let's say a particular field needs to be >rendered in bold if it is greater than 100. How would I express that in >DTML-Lite without an "if" construct? Excellent point. I have this as well in a real life project. We use different CSS styles for numbers that are negative, zero or positive. I guess to support display logic you would in fact have to have both expressions and "if". So we could still axe: raise, return, sql*, try Also, do we want to add a "set" for convenience? [set salary value=[department.manager.salary]] ... [value salary] Um, and also nested tags? (I didn't mention that in my first spec.) -Chuck |
From: Geoff T. <gta...@me...> - 2001-04-07 17:34:02
|
At 10:27 AM 4/7/2001 -0400, Chuck Esterbrook wrote: >At 06:36 PM 4/6/2001 -0400, Geoff Talvola wrote: >>At 05:49 PM 4/6/01 -0400, Chuck Esterbrook wrote: >>>* Remove most of the programmatic commands like: >>> if, raise, return, sql*, try, with >>> >>>Reason: Keep programming in Python objects where it belongs. >> >>What if I need to display a page based on a database table, and I need to >>display certain fields in bold. Let's say a particular field needs to be >>rendered in bold if it is greater than 100. How would I express that in >>DTML-Lite without an "if" construct? > >Excellent point. I have this as well in a real life project. We use >different CSS styles for numbers that are negative, zero or positive. > >I guess to support display logic you would in fact have to have both >expressions and "if". Here's one way you could do conditional styling without using an "if" operator: Precompute the conditional logic in your Python code and store the resulting boolean value as an extra field. Then the template uses this field to construct the style classname. Here's an example in PSP but the concept ought to work in whatever templating language you're using. Something like this has a chance of looking reasonable when previewed in a web browser: ############################# <% data = [('Alice',42), ('Bob',2), ('Chris',15), ('Debra',21)] records = [(name, age, age<21) for name, age in data] %> <html> <head> <style> span.underage0 {color: blue} span.underage1 {color: red} </style> </head> <body> <%for name, age, underage in records:%> <p><span class="underage<%=underage%>"><%=name%> is <%=age%> years old</span> <%end%> </body> </html> ############################# |
From: Mike O. <ir...@ms...> - 2001-04-07 19:45:08
|
On Sat, Apr 07, 2001 at 10:27:32AM -0400, Chuck Esterbrook wrote: > >What if I need to display a page based on a database table, and I need to > >display certain fields in bold. Let's say a particular field needs to be > >rendered in bold if it is greater than 100. How would I express that in > >DTML-Lite without an "if" construct? > > Excellent point. I have this as well in a real life project. We use > different CSS styles for numbers that are negative, zero or positive. > > I guess to support display logic you would in fact have to have both > expressions and "if". Why does the template class need display logic? Looping can be done with blocks. To display big numbers in bold, do: ### In the template. <TD> {value_format_begin} ${value} {value_format_end} </TD> ### In the calling program. if real_value > 100.00: value_format_begin = "<STRONG>" value_format_end = "</STRONG>" else: value_format_begin = "" value_format_end = "" value = "%.2f" % real_value # Display two decimal places. > Also, do we want to add a "set" for convenience? > > [set salary value=[department.manager.salary]] > ... > [value salary] This makes "salary" a temporary plugin value? Again, it's the responsibility of the caller to set the appropriate plugin values at the appropriate time. > Um, and also nested tags? (I didn't mention that in my first spec.) By nested tags do you mean nested substitutions (loop inside the content fragment inside the entire page)? Or what do you mean? I think the template class should be as simple as possible, and both programming logic and display logic should stay in the caller. If there is a need for enhanced values in a loop (e.g., row numbering, totals, batches), why not have the caller use a separate class which wraps a list and provides all those derived values that <dtml-in ...> does? -- -Mike (Iron) Orr, ir...@ms... (if mail problems: ms...@ji...) http://mso.oz.net/ English * Esperanto * Russkiy * Deutsch * Espan~ol |
From: Chuck E. <ec...@mi...> - 2001-04-08 14:53:22
|
At 12:45 PM 4/7/2001 -0700, Mike Orr wrote: >Why does the template class need display logic? Looping can be done with >blocks. To display big numbers in bold, do: > >### In the template. > <TD> {value_format_begin} ${value} {value_format_end} </TD> > >### In the calling program. > if real_value > 100.00: > value_format_begin = "<STRONG>" > value_format_end = "</STRONG>" > else: > value_format_begin = "" > value_format_end = "" > value = "%.2f" % real_value # Display two decimal places. I don't see any looping here... > > Also, do we want to add a "set" for convenience? > > > > [set salary value=[department.manager.salary]] > > ... > > [value salary] > >This makes "salary" a temporary plugin value? Again, it's the >responsibility of the caller to set the appropriate plugin values at >the appropriate time. Providing "set" isn't taking away the responsibility you mention. It is providing convenience for the designer who might get tired of saying "department.manager.salary" 4 times if he uses it 4 times. > > Um, and also nested tags? (I didn't mention that in my first spec.) > >By nested tags do you mean nested substitutions (loop inside the content >fragment inside the entire page)? Or what do you mean? The example was just above: [set salary value=[department.manager.salary]] Although I probably meant this: [set salary value=[value department.manager.salary]] Or based on recent discussion, this: [set salary value=[$department.manager.salary]] >I think the template class should be as simple as possible, and both >programming logic and display logic should stay in the caller. Agreed on programming logic. Still contemplating display logic. >If there is a need for enhanced values in a loop (e.g., row numbering, >totals, batches), why not have the caller use a separate class which wraps a >list and provides all those derived values that <dtml-in ...> does? Fine, but I would want that to be a default behavior. In other words, the designer would always know that he has those values available when working with a list. Again, it comes back to the fact that I work with designers in my consulting. I don't want them to have to tap me on the shoulder every time they want an index for a set of data they are looping through. That's a pain in the arse for everyone. -Chuck |
From: Mike O. <ir...@ms...> - 2001-04-08 22:04:42
|
On Sun, Apr 08, 2001 at 10:51:24AM -0400, Chuck Esterbrook wrote: > At 12:45 PM 4/7/2001 -0700, Mike Orr wrote: > >Why does the template class need display logic? Looping can be done with > >blocks. To display big numbers in bold, do: > > > >### In the template. > > <TD> {value_format_begin} ${value} {value_format_end} </TD> > > > >### In the calling program. > > if real_value > 100.00: > > value_format_begin = "<STRONG>" > > value_format_end = "</STRONG>" > > else: > > value_format_begin = "" > > value_format_end = "" > > value = "%.2f" % real_value # Display two decimal places. > > I don't see any looping here... This in itself doesn't loop. But I'm assuming the entire <TD>...</TD> is inside a block. > > > Also, do we want to add a "set" for convenience? > > > > > > [set salary value=[department.manager.salary]] > > > ... > > > [value salary] > > > >This makes "salary" a temporary plugin value? > > Providing "set" isn't taking away the responsibility you mention. It is > providing convenience for the designer who might get tired of saying > "department.manager.salary" 4 times if he uses it 4 times. Oh, I see. An alias for a longer value. Yes, that would be convenient. It would also cache the value for free. > Again, it comes back to the fact that I work with designers in my > consulting. I don't want them to have to tap me on the shoulder every time > they want an index for a set of data they are looping through. That's a > pain in the arse for everyone. OK, you're talking about programming in a different situation than I have. In my case, the developers handle both the program and the templates, and if we hire a professional design firm, they only produce a sample page once and we maintain it thereafter. So I prefer the templates to be as dumb as possible, but I can see how you want to give your designers more autonomy. I don't agree that it's necessarily worth the effort to put looping constructs and if-blocks in the template (plus the inevitable debugging and enhancements that will come), but it's not worth arguing about. Put display logic in TemplateFiller if you and Tavis want it, and I'll make a simpler version of Plow that doesn't have it (which I need for my pages anyway, before TemplateFiller is completed). Then there will be a robust class and a no-frills alternative. I do like the proposed restructuring for Page.writeHTML(), BTW. I'm not sure how templates should be integrated with Page. There should be a way that the servlet maintainer can access the template class with a minimum of imports and constructors. On the other hand, it should also be easy to use an alternative template class or no templates at all. The name PlateKit is good. The problem with the word "template" is that it's too generic. -- -Mike (Iron) Orr, ir...@ms... (if mail problems: ms...@ji...) http://mso.oz.net/ English * Esperanto * Russkiy * Deutsch * Espan~ol |
From: Chuck E. <ec...@mi...> - 2001-04-08 23:58:04
|
At 03:04 PM 4/8/2001 -0700, Mike Orr wrote: >I'm not sure how templates should be integrated with Page. There should >be a way that the servlet maintainer can access the template class with >a minimum of imports and constructors. On the other hand, it should >also be easy to use an alternative template class or no templates at >all. This type of thing often changes per developer and I find myself enhancing my SitePage to provide the kind of conveniences for templating and configuration that I need for a given site. I foresee some recipes. Although I notice that I'm just about the only one who formally posts them. :-( -Chuck |
From: Chuck E. <ec...@mi...> - 2001-04-08 14:36:30
|
At 01:33 PM 4/7/2001 -0400, Geoff Talvola wrote: >Here's one way you could do conditional styling without using an "if" >operator: Precompute the conditional logic in your Python code and store >the resulting boolean value as an extra field. Then the template uses >this field to construct the style classname. I agree that this technique works. But I'm wondering if all "display logic" should really be under the programmer's domain, or if we can expose some to the designer. In other words: Should the designer always have to go back to the programmer for things like "I want to use a different style tag based on the value of a number." I don't know... -Chuck |
From: Tavis R. <ta...@ca...> - 2001-04-08 17:17:07
|
> I agree that this technique works. But I'm wondering if > all "display logic" should really be under the > programmer's domain, or if we can expose some to the > designer. > > In other words: Should the designer always have to go > back to the programmer for things like "I want to use a > different style tag based on the value of a number." I agree that the designer making the templates should have access to conditional blocks and for loops. Just how to do it, what delimeters to use, and whether or not to allow else and elif clauses are the questions I'm interested in. |
From: Chuck E. <ec...@mi...> - 2001-04-07 14:15:10
|
At 03:18 PM 4/6/2001 -0700, Tavis Rudd wrote: > > - "[]" is rarely, if ever, used in regular text, > > filenames or HTML. > >What about the thousands of pages that discuss anything to >do with progamming? %[name] is just as simple, and has >the same benefits. And %%[name] will automatically be >escaped by the sprintf backend to TemplateFiller, and most >similar templating engines. I'm not clear on what your question means. Regarding %[] vs. [], I don't see any advantage to putting a % sign in front... I don't see how that would help my HTML designers. > > * With regards to namespace stacking, and the default > > means of using these templates in WebKit: don't stack the > > name spaces. The default namespace would be app, request, > > response, servlet, session. Using dotted notation > > (provided by NamedValueAccess), you could go from there. > > Using custom subclasses of Page, you could add more names > > to the space, like "user". > > Reason: Keep things simple. Avoid strange substitutions > > resulting from a big namespace stack. > >What are you referring to by 'namespace stack'? I'm not >totally familiar with DTML... I'll give you a really brief answer and then refer you to the Zope docs. In DTML if you use 'foo', then 'foo' will be looked for in the local variables, form fields, cookies, http headers, etc. Here is the precise part of the Zope book that explains this: http://www.zope.org/Members/michel/ZB/AdvDTML.dtml > > * Remove most of the programmatic commands like: > > if, raise, return, sql*, try, with > > Reason: Keep programming in Python objects where it > > belongs. > >I agree with you completely on that point. Yeah, although Geoff raises a good point in an e-mail I glanced at last night: What about display logic? > > * Regarding WebKit integration, follow PSP's lead and > > allow the template to optionally specify its superclass > > and method. >Are you thinking of using a custom servlet factory for >templates? I was thinking along these lines initially, but >I found it to be much easier just work in with PSP or .py >servlets. PSPs are always subclasses of a Python servlet. I pictured the template doing the same thing (when integrated with WebKit). So like PSP, there would likely be a custom servlet factory. But at this point, I'm more concerned with the external design: - ease of use - discourage application logic - provide for display logic? -Chuck |
From: Tavis R. <ta...@ca...> - 2001-04-06 22:07:20
|
> - "[]" is rarely, if ever, used in regular text, > filenames or HTML. What about the thousands of pages that discuss anything to do with progamming? %[name] is just as simple, and has the same benefits. And %%[name] will automatically be escaped by the sprintf backend to TemplateFiller, and most similar templating engines. > * With regards to namespace stacking, and the default > means of using these templates in WebKit: don't stack the > name spaces. The default namespace would be app, request, > response, servlet, session. Using dotted notation > (provided by NamedValueAccess), you could go from there. > Using custom subclasses of Page, you could add more names > to the space, like "user". > Reason: Keep things simple. Avoid strange substitutions > resulting from a big namespace stack. What are you referring to by 'namespace stack'? I'm not totally familiar with DTML... > * Remove most of the programmatic commands like: > if, raise, return, sql*, try, with > Reason: Keep programming in Python objects where it > belongs. I agree with you completely on that point. > * Regarding WebKit integration, follow PSP's lead and > allow the template to optionally specify its superclass > and method. Are you thinking of using a custom servlet factory for templates? I was thinking along these lines initially, but I found it to be much easier just work in with PSP or .py servlets. > What's left after this is something that is easy to learn > and use and discourages "programming in HTML". !! the only thing that should be in templates simpled evaluations - like what the eval() function accepts - with NamedValueAccess for ease of use. > What do you think of this approach from a design point of > view? Not sure yet. |
From: Mike O. <ir...@ms...> - 2001-04-07 18:47:45
|
On Sat, Apr 07, 2001 at 10:13:15AM -0400, Chuck Esterbrook wrote: > > > - "[]" is rarely, if ever, used in regular text, > > > filenames or HTML. Normal prose text has (aside material written by the author in parentheses). It may also have [comments inserted by the editor in brackets]. > Regarding %[] vs. [], I don't see any advantage to putting a % sign in > front... It means you can use ordinary [brackets] in your text without escaping them. What Tavis and I are converging on is a flexible way to specify delimeters. A single regular expression matches the entire placeholder and contain a group for the key name. The expression is written to *not* match the escaped form. The default expression is: r"[^%]*%\[([^\]]+)\]" which matches "%[key]" and placed "key" in a group. It doesn't match "%%[key]". (Tavis-- this is copied from TemplateFiller.py, but it looks like the last "]" before the "+" doesn't belong there, no?) We will ship with alternate regexes to handle %(key)s [key] {key} and whatever else there is significant clamor for. The user can enable any of the alternate regexes instead of the default, or supply her own regex. For the escaped forms, I suggest either doubling the first character or prepending a backslash. Doubling follows the precedent of the "%" operator, but backslash avoids unbalanced brackets in cases like "\[not a placeholder]" vs "[[not a placeholder]" . Again, why not make regexes for both cases and let the user decide? This could be extended to handle <span tal:content="name">Chuck</span> if somebody (not me) can write the appropriate regexes. > So like PSP, there would likely be a custom servlet factory. Tavis, can you handle this part? -- -Mike (Iron) Orr, ir...@ms... (if mail problems: ms...@ji...) http://mso.oz.net/ English * Esperanto * Russkiy * Deutsch * Espan~ol |
From: Tavis R. <ta...@ca...> - 2001-04-07 20:22:42
|
Have you done anything on the implementation of the display logic block substitution? I need advice on ways to identify and extract/replace the blocks from the initial template string. Expanding on your proposal to from last night: ## [- ... -] = display logic delims in this example # they could also be anything else ... ---------------------------------- """ A whole bunch of html for the header of this template... <TABLE> <TR><TD>Client ID</TD><TD>Name</TD><TD>Telephone</TD></TR> [- for client in clients: -] <TR> <TD>%[client.id]</TD> <TD>%[client.name]</TD> <TD>%[client.telephone]</TD> </TR> [- end -] </TABLE> [-if printFooter: -] The footer text [- if printLegal: -] %[legalFooter] [- end-] [- end -] The rest of the html for this template... """ ---------------------------------- BoundTemplate's __init__ would identify the top-level display logic blocks (not nested ones), then translate the template to: ---------------------------------- """ A whole bunch of html for the header of this template... <TABLE> <TR><TD>Client ID</TD><TD>Name</TD><TD>Telephone</TD></TR> %[displayLogicBlock1] </TABLE> %[displayLogicBlock2] The rest of the html for this template... """ ---------------------------------- where %[displayLogicBlock1] & 2 are dynamically defined as part of the BoundTemplate instance. The BoundTemplate intance would also add itself (i.e. self ) to its _objectsToSearch attribute so these new methods can be found with a call to self.nameMappings() ---------------------------------- def displayLogicBlock1(self): # self being the instance of BoundTemplate blockTemplateString = """ <TR> <TD>%[client.id]</TD> <TD>%[client.name]</TD> <TD>%[client.telephone]</TD> </TR> """ output = '' objects= self._objectsToSearch for client in self.valueForName('clients'): output += BoundTemplate(blockTemplateString, {'client':client}, objectsToSearch=objects).fill() return output ---------------------------------- Nested display logic would be handled like this: ---------------------------------- def displayLogicBlock2(self): # self being the instance of BoundTemplate blockTemplateString = """ The footer text [- if printLegal: -] %[legalFooter] [- end-] """ output = '' objects= self._objectsToSearch for client in self.valueForName('clients'): output += BoundTemplate(blockTemplateString, {'client':client}, objectsToSearch=objects).fill() return output ---------------------------------- The nested """[- if printLegal: -] %[legalFooter] [- end-]""" block would then be handled by the recursive call to BoundTemplate(). If performance became an issue with all the recursive calls to BoundTemplate, its slowest operations could be rewritten in C. Considering that the NameMapper and BoundTemplate classes are both under 100 lines, this shouldn't be hugely difficult. The likely candidates for C rewriting, boundTemplate.findVarNames() and BoundTemplate.nameMappings(), are only 28 lines long combined. Hopefully it won't be an issue. What do you think? Cheers, Tavis |
From: Chuck E. <ec...@mi...> - 2001-04-08 14:57:25
|
At 01:33 PM 4/7/2001 -0700, Tavis Rudd wrote: >Have you done anything on the implementation of the display >logic block substitution? I need advice on ways to >identify and extract/replace the blocks from the initial >template string. * I wonder what PSP does to handle blocks. Seems like a working example is in Webware... * I wonder if we could translate templates to PSP and then just go from there. PSPs already gets translated to Python which gets cached as bytecode. Maybe Jay has some thoughts on this since he wrote most of PSP, although I notice his mail has bounced a lot... -Chuck |
From: Chuck E. <ec...@mi...> - 2001-04-08 14:47:59
|
At 11:47 AM 4/7/2001 -0700, Mike Orr wrote: >On Sat, Apr 07, 2001 at 10:13:15AM -0400, Chuck Esterbrook wrote: > > > > - "[]" is rarely, if ever, used in regular text, > > > > filenames or HTML. > >Normal prose text has (aside material written by the author in >parentheses). It may also have [comments inserted by the editor >in brackets]. It could. I've just never, ever seen it before. :-) > > Regarding %[] vs. [], I don't see any advantage to putting a % sign in > > front... > >It means you can use ordinary [brackets] in your text without escaping them. It seems you should also be able to use a % without any escaping or doubling, however, you guys keep referring to that... Can I say "Give it 100%" in this scheme? (As opposed to "...100%%" or "...100\%") >We will ship with alternate regexes to handle > %(key)s > [key] > {key} >and whatever else there is significant clamor for. The user can enable >any of the alternate regexes instead of the default, or supply her own >regex. That sounds good. >For the escaped forms, I suggest either doubling the first character or >prepending a backslash. Doubling follows the precedent of the "%" >operator, but backslash avoids unbalanced brackets in cases like >"\[not a placeholder]" vs "[[not a placeholder]" . Again, why not >make regexes for both cases and let the user decide? What do you mean by decide? Can't we always support both? %% \% But again, I'd rather just say "%". Or is this just to cover the case where someone wants to say "%[" in their final output? -Chuck |
From: Mike O. <ir...@ms...> - 2001-04-08 21:35:58
|
On Sun, Apr 08, 2001 at 10:46:04AM -0400, Chuck Esterbrook wrote: > >Normal prose text has (aside material written by the author in > >parentheses). It may also have [comments inserted by the editor > >in brackets]. > > It could. I've just never, ever seen it before. :-) Or maybe the text is a Python HOWTO discussing variable[subscripts]. :) :) > It seems you should also be able to use a % without any escaping or > doubling, however, you guys keep referring to that... The percent-doubling issue is because TemplateFiller.py translates the placeholders to "%(key)s" and then uses the percent operator to do the actual substitution. Try this: >>> '<HR WIDTH="20%"> Hello, %(what)s!' % { 'what': 'world' } Traceback (most recent call last): File "<stdin>", line 1, in ? ValueError: unsupported format character '"' (0x22) >>> '<HR WIDTH="20%%"> Hello, %(what)s!' % { 'what': 'world' } '<HR WIDTH="20%"> Hello, world!' So either the template maintainer must double his %s (ugly) or we have to do it for him. There are a couple alternative strategies that don't require doubling: 1) Take each possible substitution key, slap delimeters around it, and do string.replace(). (DIS)ADVANTAGES: ** Using literal strings is faster than regexes. ** You have to loop through all the keys, even those that have no placeholders. ** Placeholders without a substitution value are left alone unless you do post-processing. ** May try to substitute escaped delimeters or things that look like delimeters. 2) Use a regular expression to find each ocurrence of a placeholder in the template and look up that value in the ItemsToSearch. (DIS)ADVANTAGES: ** A robust regex can exclude escapes. ** Placeholders without substitution values are found too. ** Every substitution requires a regex search. However, the percent operator has the advantage that all substitutions are done in a single C function. It would be interesting to see some benchmarks of the different approaches. However, all of them require doing lots of Python string parsing one way or another, so it might be a wash. > >For the escaped forms, I suggest either doubling the first character or > >prepending a backslash. Again, why not > >make regexes for both cases and let the user decide? > > What do you mean by decide? Can't we always support both? %% \% If we can come up with a single regex that reliably excludes both. -- -Mike (Iron) Orr, ir...@ms... (if mail problems: ms...@ji...) http://mso.oz.net/ English * Esperanto * Russkiy * Deutsch * Espan~ol |
From: Tavis R. <ta...@ca...> - 2001-04-07 17:57:31
|
Chuck, you've been be busy! It's only 11 and there's 24 messages already. And I thought yesterday was active ;-) Have a look at the new NameMapper and TemplateFiller files attached. They answer many of the questions/ideas that are being raised (with the exception of display logic). Let me know what you think. > >What about the thousands of pages that discuss anything > > to do with progamming? %[name] is just as simple, and > > has the same benefits. And %%[name] will automatically > > be escaped by the sprintf backend to TemplateFiller, > > and most similar templating engines. > > I'm not clear on what your question means. I meant that [] is very common on sites that discuss programming, mathematics, graphics, etc. For that reason alone, I prefer to use %[] instead. The only problem with it is that %% would have to be used anywhere that a single % is wanted in the output. However, that's only my preference. Any tools Webware provides should allow choice in this matter. > In DTML if you use 'foo', then 'foo' will be looked for > in the local variables, form fields, cookies, http > headers, etc. Ok, I thought that's what you meant. I don't like it. As we discussed earlier this week, implicit namespace collapsing is a bad idea, However, explicit collapsing/cascading is a totally different thing. Inheritance is one for of this and the objectsToSearchList in NameMapper is another. I like the idea of being able to do all of the following with a template: ========================= # .psp from Templates.Report import Template self.write( Template() ) ========================= # .psp from Templates.Report import Template from Styles import Classic as style bgColor = "#EBEBEB" self.write( Template( vars() )) ========================= # Templates.Report.Financial.py import Templates.Report import Styles.Classic import Report.Financial def Template( Page, Templates.Report.Template): _bgColor="#EBEBEB" _style = Styles.Classic _report = Report.Financial def writeHTML(self): self.write( self ) # or write( self.fillTemplate() ) ========================= # .psp from Templates.Report.Financial import Template tblWidth = 750 self.write( Template( vars() ) ) ========================= # or even from Templates.Report.Financial import Template tblWidth = 750 Template(vars()).write() #as template can access self.write through vars() ========================= # from a .tmpl file from Templates.Report.Financial import Template tblWidth = 750 # the .tmpl servlet factory automatically calls # self.write( Template(vars()) ) ========================= > Yeah, although Geoff raises a good point in an e-mail I > glanced at last night: What about display logic? In light of your DTML-like proposal I'm starting to think a small bit of display logic is a good thing: * for item in list: * for key, value in dict.items(): * if expression: * a way to end a logic block [% end %] Like you I prefer a tags that shows up on screen when the html is rendered: [% %] or something similar. > PSPs are always subclasses of a Python servlet. I > pictured the template doing the same thing (when > integrated with WebKit). See the new TemplateFille.Mixin. It provides a very simple way to do this. However, I like the idea of keeping TemplateFIller.Mixin decendants separate from the Servle/Page inheritance tree, so that they can be used as plugins, or be callable from the command-line (see the Mixin). I'd rather have a very simple servlet that does this in response(): from Templates.Blah import Template response.write( Template(vars()) ) #or response.write( Template(self) ) > So like PSP, there would likely be a custom servlet > factory. Sure why not. So long as it doesn't tie the Template architecture to the new factory. > But at this point, I'm more concerned with the external > design: - ease of use > - discourage application logic > - provide for display logic? Good separation. Cheers, Tavis |