Sunday, June 12, 2016

A Pipboy-like terminal application in Guile: Part 3 - labels and progress bars

So, in trying to put together a new release of the ncurses binding for GNU Guile, I decided I'd try to make a Pip-Boy like application that runs in a terminal emulator like xterm or Gnome Terminal  This is just for the nonsense of it, and the challenge.

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.
  1. The ncurses panel's size is determined first.
  2. Any border is on the outside edge of the panel, reducing the available window size by 1 on all four sides.
  3. Inside of that is a user-defined padding width.
  4. 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...

Thursday, June 09, 2016

Mapping xterm 256-color palette colors to X11 color names

Here is a table that might be of some use to somebody, someday.

The xterm-like terminals all have pretty similar predefined colors in their 256-color palettes.  The 1st eight colors seem to vary since they often get replaced with system colors, but the remainder are quite stable among 256-color terminal emulators claiming xterm compliance.

Unrelated to this, X11 has long included a file called /usr/share/X11/rgb.txt that has names of colors.  I wondered what overlap there was between these two things.

So, this is a list of the xterm 256-color palette indices vs X11 RGB color names.  To declare something a match, I chose the closest X11 color to the xterm palette color in LAB coordinates, but, never searched farther that 6.9 units of difference in LAB space.  Under those criteria, 129 of 256 xterm colors approximate named X11 RGB colors.



0: BLACK
1: WEBMAROON
2: WEBGREEN
3: OLIVE
4: NAVY, NAVYBLUE
5: WEBPURPLE
6: TEAL
7: SILVER
8: WEBGRAY, WEBGREY
9: RED, RED1
10: GREEN, LIME, X11GREEN, GREEN1
11: YELLOW, YELLOW1
12: BLUE, BLUE1
13: MAGENTA, FUCHSIA, MAGENTA1
14: CYAN, AQUA, CYAN1
15: WHITE
16: BLACK
18: BLUE4, DARKBLUE
20: MEDIUMBLUE, BLUE3
21: BLUE, BLUE1
22: DARKGREEN
24: DEEPSKYBLUE4
26: ROYALBLUE
28: GREEN4
30: CYAN4, DARKCYAN
37: LIGHTSEAGREEN
40: GREEN3
44: CYAN3
46: GREEN, LIME, X11GREEN, GREEN1
48: SPRINGGREEN, SPRINGGREEN1
51: CYAN, AQUA, CYAN1
54: INDIGO
59: GRAY37, GREY37
62: SLATEBLUE3
65: DARKSEAGREEN4
66: PALETURQUOISE4
68: CORNFLOWERBLUE
74: SKYBLUE3
75: STEELBLUE1
76: CHARTREUSE3
78: SEAGREEN3
79: MEDIUMAQUAMARINE, AQUAMARINE3
80: MEDIUMTURQUOISE
86: AQUAMARINE, AQUAMARINE1
88: RED4, DARKRED
89: MAROON4
90: MAGENTA4, DARK MAGENTA, DARKMAGENTA
92: DARKVIOLET
94: DARKGOLDENROD4
95: LIGHTPINK4
96: PLUM4
100: YELLOW4
102: GRAY53, GREY53
108: DARKSEAGREEN
110: SKYBLUE3
114: PALEGREEN3
116: DARKSLATEGRAY3
117: LIGHTSKYBLUE
118: CHARTREUSE, CHARTREUSE1
122: AQUAMARINE, AQUAMARINE1
123: DARKSLATEGRAY1
134: MEDIUMORCHID3
136: DARKGOLDENROD
138: ROSYBROWN
141: MEDIUMPURPLE1
143: DARKKHAKI
145: GRAY69, GREY69
149: DARKOLIVEGREEN3
152: POWDERBLUE
154: GREENYELLOW
159: PALETURQUOISE1
160: RED3
162: VIOLETRED
164: MAGENTA3
167: INDIANRED
171: MEDIUMORCHID1
172: ORANGE3
173: LIGHTSALMON3
178: GOLD3
180: BURLYWOOD3
184: YELLOW3
186: KHAKI3
187: LEMONCHIFFON3
188: GRAY84, GREY84
195: LIGHTCYAN, LIGHTCYAN1
196: RED, RED1
198: DEEPPINK, DEEPPINK1
201: MAGENTA, FUCHSIA, MAGENTA1
203: INDIANRED1
205: HOTPINK
208: DARKORANGE
209: SALMON1
210: LIGHTCORAL
211: PALEVIOLETRED1
213: ORCHID1
214: DARKGOLDENROD1
215: SANDYBROWN
217: LIGHTPINK1
220: GOLD, GOLD1
223: PEACHPUFF, PEACHPUFF1
224: MISTYROSE, MISTYROSE1, MISTYROSE2
225: THISTLE1
226: YELLOW, YELLOW1
230: LIGHTGOLDENRODYELLOW
231: WHITE
232: GRAY3, GREY3
233: GRAY7, GREY7
234: GRAY11, GREY11
235: GRAY15, GREY15
236: GRAY19, GREY19
237: GRAY23, GREY23
238: GRAY27, GREY27
239: GRAY30, GREY30, GRAY31, GREY31
240: GRAY34, GREY34, GRAY35, GREY35
241: GRAY38, GREY38, GRAY39, GREY39
242: GRAY42, GREY42
243: GRAY46, GREY46
244: WEBGRAY, WEBGREY
245: GRAY54, GREY54
246: GRAY58, GREY58
247: GRAY62, GREY62
248: GRAY66, GREY66
249: GRAY70, GREY70
250: GRAY74, GREY74
251: GRAY78, GREY78
252: GRAY81, GREY81, GRAY82, GREY82
253: GRAY85, GREY85, GRAY86, GREY86
254: GRAY89, GREY89, GRAY90, GREY90
255: GRAY93, GREY93