Browse Source

Code Cleanup (resharper)

tznind 9 months ago
parent
commit
fbbda69ba0

+ 4 - 7
Terminal.Gui/ConsoleDrivers/AnsiEscapeSequenceRequest.cs

@@ -43,12 +43,9 @@ public class AnsiEscapeSequenceRequest
     public required string Terminator { get; init; }
 
     /// <summary>
-    /// Sends the <see cref="Request"/> to the raw output stream of the current <see cref="ConsoleDriver"/>.
-    /// Only call this method from the main UI thread. You should use <see cref="AnsiRequestScheduler"/> if
-    /// sending many requests.
+    ///     Sends the <see cref="Request"/> to the raw output stream of the current <see cref="ConsoleDriver"/>.
+    ///     Only call this method from the main UI thread. You should use <see cref="AnsiRequestScheduler"/> if
+    ///     sending many requests.
     /// </summary>
-    public void Send ()
-    {
-        Application.Driver?.RawWrite (Request);
-    }
+    public void Send () { Application.Driver?.RawWrite (Request); }
 }

+ 59 - 49
Terminal.Gui/ConsoleDrivers/AnsiResponseParser/AnsiRequestScheduler.cs

@@ -4,10 +4,10 @@ using System.Collections.Concurrent;
 namespace Terminal.Gui;
 
 /// <summary>
-/// Manages <see cref="AnsiEscapeSequenceRequest"/> made to an <see cref="IAnsiResponseParser"/>.
-/// Ensures there are not 2+ outstanding requests with the same terminator, throttles request sends
-/// to prevent console becoming unresponsive and handles evicting ignored requests (no reply from
-/// terminal).
+///     Manages <see cref="AnsiEscapeSequenceRequest"/> made to an <see cref="IAnsiResponseParser"/>.
+///     Ensures there are not 2+ outstanding requests with the same terminator, throttles request sends
+///     to prevent console becoming unresponsive and handles evicting ignored requests (no reply from
+///     terminal).
 /// </summary>
 internal class AnsiRequestScheduler
 {
@@ -17,53 +17,55 @@ internal class AnsiRequestScheduler
     private readonly List<Tuple<AnsiEscapeSequenceRequest, DateTime>> _requests = new ();
 
     /// <summary>
-    ///<para>
-    /// Dictionary where key is ansi request terminator and value is when we last sent a request for
-    /// this terminator. Combined with <see cref="_throttle"/> this prevents hammering the console
-    /// with too many requests in sequence which can cause console to freeze as there is no space for
-    /// regular screen drawing / mouse events etc to come in.
-    /// </para>
-    /// <para>
-    /// When user exceeds the throttle, new requests accumulate in <see cref="_requests"/> (i.e. remain
-    /// queued).
-    /// </para>
+    ///     <para>
+    ///         Dictionary where key is ansi request terminator and value is when we last sent a request for
+    ///         this terminator. Combined with <see cref="_throttle"/> this prevents hammering the console
+    ///         with too many requests in sequence which can cause console to freeze as there is no space for
+    ///         regular screen drawing / mouse events etc to come in.
+    ///     </para>
+    ///     <para>
+    ///         When user exceeds the throttle, new requests accumulate in <see cref="_requests"/> (i.e. remain
+    ///         queued).
+    ///     </para>
     /// </summary>
     private readonly ConcurrentDictionary<string, DateTime> _lastSend = new ();
 
     /// <summary>
-    /// Number of milliseconds after sending a request that we allow
-    /// another request to go out.
+    ///     Number of milliseconds after sending a request that we allow
+    ///     another request to go out.
     /// </summary>
-    private TimeSpan _throttle = TimeSpan.FromMilliseconds (100);
-    private TimeSpan _runScheduleThrottle = TimeSpan.FromMilliseconds (100);
+    private readonly TimeSpan _throttle = TimeSpan.FromMilliseconds (100);
+
+    private readonly TimeSpan _runScheduleThrottle = TimeSpan.FromMilliseconds (100);
 
     /// <summary>
-    /// If console has not responded to a request after this period of time, we assume that it is never going
-    /// to respond. Only affects when we try to send a new request with the same terminator - at which point
-    /// we tell the parser to stop expecting the old request and start expecting the new request.
+    ///     If console has not responded to a request after this period of time, we assume that it is never going
+    ///     to respond. Only affects when we try to send a new request with the same terminator - at which point
+    ///     we tell the parser to stop expecting the old request and start expecting the new request.
     /// </summary>
-    private TimeSpan _staleTimeout = TimeSpan.FromSeconds (5);
+    private readonly TimeSpan _staleTimeout = TimeSpan.FromSeconds (5);
 
+    private readonly DateTime _lastRun;
 
-    private DateTime _lastRun;
     public AnsiRequestScheduler (IAnsiResponseParser parser, Func<DateTime>? now = null)
     {
         _parser = parser;
         _now = now ?? (() => DateTime.Now);
         _lastRun = _now ();
     }
+
     /// <summary>
-    /// Sends the <paramref name="request"/> immediately or queues it if there is already
-    /// an outstanding request for the given <see cref="AnsiEscapeSequenceRequest.Terminator"/>.
+    ///     Sends the <paramref name="request"/> immediately or queues it if there is already
+    ///     an outstanding request for the given <see cref="AnsiEscapeSequenceRequest.Terminator"/>.
     /// </summary>
     /// <param name="request"></param>
     /// <returns><see langword="true"/> if request was sent immediately. <see langword="false"/> if it was queued.</returns>
     public bool SendOrSchedule (AnsiEscapeSequenceRequest request)
     {
-
-        if (CanSend (request, out var reason))
+        if (CanSend (request, out ReasonCannotSend reason))
         {
             Send (request);
+
             return true;
         }
 
@@ -75,26 +77,28 @@ internal class AnsiRequestScheduler
             if (CanSend (request, out _))
             {
                 Send (request);
+
                 return true;
             }
         }
 
-        _requests.Add (Tuple.Create (request, _now()));
+        _requests.Add (Tuple.Create (request, _now ()));
+
         return false;
     }
 
     /// <summary>
-    /// Looks to see if the last time we sent <paramref name="withTerminator"/>
-    /// is a long time ago. If so we assume that we will never get a response and
-    /// can proceed with a new request for this terminator (returning <see langword="true"/>).
+    ///     Looks to see if the last time we sent <paramref name="withTerminator"/>
+    ///     is a long time ago. If so we assume that we will never get a response and
+    ///     can proceed with a new request for this terminator (returning <see langword="true"/>).
     /// </summary>
     /// <param name="withTerminator"></param>
     /// <returns></returns>
     private bool EvictStaleRequests (string withTerminator)
     {
-        if (_lastSend.TryGetValue (withTerminator, out var dt))
+        if (_lastSend.TryGetValue (withTerminator, out DateTime dt))
         {
-            if (_now() - dt > _staleTimeout)
+            if (_now () - dt > _staleTimeout)
             {
                 _parser.StopExpecting (withTerminator, false);
 
@@ -105,23 +109,26 @@ internal class AnsiRequestScheduler
         return false;
     }
 
-
     /// <summary>
-    /// Identifies and runs any <see cref="_requests"/> that can be sent based on the
-    /// current outstanding requests of the parser.
+    ///     Identifies and runs any <see cref="_requests"/> that can be sent based on the
+    ///     current outstanding requests of the parser.
     /// </summary>
-    /// <param name="force">Repeated requests to run the schedule over short period of time will be ignored.
-    /// Pass <see langword="true"/> to override this behaviour and force evaluation of outstanding requests.</param>
-    /// <returns><see langword="true"/> if a request was found and run. <see langword="false"/>
-    /// if no outstanding requests or all have existing outstanding requests underway in parser.</returns>
+    /// <param name="force">
+    ///     Repeated requests to run the schedule over short period of time will be ignored.
+    ///     Pass <see langword="true"/> to override this behaviour and force evaluation of outstanding requests.
+    /// </param>
+    /// <returns>
+    ///     <see langword="true"/> if a request was found and run. <see langword="false"/>
+    ///     if no outstanding requests or all have existing outstanding requests underway in parser.
+    /// </returns>
     public bool RunSchedule (bool force = false)
     {
-        if (!force && _now() - _lastRun < _runScheduleThrottle)
+        if (!force && _now () - _lastRun < _runScheduleThrottle)
         {
             return false;
         }
 
-        var opportunity = _requests.FirstOrDefault (r => CanSend (r.Item1, out _));
+        Tuple<AnsiEscapeSequenceRequest, DateTime>? opportunity = _requests.FirstOrDefault (r => CanSend (r.Item1, out _));
 
         if (opportunity != null)
         {
@@ -136,7 +143,7 @@ internal class AnsiRequestScheduler
 
     private void Send (AnsiEscapeSequenceRequest r)
     {
-        _lastSend.AddOrUpdate (r.Terminator, _=>_now(), (_, _) => _now());
+        _lastSend.AddOrUpdate (r.Terminator, _ => _now (), (_, _) => _now ());
         _parser.ExpectResponse (r.Terminator, r.ResponseReceived, false);
         r.Send ();
     }
@@ -146,16 +153,19 @@ internal class AnsiRequestScheduler
         if (ShouldThrottle (r))
         {
             reason = ReasonCannotSend.TooManyRequests;
+
             return false;
         }
 
         if (_parser.IsExpecting (r.Terminator))
         {
             reason = ReasonCannotSend.OutstandingRequest;
+
             return false;
         }
 
-        reason = default;
+        reason = default (ReasonCannotSend);
+
         return true;
     }
 
@@ -163,7 +173,7 @@ internal class AnsiRequestScheduler
     {
         if (_lastSend.TryGetValue (r.Terminator, out DateTime value))
         {
-            return _now() - value < _throttle;
+            return _now () - value < _throttle;
         }
 
         return false;
@@ -173,18 +183,18 @@ internal class AnsiRequestScheduler
 internal enum ReasonCannotSend
 {
     /// <summary>
-    /// No reason given.
+    ///     No reason given.
     /// </summary>
     None = 0,
 
     /// <summary>
-    /// The parser is already waiting for a request to complete with the given terminator.
+    ///     The parser is already waiting for a request to complete with the given terminator.
     /// </summary>
     OutstandingRequest,
 
     /// <summary>
-    /// There have been too many requests sent recently, new requests will be put into
-    /// queue to prevent console becoming unresponsive.
+    ///     There have been too many requests sent recently, new requests will be put into
+    ///     queue to prevent console becoming unresponsive.
     /// </summary>
     TooManyRequests
 }

+ 2 - 5
Terminal.Gui/ConsoleDrivers/AnsiResponseParser/AnsiResponseExpectation.cs

@@ -3,8 +3,5 @@ namespace Terminal.Gui;
 
 internal record AnsiResponseExpectation (string Terminator, Action<IHeld> Response)
 {
-    public bool Matches (string cur)
-    {
-        return cur.EndsWith (Terminator);
-    }
-}
+    public bool Matches (string cur) { return cur.EndsWith (Terminator); }
+}

+ 72 - 83
Terminal.Gui/ConsoleDrivers/AnsiResponseParser/AnsiResponseParser.cs

@@ -2,25 +2,25 @@
 
 namespace Terminal.Gui;
 
-
 internal abstract class AnsiResponseParserBase : IAnsiResponseParser
 {
-    protected object lockExpectedResponses = new object();
+    protected object lockExpectedResponses = new ();
+
+    protected object lockState = new ();
 
-    protected object lockState = new object ();
     /// <summary>
-    /// Responses we are expecting to come in.
+    ///     Responses we are expecting to come in.
     /// </summary>
     protected readonly List<AnsiResponseExpectation> expectedResponses = new ();
 
     /// <summary>
-    /// Collection of responses that we <see cref="StopExpecting"/>.
+    ///     Collection of responses that we <see cref="StopExpecting"/>.
     /// </summary>
     protected readonly List<AnsiResponseExpectation> lateResponses = new ();
 
     /// <summary>
-    /// Responses that you want to look out for that will come in continuously e.g. mouse events.
-    /// Key is the terminator.
+    ///     Responses that you want to look out for that will come in continuously e.g. mouse events.
+    ///     Key is the terminator.
     /// </summary>
     protected readonly List<AnsiResponseExpectation> persistentExpectations = new ();
 
@@ -47,21 +47,20 @@ internal abstract class AnsiResponseParserBase : IAnsiResponseParser
     // These all are valid terminators on ansi responses,
     // see CSI in https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h3-Functions-using-CSI-_-ordered-by-the-final-character_s
     // No - N or O
-    protected readonly HashSet<char> _knownTerminators = new (new []
-    {
-        '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
-        // No - N or O
-        'P', 'Q', 'R', 'S', 'T', 'W', 'X', 'Z',
-        '^', '`', '~',
-        'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i',
-        'l', 'm', 'n',
-        'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'
-    });
-
-    protected AnsiResponseParserBase (IHeld heldContent)
-    {
-        this.heldContent = heldContent;
-    }
+    protected readonly HashSet<char> _knownTerminators = new (
+                                                              new []
+                                                              {
+                                                                  '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
+
+                                                                  // No - N or O
+                                                                  'P', 'Q', 'R', 'S', 'T', 'W', 'X', 'Z',
+                                                                  '^', '`', '~',
+                                                                  'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i',
+                                                                  'l', 'm', 'n',
+                                                                  'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'
+                                                              });
+
+    protected AnsiResponseParserBase (IHeld heldContent) { this.heldContent = heldContent; }
 
     protected void ResetState ()
     {
@@ -187,8 +186,8 @@ internal abstract class AnsiResponseParserBase : IAnsiResponseParser
             if (MatchResponse (
                                cur,
                                expectedResponses,
-                               invokeCallback: true,
-                               removeExpectation: true))
+                               true,
+                               true))
             {
                 return false;
             }
@@ -197,8 +196,8 @@ internal abstract class AnsiResponseParserBase : IAnsiResponseParser
             if (MatchResponse (
                                cur,
                                lateResponses,
-                               invokeCallback: false,
-                               removeExpectation: true))
+                               false,
+                               true))
             {
                 return false;
             }
@@ -207,8 +206,8 @@ internal abstract class AnsiResponseParserBase : IAnsiResponseParser
             if (MatchResponse (
                                cur,
                                persistentExpectations,
-                               invokeCallback: true,
-                               removeExpectation: false))
+                               true,
+                               false))
             {
                 return false;
             }
@@ -222,11 +221,12 @@ internal abstract class AnsiResponseParserBase : IAnsiResponseParser
             State = AnsiResponseParserState.Normal;
 
             // Maybe swallow anyway if user has custom delegate
-            var swallow =  ShouldSwallowUnexpectedResponse ();
+            bool swallow = ShouldSwallowUnexpectedResponse ();
 
             if (swallow)
             {
                 heldContent.ClearHeld ();
+
                 // Do not send back to input stream
                 return false;
             }
@@ -239,14 +239,15 @@ internal abstract class AnsiResponseParserBase : IAnsiResponseParser
     }
 
     /// <summary>
-    /// <para>
-    /// When overriden in a derived class, indicates whether the unexpected response
-    /// currently in <see cref="heldContent"/> should be released or swallowed.
-    /// Use this to enable default event for escape codes.
-    /// </para>
-    /// 
-    /// <remarks>Note this is only called for complete responses.
-    /// Based on <see cref="_knownTerminators"/></remarks>
+    ///     <para>
+    ///         When overriden in a derived class, indicates whether the unexpected response
+    ///         currently in <see cref="heldContent"/> should be released or swallowed.
+    ///         Use this to enable default event for escape codes.
+    ///     </para>
+    ///     <remarks>
+    ///         Note this is only called for complete responses.
+    ///         Based on <see cref="_knownTerminators"/>
+    ///     </remarks>
     /// </summary>
     /// <returns></returns>
     protected abstract bool ShouldSwallowUnexpectedResponse ();
@@ -254,7 +255,7 @@ internal abstract class AnsiResponseParserBase : IAnsiResponseParser
     private bool MatchResponse (string cur, List<AnsiResponseExpectation> collection, bool invokeCallback, bool removeExpectation)
     {
         // Check for expected responses
-        var matchingResponse = collection.FirstOrDefault (r => r.Matches (cur));
+        AnsiResponseExpectation? matchingResponse = collection.FirstOrDefault (r => r.Matches (cur));
 
         if (matchingResponse?.Response != null)
         {
@@ -262,6 +263,7 @@ internal abstract class AnsiResponseParserBase : IAnsiResponseParser
             {
                 matchingResponse.Response.Invoke (heldContent);
             }
+
             ResetState ();
 
             if (removeExpectation)
@@ -275,23 +277,23 @@ internal abstract class AnsiResponseParserBase : IAnsiResponseParser
         return false;
     }
 
-    /// <inheritdoc />
+    /// <inheritdoc/>
     public void ExpectResponse (string terminator, Action<string> response, bool persistent)
     {
         lock (lockExpectedResponses)
         {
             if (persistent)
             {
-                persistentExpectations.Add (new (terminator, (h) => response.Invoke (h.HeldToString ())));
+                persistentExpectations.Add (new (terminator, h => response.Invoke (h.HeldToString ())));
             }
             else
             {
-                expectedResponses.Add (new (terminator, (h) => response.Invoke (h.HeldToString ())));
+                expectedResponses.Add (new (terminator, h => response.Invoke (h.HeldToString ())));
             }
         }
     }
 
-    /// <inheritdoc />
+    /// <inheritdoc/>
     public bool IsExpecting (string terminator)
     {
         lock (lockExpectedResponses)
@@ -301,10 +303,9 @@ internal abstract class AnsiResponseParserBase : IAnsiResponseParser
         }
     }
 
-    /// <inheritdoc />
+    /// <inheritdoc/>
     public void StopExpecting (string terminator, bool persistent)
     {
-
         lock (lockExpectedResponses)
         {
             if (persistent)
@@ -313,9 +314,9 @@ internal abstract class AnsiResponseParserBase : IAnsiResponseParser
             }
             else
             {
-                var removed = expectedResponses.Where (r => r.Terminator == terminator).ToArray ();
+                AnsiResponseExpectation [] removed = expectedResponses.Where (r => r.Terminator == terminator).ToArray ();
 
-                foreach (var r in removed)
+                foreach (AnsiResponseExpectation r in removed)
                 {
                     expectedResponses.Remove (r);
                     lateResponses.Add (r);
@@ -329,14 +330,12 @@ internal class AnsiResponseParser<T> : AnsiResponseParserBase
 {
     public AnsiResponseParser () : base (new GenericHeld<T> ()) { }
 
-
     /// <inheritdoc cref="AnsiResponseParser.UnknownResponseHandler"/>
-    public Func<IEnumerable<Tuple<char, T>>, bool> UnexpectedResponseHandler { get; set; } = (_) => false;
-
+    public Func<IEnumerable<Tuple<char, T>>, bool> UnexpectedResponseHandler { get; set; } = _ => false;
 
     public IEnumerable<Tuple<char, T>> ProcessInput (params Tuple<char, T> [] input)
     {
-        List<Tuple<char, T>> output = new List<Tuple<char, T>> ();
+        List<Tuple<char, T>> output = new ();
 
         ProcessInputBase (
                           i => input [i].Item1,
@@ -352,64 +351,57 @@ internal class AnsiResponseParser<T> : AnsiResponseParserBase
         // Lock in case Release is called from different Thread from parse
         lock (lockState)
         {
-            foreach (Tuple<char, T> h in HeldToEnumerable())
+            foreach (Tuple<char, T> h in HeldToEnumerable ())
             {
                 yield return h;
             }
 
             ResetState ();
         }
-
     }
 
-    private IEnumerable<Tuple<char, T>> HeldToEnumerable ()
-    {
-        return (IEnumerable<Tuple<char, T>>)heldContent.HeldToObjects ();
-    }
+    private IEnumerable<Tuple<char, T>> HeldToEnumerable () { return (IEnumerable<Tuple<char, T>>)heldContent.HeldToObjects (); }
 
     /// <summary>
-    /// 'Overload' for specifying an expectation that requires the metadata as well as characters. Has
-    /// a unique name because otherwise most lamdas will give ambiguous overload errors.
+    ///     'Overload' for specifying an expectation that requires the metadata as well as characters. Has
+    ///     a unique name because otherwise most lamdas will give ambiguous overload errors.
     /// </summary>
     /// <param name="terminator"></param>
     /// <param name="response"></param>
     /// <param name="persistent"></param>
-    public void ExpectResponseT (string terminator, Action<IEnumerable<Tuple<char,T>>> response, bool persistent)
+    public void ExpectResponseT (string terminator, Action<IEnumerable<Tuple<char, T>>> response, bool persistent)
     {
         lock (lockExpectedResponses)
         {
             if (persistent)
             {
-                persistentExpectations.Add (new (terminator, (h) => response.Invoke (HeldToEnumerable ())));
+                persistentExpectations.Add (new (terminator, h => response.Invoke (HeldToEnumerable ())));
             }
             else
             {
-                expectedResponses.Add (new (terminator, (h) => response.Invoke (HeldToEnumerable ())));
+                expectedResponses.Add (new (terminator, h => response.Invoke (HeldToEnumerable ())));
             }
         }
     }
 
-    /// <inheritdoc />
-    protected override bool ShouldSwallowUnexpectedResponse ()
-    {
-        return UnexpectedResponseHandler.Invoke (HeldToEnumerable ());
-    }
+    /// <inheritdoc/>
+    protected override bool ShouldSwallowUnexpectedResponse () { return UnexpectedResponseHandler.Invoke (HeldToEnumerable ()); }
 }
 
 internal class AnsiResponseParser : AnsiResponseParserBase
 {
     /// <summary>
-    /// <para>
-    /// Delegate for handling unrecognized escape codes. Default behaviour
-    /// is to return <see langword="false"/> which simply releases the
-    /// characters back to input stream for downstream processing.
-    /// </para>
-    /// <para>
-    /// Implement a method to handle if you want and return <see langword="true"/> if you want the
-    /// keystrokes 'swallowed' (i.e. not returned to input stream).
-    /// </para>
+    ///     <para>
+    ///         Delegate for handling unrecognized escape codes. Default behaviour
+    ///         is to return <see langword="false"/> which simply releases the
+    ///         characters back to input stream for downstream processing.
+    ///     </para>
+    ///     <para>
+    ///         Implement a method to handle if you want and return <see langword="true"/> if you want the
+    ///         keystrokes 'swallowed' (i.e. not returned to input stream).
+    ///     </para>
     /// </summary>
-    public Func<string, bool> UnknownResponseHandler { get; set; } = (_) => false;
+    public Func<string, bool> UnknownResponseHandler { get; set; } = _ => false;
 
     public AnsiResponseParser () : base (new StringHeld ()) { }
 
@@ -430,16 +422,13 @@ internal class AnsiResponseParser : AnsiResponseParserBase
     {
         lock (lockState)
         {
-            var output = heldContent.HeldToString ();
+            string output = heldContent.HeldToString ();
             ResetState ();
 
             return output;
         }
     }
 
-    /// <inheritdoc />
-    protected override bool ShouldSwallowUnexpectedResponse ()
-    {
-        return UnknownResponseHandler.Invoke (heldContent.HeldToString ());
-    }
-}
+    /// <inheritdoc/>
+    protected override bool ShouldSwallowUnexpectedResponse () { return UnknownResponseHandler.Invoke (heldContent.HeldToString ()); }
+}

+ 8 - 5
Terminal.Gui/ConsoleDrivers/AnsiResponseParser/GenericHeld.cs

@@ -2,15 +2,18 @@
 namespace Terminal.Gui;
 
 /// <summary>
-/// Implementation of <see cref="IHeld"/> for <see cref="AnsiResponseParser{T}"/>
+///     Implementation of <see cref="IHeld"/> for <see cref="AnsiResponseParser{T}"/>
 /// </summary>
 /// <typeparam name="T"></typeparam>
 internal class GenericHeld<T> : IHeld
 {
     private readonly List<Tuple<char, T>> held = new ();
 
-    public void ClearHeld () => held.Clear ();
-    public string HeldToString () => new (held.Select (h => h.Item1).ToArray ());
-    public IEnumerable<object> HeldToObjects () => held;
-    public void AddToHeld (object o) => held.Add ((Tuple<char, T>)o);
+    public void ClearHeld () { held.Clear (); }
+
+    public string HeldToString () { return new (held.Select (h => h.Item1).ToArray ()); }
+
+    public IEnumerable<object> HeldToObjects () { return held; }
+
+    public void AddToHeld (object o) { held.Add ((Tuple<char, T>)o); }
 }

+ 26 - 20
Terminal.Gui/ConsoleDrivers/AnsiResponseParser/IAnsiResponseParser.cs

@@ -2,46 +2,52 @@
 namespace Terminal.Gui;
 
 /// <summary>
-/// When implemented in a derived class, allows watching an input stream of characters
-/// (i.e. console input) for ANSI response sequences.
+///     When implemented in a derived class, allows watching an input stream of characters
+///     (i.e. console input) for ANSI response sequences.
 /// </summary>
 public interface IAnsiResponseParser
 {
     /// <summary>
-    /// Current state of the parser based on what sequence of characters it has
-    /// read from the console input stream.
+    ///     Current state of the parser based on what sequence of characters it has
+    ///     read from the console input stream.
     /// </summary>
     AnsiResponseParserState State { get; }
 
     /// <summary>
-    /// Notifies the parser that you are expecting a response to come in
-    /// with the given <paramref name="terminator"/> (i.e. because you have
-    /// sent an ANSI request out).
+    ///     Notifies the parser that you are expecting a response to come in
+    ///     with the given <paramref name="terminator"/> (i.e. because you have
+    ///     sent an ANSI request out).
     /// </summary>
     /// <param name="terminator">The terminator you expect to see on response.</param>
-    /// <param name="persistent"><see langword="true"/> if you want this to persist permanently
-    /// and be raised for every event matching the <paramref name="terminator"/>.</param>
+    /// <param name="persistent">
+    ///     <see langword="true"/> if you want this to persist permanently
+    ///     and be raised for every event matching the <paramref name="terminator"/>.
+    /// </param>
     /// <param name="response">Callback to invoke when the response is seen in console input.</param>
-    /// <exception cref="ArgumentException">If trying to register a persistent request for a terminator
-    /// that already has one.
-    /// exists.</exception>
+    /// <exception cref="ArgumentException">
+    ///     If trying to register a persistent request for a terminator
+    ///     that already has one.
+    ///     exists.
+    /// </exception>
     void ExpectResponse (string terminator, Action<string> response, bool persistent);
 
     /// <summary>
-    /// Returns true if there is an existing expectation (i.e. we are waiting a response
-    /// from console) for the given <paramref name="terminator"/>.
+    ///     Returns true if there is an existing expectation (i.e. we are waiting a response
+    ///     from console) for the given <paramref name="terminator"/>.
     /// </summary>
     /// <param name="terminator"></param>
     /// <returns></returns>
     bool IsExpecting (string terminator);
 
     /// <summary>
-    /// Removes callback and expectation that we will get a response for the
-    /// given <pararef name="requestTerminator"/>. Use to give up on very old
-    /// requests e.g. if you want to send a different one with the same terminator.
+    ///     Removes callback and expectation that we will get a response for the
+    ///     given <pararef name="requestTerminator"/>. Use to give up on very old
+    ///     requests e.g. if you want to send a different one with the same terminator.
     /// </summary>
     /// <param name="requestTerminator"></param>
-    /// <param name="persistent"><see langword="true"/> if you want to remove a persistent
-    /// request listener.</param>
+    /// <param name="persistent">
+    ///     <see langword="true"/> if you want to remove a persistent
+    ///     request listener.
+    /// </param>
     void StopExpecting (string requestTerminator, bool persistent);
-}
+}

+ 7 - 7
Terminal.Gui/ConsoleDrivers/AnsiResponseParser/IHeld.cs

@@ -2,31 +2,31 @@
 namespace Terminal.Gui;
 
 /// <summary>
-/// Describes a sequence of chars (and optionally T metadata) accumulated
-/// by an <see cref="IAnsiResponseParser"/>
+///     Describes a sequence of chars (and optionally T metadata) accumulated
+///     by an <see cref="IAnsiResponseParser"/>
 /// </summary>
 internal interface IHeld
 {
     /// <summary>
-    /// Clears all held objects
+    ///     Clears all held objects
     /// </summary>
     void ClearHeld ();
 
     /// <summary>
-    /// Returns string representation of the held objects
+    ///     Returns string representation of the held objects
     /// </summary>
     /// <returns></returns>
     string HeldToString ();
 
     /// <summary>
-    /// Returns the collection objects directly e.g. <see langword="char"/>
-    /// or <see cref="Tuple"/> <see langword="char"/> + metadata T
+    ///     Returns the collection objects directly e.g. <see langword="char"/>
+    ///     or <see cref="Tuple"/> <see langword="char"/> + metadata T
     /// </summary>
     /// <returns></returns>
     IEnumerable<object> HeldToObjects ();
 
     /// <summary>
-    /// Adds the given object to the collection.
+    ///     Adds the given object to the collection.
     /// </summary>
     /// <param name="o"></param>
     void AddToHeld (object o);

+ 8 - 5
Terminal.Gui/ConsoleDrivers/AnsiResponseParser/StringHeld.cs

@@ -2,14 +2,17 @@
 namespace Terminal.Gui;
 
 /// <summary>
-/// Implementation of <see cref="IHeld"/> for <see cref="AnsiResponseParser"/>
+///     Implementation of <see cref="IHeld"/> for <see cref="AnsiResponseParser"/>
 /// </summary>
 internal class StringHeld : IHeld
 {
     private readonly StringBuilder held = new ();
 
-    public void ClearHeld () => held.Clear ();
-    public string HeldToString () => held.ToString ();
-    public IEnumerable<object> HeldToObjects () => held.ToString ().Select (c => (object)c);
-    public void AddToHeld (object o) => held.Append ((char)o);
+    public void ClearHeld () { held.Clear (); }
+
+    public string HeldToString () { return held.ToString (); }
+
+    public IEnumerable<object> HeldToObjects () { return held.ToString ().Select (c => (object)c); }
+
+    public void AddToHeld (object o) { held.Append ((char)o); }
 }