Support Partial Formatting #15746
Replies: 3 comments 4 replies
-
We get into a conceptual mess. There are two fundamental ideas that, if not officially rejected, are ignored:
The first suggestion introduces incredible flexibility to the Formatting System, allowing users to manipulate formatting on the fly like with any other data. The second suggestion is about replacing unfriendly and outdated XML with modern, well-known, easy-to-manipulate format. Note that these proposals can be implemented completely independently and added as a separate "plugin". |
Beta Was this translation helpful? Give feedback.
-
I like the idea of making it easier to customize formatting. But I'd really love to see users NOT have to deal with XML though. What if we added cmdlets (or updated existing cmdlets) and removed the need to supply XML e.g.: Update-FormatData -Source TerminalIcons -TypeName System.Service.ServiceController -Property Status -View Table -Scriptblock {
param($obj)
($obj.Status -eq 'Stopped') ? $PSStyle.Foreground.Red + $obj.Status + $PSStyle.Reset : $obj.Status
} This would require other parameter sets (or cmdlets) to accommodate adding rows and columns. Not sure what to do about multiple modules trying to customize the same property/view. I think "last imported wins" is OK but you could run into catch-22 situations relying only on module load order. I wonder if it would be worth it to provide a way for the user to set the priority of view customizations? |
Beta Was this translation helpful? Give feedback.
-
@SteveL-MSFT a few thoughts / notes on this idea.
While this conceptually looks good, unless .PS1XML would be updated on 5.1, any changes to the standard would create formatting that would only work for one version. I don't know of a way to allow a module to use one formatter for 7+ and another for 5.1. If you do, this feedback becomes less relevant.
There are many circumstances where one wants to change/tweak/extend existing formatting. You've already happened upon one of them, with $psStyle.FileInfo. What's great about $psStyle.FileInfo is that it allows me to do conditional formatting on a particular type of object, with some "buy in" from the original formatter. From an implementation standpoint, $psStyle.FileInfo is basically saying "If you're a FileInfo object, here are some ways we can format you". The approach used in $psStyle.FileInfo could be used for any type of object, and here is how:
If that typename had a property with a single value, like .Directory, it can be used to say "if the typename is this type, apply this formatting". If that typename had a property with a dictionary/subproperties, it can be used to say "if this named property matches this condition". This is close to how the current $psStyle.FileInfo seems to be working, with a few key diffs: a. Going forward, I'd suggest: $psStyle.$typeName.$propertyName = 'prefix' # one value should be a prefix
$psStyle.$typeName.$propertyName = 'prefix', 'suffix' # two value should be a prefix and suffix
# If $property name was a, apply prefix and suffix. If named b*, apply prefix.
$psStyle.$typename.$propertyName = @{a= "prefix", "suffix"; 'b*' = "prefix" } Then, as the formatting engine runs across each typename / property, it should apply the prefixes and suffixes found in $psStyle. This approach would allow you to add conditional colorization and iconography to any existing formatter or type without writing a .PS1XML. It would also give you a fairly easy path to making a formatter output tags or other balanced content. If On a related note, right now $psStyle.OutputRendering is a fixed set of inputs. It might be nice to extend this fixed set of inputs for tag generation (I currently use an attached member to $host to indicate if a formatter should, say, become HTML). |
Beta Was this translation helpful? Give feedback.
-
UserScenario
The current formatting system in PowerShell allows for user customization, but it overwrites any default formatting. This means that, for example, you wanted to colorize a specific property you would write your own format.ps1xml file for that type which PowerShell will use instead of the default. However, if the default format gets updated (perhaps a new .NET property was added), then your specific format would be used and any enhancements to the default format including showing new properties won't be shown.
In most cases, users don't want to completely change how formatting works and generally wants to customize a specific aspect of the default formatter. For example, they may want the services returned from
Get-Service
to show stopped status as red text (but only theStatus
member, not the whole row).Customizing properties
Formatting is currently at the type level only. We would need to introduce the ability to provide formatting for specific properties.
The current format.ps1xml syntax uses the
<Configuration>
when defining a new format configuration, the root element for partial formatting will be<PartialConfiguration>
.For a table partial format update, a simplified version of the current configuration xml schema is used. Example to update service table view to put stopped services in red for both table and list views:
Adding a new column for tables
Terminal-Icons is a module that adds icons to FileInfo making it easier to see different file types. To support this type of extension, we should allow partial formatting to add a new column (although this module currently modifies the display of the name, a new column seems like a better choice). For a new column, it is desirable to specify the relative location:
Here both
<PlaceAfterHeader>
and<PlaceBeforeHeader>
is used to put between Length and Name, but only one is necessary in most cases. If the placement cannot be provided (they are logically inconsistent or the default formatting has changed and the header is no longer available), then the new header will show up before the last column instead of providing an error. The last column is typically unbounded length, so in most cases right before that works best as additive.Adding new row for lists
Same scenario as previous for a list:
The placement here is reversed as the default list format for a FileInfo has
Name
first, thenLength
.Layering
Since multiple partial formatting may be desired, there needs to be an order on which formatting is applied where it will be last one wins. The type formatter would be applied, then (to keep things simple) partial formatting is applied in the order they are registered via
Update-FormatData
. It will be up to the user to import modules that provide partial formatting or to explicitly callUpdate-FormatData
in the order desired.User customization of partial formatting
In the case of someone publishing a module that changes the
Stopped
status of services to red, the end user may prefer to have it in italics and bold instead of red. So the best practice would be for partial formats to support end user customization. Modules can expose their own means for customization, but if this becomes popular we may want to standardize this to improve discovery and consistency. However, this is additive and can be deferred until the need arises.Alternate considerations
Support multiple partial formatting in one
If most customization is more extensive than a single member, then it would make sense to allow for partial formatting to specify multiple members, but if this turns out not to be true, we would need more complex xml to support partial updates to multiple properties at once.
Beta Was this translation helpful? Give feedback.
All reactions