Date: Sun, 20 Jun 1999 14:26:21 -0500 To: zope-dev@zope.org From: "Phillip J. Eby" <pje@telecommunity.com> Subject: [Zope-dev] ANN: ZScript 0.5 - DTML without the punctuation Tired of typing <!--#foo--><!--#/foo--> until your fingers bleed? Eyes going numb trying to read unindented (and unindentable because it would change the output) DTML code? Ever wished you could return something other than a string from a DTML method, so you wouldn't have to write an ExternalMethod? Waiting with bated breath for a "safe Python method" product? Or perhaps you'd like to easily do streaming output from Zope without dropping to Python? Well, guess what... now you can fix 80-90% of the above, with the new, free (and absolutely without warranty), ZScript classes. In a ZScript, you can write DTML like this: ================================================ if spam with "foo.bar" let goats="fish and not fowl" #embedded comment \ pigs="green.eggs and ham" \ fool="'on the hill'" # Make sure we use the widget! call "manage_editProperties(...)" /let /with else return "['red','herring']" end if call "RESPONSE.redirect('/wazoo')" ================================================ Notice that each tag *must* begin on a seperate line, with no exceptions. \ is used to continue tag arguments on subsequent lines. # begins a comment which runs until the end of the line. There is no "content" here - ZScripts always return an empty string unless a var or similar tag was executed in the script body. Also notice that you can use "/tag" or "end tag" to close blocks as suits your fancy. Indentation is ignored unless it's part of a quoted argument to a tag (in which case it's passed through to the tag's parser), so you have to close all of your blocks. The ZScript classes also add a 'return' tag which can take a name or expr, just like var. Unlike var, however, the result is not converted into a string, but instead is returned to the ZScript's caller, breaking out of the entire method in the process. With this addition to the existing DTML vocabulary, ZScript can do pretty much all the "safe" things Python can. (The only significant item remaining is setting local variables, but that'll have to wait till I upgrade DT_Let to support a 'set' block continuation. Arguably, a "finally" clause for the try tag would be the only other ommission to speak of.) Because ZScripts can't contain any "content", you must use var or similar tags to insert any constant text. If you're doing significant content, you should put it in regular DTML methods and call them from your ZScript. The benefit of not generating any text by default, is that it makes 'return' more useful, and also allows you to do streaming output using: call "RESPONSE.write('text')" and call "RESPONSE.flush()" Thus, you can display in-progress data as a complex method executes. Of course, if an error occurs in your script once a RESPONSE.write() has taken place, no error message will be displayed (although any side-effects of standard_error_message or other error handlers would still apply). This is because there's no way to "take back" streamed output, and the current HTTPResponse class doesn't check for streamed output when outputting exception data. Still, if you can accept this limitation, streamed output can easily be yours. Obligatory disclaimers: I wrote this code today, because I just had the idea and I couldn't get it to go away. It has received only minimal testing, which attempted to exercise all the code paths through the parser. That doesn't mean that all the paths actually got tested, that it doesn't have bugs, or that it will work in your application. Also, it is an extension of DocumentTemplate, not a Zope Product, so some Productmeister (perhaps the folks at DC?) will need to package it up as a Product if you want to be able to drop ZScript Methods into a Zopelication. Finally, it installs the 'return' tag globally, which means return can be called from regular DocumentTemplates. This will throw an exception unless the template was called from inside a ZScript, in which case the ZScript will act as though the return came from within itself. But anyway, if you like living dangerously, can implement a Product with one hand behind your back, and don't mind tinkering with alpha software, then copy this file into your DocumentTemplate package directory: http://telecommunity.com/DT_Script.py Please note that if you want to use the 'let' tag as shown in the examples, you will also need to import: http://telecommunity.com/DT_Let.py Finally, to use a ZScript once the package(s): from DocumentTemplate.DT_Script import ZScript, ZScriptFile, ZScriptDefault And then use any of the three classes as you would the corresponding DocumentTemplate.HTML* classes. Don't forget to import DT_Let if you want the 'let' tag as well. _______________________________________________ Zope-Dev maillist - Zope-Dev@zope.org http://www.zope.org/mailman/listinfo/zope-dev (For non-developer, user-level issues, use the companion list, zope@zope.org, http://www.zope.org/mailman/listinfo/zope )