Reputation: 1689
I currently have the code:
import sys
shell = sys.stdout.shell
my_name = ("Bob", "STRING")
friends_name = ("Jeff", "KEYWORD")
question = ("My name is %s in green and my friend's name is %s in red" % (my_name, friends_name))
shell.write(question)
I am trying to achieve an output of:
My name is Bob in green and my friend's name is Jeff in red.
And in the output the word Bob
is green and Jeff
is red.
However the code I tried simply gives an output of:
My name is ('Bob', 'STRING') in green and my friend's name is ('Jeff', 'KEYWORD') in red
I do know that just typing shell.write("Bob", "STRING")
works but that takes up too many lines of code if you need to print more things in colour.
I have also tried to do
my_name = shell.write("Bob", "STRING")
But when you print that it just outputs 3
I need an answer of how to achieve the output, and also why it outputs 3
when printing
my_name = shell.write("Bob", "STRING")
I would also like to know why it strangely also prints 'Bobby' in green upon being defined like above
PS. I am on a Windows machine with python 3.4.3
Upvotes: 2
Views: 157
Reputation: 44364
Here's a way to do it.
import sys
def shell_print(txt, *args):
out = txt.split("%s")
# vars = [*args] # See comments
vars = list(args)
for t in out:
sys.stdout.shell.write(t)
if vars:
v = vars.pop(0)
sys.stdout.shell.write(*v)
my_name = ("Bob", "STRING")
friends_name = ("Jeff", "KEYWORD")
question = "My name is %s in green and my friend's name is %s in red"
shell_print(question, my_name, friends_name)
It's only a QAD (Quick and Dirty) solution, and will only for with "%s"
, but its a start. So the first parameter is the string containing the %s
place holders, the following parameters (any number of them) are the variables, with their attributes, to be inserted.
EDIT: The basic principle is that first we take the string in txt
and split it around the %s
's, so we are left with (in the example) a list like this (out
):
["My name is ", "in green and my friend's name is", "in red"]
Then we loop through (iterate) this list. We write the next element of out
then look at the first element in args
, which is a tuple. Assuming there is one, then we pass those two tuple elements to write()
.
sys.stdout.shell.write(*v)
The *
does unpacking, that is, if there are two elements in the tuple called v
then it will pass two arguments.
We converted the args
into a list so that we can pop()
the elements. The pop(0)
method removes a element from the list, returning what it removed. So every time we go around the loop we always get the first element in the list.
By the way, we are "popping" from the front of the list (that's the zero), which is inefficient (more efficient to pop from the end). But the list will be small so it is not a big deal.
2nd EDIT:
Improved version, including further tests:
import sys
def shell_print(txt, *args):
shell = sys.stdout.shell
out = txt.split("%s")
argc = len(args)
for i, t in enumerate(out):
shell.write(t)
if i < argc:
sargs = (str(args[i][0]), args[i][1])
shell.write(*sargs)
my_name = ("Bob", "STRING")
friends_name = ("Jeff", "KEYWORD")
question = "My name is %s in green and my friend's name is %s in red\n"
shell_print(question, my_name, friends_name)
# Test all tags
valid_tags = {"COMMENT","KEYWORD","BUILTIN","STRING","DEFINITION","SYNC",
"TODO","ERROR"}
for tag in valid_tags:
shell_print("\n", (tag, tag))
# Other types
my_num = (1234, "STRING")
my_float = (3.142, "COMMENT")
text = "\nMy number: %s, My float: %s\n"
shell_print(text, my_num, my_float)
Upvotes: 1