@@ -24,6 +24,10 @@ namespace Microsoft.PowerShell.EditorServices.Services.PowerShell.Host
2424{
2525 using System . Management . Automation ;
2626 using System . Management . Automation . Runspaces ;
27+ // NOTE: These last three are for a workaround for temporary integrated consoles.
28+ using Microsoft . PowerShell . EditorServices . Handlers ;
29+ using Microsoft . PowerShell . EditorServices . Server ;
30+ using OmniSharp . Extensions . DebugAdapter . Protocol . Server ;
2731
2832 internal class PsesInternalHost : PSHost , IHostSupportsInteractiveSession , IRunspaceContext , IInternalPowerShellExecutionService
2933 {
@@ -41,6 +45,14 @@ internal class PsesInternalHost : PSHost, IHostSupportsInteractiveSession, IRuns
4145
4246 private readonly ILanguageServerFacade _languageServer ;
4347
48+ /// <summary>
49+ /// TODO: Improve this coupling. It's assigned by <see cref="PsesDebugServer.StartAsync()" />
50+ /// so that the PowerShell process started when <see cref="PsesLaunchRequestArguments.CreateTemporaryIntegratedConsole" />
51+ /// is true can also receive the required 'sendKeyPress' notification to return from a
52+ /// canceled <see cref="System.Console.ReadKey()" />.
53+ /// </summary>
54+ internal IDebugAdapterServerFacade DebugServer ;
55+
4456 private readonly HostStartupInfo _hostInfo ;
4557
4658 private readonly BlockingConcurrentDeque < ISynchronousTask > _taskQueue ;
@@ -1053,20 +1065,31 @@ private void OnCancelKeyPress(object sender, ConsoleCancelEventArgs args)
10531065
10541066 private ConsoleKeyInfo ReadKey ( bool intercept )
10551067 {
1056- // PSRL doesn't tell us when CtrlC was sent.
1057- // So instead we keep track of the last key here.
1058- // This isn't functionally required,
1059- // but helps us determine when the prompt needs a newline added
1060-
10611068 // NOTE: This requests that the client (the Code extension) send a non-printing key back
10621069 // to the terminal on stdin, emulating a user pressing a button. This allows
10631070 // PSReadLine's thread waiting on Console.ReadKey to return. Normally we'd just cancel
10641071 // this call, but the .NET API ReadKey is not cancellable, and is stuck until we send
10651072 // input. This leads to a myriad of problems, but we circumvent them by pretending to
10661073 // press a key, thus allowing ReadKey to return, and us to ignore it.
10671074 using CancellationTokenRegistration registration = _readKeyCancellationToken . Register (
1068- ( ) => _languageServer ? . SendNotification ( "powerShell/sendKeyPress" ) ) ;
1069-
1075+ ( ) =>
1076+ {
1077+ // For the regular integrated console, we have an associated language server on
1078+ // which we can send a notification, and have the client subscribe an action to
1079+ // send a key press.
1080+ _languageServer ? . SendNotification ( "powerShell/sendKeyPress" ) ;
1081+
1082+ // When temporary integrated consoles are spawned, there will be no associated
1083+ // language server, but instead a debug adaptor server. In this case, the
1084+ // notification sent here will come across as a DebugSessionCustomEvent to which
1085+ // we can subscribe in the same way.
1086+ DebugServer ? . SendNotification ( "powerShell/sendKeyPress" ) ;
1087+ } ) ;
1088+
1089+ // PSReadLine doesn't tell us when CtrlC was sent. So instead we keep track of the last
1090+ // key here. This isn't functionally required, but helps us determine when the prompt
1091+ // needs a newline added
1092+ //
10701093 // TODO: We may want to allow users of PSES to override this method call.
10711094 _lastKey = System . Console . ReadKey ( intercept ) ;
10721095 return _lastKey . Value ;
0 commit comments