Browse Source

Give AnsiResponseParser a chance to release its content each iteration if it has been some time since we saw Esc

tznind 10 months ago
parent
commit
dbfdffba7a

+ 18 - 1
Terminal.Gui/ConsoleDrivers/AnsiResponseParser.cs

@@ -218,12 +218,23 @@ namespace Terminal.Gui;
             return output;
         }
 
+        public IEnumerable<Tuple<char, T>> Release ()
+        {
+            foreach (var h in held)
+            {
+                yield return h;
+            }
+            ResetState ();
+        }
+
         public override void ClearHeld () => held.Clear ();
 
         protected override string HeldToString () => new string (held.Select (h => h.Item1).ToArray ());
 
         protected override void AddToHeld (char c) => held.Add (new Tuple<char, T> (c, default!));
-    }
+
+
+}
 
     internal class AnsiResponseParser : AnsiResponseParserBase
     {
@@ -235,7 +246,13 @@ namespace Terminal.Gui;
             ProcessInputBase (i => input [i], c => output.Append (c), input.Length);
             return output.ToString ();
         }
+        public string Release ()
+        {
+            var output = held.ToString ();
+            ResetState ();
 
+            return output;
+        }
         public override void ClearHeld () => held.Clear ();
 
         protected override string HeldToString () => held.ToString ();

+ 28 - 0
Terminal.Gui/ConsoleDrivers/WindowsDriver.cs

@@ -1457,6 +1457,11 @@ internal class WindowsDriver : ConsoleDriver
     }
 
     private bool firstTime = true;
+
+    /// <summary>
+    /// How long after Esc has been pressed before we give up on getting an Ansi escape sequence
+    /// </summary>
+    private TimeSpan _escTimeout = TimeSpan.FromMilliseconds (50);
     public AnsiResponseParser<WindowsConsole.InputRecord> Parser { get; set; } = new ();
 
     internal void ProcessInput (WindowsConsole.InputRecord inputEvent)
@@ -1566,6 +1571,11 @@ internal class WindowsDriver : ConsoleDriver
 
         // TODO: keydown/keyup badness
 
+        foreach (var i in ShouldRelease ())
+        {
+            yield return i;
+        }
+
         foreach (Tuple<char, WindowsConsole.InputRecord> output in
                  Parser.ProcessInput (Tuple.Create(inputEvent.KeyEvent.UnicodeChar,inputEvent)))
         {
@@ -1573,6 +1583,19 @@ internal class WindowsDriver : ConsoleDriver
         }
     }
 
+    public IEnumerable<WindowsConsole.InputRecord> ShouldRelease ()
+    {
+
+        if (Parser.State == ParserState.ExpectingBracket &&
+            DateTime.Now - Parser.StateChangedAt > _escTimeout)
+        {
+            foreach (Tuple<char, WindowsConsole.InputRecord> output in Parser.Release ())
+            {
+                yield return output.Item2;
+            }
+        }
+    }
+
 #if HACK_CHECK_WINCHANGED
     private void ChangeWin (object s, SizeChangedEventArgs e)
     {
@@ -2276,6 +2299,11 @@ internal class WindowsMainLoop : IMainLoopDriver
 
     void IMainLoopDriver.Iteration ()
     {
+        foreach(var i in ((WindowsDriver)_consoleDriver).ShouldRelease())
+        {
+            ((WindowsDriver)_consoleDriver).ProcessInput (i);
+        }
+
         while (_resultQueue.Count > 0)
         {
             WindowsConsole.InputRecord [] inputRecords = _resultQueue.Dequeue ();

+ 0 - 2
UnitTests/ConsoleDrivers/AnsiResponseParserTests.cs

@@ -1,7 +1,5 @@
 using System.Diagnostics;
 using System.Text;
-using Microsoft.VisualStudio.TestPlatform.Utilities;
-using Terminal.Gui;
 using Xunit.Abstractions;
 
 namespace UnitTests.ConsoleDrivers;