tag:blogger.com,1999:blog-149786672024-08-30T07:45:34.356-07:00Lonely CactusA life of punk, code and apathyMikehttp://www.blogger.com/profile/00699531526967964528noreply@blogger.comBlogger63125tag:blogger.com,1999:blog-14978667.post-36521463998239267362021-10-28T09:02:00.000-07:002021-10-28T09:02:05.032-07:00May you live in interesting times<p>Hey everybody.</p><p>So last February now, I, in a fit of optimism, thought I'd take on the Guile Potluck duties for 2021: asking people to submit the fun stuff they were up to, and then I'd blog about it. That didn't happen, for which I humbly apologize. But I should know by now that every time I actually commit to something publicly visible in free software, reality intervenes. So from now on, I promise that I will never again commit to anything.</p><p>But life is getting better, my vision problems are improving. My back is all healed and I can actually sit in an office chair all day without pain.</p><p>So yeah.</p><p>Anyway, while I shy away from term <i>commitment</i>, I do have <i>intention</i>&nbsp;to make good on old promises.</p><p>In the meantime (and one of the reasons I'm actually talking about feelings on this backup blog right now instead of my standard repository of feelings) I do have to do something about my always-neglected primary website&nbsp;<a href="https://lonelycactus.com">Lonely Cactus</a>&nbsp;which apparently has gone to blog heaven.&nbsp; A pity. There was some cool stuff on there.</p><p>My hope is to get Lonely Cactus up and running on a different set of technologies, as a learning exercise.&nbsp; Maybe a GNU/Hurd VM. Maybe Guix.&nbsp; Because if you're going to do something weird, might as well go all the way.</p><p>But in real life, if you're keeping score, I have returned to <span style="font-family: courier;">/dev/null</span><span style="font-family: inherit;">. Single again, no kids in the house anymore, unfit, no church life to speak of. I still own this dilapidated, century-old house in Los Angeles, and have a day job, so I'm better off than billions of people. And I'm lucky in that comparatively few people I know have died during the plague year.&nbsp;</span></p><p><span style="font-family: inherit;">Time for life v4.0, or v5.0. I'm not sure of my current revision number.</span></p><p><span style="font-family: inherit;"><br /></span></p>Mikehttp://www.blogger.com/profile/00699531526967964528noreply@blogger.com0tag:blogger.com,1999:blog-14978667.post-78999883179899196812021-03-29T20:51:00.000-07:002021-03-29T20:51:44.993-07:00Guile Potluck 2021 Part 1: Genshou and Anguish<h2 style="text-align: left;">Preface</h2><p>Guile Potluck 2021 was an event where hackers got to advertise their exciting new projects.&nbsp; It wrapped up a few weeks ago, and at that time I was my intention to blog my way through the entrants right away.&nbsp; Well, I have not been expedient on that front.<br />I'm so very sorry it has taken me so long to get back to Guile Potluck 2021.&nbsp; Somewhere between family, kids, the day job, actually working on Guile, and the vague depression that quarantine seems to instill in me, it all got away from me.<br />But hey, let's see what we've got. I'll start from the end, and work my way back to the beginning.<br /></p><h2 style="text-align: left;">Genshou, by Walter Lewis</h2><p><a href="https://git.sr.ht/~wklew/genshou">https://git.sr.ht/~wklew/genshou</a><br /><br />Here, <i>wklew</i> implements an <b>extensible effects</b> system, that allows stateful computations without any mutation.&nbsp; Thought provoking stuff, especially if you like pondering monads, denotational semantics and other such things.</p><p>Honestly, it is projects like this that activate my impostor syndrome with regards to Scheme. Many Scheme hackers approach it from a deep interest in Computer Science, and mostly I look at their work in awe whilst carrying on with my second-hand understanding of programming that somehow I've built a career on.<br />&nbsp;</p><h2 style="text-align: left;">Anguish, by Rutger van Beusekom</h2><p style="text-align: left;"><a href="https://gitlab.com/rutger.van.beusekom/anguish">https://gitlab.com/rutger.van.beusekom/anguish</a><br />&nbsp;</p><p style="text-align: left;"></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg06VuinJqZ1YF_HZPqBXO0qdZ9oli9CVtCPDFO4suC3FKMzo1nPAuJs1C41OR93GfUhTu_8ByHvxW0dDGBgkyMO7bLLUSZbk246cFZjS876r33awKVSccd7x0UNKfeAuxvCPc/s408/anguish.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="105" data-original-width="408" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg06VuinJqZ1YF_HZPqBXO0qdZ9oli9CVtCPDFO4suC3FKMzo1nPAuJs1C41OR93GfUhTu_8ByHvxW0dDGBgkyMO7bLLUSZbk246cFZjS876r33awKVSccd7x0UNKfeAuxvCPc/s320/anguish.png" width="320" /></a></div><br />&nbsp;<p></p><p style="text-align: left;"><i>rutger.van.beusekom</i> has written as parser for the POSIX sh language<br />using PEG grammar, which he hopes to convert into a full fledged shell<br />in future. At the moment, it converts shell statements into an SXML-like representation.</p><p style="text-align: left;">I am excited to see someone exercise Guile's PEG parser, which is both powerful and under-utilized.<br /><br /></p>Mikehttp://www.blogger.com/profile/00699531526967964528noreply@blogger.com1tag:blogger.com,1999:blog-14978667.post-5672252787181238222021-02-18T09:58:00.000-08:002021-02-18T12:09:56.730-08:00Guile Potluck 2021<p><span style="font-family: inherit;">&nbsp;<span style="-webkit-text-stroke-width: 0px; background-color: white; caret-color: rgb(46, 52, 54); color: #2e3436; display: inline !important; float: none; font-size: 13.3333px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-decoration: none; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px;">Hello All-</span><br style="-webkit-text-stroke-width: 0px; background-color: white; caret-color: rgb(46, 52, 54); color: #2e3436; font-size: 13.3333px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-decoration: none; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px;" /><br style="-webkit-text-stroke-width: 0px; background-color: white; caret-color: rgb(46, 52, 54); color: #2e3436; font-size: 13.3333px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-decoration: none; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px;" /><span style="-webkit-text-stroke-width: 0px; background-color: white; caret-color: rgb(46, 52, 54); color: #2e3436; display: inline !important; float: none; font-size: 13.3333px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-decoration: none; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px;">In celebration of the (slightly belated) 10-year anniversary of Guile </span><span style="-webkit-text-stroke-width: 0px; background-color: white; caret-color: rgb(46, 52, 54); color: #2e3436; display: inline !important; float: none; font-size: 13.3333px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-decoration: none; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px;">v2.0, we're having another Guile Potluck!&nbsp; The Guile Potluck is a </span><span style="-webkit-text-stroke-width: 0px; background-color: white; caret-color: rgb(46, 52, 54); color: #2e3436; display: inline !important; float: none; font-size: 13.3333px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-decoration: none; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px;">randomly annual event to give people a chance to show off their Guile </span><span style="-webkit-text-stroke-width: 0px; background-color: white; caret-color: rgb(46, 52, 54); color: #2e3436; display: inline !important; float: none; font-size: 13.3333px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-decoration: none; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px;">projects and skills.&nbsp; Think of it as a game jam, but, not constrained </span><span style="-webkit-text-stroke-width: 0px; background-color: white; caret-color: rgb(46, 52, 54); color: #2e3436; display: inline !important; float: none; font-size: 13.3333px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-decoration: none; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px;">to games.<span class="Apple-converted-space">&nbsp;</span></span><br style="-webkit-text-stroke-width: 0px; background-color: white; caret-color: rgb(46, 52, 54); color: #2e3436; font-size: 13.3333px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-decoration: none; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px;" /><br style="-webkit-text-stroke-width: 0px; background-color: white; caret-color: rgb(46, 52, 54); color: #2e3436; font-size: 13.3333px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-decoration: none; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px;" /><span style="-webkit-text-stroke-width: 0px; background-color: white; caret-color: rgb(46, 52, 54); color: #2e3436; display: inline !important; float: none; font-size: 13.3333px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-decoration: none; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px;">To participate, on or before Mar 6, send an email to<span class="Apple-converted-space">&nbsp;</span></span><a href="mailto:guile-user@gnu.org" style="-webkit-text-stroke-width: 0px; background-color: white; font-size: 13.3333px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px;" title="Click to mail guile-user@gnu.org">guile-user@gnu.org</a><span style="-webkit-text-stroke-width: 0px; background-color: white; font-size: 13.3333px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px;"> </span><span style="-webkit-text-stroke-width: 0px; background-color: white; caret-color: rgb(46, 52, 54); color: #2e3436; display: inline !important; float: none; font-size: 13.3333px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-decoration: none; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px;">with Potluck in the subject line. Please include instructions on how to find your entry, which could be anything </span><span style="-webkit-text-stroke-width: 0px; background-color: white; caret-color: rgb(46, 52, 54); color: #2e3436; display: inline !important; float: none; font-size: 13.3333px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-decoration: none; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px;">you like.&nbsp; For example,</span><br style="-webkit-text-stroke-width: 0px; background-color: white; caret-color: rgb(46, 52, 54); color: #2e3436; font-size: 13.3333px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-decoration: none; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px;" /><br style="-webkit-text-stroke-width: 0px; background-color: white; caret-color: rgb(46, 52, 54); color: #2e3436; font-size: 13.3333px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-decoration: none; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px;" /><span style="-webkit-text-stroke-width: 0px; background-color: white; caret-color: rgb(46, 52, 54); color: #2e3436; display: inline !important; float: none; font-size: 13.3333px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-decoration: none; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px;">&nbsp;&nbsp; - a script showing off some feature of Guile or your favorite Guile</span><span style="-webkit-text-stroke-width: 0px; background-color: white; caret-color: rgb(46, 52, 54); color: #2e3436; display: inline !important; float: none; font-size: 13.3333px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-decoration: none; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px;"> library</span><br style="-webkit-text-stroke-width: 0px; background-color: white; caret-color: rgb(46, 52, 54); color: #2e3436; font-size: 13.3333px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-decoration: none; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px;" /><span style="-webkit-text-stroke-width: 0px; background-color: white; caret-color: rgb(46, 52, 54); color: #2e3436; display: inline !important; float: none; font-size: 13.3333px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-decoration: none; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px;">&nbsp;&nbsp; - a blog post describing something interesting about Guile</span><br style="-webkit-text-stroke-width: 0px; background-color: white; caret-color: rgb(46, 52, 54); color: #2e3436; font-size: 13.3333px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-decoration: none; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px;" /><span style="-webkit-text-stroke-width: 0px; background-color: white; caret-color: rgb(46, 52, 54); color: #2e3436; display: inline !important; float: none; font-size: 13.3333px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-decoration: none; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px;">&nbsp;&nbsp; - an updated release of a neglected library</span><br style="-webkit-text-stroke-width: 0px; background-color: white; caret-color: rgb(46, 52, 54); color: #2e3436; font-size: 13.3333px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-decoration: none; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px;" /><span style="-webkit-text-stroke-width: 0px; background-color: white; caret-color: rgb(46, 52, 54); color: #2e3436; display: inline !important; float: none; font-size: 13.3333px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-decoration: none; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px;">&nbsp;&nbsp; - a mini-game</span><br style="-webkit-text-stroke-width: 0px; background-color: white; caret-color: rgb(46, 52, 54); color: #2e3436; font-size: 13.3333px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-decoration: none; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px;" /><span style="-webkit-text-stroke-width: 0px; background-color: white; caret-color: rgb(46, 52, 54); color: #2e3436; display: inline !important; float: none; font-size: 13.3333px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-decoration: none; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px;">&nbsp;&nbsp; - a graphical or audio demoscene-type demo</span><br style="-webkit-text-stroke-width: 0px; background-color: white; caret-color: rgb(46, 52, 54); color: #2e3436; font-size: 13.3333px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-decoration: none; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px;" /><span style="-webkit-text-stroke-width: 0px; background-color: white; caret-color: rgb(46, 52, 54); color: #2e3436; display: inline !important; float: none; font-size: 13.3333px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-decoration: none; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px;">&nbsp;&nbsp;<span class="Apple-converted-space">&nbsp;</span></span><br style="-webkit-text-stroke-width: 0px; background-color: white; caret-color: rgb(46, 52, 54); color: #2e3436; font-size: 13.3333px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-decoration: none; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px;" /><span style="-webkit-text-stroke-width: 0px; background-color: white; caret-color: rgb(46, 52, 54); color: #2e3436; display: inline !important; float: none; font-size: 13.3333px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-decoration: none; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px;">There probably won't be any prizes.&nbsp; But there will definitely be an e-</span><span style="-webkit-text-stroke-width: 0px; background-color: white; caret-color: rgb(46, 52, 54); color: #2e3436; display: inline !important; float: none; font-size: 13.3333px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-decoration: none; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px;">mail and blog post about the entries.</span><br style="-webkit-text-stroke-width: 0px; background-color: white; caret-color: rgb(46, 52, 54); color: #2e3436; font-size: 13.3333px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-decoration: none; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px;" /><br style="-webkit-text-stroke-width: 0px; background-color: white; caret-color: rgb(46, 52, 54); color: #2e3436; font-size: 13.3333px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-decoration: none; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px;" /><span style="-webkit-text-stroke-width: 0px; background-color: white; caret-color: rgb(46, 52, 54); color: #2e3436; display: inline !important; float: none; font-size: 13.3333px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-decoration: none; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px;">I'd love to see y'all participate. Feel free to e-mail me at spk121@yahoo.com if you'd like to discuss anything directly.</span></span></p><p><span style="font-family: inherit;"><span style="-webkit-text-stroke-width: 0px; background-color: white; caret-color: rgb(46, 52, 54); color: #2e3436; display: inline !important; float: none; font-size: 13.3333px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-decoration: none; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px;">And please forward this info along, if you know of any other corners of the internet that might be interested. </span><span style="-webkit-text-stroke-width: 0px; background-color: white; caret-color: rgb(46, 52, 54); color: #2e3436; display: inline !important; float: none; font-size: 13.3333px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-decoration: none; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px;"></span><br style="-webkit-text-stroke-width: 0px; background-color: white; caret-color: rgb(46, 52, 54); color: #2e3436; font-size: 13.3333px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-decoration: none; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px;" /><br style="-webkit-text-stroke-width: 0px; background-color: white; caret-color: rgb(46, 52, 54); color: #2e3436; font-size: 13.3333px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-decoration: none; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px;" /><span style="-webkit-text-stroke-width: 0px; background-color: white; caret-color: rgb(46, 52, 54); color: #2e3436; display: inline !important; float: none; font-size: 13.3333px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-decoration: none; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px;">Regards,</span><br style="-webkit-text-stroke-width: 0px; background-color: white; caret-color: rgb(46, 52, 54); color: #2e3436; font-size: 13.3333px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-decoration: none; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px;" /><span style="-webkit-text-stroke-width: 0px; background-color: white; caret-color: rgb(46, 52, 54); color: #2e3436; display: inline !important; float: none; font-size: 13.3333px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-decoration: none; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px;">Mike Gran</span><br style="-webkit-text-stroke-width: 0px; background-color: white; caret-color: rgb(46, 52, 54); color: #2e3436; font-size: 13.3333px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-decoration: none; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px;" /><br style="-webkit-text-stroke-width: 0px; background-color: white; caret-color: rgb(46, 52, 54); color: #2e3436; font-size: 13.3333px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-decoration: none; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px;" /><br style="-webkit-text-stroke-width: 0px; background-color: white; caret-color: rgb(46, 52, 54); color: #2e3436; font-size: 13.3333px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-decoration: none; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px;" /><br /></span></p>Mikehttp://www.blogger.com/profile/00699531526967964528noreply@blogger.com0tag:blogger.com,1999:blog-14978667.post-49254571460834573922018-07-30T08:09:00.001-07:002018-07-30T08:09:33.865-07:00On the Joys and Perils of YouTubeFor want of a social aspect to my technology addiction, of late I have been recording video content and placing it on YouTube.&nbsp; It has been an interesting endeavor, because it involves skills that I heretofore have never trained.&nbsp; How does one look good on camera?&nbsp; What does one do with one's hands?&nbsp; What it the efficient way to record and edit video.&nbsp; What is the right way to do lighting and audio?&nbsp; It has been fun so far, largely because the videos I've recorded still look so amateurish.&nbsp; That I will be able to learn and progress at something new enchants me.<br /> <br /> YouTube is an amazing platform, and the result of untold man-years of effort. The voice recognition involved in the automatic closed captioning is impressive.<br /> <br /> But as any graybeard GNU-ster will attest, placing you content solely in the hands of a faceless evil corporation like Google is unwise, since I am not their customer.&nbsp; Their advertisers are their customers, and their users are just free content creators and a source of training data for their AI.&nbsp; So, in parallel, I've been revisiting the idea of resurrecting my website.<br /> <br /> It is a somewhat overwhelming idea for me because there are infinite possibilities.&nbsp; I could (and should) just do a WordPress instance and call it a day, for that would be efficient, but, I would love to take the opportunity to learn something new.<br /> <br /> Over the weekend, I enumerated my many sources of internet content.&nbsp; So far, I've discovered<br /> <ul> <li>YouTube</li> <li>Twitter </li> <li>A code blog on Blogger</li> <li>A personal website, hosted by a hosting provided, that is never updated</li> <li>Another personal website that is just a parked domain right now </li> <li>Yet another personal website, on my home PC, that is rarely updated</li> <li>A security camera</li> </ul> Over a weekend's pondering, I have decided that I will keep three projects, and that each of these will just be different skins on the same content.<br /> <ul> <li>The true content backend -- not publicly visible -- which will be the source.&nbsp; Video, images, audio will be stored in their native resolution and formats</li> <li>A website.&nbsp; It will be GNU-friendly.&nbsp; No weird javascript.&nbsp; Video will be medium resolution to split the difference quality and download time.&nbsp; Probably 720p Ogg+Theora+Vorbis.&nbsp; Audio will be Ogg+Vorbis or MP3.&nbsp; Images will be JPEG.</li> <li>YouTube. </li> <li>A gopher server where the 1990s will live on forever.&nbsp; Video will be shrunk to 352x288 pixel MP4 or CIF-sized 3gp+h.263+AMR_NB.&nbsp; Audio will be MP3.&nbsp; Images will be 640x480 GIF.</li> </ul> I will probably end up with a LAMP instance with Python/Django or whatever because hosting VMs like that.<br /><br /> ---<br /> <br /> In my personal archaeology, I also found these projects that are not externally visible or not working<br /> <ul> <li>An instance of the never-completed telnet PupperBBS, which has no content</li> <li>A real-time chat service called Jozabad</li> <li>A shoutcast/icecast server that has been serving up the same song for who knows how long</li> </ul> Mikehttp://www.blogger.com/profile/00699531526967964528noreply@blogger.com0tag:blogger.com,1999:blog-14978667.post-78443554231513765612018-01-25T21:38:00.000-08:002018-01-25T21:38:21.451-08:00The Ridiculous Gopher Project: BBSs and ZModemIn the previous entry, I talked about the ridiculous Gopher project, in which I might try to make a presence for myself in Gopher Space.<br /> <br /> So my first though was that I would have a blog and a webgallery over gopher.<br /> <br /> The blog entries are a very simple prospect, since they need to be plain text.&nbsp; I don't really like the block paragraph style, but, I did sketch out a conversion from markdown to troff to text that does some nice formatting.<br /> <br /> The directory of the blog entries is a bit more complicated.&nbsp; I had an idea for a cgi that handled directory structures and indices that are date-based with a parallel directory structure and index that is keyword based.<br /> <br /> But anyway, I got stuck on my first step, and fell down a rabbit hole, as per usual.<br /> <br /> So I thought to myself, what if I wanted to have comments for my gopher blog?&nbsp; How would that work?&nbsp; What technology would I used?&nbsp; Well, in the original Gopher spec, there is a capacity for a Telnet session.&nbsp; I thought that I could make a tiny Telnet-based BBS with just enough functionality to let one leave a comment or read comments.<br /> <br /> So I went on the internet to find a tiny BBS to examine.&nbsp; I found just about the simplest BBS one could imagine.&nbsp; It is called Puppy BBS. <br /> I found it in here: <a href="http://cd.textfiles.com/simtel/simtel20/MSDOS/FIDO/.index.html" rel="nofollow">http://cd.textfiles.com/simtel/simtel20/MSDOS/FIDO/.index.html</a><br /> <br /> So there this California-based guy named Tom Jennings who does a lot of stuff in the intersection between tech and art. Once upon a time he was a driving force behind FidoNet, which was a pre-internet community of dial-up BBSs. He's done many cool things since FidoNet.<br /> <br /> Check out his cool art at <a href="http://www.sensitiveresearch.com/" rel="nofollow">http://www.sensitiveresearch.com/</a><br /> <br /> I guess Tom wrote PuppyBBS as a reaction to how complicated BBSs had become back in the late 1980s.<br /> <br /> So I thought, hey, does this thing still build and run? Well, not exactly. First off, it uses a MS-DOS C library that handles serial comms, which, of course, doesn't work on Microsoft Windows 10 or on Linux. And even if that library did still exist, I couldn't try it even if I wanted to. I mean, if I wanted to try it I would need two landlines and two dial-up modems so I could call myself. I do have a dial-up modem in a box in the garage, but, I'm not going to get another landline for this nonsense.<br /> <br /> Anyway, I e-mailed Tom and asked if I could hack it up and post it on Github, and he said okay. And so this is what this is <a href="https://github.com/spk121/puppybbs">PuppyBBS</a>.<br /> <br /> Puppy BBS has four functions:<br /> <ul> <li>write messages</li> <li>read messages</li> <li>upload files</li> <li>download files</li> </ul> From there, I started writing a Telnet-based BBS, which <a href="https://github.com/spk121/pupperbbs">PupperBBS</a>.&nbsp; And that went pretty well.&nbsp; It took very little time to get the message reading and writing running.&nbsp; I was on a roll, so I decided that I would quickly tackle the other two functions that PuppyBBS had: uploading and downloading files.&nbsp; And that was where it all got complicated.<br /> <br /> PuppyBBS used <a href="https://en.wikipedia.org/wiki/XMODEM">XModem</a> for file transfer, because it was the 80's and that was what people did.&nbsp; But I thought ZModem, which was faster and more reliable, would be the way to go.&nbsp; So, I thought I'd just link a zmodem library to the BBS and I'd be ready to go.<br /> <br /> But, I couldn't find a zmodem library that was ready to go.&nbsp; All zmodem code seems to be derived for lrzsz, so I downloaded the code from lrzsz and made it into a library.&nbsp; To do that, I had to understand the code, so I tried to read it.&nbsp; That code is so very 1980s.&nbsp; It is terrible, so I had to fix it.<br /> <br /> (Let the record show that by "terrible" I mean terrible from a reader's point of view.&nbsp; It was written with so much global state and no indication of which procedures modify that state.&nbsp; There is no isolation, no separation of concerns.&nbsp; As a practical matter, it works great.)<br /> <br /> And that led to a full week of untangling it all, which is what became <a href="https://github.com/spk121/libzmodem">the libzmodem library</a>.&nbsp; Now my libzmodem isn't really much more readable than the original code, but, at least it makes more sense to me.<br /> <br /> Great, now I linked libzmodem to PupperBBS to add some ZModem send and receive functionality.&nbsp; Now to test it.&nbsp; I set up PupperBBS.&nbsp; I telnetted in to the system, got to the BBS, and tried to upload and download some files.&nbsp; It became apparent that for ZModem to work, the telnet program itself has to have some parnership with rz and sz, launching one or the other as appropriate.<br /> <br /> Since this had to have worked in the past, some internet searches led me to <a href="http://zssh.sourceforge.net/">zssh on sourceforge</a>&nbsp; . zssh has a telnet program that has a built-in zmodem send and receive functionality.&nbsp; Unfortunately, it wasn't packaged on Fedora didn't compile out of the box, so I started trying to understand it and fix it.<br /> <br /> So, anyway to summarize:<br /> <ol> <li>Let's do a Gopher blog!</li> <li>How do you do comments?</li> <li>Telnet works on Gopher!</li> <li>Let's make a BBS</li> <li>BBS's do Zmodem</li> <li>Let's make a ZModem library</li> <li>Let's make a Telnet client that does ZModem.</li> </ol> And this is why I never finish anything.Mikehttp://www.blogger.com/profile/00699531526967964528noreply@blogger.com0tag:blogger.com,1999:blog-14978667.post-20526709661606569412018-01-04T15:10:00.000-08:002018-01-04T15:14:31.259-08:00The ridiculous gopher projectMy primary New Year's Resolution for 2018 is to start no new projects, and to only finish old ones.&nbsp; In looking over my repos&nbsp; -- more aptly titled the graveyard of 1,000 Saturdays -- I have excavated a couple of projects from the earth.<br /> <br /> I'm starting, for now, with what is one of the most ridiculous of all possible projects: a gopher-protocol blog.&nbsp; Do you remember <a href="http://sdf.org/?tutorials/gopher">gopher</a>?&nbsp; It was a protocol and a network ecosystem that existed just before HTTP took over the world.&nbsp; I presented the world as directories that contained files, and users could poke around and look at those files to their heart's content.<br /> <br /> There is a reason that I'm nostalgic for those days, and it lies primarily in how all of the world of HTTP and the world of iPhone and Android applications are really data-mining spy operations.&nbsp; The gopher protocol is too primitive to allow the wholesale data mining operations that the modern web has become.&nbsp; I has no client side scripting and cookies.&nbsp; And because the world of gopher is so strange and hard to reach, there is a bit of a pioneer mindset among aficionados<br /> <br /><div class="separator" style="clear: both; text-align: center;"> <a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi3uvyiHpZL_ygl4t7ed8yzCus_gjB_b7hqcWe-gyKq81Rklg3ja1V6t-bfAcEWgayEtVmhtEHhNc9wf2El_4fYAdmuKtnOb6e1kTyDTq_CaxNgaeqyKguG2yhkEYq1112ogj8/s1600/goph.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="272" data-original-width="524" height="166" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi3uvyiHpZL_ygl4t7ed8yzCus_gjB_b7hqcWe-gyKq81Rklg3ja1V6t-bfAcEWgayEtVmhtEHhNc9wf2El_4fYAdmuKtnOb6e1kTyDTq_CaxNgaeqyKguG2yhkEYq1112ogj8/s320/goph.png" width="320" /></a></div> <br /> So yeah, gopher.&nbsp; A big directory of files of the types on the following list.&nbsp; Take a look at this table of filetypes that Gopher handles natively. <br /> <br /> <br /> <table> <tbody> <tr> <th>Itemtype</th> <th>Content</th> </tr> <tr><td>0</td><td>Text file</td></tr> <tr><td>1</td><td>Directory</td></tr> <tr><td>5</td><td>PC binary</td></tr> <tr><td>6</td><td>UNIX uuencoded file</td></tr> <tr><td>8</td><td>Telnet Session</td></tr> <tr><td>9</td><td>Binary File</td></tr> <tr><td>g</td><td>GIF image</td></tr> <tr><td>s</td><td>Sound</td></tr> <tr><td>I</td><td>Image (other than GIF)</td></tr> <tr><td>0</td><td>Text file</td></tr> </tbody></table> <br /> Pretty old school, eh?&nbsp; Just feel the power of the 1990s.<br /> <br /> There are a lot of people running blogs in Gopher.&nbsp; Really they just are directories of plain text files, ordered by date.&nbsp; It is very pure, but, slightly boring.&nbsp; So I looked at that list and asked myself if I could create a <i>modern</i> (lol) Gopher blog engine.<br /> <br /> You can, of course, write servers that push out dynamic-generated content, but the clients only receive these static files.&nbsp; Do you remember back when Perl5 was the way one would write CGI scripts that created "dynamic" HTML?&nbsp; You can to the same thing here: make CGI scripts that create text files or GIF images.<br /> <br /> In my conception, a modern gopher weblog engine would have text files of blog entries, a gallery of GIFs, and a commenting system.&nbsp; Lacking any other gopher available method, the commenting system would be a Telnet session.<br /> <br /> So I have picked up a couple of old ideas: a weblog software with a Gopher interface, a web gallery with a Gopher interface, and a tiny Telnet BBS where people can leave comments.&nbsp; I've (re)started with the BBS, because it is the most ridiculous.Mikehttp://www.blogger.com/profile/00699531526967964528noreply@blogger.com0tag:blogger.com,1999:blog-14978667.post-34401113561249630722018-01-01T21:40:00.003-08:002018-01-01T21:40:37.672-08:00Writing as little as possibleMy New Year's Resolution for 2018 is to start no new projects.&nbsp; For 2018, I will only finish my many, many uncompleted projects.<br /> <br /> I've started up with one of my most pointless coding projects: a telnet BBS.&nbsp; Writing a BBS in the late 1980's and early 1990's was something of a rite of passage.&nbsp; Much like writing your own blog software was in the late 1990's and 2000's.<br /> <br /> But going back to the idea of <b>finishing things</b>, I've given myself some additional constraints.<br /> <ul> <li>Write as little code as possible. </li> <li>Use common libraries and components sensibly and liberally.</li> <li>Bend my concept to the strengths and constraints created by the libraries and components, instead of wrangling them into matching my vision.</li> </ul> This ends up being very hard to do.&nbsp; To be specific, it is very difficult to quash my ego and perfectionism; that perfectionism is why my repo has two dozens projects, of which only three are functional.<br /> <br /> One of the forces that pushes me to write my own code, instead of using other people's code, is that reading and understanding other people's code and documentation is hard and it doesn't feel like an accomplishment.&nbsp; To properly use another library, one really does need to put in the work of reading the docs and understanding their logic, which is deeply unsatisfying. <br /> <br /> Will 2018 be the year I recover from Incompletion Syndrome?&nbsp; Time will tell.<br /> <br />Mikehttp://www.blogger.com/profile/00699531526967964528noreply@blogger.com0tag:blogger.com,1999:blog-14978667.post-75073158474292563812017-10-30T12:09:00.000-07:002017-10-30T12:09:03.210-07:00CouchsurfingOne of the best decisions I've made over the last decade is to participate in Couchsurfing. Couchsurfing is generically letting travelers stay in your home for free, just for the experience of meeting people.&nbsp; Couchsurfing is also specifically the corporation that runs the couchsurfing.com website and its associated app.&nbsp; There are other websites that facilitate traveler hosting, such as Warm Showers.<br /> <br /> Key to the couchsurfing.com implementation of the idea is a rating/reviewing system and the idea of preserving one's reputation.&nbsp; The backpackers comment on the places they've stayed.&nbsp; The hosts comment on the people that have stayed with them.&nbsp; A reputation is built up, and, hopefully, safety and civility for hosts and guests is ensured by the online reputation system.&nbsp; To be honest, it all works quite well.&nbsp; I've had only one bad experience out of the three dozen groups that have stayed with me.<br /> <br /> But there absolutely have been tragic events associated with couchsurfing: theft, sexual assault, and a couple of murders have occurred, as well as a not insignificant amount of douchebaggery that surrounds creepy guys interacting with single women.&nbsp; But for experienced guests and hosts, I would wager that the safety and security is much greater than other interactions that one has with strangers.<br /> <br /> Thinking about all of the current discussions that swirl about about power dynamics, sexual assault, the gig economy, toxic masculinity, and tech, I have put some thought into why couchsurfing.com hasn't degenerated into a complete nightmare like most online communities tend to do.&nbsp; My conclusion is that power dynamics are weak.&nbsp; I, as a host, don't particularly fear couchsurfing.com the website.&nbsp; If they are rude to me, I'll just quit.&nbsp; If putting up people in my home became inconvenient, I would just quit.&nbsp; The people that stay with me, if they didn't like me, there are tens of thousands of hotel rooms in the city they could go to.&nbsp; There is so little gain or loss to be had by participating.&nbsp; The idea requires, at least on the part of the host, a sense of altruism.<br /> <br /> But then again, participating in free software and open source also requires a sense of altruism on the part of the volunteers, yet it doesn't always achieve the same community spirit.<br /> <br /> One thing I like about backpacker communities vs free software communities is that there is greater freedom of religion in backpacker communities.&nbsp; When I head off to mass on Sunday, my guests never ridicule me.&nbsp; They are there for intercultural exchange, so when someone does something out of the world urban normal, it is odd and interesting.&nbsp; I have never confessed to be a church-goer in a free software context.&nbsp; I fear the consequences.<br /> <span style="font-size: x-small;"><br /></span> <span style="font-size: x-small;">(On couchsurfing.com, they claim there are 70,000 hosts in Los Angeles.&nbsp; This is a lie.&nbsp; There are about 300 active hosts and they are hammered with requests daily.)</span><br /> <br /> <br /> <br />Mikehttp://www.blogger.com/profile/00699531526967964528noreply@blogger.com1tag:blogger.com,1999:blog-14978667.post-45159242331947244332017-10-11T10:00:00.000-07:002017-10-11T10:00:24.482-07:0010/11/2017One of my favorite pastimes is imagining and planning to write new coding projects: researching technologies, checking out libraries I might use, making GUI mockups, downloading similar projects.<br /> <br /> I was thinking the other day that it might be fun to create a desktop-based editor that had an HTTP server embedded.&nbsp; The HTTP server would serve up only one document, which is the document being currently edited, and it would show a live representation of the screen as being show the person editing the document.<br /> <br /> I was thinking it might be fun to re-implement the old HyperCard system.<br /> <br /> I was thinking that it might be fun to make a real-time chat client/server, like the old talkd daemon did on consoles back in the day.&nbsp; The client would show every character being typed, in real time, instead of line by line.<br /> <br /> I was thinking it might be fun to make a collaboratively editable mosaic: a million tiles across by a million tiles wide, where each tile is 16 pixels square.&nbsp; Anyone could make new tiles and could place them anywhere on the grid.<br /> <br /> I was thinking that it might be fun to make a webpage whose primary purpose was to annoy the server operator.&nbsp; The webpage would have buttons to make silly noises on the server machine, and the webcam on the server machine would capture pictures of the operator being annoyed and place them on the webpage.<br /> <br /> I was thinking it would be fun to make a Twitter bot, that automatically searches for and retweets controversial statements, but, changing key words to make them more benign and playful.<br /> <br /> I was thinking that it might be fun to make a Christian devotional app that keeps the list of the ~600 New Testament commandments and chooses one at random for someone to follow on any given day.&nbsp; Also it could chime for Matins, Sext, Vespers, and Compline.<br /> <br /> I was thinking it might be good to make an app for depressed and despairing people. Upon logging in, you could write about your struggle, and after submitting, you'd receive an anonymized note that someone else had written about their struggle.<br /> <br />Mikehttp://www.blogger.com/profile/00699531526967964528noreply@blogger.com0tag:blogger.com,1999:blog-14978667.post-58620417405994433052017-09-25T10:55:00.000-07:002017-09-25T10:58:27.135-07:009/25/17For work, I have a project that requires a C++ program on Windows 10 that compiles without any library dependencies except the C++14 standard library and the Win32 API only when the C++ standard library lacks necessary functionality. Standard C++ has no fork/exec or spawn, so that is one area when I'm using the Win32 API. &nbsp; It is a very strange API that is usually abstracted away using CoreFX .NET classes.&nbsp; I'm rarely this close to Win32 metal.&nbsp; But I'm beginning to understand why Cygwin's fork/exec are so odd.<br /> <br /> --<br /> <br /> So I'm fat. I'm probably about the median weight by USA standards, but, I'm still overweight in a BMI sense.&nbsp; Of course almost all USA men have a BMI above the recommended 25.1 or whatever.<br /> <br /> But I once had an eating disorder.&nbsp; When I was young, I basically starved myself.&nbsp; As part of my recovery from that, I've had to change my thinking completely.&nbsp; I stopped letting myself be concerned about what my weight was or what I was eating.&nbsp; Whenever I find myself worrying to much about food or weight, I tell myself that I am not allowed to concern myself with that, and I don't let myself think about it.<br /> <br /> But now I've decided to lose some weight.&nbsp; To avoid going off the rails, I'm trying to find some non-subjective metrics about weight, so that I don't have to trust the evidence of my (anorexic, lying) eyes.<br /> <br /> That lead me into some interesting research on what shape American men used to be, before the obesity epidemic.&nbsp; And some of the best metrics for men, and what shape men used to be, is from the US Department of Defense.<br /> <br /> <a href="http://everyspec.com/DoD/DoD-HDBK/DOD-HDBK-743A_16856/">DOD-HDBK-743A (1991) "Anthropometry of U.S. Military Personnel"</a> and Technical Report 72-51-CE (1971) "The Body Size of Soldiers: U.S. Army Anthropometry: 1966" are a deep dive into the length, breadth, and circumference of every part of a man.&nbsp; The difference between then and now is astounding.<br /> <br /> <br />Mikehttp://www.blogger.com/profile/00699531526967964528noreply@blogger.com0tag:blogger.com,1999:blog-14978667.post-11687674579571222812017-09-22T13:42:00.000-07:002017-09-22T13:42:10.696-07:009/22/17In digging through the ASIO C++ library examples, I came across an actual use of <a href="http://en.cppreference.com/w/cpp/utility/functional/bind"><span style="font-family: &quot;Courier New&quot;,Courier,monospace;">std::bind</span></a>. Its entry in cppreference seemed like buzzword salad, so I never previously had paid it any attention.<br /> <br /> But in ASIO, they use std::bind to create functions from class methods and associated data.&nbsp; The functions get passed to its async driver.&nbsp; So if I liken the output of std::bind to a sort of closure that returns a procedure, it makes sense to me.<br /> Mikehttp://www.blogger.com/profile/00699531526967964528noreply@blogger.com0tag:blogger.com,1999:blog-14978667.post-64984251672023993302017-09-20T10:48:00.001-07:002017-09-20T10:48:40.969-07:009/20/2017On my birthday, I kayaked the sea caves on Santa Cruz island, which was fun.<br /> <br /> I've been quite depressed lately: my exercise regimen has faltered.<br /> <br /> I'm glad to find that one can use <a href="https://think-async.com/Asio">ASIO</a> as a header-only package without installing all of Boost.Mikehttp://www.blogger.com/profile/00699531526967964528noreply@blogger.com0tag:blogger.com,1999:blog-14978667.post-12843089219954340492016-11-05T22:02:00.003-07:002016-11-05T22:02:51.019-07:00Movin' on up to the TopMaybe it was the death of Pieter Hintjens, or maybe just (late) middle age that has me mentally reviewing the type of programming that I’ve done and how I’ve gone about it.<br /> <br /> But here’s the thing: I remember&nbsp;paper tape and VT420s and CP/M and 8" floppies.&nbsp; I am a dinosaur.<br /> <br /> When I started programming, I started with the high-level language of the 1980s: plain old C.&nbsp; And I did it on the high-level platforms of the day: MS-DOS and UNIX. This was a great choice, in hindsight, because after 30 years, I’m still programming on C in UNIX-like systems.<br /> <br /> But as technology advanced, my niche, which was once the top level of the stack -- CLI programs of the old UNIX philosophy – is now basically two levels up from the bottom.&nbsp; And many, many layers have been built atop the layer where I make my living.<br /> <br /> I’m down in the weeds, so to speak.&nbsp; And as a consequence, none of my non-tech friends have ever understood what I do because there is nothing I can show them that has any connection to their understanding of technology: phone apps, webpages, or desktop applications.&nbsp; Talking about DO178B or writing device drivers at dinner is a bit of a snoozefest.<br /> <br /> There’s another thing that has held me down in the weeds: free software.&nbsp; For most of my career I’ve been working in free software: GNU, GCC, Linux.&nbsp; It places a high value on stability.&nbsp; I have programs that I've been maintaining for over a decade with not a huge amount of effort.&nbsp; That stability is so comforting.<br /> <br /> Maybe it might be fun to climb my way back to the top of the stack: this highest level languages and toolkits.&nbsp; In the GUI space, the amount of churn is rather amazing, but, then again, the amount of churn in the UX patterns form factors is also very high.<br /> <br /> I'm not really sure what is at the top of the stack&nbsp;these days.&nbsp; I did some searching.<br /> <br /> Likely the highest level toolkit and language out there right now is Unity, but, it is a bit specialized for the game space.<br /> <br /> The highest level language out there right now is undoubtedly Perl 6, but, its GUI toolkit hooks seem to be rather raw.<br /> <br /> For Windows 10, C#&nbsp;on UWP is probably the winner.<br /> <br /> Among the maintained languages for the GTK/Gnome stack, the high level language is probably Python.&nbsp;&nbsp;Among the maintained languages for the&nbsp;Qt stack, is it QML and C++. <br /> <br /> I don't know much about mobile, but, Android seems to be C# via Xamarin, and iOS&nbsp;is Swift.<br /> <br /> In the web space, it is obviously JavaScript of some description. I have no clue what the top level GUI toolkit is.&nbsp; Maybe it is the React JavaScript library.&nbsp; As for the language itself, plain old JavaScript seems to be coming back in fashion.&nbsp; The back end is mysterious.&nbsp; It used to be Java.&nbsp; Now it seems to be one of a dozen languages and rail-like things.<br /> <br /> After Unity, Qt seems to be the most multiplatform native toolkit, with HTML5 being the most multiplatform of all.<br /> <br /> The real question is, if I wanted to write a stupid program that my friends could run, what platform would it be?<br /> <br /> HTML5 would be the best, followed by native mobile, followed by desktop Windows 10. It is a shame that the HTML5 development experience is such a mess.<br /> <br /> It is interesting how there is so much fragmentation in the high level. I wonder how many of these toolkits will still be relevant in five years?&nbsp; Microsoft toolkits have the highest level of churn. Remember WinForms or XNA?<br /> <br /> Maybe I should stick with Unix-like CLI in C, where I belong.<br /> <br /> What do you think?&nbsp; Do you have a different opinion on what is the high-level language and toolkit on your favorite platform?<br /> <div style="margin: 0px 0px 11px;"> <br /></div> Mikehttp://www.blogger.com/profile/00699531526967964528noreply@blogger.com0tag:blogger.com,1999:blog-14978667.post-74000557074505083622016-10-29T12:49:00.000-07:002016-10-29T12:49:14.103-07:00guile-aspell 0.3 releasedI am&nbsp;pleased to announce&nbsp;an update of guile-aspell, which is a library for comparing a string against a dictionary and suggesting&nbsp;spelling corrections. It is in the <a href="http://www.gnu.org/s/guile">GNU Guile</a> dialect of the Scheme programming language.&nbsp; It is based on the aspell library.<br /> <br /> The webpage for the library is at <a href="http://lonelycactus.com/guile-aspell.html" id="yui_3_16_0_ym19_1_1477267441013_24319" target="_blank">http://lonelycactus.com/guile-aspell.html</a><br /> <br /> The development tree is at <a href="https://github.com/spk121/guile-aspell/" id="yui_3_16_0_ym19_1_1477267441013_24308" target="_blank">https://github.com/spk121/guile-aspell/</a><br /> <br /> The latest source archive is at <a href="http://lonelycactus.com/tarball/guile_aspell-0.3.tar.gz" id="yui_3_16_0_ym19_1_1477267441013_24312" target="_blank">http://lonelycactus.com/tarball/guile_aspell-0.3.tar.gz</a><br /> <br /> The NEWS for this release is<br /> - move to FFI bindings<br /> - drop Guile 1.8 support<br /> <br /> There is no mailing list per se, but, you can contact the project either via <a href="https://github.com/spk121/guile-aspell/issues" id="yui_3_16_0_ym19_1_1477267441013_24313" target="_blank">https://github.com/spk121/guile-aspell/issues</a>&nbsp;or by e-mailing me directly at <a href="https://www.blogger.com/null" ymailto="mailto:spk121@yahoo.com">spk121@yahoo.com</a><br /> <br /> Thanks,<br /> Mike Gran<br /> <b></b><i></i><u></u><sub></sub><sup></sup><strike></strike><br />Mikehttp://www.blogger.com/profile/00699531526967964528noreply@blogger.com0tag:blogger.com,1999:blog-14978667.post-64332760487699991072016-10-23T19:01:00.002-07:002016-10-23T19:01:15.890-07:00guile-curl v0.4 releasedI am&nbsp;pleased to announce&nbsp;an small update of guile-curl, which is a library for fetching files by URL from the internet in the <a href="http://www.gnu.org/s/guile">GNU Guile</a> dialect of the Scheme programming language.&nbsp; It supports many protocols, such as https, ftp, tftp, and, most importantly,&nbsp;gopher.<br /> <br />The webpage for the library is at <a href="http://lonelycactus.com/guile-curl.html" id="yui_3_16_0_ym19_1_1477267441013_24319" target="_blank">http://lonelycactus.com/guile-curl.html</a><br /> <br />The development tree is at <a href="https://github.com/spk121/guile-curl/" id="yui_3_16_0_ym19_1_1477267441013_24308" target="_blank">https://github.com/spk121/guile-curl/</a><br /> <br />The latest source archive is at <a href="http://lonelycactus.com/tarball/guilecurl-0.4.tar.gz" id="yui_3_16_0_ym19_1_1477267441013_24312" target="_blank">http://lonelycactus.com/tarball/guilecurl-0.4.tar.gz</a><br /> <br />The NEWS for this release is<br />- support for READDATA callbacks<br />- bug fixes, especially with respect to garbage collection on newer versions of Guile.<br /> <br />There is no mailing list per se, but, you can contact the project either via <a href="https://github.com/spk121/guile-curl/issues" id="yui_3_16_0_ym19_1_1477267441013_24313" target="_blank">https://github.com/spk121/guile-curl/issues</a>&nbsp;or by e-mailing me directly at <a href="https://www.blogger.com/null" ymailto="mailto:spk121@yahoo.com">spk121@yahoo.com</a><br /> <br />Thanks,<br />Mike Gran<br /><b></b><i></i><u></u><sub></sub><sup></sup><strike></strike>Mikehttp://www.blogger.com/profile/00699531526967964528noreply@blogger.com0tag:blogger.com,1999:blog-14978667.post-12758864475845462252016-10-02T09:40:00.000-07:002016-10-02T09:40:50.016-07:00The Bug ReportSo I get a bug report. It is on GNU/Linux, of course, because that is the only ecosystem that sends bug reports.<br /> <br /> So first I boot up my work box (Computer #1, Windows 10) which is the one that has the sweet monitor and try to VPN to the Server box (Computer #2, GNU/Linux Fedora Server, amd64).&nbsp; But, of course, at one point I'd stripped all the non-console-mode functionality off of the server, so VPN is a fail.&nbsp; I could have done the fix easily via ssh and emacs-nox, but, I figure it will only take a minute to get a graphical environment up and running.<br /> <br /> There's a GNU Linux VM running on VirtualBox on the work box, but, I get distracted from the actual problem when I can't figure out how to get VirtualBox to create a large screen.&nbsp; Totally not a problem, but, I get obsessed with this minutiae and can't let it go. I waste time tweaking the virtual graphics card settings with no effect.<br /> <br /> So then I boot up the old linux box (Computer #3, GNU/Linux Fedora Workstation). It is 64 bit, but, it is running the i686 distro for reasons lost to history.&nbsp; And then I remember that when I upgraded my wireless router, it stopped connecting via USB-connected Wifi. There are wpa_supplicant errors. Don't know why.&nbsp; Spent a couple of hours trying to make it work.<br /> <br /> Thus, I drag the old linux box to the room with the router so I can plug it in directly.&nbsp; The only table is covered in padlocks, bottles of sunscreen, beads, jars of coins, and multiple Rubik's Cubes.&nbsp; I clear a space.<br /> <div class="separator" style="clear: both; text-align: center;"> <a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiPs8ScgEcnSDaCBA7Nz26N2n0yNOS9MyPXHR_M59xWQ4fthAE8_D_kP8cZlNgZs2qy_aQEeuI82wJ8O-wcNW9VorQLY4kHGfHBiUW0f_zcknqlC0YoMFmjD6lDh12-pMoCwQs/s1600/IMG_20161002_093238.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiPs8ScgEcnSDaCBA7Nz26N2n0yNOS9MyPXHR_M59xWQ4fthAE8_D_kP8cZlNgZs2qy_aQEeuI82wJ8O-wcNW9VorQLY4kHGfHBiUW0f_zcknqlC0YoMFmjD6lDh12-pMoCwQs/s320/IMG_20161002_093238.jpg" width="320" /></a></div> <br /> <br /> The power cable to the spare monitor has gone missing.&nbsp; It is a tiny HP w17e, but, still higher resolution than what I was getting from VirtualBox. &nbsp; I search for 20 minutes. Eventually steal the power cable from work box.&nbsp; My mostly ruined back complains when I shimmy under the desk to untangle it from the cable octopus.<br /> <br /> I boot up old linux box.&nbsp; Huh, it is only 100BaseT.&nbsp; I dutifully do a "dnf upgrade". 1404 packages to update.&nbsp; That takes another half hour.<br /> <br /> And thus, I've used up the four hours of Saturday morning time which is the only time I have to devote to personal hacking.&nbsp; Sorry bug reporter.&nbsp; I'm too stupid to work on your request, and the computer gods hate me.&nbsp; Better luck next week.<br /> <br />Mikehttp://www.blogger.com/profile/00699531526967964528noreply@blogger.com0tag:blogger.com,1999:blog-14978667.post-41153002845036385882016-07-12T06:45:00.000-07:002016-07-12T06:45:23.831-07:00Pip-Boy like terminal application in Guile, part 4: the terminalThis is the fourth in a series of articles where I try to recreate some Pip Boy like displays in <a href="http://www.gnu.org/software/guile/">GNU Guile</a> and <a href="https://www.gnu.org/software/guile-ncurses">ncurses</a>.<br /> <br /> <span style="font-size: x-small;">A Pip Boy is a fictional computer in the Fallout 4 computer games.&nbsp; GNU Guile is an implementation of the Scheme language.&nbsp; Ncurses is a library for creating text user interfaces on terminals like the Linux terminal, Xterm, or the Gnome Terminal.</span><br /> <br /> One of the iconic experiences in Fallout 4 is using the in-game computers, which are bulky, green screen monochrome terminals not unlike a DEC VT100.&nbsp; Actually a closer match is the Televideo TVI-912.&nbsp; Generally they are used in two ways: displaying a text block with some selectable links, or playing a hacking minigame.&nbsp; Today we'll look at the first.<br /> <div class="separator" style="clear: both; text-align: center;"> <a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiPI-GxFJ29EduFosy8LFhyglLgv6CJlGB4ysgYwQf6sh-5mngsk7yAZ5h-luD5pKKELk1Nq388_loX-5p7oDpZMlGzeXL198QVUYVL1nvSI8LElls8fe3iR886ROgC-NdO9I0/s1600/1821174_0.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="183" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiPI-GxFJ29EduFosy8LFhyglLgv6CJlGB4ysgYwQf6sh-5mngsk7yAZ5h-luD5pKKELk1Nq388_loX-5p7oDpZMlGzeXL198QVUYVL1nvSI8LElls8fe3iR886ROgC-NdO9I0/s320/1821174_0.jpg" width="320" /></a></div> <br /> The basic user experience is this:<br /> <ul> <li>When activated, the terminal will begin an animation where it is add adding text to the screen one glyph at a time at about ~75 characters per second.&nbsp; There is a tick sound associated with each glyph appearing on the screen.</li> <li>Clicking the mouse or pressing enter will interrupt this drawing animation and will make all the text appear on the screen.&nbsp; There is a tick sound associated with this.</li> <li>Once drawing is complete, any text surrounded by square brackets become a link.</li> <li>The first link is highlighted.</li> <li>Mousing over a link or using the arrow keys will move between links.&nbsp; There is a tick sound associated with moving between links.</li> <li>Clicking on a link or pressing enter will select the highlighted link and end the interaction.&nbsp; There is a sound associated with selection.</li> </ul> So, here there is user interaction, audio cues, time-based rendering.&nbsp; It actually is a fair bit of functionality, and it also is not too friendly to the paradigm provided by the ncurses toolkit.<br /> <div class="separator" style="clear: both; text-align: center;"> <a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjEotLgAd6vGb0MxP7NnVeDRcRoy_7Dg6G-5mrtWIvKXAPplEEfX6mJyAoAjSALkdHMqpHhgtai6PVf6xA9mwoBg5E5wJbYN5FkV2gFfyBnDAsCfvPtNC5AKu6Mz_SJ5AsIpss/s1600/fv1tY6w.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="180" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjEotLgAd6vGb0MxP7NnVeDRcRoy_7Dg6G-5mrtWIvKXAPplEEfX6mJyAoAjSALkdHMqpHhgtai6PVf6xA9mwoBg5E5wJbYN5FkV2gFfyBnDAsCfvPtNC5AKu6Mz_SJ5AsIpss/s320/fv1tY6w.jpg" width="320" /></a></div> <br /> <div class="separator" style="clear: both; text-align: center;"> <a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhlgOL8dvYHJUwFg62sE6TjPmWx9nKSg8waxx-6l9CbVyTJjCG9OlB3t-tEQOBrsETz3qiWzEpsq89u0nU68RJYKRPSTPGURfQD_Zk9ZCbaZ_kKx9a4CZ8bfowZT3Yuq7ZPxTs/s1600/350911300.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="180" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhlgOL8dvYHJUwFg62sE6TjPmWx9nKSg8waxx-6l9CbVyTJjCG9OlB3t-tEQOBrsETz3qiWzEpsq89u0nU68RJYKRPSTPGURfQD_Zk9ZCbaZ_kKx9a4CZ8bfowZT3Yuq7ZPxTs/s320/350911300.jpg" width="320" /></a></div> <br /> So I put together three different code units<br /> <ul> <li>a main event <a href="https://github.com/spk121/pip-tui/blob/master/pip-tui/tui-action.scm">loop</a></li> <li>glue code to allow interaction with <a href="https://github.com/spk121/pip-tui/blob/master/pip-tui/pulseaudio.scm">Pulseaudio</a></li> <li>and, the <a href="https://github.com/spk121/pip-tui/blob/master/pip-tui/tui-terminal.scm">tui-terminal</a> widget itself</li> </ul> As a side note, Guile has had a complete set of bindings to the multimedia enving GStreamer, which I wanted to use, but, it appears to be in need of some maintenance.&nbsp; I did look at it so see if I could patch it up, but, the binding is related to the Glib binding, and I didn't want to take the time to understand all that right now.&nbsp; Pulseaudio is much lower level, but, also much simpler.&nbsp; I had code lying around from some old game engine attempt.<br /> <br /> If you've coded in QT or GTK, you know that a central function of a GUI toolkit main loop is to allow each widget to send out notifications and to have other widgets be able to subscribe and react to these notifications.&nbsp; In QT, these are "signals" and "slots".&nbsp; In GTK they are "signals" and "signal handlers".<br /> To keep things somewhat simple, the primitive main loop works like this...<br /> <ul> <li>There are one or more event handlers. An event handler may have an associated widget.</li> <li>The main loop checks for an event in the queue: either a keypress, a mouse event, or a signal sent out by one of the widgets. If it finds an event, it sends it to all the event handlers.&nbsp; Every handler receives every event: there is no attempt to be precise.</li> <li>If no event is ready, the main loop sends an "idle" event to all the signal handlers, does a single step in Pulseaudio's main loop, and then sleeps for a few microseconds.</li> </ul> <br /> This is familiar territory.&nbsp; There's nothing new under the sun.<br /> <br /> I had to choose between letting Pulseaudio run its own event loop in its own thread, or to merge Pulseaudio's event look in to my main event loop.&nbsp; I chose the latter.<br /> <br /> Put together, it all looks like this.&nbsp; For the life of me, I cannot seem to record audio on my screengrab.&nbsp; I blame Wayland.<br /> <br /> <div class="separator" style="clear: both; text-align: center;"> <iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.blogger.com/video.g?token=AD6v5dxnnUnhs60-nD0VJY8UPmELtVm5B20T2-hzdYQlCglLKoYuR13UwzEb-pq6J-n_-sH25p9NcZLI6VQ' class='b-hbp-video b-uploaded' frameborder='0'></iframe></div> <br /> <br /> The code, in its current form, is <a href="http://github.com/spk121/pip-tui">here.</a>&nbsp; It is not ready for use.Mikehttp://www.blogger.com/profile/00699531526967964528noreply@blogger.com0tag:blogger.com,1999:blog-14978667.post-77176330080053504162016-06-12T09:17:00.000-07:002016-06-12T09:17:18.897-07:00A Pipboy-like terminal application in Guile: Part 3 - labels and progress barsSo, 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&nbsp; This is just for the nonsense of it, and the challenge.<br /> <br /> <span style="font-size: x-small;">FYI, Ncurses is a library for text user interfaces.&nbsp; Guile is an implementation of the Scheme programming language.&nbsp; And a Pip Boy is a fictional computer that appears in the Fallout video games.</span><br /> <div> <span style="font-size: small;"><br /></span></div> <div> In the first two parts of this little series of nonsense (<a href="http://lcinexile.blogspot.com/2016/06/a-pipboy-like-terminal-application-in.html">part 1</a>,&nbsp;<a href="http://lcinexile.blogspot.com/2016/06/a-pipboy-like-terminal-application-in_4.html">part 2</a>), 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.&nbsp; I pulled in two libraries, GNU Fribidi and GNU Libunistring, to create this procedure to wrap a string.&nbsp; So much coder's blood spilled to do something so apparently simple...&nbsp;</div> <div> <blockquote class="tr_bq"> <br /><span style="font-family: &quot;Courier New&quot;, Courier, monospace; font-size: x-small;">(define (string-render str tabsize n-cells alignment bidi)<br />&nbsp; "Given a string STR, this converts the string into a list of strings<br />with each string contining N-CELLS cells or fewer.&nbsp; Tabs are expanded<br />into TABSIZE spaces.&nbsp; Other Unicode spaces are replace with the common<br />space character.&nbsp; Any control characters are replaced with replacement glyphs.&nbsp; If alignment is 'left, lines are padded with spaces at the end of each string to take up N-CELLS.&nbsp; 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."</span></blockquote> </div> <div> <br /></div> <div> So anyway, I bashed out&nbsp;a couple of widgets.</div> <ul> <li>A "label" is some wrapped text in a box, possibly with a border</li> <li>A "progress bar" is short text followed by a colored bar whose length is a representation 0% to 100%.</li> </ul> <div> There isn't much to say about the code, which is <a href="https://github.com/spk121/pip-tui">here</a>.&nbsp; It is all very rough and boring and workman-like and verbose.&nbsp; To render these widgets, I settled on an outside-in drawing model.</div> <ol> <li>The ncurses panel's size is determined first.</li> <li>Any border is on the outside edge of the panel, reducing the available window size by 1 on all four sides.</li> <li>Inside of that is a user-defined padding width.</li> <li>What remains inside of that is available for content.</li> </ol> <div class="separator" style="clear: both; text-align: center;"> <a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgED-FVeQNxRZ5dLe319ri29VbPw93TifH48X7mbGHt1eiJX9CwfHQ-D4_5KkfZnp3mmxtRZtzYZzemzzflLaB3TMSmA776QcAWe4ZPDzwZtbxJ7u9BbqpZvac-VRMpkFlinJ4/s1600/IMG_20160612_074644.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="246" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgED-FVeQNxRZ5dLe319ri29VbPw93TifH48X7mbGHt1eiJX9CwfHQ-D4_5KkfZnp3mmxtRZtzYZzemzzflLaB3TMSmA776QcAWe4ZPDzwZtbxJ7u9BbqpZvac-VRMpkFlinJ4/s320/IMG_20160612_074644.jpg" width="320" /></a></div> <div> <br /></div> <br /> Here's more&nbsp;Unicode and xterm trivia, which excites me because I am a weirdo.<br /> <h4> Boxes</h4> There are a few usable sets of border drawing characters.&nbsp; These should be well aligned if you have a proper monospace font in your browser.<br /> <br /> <span style="font-family: &quot;Courier New&quot;, Courier, monospace;">;; Light box<br />;; ┌─┐<br />;; │ │<br />;; └─┘<br />(define *box-chars-light* "┌─┐│ │└─┘")<br />;; Light round box<br />;; ╭─╮<br />;; │ │<br />;; ╰─╯<br />(define *box-chars-rounded* "╭─╮│ │╰─╯")<br />;; Heavy box<br />;; ┏━┓<br />;; ┃ ┃<br />;; ┗━┛<br />(define *box-chars-heavy* "┏━┓┃ ┃┗━┛")<br />;; Double box<br />;; ╔═╗<br />;; ║ ║<br />;; ╚═╝<br />(define *box-chars-double* "╔═╗║ ║╚═╝")<br />;; Block-char box<br />;; ▛▀▜<br />;; ▌ ▐<br />;; ▙▄▟</span><br /> <span style="font-family: Courier New;">(<span class="pl-k">define</span> *box-chars-block* <span class="pl-s"><span class="pl-pds">"</span>▛▀▜▌ ▐▙▄▟<span class="pl-pds">"</span></span>)</span><span style="font-family: Courier New;"><br /></span><br /> <h4> xterm 256-color palette</h4> 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.<br /> <br /> <div class="separator" style="clear: both; text-align: center;"> <a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhX_i77fZUmSWL9CHuIXEBfoorPryOOjD-px2plN3gZTqA6YysPfDzuJ4gLH6F8eiPIVhZQKW8aD3UkiIuAAPu6EjQy3-lDOKnFPlOpQGkCW6zMTlkQhRj1zEeMwVkIyAg3AIQ/s1600/PipGreens.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhX_i77fZUmSWL9CHuIXEBfoorPryOOjD-px2plN3gZTqA6YysPfDzuJ4gLH6F8eiPIVhZQKW8aD3UkiIuAAPu6EjQy3-lDOKnFPlOpQGkCW6zMTlkQhRj1zEeMwVkIyAg3AIQ/s1600/PipGreens.PNG" /></a></div> <br /> With the above widgets and colors, I was able to make the following with just a <a href="https://github.com/spk121/pip-tui/blob/master/examples/tui-label-demo.scm">few (very long) lines of code</a>.<br /> <br /> <div class="separator" style="clear: both; text-align: center;"> <a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjNAoADeS31PjIX6ssORtIgZPhNS0p9BDDd-o5RYfdh58yQkRjRni5ZJYM05FqySBlbdyHeKUd6LIfL8D7JB3ey_fjweieYzxekJhueIV7aaZzLY1m3haaTRceub_FmxmoHT8Y/s1600/PipLabel.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="131" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjNAoADeS31PjIX6ssORtIgZPhNS0p9BDDd-o5RYfdh58yQkRjRni5ZJYM05FqySBlbdyHeKUd6LIfL8D7JB3ey_fjweieYzxekJhueIV7aaZzLY1m3haaTRceub_FmxmoHT8Y/s400/PipLabel.PNG" width="400" /></a></div> <h4> Next Time</h4> <div> Before I get to the interactive widgets, I want to get to the audio design.&nbsp; 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.&nbsp; So I have to figure out how to do some audio.&nbsp; I guess I'm going to have to dig into GStreamer, which is always daunting...</div> <br />Mikehttp://www.blogger.com/profile/00699531526967964528noreply@blogger.com3tag:blogger.com,1999:blog-14978667.post-91461947494767503342016-06-09T17:07:00.002-07:002016-06-09T17:16:15.680-07:00Mapping xterm 256-color palette colors to X11 color namesHere is a table that might be of some use to somebody, someday.<br /> <br /> The xterm-like terminals all have pretty similar predefined colors in their 256-color palettes.&nbsp; 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.<br /> <br /> Unrelated to this, X11 has long included a file called <span style="font-family: &quot;Courier New&quot;,Courier,monospace;">/usr/share/X11/rgb.txt</span> that has names of colors.&nbsp; I wondered what overlap there was between these two things.<br /> <br /> So, this is a list of the xterm 256-color palette indices vs X11 RGB color names.&nbsp; 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.&nbsp; Under those criteria, 129 of 256 xterm colors approximate named X11 RGB colors.<br /> <br /> <div class="separator" style="clear: both; text-align: center;"> <a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi9vs4RF8XenaMLFftEjugKB-Y4x3I_TK4pSV1diQSIxIpHfNZhDpjwEWQJuLMSzQNAy2dF3a8XkVsjM2HLfh4tF6QWiogF-W2HV5DlgzEk29EqR2olfl4VU1cEYtDVHnB3BFc/s1600/x11_xterm_rgb.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="389" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi9vs4RF8XenaMLFftEjugKB-Y4x3I_TK4pSV1diQSIxIpHfNZhDpjwEWQJuLMSzQNAy2dF3a8XkVsjM2HLfh4tF6QWiogF-W2HV5DlgzEk29EqR2olfl4VU1cEYtDVHnB3BFc/s400/x11_xterm_rgb.png" width="400" /></a></div> <br /> <br /> <span style="font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace;">0: BLACK<br />1: WEBMAROON<br />2: WEBGREEN<br />3: OLIVE<br />4: NAVY, NAVYBLUE<br />5: WEBPURPLE<br />6: TEAL<br />7: SILVER<br />8: WEBGRAY, WEBGREY<br />9: RED, RED1<br />10: GREEN, LIME, X11GREEN, GREEN1<br />11: YELLOW, YELLOW1<br />12: BLUE, BLUE1<br />13: MAGENTA, FUCHSIA, MAGENTA1<br />14: CYAN, AQUA, CYAN1<br />15: WHITE<br />16: BLACK<br />18: BLUE4, DARKBLUE<br />20: MEDIUMBLUE, BLUE3<br />21: BLUE, BLUE1<br />22: DARKGREEN<br />24: DEEPSKYBLUE4<br />26: ROYALBLUE<br />28: GREEN4<br />30: CYAN4, DARKCYAN<br />37: LIGHTSEAGREEN<br />40: GREEN3<br />44: CYAN3<br />46: GREEN, LIME, X11GREEN, GREEN1<br />48: SPRINGGREEN, SPRINGGREEN1<br />51: CYAN, AQUA, CYAN1<br />54: INDIGO<br />59: GRAY37, GREY37<br />62: SLATEBLUE3<br />65: DARKSEAGREEN4<br />66: PALETURQUOISE4<br />68: CORNFLOWERBLUE<br />74: SKYBLUE3<br />75: STEELBLUE1<br />76: CHARTREUSE3<br />78: SEAGREEN3<br />79: MEDIUMAQUAMARINE, AQUAMARINE3<br />80: MEDIUMTURQUOISE<br />86: AQUAMARINE, AQUAMARINE1<br />88: RED4, DARKRED<br />89: MAROON4<br />90: MAGENTA4, DARK MAGENTA, DARKMAGENTA<br />92: DARKVIOLET<br />94: DARKGOLDENROD4<br />95: LIGHTPINK4<br />96: PLUM4<br />100: YELLOW4<br />102: GRAY53, GREY53<br />108: DARKSEAGREEN<br />110: SKYBLUE3<br />114: PALEGREEN3<br />116: DARKSLATEGRAY3<br />117: LIGHTSKYBLUE<br />118: CHARTREUSE, CHARTREUSE1<br />122: AQUAMARINE, AQUAMARINE1<br />123: DARKSLATEGRAY1<br />134: MEDIUMORCHID3<br />136: DARKGOLDENROD<br />138: ROSYBROWN<br />141: MEDIUMPURPLE1<br />143: DARKKHAKI<br />145: GRAY69, GREY69<br />149: DARKOLIVEGREEN3<br />152: POWDERBLUE<br />154: GREENYELLOW<br />159: PALETURQUOISE1<br />160: RED3<br />162: VIOLETRED<br />164: MAGENTA3<br />167: INDIANRED<br />171: MEDIUMORCHID1<br />172: ORANGE3<br />173: LIGHTSALMON3<br />178: GOLD3<br />180: BURLYWOOD3<br />184: YELLOW3<br />186: KHAKI3<br />187: LEMONCHIFFON3<br />188: GRAY84, GREY84<br />195: LIGHTCYAN, LIGHTCYAN1<br />196: RED, RED1<br />198: DEEPPINK, DEEPPINK1<br />201: MAGENTA, FUCHSIA, MAGENTA1<br />203: INDIANRED1<br />205: HOTPINK<br />208: DARKORANGE<br />209: SALMON1<br />210: LIGHTCORAL<br />211: PALEVIOLETRED1<br />213: ORCHID1<br />214: DARKGOLDENROD1<br />215: SANDYBROWN<br />217: LIGHTPINK1<br />220: GOLD, GOLD1<br />223: PEACHPUFF, PEACHPUFF1<br />224: MISTYROSE, MISTYROSE1, MISTYROSE2<br />225: THISTLE1<br />226: YELLOW, YELLOW1<br />230: LIGHTGOLDENRODYELLOW<br />231: WHITE<br />232: GRAY3, GREY3<br />233: GRAY7, GREY7<br />234: GRAY11, GREY11<br />235: GRAY15, GREY15<br />236: GRAY19, GREY19<br />237: GRAY23, GREY23<br />238: GRAY27, GREY27<br />239: GRAY30, GREY30, GRAY31, GREY31<br />240: GRAY34, GREY34, GRAY35, GREY35<br />241: GRAY38, GREY38, GRAY39, GREY39<br />242: GRAY42, GREY42<br />243: GRAY46, GREY46<br />244: WEBGRAY, WEBGREY<br />245: GRAY54, GREY54<br />246: GRAY58, GREY58<br />247: GRAY62, GREY62<br />248: GRAY66, GREY66<br />249: GRAY70, GREY70<br />250: GRAY74, GREY74<br />251: GRAY78, GREY78<br />252: GRAY81, GREY81, GRAY82, GREY82<br />253: GRAY85, GREY85, GRAY86, GREY86<br />254: GRAY89, GREY89, GRAY90, GREY90<br />255: GRAY93, GREY93</span>Mikehttp://www.blogger.com/profile/00699531526967964528noreply@blogger.com0tag:blogger.com,1999:blog-14978667.post-38556280254341895662016-06-04T09:30:00.000-07:002016-06-04T09:30:07.469-07:00A Pipboy-like terminal application in Guile: Part 2 - more on stringsHello again. I'm back to talk about&nbsp;recreating some Pip Boy like terminal&nbsp;widgets in ncurses.<br /> <br /> <a href="http://lcinexile.blogspot.com/2016/06/a-pipboy-like-terminal-application-in.html">Last time</a>, I started talking about the remedial problems of how to *render* a string for a character cell console, e.g., how to convert a logical string to a list of visual strings that can be displayed on a terminal.&nbsp; So far, I said that you need to<br /> <ul> <li>Put the string in Unicode NFC normalization, because NFC normalized strings are more likely to&nbsp;be prepared glyphs&nbsp;on a terminal&nbsp;and not&nbsp;overstruck glyphs.&nbsp; Unicode normalization is discussed in <a href="http://www.unicode.org/reports/tr15/">http://www.unicode.org/reports/tr15/</a></li> <li>Convert tabs to spaces</li> <li>Replace&nbsp;almost all of the control characters or <a href="http://www.unicode.org/faq/private_use.html">Private Use Area</a> characters with replacement glyphs.&nbsp;&nbsp;This hygiene is necessary since&nbsp;some unhandled control character could&nbsp;garble&nbsp;the terminal display.&nbsp;&nbsp;Some control characters that don't get removed are the 5 line separators (CR, LF, NEL, PS, and LS) and the 8 bidirectional&nbsp; formatting characters (LRE, RLE, LRO, RLO, PDF, LRI, RLI, FSI, PDI, LRM, RLM, and ALM) because we'll use them in a second.</li> </ul> <div> So that just leaves</div> <ul> <li>Prepare to handle any right-to-left text in the string.&nbsp; This is described in the Unicode Bidirectional Algorithm in <a href="http://www.unicode.org/reports/tr9/">http://www.unicode.org/reports/tr9/</a></li> <li>Do any Arabic shaping of the glyphs</li> <li>Wrap the string to a given number of character cells.&nbsp; The Unicode line-breaking algorithm is described here: <a href="http://www.unicode.org/reports/tr14/tr14-35.html">http://www.unicode.org/reports/tr14/tr14-35.html</a></li> <li>Pad the list of wrapped strings to left, center, or right aligned</li> </ul> <h4> Bidirectional text</h4> <div> First off, I'm not qualified to talk about this, but here's the highlights.</div> <div> <br /></div> <div> Most European languages are written left to right.&nbsp; The big right-to-left alphabets are Arabic and Hebrew.&nbsp; Here in the Los Angeles, I'd guess the most common right-to-left languages&nbsp;are probably Persian, Hebrew, Arabic, and Yiddish.</div> <div> <br /></div> <div> But Scheme strings are normally encoded in logical order: e.g. the beginning of a string is the part of the string that would be read first by a human.&nbsp; If a string contained a line of French, the first character would be the left-most character to be displayed on a screen.&nbsp; If it contained Arabic, the first character would be the right-most character to be displayed on a screen.</div> <div> <br /></div> <div> Terminal emulators generally take one of two strategies when given strings to display. They either</div> <ul> <li>Display the text from left-to-right regardless of the contents of the text</li> <li>Or, try to be context sensitive when they display the text, switching from left-to-right and right-to-left depending on the apparent language of the text</li> </ul> <div> Weirdly, in a ncurses application, neither strategy is particularly helpful.&nbsp; If a terminal does the former, it becomes the programmers' responsibility to convert the string from logical order to visual order.&nbsp; If it does the latter, and you ask ncurses to write a string at a given (y,x) position, it is hard to know if that x is columns counted from the left or columns counted from the right.<br /> <br /></div> Consider the following program, and its output on the Cygwin terminal.&nbsp; It starts ncurses, prints a line of Latin text starting at&nbsp;column 30, row 1, and prints a&nbsp;word in the Hebrew alphabet&nbsp;starting at column 30, row 2.&nbsp; Both lines are supposed to begin a column 30, but, the terminal tries to be helpful and makes the second line print in the 30th column from the right, which is unlikely to be the intention of the programmer.<br /> <br /> <pre>(use-modules (ncurses curses)) (setlocale LC_ALL "") (define win (initscr)) (addstr win "LATIN TEXT" #:x 30 #:y 1) (addstr win (string #\ט\# ק\# ס\# ט ) #:x 30 #:y 2) (refresh win) (sleep 10) (endwin)</pre> <br /> <a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhYymF136vN5-VV_MofTsGmv_-dSM_pll5ezkcRmJd-903ec3paTJmcN6taj4jZ5cPnmw_oSVHds81NVr_qZs4ACT97LrkTQc_uMhaNku6WchiG2tt1ZyJLkvLwyF3u7u-9ct0/s1600/terminal1.png" imageanchor="1"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhYymF136vN5-VV_MofTsGmv_-dSM_pll5ezkcRmJd-903ec3paTJmcN6taj4jZ5cPnmw_oSVHds81NVr_qZs4ACT97LrkTQc_uMhaNku6WchiG2tt1ZyJLkvLwyF3u7u-9ct0/s1600/terminal1.png" /></a> <br /> <br /> So, what to do?<br /> <br /> To complicate matters, Unicode has some explicit control characters that can be embedded in strings when one wants to explicitly state the directionality of all or part of the text.&nbsp; They can be used to explicitly indicate the direction of a run of text, or override the current general direction of the text. The 8 bidirectional&nbsp; formatting characters (LRE, RLE, LRO, RLO, PDF, LRI, RLI, FSI, PDI, LRM, RLM, and ALM) need to be interpreted.&nbsp; See Unicode TR#9 for details.<br /> <div> <br /></div> One strategy is to <br /> <ol> <li>Use a library like GNU FriBiDi to convert the string from logical to visual order</li> <li>Set the terminal program to *not* try to help with bidirectionalization.</li> </ol> <div> So, the FriBiDi function <span style="font-family: &quot;Courier New&quot;, Courier, monospace;">fribidi_log2vis </span>is the important function for this.&nbsp; There needs to be a Guile function <span style="font-family: inherit;">that wraps up the FriBiDi functionality.&nbsp; There isn't one yet.</span></div> <div> <br /></div> <h4> Arabic Shaping</h4> <div> Arabic shaping is another one of those topics about which I know almost nothing, but, here's the highlights.</div> <div> <br /></div> <div> The same Arabic letter can have a different glyph depending on where it appears in&nbsp;a word.&nbsp; If it appears in the middle of a word, the glyph should join smoothly&nbsp;to its neighboring letters, like English&nbsp;cursive letters.&nbsp; If it appears at the beginning or end of a word it has a different form.&nbsp; And it might also look different when it is a single letter not in a word.</div> <div> <br /></div> <div> <a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZ4AKcs9Sou_UPVaYH8_xKPmYf4rotEOI_XgFYPuBCvgYY32hxogzlXGlotuS1udYLEvxg2mNtVWnR7bijHuTELO4L6G3vAAA6K2fWq2nrvnY_l0xdoacZAMAfVCjhJNV32W4/s1600/arabic_shaping.jpg" imageanchor="1"><img border="0" height="284" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZ4AKcs9Sou_UPVaYH8_xKPmYf4rotEOI_XgFYPuBCvgYY32hxogzlXGlotuS1udYLEvxg2mNtVWnR7bijHuTELO4L6G3vAAA6K2fWq2nrvnY_l0xdoacZAMAfVCjhJNV32W4/s320/arabic_shaping.jpg" width="320" /></a></div> <div> <br /></div> <div> Some new terminal emulators are smart enough to do this shaping for you. If it detects an Arabic letter in the middle of a work, it uses the correct glyph.&nbsp; But if you've asked your terminal to *not* help with bidirectionalization so that the behavior of&nbsp;the ncurses screen locations&nbsp;is still predictable, it is still going to do Arabic letter shaping for you?&nbsp; I don't know.&nbsp; It is a mess.<br /> <br /> There are other complications.&nbsp; There are Unicode controls that exist to encourage characters to be joined (ZWJ, for example) or to discourage it (ZWNJ).</div> <div> <br /></div> <div> In any case, if you need to do shaping manually instead of leaving it to your terminal emulator, again GNU FriBiDi is your goto library for this.&nbsp;&nbsp;And someone needs to package that for Guile, too.</div> <div> <br /></div> <h4> Line Length and Line Breaking</h4> <div> OK.&nbsp; You have your string.&nbsp; It is NFC, untabified, has no nasty control characters in it, and you've decided upon some strategy for bidirectional text.&nbsp; Next up, we need to figure out how much screen real estate each string takes up, and whether the lines need to be wrapped.</div> <div> <br /></div> <div> For console programs, each character takes up zero, one, or two cells. Latin letters usually take one cell. Chinese, Japanese, and Korean letters usually take two, as in the following pic.</div> <div> <br /></div> <div> <br /></div> <div> <a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhqoi62H0cyH0GoP-ETdjBf3mgKFHaBgC1d7LPexwKsrFg0NMLN7OVP09HFS1LPHzYva0UXtQ3ZXFFiwzKKL5SFVaj1gYedSO1Tn55g71gsaFfHeTpXkBMGEcB50Napu2ycOo0/s1600/Screenshot+%25286%2529.png" imageanchor="1"><img border="0" height="188" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhqoi62H0cyH0GoP-ETdjBf3mgKFHaBgC1d7LPexwKsrFg0NMLN7OVP09HFS1LPHzYva0UXtQ3ZXFFiwzKKL5SFVaj1gYedSO1Tn55g71gsaFfHeTpXkBMGEcB50Napu2ycOo0/s400/Screenshot+%25286%2529.png" width="400" /></a></div> <div> <br /></div> <div> So how do you tell how many cells a glyph is going to take?&nbsp; Basically the C library function <span style="font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace;"><a href="http://pubs.opengroup.org/onlinepubs/009695399/functions/wcwidth.html">wcwidth</a> </span><span style="font-family: inherit;">is the basis for this.&nbsp; It will tell you if a codepoint has a glyph that takes up one cell or two.&nbsp; Unicode has their own explanation over here: <a href="http://unicode.org/reports/tr11/">http://unicode.org/reports/tr11/</a></span></div> <div> <br /></div> Guile needs a function to compute the screen width of a line of text.&nbsp; I like <span style="font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace;">u32_strwidth</span> from GNU Libunistring, and that's a function that needs to be made available to Guile, too.<br /> <br /> But this also has some problems.&nbsp; Some characters have a width that is ambiguous, and should be 2 cells on a screen that mostly consists of CJK text, or should be 1 on a screen that mostly consists of Latin text.&nbsp; Some example ambiguous width characters are some punctuation or math symbols.&nbsp; Not all terminals agree on what to do about ambiguous width characters. But I'm not going to solve this problem.<br /> <br /> But once one knows how many screen cells a line of text is going to take, it&nbsp;would seem fairly&nbsp;easy to then construct a line-breaking algorithm.&nbsp; Line breaks need to be put in at all the explicit line breaks of the five line breaking characters CR, LF, NEL, PS, and LS.&nbsp;Remember that CR+LF counts as just a single line break.&nbsp; And then lines that exceed a desired number of columns need to be broken at plausible locations at the end of words.<br /> <br /> There are some other complications.&nbsp; There are some Unicode characters that are there to prevent line breaking or encourage line breaking: various hyphens, soft hyphens, double hyphens, word joiners.<br /> <br /> Hopefully this convinces you that line breaking is not really something you should treat casually.&nbsp;&nbsp;&nbsp; See Unicode TR #14 for its generic line breaking algorithm.&nbsp; It is actually quite complex.&nbsp; In any case, I'm not going to engineer a console line-wrapping algorithm.&nbsp; I like the one in GNU Libunistring called <span style="font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace;">u32_width_linebreaks()</span> described <a href="http://www.gnu.org/software/libunistring/manual/libunistring.html#unilbrk_002eh">here</a>. And, again, this isn't available to Guile yet, so&nbsp;I need&nbsp;to package that, too.<br /> <br /> But if there were such a function, it would take a string and break it into a list of strings, where each element of the list had one screen line of text.<br /> <br /> <h4> Alignment and Padding</h4> <div> Alright, now we're at the end of this process.&nbsp; The last step is padding the string to get the desired alignment.<br /> <br /> The default alignment for Latin console text&nbsp;should be to have an aligned left margin and a ragged right margin.&nbsp; For RTL text is should be to have an aligned right margin and a ragged left margin.&nbsp; So you need a function that tries to determine the general directionality of a paragraph.</div> <div> <br /></div> <div> If you want a paragraph of text to be right-aligned or center-aligned, you need to pad the strings&nbsp;on the left with spaces.&nbsp; To know how many spaces to pad a line, you need to know how many cells a line occupies on the screen.&nbsp; Again it all goes back to <span style="font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace;">wcwidth</span> and&nbsp; <span style="font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace;">u32_strwidth</span> as described above.</div> <div> <br /></div> <h4> Next</h4> <div> So I'll come back when I have all the above functionality in some library somewhere, and we'll finally be ready to put some green text in a green box.</div> <div> <br /></div> <div> <a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjUXbWiIOry0NmeVNfpeQDPZSjh8SvqYgi_yade_hwfPwXqKmjs9BzbOwBe4ID7YkFmFoy7zu4PWq_253HL2l5Z7TTS-Whr00SxUg2RwOtblSbjuf2L-dIoEGpbJq9hAu3Kfx8/s1600/20160603213249_1.jpg" imageanchor="1"><img border="0" height="205" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjUXbWiIOry0NmeVNfpeQDPZSjh8SvqYgi_yade_hwfPwXqKmjs9BzbOwBe4ID7YkFmFoy7zu4PWq_253HL2l5Z7TTS-Whr00SxUg2RwOtblSbjuf2L-dIoEGpbJq9hAu3Kfx8/s320/20160603213249_1.jpg" width="320" /></a></div> Mikehttp://www.blogger.com/profile/00699531526967964528noreply@blogger.com0tag:blogger.com,1999:blog-14978667.post-12646710754126744332016-06-02T16:09:00.000-07:002016-06-02T16:09:18.517-07:00A Pipboy-like terminal application in Guile: Part 1 - rendering strings<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhzOK2_fu4WlbXjB7wRJKD_vphuSAOpiTKEk_tQO_mWPWnFe3JK6ww1rqje6Zuorhb8DjQoU7u0dHBLPxKVJvxg4aIR70V6mowdrwwOE3PVWFVFU6JLRJ43byPrn5bc3UYM1K4/s1600/pip.jpg" imageanchor="1"><img border="0" height="258" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhzOK2_fu4WlbXjB7wRJKD_vphuSAOpiTKEk_tQO_mWPWnFe3JK6ww1rqje6Zuorhb8DjQoU7u0dHBLPxKVJvxg4aIR70V6mowdrwwOE3PVWFVFU6JLRJ43byPrn5bc3UYM1K4/s320/pip.jpg" width="320" /></a><br /> <br /> So I've been playing a ton of Fallout 4.&nbsp; It is not as much fun as Fallout: New Vegas, but, it is pretty good.<br /> <br /> For the uninitiated, the Fallout games are videogame RPGs that deal with a lone wanderer making the world a better place by helping out in a post-nuclear-war world.&nbsp; Part of the unusual world-building in the game is type of technology that exists in this future.<br /> <br /> Most computers in this future are monochrome green-screen terminals, much like the old DEC VT420 terminals in our world.<br /> <br /> Well, I do happen to be the maintainer of guile-ncurses, a TUI library for programming in Scheme.&nbsp; So I think I'll spend a few weeks seeing if I can recreate some of the visual elements from Fallout 4 in a text-user interface, and in the process demonstrate something of the process of creating a TUI.<br /> <br /> The problem with ncurses, as anyone who has tried to use it will quickly realize, it that it is quite a low-level toolkit.&nbsp; In the analogy with GNOME, it is not GTK, it is Cairo or GDK.<br /> <br /> (Note that there is a higher level TUI toolkit built on ncurses called CDK, which is much easier to use if you want to do any rapid prototyping on a TUI.&nbsp; There is no Guile library for this, yet, though.) <br /> <br /> If you want to follow along with the code, well, there isn't any yet.&nbsp; But soon there will be some at my Github. <a href="https://github.com/spk121/pip.git">https://github.com/spk121/pip-tui.git</a><br /> <br /> Today we're going to try something that sounds simple but absolutely is not. In fact it is so complicated that I'm only going to begin the topic today.<br /> <br /> We're going to work on displaying some text in a character cell terminal!&nbsp; I know, crazy, right? <br /> <br /> In ASCII, this is quite easy, of course.&nbsp; But, I'm going include some details involved in using Unicode text, even if I ultimately end up just using ASCII, because, it is an interesting and valuable topic.&nbsp; If we have a Unicode string that we want to display in a character cell terminal, we need to *render* it, to decide which glyphs go into which cells.&nbsp; Rendering a string -- converting a string to a list of glyphs that go into cells -- has roughly the following steps. <br /> <ul> <li>The string should be in the NFC normalization. </li> <li>The string needs to have horizontal tabs replaced with spaces.</li> <li>The C0 control characters that will not be handled later should be replaced with replacement characters.&nbsp; Only carriage return and line feed will be handled later.</li> <li>C1 controls, except for NEL, unassigned characters, and private-use characters should be replaced with the generic replacement character. </li> <li>Some strings have a different visual order than their logical order.&nbsp; Hebrew and Arabic have a visual order that is right-to-left even though the strings are encoded in logical order, from beginning to end.&nbsp; This is handled by the Unicode bidirectional algorithm.</li> <li>Arabic letters are cursive, so the various letters can have different shapes depending on if they appear at the beginning, the middle, or the end of a word. </li> <li>The rendered string has to be in the locale of the terminal to display properly.&nbsp; Characters that cannot be properly displayed need to be replaced with replacement characters. </li> <li>And lastly, strings need to be line wrapped if they occupy more cells than are available.&nbsp; This means understanding the number of cells a string occupies. On terminals, Unicode codepoints take zero, one, or two cells of space. Latin characters take one cell.&nbsp; Fullwidth hanzi and kanji take two cells.</li> </ul> To begin, we start with the operations that need to occur in *logical order* not *visual order*. <br /> <h3> Normalization</h3> When rendering strings for use with character cell terminals, it is much easier to deal with composed glyphs, such as U+00C0 LATIN CAPITAL LETTER A WITH GRAVE, than with the combining accents, such as U+0041 LATIN CAPITAL LETTER A and U+0300 COMBINING GRAVE ACCENT.<br /> <br /> All strings to be rendered should thus be passed through core Guile function <span style="font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace;">string-normalize-nfc.</span> <br /> <h3> Untabifying</h3> Canonically a horizontal tab occupies 8 spaces, so each instance of a horizontal tab in a string must be replace with 8 spaces.<br /> <br /> Pedantry: on some old terminals and line printers, horizontal tabs actually moved one to the next tab stop, which was the next column that was a multiple of 8.<br /> <br /> Here's one way to do the string expansion.<br /> <br /> <span style="font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace;">(define (string-untabify in-string TABSIZE)</span><br /> <span style="font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace;">&nbsp; (string-fold</span><br /> <span style="font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace;">&nbsp;&nbsp; (lambda (c str)</span><br /> <span style="font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace;">&nbsp;&nbsp;&nbsp;&nbsp; (if (char=? c #\tab)</span><br /> <span style="font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (string-append str (make-string TABSIZE #\space))</span><br /> <span style="font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (string-append str (string c))))</span><br /> <span style="font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace;">&nbsp;&nbsp; ""</span><br /> <span style="font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace;">&nbsp;&nbsp; in-string))</span><br /> <br /> <h3> Replacement Characters</h3> Next up is replacing some of the control, private-use, and unrepresented characters with replacement symbols.&nbsp; Why do this?<br /> <ol> <li>If you try to print C0 control characters (U+0000 to U+001F) to a console, the console might interpret it as commands.</li> <li>If you try to print C1 control characters (U+0080 to U+009F) to a console, consoles in 8-bit mode might interpret them as commands, and can potentially hang.</li> <li>Some characters -- such as all the unassigned characters and Private Use Area (PUA) characters -- won't be rendered by any character cell terminal, so there is no point in allowing them to continue.</li> </ol> To replace the C0 control codes from U+0000 to U+001F and also U+007F with graphical symbols, there are two reasonable choices. ISO-2047 symbols are fairly obscure but, hey, they are a standard.&nbsp; But, the graphical pictures for control codes starting at U+2400 are more familiar and are probably a better choice.<br /> <br /> Unicode control codes for U+0000 NULL to U+0007 BELL look like ␀␁␂␃␄␅␆␇.<br /> ISO-2047 control codes for U+0000 NULL to U+0007 BELL look like ⎕⌈⊥⌋⌁⊠✓⍾.<br /> There are many other codepoints that should just be replaced with <span style="font-size: 125%;">�, </span>the U+FFFD REPLACEMENT CHARACTER, including<br /> <ul> <li>All the C1 control characters U+0080 to U+009F, excluding U+0085 NEXT LINE (NEL).</li> <li>All the private use area characters U+E000..U+F8FF, U+F0000..U+FFFFD, and U+100000..U+10FFFD</li> <li>Any other character with the general category of control, surrogate, or unassigned.</li> </ul> Note that we do not include the control format characters in this list, such as U+200E LEFT-TO-RIGHT MARK, because we'll need them later when be handle bi-directional text.<br /> <br /> In the library, there will be a function that might be called <span style="font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace;">string-replace-controls-and-pua</span> which will do this replacement.<span style="font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace;"><span style="font-family: inherit;"> </span></span><br /> <br /> That's all for now.&nbsp; Next time we'll handle bidirectional text, Arabic shaping, and line wrapping.Mikehttp://www.blogger.com/profile/00699531526967964528noreply@blogger.com3tag:blogger.com,1999:blog-14978667.post-68965069811337126772016-01-29T10:50:00.001-08:002016-01-29T10:50:59.471-08:00A Portrait of the Coder as an Old ManI've been thinking quite a bit about being a older coder.&nbsp; I've come to the realization that, like most other professions or activities, as we age, we need to make accommodations.<br /> <br /> For example, as we age, the short term memory begins to fade.&nbsp; Where once I could reliably recall the names and type details of&nbsp;hundreds of the variables, functions, and methods I've touched on a large task, now I can only reliably remember a couple dozen.&nbsp; As a young man, I could focus on whatever function I was modifying, using memory and recall should I need to add a function call or variable reference.&nbsp; Now I do spend a lot of time tap dancing through code, always referencing headers and declarations, with dozens of files open at any given moment.<br /> <br /> On the flip side, the long term memory, now so richly loaded with associations, can get bogged down in those associations.&nbsp; Every module or algorithm brings to mind another module or algorithm.&nbsp; This is like that is like this is like that.&nbsp; Which is very useful given that there is nothing new under the sun, but sometimes there is something new that needs to be considered on its own merits.<br /> <br /> Also, there is the problem of irascibility.<br /> <br /> I have spend almost all of my professional life coding in subsets of C.&nbsp; Various embedded or safe or DO-178B restrictions to C.<br /> <br /> C, in particular, has two problems for the old coder.<br /> <br /> First is the problem of irascibility.<br /> <br /> C is very simple with a minimal library.&nbsp; I remember the first time I coded a doubly-linked list or a binary tree.&nbsp; So satisfying to get this concept and see it function.&nbsp; It is fun the first time, or the second.&nbsp; But after 30 years, I never again want to code a doubly-linked list, a sort, a hash map, a binary tree, a dispatcher, a parser, a lexer, a matrix pseudoclass, a polynomial solver, or a Kalman filter.&nbsp; It is just no fun anymore.<br /> <br /> Second is the problem of verbosity.<br /> <br /> Since I know I no longer have an infallible, photographic recall of an entire codebase, it helps to be able to have as much code on the screen at any given moment: to be able to see as much as possible of what I am doing.&nbsp; And C, in particular, is so verbose that it restricts the amount of meaning I can throw up on any given screen.&nbsp; C so often oscillates between being information dense and having a paucity of information per line.<br /> <br /> So, then, coding as an old man...<br /> <ul> <li>I need my language and tools to help me remember details of variables, functions, and methods.&nbsp; And I need those tools to help me remember in a way that doesn't destroy my flow.</li> <li>I need my language and tools to let me see as much of what I am doing as possible.</li> <li>I need my language and tools to not require me to re-code or re-integrate fundamental algorithms that are no longer entertaining.</li> <li>I need my language and tools to help me determine if a code block is or is not a fundamental algorithm.&nbsp; If it is, I want to use that fundamental algorithm.</li> </ul> Let's imagine, for a second, the properties of a theoretical programming language created for older coders. Such a theoretical language would be designed from the ground to play well with tools.&nbsp; There should be nothing in the grammar of the language that would prevent tools from autocompleting or suggesting a given declaration.&nbsp; The scoping and context rules should not have the sort of ambiguity that prevents effective tooling.&nbsp; And compilation errors should be flagged immediately.<br /> <br /> Also such a language should have a consistent level of information density, so that a screenful of text is sufficient to display a "unit" of code.<br /> <br /> I don't often stray too far from the C-language family.&nbsp; To be honest, C# is pretty good as an old man language. But, I've been trying to brush up on my C++17.<br /> <br /> #include 〈algorithm〉 is pretty cool.Mikehttp://www.blogger.com/profile/00699531526967964528noreply@blogger.com1tag:blogger.com,1999:blog-14978667.post-42303443263504462892015-12-09T16:13:00.002-08:002015-12-09T16:13:53.386-08:00Silly questions about telephonyHello Internet, I have some questions.<br /> <br /> I would search for them online, but, I haven't yet figured out the keywords I should be using. There seems to be a large overloading of meaning for telephony terminology.<br /> <br /> Question one. From a program running on GNU/Linux PC, I want to have the capability to connect to a USA cell phone network as a voice call and send and receive audio over a cell phone voice call. The program will be generating the audio. Imagine a robo-caller program that would be calling a list of phone numbers to play emergency announcements.<br /> <br /> Question two. From a GNU/Linux PC, I want the capability to connect to a USA cell phone network and make a voice call to an old-school 9600 bps landline audio modem, and have serial comms with this landline audio modem.<br /> <br /> In both cases, the PC doesn't have any native capability to connect to the cell phone network, so it either needs a service or some hardware that will provide this capability.<br /> <br /> I understand what I am trying to do may be silly. That is the point. Mikehttp://www.blogger.com/profile/00699531526967964528noreply@blogger.com1tag:blogger.com,1999:blog-14978667.post-39857298737750543432014-11-09T22:39:00.000-08:002014-11-09T22:39:12.735-08:00archive.org is good for old tech docs<p>I saw on <a href="http://undeadly.org">Undeadly</a> a note that OpenBSD's Ted was patching the ancient <a href="http://www.tedunangst.com/flak/post/improving-bcd">bcd</a> program, which converts text into ASCII-art representations of punch cards. Punch cards were a technology from the 1960s and 1970s (?) that stored code or data on cardstock, with holes punched out of them. Each card held a line of text. If I recall correctly, each character was a column on the card, with as many as seven holes punched out of set of 12 possible locations. There were 40 to 80 columns on the card, according to the brand and the decade.</p> <p>Anyway, Ted modified the bcd program to read in the ASCII-art representation of punch cards that it generated, so that it became, essentially, a very inefficient reversible encoding, but, he was unsure where to search for documents that he could use to validate the output.</p> <p>My goto place for tech docs from the 1970s is <a href="http://archive.org">archive.org</a>. If you've never searched its collection, you should check it out.</p> <p>Anyway, I did manage to find a couple of references there to <a href="https://archive.org/details/bitsavers_cdccyberpe0B34463644CardPunchCtlrMay72_5334965">punch card encoding</a>.</p> <p>For a couple of brands, anyway, punch card encoding seemed to have, for each character, a 4-bit "zone" or category and an 8-bit index. But this didn't result in a 12-bit encoding. Only a sparse subset of the available 12-bits indicated a character, for mechanical reasons, I guess. A subset of the characters now included in ASCII were encodable, but, missing some punctuation such as square brackets. It is for reasons like this that the C standard has trigraphs.</p>Mikehttp://www.blogger.com/profile/00699531526967964528noreply@blogger.com0tag:blogger.com,1999:blog-14978667.post-6333179943478459412014-03-17T09:34:00.000-07:002014-03-17T09:34:38.709-07:00My failures, games, and an offering of timeDear internet, life continues to be strange. <br /> <br /> A year ago or so, I started writing a custom game engine for a game idea I had.&nbsp; I actually got as far as creating about 50% of that game engine before it languished.&nbsp; Yet another uncompleted project.&nbsp; Yet another example of how, when it comes to my own personal hobby projects, I enjoy of the process of learning and tinkering and abstractificating more than completion.<br /> <br /> But I picked up the book <u>Game Engine Architecture</u> by Jason Gregory, and now I'm reinvigorated.&nbsp; It is interesting to compare it to the much older book <u>Game Coding Complete</u> by Mike McShaffry.&nbsp; They actually agree on many topics.&nbsp; Looking at the two books, this idea of writing a game seems tractable, again.&nbsp;&nbsp; It is interesting to see how game engines are converging into a discipline.<br /> <br /> And thus with the idea of writing a game seeming possible again, I've been reading through the SDL2 library docs.&nbsp; At the moment, it seems that SDL (or monogame and friends) is the best free-software-compatible way to write cross-platform games.&nbsp; Unfortunately, the docs for SDL2 -- while excellent for a free software project -- are still lacking examples.&nbsp; The API for SDL1 was modernized for SDL2, and the community is still catching up with the new API.<br /> <br /> But, I think I hack this game in private until I have something to show.<br /> <br /> §<br /> <br /> <br /> With the war in Afghanistan finally approaching the endgame, I'll have some free time for volunteering, so if anyone in GNU has a well-defined ~80 hour task for me, hit me up.&nbsp; I've done embedded systems, global positioning systems, numerical analysis, some device drivers, some low-level audio and video, endless technical docs and a ton of extremely formal software engineering and testing.&nbsp; Lots of C, a bit of C++. Or if you just need fresh eyes to try out your program. Lemme know. I'm mike at lonelycactus.com and I'm in Los Angeles.<br /> <br />Mikehttp://www.blogger.com/profile/00699531526967964528noreply@blogger.com0