Velocity: Is it possible to nest macros that use # @ and $ bodyContent?

I have a macro that looks something like this:

#macro( surround $x ) surround:$x $bodyContent /surround:$x #end 

A call to #@surround("A")bunch o' stuff#end creates a "surround: Bunch o' stuff / surround: A" as expected. Calling #@surround("A")#@surround("B")more stuff#end#end produces surround: A surround: B more material / surround: B / surround: A, which is exactly what I want.

But now I want to create up using another macro

 #macro( annotated-surround $x $y ) #@surround( $x ) annotate:$y $bodyContent #end #end 

Expected extension #annotated-surround( "C" "note" ) stuff #end surround: C annotate: mark material / surround: C

... but it does not work; I get a terrible semi-infinite extension of the body of the annotated environment content.

I read the answer in Closing Velocity Template Macros and still don't quite know if what I want to do is possible.

I am willing to do arbitrarily complex things in the definitions of #surround and #annotated-surround , but I do not want users of these macros to see any complexity. The whole idea is to simplify their life.

As long as I have an ear: the macro.provide.scope.control=true setting should be "local namespace in macros". What does it mean? Is the provided namespace independent of the default context, but with one such space shared between all calls to all macros? Or is it a separate context provided for each macro call, even recursively? It should be the last one due to $macro.parent , right?

And one more question. Consider the following macro:

 #macro( recursive $x ) #if($x == 0) zero #else $x before . . . #set($xMinusOne = $x - 1) #recursive($xMinusOne) . . . $x after #end #end 

#recursive( 4 ) gives:

4 before., 3 before., 2 before., 1 before., Zero., 0 โ€‹โ€‹after., 0 after., 0 after., 4 after.

Now I understand all these occurrences of "0": there is only one global $ x, so assigning it recursive calls breaks it, and it does not recover. But where does this final โ€œ4โ€ come from? In this regard, how is it that my first โ€œsurroundingโ€ macro works at an arbitrary depth; how does his final $ x not break in internal calls?

Sorry there are so many, but I could not find clear documentation on this.

+4
source share
1 answer

Starting from the simplest, macro.provide.scope.control = true will definitely create a separate macro macro area object for each macro call. Otherwise, as you noticed, $ macro.parent would be nonsense. The whole point of "domain management" is to provide an explicit namespace for the type of VTL block in question. You can even do surround.provide.scope.control = true to automatically create a $ volume area inside # @surround bodyContent.

On the first question, I'm a little confused what is going on. Both # @ annotate-surround calls and the # @surround nested call will make $ bodyContent links available. Is it right that it happens that the "wrong" $ bodyContent is used? The $ bodyContent link must belong to the nearest block macro message. To reference the external $ bodyContent macro inside the internal macro, you probably need #set ($ macro.bodyContent = $ bodyContent), and then, inside the internal, use it through $ macro.parent.bodyContent

As for #recursive weirdness, I donโ€™t know what to do, and now I need to do other work. It also does not help that I do not have the speed tested on my current machine, so I can not try it quickly.

0
source

Source: https://habr.com/ru/post/1440806/


All Articles