diff --git a/src/Microsoft.PowerShell.Commands.Management/commands/management/NewPropertyCommand.cs b/src/Microsoft.PowerShell.Commands.Management/commands/management/NewPropertyCommand.cs index caef4af84dc..fb134ce7a11 100644 --- a/src/Microsoft.PowerShell.Commands.Management/commands/management/NewPropertyCommand.cs +++ b/src/Microsoft.PowerShell.Commands.Management/commands/management/NewPropertyCommand.cs @@ -189,7 +189,32 @@ protected override void ProcessRecord() /// public class PropertyTypeArgumentCompleter : IArgumentCompleter { - private static readonly string[] s_RegistryPropertyTypes = new string[] + private static readonly CompletionHelpers.CompletionDisplayInfoMapper RegistryPropertyTypeDisplayInfoMapper = registryPropertyType => registryPropertyType switch + { + "String" => ( + ToolTip: TabCompletionStrings.RegistryStringToolTip, + ListItemText: "String"), + "ExpandString" => ( + ToolTip: TabCompletionStrings.RegistryExpandStringToolTip, + ListItemText: "ExpandString"), + "Binary" => ( + ToolTip: TabCompletionStrings.RegistryBinaryToolTip, + ListItemText: "Binary"), + "DWord" => ( + ToolTip: TabCompletionStrings.RegistryDWordToolTip, + ListItemText: "DWord"), + "MultiString" => ( + ToolTip: TabCompletionStrings.RegistryMultiStringToolTip, + ListItemText: "MultiString"), + "QWord" => ( + ToolTip: TabCompletionStrings.RegistryQWordToolTip, + ListItemText: "QWord"), + _ => ( + ToolTip: TabCompletionStrings.RegistryUnknownToolTip, + ListItemText: "Unknown"), + }; + + private static readonly IReadOnlyList s_RegistryPropertyTypes = new List(capacity: 7) { "String", "ExpandString", @@ -200,17 +225,6 @@ public class PropertyTypeArgumentCompleter : IArgumentCompleter "Unknown" }; - private static string GetRegistryPropertyTypeToolTip(string propertyTypeName) => propertyTypeName switch - { - "String" => TabCompletionStrings.RegistryStringToolTip, - "ExpandString" => TabCompletionStrings.RegistryExpandStringToolTip, - "Binary" => TabCompletionStrings.RegistryBinaryToolTip, - "DWord" => TabCompletionStrings.RegistryDWordToolTip, - "MultiString" => TabCompletionStrings.RegistryMultiStringToolTip, - "QWord" => TabCompletionStrings.RegistryQWordToolTip, - _ => TabCompletionStrings.RegistryUnknownToolTip - }; - /// /// Returns completion results for PropertyType parameter. /// @@ -230,7 +244,7 @@ public IEnumerable CompleteArgument( ? CompletionHelpers.GetMatchingResults( wordToComplete, possibleCompletionValues: s_RegistryPropertyTypes, - toolTipMapping: GetRegistryPropertyTypeToolTip, + displayInfoMapper: RegistryPropertyTypeDisplayInfoMapper, resultType: CompletionResultType.ParameterValue) : []; diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/Join-String.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/Join-String.cs index b9fc29d45fe..80a04b07f17 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/Join-String.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/Join-String.cs @@ -165,35 +165,51 @@ protected override void EndProcessing() /// public sealed class SeparatorArgumentCompleter : IArgumentCompleter { - private static readonly string NewLineText = + private const string NewLineText = #if UNIX "`n"; #else "`r`n"; #endif - private static readonly Dictionary s_separatorMappings = new(capacity: 7) + private static readonly CompletionHelpers.CompletionDisplayInfoMapper SeparatorDisplayInfoMapper = separator => separator switch { - { ",", (TabCompletionStrings.SeparatorCommaToolTip, "Comma") }, - { ", ", (TabCompletionStrings.SeparatorCommaSpaceToolTip, "Comma-Space") }, - { ";", (TabCompletionStrings.SeparatorSemiColonToolTip, "Semi-Colon") }, - { "; ", (TabCompletionStrings.SeparatorSemiColonSpaceToolTip, "Semi-Colon-Space") }, - { NewLineText, (StringUtil.Format(TabCompletionStrings.SeparatorNewlineToolTip, NewLineText), "Newline") }, - { "-", (TabCompletionStrings.SeparatorDashToolTip, "Dash") }, - { " ", (TabCompletionStrings.SeparatorSpaceToolTip, "Space") }, + "," => ( + ToolTip: TabCompletionStrings.SeparatorCommaToolTip, + ListItemText: "Comma"), + ", " => ( + ToolTip: TabCompletionStrings.SeparatorCommaSpaceToolTip, + ListItemText: "Comma-Space"), + ";" => ( + ToolTip: TabCompletionStrings.SeparatorSemiColonToolTip, + ListItemText: "Semi-Colon"), + "; " => ( + ToolTip: TabCompletionStrings.SeparatorSemiColonSpaceToolTip, + ListItemText: "Semi-Colon-Space"), + "-" => ( + ToolTip: TabCompletionStrings.SeparatorDashToolTip, + ListItemText: "Dash"), + " " => ( + ToolTip: TabCompletionStrings.SeparatorSpaceToolTip, + ListItemText: "Space"), + NewLineText => ( + ToolTip: StringUtil.Format(TabCompletionStrings.SeparatorNewlineToolTip, NewLineText), + ListItemText: "Newline"), + _ => ( + ToolTip: separator, + ListItemText: separator), }; - private static readonly IEnumerable s_separatorValues = s_separatorMappings.Keys; - - private static string GetSeparatorToolTip(string separator) - => s_separatorMappings.TryGetValue(separator, out var mapping) - ? mapping.Tooltip - : separator; - - private static string GetSeparatorListItemText(string separator) - => s_separatorMappings.TryGetValue(separator, out var mapping) - ? mapping.ListItemText - : separator; + private static readonly IReadOnlyList s_separatorValues = new List(capacity: 7) + { + ",", + ", ", + ";", + "; ", + NewLineText, + "-", + " ", + }; /// /// Returns completion results for Separator parameter. @@ -213,8 +229,7 @@ public IEnumerable CompleteArgument( => CompletionHelpers.GetMatchingResults( wordToComplete, possibleCompletionValues: s_separatorValues, - listItemTextMapping: GetSeparatorListItemText, - toolTipMapping: GetSeparatorToolTip, + displayInfoMapper: SeparatorDisplayInfoMapper, resultType: CompletionResultType.ParameterValue); } diff --git a/src/System.Management.Automation/engine/CommandCompletion/CompletionHelpers.cs b/src/System.Management.Automation/engine/CommandCompletion/CompletionHelpers.cs index e7bc41667c2..d54f4d5dc87 100644 --- a/src/System.Management.Automation/engine/CommandCompletion/CompletionHelpers.cs +++ b/src/System.Management.Automation/engine/CommandCompletion/CompletionHelpers.cs @@ -23,19 +23,18 @@ internal static class CompletionHelpers /// /// The word to complete. /// The possible completion values to iterate. - /// The optional tool tip mapping delegate. - /// The optional list item text mapping delegate. + /// The optional completion display info mapper delegate for tool tip and list item text. /// The optional completion result type. Default is Text. /// The optional match strategy delegate. /// List of matching completion results. internal static IEnumerable GetMatchingResults( string wordToComplete, IEnumerable possibleCompletionValues, - Func toolTipMapping = null, - Func listItemTextMapping = null, + CompletionDisplayInfoMapper displayInfoMapper = null, CompletionResultType resultType = CompletionResultType.Text, MatchStrategy matchStrategy = null) { + displayInfoMapper ??= DefaultDisplayInfoMapper; matchStrategy ??= DefaultMatch; string quote = HandleDoubleAndSingleQuote(ref wordToComplete); @@ -49,14 +48,30 @@ internal static IEnumerable GetMatchingResults( if (matchStrategy(value, wordToComplete)) { string completionText = QuoteCompletionText(value, quote); - string toolTip = toolTipMapping?.Invoke(value) ?? value; - string listItemText = listItemTextMapping?.Invoke(value) ?? value; + + (string toolTip, string listItemText) = displayInfoMapper(value); yield return new CompletionResult(completionText, listItemText, resultType, toolTip); } } } + /// + /// Provides the display information for a completion result. + /// This delegate is used to map a string value to its corresponding display information. + /// + /// The input value to be mapped + /// Completion display info containing tool tip and list item text. + internal delegate (string ToolTip, string ListItemText) CompletionDisplayInfoMapper(string value); + + /// + /// Provides the default display information for a completion result. + /// Defaults to using the input value for both the tool tip and list item text. + /// + /// Completion display info containing tool tip and list item text. + internal static readonly CompletionDisplayInfoMapper DefaultDisplayInfoMapper = value + => (value, value); + /// /// Normalizes the input string to an expandable string format for PowerShell. /// diff --git a/test/powershell/Host/TabCompletion/TabCompletion.Tests.ps1 b/test/powershell/Host/TabCompletion/TabCompletion.Tests.ps1 index 7d20bd8e173..fb3ffc8484e 100644 --- a/test/powershell/Host/TabCompletion/TabCompletion.Tests.ps1 +++ b/test/powershell/Host/TabCompletion/TabCompletion.Tests.ps1 @@ -1368,6 +1368,13 @@ param([ValidatePattern( $res = TabExpansion2 -inputScript $TextInput -cursorColumn $TextInput.Length $completionText = $res.CompletionMatches.CompletionText $completionText -join ' ' | Should -BeExactly $ExpectedPropertyTypes + + foreach ($match in $res.CompletionMatches) { + $completionText = $match.CompletionText.Replace("""", "").Replace("'", "") + $listItemText = $match.ListItemText + $completionText | Should -BeExactly $listItemText + $match.ToolTip | Should -Not -BeNullOrEmpty + } } It "Test fallback to provider of current location if no path specified" -Skip:(!$IsWindows) { @@ -1554,6 +1561,14 @@ param([ValidatePattern( $res = TabExpansion2 -inputScript $TextInput -cursorColumn $TextInput.Length $completionText = $res.CompletionMatches.CompletionText $completionText -join ' ' | Should -BeExactly $Expected + + foreach ($match in $res.CompletionMatches) { + $toolTip = $match.ToolTip.Replace("""", "").Replace("'", "") + $completionText = $match.CompletionText.Replace("""", "").Replace("'", "") + $listItemText = $match.ListItemText + $toolTip.StartsWith($completionText) | Should -BeTrue + $toolTip.EndsWith($listItemText) | Should -BeTrue + } } It "Should complete for ''" -Skip:(!$IsWindows) -TestCases @( @@ -1574,6 +1589,14 @@ param([ValidatePattern( $res = TabExpansion2 -inputScript $TextInput -cursorColumn $TextInput.Length $completionText = $res.CompletionMatches.CompletionText $completionText -join ' ' | Should -BeExactly $Expected + + foreach ($match in $res.CompletionMatches) { + $toolTip = $match.ToolTip.Replace("""", "").Replace("'", "") + $completionText = $match.CompletionText.Replace("""", "").Replace("'", "") + $listItemText = $match.ListItemText + $toolTip.StartsWith($completionText) | Should -BeTrue + $toolTip.EndsWith($listItemText) | Should -BeTrue + } } It "Should complete for ''" -Skip:($IsWindows) -TestCases @( @@ -1590,6 +1613,14 @@ param([ValidatePattern( $res = TabExpansion2 -inputScript $TextInput -cursorColumn $TextInput.Length $completionText = $res.CompletionMatches.CompletionText $completionText -join ' ' | Should -BeExactly $Expected + + foreach ($match in $res.CompletionMatches) { + $toolTip = $match.ToolTip.Replace("""", "").Replace("'", "") + $completionText = $match.CompletionText.Replace("""", "").Replace("'", "") + $listItemText = $match.ListItemText + $toolTip.StartsWith($completionText) | Should -BeTrue + $toolTip.EndsWith($listItemText) | Should -BeTrue + } } }