Skip to content

Commit f2b12da

Browse files
yotsudaSIRMARGIN
authored andcommitted
Add -ExcludeProperty parameter to Format-* cmdlets (PowerShell#26514)
1 parent fae4f28 commit f2b12da

16 files changed

Lines changed: 401 additions & 124 deletions

File tree

src/Microsoft.PowerShell.Commands.Utility/commands/utility/FormatAndOutput/format-object/Format-Object.cs

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,12 @@ public object[] Property
4141

4242
private object[] _props;
4343

44+
/// <summary>
45+
/// Gets or sets the properties to exclude from formatting.
46+
/// </summary>
47+
[Parameter]
48+
public string[] ExcludeProperty { get; set; }
49+
4450
/// <summary>
4551
/// </summary>
4652
/// <value></value>
@@ -61,22 +67,36 @@ internal override FormattingCommandLineParameters GetCommandLineParameters()
6167
{
6268
FormattingCommandLineParameters parameters = new();
6369

70+
// Check View conflicts first (before any auto-expansion)
71+
if (!string.IsNullOrEmpty(this.View))
72+
{
73+
// View cannot be used with Property or ExcludeProperty
74+
if ((_props is not null && _props.Length != 0) || (ExcludeProperty is not null && ExcludeProperty.Length != 0))
75+
{
76+
ReportCannotSpecifyViewAndProperty();
77+
}
78+
79+
parameters.viewName = this.View;
80+
}
81+
6482
if (_props != null)
6583
{
6684
ParameterProcessor processor = new(new FormatObjectParameterDefinition());
6785
TerminatingErrorContext invocationContext = new(this);
6886
parameters.mshParameterList = processor.ProcessParameters(_props, invocationContext);
6987
}
7088

71-
if (!string.IsNullOrEmpty(this.View))
89+
if (ExcludeProperty is not null)
7290
{
73-
// we have a view command line switch
74-
if (parameters.mshParameterList.Count != 0)
91+
parameters.excludePropertyFilter = new PSPropertyExpressionFilter(ExcludeProperty);
92+
93+
// ExcludeProperty implies -Property * for better UX
94+
if (_props is null || _props.Length == 0)
7595
{
76-
ReportCannotSpecifyViewAndProperty();
96+
ParameterProcessor processor = new(new FormatObjectParameterDefinition());
97+
TerminatingErrorContext invocationContext = new(this);
98+
parameters.mshParameterList = processor.ProcessParameters(new object[] { "*" }, invocationContext);
7799
}
78-
79-
parameters.viewName = this.View;
80100
}
81101

82102
parameters.groupByParameter = this.ProcessGroupByParameter();

src/Microsoft.PowerShell.Commands.Utility/commands/utility/FormatAndOutput/format-wide/Format-Wide.cs

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,14 @@ public object Property
4242
private object _prop;
4343

4444
/// <summary>
45-
/// Optional, non positional parameter.
45+
/// Gets or sets the properties to exclude from formatting.
46+
/// </summary>
47+
[Parameter]
48+
public string[] ExcludeProperty { get; set; }
49+
50+
/// <summary>
51+
/// Gets or sets a value indicating whether to autosize the output.
4652
/// </summary>
47-
/// <value></value>
4853
[Parameter]
4954
public SwitchParameter AutoSize
5055
{
@@ -74,22 +79,36 @@ internal override FormattingCommandLineParameters GetCommandLineParameters()
7479
{
7580
FormattingCommandLineParameters parameters = new();
7681

82+
// Check View conflicts first (before any auto-expansion)
83+
if (!string.IsNullOrEmpty(this.View))
84+
{
85+
// View cannot be used with Property or ExcludeProperty
86+
if (_prop is not null || (ExcludeProperty is not null && ExcludeProperty.Length != 0))
87+
{
88+
ReportCannotSpecifyViewAndProperty();
89+
}
90+
91+
parameters.viewName = this.View;
92+
}
93+
7794
if (_prop != null)
7895
{
7996
ParameterProcessor processor = new(new FormatWideParameterDefinition());
8097
TerminatingErrorContext invocationContext = new(this);
8198
parameters.mshParameterList = processor.ProcessParameters(new object[] { _prop }, invocationContext);
8299
}
83100

84-
if (!string.IsNullOrEmpty(this.View))
101+
if (ExcludeProperty is not null)
85102
{
86-
// we have a view command line switch
87-
if (parameters.mshParameterList.Count != 0)
103+
parameters.excludePropertyFilter = new PSPropertyExpressionFilter(ExcludeProperty);
104+
105+
// ExcludeProperty implies -Property * for better UX
106+
if (_prop is null)
88107
{
89-
ReportCannotSpecifyViewAndProperty();
108+
ParameterProcessor processor = new(new FormatWideParameterDefinition());
109+
TerminatingErrorContext invocationContext = new(this);
110+
parameters.mshParameterList = processor.ProcessParameters(new object[] { "*" }, invocationContext);
90111
}
91-
92-
parameters.viewName = this.View;
93112
}
94113

95114
// we cannot specify -column and -autosize, they are mutually exclusive

src/Microsoft.PowerShell.Commands.Utility/commands/utility/Select-Object.cs

Lines changed: 0 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -12,47 +12,6 @@
1212

1313
namespace Microsoft.PowerShell.Commands
1414
{
15-
/// <summary>
16-
/// Helper class to do wildcard matching on PSPropertyExpressions.
17-
/// </summary>
18-
internal sealed class PSPropertyExpressionFilter
19-
{
20-
/// <summary>
21-
/// Initializes a new instance of the <see cref="PSPropertyExpressionFilter"/> class
22-
/// with the specified array of patterns.
23-
/// </summary>
24-
/// <param name="wildcardPatternsStrings">Array of pattern strings to use.</param>
25-
internal PSPropertyExpressionFilter(string[] wildcardPatternsStrings)
26-
{
27-
ArgumentNullException.ThrowIfNull(wildcardPatternsStrings);
28-
29-
_wildcardPatterns = new WildcardPattern[wildcardPatternsStrings.Length];
30-
for (int k = 0; k < wildcardPatternsStrings.Length; k++)
31-
{
32-
_wildcardPatterns[k] = WildcardPattern.Get(wildcardPatternsStrings[k], WildcardOptions.IgnoreCase);
33-
}
34-
}
35-
36-
/// <summary>
37-
/// Try to match the expression against the array of wildcard patterns.
38-
/// The first match shortcircuits the search.
39-
/// </summary>
40-
/// <param name="expression">PSPropertyExpression to test against.</param>
41-
/// <returns>True if there is a match, else false.</returns>
42-
internal bool IsMatch(PSPropertyExpression expression)
43-
{
44-
for (int k = 0; k < _wildcardPatterns.Length; k++)
45-
{
46-
if (_wildcardPatterns[k].IsMatch(expression.ToString()))
47-
return true;
48-
}
49-
50-
return false;
51-
}
52-
53-
private readonly WildcardPattern[] _wildcardPatterns;
54-
}
55-
5615
internal sealed class SelectObjectExpressionParameterDefinition : CommandParameterDefinition
5716
{
5817
protected override void SetEntries()

src/System.Management.Automation/FormatAndOutput/common/BaseFormattingCommand.cs

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
using System.Management.Automation;
1010
using System.Management.Automation.Internal;
1111
using System.Management.Automation.Runspaces;
12+
using Microsoft.PowerShell.Commands;
1213

1314
namespace Microsoft.PowerShell.Commands.Internal.Format
1415
{
@@ -729,6 +730,12 @@ public class OuterFormatTableAndListBase : OuterFormatShapeCommandBase
729730
[Parameter(Position = 0)]
730731
public object[] Property { get; set; }
731732

733+
/// <summary>
734+
/// Optional parameter for excluding properties from formatting.
735+
/// </summary>
736+
[Parameter]
737+
public string[] ExcludeProperty { get; set; }
738+
732739
#endregion
733740

734741
internal override FormattingCommandLineParameters GetCommandLineParameters()
@@ -751,6 +758,18 @@ internal override FormattingCommandLineParameters GetCommandLineParameters()
751758

752759
internal void GetCommandLineProperties(FormattingCommandLineParameters parameters, bool isTable)
753760
{
761+
// Check View conflicts first (before any auto-expansion)
762+
if (!string.IsNullOrEmpty(this.View))
763+
{
764+
// View cannot be used with Property or ExcludeProperty
765+
if ((Property is not null && Property.Length != 0) || (ExcludeProperty is not null && ExcludeProperty.Length != 0))
766+
{
767+
ReportCannotSpecifyViewAndProperty();
768+
}
769+
770+
parameters.viewName = this.View;
771+
}
772+
754773
if (Property != null)
755774
{
756775
CommandParameterDefinition def;
@@ -765,15 +784,21 @@ internal void GetCommandLineProperties(FormattingCommandLineParameters parameter
765784
parameters.mshParameterList = processor.ProcessParameters(Property, invocationContext);
766785
}
767786

768-
if (!string.IsNullOrEmpty(this.View))
787+
if (ExcludeProperty is not null)
769788
{
770-
// we have a view command line switch
771-
if (parameters.mshParameterList.Count != 0)
789+
parameters.excludePropertyFilter = new PSPropertyExpressionFilter(ExcludeProperty);
790+
791+
// ExcludeProperty implies -Property * for better UX
792+
if (Property is null || Property.Length == 0)
772793
{
773-
ReportCannotSpecifyViewAndProperty();
774-
}
794+
CommandParameterDefinition def = isTable
795+
? new FormatTableParameterDefinition()
796+
: new FormatListParameterDefinition();
797+
ParameterProcessor processor = new ParameterProcessor(def);
798+
TerminatingErrorContext invocationContext = new TerminatingErrorContext(this);
775799

776-
parameters.viewName = this.View;
800+
parameters.mshParameterList = processor.ProcessParameters(new object[] { "*" }, invocationContext);
801+
}
777802
}
778803
}
779804
}

src/System.Management.Automation/FormatAndOutput/common/BaseFormattingCommandParameters.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,11 @@ internal sealed class FormattingCommandLineParameters
7070
/// Extension mechanism for shape specific parameters.
7171
/// </summary>
7272
internal ShapeSpecificParameters shapeParameters = null;
73+
74+
/// <summary>
75+
/// Filter for excluding properties from formatting.
76+
/// </summary>
77+
internal PSPropertyExpressionFilter excludePropertyFilter = null;
7378
}
7479

7580
/// <summary>

src/System.Management.Automation/FormatAndOutput/common/FormatViewGenerator.cs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// Licensed under the MIT License.
33

44
using System.Collections.Generic;
5+
using System.Linq;
56
using System.Collections.ObjectModel;
67
using System.Management.Automation;
78
using System.Management.Automation.Internal;
@@ -348,7 +349,19 @@ protected class DataBaseInfo
348349
protected DataBaseInfo dataBaseInfo = new DataBaseInfo();
349350

350351
protected List<MshResolvedExpressionParameterAssociation> activeAssociationList = null;
351-
protected FormattingCommandLineParameters inputParameters = null;
352+
/// <summary>
353+
/// Apply ExcludeProperty filter to activeAssociationList if specified.
354+
/// This method filters and updates "activeAssociationList" instance property.
355+
/// </summary>
356+
protected void ApplyExcludePropertyFilter()
357+
{
358+
if (this.parameters is not null && this.parameters.excludePropertyFilter is not null)
359+
{
360+
this.activeAssociationList = this.activeAssociationList
361+
.Where(item => !this.parameters.excludePropertyFilter.IsMatch(item.ResolvedExpression))
362+
.ToList();
363+
}
364+
}
352365

353366
protected string GetExpressionDisplayValue(PSObject so, int enumerationLimit, PSPropertyExpression ex,
354367
FieldFormattingDirective directive)

src/System.Management.Automation/FormatAndOutput/common/FormatViewGenerator_Complex.cs

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
using System.Collections;
55
using System.Collections.Generic;
6+
using System.Linq;
67
using System.Collections.ObjectModel;
78
using System.Management.Automation;
89
using System.Management.Automation.Internal;
@@ -16,7 +17,6 @@ internal override void Initialize(TerminatingErrorContext errorContext, PSProper
1617
PSObject so, TypeInfoDataBase db, FormattingCommandLineParameters parameters)
1718
{
1819
base.Initialize(errorContext, expressionFactory, so, db, parameters);
19-
this.inputParameters = parameters;
2020
}
2121

2222
internal override FormatStartData GenerateStartData(PSObject so)
@@ -40,7 +40,7 @@ internal override FormatEntryData GeneratePayload(PSObject so, int enumerationLi
4040
private ComplexViewEntry GenerateComplexViewEntryFromProperties(PSObject so, int enumerationLimit)
4141
{
4242
ComplexViewObjectBrowser browser = new ComplexViewObjectBrowser(this.ErrorManager, this.expressionFactory, enumerationLimit);
43-
return browser.GenerateView(so, this.inputParameters);
43+
return browser.GenerateView(so, this.parameters);
4444
}
4545

4646
private ComplexViewEntry GenerateComplexViewEntryFromDataBaseInfo(PSObject so, int enumerationLimit)
@@ -425,17 +425,18 @@ internal ComplexViewObjectBrowser(FormatErrorManager resultErrorManager, PSPrope
425425
/// of the object.
426426
/// </summary>
427427
/// <param name="so">Object to process.</param>
428-
/// <param name="inputParameters">Parameters from the command line.</param>
428+
/// <param name="parameters">Parameters from the command line.</param>
429429
/// <returns>Complex view entry to send to the output command.</returns>
430-
internal ComplexViewEntry GenerateView(PSObject so, FormattingCommandLineParameters inputParameters)
430+
internal ComplexViewEntry GenerateView(PSObject so, FormattingCommandLineParameters parameters)
431431
{
432-
_complexSpecificParameters = (ComplexSpecificParameters)inputParameters.shapeParameters;
432+
_parameters = parameters;
433+
_complexSpecificParameters = (ComplexSpecificParameters)parameters.shapeParameters;
433434

434435
int maxDepth = _complexSpecificParameters.maxDepth;
435436
TraversalInfo level = new TraversalInfo(0, maxDepth);
436437

437438
List<MshParameter> mshParameterList = null;
438-
mshParameterList = inputParameters.mshParameterList;
439+
mshParameterList = parameters.mshParameterList;
439440

440441
// create a top level entry as root of the tree
441442
ComplexViewEntry cve = new ComplexViewEntry();
@@ -513,6 +514,14 @@ private void DisplayObject(PSObject so, TraversalInfo currentLevel, List<MshPara
513514
List<MshResolvedExpressionParameterAssociation> activeAssociationList =
514515
AssociationManager.SetupActiveProperties(parameterList, so, _expressionFactory);
515516

517+
// Apply ExcludeProperty filter if specified
518+
if (_parameters != null && _parameters.excludePropertyFilter != null)
519+
{
520+
activeAssociationList = activeAssociationList
521+
.Where(item => !_parameters.excludePropertyFilter.IsMatch(item.ResolvedExpression))
522+
.ToList();
523+
}
524+
516525
// create a format entry
517526
FormatEntry fe = new FormatEntry();
518527
formatValueList.Add(fe);
@@ -758,6 +767,7 @@ private List<FormatValue> AddIndentationLevel(List<FormatValue> formatValueList)
758767
return feFrame.formatValueList;
759768
}
760769

770+
private FormattingCommandLineParameters _parameters;
761771
private ComplexSpecificParameters _complexSpecificParameters;
762772

763773
/// <summary>

src/System.Management.Automation/FormatAndOutput/common/FormatViewGenerator_List.cs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ internal override void Initialize(TerminatingErrorContext errorContext, PSProper
3131
_listBody = (ListControlBody)this.dataBaseInfo.view.mainControl;
3232
}
3333

34-
this.inputParameters = parameters;
34+
this.parameters = parameters;
3535
SetUpActiveProperties(so);
3636
}
3737

@@ -227,10 +227,12 @@ private void SetUpActiveProperties(PSObject so)
227227
{
228228
List<MshParameter> mshParameterList = null;
229229

230-
if (this.inputParameters != null)
231-
mshParameterList = this.inputParameters.mshParameterList;
230+
if (this.parameters != null)
231+
mshParameterList = this.parameters.mshParameterList;
232232

233233
this.activeAssociationList = AssociationManager.SetupActiveProperties(mshParameterList, so, this.expressionFactory);
234+
235+
ApplyExcludePropertyFilter();
234236
}
235237
}
236238
}

0 commit comments

Comments
 (0)