FYI, Ncurses is a library for text user interfaces. Guile is an implementation of the Scheme programming language. And a Pip Boy is a fictional computer that appears in the Fallout video games.
In the first two parts of this little series of nonsense (part 1, part 2), I wrote about how rendering a string -- turning a logical string into a display string -- got very complicated once you tried to word break properly with non-English and non-ASCII text, deal with control characters, and think about bi-directionality. Unicode is hard. I pulled in two libraries, GNU Fribidi and GNU Libunistring, to create this procedure to wrap a string. So much coder's blood spilled to do something so apparently simple...
(define (string-render str tabsize n-cells alignment bidi)
"Given a string STR, this converts the string into a list of strings
with each string contining N-CELLS cells or fewer. Tabs are expanded
into TABSIZE spaces. Other Unicode spaces are replace with the common
space character. Any control characters are replaced with replacement glyphs. If alignment is 'left, lines are padded with spaces at the end of each string to take up N-CELLS. If ALIGNMENT is 'right, lines are padded with spaces on the left. ALIGNMENT can also be 'center. If BIDI is true, strings are converted from logical order to visual order."
So anyway, I bashed out a couple of widgets.
- A "label" is some wrapped text in a box, possibly with a border
- A "progress bar" is short text followed by a colored bar whose length is a representation 0% to 100%.
There isn't much to say about the code, which is here. It is all very rough and boring and workman-like and verbose. To render these widgets, I settled on an outside-in drawing model.
- The ncurses panel's size is determined first.
- Any border is on the outside edge of the panel, reducing the available window size by 1 on all four sides.
- Inside of that is a user-defined padding width.
- What remains inside of that is available for content.
Here's more Unicode and xterm trivia, which excites me because I am a weirdo.
Boxes
There are a few usable sets of border drawing characters. These should be well aligned if you have a proper monospace font in your browser.;; Light box
;; ┌─┐
;; │ │
;; └─┘
(define *box-chars-light* "┌─┐│ │└─┘")
;; Light round box
;; ╭─╮
;; │ │
;; ╰─╯
(define *box-chars-rounded* "╭─╮│ │╰─╯")
;; Heavy box
;; ┏━┓
;; ┃ ┃
;; ┗━┛
(define *box-chars-heavy* "┏━┓┃ ┃┗━┛")
;; Double box
;; ╔═╗
;; ║ ║
;; ╚═╝
(define *box-chars-double* "╔═╗║ ║╚═╝")
;; Block-char box
;; ▛▀▜
;; ▌ ▐
;; ▙▄▟
(define *box-chars-block* "▛▀▜▌ ▐▙▄▟")
xterm 256-color palette
If you want a good all-green palette from the xterm 256-color palette without modifying the xterm colors, you have about ~10 available colors.With the above widgets and colors, I was able to make the following with just a few (very long) lines of code.
Next Time
Before I get to the interactive widgets, I want to get to the audio design. In Fallout 4, there are tiny click noises when you scroll or select an object on the GUI, which is very satisfying from a UX perspective. So I have to figure out how to do some audio. I guess I'm going to have to dig into GStreamer, which is always daunting...

