Gareth posted an entry in June (with links to previous postings on the same subject) about Text Templating code generation engine. Pleas refert to it for background information. After hearing feedback from customers and from our own use of the feature, we recently made some improvements to it that we hope you'll like.
Previously, if you wanted to append to the output text from within a method in a class-feature block, you would have to use clumsy Write() and WriteLine() statements. For example:
<# PrintPowersOfTwo(1,5); #><#+private void PrintPowersOfTwo(int i, int j){ for(;i<j;i++) { WriteLine("2 to the power {0} is:", i); WriteLine(Math.Pow(2,i).ToString()); }}#>
This could get clumsy quickly, especially if you have methods that output large amounts of text.
To help the situation, we added a new feature to allow boilerplate and expression blocks to be embedded within class-feature blocks. For example, the same PrintPowersOfTwo() function above could look like this:
<#+private void PrintPowersOfTwo(int i, int j){ for(;i<j;i++) {#>2 to the power <#= i #> is:<#= Math.Pow(2,i) #><#+ }}#>
We feel this helps conform better to the users instinctive expectation of what the above template should do. It is a very natural way to use class-feature blocks to spit up code-generation into different methods. I've used it myself for some of my code-generation tasks and find it tremendously useful, and I hope you find the same.
With this change, no statement blocks will be allowed after the first class-feature block within a file. And all boilerplate or expression blocks found after the first class-feature block will be treated as embedded within the class-feature. So doing something like this will cause a compiler error:
<#+private void DoNothing() {}#>boilerplate text<#+private void DoNothingAgain() {}#>
The restrictions above don't affect the code-generation functionality of Text Templates in any way, however. And as I mentioned earlier, the outcome does feel more natural once you've tried it.
Another feature we've added, that goes hand in hand with the above feature, is three methods and one property in the base code-generation class to manage indents:
public void PushIndent(string indent);public string PopIndent();public void ClearIndent();public string CurrentIndent { get; }
PushIndent adds the provided indent to the current indent. PopIndent removes the previously indend added through PushIndent, and does nothing if there is no indent. ClearIndent clears the current indent. And CurrentIndent gets the current indent string. The current indent is applied after every newline that is ouput (even if it's output using the Write() or WriteLine() functions). For example, using the PrintPowersOfTwo() function provided earlier:
<#PrintPowersOfTwo(1,3);PushIndent(" ");PrintPowersOfTwo(4,6);PushIndent("indent>");PrintPowersOfTwo(7,9);PopIndent();WriteLine("Test Indent");WriteLine("Current Indent is \""+CurrentIndent+"\"");ClearIndent();#>
Produces the following output:
2 to the power 1
I hope you like these improvements. Any comments, suggestions, or other feedback would be very much appreciated.
Unfortunately, this will not be in the November CTP, and I don't know the exact dates for our next release. Sorry to get you all excited and then tell you you can't have it yet. But it is worth the wait :). And this gives us a chance to gather some early feedback on the feature (so please spill your thoughts).
Thanks,George