ANSI Escape Codes in Python
LeonDoesCode (272)

What are You Even on About?

Remember when we looked at Terminal Colour in Python? Well, that's how they make these colours in the Terminal! Well, in Linux and Mac, unless if you enable it on Windows. Talking about that, if you do want to enable ANSI on Windows, you can run this command int the CMD or PowerShell:

:: Enable ANSI on Windows
reg add HKEY_CURRENT_USER\Console /v VirtualTerminalLevel /t REG_DWORD /d 1
:: Disable ANSI on Windows
reg add HKEY_CURRENT_USER\Console /v VirtualTerminalLevel /t REG_DWORD /d 0

So let's get onto making our own little Library for ANSI Escape Codes!

Colours

Let's begin by looking at the colours. Depending on what terminal you are using, and what you want to support, you can have quite a lot of colours. We will be implementing all the 8 bit colours, and and rgb function which can take in a r, g, and b value.

Before we do this, let's look at how our Library is going to work. When we want to use an 8 bit colour, which will be stored in a variable, we can just use the class bg or fg and the colours name. E.g. print(bg.white + fg.white + "Hello, World!"). When we want to use a RGB values, we will use the function rgb instead , like so print(bg.rgb(210, 210, 210) + fg.rgb(50, 50, 50) + "Hello, World!"). Simples!

We will also need to import a few things, this is not required, but I also create a few extra Utilities that might come in handy:

from sys import stdout, stdin
from time import sleep

Now for implementing the 8 bit and RGB colours:

class fg:
  black = "\u001b[30m"
  red = "\u001b[31m"
  green = "\u001b[32m"
  yellow = "\u001b[33m"
  blue = "\u001b[34m"
  magenta = "\u001b[35m"
  cyan = "\u001b[36m"
  white = "\u001b[37m"

  def rgb(r, g, b): return f"\u001b[38;2;{r};{g};{b}m"

class bg:
  black = "\u001b[40m"
  red = "\u001b[41m"
  green = "\u001b[42m"
  yellow = "\u001b[43m"
  blue = "\u001b[44m"
  magenta = "\u001b[45m"
  cyan = "\u001b[46m"
  white = "\u001b[47m"

  def rgb(r, g, b): return f"\u001b[48;2;{r};{g};{b}m"

As you can see, the only difference between the background and foreground colours, is the use of 30+ or 40+. you can see that each ANSI Escape Code starts with \u001b[, we then put the code. For the rgb functions, we just made it so that it returns a string with the RGB values placed inside it.

Utilities

Other than the colours, we can also use some "Utility Code" if you want to think of them like that. These allow us to move the Cursor, Clear the scree, Reset the colours, and so on. So lets have a look at those:

class util:
  reset = "\u001b[0m"
  bold = "\u001b[1m"
  underline = "\u001b[4m"
  reverse = "\u001b[7m"

  clear = "\u001b[2J"
  clearline = "\u001b[2K"

  up = "\u001b[1A"
  down = "\u001b[1B"
  right = "\u001b[1C"
  left = "\u001b[1D"

  nextline = "\u001b[1E"
  prevline = "\u001b[1F"

  top = "\u001b[0;0H"

  def to(x, y):
    return f"\u001b[{y};{x}H"

  def write(text="\n"):
    stdout.write(text)
    stdout.flush()

  def writew(text="\n", wait=0.5):
    for char in text:
      stdout.write(char)
      stdout.flush()
      sleep(wait)

  def read(begin=""):
    text = ""

    stdout.write(begin)
    stdout.flush()

    while True:
      char = ord(stdin.read(1))
      
      if char == 3: return
      elif char in (10, 13): return text
      else: text += chr(char)

  def readw(begin="", wait=0.5):
    text = ""

    for char in begin:
      stdout.write(char)
      stdout.flush()
      sleep(wait)

    while True:
      char = ord(stdin.read(1))
      
      if char == 3: return
      elif char in (10, 13): return text
      else: text += chr(char)

Note: I added the write, writew, read, and readw myself, and are just something I added that you can use. Because of this, I am not going to explain them in much detail.

Once again, we start the ANSI Escape Codes and give the codes. We have a function called to which allows you to input a row and column (x and y) to move the Cursor to. Other than that, we have some basic ones which Clear the screen, Reset the colours, and so on. The read and write functions act like input and print, the ones with "w" on the ends have a delay so that you can make them look typed. They also don't create a new line automatically.

Now that we have our little Library, let's give it a quick test!

Testing

Note: I called the Library textit as it was all text based Utilities. You may need to change this depending on what you do.

from textit import *
from time import sleep
from random import randint

from sys import stdout, stdin

util.write(bg.rgb(210, 210, 210) + fg.rgb(50, 50, 50) + util.bold + "Hello, World!\n")

util.write(bg.black + fg.green)
util.write(util.clear)
util.write(util.top)

util.writew("CRT", 0.1)
util.writew("." * randint(3, 8))
util.write()

util.writew("OS", 0.1)
util.writew("." * randint(3, 8))
util.write()

util.writew("USERS", 0.1)
util.writew("." * randint(3, 8))
util.write()

sleep(3)
util.write(util.clear)
util.write(util.top)

login = util.readw("LOGIN: ", 0.1)

util.writew(f"Logging in as {login}", 0.1)
util.writew("." * randint(1, 8))
util.write()

sleep(3)
util.write(util.clear)
util.write(util.top)

util.write(util.reset)

Give this a little run to see how most of the stuff we created works, and play around wit it. When you run this, you should get the text "Hello, World!" with a white background and black foreground. After that, it will clear very quickly and move to a black and green scheme. This will then do a little start-up and login sequence to show you how the Library can be used. Pretty cool!

Conclusion

While this may not be a cross platform solution (unless you prompt a Windows user to run that command from the beginning), it's a goof introduction to how ANSI Escape Codes work. We may even use this i the future...

P.S
If you have any suggestions for tutorials, leave them in the comments and I'll be sure to have a look. If you like one in the comments, then give it an up vote to show that you want to see it. It makes my life so much more easier. Thanks in advance!

User Additions

@theangryepicbanana Note: you can actually do this in any language (except js to an extent) since ANSI codes are a terminal thing :). cool tho

@TaylorLiang Found a link from stackoverflow: https://svn.blender.org/svnroot/bf-blender/trunk/blender/build_files/scons/tools/bcolors.py

You are viewing a single comment. View All
LeonDoesCode (272)

@theangryepicbanana true, true. Just though I'd also show how to make a little library in Python as the ANSI Codes by them self didn't seem like they could do one tutorial. Thanks!