From 2ac482360258a86391b34ed01673eb636a23396c Mon Sep 17 00:00:00 2001 From: Patrick Meinecke Date: Thu, 28 Apr 2022 11:59:02 -0400 Subject: [PATCH 1/3] Track cursor position when writing prompt We were running into a situation where we'd print the prompt on the same line that we had previously printed it. This was especially noticable when stepping through the debugger. This change ensures that we always write a new line if that situation occurs. --- .../PowerShell/Host/PsesInternalHost.cs | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/PowerShellEditorServices/Services/PowerShell/Host/PsesInternalHost.cs b/src/PowerShellEditorServices/Services/PowerShell/Host/PsesInternalHost.cs index 8b2fd79ad..cc7d65321 100644 --- a/src/PowerShellEditorServices/Services/PowerShell/Host/PsesInternalHost.cs +++ b/src/PowerShellEditorServices/Services/PowerShell/Host/PsesInternalHost.cs @@ -1,4 +1,4 @@ -// Copyright (c) Microsoft Corporation. +// Copyright (c) Microsoft Corporation. // Licensed under the MIT License. using System; @@ -77,6 +77,8 @@ internal class PsesInternalHost : PSHost, IHostSupportsInteractiveSession, IRuns private bool _resettingRunspace; + private (int x, int y)? _lastPromptPosition; + public PsesInternalHost( ILoggerFactory loggerFactory, ILanguageServerFacade languageServer, @@ -757,7 +759,20 @@ private void DoOneRepl(CancellationToken cancellationToken) try { string prompt = GetPrompt(cancellationToken); + + // Check cursor position to see if we're in the exact same spot as the last time we + // wrote the prompt. If we are, write a new line. + if (_lastPromptPosition is not null) + { + (int x, int y) current = (System.Console.CursorLeft, System.Console.CursorTop); + if (current == _lastPromptPosition.Value) + { + UI.WriteLine(); + } + } + UI.Write(prompt); + _lastPromptPosition = (System.Console.CursorLeft, System.Console.CursorTop); string userInput = InvokeReadLine(cancellationToken); // If the user input was empty it's because: From baf33e973c6acf8d00ea2ad2d35c8d36fc4b9898 Mon Sep 17 00:00:00 2001 From: Patrick Meinecke Date: Thu, 28 Apr 2022 13:30:34 -0400 Subject: [PATCH 2/3] Revert "Track cursor position when writing prompt" This reverts commit 2ac482360258a86391b34ed01673eb636a23396c. --- .../PowerShell/Host/PsesInternalHost.cs | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/src/PowerShellEditorServices/Services/PowerShell/Host/PsesInternalHost.cs b/src/PowerShellEditorServices/Services/PowerShell/Host/PsesInternalHost.cs index cc7d65321..8b2fd79ad 100644 --- a/src/PowerShellEditorServices/Services/PowerShell/Host/PsesInternalHost.cs +++ b/src/PowerShellEditorServices/Services/PowerShell/Host/PsesInternalHost.cs @@ -1,4 +1,4 @@ -// Copyright (c) Microsoft Corporation. +// Copyright (c) Microsoft Corporation. // Licensed under the MIT License. using System; @@ -77,8 +77,6 @@ internal class PsesInternalHost : PSHost, IHostSupportsInteractiveSession, IRuns private bool _resettingRunspace; - private (int x, int y)? _lastPromptPosition; - public PsesInternalHost( ILoggerFactory loggerFactory, ILanguageServerFacade languageServer, @@ -759,20 +757,7 @@ private void DoOneRepl(CancellationToken cancellationToken) try { string prompt = GetPrompt(cancellationToken); - - // Check cursor position to see if we're in the exact same spot as the last time we - // wrote the prompt. If we are, write a new line. - if (_lastPromptPosition is not null) - { - (int x, int y) current = (System.Console.CursorLeft, System.Console.CursorTop); - if (current == _lastPromptPosition.Value) - { - UI.WriteLine(); - } - } - UI.Write(prompt); - _lastPromptPosition = (System.Console.CursorLeft, System.Console.CursorTop); string userInput = InvokeReadLine(cancellationToken); // If the user input was empty it's because: From 5d38acabcb44a4caa73790605b32740e248d7ca9 Mon Sep 17 00:00:00 2001 From: Patrick Meinecke Date: Thu, 28 Apr 2022 13:44:20 -0400 Subject: [PATCH 3/3] Add `WriteWithPrompt` workaround back in --- .../Execution/SynchronousPowerShellTask.cs | 2 +- .../Services/PowerShell/Host/PsesInternalHost.cs | 15 ++++++++++++++- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/PowerShellEditorServices/Services/PowerShell/Execution/SynchronousPowerShellTask.cs b/src/PowerShellEditorServices/Services/PowerShell/Execution/SynchronousPowerShellTask.cs index 52ea70efe..71accf212 100644 --- a/src/PowerShellEditorServices/Services/PowerShell/Execution/SynchronousPowerShellTask.cs +++ b/src/PowerShellEditorServices/Services/PowerShell/Execution/SynchronousPowerShellTask.cs @@ -62,7 +62,7 @@ public override IReadOnlyList Run(CancellationToken cancellationToken) if (PowerShellExecutionOptions.WriteInputToHost) { - _psesHost.UI.WriteLine(_psCommand.GetInvocationText()); + _psesHost.WriteWithPrompt(_psCommand, cancellationToken); } return _pwsh.Runspace.Debugger.InBreakpoint diff --git a/src/PowerShellEditorServices/Services/PowerShell/Host/PsesInternalHost.cs b/src/PowerShellEditorServices/Services/PowerShell/Host/PsesInternalHost.cs index 8b2fd79ad..0d674b64c 100644 --- a/src/PowerShellEditorServices/Services/PowerShell/Host/PsesInternalHost.cs +++ b/src/PowerShellEditorServices/Services/PowerShell/Host/PsesInternalHost.cs @@ -770,7 +770,7 @@ private void DoOneRepl(CancellationToken cancellationToken) // one, but we do not want to print one if the ReadLine task was canceled. if (string.IsNullOrEmpty(userInput)) { - if (LastKeyWasCtrlC()) + if (cancellationToken.IsCancellationRequested || LastKeyWasCtrlC()) { UI.WriteLine(); } @@ -836,6 +836,19 @@ private string GetPrompt(CancellationToken cancellationToken) return prompt; } + /// + /// This is used to write the invocation text of a command with the user's prompt so that, + /// for example, F8 (evaluate selection) appears as if the user typed it. Used when + /// 'WriteInputToHost' is true. + /// + /// The PSCommand we'll print after the prompt. + /// + public void WriteWithPrompt(PSCommand command, CancellationToken cancellationToken) + { + UI.Write(GetPrompt(cancellationToken)); + UI.WriteLine(command.GetInvocationText()); + } + private string InvokeReadLine(CancellationToken cancellationToken) { try