Hi Chris, You are right - for a solution that is part of the standard, it would be better to use a nested context to avoid the "args." prefix. I already used macros with only one args parameter - so for me it didn't make sense to do this.
When adding this functionality, I think it would be best to just add an optional map parameter to the parse directive - this way users don't have to learn any new directive and it would be easy to adopt this feature. Also setting a different base directory for where parse takes the templates from would be useful. This way you can keep the reusable code in one place and you don't have to write the full path when using the parse directive. Since you are adding the arguments to the context, it might make sense to create another directive - something like #default that takes a map and defaults variables in the context to map entries. When you have many parameters for a macro, being able to efficiently set default values is crucial. To allow a content to be rendered (what I did with #callBlock and #content), you will need a new directive since it has to be a blockDirective. You wrote: I think you can choose to use the wrapped versus outer context however you want... I did not really understand why this was true: > // the callStack is needed for the ContentDirective - when the content is rendered, > // we have to move one level back in the callStack This is because when you render the content of the callBlock directive (using #content), you have to reset the args map to what it was before the directive was called - it's essential for nested callBlock statements and recursions. But it should be possible to do the same thing with nested contexts. Frankly I don't have much time now to contribute a lot to the project - I am just sharing what I've done. If that functionality makes it into the base product I think it would be a great enhancement. Cheers, Guido -----Original Message----- From: Christopher Schultz [mailto:[EMAIL PROTECTED] Sent: Wednesday, March 05, 2008 9:00 PM To: Velocity Developers List Subject: Re: A simple macro replacement with user directives Guido, Deinhammer, Guido wrote: > I understand my writing turned out a little lengthy, but if you are > using macros, it should be worth the read... It definitely is. Thanks for investigating /and providing code/! > The second parameter is a map that is added to the context under the > name "args" - the "macro" can access the parameters with $args.arg1. What about wrapping the current VelocityContext in another one that contains the argument map? That would allow you to use your template either through your #call directive or with #parse (because it would remove the need for the "$args." prefix). It would be an easy fix. Starting with CallDirective.java:120: > Object oldArgs = context.put(ARGUMENTS_VARIABLE_NAME, args); Change this to: // Wrap the outer context with a new one Context subContext = new VelocityContext(context); // Copy the arguments into the inner context for(Iterator i=args.entrySet().iterator(); i.hasNext(); ) { Map.Entry entry = (Map.Entry)i.next(); subContext.put((String)entry.getKey(), entry.getValue()); } I think you can choose to use the wrapped versus outer context however you want... I did not really understand why this was true: > // the callStack is needed for the ContentDirective - when the content is rendered, > // we have to move one level back in the callStack ... so it's up to you. ;) Of course, you'd want to use the wrapped context, here: > template.merge(context, writer); template.merge(subContext, writer); And this line is unnecessary, since subContext will simply fall out of scope: > context.put(ARGUMENTS_VARIABLE_NAME, oldArgs); I'm also not sure about the push and pop of template names if you use a wrapped context. I don't know enough about the internals of Velocity to know if they are required or not. Let me know if you think these are reasonable improvements. -chris --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]