Comments (15)
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.
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.
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:
- We should not be too smart on the color mode by checking
ENV["COLORTERM"]
. There should be an API to encode a given color to either 256 or 24bit mode codes no matter what the host terminal is. For instance, ImageInTerminal provides a dispatching typeTermColor256
andTermColor24bit
https://github.com/JuliaImages/ImageInTerminal.jl/blob/4cd5bebf718196cb49a66b600b27d4023696ead4/src/colorant2ansi.jl#L36-L55 This also makes it possible to do unit test. - IIUC Windows with Julia < 1.6 doesn't support any kind of ANSI color (even with the fancy Windows Terminal), so there should be an additional check on
iswindows() && VERSION < v"1.6"
. https://github.com/JuliaImages/ImageInTerminal.jl/blob/4cd5bebf718196cb49a66b600b27d4023696ead4/src/ImageInTerminal.jl#L88-L97
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.
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.
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:
It should be very easy to crate the kind of visualizations you're after.
from colors.jl.
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.
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
with that in mind, I consider the adjoint
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.
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.
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.
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"
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
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.
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.
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.
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.
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.
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.
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.
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)
- RGB -> XTerm256 approximation? HOT 13
- move storage type conversion trait from ImageCore to Colors HOT 6
- Optimizing the types used for intermediate calculations HOT 5
- Source of the YIQ transform matrix HOT 1
- is `inv` on Colors well defined? HOT 4
- Fatal performance degradation due to precompilation or inference bugs HOT 8
- MethodError: no method matching coloralpha(::Type{RGB24}) HOT 1
- What should `default_brettel_neutral` be? HOT 1
- Ambiguity with AbstractTrees
- in the README, put a link on the home page HOT 2
- colorwheel generator HOT 1
- add colorwheel generator HOT 1
- Release v0.13? HOT 2
- Ambiguous show method for `Union{}[]` HOT 3
- colormap("<Color>", maxcount; w=<Int>, logscale=<Bool>) stackoverflows HOT 7
- oklab/oklch for CSS4 and cheap deltaE HOT 1
- BGR interpreted as RGB HOT 1
- Luv and LCHuv gives incorrect color values for low lightness cyan HOT 1
- Support for Preferences.jl HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from colors.jl.