1515namespace 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