On Thu, Mar 6, 2008 at 6:21 AM, Deinhammer, Guido
<[EMAIL PROTECTED]> wrote:
> 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.

i thought this at first, but i'm not so sure now.  taking a map of
arguments isn't the only difference.  having a chained context,
setting a base directory (unique from the resource loader system), and
taking the first arg as a literal #call( foo ) instead of a string
#parse( "foo.vm" ).

Regarding #callBlock, there's been talk of a #macroblock too.  I
wonder if we should just focus on a #block( foo ) here's da block #end
directive to define blocks, and leave the user to pass the blocks into
the macro or #call on their own.

> 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.

true.  that might be useful in general.  Will, how would these ideas
fit with your IncludeEventHandler?

>  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.

I can't really see that ever being part of a standard distribution.
Also, it could be probably done easily as a tool (or extension
of/addition to the ContextTool).

>  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]
>
>

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to