8000 Add completion of modules by their shortname (#20330) · PowerShell/PowerShell@8cdb728 · GitHub
[go: up one dir, main page]

Skip to content

Commit 8cdb728

Browse files
authored
Add completion of modules by their shortname (#20330)
1 parent b74e708 commit 8cdb728

File tree

2 files changed

+42
-11
lines changed

2 files changed

+42
-11
lines changed

src/System.Management.Automation/engine/CommandCompletion/CompletionCompleters.cs

+37-11
Original file line numberDiff line numberDiff line change
@@ -423,16 +423,34 @@ public override AstVisitAction VisitFunctionDefinition(FunctionDefinitionAst fun
423423

424424
internal static List<CompletionResult> CompleteModuleName(CompletionContext context, bool loadedModulesOnly, bool skipEditionCheck = false)
425425
{
426-
var moduleName = context.WordToComplete ?? string.Empty;
426+
var wordToComplete = context.WordToComplete ?? string.Empty;
427427
var result = new List<CompletionResult>();
428-
var quote = HandleDoubleAndSingleQuote(ref moduleName);
428+
var quote = HandleDoubleAndSingleQuote(ref wordToComplete);
429429

430-
if (!moduleName.EndsWith('*'))
430+
// Indicates if we should search for modules where the last part of the name matches the input text
431+
// eg: Host<Tab> finds Microsoft.PowerShell.Host
432+
// If the user has entered a manual wildcard, or a module name that contains a "." we assume they only want results that matches the input exactly.
433+
bool shortNameSearch = wordToComplete.Length > 0 && !WildcardPattern.ContainsWildcardCharacters(wordToComplete) && !wordToComplete.Contains('.');
434+
435+
if (!wordToComplete.EndsWith('*'))
436+
{
437+
wordToComplete += "*";
438+
}
439+
440+
string[] moduleNames;
441+
WildcardPattern shortNamePattern;
442+
if (shortNameSearch)
443+
{
444+
moduleNames = new string[] { wordToComplete, "*." + wordToComplete };
445+
shortNamePattern = new WildcardPattern(wordToComplete, WildcardOptions.IgnoreCase);
446+
}
447+
else
431448
{
432-
moduleName += "*";
449+
moduleNames = new string[] { wordToComplete };
450+
shortNamePattern = null;
433451
}
434452

435-
var powershell = context.Helper.AddCommandWithPreferenceSetting("Get-Module", typeof(GetModuleCommand)).AddParameter("Name", moduleName);
453+
var powershell = context.Helper.AddCommandWithPreferenceSetting("Get-Module", typeof(GetModuleCommand)).AddParameter("Name", moduleNames);
436454
if (!loadedModulesOnly)
437455
{
438456
powershell.AddParameter("ListAvailable", true);
@@ -444,18 +462,26 @@ internal static List<CompletionResult> CompleteModuleName(CompletionContext cont
444462
}
445463
}
446464

447-
Exception exceptionThrown;
448-
var psObjects = context.Helper.ExecuteCurrentPowerShell(out exceptionThrown);
465+
Collection<PSObject> psObjects = context.Helper.ExecuteCurrentPowerShell(out _);
449466

450467
if (psObjects != null)
451468
{
452-
foreach (dynamic moduleInfo in psObjects)
469+
foreach (PSObject item in psObjects)
453470
{
454-
var completionText = moduleInfo.Name.ToString();
471+
var moduleInfo = (PSModuleInfo)item.BaseObject;
472+
var completionText = moduleInfo.Name;
455473
var listItemText = completionText;
456-
var toolTip = "Description: " + moduleInfo.Description.ToString() + "\r\nModuleType: "
474+
if (shortNameSearch
475+
&& completionText.Contains('.')
476+
&& !shortNamePattern.IsMatch(completionText.Substring(completionText.LastIndexOf('.') + 1))
477+
&& !shortNamePattern.IsMatch(completionText))
478+
{
479+
continue;
480+
}
481+
482+
var toolTip = "Description: " + moduleInfo.Description + "\r\nModuleType: "
457483
+ moduleInfo.ModuleType.ToString() + "\r\nPath: "
458-
+ moduleInfo.Path.ToString();
484+
+ moduleInfo.Path;
459485

460486
if (CompletionRequiresQuotes(completionText, false))
461487
{

test/powershell/Host/TabCompletion/TabCompletion.Tests.ps1

+5
5855
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,11 @@ Describe "TabCompletion" -Tags CI {
2323
$res | Should -BeExactly 'Test-AbbreviatedFunctionExpansion'
2424
}
2525

26+
It 'Should complete module by shortname' {
27+
$res = TabExpansion2 -inputScript 'Get-Module -ListAvailable -Name Host'
28+
$res.CompletionMatches[0].CompletionText | Should -BeExactly 'Microsoft.PowerShell.Host'
29+
}
30+
2631
It 'Should complete native exe' -Skip:(!$IsWindows) {
2732
$res = TabExpansion2 -inputScript 'notep' -cursorColumn 'notep'.Length
2833
$res.CompletionMatches[0].CompletionText | Should -BeExactly 'notepad.exe'

0 commit comments

Comments
 (0)
0