Allow multiple expected responses at once

This commit is contained in:
tznind
2024-10-11 19:50:33 +01:00
parent bb0bdb0bc5
commit af2ea009c4

View File

@@ -5,8 +5,7 @@ namespace Terminal.Gui;
internal class AnsiResponseParser
{
private readonly StringBuilder held = new ();
private string? currentTerminator;
private Action<string>? currentResponse;
private readonly List<(string terminator, Action<string> response)> expectedResponses = new ();
private readonly List<Func<string, bool>> _ignorers = new ();
@@ -20,7 +19,7 @@ internal class AnsiResponseParser
// Current state of the parser
private ParserState currentState = ParserState.Normal;
private HashSet<string> _knownTerminators = new HashSet<string> ();
private readonly HashSet<string> _knownTerminators = new ();
/*
* ANSI Input Sequences
@@ -58,6 +57,7 @@ internal class AnsiResponseParser
_knownTerminators.Add ("K");
_knownTerminators.Add ("L");
_knownTerminators.Add ("M");
// No - N or O
_knownTerminators.Add ("P");
_knownTerminators.Add ("Q");
@@ -82,7 +82,6 @@ internal class AnsiResponseParser
_knownTerminators.Add ("h");
_knownTerminators.Add ("i");
_knownTerminators.Add ("l");
_knownTerminators.Add ("m");
_knownTerminators.Add ("n");
@@ -139,7 +138,7 @@ internal class AnsiResponseParser
break;
case ParserState.ExpectingBracket:
if (currentChar == '[' )
if (currentChar == '[')
{
// Detected '[' , transition to InResponse state
currentState = ParserState.InResponse;
@@ -194,15 +193,18 @@ internal class AnsiResponseParser
private string HandleHeldContent ()
{
var cur = held.ToString ();
// If we're expecting a specific terminator, check if the content matches
if (currentTerminator != null && cur.EndsWith (currentTerminator))
// Check for expected responses
(string terminator, Action<string> response) matchingResponse = expectedResponses.FirstOrDefault (r => cur.EndsWith (r.terminator));
if (matchingResponse.response != null)
{
DispatchResponse ();
DispatchResponse (matchingResponse.response);
expectedResponses.Remove (matchingResponse);
return string.Empty;
}
if (_knownTerminators.Any (cur.EndsWith) && cur.StartsWith (EscSeqUtils.CSI))
{
// Detected a response that we were not expecting
@@ -222,12 +224,10 @@ internal class AnsiResponseParser
return string.Empty;
}
private void DispatchResponse ()
private void DispatchResponse (Action<string> response)
{
// If it matches the expected response, invoke the callback and return nothing for output
currentResponse?.Invoke (held.ToString ());
currentResponse = null;
currentTerminator = null;
response?.Invoke (held.ToString ());
ResetState ();
}
@@ -235,9 +235,5 @@ internal class AnsiResponseParser
/// Registers a new expected ANSI response with a specific terminator and a callback for when the response is
/// completed.
/// </summary>
public void ExpectResponse (string terminator, Action<string> response)
{
currentTerminator = terminator;
currentResponse = response;
}
public void ExpectResponse (string terminator, Action<string> response) { expectedResponses.Add ((terminator, response)); }
}