SeeminglyScience / PSStringTemplate

Create and render templates using the StringTemplate template engine.
MIT License
11 stars 3 forks source link

Add support for custom renderers #12

Open SeeminglyScience opened 6 years ago

SeeminglyScience commented 6 years ago

StringTemplate has support for adding custom renderers. These renders provide three things

  1. Ability to change the default rendering of certain types
  2. Usage of custom format strings
  3. A method of handling rendering specific to the current culture

For example, lets say you wanted type objects to render like they do in certain PowerShell format displays, you could create this renderer:

using namespace System.Management.Automation
using namespace Antlr4.StringTemplate

class TypeRenderer : StringRenderer {
    [string] ToString([object] $o, [string] $formatString, [cultureinfo] $culture) {
        $typeString = [ToStringCodeMethods]::Type($o)
        if ($formatString -eq 'NoNamespaces') {
             return $typeString.Split('.')[-1]
        }

        return $typeString
    }
}

If Invoke-StringTemplate was using that renderer you could do this

$result = Invoke-StringTemplate -Definition '
    <codemethod>
    <codemethod; format="NoNamespaces">
    <runspace>
    <runspace;  format="NoNamespaces">' -Parameters @{
     runspace = [runspace]
    codemethod = [System.Management.Automation.PSCodeMethod]
}

$result
# System.Management.Automation.PSCodeMethod
# PSCodeMethod
# runspace
# runspace

Adding support for this would be great, but there are some things to consider.

  1. PowerShell doesn't scale very well. Adding global renderers could significantly impact performance. For the same reason adding Where-Object-like filters that determine if an attribute should be rendered by PowerShell isn't feasible

    • Probably best to stick to how StringTemplate does it by default, by type.
  2. This is difficult to present in an accessible way from PowerShell

    • If it was a parameter it would need to be a hashtable and that hurts discoverablity.
    • Might be best as a separate Cmdlet, maybe Register-StringTemplateRenderer? Would this register globally or would it require passing a template group instance?

The implementation would likely be a custom AttributeRenderer implementation that stores registered type to scriptblock mappings and evaluates each attribute.