Hi!
I want to ask to critique my idea of colorprinting. Maybe it's too complicated, maybe solution already exists in Julia, may be it's ok, but can be done better.
Sometimes we need colorful output, but current printing facilities like printstyled
or Crayons.jl are too low level, verbose and inflexible. By inflexible, I mean that it is very hard to change colorscheme for example, because everything is hard coded. And low level means, that by looking at code it's hard to understand how final output will look like.
Make a macro, which accepts following arguments: io
, colorscheme
and string
where string
encodes colors inside itself. Example:
@colorprint io colorscheme "{The quick brown fox}:fox jumps over the lazy dog:dog"
Here colorscheme is a Dict
of the form Dict(:fox => :brown, :dog => :yellow)
When this macro parse this string, it do one of two things:
{...}:<color>
group, then color applies to all groupword:<color>
then color applies only to the word.So, this string will turn into this:
printstyled(io, "The quick brown fox", color = Dict[:fox])
printstyled(io, " jumps over the lazy ")
printstyled(io, "dog", color = Dict[:dog])
With this approach, we can get
:fox
wouldn't make it less readable)Dict
with colors to another to get new output.Of course, it is more limited then printstyled
or Crayons, but if it covers more than 50% usecases I am fine with that.
And of course there is problem of bold
etc, but it can be easily solved by changingDict
to Dict(:fox => (; color = :brown, bold = true, underline = false))
and splatting in printstyled
.
That sounds pretty good to me. I have two suggestions
@color_str
macro which returns and object that when print
ed does what you'd expect.If you develop this I'm likely to use it. It never ceases to amaze me how hard it is to print things nicely. My own most recent attempt (which I consider a failure, too hard to use) was ShowCases.jl
To expand on my comment about @color_str
, it makes a better API to have "shallow" macros, though in this case I'm not entirely sure it's possible to do it that way and get performance as good as a macro that converts directly to printstyled
calls.
I like the idea of @color_str
macro. But since I still want to support colorschemes, resulting interface looks like
print(colorscheme, color"{The quick brown fox}:fox jumps over the lazy dog:dog")
Of course, I can make default dict with relation :black => :black
, so one can use default color's naming and get colorized output.
As for the first question, I do not know any standard syntax (that was part of the question, actually). It is possible to use colors in markdown, but it looks long and verbose. I've used similar syntax in few packages already (e.g. https://github.com/JuliaLogging/MiniLoggers.jl), so it looks reasonable enough for me, but I am biased.
Yeah, it looks reasonable to me to. Maybe there isn't a standard alternative, I don't know
Personally I think it would be clearer if the color came first.
color"fox:{The quick brown fox} jumps over the lazy dog:dog"?
Ha, dog
is a bad example :-)
Or color"{blue:this text is blue} this is default"
Ah, I see.
Yeah, it's like active voice.
"apply action" to "something", instead of "something" "acted upon"
Yeah, this is good.
I think parsing should be more or less the same.
I don't really like the color inside of the brackets because blue:this text is blue
looks like it only applies to this
You could maybe go a simplified latex route {\blue this text is blue} this text is default
I just feel like I have seen the syntax I suggested somewhere.
And something like {\blue\bold this text is blue and bold} this text is default
, is it readable?
Hm, and I immediately run into the problem
f(s) = s
macro foo_str(s)
f(s)
end
x = 1
julia> foo"_$x_"
"_\$x_"
Is it possible to interpolate string, which is used in macro?
Otherwise this idea lose 50% of it's usefulness.
You have to implement the interpolation yourself.
Any references how to do it? I do not know where to start.
Ah, ok, dump
it is.
I am sure there are better examples, but here is one: search for $ then parse an identifier.
Andrey Oskin said:
And something like
{\blue\bold this text is blue and bold} this text is default
, is it readable?
To me yes, but that probably says a lot more about how much of my life I've spent looking at latex than how many people are likely to find it readable
Well, the only problem I see is that backslash interfere with other backslash usage. "\b" is bell as far as I remember, "\n" is caret return and so on. So it's better to use other direction "/blue/bold"
But at this point maybe colon is ok too :)
Can the colour dictionary be inserted into io
?
One nice thing about colours after the text is that string macros can take a flag at the end, so you could allow a format without the extra brackets:
ioc = IOContext(io, color = Dict(:fox => :brown, :dog => :yellow))
print(ioc, c"this text is blue"blue, " and ", c"{The quick brown fox}:fox jumps over the lazy dog:dog")
Very seldom have I wanted to print colour without interpolating some data or objects, too, so that deserves thought. Should I be able to put :dollar => :red
or something in the dictionary? :code => blue
for things in backticks?
Ok, here is some preliminary details. Of course, there are some bugs which should be fixed, but I think that these preliminary details are already rather good.
IOContext
, but can be used without it. Depends on how you prefer to work.flameshot-2022-03-13T23-54-37.png
flameshot-2022-03-13T23-54-50.png
using Statistics
v = rand(100);
cs = ColorScheme(:median => :red, :δ => :yellow)
s = c"""
Median: :median{$(median(v))}
Standard deviation: :δ{$(std(v))}
"""
print(cs, s)
flameshot-2022-03-13T23-56-59.png
I use :
because latex \
interfere with escape symbol. But it can be changed to anything of course.
Michael Abbott said:
Should I be able to put
:dollar => :red
or something in the dictionary?:code => blue
for things in backticks?
Well, if you want automated resolution of $
or code, then I think it's too complicated. Best way to achieve it is by merging somehow current approach and JuliaParser.jl I think. This is an interesting experiment on it's own, I should give it a thought.
If anyone is interested, you can find this experimental package in https://github.com/Arkoniak/ColorPrinting.jl
It is unregistered of course.
I didn't go through all the discussion but have you had a look in Term.jl ?
It has a very similar syntaxes with the one you suggested. Inspired from the python rich
lib.
Ah, it's nice, but not quite what I want.
Thank you for the reference anyway, I can see how this package can be quite popular.
Last updated: Dec 28 2024 at 04:38 UTC