Skip to content

Commit 9266126

Browse files
committed
Continue tweaking REPL
1 parent b9b9b36 commit 9266126

File tree

10 files changed

+139
-63
lines changed

10 files changed

+139
-63
lines changed

src/PowerShellEditorServices/Services/PowerShell/Console/ConsoleReadLine.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ private static Task<ConsoleKeyInfo> ReadKeyAsync(CancellationToken cancellationT
139139

140140
private Task<string> ReadLineAsync(bool isCommandLine, CancellationToken cancellationToken)
141141
{
142-
return _executionService.ExecuteDelegateAsync(InvokePSReadLine, cancellationToken);
142+
return _executionService.ExecuteDelegateAsync(InvokePSReadLine, representation: "ReadLine", cancellationToken);
143143
}
144144

145145
private string InvokePSReadLine(CancellationToken cancellationToken)

src/PowerShellEditorServices/Services/PowerShell/Execution/PowerShellExecutionOptions.cs

+2-8
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,10 @@ public struct PowerShellExecutionOptions
1414

1515
public bool AddToHistory { get; set; }
1616

17-
public bool InterruptCommandPrompt { get; set; }
18-
1917
public bool WriteInputToHost { get; set; }
2018

21-
public string InputStringToDisplay { get; set; }
22-
23-
public bool UseNewScope { get; set; }
19+
public bool PropagateCancellationToCaller { get; set; }
2420

25-
internal bool IsReadLine { get; set; }
26-
27-
internal bool ShouldExecuteInOriginalRunspace { get; set; }
21+
public bool InterruptCommandPrompt { get; set; }
2822
}
2923
}

src/PowerShellEditorServices/Services/PowerShell/Execution/SynchronousDelegateTask.cs

+18
Original file line numberDiff line numberDiff line change
@@ -8,38 +8,56 @@ internal class SynchronousDelegateTask : SynchronousTask<object>
88
{
99
private readonly Action<CancellationToken> _action;
1010

11+
private readonly string _representation;
12+
1113
public SynchronousDelegateTask(
1214
ILogger logger,
1315
Action<CancellationToken> action,
16+
string representation,
1417
CancellationToken cancellationToken)
1518
: base(logger, cancellationToken)
1619
{
1720
_action = action;
21+
_representation = representation;
1822
}
1923

2024
public override object Run(CancellationToken cancellationToken)
2125
{
2226
_action(cancellationToken);
2327
return null;
2428
}
29+
30+
public override string ToString()
31+
{
32+
return _representation;
33+
}
2534
}
2635

2736
internal class SynchronousDelegateTask<TResult> : SynchronousTask<TResult>
2837
{
2938
private readonly Func<CancellationToken, TResult> _func;
3039

40+
private readonly string _representation;
41+
3142
public SynchronousDelegateTask(
3243
ILogger logger,
3344
Func<CancellationToken, TResult> func,
45+
string representation,
3446
CancellationToken cancellationToken)
3547
: base(logger, cancellationToken)
3648
{
3749
_func = func;
50+
_representation = representation;
3851
}
3952

4053
public override TResult Run(CancellationToken cancellationToken)
4154
{
4255
return _func(cancellationToken);
4356
}
57+
58+
public override string ToString()
59+
{
60+
return _representation;
61+
}
4462
}
4563
}

src/PowerShellEditorServices/Services/PowerShell/Execution/SynchronousPowerShellTask.cs

+30-9
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using System;
44
using System.Collections.ObjectModel;
55
using System.Management.Automation;
6+
using System.Management.Automation.Host;
67
using System.Management.Automation.Remoting;
78
using System.Threading;
89
using SMA = System.Management.Automation;
@@ -15,17 +16,21 @@ internal class SynchronousPowerShellTask<TResult> : SynchronousTask<Collection<T
1516

1617
private readonly PSCommand _psCommand;
1718

19+
private readonly PSHost _psHost;
20+
1821
private readonly PowerShellExecutionOptions _executionOptions;
1922

2023
public SynchronousPowerShellTask(
2124
ILogger logger,
2225
SMA.PowerShell pwsh,
26+
PSHost psHost,
2327
PSCommand command,
2428
PowerShellExecutionOptions executionOptions,
2529
CancellationToken cancellationToken)
2630
: base(logger, cancellationToken)
2731
{
2832
_pwsh = pwsh;
33+
_psHost = psHost;
2934
_psCommand = command;
3035
_executionOptions = executionOptions;
3136
}
@@ -36,6 +41,11 @@ public override Collection<TResult> Run(CancellationToken cancellationToken)
3641

3742
_pwsh.Commands = _psCommand;
3843

44+
if (_executionOptions.WriteInputToHost)
45+
{
46+
_psHost.UI.WriteLine(_psCommand.GetInvocationText());
47+
}
48+
3949
if (_executionOptions.WriteOutputToHost)
4050
{
4151
_pwsh.AddOutputCommand();
@@ -45,6 +55,11 @@ public override Collection<TResult> Run(CancellationToken cancellationToken)
4555
try
4656
{
4757
result = _pwsh.InvokeAndClear<TResult>();
58+
59+
if (_executionOptions.PropagateCancellationToCaller)
60+
{
61+
cancellationToken.ThrowIfCancellationRequested();
62+
}
4863
}
4964
catch (Exception e) when (e is PipelineStoppedException || e is PSRemotingDataStructureException)
5065
{
@@ -56,25 +71,31 @@ public override Collection<TResult> Run(CancellationToken cancellationToken)
5671
{
5772
Logger.LogWarning($"Runtime exception occurred while executing command:{Environment.NewLine}{Environment.NewLine}{e}");
5873

59-
if (_executionOptions.WriteErrorsToHost)
74+
if (!_executionOptions.WriteErrorsToHost)
6075
{
61-
_pwsh.AddOutputCommand()
62-
.AddParameter("InputObject", e.ErrorRecord.AsPSObject())
63-
.InvokeAndClear();
76+
throw;
6477
}
6578

66-
throw;
79+
_pwsh.AddOutputCommand()
80+
.AddParameter("InputObject", e.ErrorRecord.AsPSObject())
81+
.InvokeAndClear();
6782
}
68-
69-
70-
if (_pwsh.HadErrors)
83+
finally
7184
{
72-
_pwsh.Streams.Error.Clear();
85+
if (_pwsh.HadErrors)
86+
{
87+
_pwsh.Streams.Error.Clear();
88+
}
7389
}
7490

7591
return result;
7692
}
7793

94+
public override string ToString()
95+
{
96+
return _psCommand.GetInvocationText();
97+
}
98+
7899
private void Cancel()
79100
{
80101
_pwsh.Stop();

src/PowerShellEditorServices/Services/PowerShell/Execution/SynchronousTask.cs

+5-1
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ protected SynchronousTask(ILogger logger, CancellationToken cancellationToken)
3636

3737
public abstract TResult Run(CancellationToken cancellationToken);
3838

39+
public abstract override string ToString();
40+
3941
public void ExecuteSynchronously(ref CancellationTokenSource cancellationSource, CancellationToken threadCancellation)
4042
{
4143
if (_taskCancellationToken.IsCancellationRequested || threadCancellation.IsCancellationRequested)
@@ -47,7 +49,9 @@ public void ExecuteSynchronously(ref CancellationTokenSource cancellationSource,
4749
cancellationSource = CancellationTokenSource.CreateLinkedTokenSource(_taskCancellationToken, threadCancellation);
4850
try
4951
{
50-
_taskCompletionSource.SetResult(Run(cancellationSource.Token));
52+
TResult result = Run(cancellationSource.Token);
53+
54+
_taskCompletionSource.SetResult(result);
5155
}
5256
catch (OperationCanceledException)
5357
{

src/PowerShellEditorServices/Services/PowerShell/PowerShellConsoleService.cs

+30-12
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ public static PowerShellConsoleService CreateAndStart(
2121
executionService,
2222
executionService.EngineIntrinsics,
2323
executionService.EditorServicesHost,
24-
executionService.ReadLine);
24+
executionService.ReadLine,
25+
executionService.PSReadLineProxy);
2526

2627
return consoleService;
2728
}
@@ -36,6 +37,8 @@ public static PowerShellConsoleService CreateAndStart(
3637

3738
private readonly ConsoleReadLine _readLine;
3839

40+
private readonly PSReadLineProxy _psrlProxy;
41+
3942
private Task _consoleLoopThread;
4043

4144
private CancellationTokenSource _replLoopCancellationSource;
@@ -47,13 +50,15 @@ private PowerShellConsoleService(
4750
PowerShellExecutionService executionService,
4851
EngineIntrinsics engineIntrinsics,
4952
EditorServicesConsolePSHost editorServicesHost,
50-
ConsoleReadLine readLine)
53+
ConsoleReadLine readLine,
54+
PSReadLineProxy psrlProxy)
5155
{
5256
_logger = loggerFactory.CreateLogger<PowerShellConsoleService>();
5357
_executionService = executionService;
5458
_engineIntrinsics = engineIntrinsics;
5559
_editorServicesHost = editorServicesHost;
5660
_readLine = readLine;
61+
_psrlProxy = psrlProxy;
5762
}
5863

5964
public void Dispose()
@@ -66,7 +71,14 @@ public void StartRepl()
6671
_replLoopCancellationSource = new CancellationTokenSource();
6772
System.Console.CancelKeyPress += HandleConsoleCancellation;
6873
System.Console.OutputEncoding = Encoding.UTF8;
74+
_psrlProxy.OverrideReadKey(ReadKey);
6975
_consoleLoopThread = Task.Run(RunReplLoopAsync, _replLoopCancellationSource.Token);
76+
_executionService.RegisterConsoleService(this);
77+
}
78+
79+
public void CancelCurrentPrompt()
80+
{
81+
_currentCommandCancellationSource?.Cancel();
7082
}
7183

7284
private async Task RunReplLoopAsync()
@@ -78,29 +90,29 @@ private async Task RunReplLoopAsync()
7890
try
7991
{
8092
await InvokePromptFunctionAsync().ConfigureAwait(false);
81-
}
82-
catch (OperationCanceledException)
83-
{
84-
break;
85-
}
8693

87-
try
88-
{
89-
// Poll for user input here so that the prompt does not block
90-
string userInput = await InvokeReadLineAsync();
94+
string userInput = await InvokeReadLineAsync().ConfigureAwait(false);
9195

9296
await InvokeInputAsync(userInput).ConfigureAwait(false);
9397
}
9498
catch (OperationCanceledException)
9599
{
96100
continue;
97101
}
102+
catch (Exception e)
103+
{
104+
105+
}
98106
}
99107
}
100108

101109
private Task InvokePromptFunctionAsync()
102110
{
103-
var promptCommand = new PSCommand().AddCommand("prompt");
111+
var promptCommand = new PSCommand()
112+
.AddCommand("prompt")
113+
.AddCommand("Write-Host")
114+
.AddParameter("NoNewline");
115+
104116
var executionOptions = new PowerShellExecutionOptions
105117
{
106118
WriteOutputToHost = true,
@@ -131,6 +143,12 @@ private Task InvokeInputAsync(string input)
131143

132144
private void HandleConsoleCancellation(object sender, ConsoleCancelEventArgs args)
133145
{
146+
_currentCommandCancellationSource.Cancel();
147+
}
148+
149+
private ConsoleKeyInfo ReadKey(bool intercept)
150+
{
151+
return ConsoleProxy.SafeReadKey(intercept, _currentCommandCancellationSource?.Token ?? CancellationToken.None);
134152
}
135153
}
136154
}

0 commit comments

Comments
 (0)