Skip to content

Commit 4c9c2f5

Browse files
committed
Fix #2313: Clear terminal scrollback in-band
1 parent f813cdf commit 4c9c2f5

3 files changed

Lines changed: 80 additions & 3 deletions

File tree

src/PowerShellEditorServices/Services/Extension/EditorOperationsService.cs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Copyright (c) Microsoft Corporation.
22
// Licensed under the MIT License.
33

4+
using System;
45
using Microsoft.PowerShell.EditorServices.Extensions;
56
using Microsoft.PowerShell.EditorServices.Services.PowerShell.Host;
67
using Microsoft.PowerShell.EditorServices.Services.TextDocument;
@@ -17,15 +18,18 @@ internal class EditorOperationsService : IEditorOperations
1718
private readonly PsesInternalHost _psesHost;
1819
private readonly WorkspaceService _workspaceService;
1920
private readonly ILanguageServerFacade _languageServer;
21+
private readonly ConfigurationService _configurationService;
2022

2123
public EditorOperationsService(
2224
PsesInternalHost psesHost,
2325
WorkspaceService workspaceService,
24-
ILanguageServerFacade languageServer)
26+
ILanguageServerFacade languageServer,
27+
ConfigurationService configurationService)
2528
{
2629
_psesHost = psesHost;
2730
_workspaceService = workspaceService;
2831
_languageServer = languageServer;
32+
_configurationService = configurationService;
2933
}
3034

3135
public async Task<EditorContext> GetEditorContextAsync()
@@ -260,6 +264,12 @@ public async Task SetStatusBarMessageAsync(string message, int? timeout)
260264

261265
public void ClearTerminal()
262266
{
267+
if (_configurationService.CurrentSettings.IntegratedConsole.ForceClearScrollbackBuffer)
268+
{
269+
Console.Write("\u001b[3J");
270+
return;
271+
}
272+
263273
if (!TestHasLanguageServer(warnUser: false))
264274
{
265275
return;

src/PowerShellEditorServices/Services/Workspace/LanguageServerSettings.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ internal class LanguageServerSettings
2121
public CodeFormattingSettings CodeFormatting { get; set; }
2222
public CodeFoldingSettings CodeFolding { get; set; }
2323
public PesterSettings Pester { get; set; }
24+
public IntegratedConsoleSettings IntegratedConsole { get; set; }
2425
public string Cwd { get; set; }
2526
public bool EnableReferencesCodeLens { get; set; } = true;
2627
public bool AnalyzeOpenDocumentsOnly { get; set; }
@@ -31,6 +32,7 @@ public LanguageServerSettings()
3132
CodeFormatting = new CodeFormattingSettings();
3233
CodeFolding = new CodeFoldingSettings();
3334
Pester = new PesterSettings();
35+
IntegratedConsole = new IntegratedConsoleSettings();
3436
}
3537

3638
public void Update(
@@ -47,6 +49,7 @@ public void Update(
4749
CodeFormatting = new CodeFormattingSettings(settings.CodeFormatting);
4850
CodeFolding.Update(settings.CodeFolding, logger);
4951
Pester.Update(settings.Pester, logger);
52+
IntegratedConsole = new IntegratedConsoleSettings(settings.IntegratedConsole);
5053
Cwd = settings.Cwd;
5154
EnableReferencesCodeLens = settings.EnableReferencesCodeLens;
5255
AnalyzeOpenDocumentsOnly = settings.AnalyzeOpenDocumentsOnly;
@@ -55,6 +58,21 @@ public void Update(
5558
}
5659
}
5760

61+
internal class IntegratedConsoleSettings
62+
{
63+
public IntegratedConsoleSettings() { }
64+
65+
public IntegratedConsoleSettings(IntegratedConsoleSettings integratedConsoleSettings)
66+
{
67+
if (integratedConsoleSettings is not null)
68+
{
69+
ForceClearScrollbackBuffer = integratedConsoleSettings.ForceClearScrollbackBuffer;
70+
}
71+
}
72+
73+
public bool ForceClearScrollbackBuffer { get; set; }
74+
}
75+
5876
internal class ScriptAnalysisSettings
5977
{
6078
private readonly object updateLock = new();

test/PowerShellEditorServices.Test/Extensions/EditorOperationsServiceTests.cs

Lines changed: 51 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,21 @@
66
using Microsoft.Extensions.Logging.Abstractions;
77
using Microsoft.PowerShell.EditorServices.Extensions;
88
using Microsoft.PowerShell.EditorServices.Services;
9+
using Microsoft.PowerShell.EditorServices.Services.Configuration;
910
using Microsoft.PowerShell.EditorServices.Services.Extension;
1011
using Microsoft.PowerShell.EditorServices.Services.TextDocument;
12+
using Newtonsoft.Json;
1113
using OmniSharp.Extensions.LanguageServer.Protocol;
1214
using Xunit;
1315

1416
namespace PowerShellEditorServices.Test.Extensions
1517
{
18+
[CollectionDefinition("Console", DisableParallelization = true)]
19+
public class ConsoleCollectionDefinition
20+
{
21+
}
22+
23+
[Collection("Console")]
1624
[Trait("Category", "Extensions")]
1725
public class EditorOperationsServiceTests
1826
{
@@ -36,7 +44,8 @@ public void GetWorkspaceOpenDocumentsReturnsOnlyOpenDocumentsAndCurrentInMemoryS
3644
EditorOperationsService editorOperationsService = new(
3745
psesHost: null,
3846
workspaceService,
39-
languageServer: null);
47+
languageServer: null,
48+
new ConfigurationService());
4049

4150
WorkspaceOpenDocument[] documents = editorOperationsService.GetWorkspaceOpenDocuments();
4251

@@ -60,7 +69,8 @@ public void GetWorkspaceOpenDocumentsTracksEditedAndUntitledSaveStates()
6069
EditorOperationsService editorOperationsService = new(
6170
psesHost: null,
6271
workspaceService,
63-
languageServer: null);
72+
languageServer: null,
73+
new ConfigurationService());
6474

6575
WorkspaceOpenDocument[] initialDocuments = editorOperationsService.GetWorkspaceOpenDocuments();
6676
Assert.Contains(initialDocuments, static document => document.Path.EndsWith("open-saved.ps1") && document.Saved);
@@ -87,6 +97,45 @@ public void GetWorkspaceOpenDocumentsTracksEditedAndUntitledSaveStates()
8797
Assert.Contains(savedDocuments, static document => document.Path.StartsWith("untitled:", StringComparison.Ordinal) && !document.Saved);
8898
}
8999

100+
[Fact]
101+
public void LanguageServerSettingsUpdatesForceClearScrollbackBuffer()
102+
{
103+
LanguageServerSettings incomingSettings = JsonConvert.DeserializeObject<LanguageServerSettings>(
104+
"{\"integratedConsole\":{\"forceClearScrollbackBuffer\":true}}");
105+
LanguageServerSettings currentSettings = new();
106+
107+
currentSettings.Update(incomingSettings, workspaceRootPath: string.Empty, NullLogger.Instance);
108+
109+
Assert.True(currentSettings.IntegratedConsole.ForceClearScrollbackBuffer);
110+
}
111+
112+
[Fact]
113+
public void ClearTerminalWritesEraseSavedLinesWhenConfigured()
114+
{
115+
WorkspaceService workspaceService = new(NullLoggerFactory.Instance);
116+
ConfigurationService configurationService = new();
117+
configurationService.CurrentSettings.IntegratedConsole.ForceClearScrollbackBuffer = true;
118+
EditorOperationsService editorOperationsService = new(
119+
psesHost: null,
120+
workspaceService,
121+
languageServer: null,
122+
configurationService);
123+
StringWriter output = new();
124+
TextWriter originalOutput = Console.Out;
125+
126+
try
127+
{
128+
Console.SetOut(output);
129+
editorOperationsService.ClearTerminal();
130+
}
131+
finally
132+
{
133+
Console.SetOut(originalOutput);
134+
}
135+
136+
Assert.Equal("\u001b[3J", output.ToString());
137+
}
138+
90139
private static ScriptFile CreateFileBuffer(WorkspaceService workspaceService, string fileName)
91140
{
92141
string filePath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString("N"), fileName);

0 commit comments

Comments
 (0)