#sed directive -------------- [Proposal revised 10 Nov 2001 -- MikeOrr_] *#sed* would be like #filter but operate on on the final output, line by line, just before Cheetah returns it to the caller. (#filter operates on $placeholder values.) The filters in Cheetah.Filters are interchangeable between #filter and #sed, although some filters make sense more with one than with the other. In particular, the Strip filter should work equally well in either case. (Strip strips leading/trailing whitespace on each line but does not join lines, which was the request that originally inspired #sed.) Unlike #filter, which always uses a default filter if no other filter is active, #sed would not call a filter in the default case. It would be redundant, since in #sed's case (but not in #filter's), the default filter would return the string unchanged. Initially, and after '#end sed', '#sed None' or '#sed Sed' (all interchangeable), the template would execute:: self._currentSed = None (or the equivalent). After '#sed SomeFilter', the code would be:: self._currentSed = SomeFilter_(self) Then just before returning the output, split the output into lines with trailing newline, and feed each line through the filter. For example, using code from Strip:: # Assuming string 's' contains all the lines to be sed'ded. sed = self._currentSed if sed is None: return s # Return the input unchanged. result = StringIO_() start = 0 # The current line will be s[start:end] while 1: # Loop through each line. end = s.find('\n', start) # Find the next newline. if end == -1: # If no more newlines. break chunk = s[start:end+1] # Include the trailing newline. chunk = sed(chunk) result.write(chunk) start = end + 2 # Skip to first char after trailing newline. # Write the unfinished portion after the last newline, if any. chunk = s[start:] chunk = sed(chunk) result.write(chunk) return result.getvalue() *#sed* is named after the Unix 'sed' command, of course. -- MikeOrr_ - 10 Nov 2001 --- The name '#sed' means mean nothing to many web designers, even those who work on Unix systems. If web designers are intended to be included among Cheetah's users, a less jargony name may be better. -- Hamish Lawson 09 Nov 2001 Suggestions? I proposed #output-filter, but BDFL Tavis rejected it because he wants the term "output filter" to apply to #filter. #sed is an appropriate name because out of all the commands on all platforms (AFAIK), 'sed' is the only one that edits files line by line in the manner #sed does. -- MikeOrr_ - 09 Nov 2001 'sed' is short for "stream editor", so the name is not totally arcane. Other suggestions? -- TavisRudd_ - 09 Nov 2001 ---------- It might be possible to implement this behaviour without any extensions to Cheetah, by using a combination of #def and #filter. Once we've worked out the behaviour and the implementation then we can address the syntactic sugar issue. :: #def stuffToSed_ blah blah blah #end def #filter sed ${stuffToSed_, [argsToSed_]} #end filter ## (which, I think we should implement!!) Or even simpler:: #def stuffToSed_ blah blah blah #end def $sed($stuffToSed_, [argsToSed_]) where sed is a method of the servlet. -- TavisRudd_ - 09 Nov 2001 My only objection is the fact that all strippable lines have to be wrapped in a #def method. This would be inconvenient if a large section is to be sed'ded (or even the entire template), especially if the section contains embedded #def's and #block's. Also, it means an extra $theSedSection_ placeholder that would not normally be there, since this is "regular template text" and not a "value" per se. -- MikeOrr_ - 10 Nov 2001 One of the things people praise PHP and SkunkWeb_ for is output caching -- allowing you to cache an entire portion of output regardless of how it was constructed. (Whereas with #filter, it matters how it was constructred -- it must be something stuffed into a $placeholder value, even if that wouldn't be the most logical way to express it.) As a result, Webware has output caching on its wishlist, in addition to its regular caching. #sed is analogous to output caching, but it's "output editing". A feature that Cheetah would be unique in, and which might provide unexpected benefits in terms of flexibility in the future. At the very least, it will answer the request for a #strip directive. And for those who don't use it, it's completely unobtrusive and low overhead. I'm not sure what you mean by a StripLines_ filter. Is that the same as the StripSqueeze filter I just checked in? (It replaces chunks of whitespace with ' ', removing all newlines.)-- MikeOrr_ - 10 Nov 2001 --------- I deleted my other comment, because I was confused. What I think might be sufficient is an extended function-call syntax. So if you make a function like:: def striplines(s): return '\n'.join(map(lambda x: x.strip(), s.split('\n'))) Then with the (imaginary) extended function call syntax, you'd just do: #call $striplines lots of text... #end call -- IanBicking_ - 12 Nov 2001