Skip to content

Commit 3fa3443

Browse files
Reset progress messages at end of REPL (#1719)
This seems to work. We needed to hold onto processed progress records, and then at the end of the REPL mark each as completed and re-write it (which uses the underlying host and effectively clears it).
1 parent c0ca6db commit 3fa3443

File tree

2 files changed

+45
-1
lines changed

2 files changed

+45
-1
lines changed

src/PowerShellEditorServices/Services/PowerShell/Host/EditorServicesConsolePSHostUserInterface.cs

+36-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// Licensed under the MIT License.
33

44
using System;
5+
using System.Collections.Concurrent;
56
using System.Collections.Generic;
67
using System.Collections.ObjectModel;
78
using System.Management.Automation;
@@ -22,6 +23,12 @@ internal class EditorServicesConsolePSHostUserInterface : PSHostUserInterface
2223

2324
private readonly PSHostUserInterface _consoleHostUI;
2425

26+
/// <summary>
27+
/// We use a ConcurrentDictionary because ConcurrentHashSet does not exist, hence the value
28+
/// is never actually used, and `WriteProgress` must be thread-safe.
29+
/// </summary>
30+
private readonly ConcurrentDictionary<(long, int), object> _currentProgressRecords = new();
31+
2532
public EditorServicesConsolePSHostUserInterface(
2633
ILoggerFactory loggerFactory,
2734
IReadLineProvider readLineProvider,
@@ -103,7 +110,35 @@ public override PSCredential PromptForCredential(string caption, string message,
103110

104111
public override void WriteLine(string value) => _underlyingHostUI.WriteLine(value);
105112

106-
public override void WriteProgress(long sourceId, ProgressRecord record) => _underlyingHostUI.WriteProgress(sourceId, record);
113+
public override void WriteProgress(long sourceId, ProgressRecord record)
114+
{
115+
if (record.RecordType == ProgressRecordType.Completed)
116+
{
117+
_ = _currentProgressRecords.TryRemove((sourceId, record.ActivityId), out _);
118+
}
119+
else
120+
{
121+
_ = _currentProgressRecords.TryAdd((sourceId, record.ActivityId), null);
122+
}
123+
_underlyingHostUI.WriteProgress(sourceId, record);
124+
}
125+
126+
public void ResetProgress()
127+
{
128+
// Mark all processed progress records as completed.
129+
foreach ((long sourceId, int activityId) in _currentProgressRecords.Keys)
130+
{
131+
// NOTE: This initializer checks that string is not null nor empty, so it must have
132+
// some text in it.
133+
ProgressRecord record = new(activityId, "0", "0")
134+
{
135+
RecordType = ProgressRecordType.Completed
136+
};
137+
_underlyingHostUI.WriteProgress(sourceId, record);
138+
_currentProgressRecords.Clear();
139+
}
140+
// TODO: Maybe send the OSC sequence to turn off progress indicator.
141+
}
107142

108143
public override void WriteVerboseLine(string message) => _underlyingHostUI.WriteVerboseLine(message);
109144

src/PowerShellEditorServices/Services/PowerShell/Host/PsesInternalHost.cs

+9
Original file line numberDiff line numberDiff line change
@@ -662,6 +662,15 @@ private void DoOneRepl(CancellationToken cancellationToken)
662662
UI.WriteErrorLine($"An error occurred while running the REPL loop:{Environment.NewLine}{e}");
663663
_logger.LogError(e, "An error occurred while running the REPL loop");
664664
}
665+
finally
666+
{
667+
// At the end of each REPL we need to complete all progress records so that the
668+
// progress indicator is cleared.
669+
if (UI is EditorServicesConsolePSHostUserInterface ui)
670+
{
671+
ui.ResetProgress();
672+
}
673+
}
665674
}
666675

667676
private string GetPrompt(CancellationToken cancellationToken)

0 commit comments

Comments
 (0)