Skip to content

Commit 192f41e

Browse files
Fix editor commands to interrupt current prompt (#1725)
Also refactored it slightly to accept the existing `cancellationToken` send to the handler, and removed an unused logger service.
1 parent f7c5c0f commit 192f41e

File tree

4 files changed

+27
-31
lines changed

4 files changed

+27
-31
lines changed

src/PowerShellEditorServices/Extensions/Api/ExtensionCommandService.cs

+2-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using Microsoft.PowerShell.EditorServices.Services.Extension;
55
using System;
66
using System.Collections.Generic;
7+
using System.Threading;
78
using System.Threading.Tasks;
89

910
namespace Microsoft.PowerShell.EditorServices.Extensions.Services
@@ -78,7 +79,7 @@ public ExtensionCommandService(ExtensionService extensionService)
7879

7980
public IReadOnlyList<EditorCommand> GetCommands() => _extensionService.GetCommands();
8081

81-
public Task InvokeCommandAsync(string commandName, EditorContext editorContext) => _extensionService.InvokeCommandAsync(commandName, editorContext);
82+
public Task InvokeCommandAsync(string commandName, EditorContext editorContext) => _extensionService.InvokeCommandAsync(commandName, editorContext, CancellationToken.None);
8283

8384
public bool RegisterCommand(EditorCommand editorCommand) => _extensionService.RegisterCommand(editorCommand);
8485

src/PowerShellEditorServices/Services/Extension/ExtensionService.cs

+10-9
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ internal Task InitializeAsync()
119119
/// <param name="editorContext">The context in which the command is being invoked.</param>
120120
/// <returns>A Task that can be awaited for completion.</returns>
121121
/// <exception cref="KeyNotFoundException">The command being invoked was not registered.</exception>
122-
public async Task InvokeCommandAsync(string commandName, EditorContext editorContext)
122+
public Task InvokeCommandAsync(string commandName, EditorContext editorContext, CancellationToken cancellationToken)
123123
{
124124
if (editorCommands.TryGetValue(commandName, out EditorCommand editorCommand))
125125
{
@@ -128,20 +128,21 @@ public async Task InvokeCommandAsync(string commandName, EditorContext editorCon
128128
.AddParameter("ScriptBlock", editorCommand.ScriptBlock)
129129
.AddParameter("ArgumentList", new object[] { editorContext });
130130

131-
await ExecutionService.ExecutePSCommandAsync(
131+
// This API is used for editor command execution, so it needs to interrupt the
132+
// current prompt (or other foreground task).
133+
return ExecutionService.ExecutePSCommandAsync(
132134
executeCommand,
133-
CancellationToken.None,
135+
cancellationToken,
134136
new PowerShellExecutionOptions
135137
{
136138
WriteOutputToHost = !editorCommand.SuppressOutput,
139+
AddToHistory = !editorCommand.SuppressOutput,
137140
ThrowOnError = false,
138-
AddToHistory = !editorCommand.SuppressOutput
139-
}).ConfigureAwait(false);
140-
}
141-
else
142-
{
143-
throw new KeyNotFoundException($"Editor command not found: '{commandName}'");
141+
InterruptCurrentForeground = true
142+
});
144143
}
144+
145+
throw new KeyNotFoundException($"Editor command not found: '{commandName}'");
145146
}
146147

147148
/// <summary>

src/PowerShellEditorServices/Services/Extension/Handlers/InvokeExtensionCommandHandler.cs

+4-16
Original file line numberDiff line numberDiff line change
@@ -4,40 +4,28 @@
44
using System.Threading;
55
using System.Threading.Tasks;
66
using MediatR;
7-
using Microsoft.Extensions.Logging;
87
using Microsoft.PowerShell.EditorServices.Extensions;
98

109
namespace Microsoft.PowerShell.EditorServices.Services.Extension
1110
{
1211
internal class InvokeExtensionCommandHandler : IInvokeExtensionCommandHandler
1312
{
14-
private readonly ILogger<InvokeExtensionCommandHandler> _logger;
1513
private readonly ExtensionService _extensionService;
1614
private readonly EditorOperationsService _editorOperationsService;
1715

1816
public InvokeExtensionCommandHandler(
19-
ILoggerFactory factory,
2017
ExtensionService extensionService,
21-
EditorOperationsService editorOperationsService
22-
)
18+
EditorOperationsService editorOperationsService)
2319
{
24-
_logger = factory.CreateLogger<InvokeExtensionCommandHandler>();
2520
_extensionService = extensionService;
2621
_editorOperationsService = editorOperationsService;
2722
}
2823

2924
public async Task<Unit> Handle(InvokeExtensionCommandParams request, CancellationToken cancellationToken)
3025
{
31-
// We can now await here because we handle asynchronous message handling.
32-
EditorContext editorContext =
33-
_editorOperationsService.ConvertClientEditorContext(
34-
request.Context);
35-
36-
await _extensionService.InvokeCommandAsync(
37-
request.Name,
38-
editorContext).ConfigureAwait(false);
39-
40-
return await Unit.Task.ConfigureAwait(false);
26+
EditorContext editorContext = _editorOperationsService.ConvertClientEditorContext(request.Context);
27+
await _extensionService.InvokeCommandAsync(request.Name, editorContext, cancellationToken).ConfigureAwait(false);
28+
return Unit.Value;
4129
}
4230
}
4331
}

src/PowerShellEditorServices/Services/PowerShell/Handlers/EvaluateHandler.cs

+11-5
Original file line numberDiff line numberDiff line change
@@ -30,15 +30,21 @@ public EvaluateHandler(
3030

3131
public async Task<EvaluateResponseBody> Handle(EvaluateRequestArguments request, CancellationToken cancellationToken)
3232
{
33-
// TODO: Understand why we currently handle this asynchronously and why we return a dummy result value
34-
// instead of awaiting the execution and returing a real result of some kind
35-
36-
// This API is mostly used for F8 execution, so needs to interrupt the command prompt
33+
// This API is mostly used for F8 execution, so it needs to interrupt the command prompt
34+
// (or other foreground task).
3735
await _executionService.ExecutePSCommandAsync(
3836
new PSCommand().AddScript(request.Expression),
3937
CancellationToken.None,
40-
new PowerShellExecutionOptions { WriteInputToHost = true, WriteOutputToHost = true, AddToHistory = true, ThrowOnError = false, InterruptCurrentForeground = true }).ConfigureAwait(false);
38+
new PowerShellExecutionOptions
39+
{
40+
WriteInputToHost = true,
41+
WriteOutputToHost = true,
42+
AddToHistory = true,
43+
ThrowOnError = false,
44+
InterruptCurrentForeground = true
45+
}).ConfigureAwait(false);
4146

47+
// TODO: Should we return a more informative result?
4248
return new EvaluateResponseBody
4349
{
4450
Result = "",

0 commit comments

Comments
 (0)