Skip to content

Commit 6c7da2b

Browse files
committed
Added default TabExpansion2 implementation so PSES works out of the box in a constrained runspace
1 parent 79f4b8c commit 6c7da2b

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
@@ -88,7 +88,61 @@ static PowerShellContextService()
8888
private readonly Stack<RunspaceDetails> runspaceStack = new Stack<RunspaceDetails>();
8989

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

94148
#region Properties
@@ -220,8 +274,15 @@ public static PowerShellContextService Create(
220274
if (hostStartupInfo.InitialSessionState.LanguageMode != PSLanguageMode.FullLanguage)
221275
{
222276
if(hostStartupInfo.AdditionalModules.Count > 0)
277+
{
223278
hostStartupInfo.InitialSessionState.ImportPSModule(hostStartupInfo.AdditionalModules as string[]);
224-
hostStartupInfo.InitialSessionState.ImportPSModule(new string[] { s_commandsModulePath });
279+
}
280+
281+
hostStartupInfo.InitialSessionState.ImportPSModule(new [] { s_commandsModulePath });
282+
if(!hostStartupInfo.InitialSessionState.Commands.Any(a=> a.Name.ToLower() == "tabexpansion2"))
283+
{
284+
hostStartupInfo.InitialSessionState.Commands.Add(new SessionStateFunctionEntry("TabExpansion2", tabExpansionFunctionText));
285+
}
225286
}
226287
Runspace runspace = PowerShellContextService.CreateRunspace(psHost, hostStartupInfo.InitialSessionState);
227288
powerShellContext.Initialize(hostStartupInfo.ProfilePaths, runspace, true, hostUserInterface);

0 commit comments

Comments
 (0)