Writing cool CLI menus with Python

When you work on projects you often find yourself in a position where you have to write an interactive CLI menu. If it happens that you did that before, you probably know how much pain in the ass that might be, especially if you are handling the user choice inside a big switch-case block. It gets even more complicated when you need to update your menu by adding or changing some entries as the project grows bigger.

I recently found myself in this situation, and tried to figure out a way of making a nice CLI menu in Python, with as less pain as possible. I didn’t do an extensive Google search on the matter, so maybe this idea have been documented elsewhere, but I am writing it down here anyway for the sake of my future documentation.

In this tutorial, we’ll be having a 3 options menu: [0] call foo(), [1] call bar() and [2] Exit. The final result will look like this:

What we need to do first is define the foo() and bar() functions:

Yeah, I’m using Python2 *shame, ding ding, shame*

Next thing to do is declare an array that will hold our menu entries. Each element of the array is a dictionary:

The catch here is that for each dictionary in this array, the key is the text that will be shown in the CLI program, and the value is the address of the function to call (which we defined beforehand).

And finally, in our main() function:

What this piece of code will do is iterate over our menu array, and for each element print its index (that’s our menu choice number between square brackets) and the menu text (that’s the value of the dictionary)

But what’s a menu without a user input. Right, here:

This last piece of code is pretty much simple. We get the user input: If the user enters a negative value, we raise a ValueError exception which we’ll catch later, and if the input is bigger that the size of the menu array, no problemo amigo, an IndexError will raise which we’ll catch also.

If all is good, we call the right function: menuItems[int(choice)]  will retrieve the dictionary that holds up the desired menu option, on which we call the method values()  that’ll return the value associated with our dict() (remember, that’s the function address), and finally we append () so that the function is called.

The final result looks something like this :

Easy, right ? The nice thing with this method is that you don’t have to touch your loop’s code anymore. All you have to do is update the array that holds the menu items.

Let’s get schwifty

Now’s the time to add some ascii art and colors to our menu. We don’t want to bore our users with a dull white-on-black menu, right ?

Let us define a function that colorizes strings, and while we’re at it, grab some ascii art from here too.

We slightly update the main() function:

There you go. Now you have a neat CLI menu with colors and badass ascii art.

And for your convenience, here’s the complete code ready to copy-n-paste: