piotrmurach / pastel

Terminal output styling with intuitive and clean API.
https://ttytoolkit.org
MIT License
640 stars 23 forks source link

Support for other colors like brown? #27

Closed brandondrew closed 1 day ago

brandondrew commented 6 days ago

Describe the problem

I would like to display other colors that are not available in Pastel, but which my terminal supports, such as brown. I can get this to work in pry with puts "\033[38;2;150;75;0mfoo", but it doesn't seem to be possible to replicate this with Pastel. At least my attempts to do so have failed.

For example, pastel.undecorate("\033[38;2;150;75;0mfoo") returns

=> [{:text=>"38;2;150;75;0mfoo"}]

The same is true if I change \033 to \e.

There doesn't seem to be a way to define new colors. I couldn't find anything in the README, and both of these experiments failed with a Pastel::InvalidAttributeNameError:

pastel.decorate("brown", "\e[38;2;150;75;0m")
pastel.alias_color(:brown, "\e[38;2;150;75;0m")

How would the new feature work?

I think it would be very useful if Pastel provided a way to define new colors, such as

pastel.define(:brown, "\e[38;2;150;75;0m")

It might also be valuable to have the ability to detect whether the current terminal is capabale of displaying colors beyond those that Pastel normally provides. That might be done by something like this:

pastel.extended?

Drawbacks

Can you see any potential drawbacks?

The potential drawbacks are very small, and the pay-off seems very significant. Pastel already handles the huge complexity of making terminal color escape sequences easy to manage from Ruby. Adding the ability to go beyond 16 colors (while still allowing it to be used in minimalistic terminals that can't support more than 16 colors) would greatly extend its versatility.

To bring the drawbacks almost to zero, every definition could possibly have a secondary "fallback" definition to use in cases where the main definition can't be used:

pastel.define(:brown, "\e[38;2;150;75;0m", fallback: [:red, :dark, :bold])

This would allow those using Pastel to avoid having to constantly use pastel.extended? and manually type code to provide an alternative if it's false.

piotrmurach commented 1 day ago

Hi Brandon, 👋

Thanks for taking an interest in pastel.

The pastel works with 16 ANSI colours. It's complete in this sense. It doesn't miss any colours.

Do I plan to extend pastel to work with 256 ANSI colours palette or the Truecolor? That's always been a plan. Why it hasn't happened yet? It's not because I'm unaware of terminal capabilities. It's also not because I don't know what the API could look like. The answer is more mundane, it wasn't critical for the development of other tty components and requires investment of time which is a scarce commodity.

The addition of richer colour palettes to pastel would open up more possibilities for other gems including tty components. To give you a glimpse into what I'm thinking, the API wouldn't change that much. It definitely wouldn't involve knowing anything, and forbid, specifying any ANSI codes manually. That wouldn't be a user-friendly API. Fundamentally, the basic colours would be used the same, for example, pastel.red but produce different ANSI based on the terminal colour support(this could be overridden). Collorarly, any new colour names like pastel.crimson or pastel.brown would automatically display the correct ANSI codes. It's not a trivial change though.

As for when I cannot promise anything. But this is a higher priority for me nowadays due to slideck and the many benefits it would bring.

brandondrew commented 1 day ago

Okay, that's very unfortunate but of course I understand time being short.

Also, thanks for reminding me of Slideck. I had forgotten about it (but since I had it starred I was obviously aware of it at some point in the past 😅).