ANSI Library

I write a lot of small programs in QPython, for example to solve puzzles (most recently to evaluate opening words for Wordle!), or for research in number theory and linguistics. These programs need to be dashed off and revised very quickly, so the effort of developing full graphical user interfaces for them is definitely not cost effective. However I do sometimes find a scrolling teletype interface rather too cumbersome and so I'd like to have quick access to the sort of text-based windowing interface that Turbo Pascal used to offer me 40 years ago, which would mean introducing cursor and colour control to QPython.  

I've had no luck at all getting the Unix curses library, which QPython is supposed to support, to work: it simply won't initialise on my Chromebook (nor on quite a few other peoples' to judge from the forums), though having read the curses  documentation I'm not all that interested anyway -- it's the sort of counter-intuitive package that Unix users perhaps enjoy but which I run a mile from. 

Recently though I discovered how to implement ANSI control codes in QPython, and I've been using them to write my own library that provides a full set of 'widgets' from which to create simple text-based windows, input boxes, menus and bar charts in 256 colours for very little programming effort. The only problem I faced is with the Unicode box-drawing characters used to create borders and lines: on my Chromebook these suffer from a bug that deforms the right-hand corners of boxes, as you will see in this a sample user interface which I knocked up to demonstrate the library. You can download the code for yourself below and see whether the box-characters behave themselves on your system : 

Here's another example of an interface using more conventional pull-down menus, but I need to explain why certain limitations of Python's input() function means that they don't work quite as you might expect. Input() has several annoying restrictions, in particular that it requires a carriage-return to complete every input operation and cannot detect keystrokes without one. Python has no keypressed function like that in Basic and many other languages, and versions provided in modules like keyboard all have drawbacks like being Windows-only or requiring me to root Linux. This made using the cursor arrow keys to navigate menus impossibly awkward, and so I designed menus in which you use Return to scroll down, and any other key to select the option under the cursor.

Another annoyance is that all Python functions return a value, which is None if the function doesn't actually return any value: this meant that scrolling down a menu produced an unsightly moving 'None' at left screen edge that stalked the cursor. However input() does have a really neat redeeming ability, namely that its parameter, which creates the prompt, may be an executable expression. I therefore use as parameter the expression prixy(0,35,'') which as it executes pushes that nasty 'None' down to the bottom-left corner of the screen and erases it once a selection is made. 

I've also used the widgets from my ANSI library to make far more attractive versions of my Poker programs which originally only used ASCII text: you can see these on the ANSI Poker Game page. 

BIG FONT

As a further example of the use of this ANSI code, I've written another library that implements a large matrix font using ANSI characters. Big Font is based on a 6x5 matrix, but as it uses two block characters per 'pixel' it's really equivalent to only 3x5 with half pixels for rounding the corners. Each glyph is therefore represented by a 15-character template string using the four values 0=blank, 1=full width , 2=left half and 3=right half. It's a very blocky font, reminiscent of old-style 8-bit games for the Sinclair Spectrum. I implemented numbers, upper-case letters, punctuation and some symbols for creating boxes and background textures:    

A note for anyone using this Big Font library: there's an inevitable clash between the two different co-ordinate systems involved, since the characters that make up each Big Font glyph are positioned on the native 160x40 character screen, while the big glyphs themselves have to be positioned on a coarser grid of 6x5 character blocks, roughly 26 to each line of 8 lines. Automatically converting between the two grids would introduced hopeless confusion - I point out in the comments for each function which grid its x and y arguments represent and you must perform necessary conversion inside your own for-loops. 

In fact screen co-ordinates have been a problem for this project. A good programmer would ideally place at the very top of their code, constants MaxX and MaxY which users can change to their own screen dimensions. This code was written on an ASUS ChromeBook under QPython, which made screen dimensions variable quantities: the ChromeOS Android engine runs inside a Chrome window and there's a hardware button that selects full-screen mode. My test examples work only on that 169x40 full screen and will scroll wildly if it's not selected. If you're working on Windows you'll need to determine your own character screen dimensions and adjust my code accordingly.

DOWNLOADS

Here's the library file ANSI.py which needs to go into your site-packages folder, and the demo file ANSI DEMO.py which calls it.