Skip to content

Commit 9be9cce

Browse files
committed
Add idle support for legacy readline
1 parent 3f96f56 commit 9be9cce

File tree

1 file changed

+41
-2
lines changed

1 file changed

+41
-2
lines changed

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

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,21 +15,27 @@
1515
namespace Microsoft.PowerShell.EditorServices.Services.PowerShell.Console
1616
{
1717
using System;
18+
using System.Threading.Tasks;
1819

1920
internal class LegacyReadLine : TerminalReadLine
2021
{
2122
private readonly PsesInternalHost _psesHost;
2223

2324
private readonly IPowerShellDebugContext _debugContext;
2425

26+
private readonly Task[] _readKeyTasks;
27+
2528
private Func<bool, ConsoleKeyInfo> _readKeyFunc;
2629

30+
private Action _onIdleAction;
31+
2732
public LegacyReadLine(
2833
PsesInternalHost psesHost,
2934
IPowerShellDebugContext debugContext)
3035
{
3136
_psesHost = psesHost;
3237
_debugContext = debugContext;
38+
_readKeyTasks = new Task[2];
3339
}
3440

3541
public override string ReadLine(CancellationToken cancellationToken)
@@ -383,6 +389,7 @@ public override string ReadLine(CancellationToken cancellationToken)
383389

384390
public override bool TryOverrideIdleHandler(Action<CancellationToken> idleHandler)
385391
{
392+
_onIdleAction = idleHandler;
386393
return true;
387394
}
388395

@@ -397,15 +404,47 @@ protected override ConsoleKeyInfo ReadKey(CancellationToken cancellationToken)
397404
cancellationToken.ThrowIfCancellationRequested();
398405
try
399406
{
400-
// intercept = false means we display the key in the console
401-
return _readKeyFunc(/* intercept */ false);
407+
return _onIdleAction is null
408+
? InvokeReadKeyFunc()
409+
: ReadKeyWithIdleSupport(cancellationToken);
402410
}
403411
finally
404412
{
405413
cancellationToken.ThrowIfCancellationRequested();
406414
}
407415
}
408416

417+
private ConsoleKeyInfo ReadKeyWithIdleSupport(CancellationToken cancellationToken)
418+
{
419+
// We run the readkey function on another thread so we can run an idle handler
420+
Task<ConsoleKeyInfo> readKeyTask = Task.Run(InvokeReadKeyFunc);
421+
422+
_readKeyTasks[0] = readKeyTask;
423+
_readKeyTasks[1] = Task.Delay(millisecondsDelay: 300, cancellationToken);
424+
425+
while (true)
426+
{
427+
switch (Task.WaitAny(_readKeyTasks, cancellationToken))
428+
{
429+
// ReadKey returned
430+
case 0:
431+
return readKeyTask.Result;
432+
433+
// The idle timed out
434+
case 1:
435+
_onIdleAction();
436+
_readKeyTasks[1] = Task.Delay(millisecondsDelay: 300, cancellationToken);
437+
continue;
438+
}
439+
}
440+
}
441+
442+
private ConsoleKeyInfo InvokeReadKeyFunc()
443+
{
444+
// intercept = false means we display the key in the console
445+
return _readKeyFunc(/* intercept */ false);
446+
}
447+
409448
private static int InsertInput(
410449
StringBuilder inputLine,
411450
int promptStartCol,

0 commit comments

Comments
 (0)