Open ctian1 opened 9 years ago
The new colors.py
util module can do this, and more. It's not the exact same kind of syntax, though.
from cloudbot import hook
from cloudbot.util import colors
@hook.command()
def my_command():
string = "$(bold)This is bold$(clear) but this is not, however $(bold,red)this is bold and red!$(clear)"
returns colors.parse(string)
I've seen that, but IMHO it seems kind of hard to use in some situations
it can be useful when building strings, but what if:
def command(text, reply):
msg = "$(bold)Adding option '$(clear){}$(bold)' to database."
reply(colors.parse(msg))
Now, if a user were to add an option such as '$(red)asdf', they could wreck the colors and stuff.
I'm just saying, I thought it was handy to able to do things like reply(bold("[Settings] ") + italic(input) + color(" has now been changed to 0", 4))
Well, in that specific situation you can use $(bold)
again to toggle it off (mirc colors are weird), but I get your feedback. Perhaps I can add some manual functions to colors.py
like bold(str)
and color(str, colorname)
.
edit: Ah, yes, sorry. I didn't get your post at first, yeah, users can inject colors. But you can simply run colors.strip(str)
on the input to remove all color formatting from it if needed, but it might not be ideal.
Also, you can get the color formatting codes with colors.get_color("red")
or colors.get_formatting("bold")
I can still add the manual functions if you can think of a good use-case for them though.
I use those functions a lot;
for example, in my minecraft server status script for willie, I did this somewhere;
msg = "{0} is " + bold("up") + " with {1} players and a latency of {2}ms, running {3}, and has an MOTD of \"{4}\"."
bot.say(msg.format(bold(trigger.group(2).split()[0]), players, latency, version, colorize(motd)))
doing that without bold() and stuff would probably need..
msg = colors.parse("{0} is $(bold)up$(clear) with {1} players and a latency of {2} ms, running {3}, and has an MOTD of \"{4}\".")
bot.say(msg.format(color.get_formatting("bold") + trigger.group(2).split()[0] + color.get_formatting("bold"), players, latency, version, colorize(motd)))
which isn't too bad, but particularly bold(test)
vs. color.get_formatting("bold") + text + color.get_formatting("bold")
seems particularly painful, and similar with italic and underline.
Edit: now that I look at it, the top example is pretty bad. lemme find a better one
ehhh
Better example:
in another part of my minecraft script, querying users returns a message like
$(bold)[Pangea/956e407b-d332-4df6-b0b7-08873fa7446d]: PAID: $(green)true $(clear)$(bold)| MIGRATED: $(clear)$(green)true$(clear)$(bold) | SKIN: $(clear)http://textures.minecraft.net/texture/3b42c78aa592a3110f02b23c76f325b9d4cc8ab72523884e73fc0c0649758
which should turn out like (but with colors)
[Pangea/956e407b-d332-4df6-b0b7-08873fa7446d]: PAID: true | MIGRATED: true | SKIN: http://textures.minecraft.net/texture/3b42c78aa592a3110f02b23c76f325b9d4cc8ab72523884e73fc0c0649758
the code for this was:
query = str(bold("[" + user + "/" + str(uuid.UUID(id)) + "]") + ": " + bold("PAID:") + " {0} | " + bold("MIGRATED:") + " {1}").format(paid, migrated)
hm... with colors.py..
query = str(color.get_formatting("bold") + "[" + user + "/" + str(uuid.UUID(id)) + "]" + color.get_formatting("clear") + ": " + color.get_formatting("bold") + "PAID: " + color.get_formatting("clear")
and much more I don't even want to finish right now ;-; it's that painful
[ ] underline(text)
should also be added
Or you could use colors.parse()
, and the first example is hardly a fair comparison, it adds colors when example 2 doesn't have them! But I'll add the functions you want, but colors are going to be complex to get working in an entirely logical way - MIRC colors are not something you can just turn on and off like an HTML tag, they can only be cleared with RESET, which also clears bold and other formatting codes.
So a function-based format for colors wont really work how you would expect.
Hmm.. I guess you have a point
say I have a template like $(green)asdf$(clear),04asdf
this would show the first 'asdf' as green, then ',04asdf' as default color.
with colorfunctions, you'd do:
color("asdf", 3) + ",04asdf"
but then this breaks because since it doesn't use the actual color reset ($(clear)) and inserts another color code symbol, it interprets the reset as the start of a new color section.
cloudbot version: (where [c] is color code, [r] is reset)
[c]3asdf[r],04asdf
functions:
[c]3asdf[c],04asdf
-------------^ this is interpreted as a color code
so I'm not so sure anymore.
the bold/underline/italic functions should work perfectly because the control characters for those can start and end, which won't affect colors.
colors can also be ended by the color control code, but again if the text after that begins with some numbers it can unintentionally start a new color section.
hopefully all of this wasn't too confusing
any ideas for a better solution to this?
I wasn't sure if colors ended with the color control code or not, but if they do, it makes things simplier. As for the issue or ,04asdf
, it seems like something that will very rarely happen, and I'm not sure theres really anything we can do about it. Perhaps we can include a invisible/null character just after the color codes of color()
to fix it? I'm not sure what character would be suitable, but I'm sure theres one we can use.
With the injecting colors, wouldn't that be fixed if you ran the format string through colors.parse before filling in with user-provided values?
My utility was mostly meant to add added readability for the programmer. \x0306
doesn't directly help you notice it is actually purple. And calling functions also does interfere with readability.
It certainly won't hurt to add aliases for things like bold() underline() etc, it is mostly left in the developers hand on how they want to extend on it, mine is just a base implementation.
Also, keep in mind you can chain formattings and colours in parse(), i.e.
mystr = color.parse("my string $(red, blue, bold)stuff$(clear) more string")
whereas
mystr = "my string" + color.bold(color.color("stuff", color.RED, color.BLUE)) + "more string"
just doesn't read very nicely (at least in my opinion).
Whatever the case, get_formatting() and get_color() are not functions that were intended to be called directly, but they do exist so that others can extend on it.
This probably works :P
from cloudbot import hook
from cloudbot.util import colors
@hook.command()
def my_command(text):
# remove all colors from user input
text = colors.strip_all(text)
# build the output
string = "$(bold)User Input:$(clear) {}".format(text)
returns colors.parse(string)
This has the advantage of stripping all MIRC and CloudBot formatting from the input string.
What if there's some odd chance someone needs to use $(something like this) for something not color involved? Won't those be broken?
Also, I'm more worried about making dynamic colors, like:
if user.paid:
paid = color("true", GREEN)
else:
paid = color("false", RED)
With .parse:
if user.paid:
paid = "$(green){}$(clear)".format("true")
else:
paid = "$(red){}$(clear)".format("false")
I suppose one hackery way we can solve this is adding two bold characters after a color code used to reset colors, which will ensure that there isn't another numeric color value after the color symbol. But that seems too hackery.
Like said on IRC what the code currently does doesn't support escaping of yet, but could probably be implemented easily. It wasn't added yet because it wasn't a priority feature for me.
What do you mean with dynamic colours? I don't think that'll be a problem at all.
paid = color("true" if user.paid else "false", "green" if user.paid else "red")
paid = "$({}){}$(clear)".format("green" if user.paid else "red", "true" if user.paid else "false")
paid = getColor("green" if user.paid else "red") + "{}$(clear)".format("true" if user.paid else "false")
The code would look the same in Willie, no?
I seem to be really attached to Willie.. I think it could be a good idea to have the formatting module Willie has: