gui-cs / Terminal.Gui

Cross Platform Terminal UI toolkit for .NET
MIT License
9.74k stars 694 forks source link

Leverage ANSI escape sequences as the mechanism for rich formatting w/in Terminal.Gui apps #1097

Open tig opened 3 years ago

tig commented 3 years ago

Right now we don't parse ANSI escape sequences anywhere. Thus any text input that includes them gets drawn funky.

Ideally, any control that renders text should honor ANSI sequences, e.g. changing the color of the text (but also ignoring things like cursor movement).

See: https://github.com/PowerShell/GraphicalTools/issues/131

This could be fixed in ocgv's input parsing to at least strip out the sequences. But what users really want is for formatting (like color) to be honored and displayed.

Related: https://github.com/migueldeicaza/gui.cs/issues/17

migueldeicaza commented 3 years ago

I do not think that we should be parsing escape sequences, that job belongs elsewhere.

If I understand this correctly, someone took the output of a terminal and fed that to some control? The job for that is something like a terminal emulator.

tig commented 3 years ago

Renamed the issue to make this customer centric.

As a developer, I want to richly format output w/in terminal.gui apps. For example, within a ListView, I want some elements to be red and some to be blue.

That is not supported today. We could implement a new model for formatting, or, we could simply leverage ANSI escape sequences.

migueldeicaza commented 3 years ago

Oh now I understand what you mean!

One thing that we could do is support attributed strings, I like how the Spectre console API has done thins.

It would allow us to do things like:

label.AttributedText = "Make sure you choose [red]stop[/red] or [green]go[/green]"

I am not married to the syntax, it could be XML-like, or other variations, but I think that those are easier to remember than escape sequences for folks to embed, which we would still need to parse.

migueldeicaza commented 3 years ago

This shows how it works:

https://spectresystems.github.io/spectre.console/appendix/colors

Update it uses a variation of a markup system called "bbcode" https://en.wikipedia.org/wiki/BBCode

KieranDevvs commented 2 years ago

I do not think that we should be parsing escape sequences, that job belongs elsewhere.

If I understand this correctly, someone took the output of a terminal and fed that to some control? The job for that is something like a terminal emulator.

Not necessarily. My use case is to print the process output within the terminal GUI for the user to see. This is not terminal emulation as there is no user input, its purely text formatting.

image

What it should look like: image

Seeing as this library runs and renders within the terminal, I would expect ANSI escape support.

I guess users can write their own interception logic to parse the escape sequences and convert them to this libraries formatting sequences, but: 1) It doesn't appear that the library supports anything like this right now. 2) As a library, I would hope that it makes developers lives easier rather than harder.

tznind commented 2 years ago

There are 2 seperate user stories being discussed here

Easily Add Color

The proposed solution for the story is to adopt the same markup as Spectre Console. It is a very simple markup which is easy to pick up, even for beginner programmers. Implementing it would be a big task but could start small (e.g. with Label). The feature should be 'opt in' so that it doesn't break backwards compatibility. Finally we would need methods like EscapeMarkup

Handling Process outputs that already contain ANSI

This is more complicated and would require writting a parser such as this one in teds-terminal. As highlighted by @migueldeicaza , this may not belong in Terminal.Gui itself and might be better as a standalone library.

Seeing as this library runs and renders within the terminal, I would expect ANSI escape support.

@KieranDevvs given we don't currently have an ANSI parser and are unlikely to soon. You might want to consider starting by stripping the ANSI codes? There is a post on Stack Overflow that contains some Regex that will do that (example is in Python but the regex patterns are the interesting bit).

Alternatively you could use the Regex to detect which bits of output have the color markups you are looking to parse and implement the highlighting using an approach similar to the syntax highlighting Scenario

https://github.com/gui-cs/Terminal.Gui/blob/d368215e0799b37c6e2b11d1770021cbe61bab2a/UICatalog/Scenarios/SyntaxHighlighting.cs#L153-L166

The pseudocode for that might be something like:

 // Read input from process
 // Foreach escape code
     // record location in string (after removing the escape sequence)
 // Set TextView.Text to the stripped string

Then override the ColorNormal method to set the appropriate color.