Skip to content

Commit af3299a

Browse files
committed
Added default TabExpansion2 implementation so PSES works out of the box in a constrained runspace
1 parent 5d43108 commit af3299a

File tree

2 files changed

+70
-2
lines changed

2 files changed

+70
-2
lines changed

src/PowerShellEditorServices.Hosting/EditorServicesLoader.cs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
using SMA = System.Management.Automation;
1414
using System.Management.Automation;
1515
using System.Management.Automation.Runspaces;
16+
using System.Linq;
1617

1718
#if CoreCLR
1819
using System.Runtime.Loader;
@@ -257,9 +258,15 @@ private void UpdatePSModulePath()
257258
}
258259

259260
string psModulePath = Environment.GetEnvironmentVariable("PSModulePath").TrimEnd(Path.PathSeparator);
261+
string[] psModulePaths = psModulePath.Split(Path.PathSeparator);
262+
if (psModulePaths.Any(a => a == _hostConfig.BundledModulePath))
263+
{
264+
_logger.Log(PsesLogLevel.Verbose, $"PSModulePath already contains '{_hostConfig.BundledModulePath}'");
265+
return;
266+
}
267+
260268
psModulePath = $"{psModulePath}{Path.PathSeparator}{_hostConfig.BundledModulePath}";
261269
Environment.SetEnvironmentVariable("PSModulePath", psModulePath);
262-
263270
_logger.Log(PsesLogLevel.Verbose, $"Updated PSModulePath to: '{psModulePath}'");
264271
}
265272

src/PowerShellEditorServices/Services/PowerShellContext/PowerShellContextService.cs

Lines changed: 62 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,61 @@ static PowerShellContextService()
8484
private readonly Stack<RunspaceDetails> runspaceStack = new Stack<RunspaceDetails>();
8585

8686
private int isCommandLoopRestarterSet;
87+
/// <summary>
88+
/// This is the default function to use for tab expansion.
89+
/// </summary>
90+
private static string tabExpansionFunctionText = @"
91+
<# Options include:
92+
RelativeFilePaths - [bool]
93+
Always resolve file paths using Resolve-Path -Relative.
94+
The default is to use some heuristics to guess if relative or absolute is better.
95+
96+
To customize your own custom options, pass a hashtable to CompleteInput, e.g.
97+
return [System.Management.Automation.CommandCompletion]::CompleteInput($inputScript, $cursorColumn,
98+
@{ RelativeFilePaths=$false }
99+
#>
100+
101+
[CmdletBinding(DefaultParameterSetName = 'ScriptInputSet')]
102+
Param(
103+
[Parameter(ParameterSetName = 'ScriptInputSet', Mandatory = $true, Position = 0)]
104+
[string] $inputScript,
105+
106+
[Parameter(ParameterSetName = 'ScriptInputSet', Position = 1)]
107+
[int] $cursorColumn = $inputScript.Length,
87108
109+
[Parameter(ParameterSetName = 'AstInputSet', Mandatory = $true, Position = 0)]
110+
[System.Management.Automation.Language.Ast] $ast,
111+
112+
[Parameter(ParameterSetName = 'AstInputSet', Mandatory = $true, Position = 1)]
113+
[System.Management.Automation.Language.Token[]] $tokens,
114+
115+
[Parameter(ParameterSetName = 'AstInputSet', Mandatory = $true, Position = 2)]
116+
[System.Management.Automation.Language.IScriptPosition] $positionOfCursor,
117+
118+
[Parameter(ParameterSetName = 'ScriptInputSet', Position = 2)]
119+
[Parameter(ParameterSetName = 'AstInputSet', Position = 3)]
120+
[Hashtable] $options = $null
121+
)
122+
123+
End
124+
{
125+
if ($psCmdlet.ParameterSetName -eq 'ScriptInputSet')
126+
{
127+
return [System.Management.Automation.CommandCompletion]::CompleteInput(
128+
<#inputScript#> $inputScript,
129+
<#cursorColumn#> $cursorColumn,
130+
<#options#> $options)
131+
}
132+
else
133+
{
134+
return [System.Management.Automation.CommandCompletion]::CompleteInput(
135+
<#ast#> $ast,
136+
<#tokens#> $tokens,
137+
<#positionOfCursor#> $positionOfCursor,
138+
<#options#> $options)
139+
}
140+
}
141+
";
88142
#endregion
89143

90144
#region Properties
@@ -216,8 +270,15 @@ public static PowerShellContextService Create(
216270
if (hostStartupInfo.InitialSessionState.LanguageMode != PSLanguageMode.FullLanguage)
217271
{
218272
if(hostStartupInfo.AdditionalModules.Count > 0)
273+
{
219274
hostStartupInfo.InitialSessionState.ImportPSModule(hostStartupInfo.AdditionalModules as string[]);
220-
hostStartupInfo.InitialSessionState.ImportPSModule(new string[] { s_commandsModulePath });
275+
}
276+
277+
hostStartupInfo.InitialSessionState.ImportPSModule(new [] { s_commandsModulePath });
278+
if(!hostStartupInfo.InitialSessionState.Commands.Any(a=> a.Name.ToLower() == "tabexpansion2"))
279+
{
280+
hostStartupInfo.InitialSessionState.Commands.Add(new SessionStateFunctionEntry("TabExpansion2", tabExpansionFunctionText));
281+
}
221282
}
222283
Runspace runspace = PowerShellContextService.CreateRunspace(psHost, hostStartupInfo.InitialSessionState);
223284
powerShellContext.Initialize(hostStartupInfo.ProfilePaths, runspace, true, hostUserInterface);

0 commit comments

Comments
 (0)