Coder Social home page Coder Social logo

'Render' colours in REPL about colors.jl HOT 15 OPEN

tecosaur avatar tecosaur commented on June 16, 2024 3
'Render' colours in REPL

from colors.jl.

Comments (15)

kimikage avatar kimikage commented on June 16, 2024 2

I think this is a good idea, but the similar feature is available in ImageInTerminal.jl.

For example, if you want to copy and paste the output into a GitHub issue, the current "plain" text is more beneficial.
I think there needs to be an easy way for users to specify which output they want, and loading or not loading the package is one of the easiest ways.

Also, the conversion to ANSI 256 (240) colors will be supported in Colors v0.13. (cf. issue #473)

cc: @johnnychen94

from colors.jl.

kimikage avatar kimikage commented on June 16, 2024 1

BTW, @tecosaur, where did you learn the usage of color("#"*hex(c, :rrggbb))? It was deprecated 6 years ago and is going to be removed in v0.13 (cf. PR #484). I'm worried that there might be some obsolete documentation left.

from colors.jl.

johnnychen94 avatar johnnychen94 commented on June 16, 2024 1

I like the new ANSI color + value view. ImageInTerminal and perhaps UnicodePlots (cc: @t-bltg) could also benefit from this proposal if the color encoder is implemented here (or maybe https://github.com/KristofferC/Crayons.jl).

There are two things to note from my ImageInTerminal maintenance experience:

The show method, however, should perhaps live in ImageInTerminal because Colors.jl focus on pixel/colorant level, also because the sixel encoding only makes sense at the array level. If we want to have show method here then we need to provide a way to allow IIT to override the behavior using Sixel encoding.

The ANSI color + value view only makes sense if we're looking at a very small image.

from colors.jl.

kimikage avatar kimikage commented on June 16, 2024 1

IMO, it would be a good idea to submit a PR to add a swatch using ANSI escape codes for "single" Color first.

In that PR, you could design the logic and API to determine whether or not to add a swatch, and whether it uses 24-bit colors or 256 colors.
ImageInTerminal.jl (indirectly) depends on Colors.jl, so ImageInTerminal.jl should be able to reuse that API. In other words, an API that is compatible with the current API of ImageInTerminal.jl would be preferable.
(Also, supporting the environment variables defined by Crayons.jl may improve the usability.)

from colors.jl.

FedeClaudi avatar FedeClaudi commented on June 16, 2024 1

You could use Term to build a widget to visualize colors too.

See: https://fedeclaudi.github.io/Term.jl/stable/basics/colors/

Playing around with things I was able to make this:
image

It should be very easy to crate the kind of visualizations you're after.

from colors.jl.

tecosaur avatar tecosaur commented on June 16, 2024

I think this is a good idea, but the similar feature is available in ImageInTerminal.jl.

Ah, I hadn't heard of that. Looking at it, it seems like a fancier version of what I've done here, particularly with the Sixel support.

Given how easy it is to add this or something like it though, I personally feel like it would be nice to have some basic color preview support when just using Colors.jl. ImageInTerminal.jl would then be handy if you say wanted to see images with Sixels, which does seem outside what you'd want to have in Colors.jl.

if you want to copy and paste the output into a GitHub issue, the current "plain" text is more beneficial.

Mmm, though for copy-pasting the single-colour versions are basically the same - there are just 3 extra spaces at the start, so for that representation at least I see no downsides. It is also beneficial when seeing a range of colours, though much less compact of course.

image

As no information is lost here, I'd advocate for this being part of Colors.jl, if nothing else.

I think there needs to be an easy way for users to specify which output they want

I've actually just had an idea, inspired by how vectors are displayed. The above color-on-each-line-with-info is analogous to
image
with that in mind, I consider the adjoint
image
it's a rather useless way of representing colours AFAICT (usually only 2-3 are shown), so perhaps when showing them "sideways" we could squash the colour info out for the more compact view? I feel like it could be nice to trivially be able to view both representations.
image

All one needs to make it work like this is change the type signature in the last two show functions, e.g. to show(io::IO, ::MIME"text/plain", cs::Adjoint{<:Colorant, <:Vector{<:Colorant}}).

Also, the conversion to ANSI 256 (240) colors will be supported in Colors v0.13

Ah, nice. When I implemented this in a package of my own I just copied tmux's color conversion, and that's worked well for me so I think :)

where did you learn the usage of color("#"*hex(c, :rrggbb))

Well, I want r, g, and b values for any colour and convert(RGB, colorant"hsl(120, 100%, 25%)") didn't work so I tried ?hex noticed the hex(..., :rrbbgg) example, tried it, and so wrapped it with color("#"* ... ). I assume there's a better way to do it?

from colors.jl.

kimikage avatar kimikage commented on June 16, 2024

I personally feel like it would be nice to have some basic color preview support when just using Colors.jl

I agree with you. So, I think the key issue is how to avoid annoying troubles.

As you said, the issue of loss of information (i.e. copy-pasting issue) will not be a trouble as long as the color swatches and text are written together. In the case of "sideways", why not also add one line to display both?

The main trouble here is unintentional output of ANSI escape codes in environments that do not support color display.

At least, we would need to follow the :color IO property (get(io, :color, false)). However, even if color display is partially supported, there is no reliable way to determine whether 256 or 24-bit colors is supported.
Referencing environment variables, as in your example, is one way to do it. Even with that way, the evaluation of the variables should be done at "run-time".

Another trouble is compatibility with ImageInTerminal.jl (e.g. the redefinition of methods), but this can be solved with additional modifications on the ImageInTerminal.jl side.

, and so wrapped it with color("#"* ... ). I assume there's a better way to do it?

color("string") should be replaced with parse(Colorant, "string"). However, there is no need to convert a color via a string for this feature. You can just convert the color to RGB (RGB24).

from colors.jl.

tecosaur avatar tecosaur commented on June 16, 2024

This doesn't do anything for 256-colors, but other than that I think I've come up with a model that should resolve all the other concerns.

When get(io, :color, false) == true and ENV["COLORTERM"] == "truecolor"

image

I feel like this strikes a nice balance between being compact/swatchy and informative/copy-pastable. This may not improve the experience for people on terminals that don't set COLORTERM appropriately, or only support 256-color, but their experience is no worse, just not improved — so I'd consider this a "win" overall.

Otherwise

image

As far as I can tell, this is identical to the current behaviour.

Code

colorcode(rgb::Vector{<:Integer}, background=false) =
    string("\e[", if background "48" else "38" end,
           ";2;", rgb[1], ";", rgb[2], ";", rgb[3], "m")

colorcode(c::Union{RGB, RGB24}, background=false) =
    colorcode(reinterpret.([red(c), green(c), blue(c)]), background)

colorcode(c::RGB{Float64}, background=false) =
    colorcode(round.(Int, 255 .* [red(c), green(c), blue(c)]), background)

colorcode(c::Colorant, background=false) =
    colorcode(convert(RGB24, c), background)

import Base.show
function show(io::IO, ::MIME"text/plain", c::Colorant)
    if get(io, :color, false) && ENV["COLORTERM"] == "truecolor"
        print(colorcode(c, true), "  \e[0m ")
    end
    show(io, c)
end
using LinearAlgebra # for the Adjoint type
function show(io::IO, ::MIME"text/plain", cs::Adjoint{<:Colorant, <:Vector{<:Colorant}})
    summary(io, cs)
    print(":\n")
    if get(io, :color, false) && ENV["COLORTERM"] == "truecolor"
        print(" ", join(colorcode.(cs,true), if length(cs) <= 40 "  " else " " end),
              if length(cs) <= 40 "  \e[0m" else " \e[0m" end)
    else
        Base.print_array(IOContext(io, :SHOWN_SET => cs), cs)
    end
end
function show(io::IO, ::MIME"text/plain", cs::Matrix{<:Colorant})
    summary(io, cs)
    print(":\n")
    if get(io, :color, false) && ENV["COLORTERM"] == "truecolor"
        for csrow in eachrow(cs)
            println(" ", join(colorcode.(csrow,true),
                              if size(cs,2) <= 40 "  " else " " end),
                    if size(cs,2) <= 40 "  \e[0m" else " \e[0m" end)
        end
    else
        Base.print_array(IOContext(io, :SHOWN_SET => cs), cs)
    end
end

from colors.jl.

kimikage avatar kimikage commented on June 16, 2024

I don't have a clear opinion on whether show for text/plain should be implemented in Colors.jl. However, I think it is too tricky to specialize show for Adjoint anyway.
(The implementation issues of the colorcode and ENV["COLORTERM"] above should be reviewed in the PR stage.)

from colors.jl.

tecosaur avatar tecosaur commented on June 16, 2024

Sixel stuff should definitely be left to ImageInTerminal, and I think it would be nice if Colours.jl had some swatch-ing. Beyond that, I have no strong opinions. Let me know what you'd like me to put in a PR, and I'll make one.

from colors.jl.

kimikage avatar kimikage commented on June 16, 2024

Perhaps it might be useful to define a function like:

print_swatch([io,] color::Union{Color, AbstractArray{<:Color}}; width=2, mode=:auto)

to replace:

print(colorcode(c, true), " \e[0m ")

from colors.jl.

kimikage avatar kimikage commented on June 16, 2024

Currently, there are already multiple means of displaying colors on the terminal.
And with the addition of StyledStrings to stdlib, the terminal will become even more colorful in the future.

In view of this, wouldn't it be a hindrance to customize the show in Colors.jl?
As mentioned above, there is no problem with adding Colors.jl "original" APIs such as print_swatch.

from colors.jl.

tecosaur avatar tecosaur commented on June 16, 2024

As I see it, it would be nice for Colors.jl to do something a bit nicer OOTB, and with StyledStrings it is possible to do so while resolving quite a few of the concerns from earlier. For instance,

At least, we would need to follow the :color IO property (get(io, :color, false)). However, even if color display is partially supported, there is no reliable way to determine whether 256 or 24-bit colors is supported.

is now fully handled by StyledStrings + the new terminfo handling.

This doesn't preclude other packages from doing even fancier colour rendering at all, they can implement custom display methods and engage in method overwriting. What we do get though is a prettier OOTB experience 🙂

from colors.jl.

kimikage avatar kimikage commented on June 16, 2024

they can implement custom display methods and engage in method overwriting.

Generally they cannot. That is my concern.
One possibility would be to use Preferences.jl. (cf. #535)

from colors.jl.

tecosaur avatar tecosaur commented on June 16, 2024

they can implement custom display methods and engage in method overwriting.

Generally they cannot. That is my concern.

Hmmm? You absolutely can, just not during precompilation.

One possibility would be to use Preferences.jl

If there's really a need to be able to turn it off, then that does seem like a reasonable approach 👍.

from colors.jl.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.