Skip to content

Commit 15d6314

Browse files
committed
Add new Commands submodule to expose useful commands inside editor
This change adds a new PowerShellEditorServices.Commands module that gets loaded inside of the editor session's runspace to provide functions and cmdlets which are useful when working with the $psEditor APIs. This will also be the place where built-in "editor commands" are registered when the session initializes. Resolves #403. Resolves PowerShell/vscode-powershell#784.
1 parent 0488a37 commit 15d6314

File tree

10 files changed

+152
-48
lines changed

10 files changed

+152
-48
lines changed

.gitignore

+2-2
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@ lock
2727
registered_data.ini
2828
.vs/
2929
.dotnet/
30-
module/
31-
30+
module/Plaster
31+
module/PSScriptAnalyzer
3232
docs/_site/
3333
docs/_repo/
3434
docs/metadata/
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
#
2+
# Module manifest for module 'PowerShellEditorServices'
3+
#
4+
# Generated by: daviwil
5+
#
6+
# Generated on: 5/12/2016
7+
#
8+
9+
@{
10+
11+
# Script module or binary module file associated with this manifest.
12+
RootModule = 'PowerShellEditorServices.Commands.psm1'
13+
14+
# Version number of this module.
15+
ModuleVersion = '1.0.0'
16+
17+
# ID used to uniquely identify this module
18+
GUID = '9ca15887-53a2-479a-9cda-48d26bcb6c47'
19+
20+
# Author of this module
21+
Author = 'Microsoft'
22+
23+
# Company or vendor of this module
24+
CompanyName = 'Microsoft'
25+
26+
# Copyright statement for this module
27+
Copyright = '(c) 2016 Microsoft. All rights reserved.'
28+
29+
# Description of the functionality provided by this module
30+
Description = 'Provides internal commands for PowerShell Editor Services that only work in an editor session.'
31+
32+
# Minimum version of the Windows PowerShell engine required by this module
33+
# PowerShellVersion = ''
34+
35+
# Name of the Windows PowerShell host required by this module
36+
# PowerShellHostName = ''
37+
38+
# Minimum version of the Windows PowerShell host required by this module
39+
# PowerShellHostVersion = ''
40+
41+
# Minimum version of Microsoft .NET Framework required by this module
42+
# DotNetFrameworkVersion = ''
43+
44+
# Minimum version of the common language runtime (CLR) required by this module
45+
# CLRVersion = ''
46+
47+
# Processor architecture (None, X86, Amd64) required by this module
48+
# ProcessorArchitecture = ''
49+
50+
# Modules that must be imported into the global environment prior to importing this module
51+
# RequiredModules = @()
52+
53+
# Assemblies that must be loaded prior to importing this module
54+
# RequiredAssemblies = @()
55+
56+
# Script files (.ps1) that are run in the caller's environment prior to importing this module.
57+
# ScriptsToProcess = @()
58+
59+
# Type files (.ps1xml) to be loaded when importing this module
60+
# TypesToProcess = @()
61+
62+
# Format files (.ps1xml) to be loaded when importing this module
63+
# FormatsToProcess = @()
64+
65+
# Modules to import as nested modules of the module specified in RootModule/ModuleToProcess
66+
# NestedModules = @()
67+
68+
# Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export.
69+
FunctionsToExport = @('Register-EditorCommand', 'Unregister-EditorCommand')
70+
71+
# Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export.
72+
CmdletsToExport = @()
73+
74+
# Variables to export from this module
75+
VariablesToExport = @()
76+
77+
# Aliases to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no aliases to export.
78+
AliasesToExport = @()
79+
80+
# DSC resources to export from this module
81+
# DscResourcesToExport = @()
82+
83+
# List of all modules packaged with this module
84+
# ModuleList = @()
85+
86+
# List of all files packaged with this module
87+
# FileList = @()
88+
89+
# Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData hashtable with additional module metadata used by PowerShell.
90+
PrivateData = @{
91+
92+
PSData = @{
93+
94+
# Tags applied to this module. These help with module discovery in online galleries.
95+
# Tags = @()
96+
97+
# A URL to the license for this module.
98+
# LicenseUri = ''
99+
100+
# A URL to the main website for this project.
101+
# ProjectUri = ''
102+
103+
# A URL to an icon representing this module.
104+
# IconUri = ''
105+
106+
# ReleaseNotes of this module
107+
# ReleaseNotes = ''
108+
109+
} # End of PSData hashtable
110+
111+
} # End of PrivateData hashtable
112+
113+
# HelpInfo URI of this module
114+
# HelpInfoURI = ''
115+
116+
# Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix.
117+
# DefaultCommandPrefix = ''
118+
119+
}
120+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
2+
# TODO: Use a better script loading process here
3+
. $PSScriptRoot\Public\CmdletInterface.ps1

src/PowerShellEditorServices.Host/EditorServicesHost.cs

+6
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
using System;
1313
using System.Collections.Generic;
1414
using System.Diagnostics;
15+
using System.IO;
1516
using System.Management.Automation.Runspaces;
1617
using System.Reflection;
1718
using System.Threading.Tasks;
@@ -190,6 +191,11 @@ private async void OnLanguageServiceClientConnect(
190191
this.editorSession,
191192
serverChannel);
192193

194+
await this.editorSession.PowerShellContext.ImportCommandsModule(
195+
Path.Combine(
196+
Path.GetDirectoryName(this.GetType().GetTypeInfo().Assembly.Location),
197+
@"..\..\Commands"));
198+
193199
await this.languageServer.Start();
194200
}
195201

src/PowerShellEditorServices/Extensions/ExtensionService.cs

-40
Original file line numberDiff line numberDiff line change
@@ -81,46 +81,6 @@ public async Task Initialize(IEditorOperations editorOperations)
8181
"psEditor",
8282
this.EditorObject);
8383
}
84-
85-
// Load the cmdlet interface
86-
Type thisType = this.GetType();
87-
Stream resourceStream =
88-
thisType.GetTypeInfo().Assembly.GetManifestResourceStream(
89-
thisType.Namespace + ".CmdletInterface.ps1");
90-
91-
using (StreamReader reader = new StreamReader(resourceStream))
92-
{
93-
// Create a temporary folder path
94-
string randomFileNamePart =
95-
Path.GetFileNameWithoutExtension(
96-
Path.GetRandomFileName());
97-
98-
string tempScriptPath =
99-
Path.Combine(
100-
Path.GetTempPath(),
101-
"PSES_ExtensionCmdlets_" + randomFileNamePart + ".ps1");
102-
103-
Logger.Write(
104-
LogLevel.Verbose,
105-
"Executing extension API cmdlet script at path: " + tempScriptPath);
106-
107-
// Read the cmdlet interface script and write it to a temporary
108-
// file so that we don't have to execute the full file contents
109-
// directly. This keeps the script execution from creating a
110-
// lot of noise in the verbose logs.
111-
string cmdletInterfaceScript = reader.ReadToEnd();
112-
File.WriteAllText(
113-
tempScriptPath,
114-
cmdletInterfaceScript);
115-
116-
await this.PowerShellContext.ExecuteScriptString(
117-
". " + tempScriptPath,
118-
writeInputToHost: false,
119-
writeOutputToHost: false);
120-
121-
// Delete the temporary file
122-
File.Delete(tempScriptPath);
123-
}
12484
}
12585

12686
/// <summary>

src/PowerShellEditorServices/PowerShellEditorServices.csproj

-6
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,6 @@
88
<PackageTargetFallback Condition=" '$(TargetFramework)' == 'netstandard1.6' ">$(PackageTargetFallback);dnxcore50;portable-net45+win8</PackageTargetFallback>
99
</PropertyGroup>
1010

11-
<ItemGroup>
12-
<EmbeddedResource Include="Extensions\CmdletInterface.ps1">
13-
<LogicalName>Microsoft.PowerShell.EditorServices.Extensions.CmdletInterface.ps1</LogicalName>
14-
</EmbeddedResource>
15-
</ItemGroup>
16-
1711
<PropertyGroup>
1812
<!-- NOTE: -->
1913
<!-- For PowerShell v5 there are some differences between the APIs released with -->

src/PowerShellEditorServices/Session/PowerShellContext.cs

+19
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,25 @@ public void Initialize(
252252
this.runspaceWaitQueue.EnqueueAsync(runspaceHandle).Wait();
253253
}
254254

255+
/// <summary>
256+
/// Imports the PowerShellEditorServices.Commands module into
257+
/// the runspace. This method will be moved somewhere else soon.
258+
/// </summary>
259+
/// <param name="moduleBasePath"></param>
260+
/// <returns></returns>
261+
public Task ImportCommandsModule(string moduleBasePath)
262+
{
263+
PSCommand importCommand = new PSCommand();
264+
importCommand
265+
.AddCommand("Import-Module")
266+
.AddArgument(
267+
Path.Combine(
268+
moduleBasePath,
269+
"PowerShellEditorServices.Commands.psd1"));
270+
271+
return this.ExecuteCommand<PSObject>(importCommand, false, false);
272+
}
273+
255274
private static bool CheckIfRunspaceNeedsEventHandlers(RunspaceDetails runspaceDetails)
256275
{
257276
// The only types of runspaces that need to be configured are:

test/PowerShellEditorServices.Test/Extensions/ExtensionServiceTests.cs

+2
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ private enum EventType
3636
public async Task InitializeAsync()
3737
{
3838
this.powerShellContext = PowerShellContextFactory.Create();
39+
await this.powerShellContext.ImportCommandsModule(@"..\..\..\..\..\module\PowerShellEditorServices\Commands");
40+
3941
this.extensionService = new ExtensionService(this.powerShellContext);
4042
this.editorOperations = new TestEditorOperations();
4143

0 commit comments

Comments
 (0)