I'm trying to add color to values in a formatted table, but the spacing is acting strange and spacing based off of the characters instead of the format spacing I input.
dictionary:
items = {
'staff' : ['Staff', 20, 0,'Yes', 'None', 'None', 'None', ' ', 5,12],
'club' : ['Club', 75, 0,'Yes', 'None', 'None', 'None', ' ', 15,22],
'mace' : ['Mace', 200,0,'Yes', 'None', 'None', 'None', ' ', 30,371],
'warhammer' : ['Warhammer', 350,0,'Yes', 'None', 'None', 'None', ' ', 50,60]
}
argv = 'staff', 'club', 'mace', 'warhammer'
code in question:
def color(r, g, b, text):
return str("\033[38;2;{};{};{}m{} \033[38;2;255;255;255m".format(r, g, b, text))
x = 0
i = 1
print("{:<0} {:<12} {:<10} {:<10} {:<6}".format(" ", "Item", "Cost", "Damage", "Owned"))
while x < i - 1:
y = listing(x, argv, False, 0,1,8,9,3) #outputs a list from a dictionary
if y[1] > player['coins']:
y[1] = color(255,0,0,(y[1]))
else:
y[1] = color(0,255,0,(y[1]))
z = options.get(x+1) #gets an arrow for selection, not important for this code
w = {z:y}
for k, v in w.items():
item, cost, damagemin, damagemax, owned = v
print("{:<0} {:<12} {:<6} {:>03d}-{:>03d} {:<5}".format(k, item, cost, damagemin, damagemax, owned))
x += 1
it outputs this without the coin color check.
Item Cost Damage Owned
> Staff 20 005-012 Yes
Club 75 015-022 Yes
Mace 200 045-055 Yes
Warhammer 350 075-090 Yes
Back
But when I add the coin check to change the color, it outputs this:
Item Cost Damage Owned
> Staff 20 005-012 Yes
Club 75 015-022 Yes
Mace 200 045-055 Yes
Warhammer 350 075-090 Yes
Back
I've checked what it changes the value of y[1] to and it returns '\x1b[38;2;0;255;0m20 \x1b[38;2;255;255;255m'
I'm at a complete loss for how to fix this.
The solution is
while x < i - 1:
y = listing(x, argv, False, 0,1,8,9,3)
if y[1] > player['coins']:
r,g,b = 255,0,0
else:
r,g,b = 0,255,0
z = options.get(x+1)
w = {z:y}
for k, v in w.items():
item, cost, damagemin, damagemax, owned = v
print("{:<0} {:<12} \033[38;2;{};{};{}m{:<5} \033[38;2;255;255;255m {:>03d}-{:>03d} {:<5}".format(k, item, r,g,b, cost, damagemin, damagemax, owned))
x += 1
After research on the .format()
function of Python and the way Python reads it, there isn't a way (as far as I know, please correct me if I'm wrong) to fix this in a way for variable spacing amount in the "{}".format()
. So due to that, I need to break apart \033[38;2;{};{};{}m{} \033[38;2;255;255;255m
into its separate parts and manually insert them into the .format()
.
The problem with the formatting is that m{}
was effectively overriding the {:<6}
in the "{}".format()
. So in order to fix that, I broke \033[38;2;{};{};{}m{} \033[38;2;255;255;255m
into \033[38;2;{};{};{}m{}
and \033[38;2;255;255;255m
. While this is less than optimal, it does fix the problem.
In \033[38;2;{};{};{}m{}
, the first 3 {}
accept values 0-255 (in this specific case) while m{}
accepted text. Since all of this is in the "".format()
, all of the {}
still accept formatting arguments. So after inserting the color code into the "".format()
.
print("{:<0} {:<12} \033[38;2;{};{};{}m{:<5} \033[38;2;255;255;255m {:>03d}-{:>03d} {:<5}".format(k, item, r,g,b, cost, damagemin, damagemax, owned))
I added m{:<5}
to format the text, fixing the problem entirely.
Now to account for this, I changed
if y[1] > player['coins']:
y[1] = color(255,0,0,(y[1]))
else:
y[1] = color(0,255,0,(y[1]))
Which ran the color function and returned an ANSI string that was not able to be formatted. Which then I changed to
if y[1] > player['coins']:
r,g,b = 255,0,0
else:
r,g,b = 0,255,0
Which changes/adds new variables r,g,b
that will be inserted directly into the .format()
function.
This effectively is just expanding the original color()
function and inserting it directly into the .format()
.