Reputation: 21934
I have this code which makes it easy to color a string in terminal but it is looking really repetitive. Is there a functional way of doing this more effectively?
It seems really trival, something like strings blue
,red
etc should point to a generic function, and when you invoke it, you should get the output depending on the caller's name!
But apparently such a thing doesn't exist unless I call it as arguements. But then I lose the flexibility of writing blue(bold(italics("Foo")))
which is really the best way to do this from an end user perspetive.
Can I have a single function object in the memory and do this more effectively?
bcolors = {"BLUE": '\033[94m',
"HIGH": '\033[93m',
"OKAY": '\033[92m',
"FAIL": '\033[91m',
"BOLD": '\033[1m',
"LINE": '\033[4m',
"ENDC": '\033[0m'
}
def blue(string):
return bcolors["BLUE"] + string + bcolors["ENDC"]
def yellow(string):
return bcolors["HIGH"] + string + bcolors["ENDC"]
def green(string):
return bcolors["OKAY"] + string + bcolors["ENDC"]
def red(string):
return bcolors["FAIL"] + string + bcolors["ENDC"]
def bold(string):
return bcolors["BOLD"] + string + bcolors["ENDC"]
def line(string):
return bcolors["LINE"] + string + bcolors["ENDC"]
Upvotes: 1
Views: 58
Reputation: 42796
How about build them on the fly?:
bcolors = {"BLUE": '\033[94m',
"HIGH": '\033[93m',
"OKAY": '\033[92m',
"FAIL": '\033[91m',
"BOLD": '\033[1m',
"LINE": '\033[4m',
"ENDC": '\033[0m'
}
def _genF(color):
return lambda s: bcolors[color] + s + bcolors["ENDC"]
globals().update({k.lower():_genF(k) for k,v in bcolors.items()})
In[10]: blue("Foo")
Out[10]: '\x1b[94mFoo\x1b[0m'
In[11]: blue(bold(okay("Foo")))
Out[11]: '\x1b[94m\x1b[1m\x1b[92mFoo\x1b[0m\x1b[0m\x1b[0m'
This way yo can just use the bcolors dict info for boulding all the methods you need just modifiying the dict.
Upvotes: 1
Reputation: 522626
A function should never vary its behaviour depending on who called it; only its arguments should influence its behaviour, anything else is madness.
The obvious refactoring to make it dryer here would be something along these lines:
def _format(start, string):
return bicolors[start] + string + bcolors['ENDC']
def blue(string):
return _format('BLUE', string)
If you wrap this in a class with some magic properties or method call overrides, you could even start deriving the 'BLUE'
parameter from the function call.
Upvotes: 1