Aiyush Gupta
Ooshimus.com

Ooshimus.com

Printing COLOUR in IDLE in less than 2 minutes!

Printing COLOUR in IDLE in less than 2 minutes!

Aiyush Gupta's photo
Aiyush Gupta
·Aug 5, 2021·

5 min read

Subscribe to my newsletter and never miss my upcoming articles

Listen to this article

Introduction

IDLE, Integrated Development and Learning Environment, has been bundled together with Python since version 1.5 . Yet, still lacks one fundamental built-in function that all beginners crave… Coloured text.

If you just want the solution, scroll to the bottom [Easy Implementation]

Gif description

As a python newbie some 2.5 years ago, this was a feature which I had ransacked the Interweb for, until recently I had only found the usual Colorama.

It works since it...

Makes ANSI escape character sequences (for producing colored terminal text and cursor positioning) work under MS Windows. ANSI escape character sequences have long been used to produce colored terminal text and cursor positioning on Unix and Macs. Colorama makes this work on Windows, too, by wrapping stdout, stripping ANSI sequences it finds (which would appear as gobbledygook in the output), and converting them into the appropriate win32 calls to modify the state of the terminal. On other platforms, Colorama does nothing.

This was taken directly from the PyPi page for Colorama and it is a great project. In no way am I saying that it isn’t, but I still couldn’t get it to work in IDLE and remember “On other platforms, Colorama does nothing”. My aim, was to find a cross-platform solution that would be perfect for hobbyists and newbies getting started. My main issue was found in the school environment where I had no access to the command line so couldn’t even install other packages via pip – which I later found out wasn’t even installed. And we were stuck to using IDLE no VScode or Sublime.

My First Attempt

I found this solution from StackOverflow: here

Put this at the "start" of your code:

import sys

try:
    color = sys.stdout.shell
except AttributeError:
    raise RuntimeError("Use IDLE")
#And then use color.write(YourText,Color) for "printing":
color.write("Hi, are you a fan of the Ooshimus blog? \n","KEYWORD")
color.write("Yes","STRING")
color.write(" or ","KEYWORD")
color.write("No\n","COMMENT")

This prints:

Screenshot 2021-08-05 at 16.22.16.png

Note: this does NOT automatically put the enter (like in the print function/statement). So, when you are printing put \n at the end of the last string to put it.

The "Colors" you can put are: SYNC, stdin, BUILTIN, STRING, console, COMMENT, stdout, TODO, stderr, hit, DEFINITION, KEYWORD, ERROR, and sel.

Note 2: This is dependent of the color scheme you are using for IDLE. So I recommend you to use it for highlighting, and not for making a program for asking what in color is some word.

Easy Implementation

Now, this does work and it fulfils the objective however it seems a little complicated with all of the backslashes and it decreased readability and maintainability. I wanted something more concrete. And that is when I started to write my own module implementation of this. I came across this from Github : here and it successfully did everything I needed it to, even better it was a single file and wasn’t bloated at all. Since this was written in 2018 (4 years old at time of writing), I downloaded it and made some edits to ensure it worked properly and came up with this:

import sys
import random
from time import sleep

# Heavily inspired by lawsie's IDLECOLOURS, but has been updated from 2018 to 2021 and just added a typing effect
# ---------------------------
# Typing Effect
# ---------------------------

def printt(text):
    try:
        for char in text:
            sleep(0.1)
            print(char, end='', flush=True)
    except:
        raise TypeError('Printt does not support coloured text at the moment, or you are trying to print type != str')

# This will only work in IDLE, it won't work from a command prompt
try:
    shell_connect = sys.stdout.shell
except AttributeError:
    print("idlecolors highlighting only works with IDLE, why don't you try another package such as colorama?")
    exit()

global colormap
colormap = {"red": "COMMENT",
            "orange": "KEYWORD",
            "green": "STRING",
            "blue": "stdout",
            "purple": "BUILTIN",
            "black": "SYNC",
            "brown": "console"}



# Like the print() function but will allow you to print colours
def printc(text, end="\n"):
    # Parse the text provided to find {text:color} and replace with the colour. Any text not encompassed in braces
    # will be printed as black by default.
    buff = ""
    for char in text:
        if char == "{":
            # Write current buffer in black and clear
            shell_connect.write(buff, colormap["black"])
            buff = ""
        elif char == "}":
            # Write current buffer in color specified and clear
            tag_write = buff.split(":")
            shell_connect.write(tag_write[0], tag_write[1])
            buff = ""
        else:
            # Add this char to the buffer
            buff += char

    # Write the chosen end character (defaults to newline like print)
    sys.stdout.write( end )


# Individual colour functions
def red(text):
    return "{"+ text + ":" + colormap["red"] + "}"

def orange(text):
    return "{"+ text  + ":" + colormap["orange"] + "}"

def green(text):
    return "{"+ text + ":" + colormap["green"] + "}"

def blue(text):
    return "{"+ text  + ":" + colormap["blue"] + "}"

def purple(text):
    return "{"+ text + ":" + colormap["purple"] + "}"

def black(text):
    return "{"+ text  + ":" + colormap["black"] + "}"

def brown(text):
    return "{"+ text + ":" + colormap["brown"] + "}"

def randcol(text):
    color = random.choice(list(colormap.keys()))
    return "{"+ text + ":" + colormap[color] + "}"

I also added a small typing effect that could be used in text-based RPG’s. To use this, create another python file in the same directory of your project and copy/paste it and save it as “colouringIDLE.py”, you can then open your main project and:

from colouringIDLE import *

Here is some basic implementation:

printc( red("Red text") )
printc( "If you add " + red("red") + " to " + blue("blue") + ", you get " + purple("purple") )
printt("See me get typed")

Conclusion

Although this only works in IDLE, it provides an easy and sensible way for you to get started to use colour in your text-based projects to make them intuitive and immersive. If you have any questions feel free to add them to the comments or add me on LinkedIn here!

Python Logo

Did you find this article valuable?

Support Aiyush Gupta by becoming a sponsor. Any amount is appreciated!

Learn more about Hashnode Sponsors
 
Share this