-
Notifications
You must be signed in to change notification settings - Fork 689
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fixes #3767. Allowing any driver to request ANSI escape sequence with immediate response. #3768
base: v2_develop
Are you sure you want to change the base?
Fixes #3767. Allowing any driver to request ANSI escape sequence with immediate response. #3768
Conversation
To me his feels really brittle. Its what I was trying to explain in other thread. I can see its possible just dangerous:
I still think we should update the existing input processing loop(s) e.g. I think we could make a blocking public facing method even with that approach. Just need to think about it some more. Maybe we can use async and user can just call |
This is a minor problem because we are not requesting ANSI escape sequences all the time, like the one that are setting the colors when are writing to the console.
My bad, sorry. I created the
Done. Thanks.
You are right. Thanks for call my attention. I added a flag into the
But the immediate reply will still not prevail. When I found the current solution I never like how it's working because in some situations I wanted the response in the request method, to do some actions that depended on the response, but without success. I found it useless.
I think it won't block because I first stopped the mouse move reports which will decrease significantly the number of chars to read. You can use your approach as well because my PR doesn't break it, only changed from string to the class I created but still use the same behavior. The only disadvantage is that your approach only work with the If you want to test put these line in the var response1 = AnsiEscapeSequenceRequest.ExecuteAnsiRequest (EscSeqUtils.CSI_SendDeviceAttributes);
var response2 = AnsiEscapeSequenceRequest.ExecuteAnsiRequest (EscSeqUtils.CSI_RequestCursorPositionReport);
var request = EscSeqUtils.CSI_RequestCursorPositionReport;
AnsiEscapeSequenceResponse response3 = null;
request.ResponseReceived += (s, e) => response3 = e;
var response4 = AnsiEscapeSequenceRequest.ExecuteAnsiRequest (request);
Debug.Assert (response3 == response4); |
This work by @BDisp enables us to detect sixel support on demand
What is Value? I cant understand the comment. My example has 61...
Can we also please have a helper property called |
I can confirm that this works and have added it into a new branch of the main sixel branch I am working on. See tznind#169 |
Value is the number that appear at the beginning of the reply after the CSI. See https://terminalguide.namepad.de/seq/csi_st-18/ and https://terminalguide.namepad.de/seq/csi_st-15/. Both requests use the 't' as terminator and the reply also returns 't' as terminator. What distinguish each other are the Value. The prior returns 8 and the last returns 5.
It's not enough to check the error with |
Yes please either add I started with this ugliness: if (string.IsNullOrWhiteSpace (darResponse.Error) && !string.IsNullOrWhiteSpace (darResponse.Response))
{
// it worked
}
|
@tig please can you take a look at this when you get the chance? Currently I am working on 2 sixel branches (one with this merged in). If its going in right direction I will just collapse and work on only 1 branch. |
Cool thanks, although I meant for tryparse as an example of the pattern only. It should probably still be same name e.g. TryExecuteAnsi... |
Ops I misunderstood. Changed on 31dbae7. |
Got a strange error in
See error
|
I can't reproduce the error as you said but I can reproduce it by running the |
I have a fix to this. But I need your opinion, if the request terminator is empty and the response is successfully, it's need to write to the error property "Terminator request is empty." or ignore it? If I write to the error, the response will not return |
Terminator request is mandatory to stopping read when it's found. So, it'll return false and the user will check what he does wrong. |
I think maybe we are terminating our ASCII processing on the 'key down' of the response terminator and the 'key up' is still coming through from driver? Could be an oddity of the console, this is the 2022 community edition visual studio out of the box console. |
Do you are using the updated branch after the latest fixes? When I said the crash is due the lack of terminator, I referred the one that is on the request and not in the response.
What causes this exception is because the key read is a 'c' that the
It's a possibility.
It's a nor normal behavior of the |
This code is already quite complicated and coupled to the specific drivers e.g. switch statement on Driver Type. Maybe we can reuse the existing message pumps that the drivers are already running and move the new code to a Parser pattern? Each driver would then have its own pump but reuse something like this. We wouldn't stop the pumps we would just add an extra 'filtering' stage to the existing input processing pipeline? I can have a go at this unless you can see reasons why this won't work and better decouple concerns? /// <summary>
/// Driver agnostic parser that you can stream console output to as part of normal
/// input processing. Spots ansi escape sequenes as they pass through stream and
/// matches them to the current outstanding <see cref="AnsiEscapeSequenceRequest"/>
/// </summary>
public class AnsiRequestParser ()
{
[CanBeNull]
private AnsiEscapeSequenceRequest currentRequest;
StringBuilder currentResponse = new StringBuilder ();
private bool areInEscapeSequence = false;
Queue<AnsiEscapeSequenceRequest> outstandingRequests = new Queue<AnsiEscapeSequenceRequest> ();
/// <summary>
/// Sends the given <paramref name="request"/> to the terminal or queues
/// it if there is already an outstanding request.
/// </summary>
/// <param name="request"></param>
public void QueueRequest (AnsiEscapeSequenceRequest request)
{
if (currentRequest == null)
{
SendRequest (request);
}
else
{
outstandingRequests.Enqueue (request);
}
}
private void SendRequest (AnsiEscapeSequenceRequest request)
{
currentRequest = request;
Console.Write ("... the request");
}
/// <summary>
/// Takes the given key read from console input stream. Returns true
/// if input should be considered 'handled' (is part of an ongoing
/// ANSI response code)
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public bool Process (char key)
{
// Existing code in this PR for parsing
// If completes request
currentRequest = null;
// send next from queue
return true;
// We have not read an Esc so we are not in a response
return false;
}
} |
Have tried and get no difference in behaviour. I think you are right and that it is the mixing of Console
Not sure... this is why I was wanting to go for the parser approach as it is much easier to test. And each driver can concern itself with its own message pump oddities. I guess an alternative would be to try and add Read and Write methods to |
Terminal.Gui/ConsoleDrivers/AnsiEscapeSequence/AnsiEscapeSequenceRequest.cs
Outdated
Show resolved
Hide resolved
9366998
to
803dbef
Compare
Get an issue running this code with the new Windows Terminal Preview (the one that has sixel support). Seems the response you read is just full of I have tested in both 1.22.2702.0 and 1.22.2362.0 |
In which driver? I think I know why with my last refactor. |
Thanks for reporting this. This is due to iterations not handling the keys while it's still processing others. I'll see what I can do. Does this is happen with your PR? |
No, I wrote ansiparser class specifically to hold onto all keys passed to it and return anything that isn't the response back to input stream processing. It uses the native T type of each driver e.g. ConsoleKey so there is no stop or explicit read seperate from the normal loop in the driver. Maybe you can take just the ansiparser class into this pr?. |
Can you please submit a PR to my branch with the ansiparser? Maybe you will handle better adapting the code. Thanks. |
I'm realize now that the Ctrl+Shift+Home/End/PgUp/PgDown only is captured on key-up on |
Windows Terminal was using these keys internally and unbounded them solved the issue. |
With this branch I still getting exit (Esc) when trying to get response with the default terminal in Visual Studio. Think we need to pay attention to older terminals here - if we try to send a request and an Esc goes through instead and exits users app then that is a pretty bad bug. Cases we need to ensure work:
|
@tznind I would like to reproduce this but this is the below what I get using the VSDebugConsole.exe. |
Wow that totally self destructed huh! 😱 Can you try my branch out of interest, also because you have it bomb immediately on enter scenario - while in contrast when i tested using your branch it only bombed on click the DAR |
@tznind, the missing letters when typing in TextView were not due to missed or unexecuted iterations, but rather due to some wrong decoding of some raw escape sequences. You can try typing again while the requests are running and you will see that there are practically no missing letters on all drivers. If there are, it is still due to some bug, which is sometimes very hard to detect. |
But this situation happen on only run the UICatalog without run the ansi escape sequence scenario. I also tried with your branch and the same situation is happening. But I think this is normal if we aren't using WT. |
Wait as soon as you launch UICatalog the terminal does this (fills with escape codes)? Which branches does it happen for you on?
|
Yes in all V2 branches that are run without WT. |
@tznind, I don't what happened but today I tried again to run against the vs console and now it work well, damn. I don't have your issue now, maybe was some bug that I already fixed. |
Fixes
Proposed Changes/Todos
Pull Request checklist:
CTRL-K-D
to automatically reformat your files before committing.dotnet test
before commit///
style comments)