<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <title>Blind guru blog</title>
    <link href="https://blind.guru/feeds/all.atom.xml" rel="self" />
    <link href="https://blind.guru" />
    <id>https://blind.guru/feeds/all.atom.xml</id>
    <author>
        <name>Mario Lang</name>
        
        <email>mlang@blind.guru</email>
        
    </author>
    <updated>2025-02-09T00:00:00Z</updated>
    <entry>
    <title>AI badly suffers from dyscalculia</title>
    <link href="https://blind.guru/blog/2025-02-09-tts-dyscalculia.html" />
    <id>https://blind.guru/blog/2025-02-09-tts-dyscalculia.html</id>
    <published>2025-02-09T00:00:00Z</published>
    <updated>2025-02-09T00:00:00Z</updated>
    <summary type="html"><![CDATA[<p>TL;DR: As my girlfriend succinctly sums it up:
“AI systems are the first computers that really can’t deal with numbers.”</p>
<!--more-->
<h2 id="llms-need-a-calculator-tool">LLMs need a calculator tool</h2>
<p>As we all learnt when the GPT hype started,
LLMs actually need access to a calculator tool
to do math/numbers correctly. It might be able to occasionally
sum 2-digit numbers without an error, but it is really
a gamble. Stephen Wolfram more or less immediately appeared
on YouTube, talking about how the Wolfram Language
has been integrated with ChatGPT to solve this exact problem.
A few months later, access to Python was more or less
standard, and the problem somehow went underground/unnoticed
for most users. However, the fundamental issue remains.
If you LLM doesn’t have access to a caluclator tool, you can’t trust
any number it will ever give you. Well, you can’t even trust
the facts it is spitting at you, but this is a completely different topic.</p>
<h2 id="openai-tts">OpenAI TTS</h2>
<p>However, speech synthesis doesn’t just get the number wrong,
in some cases, it breaks the pronounciation of a multi-digit number completely.
To a point where the number it is trying to say is not recognizable.</p>
<p>I first noticed this phenomenon when I tried the OpenAI
speech API. I was amazed at the speech quality, no question.
However, I also immediately noticed this stuff is not usable for anything
that might contain 3-digit or more numbers. I basically
ran a METAR weather report through gpt3.5-turbo, and passed
the expansion to the OpenAI TTS. The LLM model did
a great job, but the TTS botched <em>every</em> number in subtle ways.
I was schocked, to say the least, and immediately reminded
of the Xerox compression algorithm bug debacle.</p>
<p>How can someone release a speech synthesizer that can’t
say numbers correctly, in the 21st century, and get away
with it without a huge public backlash? Do people really
don’t care about correct data anymore?</p>
<h2 id="ios-voiceover">iOS VoiceOver</h2>
<p>Next time I noticed a simplar effect was when I upgraded
my iOS to 14 or 15, I honestly don’t remember which exactly.
This time, the phenomenon was even weirder.</p>
<p>I noticed it the first time when I read a message in WhatsApp,
that was send early in the day. It said “X:15”.
Later, I heard the speech synthesizer replace
5 with V and 1 with I. Yes, you probably already caught on.</p>
<p>Something in the training of whatever, apparently picked up
roman numerals, and decided that it would be fun to
randomly replace arabic numbers with their roman counterparts.
So don’t be surprised if the balance of your bank account is “478.0V”,
thats Apple trying to tell you that you and your requirements
don’t matter.</p>
<h2 id="how-is-this-possible">How is this possible?</h2>
<p>Seriously, how is it possible that companies like Apple and OpenAI
release software that ruins numbers when speaking them?
Are we so deep into Idiocracy already that it does
go unntocied? Does nobody care about anything anymore these days?
How come this shit goes unnoticed?
I mean, really. How can you train a TTS model
and <em>forget</em> to check if it reads numbers correctly?
How can you maintain a screen reader, and not notice that
in your latest major release, arabic digits are getting replaced
with roman numerals? How can this stuff pass through QA?
IMO, this can only happen if there is actually no QA.</p>]]></summary>
</entry>
<entry>
    <title>Why the text terminal cursor is important for Accessibility</title>
    <link href="https://blind.guru/blog/2021-06-25-brick.html" />
    <id>https://blind.guru/blog/2021-06-25-brick.html</id>
    <published>2021-06-25T00:00:00Z</published>
    <updated>2021-06-25T00:00:00Z</updated>
    <summary type="html"><![CDATA[<p>Most terminal user interfaces can be used by blind users pretty easily.
But why is that, actually? After all, the content of a terminal
is pretty much unstructured data. A rectangular grid of characters
with no extra information except colours.
But is that really true?</p>
<!--more-->
<p>The most important bit of metadata for a terminal screen reader
is actually the cursor location. This is the one bit of information that
is required to make a unstructured grid of characters surprisingly useful
to a person mostly constraint to linear reading.</p>
<p>The terminal cursor acts as the focus. It indicates which part of the
screen is currently being edited or selected. For editors, this
is a pretty well understood concept. Where the cursor is, the next
character will be inserted. However, there is more to a
<a href="https://en.wikipedia.org/wiki/Text-based_user_interface">text-based user interface</a> then just editing fields.
And the cursor is not always visible.</p>
<h2 id="enter-brick-a-tui-for-haskell">Enter brick: a TUI for Haskell</h2>
<p>A while ago, I looked at the <a href="https://hackage.haskell.org/package/brick">brick</a> terminal UI library for Haskell.
When I tried its various <a href="https://github.com/jtdaugherty/brick/tree/master/programs">demo programs</a>, I noticed that
<a href="https://brltty.app/">my screen reader</a> was reporting the cursor being in the lower right corner of
the application when a menu item was selected. I had to manually investigate
the screen and look at attributes (colours) to figure out which item in a list
was currently selected. Amongst BRLTTY developers, we’ve decided
long ago to not work around these issues on the screen reader side,
rather try and make use of open source and fix the problems whenever
we see them in the wild.
Behind the scenes, we have fixed a bunch of frameworks and applications
to place the cursor at the locus of focus. So I set out to understand
brick internals to fix this.</p>
<h2 id="a-collection-of-cursors">A collection of cursors</h2>
<p>brick works different from most TUI frameworks I know.
You don’t have a single cursor which you set to a particular location.
Rather, all the different components drawn on the screen
can declare their own cursor location, and the composition mechansim
ultimately chooses which cursor should be used.</p>
<p>This, while being pretty flexible, looked fundamentally wrong to me.
Why? It doesn’t reflect the reality of a terminal.</p>
<h2 id="der-cursor-ist-immer-unter-überall">Der Cursor ist immer unter überall!</h2>
<p>There is no such thing as “no cursor” in a terminal. The cursor might
be hidden, so it is not rendered on the screen.
But the cursor still has a location where it sits and waits to print
the next output character to the screen. A screen reader
will pick that location up, no matter if the cursor is visible or hidden.</p>
<h2 id="visibility-is-key">Visibility is key</h2>
<p>So after patching brick to declare a cursor when rendering certain
list items, checkboxes and radio items, I realized the actual missing
bit. brick had no concept of cursor visibility. Rather, if the composition
mechansim did not see a cursor declared, it would hide the cursor on-screen
and “pretend” there was none. However, as we have learnt above, thats just
not true and programs like screen readers actually rely on the cursor
location to indicate the locus of fucs.</p>
<p>Raising this issue with the brick maintainer uncovered the
fact that the low level <a href="https://hackage.haskell.org/package/vty">vty</a> library used by brick to do the actual terminal
output did not have a concept of a hidden cursor either.
Jonathan fixed this in <a href="https://hackage.haskell.org/package/vty-5.33/changelog">vty 5.33</a>.</p>
<h2 id="tying-the-knot">Tying the knot</h2>
<p>And since vty 5.33 is now in stack LTS, I thought to myself yesterday
it is time to finally <a href="https://github.com/jtdaugherty/brick/pull/326">add support for invisible cursors</a> to brick.</p>
<p>There is now a new function putCursor which has the same type signature
as the already existing <a href="https://hackage.haskell.org/package/brick-0.62/docs/Brick-Widgets-Core.html#v:showCursor">showCursor</a>, but will make sure the cursor is not
visible on-screen. This can and should be used to place
a cursor at the locus of focus, even if that location
is already visually indicated by different attributes.</p>
<p>The stock widgets that come with brick should now all be screen reader friendly.
If you happen to maintain a brick application which provides a render
function to something like <a href="https://hackage.haskell.org/package/brick-0.62/docs/Brick-Widgets-List.html#v:renderList">renderList</a>, please consider
extending it to use showCursor. Once brick 0.64 is released, you can
change to putCursor to clean up the visual appearance of your program.</p>]]></summary>
</entry>
<entry>
    <title>Processing CodeBlocks in Hakyll</title>
    <link href="https://blind.guru/blog/2020-12-05-codeblock.html" />
    <id>https://blind.guru/blog/2020-12-05-codeblock.html</id>
    <published>2020-12-05T00:00:00Z</published>
    <updated>2020-12-05T00:00:00Z</updated>
    <summary type="html"><![CDATA[<p>Automatic syntax highlighting for well known programming languages
is one of the killer features of document formats like Markdown
and reStructuredText. However, sometimes the stock features
provided by your document processor are not enough. You might want more,
like actual syntax checking, or even running example code
to make sure it is correct.</p>
<p>How this can be achieved will depend on your document processing system.
In this article,
we will cover <a href="https://pandoc.org/">Pandoc</a> as it is used in the Hakyll static site generator.</p>
<!--more-->
<h2 id="motivation">Motivation</h2>
<p>I am the author of a program (<a href="../projects/bmc.html">BMC</a>) to parse and transform Braille Music Code.
One of its most basic features is to pretty print the parsed input, which
can be used to reflow braille music code according to its peculiar
hyphenation rules. It would be useful to plug this functionality
into Pandoc such that certain codebocks could be automatically
checked for validity and formatted for a certain line width.</p>
<h2 id="hakyll">Hakyll</h2>
<p><a href="https://jaspervdj.be/hakyll/">Hakyll</a> is basically a high level build system for static websites.
It has a Compiler type which is responsible for doing
something with your input data. The most important Compiler in Hakyll
is the <a href="https://hackage.haskell.org/package/hakyll/docs/Hakyll-Web-Pandoc.html#v:pandocCompiler">pandocCompiler</a>, which uses Pandoc under the hood to read
your input data and write it back as HTML.</p>
<p>What we need is a way to hook into this mechanism so that we can transform
the underlying Pandoc AST before it gets passed to the Pandoc writer.</p>
<p>The main entry point to write a pandocCompiler which transforms the AST
is the function <a href="https://hackage.haskell.org/package/hakyll/docs/Hakyll-Web-Pandoc.html#v:pandocCompilerWithTransform">pandocCompilerWithTransform</a> which has the following
type signature:</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a>pandocCompilerWithTransform</span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="ot">  ::</span> <span class="dt">ReaderOptions</span> <span class="ot">-&gt;</span> <span class="dt">WriterOptions</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>  <span class="ot">-&gt;</span> (<span class="dt">Pandoc</span> <span class="ot">-&gt;</span> <span class="dt">Pandoc</span>)</span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>  <span class="ot">-&gt;</span> <span class="dt">Compiler</span> (<span class="dt">Item</span> <span class="dt">String</span>)</span></code></pre></div>
<p>Ignoring the options, it takes a function from Pandoc to Pandoc and
returns a Compiler which will ultimately produce the result of the pandoc
writer as a String.</p>
<p>This can be enough if your transformation can never fail.
However, it is likely that if you want to do your own pre-processing, you are
also interested in reporting errors and making the
build process fail in case something went wrong.
What we need is an effectful version of the same function.
<a href="https://hackage.haskell.org/package/hakyll/docs/Hakyll-Web-Pandoc.html#v:pandocCompilerWithTransformM">pandocCompilerWithTransformM</a> is just that.</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a>pandocCompilerWithTransformM</span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a><span class="ot">  ::</span> <span class="dt">ReaderOptions</span> <span class="ot">-&gt;</span> <span class="dt">WriterOptions</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a>  <span class="ot">-&gt;</span> (<span class="dt">Pandoc</span> <span class="ot">-&gt;</span> <span class="dt">Compiler</span> <span class="dt">Pandoc</span>)</span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a>  <span class="ot">-&gt;</span> <span class="dt">Compiler</span> (<span class="dt">Item</span> <span class="dt">String</span>)</span></code></pre></div>
<h2 id="walk-the-walk">Walk the walk</h2>
<p>The <a href="https://hackage.haskell.org/package/pandoc-types/docs/Text-Pandoc-Walk.html#t:Walkable">Walkable</a> typeclass from the <a href="https://hackage.haskell.org/package/pandoc-types">pandoc-types package</a> allows to
walk a Pandoc bottom-up, replacing all the occurences of
a Block with the result of applying a function to it.</p>
<p>In particular, we want to use <a href="https://hackage.haskell.org/package/pandoc-types/docs/Text-Pandoc-Walk.html#v:walkM">walkM</a> since we want to make use of the
Hakyll Compiler monad. Here <code>a</code> will be <code>Block</code> and <code>b</code> will be <code>Pandoc</code> and
<code>m</code> will be <code>Compiler</code>.</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="ot">walkM ::</span> (<span class="dt">Monad</span> m, <span class="dt">Applicative</span> m, <span class="dt">Functor</span> m) <span class="ot">=&gt;</span> (a <span class="ot">-&gt;</span> m a) <span class="ot">-&gt;</span> b <span class="ot">-&gt;</span> m b</span></code></pre></div>
<p>So our transform function will look something like this:</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="ot">transform ::</span> <span class="dt">Pandoc</span> <span class="ot">-&gt;</span> <span class="dt">Compiler</span> <span class="dt">Pandoc</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a>transform <span class="ot">=</span> walkM codeBlock</span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a><span class="ot">codeBlock ::</span> <span class="dt">Block</span> <span class="ot">-&gt;</span> <span class="dt">Compiler</span> <span class="dt">Block</span></span></code></pre></div>
<p>The Pandoc type consists of metadata and a list of <code>Block</code>s. The Block
type contains the bulk of the structural elements of a document.</p>
<h2 id="inspecting-the-ast">Inspecting the AST</h2>
<p>The pandoc command line program can dump its internal
representation when the <code>native</code> output format is selected.
This can be used to figure out what we can match.</p>
<div class="sourceCode" id="cb5"><pre class="sourceCode markdown"><code class="sourceCode markdown"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="in">~~~{#id .class name=value}</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a><span class="in">content</span></span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a><span class="in">~~~</span></span></code></pre></div>
<p>piped to <code>pandoc -t native</code> will print</p>
<div class="sourceCode" id="cb6"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a>[<span class="dt">CodeBlock</span> (<span class="st">&quot;id&quot;</span>,[<span class="st">&quot;class&quot;</span>],[(<span class="st">&quot;name&quot;</span>,<span class="st">&quot;value&quot;</span>)]) <span class="st">&quot;content&quot;</span>]</span></code></pre></div>
<p>With this information, we can write a function which matches on a
specific CodeBlock class and pipes the content through an external program.
At this point, you can do pretty much anything. Validating syntax.
Reformatting code. You name it.</p>
<div class="sourceCode" id="cb7"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a>codeBlock (<span class="dt">CodeBlock</span> (ident, [<span class="st">&quot;bmc&quot;</span>], namevals) content) <span class="ot">=</span> <span class="kw">do</span></span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">let</span> toArg (a, b) <span class="ot">=</span> [<span class="st">&quot;--&quot;</span> <span class="op">++</span> Text.unpack a, Text.unpack b]</span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">let</span> args <span class="ot">=</span> <span class="fu">concatMap</span> toArg namevals</span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a>  (ec, out, err) <span class="ot">&lt;-</span> unsafeCompiler <span class="op">$</span></span>
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true" tabindex="-1"></a>                    readProcessWithExitCode <span class="st">&quot;bmc&quot;</span> (args <span class="op">++</span> [<span class="st">&quot;-&quot;</span>]) content</span>
<span id="cb7-6"><a href="#cb7-6" aria-hidden="true" tabindex="-1"></a>  <span class="kw">case</span> ec <span class="kw">of</span></span>
<span id="cb7-7"><a href="#cb7-7" aria-hidden="true" tabindex="-1"></a>    <span class="dt">ExitSuccess</span>   <span class="ot">-&gt;</span> <span class="fu">pure</span> <span class="op">$</span> <span class="dt">CodeBlock</span> (ident, [<span class="st">&quot;bmc&quot;</span>], namevals) out</span>
<span id="cb7-8"><a href="#cb7-8" aria-hidden="true" tabindex="-1"></a>    <span class="dt">ExitFailure</span> _ <span class="ot">-&gt;</span> <span class="fu">fail</span> <span class="op">$</span> Text.unpack err</span>
<span id="cb7-9"><a href="#cb7-9" aria-hidden="true" tabindex="-1"></a>codeBlock x <span class="ot">=</span> <span class="fu">pure</span> x</span></code></pre></div>
<p>And now we can write Braille Music code and be sure it passed validation.</p>
<div class="sourceCode" id="cb8"><pre class="sourceCode markdown"><code class="sourceCode markdown"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="in">```{.bmc locale=de width=12}</span></span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a><span class="in">!{ihg&amp;gfeyefg{ihg zhhh&amp;hhh%iii{ihg2k</span></span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a><span class="in">```</span></span></code></pre></div>
<pre class="bmc" data-locale="de" width="12"><code>
  ⠐⠷⠊⠓⠛⠯⠛⠋⠑⠐
⠽⠑⠋⠛⠷⠊⠓⠛
⠵⠓⠓⠓⠯⠓⠓⠓⠐
⠿⠊⠊⠊⠷⠊⠓⠛⠣⠅
</code></pre>
<h2 id="at-a-glance">At a glance</h2>
<p>Putting it all together, here is the source code of the BrailleMusicCompiler module.</p>
<div class="sourceCode" id="cb10"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="ot">{-# LANGUAGE OverloadedStrings #-}</span></span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a><span class="kw">module</span> <span class="dt">BrailleMusicCompiler</span> ( brailleMusicCompiler ) <span class="kw">where</span></span>
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-4"><a href="#cb10-4" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Data.Text</span> (<span class="dt">Text</span>)</span>
<span id="cb10-5"><a href="#cb10-5" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="kw">qualified</span> <span class="dt">Data.Text</span> <span class="kw">as</span> <span class="dt">Text</span></span>
<span id="cb10-6"><a href="#cb10-6" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Hakyll</span> ( <span class="dt">Compiler</span>, <span class="dt">Item</span></span>
<span id="cb10-7"><a href="#cb10-7" aria-hidden="true" tabindex="-1"></a>              , defaultHakyllReaderOptions, defaultHakyllWriterOptions</span>
<span id="cb10-8"><a href="#cb10-8" aria-hidden="true" tabindex="-1"></a>              , pandocCompilerWithTransformM</span>
<span id="cb10-9"><a href="#cb10-9" aria-hidden="true" tabindex="-1"></a>              , unsafeCompiler )</span>
<span id="cb10-10"><a href="#cb10-10" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">System.Exit</span> ( <span class="dt">ExitCode</span>(..) )</span>
<span id="cb10-11"><a href="#cb10-11" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">System.Process.Text</span> ( readProcessWithExitCode )</span>
<span id="cb10-12"><a href="#cb10-12" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Text.Pandoc</span> ( <span class="dt">Block</span>(<span class="dt">CodeBlock</span>), <span class="dt">Pandoc</span> )</span>
<span id="cb10-13"><a href="#cb10-13" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Text.Pandoc.Walk</span> ( walkM )</span>
<span id="cb10-14"><a href="#cb10-14" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-15"><a href="#cb10-15" aria-hidden="true" tabindex="-1"></a><span class="ot">brailleMusicCompiler ::</span> <span class="dt">Compiler</span> (<span class="dt">Item</span> <span class="dt">String</span>)</span>
<span id="cb10-16"><a href="#cb10-16" aria-hidden="true" tabindex="-1"></a>brailleMusicCompiler <span class="ot">=</span></span>
<span id="cb10-17"><a href="#cb10-17" aria-hidden="true" tabindex="-1"></a>  pandocCompilerWithTransformM defaultHakyllReaderOptions</span>
<span id="cb10-18"><a href="#cb10-18" aria-hidden="true" tabindex="-1"></a>                               defaultHakyllWriterOptions</span>
<span id="cb10-19"><a href="#cb10-19" aria-hidden="true" tabindex="-1"></a>                               transform</span>
<span id="cb10-20"><a href="#cb10-20" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-21"><a href="#cb10-21" aria-hidden="true" tabindex="-1"></a><span class="ot">transform ::</span> <span class="dt">Pandoc</span> <span class="ot">-&gt;</span> <span class="dt">Compiler</span> <span class="dt">Pandoc</span></span>
<span id="cb10-22"><a href="#cb10-22" aria-hidden="true" tabindex="-1"></a>transform <span class="ot">=</span> walkM codeBlock</span>
<span id="cb10-23"><a href="#cb10-23" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-24"><a href="#cb10-24" aria-hidden="true" tabindex="-1"></a><span class="ot">codeBlock ::</span> <span class="dt">Block</span> <span class="ot">-&gt;</span> <span class="dt">Compiler</span> <span class="dt">Block</span></span>
<span id="cb10-25"><a href="#cb10-25" aria-hidden="true" tabindex="-1"></a>codeBlock (<span class="dt">CodeBlock</span> (ident, [<span class="st">&quot;bmc&quot;</span>], namevals) content) <span class="ot">=</span> <span class="kw">do</span></span>
<span id="cb10-26"><a href="#cb10-26" aria-hidden="true" tabindex="-1"></a>  <span class="kw">let</span> toArg (a, b) <span class="ot">=</span> [<span class="st">&quot;--&quot;</span> <span class="op">++</span> Text.unpack a, Text.unpack b]</span>
<span id="cb10-27"><a href="#cb10-27" aria-hidden="true" tabindex="-1"></a>  <span class="kw">let</span> args <span class="ot">=</span> <span class="fu">concatMap</span> toArg namevals</span>
<span id="cb10-28"><a href="#cb10-28" aria-hidden="true" tabindex="-1"></a>  result <span class="ot">&lt;-</span> unsafeCompiler (bmc args content)</span>
<span id="cb10-29"><a href="#cb10-29" aria-hidden="true" tabindex="-1"></a>  <span class="kw">case</span> result <span class="kw">of</span></span>
<span id="cb10-30"><a href="#cb10-30" aria-hidden="true" tabindex="-1"></a>    <span class="dt">Left</span> e  <span class="ot">-&gt;</span> <span class="fu">fail</span> <span class="op">$</span> Text.unpack e</span>
<span id="cb10-31"><a href="#cb10-31" aria-hidden="true" tabindex="-1"></a>    <span class="dt">Right</span> r <span class="ot">-&gt;</span> <span class="fu">pure</span> <span class="op">$</span> <span class="dt">CodeBlock</span> (ident, [<span class="st">&quot;bmc&quot;</span>], namevals) r</span>
<span id="cb10-32"><a href="#cb10-32" aria-hidden="true" tabindex="-1"></a>codeBlock x <span class="ot">=</span> <span class="fu">pure</span> x</span>
<span id="cb10-33"><a href="#cb10-33" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-34"><a href="#cb10-34" aria-hidden="true" tabindex="-1"></a><span class="ot">bmc ::</span> [<span class="dt">String</span>] <span class="ot">-&gt;</span> <span class="dt">Text</span> <span class="ot">-&gt;</span> <span class="dt">IO</span> (<span class="dt">Either</span> <span class="dt">Text</span> <span class="dt">Text</span>)</span>
<span id="cb10-35"><a href="#cb10-35" aria-hidden="true" tabindex="-1"></a>bmc args music <span class="ot">=</span> <span class="kw">do</span></span>
<span id="cb10-36"><a href="#cb10-36" aria-hidden="true" tabindex="-1"></a>  (ec, out, err) <span class="ot">&lt;-</span> readProcessWithExitCode <span class="st">&quot;bmc&quot;</span> (args<span class="op">++</span>[<span class="st">&quot;-&quot;</span>]) music</span>
<span id="cb10-37"><a href="#cb10-37" aria-hidden="true" tabindex="-1"></a>  <span class="fu">pure</span> <span class="op">$</span> <span class="kw">case</span> ec <span class="kw">of</span></span>
<span id="cb10-38"><a href="#cb10-38" aria-hidden="true" tabindex="-1"></a>    <span class="dt">ExitSuccess</span> <span class="ot">-&gt;</span> <span class="dt">Right</span> out</span>
<span id="cb10-39"><a href="#cb10-39" aria-hidden="true" tabindex="-1"></a>    <span class="dt">ExitFailure</span> _ <span class="ot">-&gt;</span> <span class="dt">Left</span> err</span></code></pre></div>
<h2 id="usage">Usage</h2>
<p>To use your new custom pandoc based compiler, all you have to do is
replace <code>pandocCompiler</code> in your existing <code>site.hs</code> with whatever
you choose as name for your custom compiler. For instance, this article
has been processed with the following <code>match</code> rule in <code>site.hs</code>.</p>
<div class="sourceCode" id="cb11"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a>    match <span class="st">&quot;blog/*&quot;</span> <span class="op">$</span> <span class="kw">do</span></span>
<span id="cb11-2"><a href="#cb11-2" aria-hidden="true" tabindex="-1"></a>        route <span class="op">$</span> setExtension <span class="st">&quot;html&quot;</span></span>
<span id="cb11-3"><a href="#cb11-3" aria-hidden="true" tabindex="-1"></a>        compile <span class="op">$</span> brailleMusicCompiler</span>
<span id="cb11-4"><a href="#cb11-4" aria-hidden="true" tabindex="-1"></a>              <span class="op">&gt;&gt;=</span> saveSnapshot <span class="st">&quot;content&quot;</span></span>
<span id="cb11-5"><a href="#cb11-5" aria-hidden="true" tabindex="-1"></a>              <span class="op">&gt;&gt;=</span> loadAndApplyTemplate <span class="st">&quot;templates/post.html&quot;</span>    (postCtx tags)</span>
<span id="cb11-6"><a href="#cb11-6" aria-hidden="true" tabindex="-1"></a>              <span class="op">&gt;&gt;=</span> loadAndApplyTemplate <span class="st">&quot;templates/default.html&quot;</span> (postCtx tags)</span>
<span id="cb11-7"><a href="#cb11-7" aria-hidden="true" tabindex="-1"></a>              <span class="op">&gt;&gt;=</span> relativizeUrls</span></code></pre></div>
<h2 id="advent-of-haskell">Advent of Haskell</h2>
<p>This article is part of <a href="https://adventofhaskell.com/">Advent of Haskell</a> 2020.</p>]]></summary>
</entry>
<entry>
    <title>img2brl converts images to Braille</title>
    <link href="https://blind.guru/blog/2020-10-27-img2brl.html" />
    <id>https://blind.guru/blog/2020-10-27-img2brl.html</id>
    <published>2020-10-27T00:00:00Z</published>
    <updated>2020-10-27T00:00:00Z</updated>
    <summary type="html"><![CDATA[<p>Around 2013, I wrote a very small web service to convert images
in various formats to Unicode Braille. For a while now, the live
installation was apparently broken due to a server upgrade.
However, this has been fixed now and <a href="https://img2brl.delysid.org/">img2brl</a>
is online again.</p>]]></summary>
</entry>
<entry>
    <title>No more google for console junkies</title>
    <link href="https://blind.guru/blog/2019-11-25-endofgoogle.html" />
    <id>https://blind.guru/blog/2019-11-25-endofgoogle.html</id>
    <published>2019-11-25T00:00:00Z</published>
    <updated>2019-11-25T00:00:00Z</updated>
    <summary type="html"><![CDATA[<p>An era ends in the last weeks of 2019.</p>
<p>Since about two weeks, I am no longer able to use
Google with my favorite text-mode web browser, <a href="https://lynx.invisible-island.net/">Lynx</a>.</p>
<p>It started about a month ago, when I noticed that sometimes,
after submitting my search query, I was presented with a search result
page which didn’t allow to invoke the actual links.
When I reloaded the start page, it suddenly worked again.
So I guess Google was doing experiments with its users.
If someone didn’t actually click on any result links, and reloaded
the main page, they gave them the old start page.</p>
<p>But now, the redesign seems to be finalized, and I am no
longer able to use Google with Lynx at all.</p>
<p>I don’t have a X11 session open all the time, and I don’t have
a Windows PC running next to my Linux workstation.
So I don’t have an easy way to switch to a graphical browser just
to be able to research things while I do my work.</p>
<p>Luckily, there is duckduckgo. However, I have to admit,
the search results of duckduckgo are by far inferior to what
Google used to give. However, being a blind person, I
guess I have to accept that Google doesn’t care anymore.</p>
<p>Maybe I should delete my Google account as a consequence.</p>
<p>Bye bye mainstream, hello ghetto.</p>
<h1 id="update">UPDATE</h1>
<p>This rant has been <a href="https://news.ycombinator.com/item?id=21626995">featured on Hacker News</a>.
A Google dev <a href="https://news.ycombinator.com/item?id=21635575">noticed the thread</a> and managed to get basic Lynx support
back online in just a few hours. I am impressed and grateful.
However, the new design is still a step backwards.
It is less clear which link will take you to which site, and there is no way to
retrieve cached versions of websites anymore.</p>]]></summary>
</entry>
<entry>
    <title>The lang= attribute in HTML</title>
    <link href="https://blind.guru/blog/2018-08-30-htmllang.html" />
    <id>https://blind.guru/blog/2018-08-30-htmllang.html</id>
    <published>2018-08-30T00:00:00Z</published>
    <updated>2018-08-30T00:00:00Z</updated>
    <summary type="html"><![CDATA[<p>There is one very small change to your HTML that might help
international users of your site that rely on speech synthesis to read
your site. The HTML <a href="https://www.w3schools.com/tags/att_lang.asp">lang=</a>
attribute.</p>
<!--more-->
<h1 id="the-story">The story</h1>
<p>Non-native english speaking blind people have their default speech
language typically set to their native language. When they end up
browsing to a site in english (or any language other than their native
one for that matter) the screen reader starts to read english with
pronounciation from their native language. While some people start to
understand such speech output after a while, it is really a pain to work
with. Of course, you can switch to a different speech language manually,
but that takes time, and people end up not doing it in a lot of
situations.</p>
<p>Some screen readers have automatic language detection implemented, but
it fails to work correctly in many cases, which is why most users have
autodetection actually turned off.</p>
<h1 id="the-simple-fix">The simple fix</h1>
<p>Use the <code>lang=</code> attribute to declare what language your document (or
parts of your document) uses.</p>
<p>A <code>lang=</code> attribute on the top-level <code>&lt;html&gt;</code> tag will let screen
readers know what the default language of this document is.</p>
<p>This is a very simple change that you might be able to do in a few
seconds/minutes, depending on what framework you use.</p>
<p>Please consider declaring your document language, it will make the
overall experience of surfing the net for non-english blind users a lot
nicer.</p>
<h1 id="examples">Examples</h1>
<p>I am writing this article because I got frustrated with <a href="https://news.ycombinator.com/">Hacker
News</a> not declaring <code>lang="en"</code>. Whenever
I visit the site, I get all the content read with a german speaker.</p>
<p>However, HN is definitely not the only bigger site that gets this wrong.</p>
<h1 id="please-check-your-projects">Please check your projects</h1>
<p>If you are maintaining websites, please take the time and check if you
are declaring the document language. If not, please consider adding this
very small change to your site.</p>
<h1 id="guess-that-key">Guess that key</h1>
<p>A few years ago, I created a small web game to demonstrate what sort of
wrongly-pronounced words you have to deal with as a blind user if speech
language settings do not fully work.</p>
<p>You can find it <a href="https://guess-that-key.blind.guru/">here</a>.</p>]]></summary>
</entry>
<entry>
    <title>I pushed an implementation of myself to GitHub</title>
    <link href="https://blind.guru/blog/2018-01-14-MarioLANG.html" />
    <id>https://blind.guru/blog/2018-01-14-MarioLANG.html</id>
    <published>2018-01-14T00:00:00Z</published>
    <updated>2018-01-14T00:00:00Z</updated>
    <summary type="html"><![CDATA[<p>Roughly 4 years ago, I <a href="https://blind.guru/i-am-a-programming-language.html">mentioned</a> that there appears to be an esotieric
programming language which shares my full name.</p>
<p>I know, it is really late, but two days ago, I discovered <a href="https://racket-lang.org/">Racket</a>.
As a Lisp person, I immediately felt at home.
And realizing how the language dispatch mechanism works, I couldn’t resist
and write a <a href="https://github.com/mlang/mario">Racket implementation</a> of <a href="http://esolangs.org/wiki/MarioLANG">MarioLANG</a>. A nice play on words
and a good toy project to get my feet wet.</p>
<p><a href="https://racket-lang.org/">Racket</a> programs always start with <code>#lang</code>. How convenient.
<a href="http://esolangs.org/wiki/MarioLANG">MarioLANG</a> programs for <a href="https://racket-lang.org/">Racket</a> therefore look something like this:</p>
<pre><code>#lang mario
++++++++++++
===========+:
           ==</code></pre>
<p>So much about abusing coincidences. Phew, this was a fun weekend project!
And it has some potential for more challenges. Right now, it is only an interpreter,
because it appears to be tricky to compile a 2d instruction “space” to traditional
code. <a href="http://esolangs.org/wiki/MarioLANG">MarioLANG</a> does not only allow for nested loops as <a href="http://en.wikipedia.org/wiki/BrainFuck">BrainFuck</a> does,
it also includes weird concepts like the reversal of the instruction pointer direction.
Coupled with the “skip” (<code>[</code>) instruction, this allow to create
loops which have two exit conditions and reverse code execution
on every pass. Something like this:</p>
<pre><code>@[ some brainfuck [@
====================</code></pre>
<p>And since this is a 2d programming language, this theoretical loop could be
entered by jumping onto any of the instruction inbetween from above.
And, the heading could be either leftward or rightward when entering.</p>
<p>Discovering these patterns and translating them to compilable code
is quite beyond me right now. Lets see what time will bring.</p>]]></summary>
</entry>
<entry>
    <title>Qt 5.11 will fix major issues with JAWS on Windows</title>
    <link href="https://blind.guru/blog/2017-11-28-qtwin.html" />
    <id>https://blind.guru/blog/2017-11-28-qtwin.html</id>
    <published>2017-11-28T00:00:00Z</published>
    <updated>2017-11-28T00:00:00Z</updated>
    <summary type="html"><![CDATA[<p>I published a <a href="https://blind.guru/qta11y.html">rant</a> about problems with Qt accessibility
on Windows a few months ago. This posting got some
unusual amount of attention, as it was shared on HackerNews
and almost went to the top for a few minutes.</p>
<p>Apparently, ranting about it after a year of being ignored was not
the worst thing to do. I can now confirm that the current
dev version of Qt works properly with JAWS for Windows
and QTextEdit widgets. This is quite a substantial fix, as it
will likely improve the accessibility of many Windows applications
written in Qt.</p>
<p>So this <a href="https://bugreports.qt.io/browse/QTBUG-53024">bug</a> is finally (after more then a year of waiting) fixed.
Thanks to André de la Rocha for implementing UI Automation
support, which is apparently what was missing to make JAWS happy.</p>]]></summary>
</entry>
<entry>
    <title>If your software should be cross platform and accessible, forget about Qt</title>
    <link href="https://blind.guru/blog/2017-08-07-qta11y.html" />
    <id>https://blind.guru/blog/2017-08-07-qta11y.html</id>
    <published>2017-08-07T00:00:00Z</published>
    <updated>2017-08-07T00:00:00Z</updated>
    <summary type="html"><![CDATA[<p>A few years ago, I started to write software which primary
audience is going to be blind musicians. I did a small <a href="https://www.youtube.com/watch?v=TjfKDJm_xmI">presentation</a>
of the UI at <a href="https://debconf15.debconf.org/">DebConf15</a>.</p>
<p>Most of the functionality
is in a compiler-alike backend. But eventually, I wanted to create
a user interface to improve the interactive experience.</p>
<p>So, the problem again: which toolkit to choose which would be accessible
on most platforms? Last time I needed to solve a similar
problem, I used Java/Swing. This has its problems, but
it actually works on Windows, Linux and (supposedly) Mac.
This time around, my implementation language is C++, so Swing
didn’t look that interesting. It appears there is not
much that fullfils these requirements. Qt looked like it could.
But since I had my bad experiences already with Qt claiming
accessibility they really never implemented, I was at least
a bit cautious. Around 10 years ago, when Qt 4 was released,
I found that the documentation claimed that Qt4 was accessible
on Linux, but it really never was until a very late 4.x release.
This information was a blatant lie, trying to lure uninformed programmers
into using Qt, much to the disservice of their disabled users.
If you ask a random blind Windows user who knows a bit about toolkits,
they will readily tell you that they hate every app written in Qt.</p>
<p>With this knowledge, and the spirit of “We can change the world”
I wrote a private mail to the person responsible for maintaining Qt
accessibility. I explained to them that I am about to choose Qt as the UI
platform for my program, and that my primary audience is users that
rely on Accessibility. I also explained that cross-platform support
(esp. good support on Windows) is a necessary requirement for
my project. I basically got a nice marketing speak answer
back, but when I read it back then, I didn’t fully realize that just yet.
The tone basicallly: “No problem. Qt works on Linux, Mac and Windows,
and if you find any problems, just report them to us and we are going
to fix them.” Well, I was aware that I am not a paying
customer of Qt Company, so the promise above is probbably
a bit vague (I thought), but still, it sounded quite encouraging.</p>
<p>So off I went, and started to learn enough Qt to implement
the simple user interface I wanted. First tests on
Linux seemed to work, that is nice. After a while, I started
to test on Windows. And BANG, of course, there is a “hidden” problem.
The most wide-spread (commercial) screen reader used by most blind people
somehow does not see the content of text entry widgets.
This was and still is a major problem for my project. I have a number
of text entry fields in my UI. Actually, the main part of
the UI is a simple editor, so you might see the problem already.</p>
<p>So some more testing was done, just to realize that yes, text entry
fields indeed do not work with the most widely used screen
reader on Windows. While other screen readers seemed to work (NVDA)
it is simply not feasable to ask my future users to switch to a different
screen reader just for a single program. So I either needed to get JAWS
fixed, or drop Qt.</p>
<p>Well, after a lot of testing, I ended up submitting a <a href="https://bugreports.qt.io/browse/QTBUG-53024">bug</a> to the Qt tracker.
That was a little over a year ago.
The turnaround time of private mail was definitely faster.</p>
<p>And now I get a reply to my bug explaining that JAWS was
never a priority, still is not, and that my problem will
probably go away after a rewrite which has no deadline yet.</p>
<p>Why did I expect this already?</p>
<p>At least now I know why no blind users wants to have any Qt on their machines.</p>
<p>If you want to write cross-platform accessible software:
You definitely should not use Qt. And no other Free Software
toolkit for that matter, because they basically all dont give a shit
about accessibility on non-Linux platforms. Yes, GTK has
a Windows port, but that isn’t accessible at all.
Yes, wxWindows has a Windows port, but that has problems with, guess what, text entry fields (at least last time I checked).</p>
<p>Free Software is <em>NOT</em> about Accessibility or equality.
I see evidence for that claim since more then 15 years now.
It is about coolness, self-staging, scratch-your-<em>own</em>-itchness and things like that.
When Debian released Jessie, I was told that something like
Accessibility is not important enough to delay the release. If GNOME
just broke all the help system by switching to not-yet-accessible
webkit, that is just bad luck, I was told. But it is outside
of the abilities of package maintainers to ensure that what we ship is
accessible.</p>
<p>I hereby officially give up. And I admit my own
stupidity. Sorry for claiming Free Software would be a good thing for the world.
It is definitely not for my kin. If Free Software
ever takes over, the blind will be unable to use their computers.</p>
<p>Don’t get me wrong. I love my command-line.
But as the well-known saying goes: “Free Software
will be ready for the desktop user, perhaps, next year?”</p>
<p>The scratch-your-own-itch philosophy simply doesn’t work
together with a broad list of user requirements.
If you want to support users with disabilities, you probably
should not rely on hippie coders right now.</p>
<p>I repeat: If you want to write compliant software, that would
be also useable to people with disabilities, you can not use
Qt. For now, you will need to write a native UI for every
platform you want to support. Oh, and do not believe
Qt Company marketing texts, your users will suffer if you do.</p>]]></summary>
</entry>
<entry>
    <title>Squarepusher's Shobaleader One</title>
    <link href="https://blind.guru/blog/2016-12-20-shobaleader-one.html" />
    <id>https://blind.guru/blog/2016-12-20-shobaleader-one.html</id>
    <published>2016-12-20T00:00:00Z</published>
    <updated>2016-12-20T00:00:00Z</updated>
    <summary type="html"><![CDATA[<p>I recently was lucky enough to see one of my long-time favourite
drum and bass artists live! Squarepusher! I know and love his music
since the late 90s.</p>
<p>My girlfriend got us tickets for the
<a href="http://www.porgy.at/prog-01.php?id=7843">Shobaleader One performance at Progy &amp; Bess in Vienna</a>. It was fantastic!
90 minutes of high energy jazz.</p>
<p>As a personal memory, I captured one of my favourite Squarepusher tracks,
<a href="https://www.youtube.com/watch?v=mH4_axa00cQ">Cooper's World</a>. This is another case of #unseenphotography.</p>
<p>While I am usually not very much into jazz,
I like this fusion of dnb and jazz very much.</p>]]></summary>
</entry>
<entry>
    <title>Upgrading GlusterFS from Wheezy to Stretch</title>
    <link href="https://blind.guru/blog/2016-12-20-glusterfs-wheezy-stretch.html" />
    <id>https://blind.guru/blog/2016-12-20-glusterfs-wheezy-stretch.html</id>
    <published>2016-12-20T00:00:00Z</published>
    <updated>2016-12-20T00:00:00Z</updated>
    <summary type="html"><![CDATA[<p>We are about to upgrade one of our GlusterFS-based storage systems at work.
Fortunately, I was worrying about the upgrade procedure for the Debian
packages not being tested by the maintainers. It turns out I was right.
Simply upgrading the packages without manual intervention will apparently
render your GlusterFS server unusable.</p>
<h1 id="basic-setup">Basic setup</h1>
<p>I have only tested the most basic distributed GlusterFS setup.
No replication whatsoever. We have two GlusterFS servers, storage1 and storage2.
A peering between both has been established, and a very basic volume
has been configured:</p>
<pre class="shell"><code>storage1:~# gluster
gluster&gt; peer status
Number of Peers: 1

Hostname: storage2
Uuid: 2d22cc13-2252-4cf1-bfe9-3d27fa2fbc29
State: Peer in Cluster (Connected)
gluster&gt; volume create data storage1:/srv/data storage2:/srv/data
...
gluster&gt; volume start data
...
gluster&gt; volume info

Volume Name: data
Type: Distribute
Volume ID: e2bd5767-4b33-4e57-9320-91ca76f52d56
Status: Started
Number of Bricks: 2
Transport-type: tcp
Bricks:
Brick1: storage1:/srv/data
Brick2: storage2:/srv/data</code></pre>
<p>For the test setup, I populated the volume with a number of files.</p>
<h1 id="upgrading-from-wheezy-to-jessie">Upgrading from Wheezy to Jessie</h1>
<p>To be save, stop the volume before you begin with the package upgrade:</p>
<pre class="shell"><code>gluster&gt; volume stop data</code></pre>
<p>And now perform your dist-upgrade.</p>
<p>After the upgrade, you will have to perform two manual clean ups.
Both actions have to be performed on all storage servers.</p>
<h2 id="etcglusterd-is-now-varlibglusterd">/etc/glusterd is now /var/lib/glusterd</h2>
<p>The package maintainers have apparently neglected to take care of this one.
You manually need to copy the old configuration files over.</p>
<pre class="shell"><code>storage1:~# cd /var/lib/glusterd &amp;&amp; cp -r /etc/glusterd/* .</code></pre>
<h2 id="put-volume-id-in-extended-attribute">Put volume-id in extended attribute</h2>
<p>GlusterFS 3.5 requires the volume-id in an extended directory attribute.
This is also not automatically handled during package upgrade.</p>
<pre class="shell"><code>storage1:~# vol=data
storage1:~# volid=$(grep volume-id /var/lib/glusterd/vols/$vol/info | cut -d= -f2 | sed &#39;s/-//g&#39;)
storage1:~# setfattr -n trusted.glusterfs.volume-id -v 0x$volid /srv/data</code></pre>
<p>With these two steps performed on all GlusterFS servers, you should
now be able to start and mount your volume again in Debian Jessie.</p>
<p>Do not forget to explicitly stop the volume again before continueing with
the next upgrade step.</p>
<h1 id="upgrading-from-jessie-to-stretch">Upgrading from Jessie to Stretch</h1>
<p>After you have dist-upgraded to Stretch, there is yet another
manual step you have to take to convert the volume metadata to the
new layout in GlusterFS 3.8. Make sure you have stopped your volumes
and the GlusterFS server.</p>
<pre class="shell"><code>storage1:~# service glusterfs-server stop</code></pre>
<p>Now run the following command:</p>
<pre class="shell"><code>storage1:~# glusterd --xlator-option *.upgrade=on -N</code></pre>
<p>Now you should be ready to start your volume again:</p>
<pre class="shell"><code>storage1:~# service glusterfs-server start
storage1:~# gluster
gluster&gt; volume start data</code></pre>
<p>And mount it:</p>
<pre class="shell"><code>client:~# mount -t glusterfs storage1:/data /mnt</code></pre>
<p>You should now be running GlusterFS 3.8 and your files should still all be there.</p>]]></summary>
</entry>
<entry>
    <title>A Raspberry Pi Zero in a Handy Tech Active Star 40 Braille Display</title>
    <link href="https://blind.guru/blog/2016-06-12-brlpi.html" />
    <id>https://blind.guru/blog/2016-06-12-brlpi.html</id>
    <published>2016-06-12T00:00:00Z</published>
    <updated>2016-06-12T00:00:00Z</updated>
    <summary type="html"><![CDATA[<p>TL;DR: I put a $5 <a href="https://www.raspberrypi.org/products/pi-zero/">Raspberry Pi Zero</a>, a Bluetooth USB dongle, and the
required adapter cable into my new <a href="https://handytech.de/en/products/braille-displays-and-note-takers/braille-displays/active-star">Handy Tech Active Star 40</a> braille
display. An internal USB port provides the power. This has transformed
my braille display into an ARM-based, monitorless, Linux laptop that has
a keyboard and a braille display. It can be charged/powered via USB so it can
also be run from a power bank or a solar charger, thus potentially being able
to run for days, rather than just hours, without needing a standard wall-jack.</p>
<p><img src="https://blind.guru/images/as40-rpi.jpg" alt="[picture: a Raspberry Pi Zero embedded within an Active Star 40]" /></p>
<p><img src="https://blind.guru/images/as40-kbd.jpg" alt="[picture: a braille display with a keyboard on top and a Raspberry Pi Zero inside]" /></p>
<div class="contents">

</div>
<h1 id="some-background-on-braille-display-form-factors">Some Background on Braille Display Form Factors</h1>
<p>Braille displays come in various sizes. There are
models tailored for desktop use (with 60 cells or more), models tailored
for portable use with a laptop (usually with 40 cells), and, nowadays,
there are even models tailored for on-the-go use with a smartphone or similar
(with something like 14 or 18 cells).</p>
<p>Back in the old days, braille displays were rather massive.
A 40-cell braille display was typically about the size of a 13” laptop.
In modern times, manufacturers have managed to reduce the size of the internals
such that a 40-cell display can be placed in front of a laptop or keyboard
instead of placing the laptop on top of the braille display.</p>
<p>While this is a nice achievement, I personally haven’t found it to be
very convenient because you now have to place two physically separate
devices on your lap. It’s OK if you have a real desk,
but, at least in my opinion, if you try to use your laptop as its name suggests,
it’s actually inconvenient to use a small form factor, 40-cell display.</p>
<p>For this reason, I’ve been waiting for a long-promised new model
in the Handy Tech Star series. In 2002, they released
the Handy Tech Braille Star 40, which is a 40-cell braille
display with enough space to put a laptop directly on top
of it. To accommodate larger laptop models, they even built in a little
platform at the back that can be pulled out to effectively enlarge the
top surface.
Handy Tech has now released a new model, the Active Star 40,
that has essentially the same layout but modernized internals.</p>
<p><img src="https://blind.guru/images/as40-plain.jpg" alt="[picture: a plain Active Star 40]" /></p>
<p>You can still pull out the little platform to increase the space
that can be used to put something on top.</p>
<p><img src="https://blind.guru/images/as40-laptop.jpg" alt="[picture: an Active Star 40 with extended platform and a laptop on top]" /></p>
<p>But, most conveniently,
they’ve designed in an empty compartment, roughly the size of a modern
smartphone, beneath the platform. The original idea was to actually
put a smartphone inside, but this has turned out (at least to me)
to not be very feasible. Fortunately, they thought about the
need for electricity and added a Micro USB cable terminating within the
newly created, empty compartment.</p>
<p>My first idea was to put a conventional Raspberry Pi inside.
When I received the braille display, however, we immediately
noticed that a standard-sized rpi is roughly 3mm too high
to fit into the empty compartment.</p>
<p>Fortunately, though, a co-worker noticed that the <a href="https://www.raspberrypi.org/products/pi-zero/">Raspberry Pi Zero</a>
was available for order. The Raspberry Pi Zero is a lot thinner,
and fits perfectly inside (actually, I think there’s enough space
for two, or even three, of them). So we ordered one, along with some
accessories like a 64GB SDHC card, a Bluetooth dongle, and
a Micro USB adapter cable. The hardware arrived a few days later, and was
immediately bootstrapped with the assistance of very helpful friends.
It works like a charm!</p>
<h1 id="technical-details">Technical Details</h1>
<p>The backside of the Handy Tech Active Star 40 features two USB host ports
that can be used to connect devices such as a keyboard. A small form-factor,
USB keyboard with a magnetic clip-on is included. When a USB keyboard
is connected, and when the display is used via Bluetooth, the braille display
firmware additionally offers the Bluetooth HID profile, and key press/release
events received via the USB port are passed through to it.</p>
<p>I use the Bluetooth dongle for all my communication needs.
Most importantly, <a href="http://brltty.com/">BRLTTY</a> is used as a console screen reader.
It talks to the braille display via Bluetooth (more precisely, via an RFCOMM channel).</p>
<p>The keyboard connects through to Linux via the Bluetooth HID profile.</p>
<p>Now, all that is left is network connectivity. To keep the energy
consumption as low as possible, I decided to go for Bluetooth PAN.
It appears that the tethering mode of my mobile phone works (albeit with a quirk),
so I can actually access the internet as long as I have cell phone reception.
Additionally, I configured a Bluetooth PAN access point on my desktop
machines at home and at work, so I can easily (and somewhat more reliably)
get IP connectivity for the rpi when I’m near one of these machines.
I plan to configure a classic Raspberry Pi as a mobile Bluetooth access point.
It would essentially function as a Bluetooth to ethernet adapter, and should
allow me to have network connectivity in places where I don’t want to use my phone.</p>
<h1 id="bluez-5-and-pan">BlueZ 5 and PAN</h1>
<p>It was a bit challenging to figure out how to actually configure
Bluetooth PAN with <a href="http://www.bluez.org/">BlueZ</a> 5. I found the bt-pan python script
(see below) to be the only way so far to configure PAN without a GUI.</p>
<p>It handles both ends of a PAN network, configuring a server and a client.
Once instructed to do so (via D-Bus) in client mode, BlueZ will
create a new network device - bnep0 - once a connection to a server has been
established. Typically, DHCP is used to assign IP addresses
for these interfaces. In server mode, BlueZ needs to know the
name of a bridge device to which it can add a slave device for
each incoming client connection. Configuring an address for
the bridge device, as well as running a DHCP server + IP Masquerading
on the bridge, is usually all you need to do.</p>
<h1 id="a-bluetooth-pan-access-point-with-systemd">A Bluetooth PAN Access Point with Systemd</h1>
<p>I’m using systemd-networkd to configure the bridge device.</p>
<p>/etc/systemd/network/pan.netdev:</p>
<pre><code>[NetDev]
Name=pan
Kind=bridge
ForwardDelaySec=0</code></pre>
<p>/etc/systemd/network/pan.network:</p>
<pre><code>[Match]
Name=pan

[Network]
Address=0.0.0.0/24
DHCPServer=yes
IPMasquerade=yes</code></pre>
<p>Now, BlueZ needs to be told to configure a NAP profile.
To my surprise, there seems to be no way to do this with stock BlueZ 5.36
utilities. Please correct <a href="mailto:mlang@blind.guru">me</a> if I’m wrong.</p>
<p>Luckily, I found a very nice <a href="http://blog.fraggod.net/2015/03/28/bluetooth-pan-network-setup-with-bluez-5x.html">blog post</a>, as well as an accommodating
<a href="https://github.com/mk-fg/fgtk/blob/master/bt-pan">Python script</a> that performs the required D-Bus calls.</p>
<p>For convenience, I use a Systemd service to invoke the script
and to ensure that its dependencies are met.</p>
<p>/etc/systemd/system/pan.service:</p>
<pre><code>[Unit]
Description=Bluetooth Personal Area Network
After=bluetooth.service systemd-networkd.service
Requires=systemd-networkd.service
PartOf=bluetooth.service

[Service]
Type=notify
ExecStart=/usr/local/sbin/pan

[Install]
WantedBy=bluetooth.target</code></pre>
<p>/usr/local/sbin/pan:</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="co">#!/bin/sh</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a><span class="co"># Ugly hack to work around #787480</span></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a><span class="ex">iptables</span> <span class="at">-F</span></span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a><span class="ex">iptables</span> <span class="at">-t</span> nat <span class="at">-F</span></span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a><span class="ex">iptables</span> <span class="at">-t</span> mangle <span class="at">-F</span></span>
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true" tabindex="-1"></a><span class="ex">iptables</span> <span class="at">-t</span> nat <span class="at">-A</span> POSTROUTING <span class="at">-o</span> eth0 <span class="at">-j</span> MASQUERADE</span>
<span id="cb4-7"><a href="#cb4-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-8"><a href="#cb4-8" aria-hidden="true" tabindex="-1"></a><span class="bu">exec</span> /usr/local/sbin/bt-pan <span class="at">--systemd</span> <span class="at">--debug</span> server pan</span></code></pre></div>
<p>This last file wouldn’t be necessary if IPMasquerade= were
supported in Debian right now (see <a href="https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=787480">#787480</a>).</p>
<p>After the obligatory <span class="title-ref">systemctl daemon-reload</span> and <span class="title-ref">systemctl restart systemd-networkd</span>,
you can start your Bluetooth Personal Area Network with <span class="title-ref">systemctl start pan</span>.</p>
<h1 id="bluetooth-pan-client-with-systemd">Bluetooth PAN Client with Systemd</h1>
<p>Configuring the client is also quite easy to do with Systemd.</p>
<p>/etc/systemd/network/pan-client.network:</p>
<pre><code>[Match]
Name=bnep*

[Network]
DHCP=yes</code></pre>
<p>/etc/systemd/system/pan@.service:</p>
<pre><code>[Unit]
Description=Bluetooth Personal Area Network client

[Service]
Type=notify
ExecStart=/usr/local/sbin/bt-pan --debug --systemd client %I --wait</code></pre>
<p>Now, after the usual configuration reloading, you should be able to connect
to a specific Bluetooth access point with:</p>
<pre><code>systemctl start pan@00:11:22:33:44:55</code></pre>
<h1 id="pairing-via-the-command-line">Pairing via the Command Line</h1>
<p>Of course, the server and client-side service configuration require
a pre-existing pairing between the server and each of its clients.</p>
<p>On the server, start bluetoothctl and issue the following commands:</p>
<pre><code>power on
agent on
default-agent
scan on
scan off
pair XX:XX:XX:XX:XX:XX
trust XX:XX:XX:XX:XX:XX</code></pre>
<p>Once you’ve set scan mode to on, wait a few seconds until
you see the device you’re looking for scroll by. Note its
device address, and use it for the pair and (optional) trust commands.</p>
<p>On the client, the sequence is essentially the same except that
you don’t need to issue the trust command. The server needs
to trust a client in order to accept NAP profile connections from it
without waiting for manual confirmation by the user.</p>
<p>I’m actually not sure if this is the optimal sequence of commands.
It might be enough to just pair the client with the server
and issue the trust command on the server,
but I haven’t tried this yet.</p>
<h1 id="enabling-use-of-the-bluetooth-hid-profile">Enabling Use of the Bluetooth HID Profile</h1>
<p>Essentially the same as above also needs to be done
in order to use the Bluetooth HID profile of the Active Star 40 on Linux.
However, instead of <span class="title-ref">agent on</span>, you need to issue the command <span class="title-ref">agent KeyboardOnly</span>.
This explicitly tells bluetoothctl that you’re specifically looking for a HID profile.</p>
<h1 id="configuring-bluetooth-via-the-command-line-feels-vague">Configuring Bluetooth via the Command Line Feels Vague</h1>
<p>While I’m very happy that I actually managed to set all of this up,
I must admit that the command-line interface to BlueZ feels
a bit incomplete and confusing. I initially thought that agents
were only for PIN code entry. Now that I’ve discovered that “agent KeyboardOnly”
is used to enable the HID profile, I’m not sure anymore.
I’m surprised that I needed to grab a script from a random git repository
in order to be able to set up PAN. I remember, with earlier version of BlueZ,
that there was a tool called <span class="title-ref">pand</span> that you could use to do all of this
from the command-line. I don’t seem to see anything like that
for BlueZ 5 anymore. Maybe I’m missing something obvious?</p>
<h1 id="performance">Performance</h1>
<p>The data rate is roughly 120kB/s, which I consider acceptable for such a low
power solution.
The 1GHz ARM CPU actually feels sufficiently fast for a console/text-mode
person like me.
I’ll rarely be using much more than ssh and emacs on it anyway.</p>
<h1 id="console-fonts-and-screen-dimensions">Console fonts and screen dimensions</h1>
<p>The default dimensions of the framebuffer on the Raspberry Pi Zero are a bit
unexpectedly strange. <span class="title-ref">fbset</span> reports that the screen dimension
is 656x416 pixels (of course, no monitor connected). With a typical console
font of 8x16, I got 82 columns and 26 lines.</p>
<p>With a 40 cell braille display, the 82 columns are very inconvenient.
Additionally, as a braille user, I would like to be able to view Unicode
braille characters in addition to the normal charset on the console.
Fortunately, Linux supports 512 glyphs, while most console fonts
do only provide 256. <span class="title-ref">console-setup</span> can load and combine two
256-glyph fonts at once. So I added the following to <span class="title-ref">/etc/default/console-setup</span>
to make the text console a lot more friendly to braille users:</p>
<pre><code>SCREEN_WIDTH=80
SCREEN_HEIGHT=25
FONT=&quot;Lat15-Terminus16.psf.gz brl-16x8.psf&quot;</code></pre>
<div class="note">
<div class="title">
<p>Note</p>
</div>
<p>You need <span class="title-ref">console-braille</span> installed for <span class="title-ref">brl-16x8.psf</span> to be available.</p>
</div>
<h1 id="further-projects">Further Projects</h1>
<p>There’s a 3.5mm audio jack inside the braille display as well.
Unfortunately, there are no converters from Mini-HDMI to 3.5mm audio
that I know of. It would be very nice to be able to use the
sound card that is already built into the Raspberry Pi Zero,
but, unfortunately, this doesn’t seem possible at the moment.
Alternatively, I’m looking at using a Micro USB OTG hub and an
additional USB audio adapter to get sound from the Raspberry Pi Zero
to the braille display’s speakers. Unfortunately, the two USB audio
adapters I’ve tried so far have run hot for some unknown reason.
So I have to find some other chipset to see if the problem goes away.</p>
<p>A little nuisance, currently, is that you need to manually power off
the Raspberry, wait a few seconds, and then power down the braille display.
Turning the braille display off cuts power delivery via the internal USB port.
If this is accidentally done too soon then the Raspberry Pi Zero
is shut down ungracefully (which is probably not the best way to do it).
We’re looking into connecting a small, buffering battery to the GPIO pins
of the rpi, and into notifying the rpi when external power has dropped.
A graceful, software-initiated shutdown can then be performed.
You can think of it as being like a mini UPS for Micro USB.</p>
<h1 id="the-image">The image</h1>
<p>If you are a happy owner of a Handy Tech Active Star 40 and would like
to do something similar, I am happy to share my current
(Raspbian Stretch based) image. In fact, if there is enough interest by
other blind users, we might even consider putting a kit together that makes it
as easy as possible for you to get started. Let <a href="mailto:mlang@blind.guru">me</a> know if this could be
of interest to you.</p>
<h1 id="thanks">Thanks</h1>
<p>Thanks to Dave Mielke for reviewing the text of this posting.</p>
<p>Thanks to Simon Kainz for making the photos for this article.</p>
<p>And I owe a big thank you to my co-workers at Graz University
of Technology who have helped me a lot to bootstrap really quickly into the
rpi world.</p>
<h1 id="p.s.">P.S.</h1>
<p><a href="https://twitter.com/blindbird23/status/740169540018044928/photo/1">My first tweet about this topic</a> is just
five days ago, and apart from the soundcard not working yet, I feel
like the project is already almost complete! By the way, I am editing
the final version of this blog posting from my newly created monitorless
ARM-based Linux laptop via an ssh connection to my home machine.</p>]]></summary>
</entry>
<entry>
    <title>Scraping the web with Python and XQuery</title>
    <link href="https://blind.guru/blog/2016-04-21-xq.html" />
    <id>https://blind.guru/blog/2016-04-21-xq.html</id>
    <published>2016-04-21T00:00:00Z</published>
    <updated>2016-04-21T00:00:00Z</updated>
    <summary type="html"><![CDATA[<p>During a <a href="https://www.freedomscientific.com/Products/Blindness/JAWS">JAWS for Windows</a> training, I was introduced to the
<span class="title-ref">Research It</span> feature of that screen reader.
<span class="title-ref">Research It</span> is a quick way to utilize web scraping to make
working with complex web pages easier.
It is about extracting specific information from a website that
does not offer an API. For instance, look up a word
in an online dictionary, or quickly check the status of
a delivery. Strictly speaking, this feature does not belong
in a screen reader, but it is a very helpful tool to have at your
fingertips.</p>
<p><span class="title-ref">Research It</span> uses <a href="https://www.w3.org/XML/Query/">XQuery</a> (actually, <a href="http://xqilla.sourceforge.net/HomePage">XQilla</a>) to do all the
heavy lifting. This also means that the <a href="https://www.freedomsci.de/rules01.htm">Research It Rulesets</a>
are theoretically also useable on other platforms. I was immediately
hooked, because I always had a love for XPath. Looking
at XQuery code is totally self-explanatory for me.
I just like the syntax and semantics.</p>
<p>So I immediately checked out XQilla on Debian,
and found <a href="https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=821329">#821329</a> and <a href="https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=821330">#821330</a>, which were promptly
fixed by <a href="mailto:tvainika@debian.org">Tommi Vainikainen</a>, thanks to him for the really quick response!</p>
<p>Unfortunately, making <a href="http://xqilla.sourceforge.net/ExtensionFunctions#parse-html">xqilla:parse-html</a> available and
upgrading to the latest upstream version is not enough to
use XQilla on Linux with the typical webpages out there.
<a href="https://xerces.apache.org/xerces-c/">Xerces-C++</a>, which is what XQilla uses to fetch web resources,
does not support HTTPS URLs at the moment. I filed <a href="https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=821380">#821380</a> to
ask for HTTPS support in Xerces-C to be enabled by default.</p>
<p>And even with HTTPS support enabled in Xerces-C, the <span class="title-ref">xqilla:parse-html</span>
function (which is based on <a href="https://packages.debian.org/sid/libtidy-dev">HTML Tidy</a>) fails for
a lot of real-world webpages I tried.
Manually upgrading the six year old version of HTML Tidy in Debian
to the latest from GitHub (<a href="https://github.com/htacg/tidy-html5">tidy-html5</a>, <a href="https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=810951">#810951</a>) did not help a lot either.</p>
<h1 id="python-to-the-rescue">Python to the rescue</h1>
<p>XQuery is still a very nice language for extracting information
from markup documents. XQilla just has a bit of a hard time dealing
with the typical HTML documents out there. After all, it was
designed to deal with well-formed XML documents.</p>
<p>So I decided to build a little wrapper around XQilla which fetches
the web resources with the Python <a href="http://docs.python-requests.org/en/master/">Requests</a> package, and
cleans the HTML document with <a href="https://www.crummy.com/software/BeautifulSoup/">BeautifulSoup</a> (which uses lxml
to do HTML parsing). The output
of BeautifulSoup can apparently be passed to XQilla as the
context document. This is a fairly crazy hack, but it
works quite reliably so far.</p>
<p>Here is how one of my web scraping rules looks like:</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="im">from</span> click <span class="im">import</span> argument, group</span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a><span class="at">@group</span>()</span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> xq():</span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a>  <span class="co">&quot;&quot;&quot;Web scraping for command-line users.&quot;&quot;&quot;</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a>  <span class="cf">pass</span></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a><span class="at">@xq.group</span>(<span class="st">&#39;github.com&#39;</span>)</span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> github():</span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a>  <span class="co">&quot;&quot;&quot;Quick access to github.com.&quot;&quot;&quot;</span></span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a>  <span class="cf">pass</span></span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a><span class="at">@github.command</span>(<span class="st">&#39;code_search&#39;</span>)</span>
<span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a><span class="at">@argument</span>(<span class="st">&#39;language&#39;</span>)</span>
<span id="cb1-15"><a href="#cb1-15" aria-hidden="true" tabindex="-1"></a><span class="at">@argument</span>(<span class="st">&#39;query&#39;</span>)</span>
<span id="cb1-16"><a href="#cb1-16" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> github_code_search(language, query):</span>
<span id="cb1-17"><a href="#cb1-17" aria-hidden="true" tabindex="-1"></a>  <span class="co">&quot;&quot;&quot;Search for source code.&quot;&quot;&quot;</span></span>
<span id="cb1-18"><a href="#cb1-18" aria-hidden="true" tabindex="-1"></a>  scrape(get<span class="op">=</span><span class="st">&#39;https://github.com/search&#39;</span>,</span>
<span id="cb1-19"><a href="#cb1-19" aria-hidden="true" tabindex="-1"></a>         params<span class="op">=</span>{<span class="st">&#39;l&#39;</span>: language, <span class="st">&#39;q&#39;</span>: query, <span class="st">&#39;type&#39;</span>: <span class="st">&#39;code&#39;</span>})</span></code></pre></div>
<p>The function <span class="title-ref">scrape</span> automatically determines the XQuery filename according
to the callers function name. Here is how <span class="title-ref">github_code_search.xq</span> looks like:</p>
<pre class="xquery"><code>declare function local:source-lines($table as node()*) as xs:string*
{
  for $tr in $table/tr return normalize-space(data($tr))
};

let $results := html//div[@id=&quot;code_search_results&quot;]/div[@class=&quot;code-list&quot;]
for $div in $results/div
let $repo := data($div/p/a[1])
let $file := data($div/p/a[2])
let $link := resolve-uri(data($div/p/a[2]/@href))
return (concat($repo, &quot;: &quot;, $file), $link, local:source-lines($div//table),
        &quot;---------------------------------------------------------------&quot;)</code></pre>
<p>That is all I need to implement a custom web scraping rule.
A few lines of Python to specify how and where to fetch the website from.
And a XQuery file that specifies how to mangle the document content.</p>
<p>And thanks to the Python <a href="http://click.pocoo.org/5/">click</a> package, the various entry points
of my web scraping script can easily be called from the command-line.</p>
<p>Here is a sample invokation:</p>
<pre class="shell"><code>fx:~/xq% ./xq.py github.com
Usage: xq.py github.com [OPTIONS] COMMAND [ARGS]...

  Quick access to github.com.

Options:
  --help  Show this message and exit.

Commands:
  code_search  Search for source code.

fx:~/xq% ./xq.py github.com code_search Pascal &#39;&quot;debian/rules&quot;&#39;
prof7bit/LazPackager: frmlazpackageroptionsdeb.pas
https://github.com/prof7bit/LazPackager/blob/cc3e35e9bae0c5a582b0b301dcbb38047fba2ad9/frmlazpackageroptionsdeb.pas
230 procedure TFDebianOptions.BtnPreviewRulesClick(Sender: TObject);
231 begin
232 ShowPreview(&#39;debian/rules&#39;, EdRules.Text);
233 end;
234
235 procedure TFDebianOptions.BtnPreviewChangelogClick(Sender: TObject);
---------------------------------------------------------------
prof7bit/LazPackager: lazpackagerdebian.pas
https://github.com/prof7bit/LazPackager/blob/cc3e35e9bae0c5a582b0b301dcbb38047fba2ad9/lazpackagerdebian.pas
205 + &#39;mv ../rules debian/&#39; + LF
206 + &#39;chmod +x debian/rules&#39; + LF
207 + &#39;mv ../changelog debian/&#39; + LF
208 + &#39;mv ../copyright debian/&#39; + LF
---------------------------------------------------------------</code></pre>
<p>For the impatient, here is the implementation of `scrape`:</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="im">from</span> bs4 <span class="im">import</span> BeautifulSoup</span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a><span class="im">from</span> bs4.element <span class="im">import</span> Doctype, ResultSet</span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a><span class="im">from</span> inspect <span class="im">import</span> currentframe</span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a><span class="im">from</span> itertools <span class="im">import</span> chain</span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a><span class="im">from</span> os <span class="im">import</span> path</span>
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true" tabindex="-1"></a><span class="im">from</span> os.path <span class="im">import</span> abspath, dirname</span>
<span id="cb4-7"><a href="#cb4-7" aria-hidden="true" tabindex="-1"></a><span class="im">from</span> subprocess <span class="im">import</span> PIPE, run</span>
<span id="cb4-8"><a href="#cb4-8" aria-hidden="true" tabindex="-1"></a><span class="im">from</span> tempfile <span class="im">import</span> NamedTemporaryFile</span>
<span id="cb4-9"><a href="#cb4-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-10"><a href="#cb4-10" aria-hidden="true" tabindex="-1"></a><span class="im">import</span> requests</span>
<span id="cb4-11"><a href="#cb4-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-12"><a href="#cb4-12" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> scrape(get<span class="op">=</span><span class="va">None</span>, post<span class="op">=</span><span class="va">None</span>, find_all<span class="op">=</span><span class="va">None</span>,</span>
<span id="cb4-13"><a href="#cb4-13" aria-hidden="true" tabindex="-1"></a>           xquery_name<span class="op">=</span><span class="va">None</span>, xquery_vars<span class="op">=</span>{}, <span class="op">**</span>kwargs):</span>
<span id="cb4-14"><a href="#cb4-14" aria-hidden="true" tabindex="-1"></a>  <span class="co">&quot;&quot;&quot;Execute a XQuery file.</span></span>
<span id="cb4-15"><a href="#cb4-15" aria-hidden="true" tabindex="-1"></a><span class="co">  When either get or post is specified, fetch the resource and run it through</span></span>
<span id="cb4-16"><a href="#cb4-16" aria-hidden="true" tabindex="-1"></a><span class="co">  BeautifulSoup, passing it as context to the XQuery.</span></span>
<span id="cb4-17"><a href="#cb4-17" aria-hidden="true" tabindex="-1"></a><span class="co">  If find_all is given, wrap the result of executing find_all on</span></span>
<span id="cb4-18"><a href="#cb4-18" aria-hidden="true" tabindex="-1"></a><span class="co">  the BeautifulSoup in an artificial HTML body.</span></span>
<span id="cb4-19"><a href="#cb4-19" aria-hidden="true" tabindex="-1"></a><span class="co">  If xquery_name is not specified, the callers function name is used.</span></span>
<span id="cb4-20"><a href="#cb4-20" aria-hidden="true" tabindex="-1"></a><span class="co">  xquery_name combined with extension &quot;.xq&quot; is searched in the directory</span></span>
<span id="cb4-21"><a href="#cb4-21" aria-hidden="true" tabindex="-1"></a><span class="co">  where this Python script resides and executed with XQilla.</span></span>
<span id="cb4-22"><a href="#cb4-22" aria-hidden="true" tabindex="-1"></a><span class="co">  kwargs are passed to get or post calls.  Typical extra keywords would be:</span></span>
<span id="cb4-23"><a href="#cb4-23" aria-hidden="true" tabindex="-1"></a><span class="co">  params -- To pass extra parameters to the URL.</span></span>
<span id="cb4-24"><a href="#cb4-24" aria-hidden="true" tabindex="-1"></a><span class="co">  data -- For HTTP POST.</span></span>
<span id="cb4-25"><a href="#cb4-25" aria-hidden="true" tabindex="-1"></a><span class="co">  &quot;&quot;&quot;</span></span>
<span id="cb4-26"><a href="#cb4-26" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-27"><a href="#cb4-27" aria-hidden="true" tabindex="-1"></a>  response <span class="op">=</span> <span class="va">None</span></span>
<span id="cb4-28"><a href="#cb4-28" aria-hidden="true" tabindex="-1"></a>  url <span class="op">=</span> <span class="va">None</span></span>
<span id="cb4-29"><a href="#cb4-29" aria-hidden="true" tabindex="-1"></a>  context <span class="op">=</span> <span class="va">None</span></span>
<span id="cb4-30"><a href="#cb4-30" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-31"><a href="#cb4-31" aria-hidden="true" tabindex="-1"></a>  <span class="cf">if</span> get <span class="kw">is</span> <span class="kw">not</span> <span class="va">None</span>:</span>
<span id="cb4-32"><a href="#cb4-32" aria-hidden="true" tabindex="-1"></a>    response <span class="op">=</span> requests.get(get, <span class="op">**</span>kwargs)</span>
<span id="cb4-33"><a href="#cb4-33" aria-hidden="true" tabindex="-1"></a>  <span class="cf">elif</span> post <span class="kw">is</span> <span class="kw">not</span> <span class="va">None</span>:</span>
<span id="cb4-34"><a href="#cb4-34" aria-hidden="true" tabindex="-1"></a>    response <span class="op">=</span> requests.post(post, <span class="op">**</span>kwargs)</span>
<span id="cb4-35"><a href="#cb4-35" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-36"><a href="#cb4-36" aria-hidden="true" tabindex="-1"></a>  <span class="cf">if</span> response <span class="kw">is</span> <span class="kw">not</span> <span class="va">None</span>:</span>
<span id="cb4-37"><a href="#cb4-37" aria-hidden="true" tabindex="-1"></a>    response.raise_for_status()</span>
<span id="cb4-38"><a href="#cb4-38" aria-hidden="true" tabindex="-1"></a>    context <span class="op">=</span> BeautifulSoup(response.text, <span class="st">&#39;lxml&#39;</span>)</span>
<span id="cb4-39"><a href="#cb4-39" aria-hidden="true" tabindex="-1"></a>    dtd <span class="op">=</span> <span class="bu">next</span>(context.descendants)</span>
<span id="cb4-40"><a href="#cb4-40" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> <span class="bu">type</span>(dtd) <span class="kw">is</span> Doctype:</span>
<span id="cb4-41"><a href="#cb4-41" aria-hidden="true" tabindex="-1"></a>      dtd.extract()</span>
<span id="cb4-42"><a href="#cb4-42" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> find_all <span class="kw">is</span> <span class="kw">not</span> <span class="va">None</span>:</span>
<span id="cb4-43"><a href="#cb4-43" aria-hidden="true" tabindex="-1"></a>      context <span class="op">=</span> context.find_all(find_all)</span>
<span id="cb4-44"><a href="#cb4-44" aria-hidden="true" tabindex="-1"></a>    url <span class="op">=</span> response.url</span>
<span id="cb4-45"><a href="#cb4-45" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-46"><a href="#cb4-46" aria-hidden="true" tabindex="-1"></a>  <span class="cf">if</span> xquery_name <span class="kw">is</span> <span class="va">None</span>:</span>
<span id="cb4-47"><a href="#cb4-47" aria-hidden="true" tabindex="-1"></a>    xquery_name <span class="op">=</span> currentframe().f_back.f_code.co_name</span>
<span id="cb4-48"><a href="#cb4-48" aria-hidden="true" tabindex="-1"></a>  cmd <span class="op">=</span> [<span class="st">&#39;xqilla&#39;</span>]</span>
<span id="cb4-49"><a href="#cb4-49" aria-hidden="true" tabindex="-1"></a>  <span class="cf">if</span> context <span class="kw">is</span> <span class="kw">not</span> <span class="va">None</span>:</span>
<span id="cb4-50"><a href="#cb4-50" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> <span class="bu">type</span>(context) <span class="kw">is</span> BeautifulSoup:</span>
<span id="cb4-51"><a href="#cb4-51" aria-hidden="true" tabindex="-1"></a>      soup <span class="op">=</span> context</span>
<span id="cb4-52"><a href="#cb4-52" aria-hidden="true" tabindex="-1"></a>      context <span class="op">=</span> NamedTemporaryFile(mode<span class="op">=</span><span class="st">&#39;w&#39;</span>)</span>
<span id="cb4-53"><a href="#cb4-53" aria-hidden="true" tabindex="-1"></a>      <span class="bu">print</span>(soup, <span class="bu">file</span><span class="op">=</span>context)</span>
<span id="cb4-54"><a href="#cb4-54" aria-hidden="true" tabindex="-1"></a>      cmd.extend([<span class="st">&#39;-i&#39;</span>, context.name])</span>
<span id="cb4-55"><a href="#cb4-55" aria-hidden="true" tabindex="-1"></a>    <span class="cf">elif</span> <span class="bu">isinstance</span>(context, <span class="bu">list</span>) <span class="kw">or</span> <span class="bu">isinstance</span>(context, ResultSet):</span>
<span id="cb4-56"><a href="#cb4-56" aria-hidden="true" tabindex="-1"></a>      tags <span class="op">=</span> context</span>
<span id="cb4-57"><a href="#cb4-57" aria-hidden="true" tabindex="-1"></a>      context <span class="op">=</span> NamedTemporaryFile(mode<span class="op">=</span><span class="st">&#39;w&#39;</span>)</span>
<span id="cb4-58"><a href="#cb4-58" aria-hidden="true" tabindex="-1"></a>      <span class="bu">print</span>(<span class="st">&#39;&lt;html&gt;&lt;body&gt;&#39;</span>, <span class="bu">file</span><span class="op">=</span>context)</span>
<span id="cb4-59"><a href="#cb4-59" aria-hidden="true" tabindex="-1"></a>      <span class="cf">for</span> item <span class="kw">in</span> tags: <span class="bu">print</span>(item, <span class="bu">file</span><span class="op">=</span>context)</span>
<span id="cb4-60"><a href="#cb4-60" aria-hidden="true" tabindex="-1"></a>      <span class="bu">print</span>(<span class="st">&#39;&lt;/body&gt;&lt;/html&gt;&#39;</span>, <span class="bu">file</span><span class="op">=</span>context)</span>
<span id="cb4-61"><a href="#cb4-61" aria-hidden="true" tabindex="-1"></a>      context.flush()</span>
<span id="cb4-62"><a href="#cb4-62" aria-hidden="true" tabindex="-1"></a>      cmd.extend([<span class="st">&#39;-i&#39;</span>, context.name])</span>
<span id="cb4-63"><a href="#cb4-63" aria-hidden="true" tabindex="-1"></a>  cmd.extend(chain.from_iterable([<span class="st">&#39;-v&#39;</span>, k, v] <span class="cf">for</span> k, v <span class="kw">in</span> xquery_vars.items()))</span>
<span id="cb4-64"><a href="#cb4-64" aria-hidden="true" tabindex="-1"></a>  <span class="cf">if</span> url <span class="kw">is</span> <span class="kw">not</span> <span class="va">None</span>:</span>
<span id="cb4-65"><a href="#cb4-65" aria-hidden="true" tabindex="-1"></a>    cmd.extend([<span class="st">&#39;-b&#39;</span>, url])</span>
<span id="cb4-66"><a href="#cb4-66" aria-hidden="true" tabindex="-1"></a>  cmd.append(abspath(path.join(dirname(<span class="va">__file__</span>), xquery_name <span class="op">+</span> <span class="st">&quot;.xq&quot;</span>)))</span>
<span id="cb4-67"><a href="#cb4-67" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-68"><a href="#cb4-68" aria-hidden="true" tabindex="-1"></a>  output <span class="op">=</span> run(cmd, stdout<span class="op">=</span>PIPE).stdout.decode(<span class="st">&#39;utf-8&#39;</span>)</span>
<span id="cb4-69"><a href="#cb4-69" aria-hidden="true" tabindex="-1"></a>  <span class="cf">if</span> <span class="bu">type</span>(context) <span class="kw">is</span> NamedTemporaryFile: context.close()</span>
<span id="cb4-70"><a href="#cb4-70" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-71"><a href="#cb4-71" aria-hidden="true" tabindex="-1"></a>  <span class="bu">print</span>(output, end<span class="op">=</span><span class="st">&#39;&#39;</span>)</span></code></pre></div>
<p>The full source for <a href="https://github.com/mlang/xq">xq</a> can be found on <a href="https://github.com/">GitHub</a>.
The project is just two days old, so I have only implemented
three scraping rules as of now. However, adding new rules has
been made deliberately easy, so that I can just write up a few
lines of code whenever I find something on the web which I’d like to scrape
on the command-line. If you find this “framework” useful, make
sure to share your insights with me. And if you impelement your own
scraping rules for a public service, consider sharing that as well.</p>
<p>If you have an comments or questions, send me <a href="mailto:mlang@blind.guru">mail</a>.
Oh, and by the way, I am now also on Twitter as <a href="https://twitter.com/blindbird23">@blindbird23</a>.</p>]]></summary>
</entry>
<entry>
    <title>Generating C++ from a DTD with Jinja2 and lxml</title>
    <link href="https://blind.guru/blog/2016-02-21-bmmlcxx.html" />
    <id>https://blind.guru/blog/2016-02-21-bmmlcxx.html</id>
    <published>2016-02-21T00:00:00Z</published>
    <updated>2016-02-21T00:00:00Z</updated>
    <summary type="html"><![CDATA[<p>I recently stumbled across an <a href="http://bmml.googlecode.com/svn/trunk/bmml/BMML.dtd">XML format specified in a DTD</a> that I wanted
to work with from within C++. The XML format is document centric, which
is a bit of a pain with existing data binding compilers according to my limited
experience.</p>
<p>So to learn something new, and to keep control over generated code,
I started to investigate what it would take to write my
own little custom data binding compiler.</p>
<h1 id="writing-a-program-that-writes-a-program">Writing a program that writes a program</h1>
<p>It turns out that there are two very helpful libraries
in <a href="http://www.python.org/">Python</a> which can really make your life a lot easier:</p>
<blockquote>
<ul>
<li>The <a href="http://lxml.de/validation.html#id1">DTD class from lxml.etree</a>.</li>
<li>The <a href="http://jinja.pocoo.org/docs/dev/">Jinja2</a> templating system.</li>
</ul>
</blockquote>
<p>To keep my life simple, I am focusing on generating accessors for XML
attributes only for now. I leave it up to the library client to figure out how
to deal with child elements.</p>
<h1 id="a-highly-simplified-dom">A highly simplified DOM</h1>
<p>Inspired by the <a href="http://scm.codesynthesis.com/?p=libstudxml/libstudxml.git;a=tree;f=examples/hybrid">hybrid</a> example from <a href="http://www.codesynthesis.com/projects/libstudxml/">libstudxml</a>, we define a simple base
class that can store raw XML elements.</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode c++"><code class="sourceCode cpp"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> element <span class="op">{</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span><span class="op">:</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> <span class="dt">attributes_type</span> <span class="op">=</span> <span class="bu">std::</span>map<span class="op">&lt;</span>xml<span class="op">::</span>qname<span class="op">,</span> <span class="bu">std::</span>string<span class="op">&gt;;</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> <span class="dt">elements_type</span> <span class="op">=</span> <span class="bu">std::</span>vector<span class="op">&lt;</span><span class="bu">std::</span>shared_ptr<span class="op">&lt;</span>element<span class="op">&gt;&gt;;</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a>  element<span class="op">(</span><span class="at">const</span> xml<span class="op">::</span>qname<span class="op">&amp;</span> name<span class="op">)</span> <span class="op">:</span> <span class="va">tag_name_</span><span class="op">(</span>name<span class="op">)</span> <span class="op">{}</span></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a>  <span class="kw">virtual</span> <span class="op">~</span>element<span class="op">()</span> <span class="op">=</span> <span class="cf">default</span><span class="op">;</span></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a>  xml<span class="op">::</span>qname <span class="at">const</span><span class="op">&amp;</span> tag_name<span class="op">()</span> <span class="at">const</span> <span class="op">{</span> <span class="cf">return</span> <span class="va">tag_name_</span><span class="op">;</span> <span class="op">}</span></span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a>  <span class="dt">attributes_type</span> <span class="at">const</span><span class="op">&amp;</span> attributes<span class="op">()</span> <span class="at">const</span> <span class="op">{</span> <span class="cf">return</span> <span class="va">attributes_</span><span class="op">;</span> <span class="op">}</span></span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a>  <span class="dt">attributes_type</span><span class="op">&amp;</span>       attributes<span class="op">()</span>       <span class="op">{</span> <span class="cf">return</span> <span class="va">attributes_</span><span class="op">;</span> <span class="op">}</span></span>
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a>  <span class="bu">std::</span>string <span class="at">const</span><span class="op">&amp;</span> text<span class="op">()</span> <span class="at">const</span> <span class="op">{</span> <span class="cf">return</span> <span class="va">text_</span><span class="op">;</span> <span class="op">}</span></span>
<span id="cb1-15"><a href="#cb1-15" aria-hidden="true" tabindex="-1"></a>  <span class="dt">void</span> text<span class="op">(</span><span class="bu">std::</span>string <span class="at">const</span><span class="op">&amp;</span> text<span class="op">)</span> <span class="op">{</span> <span class="va">text_</span> <span class="op">=</span> text<span class="op">;</span> <span class="op">}</span></span>
<span id="cb1-16"><a href="#cb1-16" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-17"><a href="#cb1-17" aria-hidden="true" tabindex="-1"></a>  <span class="dt">elements_type</span> <span class="at">const</span><span class="op">&amp;</span> elements<span class="op">()</span> <span class="at">const</span> <span class="op">{</span><span class="cf">return</span> <span class="va">elements_</span><span class="op">;}</span></span>
<span id="cb1-18"><a href="#cb1-18" aria-hidden="true" tabindex="-1"></a>  <span class="dt">elements_type</span><span class="op">&amp;</span>       elements<span class="op">()</span>       <span class="op">{</span> <span class="cf">return</span> <span class="va">elements_</span><span class="op">;</span> <span class="op">}</span></span>
<span id="cb1-19"><a href="#cb1-19" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-20"><a href="#cb1-20" aria-hidden="true" tabindex="-1"></a>  element<span class="op">(</span>xml<span class="op">::</span>parser<span class="op">&amp;,</span> <span class="dt">bool</span> start_end <span class="op">=</span> <span class="kw">true</span><span class="op">);</span></span>
<span id="cb1-21"><a href="#cb1-21" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-22"><a href="#cb1-22" aria-hidden="true" tabindex="-1"></a>  <span class="dt">void</span> serialize <span class="op">(</span>xml<span class="op">::</span>serializer<span class="op">&amp;,</span> <span class="dt">bool</span> start_end <span class="op">=</span> <span class="kw">true</span><span class="op">)</span> <span class="at">const</span><span class="op">;</span></span>
<span id="cb1-23"><a href="#cb1-23" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-24"><a href="#cb1-24" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">typename</span> T<span class="op">&gt;</span> <span class="at">static</span> <span class="bu">std::</span>shared_ptr<span class="op">&lt;</span>element<span class="op">&gt;</span> create<span class="op">(</span>xml<span class="op">::</span>parser<span class="op">&amp;</span> p<span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-25"><a href="#cb1-25" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> <span class="bu">std::</span>make_shared<span class="op">&lt;</span>T<span class="op">&gt;(</span>p<span class="op">,</span> <span class="kw">false</span><span class="op">);</span></span>
<span id="cb1-26"><a href="#cb1-26" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb1-27"><a href="#cb1-27" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-28"><a href="#cb1-28" aria-hidden="true" tabindex="-1"></a><span class="kw">private</span><span class="op">:</span></span>
<span id="cb1-29"><a href="#cb1-29" aria-hidden="true" tabindex="-1"></a>  xml<span class="op">::</span>qname <span class="va">tag_name_</span><span class="op">;</span></span>
<span id="cb1-30"><a href="#cb1-30" aria-hidden="true" tabindex="-1"></a>  <span class="dt">attributes_type</span> <span class="va">attributes_</span><span class="op">;</span></span>
<span id="cb1-31"><a href="#cb1-31" aria-hidden="true" tabindex="-1"></a>  <span class="bu">std::</span>string <span class="va">text_</span><span class="op">;</span>           <span class="co">// Simple content only.</span></span>
<span id="cb1-32"><a href="#cb1-32" aria-hidden="true" tabindex="-1"></a>  <span class="dt">elements_type</span> <span class="va">elements_</span><span class="op">;</span>     <span class="co">// Complex content only.</span></span>
<span id="cb1-33"><a href="#cb1-33" aria-hidden="true" tabindex="-1"></a><span class="op">};</span></span></code></pre></div>
<p>For each element name in the DTD, we’re going to define a class that inherits
from the <code>element</code> class, implementing special methods to make attribute
access easier. The <code>element(xml::parser&amp;)</code> constructor is going to create the
corresponding class whenever it sees a certain element name. This calls for some
sort of factory:</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode c++"><code class="sourceCode cpp"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> factory <span class="op">{</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span><span class="op">:</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a>  <span class="at">static</span> <span class="bu">std::</span>shared_ptr<span class="op">&lt;</span>element<span class="op">&gt;</span> make<span class="op">(</span>xml<span class="op">::</span>parser<span class="op">&amp;</span> p<span class="op">);</span></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a><span class="kw">protected</span><span class="op">:</span></span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> element_info <span class="op">{</span></span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a>    xml<span class="op">::</span>content <span class="dt">content_type</span><span class="op">;</span></span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a>    <span class="bu">std::</span>shared_ptr<span class="op">&lt;</span>element<span class="op">&gt;</span> <span class="op">(*</span>construct<span class="op">)(</span>xml<span class="op">::</span>parser<span class="op">&amp;);</span></span>
<span id="cb2-9"><a href="#cb2-9" aria-hidden="true" tabindex="-1"></a>  <span class="op">};</span></span>
<span id="cb2-10"><a href="#cb2-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-11"><a href="#cb2-11" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> <span class="dt">map_type</span> <span class="op">=</span> <span class="bu">std::</span>map<span class="op">&lt;</span>xml<span class="op">::</span>qname<span class="op">,</span> element_info<span class="op">&gt;;</span></span>
<span id="cb2-12"><a href="#cb2-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-13"><a href="#cb2-13" aria-hidden="true" tabindex="-1"></a>  <span class="at">static</span> <span class="dt">map_type</span> <span class="op">*</span>get_map<span class="op">()</span> <span class="op">{</span></span>
<span id="cb2-14"><a href="#cb2-14" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> <span class="op">(!</span>map<span class="op">)</span> map <span class="op">=</span> <span class="kw">new</span> <span class="dt">map_type</span><span class="op">;</span></span>
<span id="cb2-15"><a href="#cb2-15" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-16"><a href="#cb2-16" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> map<span class="op">;</span></span>
<span id="cb2-17"><a href="#cb2-17" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb2-18"><a href="#cb2-18" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-19"><a href="#cb2-19" aria-hidden="true" tabindex="-1"></a><span class="kw">private</span><span class="op">:</span></span>
<span id="cb2-20"><a href="#cb2-20" aria-hidden="true" tabindex="-1"></a>  <span class="at">static</span> <span class="dt">map_type</span> <span class="op">*</span>map<span class="op">;</span></span>
<span id="cb2-21"><a href="#cb2-21" aria-hidden="true" tabindex="-1"></a><span class="op">};</span></span>
<span id="cb2-22"><a href="#cb2-22" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-23"><a href="#cb2-23" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">typename</span> T<span class="op">&gt;</span></span>
<span id="cb2-24"><a href="#cb2-24" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> register_element <span class="op">:</span> factory <span class="op">{</span></span>
<span id="cb2-25"><a href="#cb2-25" aria-hidden="true" tabindex="-1"></a>  register_element<span class="op">(</span>xml<span class="op">::</span>qname <span class="at">const</span><span class="op">&amp;</span> name<span class="op">,</span> xml<span class="op">::</span>content <span class="at">const</span><span class="op">&amp;</span> content<span class="op">)</span> <span class="op">{</span></span>
<span id="cb2-26"><a href="#cb2-26" aria-hidden="true" tabindex="-1"></a>    get_map<span class="op">()-&gt;</span>insert<span class="op">({</span>name<span class="op">,</span> element_info<span class="op">{</span>content<span class="op">,</span> <span class="op">&amp;</span>element<span class="op">::</span>create<span class="op">&lt;</span>T<span class="op">&gt;}});</span></span>
<span id="cb2-27"><a href="#cb2-27" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb2-28"><a href="#cb2-28" aria-hidden="true" tabindex="-1"></a><span class="op">};</span></span>
<span id="cb2-29"><a href="#cb2-29" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-30"><a href="#cb2-30" aria-hidden="true" tabindex="-1"></a>shared_ptr<span class="op">&lt;</span>element<span class="op">&gt;</span> factory<span class="op">::</span>make<span class="op">(</span>xml<span class="op">::</span>parser<span class="op">&amp;</span> p<span class="op">)</span> <span class="op">{</span></span>
<span id="cb2-31"><a href="#cb2-31" aria-hidden="true" tabindex="-1"></a>  <span class="kw">auto</span> name <span class="op">=</span> p<span class="op">.</span>qname<span class="op">();</span></span>
<span id="cb2-32"><a href="#cb2-32" aria-hidden="true" tabindex="-1"></a>  <span class="kw">auto</span> iter <span class="op">=</span> get_map<span class="op">()-&gt;</span>find<span class="op">(</span>name<span class="op">);</span></span>
<span id="cb2-33"><a href="#cb2-33" aria-hidden="true" tabindex="-1"></a>  <span class="cf">if</span> <span class="op">(</span>iter <span class="op">==</span> get_map<span class="op">()-&gt;</span>end<span class="op">())</span> <span class="op">{</span></span>
<span id="cb2-34"><a href="#cb2-34" aria-hidden="true" tabindex="-1"></a>    <span class="co">// No subclass found, so store plain data so we do not loose on roundtrip.</span></span>
<span id="cb2-35"><a href="#cb2-35" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> <span class="bu">std::</span>make_shared<span class="op">&lt;</span>element<span class="op">&gt;(</span>p<span class="op">,</span> <span class="kw">false</span><span class="op">);</span></span>
<span id="cb2-36"><a href="#cb2-36" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb2-37"><a href="#cb2-37" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-38"><a href="#cb2-38" aria-hidden="true" tabindex="-1"></a>  <span class="kw">auto</span> <span class="at">const</span><span class="op">&amp;</span> element <span class="op">=</span> iter<span class="op">-&gt;</span>second<span class="op">;</span></span>
<span id="cb2-39"><a href="#cb2-39" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-40"><a href="#cb2-40" aria-hidden="true" tabindex="-1"></a>  p<span class="op">.</span>content<span class="op">(</span>element<span class="op">.</span><span class="dt">content_type</span><span class="op">);</span></span>
<span id="cb2-41"><a href="#cb2-41" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> element<span class="op">.</span>create<span class="op">(</span>p<span class="op">);</span></span>
<span id="cb2-42"><a href="#cb2-42" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<h1 id="the-header-template">The header template</h1>
<p>Now that we have our required infrastructure, we can finally start
writing Jinja2 templates to generate classes for all elements in our DTD:</p>
<pre class="jinja2"><code>{%- for elem in dtd.iterelements() %}
  {%- if elem.name in forwards_for %}
    {%- for forward in forwards_for[elem.name] %}
class {{forward}};
    {%- endfor %}
  {%- endif %}

class {{elem.name}} : public dom::element {
  static register_element&lt;{{elem.name}}&gt; factory_registration;

public:
  {{elem.name}}(xml::parser&amp; p, bool start_end = true) : dom::element(p, start_end) {
  }

  {%- for attr in elem.iterattributes() %}
    {%- if attr is required_string_attribute %}

  std::string {{attr.name}}() const;
  void {{attr.name}}(std::string const&amp;);

    {%- elif attr is implied_string_attribute %}

  optional&lt;std::string&gt; {{attr.name}}() const;
  void {{attr.name}}(optional&lt;std::string&gt;);

    {# more branches to go here #}

    {%- endif %}
  {%- endfor %}
};
{%- endfor %}</code></pre>
<p><code>required_string_attribute</code> and <code>implied_string_attribute</code> are so-called
Jinja2 tests. They are a nice way to isolate predicates such that the
Jinja2 templates can stay relatively free of complicated expressions:</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a>templates.tests[<span class="st">&#39;required_string_attribute&#39;</span>] <span class="op">=</span> <span class="kw">lambda</span> a: <span class="op">\</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a>  a.<span class="bu">type</span> <span class="kw">in</span> [<span class="st">&#39;id&#39;</span>, <span class="st">&#39;cdata&#39;</span>, <span class="st">&#39;idref&#39;</span>] <span class="kw">and</span> a.default <span class="op">==</span> <span class="st">&#39;required&#39;</span></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a>templates.tests[<span class="st">&#39;implied_string_attribute&#39;</span>] <span class="op">=</span> <span class="kw">lambda</span> a: <span class="op">\</span></span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a>  a.<span class="bu">type</span> <span class="kw">in</span> [<span class="st">&#39;id&#39;</span>, <span class="st">&#39;cdata&#39;</span>, <span class="st">&#39;idref&#39;</span>] <span class="kw">and</span> a.default <span class="op">==</span> <span class="st">&#39;implied&#39;</span></span></code></pre></div>
<p>That is nice, but we have only seen C++ header declarations so far.
Lets have a look into the implementation of some of our attribute accessors.</p>
<h1 id="enum-conversion">Enum conversion</h1>
<p>One interesting aspect of DTD based code generation is the fact that attributes
can have enumerations specified. Assume that we have some extra
data-structure in Python which helps us to define a nice name for each
individual enumeration attribute. Then, a part of the Jinja2 template
to generate the implementation for an enumeration attribute looks like:</p>
<pre class="jinja2"><code>{%- elif attr is known_enumeration_attribute %}
  {%- set enum = enumerations[tuple(attr.values())][&#39;name&#39;] %}
  {%- if attr.default == &#39;required&#39; %}

{{enum}} {{elem.name}}::{{attr.name}}() const {
auto iter = attributes().find(qname{&quot;{{attr.name}}&quot;});
if (iter != attributes().end()) {
    {%- for value in attr.values() %}
{% if not loop.first %}else {% else %}     {% endif -%}
if (iter-&gt;second == &quot;{{value}}&quot;) return {{enum}}::{{value | mangle}};
    {%- endfor %}

throw illegal_enumeration{};
}

throw missing_attribute{};
}

void {{elem.name}}::{{attr.name}}({{enum}} value) {
static qname const attr{&quot;{{attr.name}}&quot;};

switch (value) {
    {%- for value in attr.values() %}
case {{enum}}::{{value | mangle}}:
attributes()[attr] = &quot;{{value}}&quot;;
break;
    {%- endfor %}

default:
throw illegal_enumeration{};
}
}

  {%- elif attr.default == &#39;implied&#39; %}

{# similar implementation using boost::optional #}

  {%- endif %}
{%- endif %}</code></pre>
<h1 id="putting-it-all-together">Putting it all together</h1>
<p>The header for the library is generated like this:</p>
<div class="sourceCode" id="cb6"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="im">from</span> jinja2 <span class="im">import</span> DictLoader, Environment</span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a><span class="im">from</span> lxml.etree <span class="im">import</span> DTD</span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a>LIBRARY_HEADER <span class="op">=</span> <span class="st">&quot;&quot;&quot;</span></span>
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true" tabindex="-1"></a><span class="st">{# Our template code #}</span></span>
<span id="cb6-6"><a href="#cb6-6" aria-hidden="true" tabindex="-1"></a><span class="st">&quot;&quot;&quot;</span></span>
<span id="cb6-7"><a href="#cb6-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-8"><a href="#cb6-8" aria-hidden="true" tabindex="-1"></a>bmml <span class="op">=</span> DTD(<span class="st">&#39;bmml.dtd&#39;</span>)</span>
<span id="cb6-9"><a href="#cb6-9" aria-hidden="true" tabindex="-1"></a>templates <span class="op">=</span> Environment(loader<span class="op">=</span>DictLoader(<span class="bu">globals</span>()))</span>
<span id="cb6-10"><a href="#cb6-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-11"><a href="#cb6-11" aria-hidden="true" tabindex="-1"></a>templates.filters[<span class="st">&#39;mangle&#39;</span>] <span class="op">=</span> <span class="kw">lambda</span> ident: <span class="op">\</span></span>
<span id="cb6-12"><a href="#cb6-12" aria-hidden="true" tabindex="-1"></a>  {<span class="st">&#39;8th_or_128th&#39;</span>: <span class="st">&#39;eighth_or_128th&#39;</span>,</span>
<span id="cb6-13"><a href="#cb6-13" aria-hidden="true" tabindex="-1"></a>   <span class="st">&#39;256th&#39;</span>: <span class="st">&#39;twohundredfiftysixth&#39;</span>,</span>
<span id="cb6-14"><a href="#cb6-14" aria-hidden="true" tabindex="-1"></a>   <span class="st">&#39;continue&#39;</span>: <span class="st">&#39;continue_&#39;</span></span>
<span id="cb6-15"><a href="#cb6-15" aria-hidden="true" tabindex="-1"></a>  }.get(ident, ident)</span>
<span id="cb6-16"><a href="#cb6-16" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-17"><a href="#cb6-17" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> template(name):</span>
<span id="cb6-18"><a href="#cb6-18" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> templates.get_template(name)</span>
<span id="cb6-19"><a href="#cb6-19" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-20"><a href="#cb6-20" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> hpp():</span>
<span id="cb6-21"><a href="#cb6-21" aria-hidden="true" tabindex="-1"></a>  <span class="bu">print</span>(template(<span class="st">&#39;LIBRARY_HEADER&#39;</span>).render(</span>
<span id="cb6-22"><a href="#cb6-22" aria-hidden="true" tabindex="-1"></a>    {<span class="st">&#39;dtd&#39;</span>: bmml,</span>
<span id="cb6-23"><a href="#cb6-23" aria-hidden="true" tabindex="-1"></a>     <span class="st">&#39;enumerations&#39;</span>: enumerations,</span>
<span id="cb6-24"><a href="#cb6-24" aria-hidden="true" tabindex="-1"></a>     <span class="st">&#39;forwards_for&#39;</span>: {<span class="st">&#39;ornament&#39;</span>: [<span class="st">&#39;ornament_type&#39;</span>],</span>
<span id="cb6-25"><a href="#cb6-25" aria-hidden="true" tabindex="-1"></a>                      <span class="st">&#39;score&#39;</span>: [<span class="st">&#39;score_data&#39;</span>, <span class="st">&#39;score_header&#39;</span>]}</span>
<span id="cb6-26"><a href="#cb6-26" aria-hidden="true" tabindex="-1"></a>    }))</span></code></pre></div>
<p>With all of this in place, we can have a look at a small use case for our library.</p>
<h1 id="printing-document-content">Printing document content</h1>
<p>I haven’t really explained anything about the document format we’re working with
until now. Braille Music Markup Language is an XML based plain text markup language.
Its purpose is to be able to enhance plain braille music scores with
usually hard-to-calcuate meta information. Almost all element text content
is supposed to be printed as-is to reconstruct the original plain text.</p>
<p>So we could at least define one very basic operation in our library:
printing the plain text content of an element.</p>
<p>I found an <a href="http://bmml.googlecode.com/svn/trunk/brailleMusicML/bmml.xsl">XML stylesheet</a> that is supposed to convert BMML documents to HTML.
This stylesheet apparently has a bug, insofar as it forgets to treat the
<code>rest_data</code> element in the same way as it already treats the <code>note_data</code> element.</p>
<p>note to self, I wish I would’ve done a code review before
the EU-project that developed BMML was finished. It looks like resurrecting
maintainance is one of the things I might be able to look into in a meeting
in Pisa in the first three days of March this year.</p>
<p>If we keep this in mind, we can easily reimplement what the stylesheet does
in idiomatic C++:</p>
<div class="sourceCode" id="cb7"><pre class="sourceCode c++"><code class="sourceCode cpp"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">typename</span> T<span class="op">&gt;</span></span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a><span class="kw">typename</span> <span class="bu">std::</span>enable_if<span class="op">&lt;</span><span class="bu">std::</span>is_base_of<span class="op">&lt;</span>element<span class="op">,</span> T<span class="op">&gt;::</span>value<span class="op">,</span> <span class="bu">std::</span>ostream<span class="op">&amp;&gt;::</span>type</span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a><span class="kw">operator</span><span class="op">&lt;&lt;(</span><span class="bu">std::</span>ostream <span class="op">&amp;</span>out<span class="op">,</span> <span class="bu">std::</span>shared_ptr<span class="op">&lt;</span>T<span class="op">&gt;</span> elem<span class="op">)</span> <span class="op">{</span></span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a>  <span class="cf">if</span> <span class="op">(!</span><span class="bu">std::</span>dynamic_pointer_cast<span class="op">&lt;</span>note_data<span class="op">&gt;(</span>elem<span class="op">)</span> <span class="op">&amp;&amp;</span></span>
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true" tabindex="-1"></a>      <span class="op">!</span><span class="bu">std::</span>dynamic_pointer_cast<span class="op">&lt;</span>rest_data<span class="op">&gt;(</span>elem<span class="op">)</span> <span class="op">&amp;&amp;</span></span>
<span id="cb7-6"><a href="#cb7-6" aria-hidden="true" tabindex="-1"></a>      <span class="op">!</span><span class="bu">std::</span>dynamic_pointer_cast<span class="op">&lt;</span>score_header<span class="op">&gt;(</span>elem<span class="op">))</span></span>
<span id="cb7-7"><a href="#cb7-7" aria-hidden="true" tabindex="-1"></a>  <span class="op">{</span></span>
<span id="cb7-8"><a href="#cb7-8" aria-hidden="true" tabindex="-1"></a>    <span class="kw">auto</span> <span class="at">const</span><span class="op">&amp;</span> text <span class="op">=</span> elem<span class="op">-&gt;</span>text<span class="op">();</span></span>
<span id="cb7-9"><a href="#cb7-9" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> <span class="op">(</span>text<span class="op">.</span>empty<span class="op">())</span> <span class="cf">for</span> <span class="op">(</span><span class="kw">auto</span> child <span class="op">:</span> <span class="op">*</span>elem<span class="op">)</span> out <span class="op">&lt;&lt;</span> child<span class="op">;</span> <span class="cf">else</span> out <span class="op">&lt;&lt;</span> text<span class="op">;</span></span>
<span id="cb7-10"><a href="#cb7-10" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb7-11"><a href="#cb7-11" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> out<span class="op">;</span></span>
<span id="cb7-12"><a href="#cb7-12" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>The use of <code>std::enable_if</code> is necessary here so that <code>operator&lt;&lt;</code> is defined
on the <code>element</code> class and all of its subclasses. Without the
<code>std::enable_if</code> magic, client code would be forced to manually make sure
it is passing <code>std::shared_ptr&lt;element&gt;</code> each time it wants to use the
<code>operatr&lt;&lt;</code> on any of our specially defined subclasses.</p>
<p>Now we can easily print BMML documents and get their actual plain text representation.</p>
<div class="sourceCode" id="cb8"><pre class="sourceCode c++"><code class="sourceCode cpp"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;fstream&gt;</span></span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;iostream&gt;</span></span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-4"><a href="#cb8-4" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;xml/parser&gt;</span></span>
<span id="cb8-5"><a href="#cb8-5" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;xml/serializer&gt;</span></span>
<span id="cb8-6"><a href="#cb8-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-7"><a href="#cb8-7" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&quot;bmml.hxx&quot;</span></span>
<span id="cb8-8"><a href="#cb8-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-9"><a href="#cb8-9" aria-hidden="true" tabindex="-1"></a><span class="kw">using</span> <span class="kw">namespace</span> std<span class="op">;</span></span>
<span id="cb8-10"><a href="#cb8-10" aria-hidden="true" tabindex="-1"></a><span class="kw">using</span> <span class="kw">namespace</span> xml<span class="op">;</span></span>
<span id="cb8-11"><a href="#cb8-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-12"><a href="#cb8-12" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main <span class="op">(</span><span class="dt">int</span> argc<span class="op">,</span> <span class="dt">char</span> <span class="op">*</span>argv<span class="op">[])</span> <span class="op">{</span></span>
<span id="cb8-13"><a href="#cb8-13" aria-hidden="true" tabindex="-1"></a>  <span class="cf">if</span> <span class="op">(</span>argc <span class="op">&lt;</span> <span class="dv">2</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb8-14"><a href="#cb8-14" aria-hidden="true" tabindex="-1"></a>    cerr <span class="op">&lt;&lt;</span> <span class="st">&quot;usage: &quot;</span> <span class="op">&lt;&lt;</span> argv<span class="op">[</span><span class="dv">0</span><span class="op">]</span> <span class="op">&lt;&lt;</span> <span class="st">&quot; [&lt;filename.bmml&gt;...]&quot;</span> <span class="op">&lt;&lt;</span> endl<span class="op">;</span></span>
<span id="cb8-15"><a href="#cb8-15" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> EXIT_FAILURE<span class="op">;</span></span>
<span id="cb8-16"><a href="#cb8-16" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb8-17"><a href="#cb8-17" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-18"><a href="#cb8-18" aria-hidden="true" tabindex="-1"></a>  <span class="cf">try</span> <span class="op">{</span></span>
<span id="cb8-19"><a href="#cb8-19" aria-hidden="true" tabindex="-1"></a>    <span class="cf">for</span> <span class="op">(</span><span class="dt">int</span> i <span class="op">=</span> <span class="dv">1</span><span class="op">;</span> i <span class="op">&lt;</span> argc<span class="op">;</span> <span class="op">++</span>i<span class="op">)</span> <span class="op">{</span></span>
<span id="cb8-20"><a href="#cb8-20" aria-hidden="true" tabindex="-1"></a>      ifstream ifs<span class="op">{</span>argv<span class="op">[</span>i<span class="op">]};</span></span>
<span id="cb8-21"><a href="#cb8-21" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-22"><a href="#cb8-22" aria-hidden="true" tabindex="-1"></a>      <span class="cf">if</span> <span class="op">(</span>ifs<span class="op">.</span>good<span class="op">())</span> <span class="op">{</span></span>
<span id="cb8-23"><a href="#cb8-23" aria-hidden="true" tabindex="-1"></a>        parser p<span class="op">{</span>ifs<span class="op">,</span> argv<span class="op">[</span>i<span class="op">]};</span></span>
<span id="cb8-24"><a href="#cb8-24" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-25"><a href="#cb8-25" aria-hidden="true" tabindex="-1"></a>        p<span class="op">.</span>next_expect<span class="op">(</span>parser<span class="op">::</span>start_element<span class="op">,</span> <span class="st">&quot;score&quot;</span><span class="op">,</span> content<span class="op">::</span>complex<span class="op">);</span></span>
<span id="cb8-26"><a href="#cb8-26" aria-hidden="true" tabindex="-1"></a>        cout <span class="op">&lt;&lt;</span> make_shared<span class="op">&lt;</span>bmml<span class="op">::</span>score<span class="op">&gt;(</span>p<span class="op">,</span> <span class="kw">false</span><span class="op">)</span> <span class="op">&lt;&lt;</span> endl<span class="op">;</span></span>
<span id="cb8-27"><a href="#cb8-27" aria-hidden="true" tabindex="-1"></a>        p<span class="op">.</span>next_expect<span class="op">(</span>parser<span class="op">::</span>end_element<span class="op">,</span> <span class="st">&quot;score&quot;</span><span class="op">);</span></span>
<span id="cb8-28"><a href="#cb8-28" aria-hidden="true" tabindex="-1"></a>      <span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb8-29"><a href="#cb8-29" aria-hidden="true" tabindex="-1"></a>        cerr <span class="op">&lt;&lt;</span> <span class="st">&quot;Unable to open &#39;&quot;</span> <span class="op">&lt;&lt;</span> argv<span class="op">[</span>i<span class="op">]</span> <span class="op">&lt;&lt;</span> <span class="st">&quot;&#39;.&quot;</span> <span class="op">&lt;&lt;</span> endl<span class="op">;</span></span>
<span id="cb8-30"><a href="#cb8-30" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> EXIT_FAILURE<span class="op">;</span></span>
<span id="cb8-31"><a href="#cb8-31" aria-hidden="true" tabindex="-1"></a>      <span class="op">}</span></span>
<span id="cb8-32"><a href="#cb8-32" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb8-33"><a href="#cb8-33" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span> <span class="cf">catch</span> <span class="op">(</span>xml<span class="op">::</span>exception <span class="at">const</span><span class="op">&amp;</span> e<span class="op">)</span> <span class="op">{</span></span>
<span id="cb8-34"><a href="#cb8-34" aria-hidden="true" tabindex="-1"></a>    cerr <span class="op">&lt;&lt;</span> e<span class="op">.</span>what<span class="op">()</span> <span class="op">&lt;&lt;</span> endl<span class="op">;</span></span>
<span id="cb8-35"><a href="#cb8-35" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> EXIT_FAILURE<span class="op">;</span></span>
<span id="cb8-36"><a href="#cb8-36" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb8-37"><a href="#cb8-37" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>That’s it for now. The full source for the actual library which inspired this
posting can be found on github in <a href="https://github.com/mlang">my</a> <a href="https://github.com/mlang/bmmlcxx">bmmlcxx</a> project.</p>
<p>If you have an comments or questions, send me <a href="mailto:mlang@blind.guru">mail</a>.
If you like <a href="https://github.com/mlang/bmmlcxx">bmmlcxx</a>, don’t forget to star it :-).</p>]]></summary>
</entry>
<entry>
    <title>Accidentals in Haskell</title>
    <link href="https://blind.guru/blog/2015-10-14-accidentals_in_haskell.html" />
    <id>https://blind.guru/blog/2015-10-14-accidentals_in_haskell.html</id>
    <published>2015-10-14T00:00:00Z</published>
    <updated>2015-10-14T00:00:00Z</updated>
    <summary type="html"><![CDATA[<p>I’ve had quite some fun recently (re)learning Haskell.
My learning project is to implement braille music notation parsing
in Haskell. Given that i’ve already implemented most of this stuff
in C++, it gives me a great opportunity to rethink my algorithms.</p>
<p>Not everything I’ve had to implement until now was actually pretty.
I spent yesterday evening implementing accidentals handling, which turned out
to be quite a mess. However, I wanted to share my definition
of the circle of fifths, because I find it rather concise.</p>
<h1 id="the-problem">The problem</h1>
<p>Given a key signature (often expressed as the number of sharp or flat
accidentals), tell which pitch classes are actually raised/lowered.</p>
<p>While reading through music notation software, I have seen several
implementations of this basic concept. However, I have
never seen one which was so concise.</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">module</span> <span class="dt">Accidental</span> <span class="kw">where</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span>           <span class="dt">Data.Map</span> (<span class="dt">Map</span>)</span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="kw">qualified</span> <span class="dt">Data.Map</span> <span class="kw">as</span> <span class="dt">Map</span> (fromList)</span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="kw">qualified</span> <span class="dt">Haskore.Basic.Pitch</span> <span class="kw">as</span> <span class="dt">Pitch</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a>fifths n</span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a>  <span class="op">|</span> n <span class="op">&gt;</span>  <span class="dv">0</span>    <span class="ot">=</span> <span class="kw">let</span> [a,b,c,d,e,f,g] <span class="ot">=</span> fifths (n<span class="op">-</span><span class="dv">1</span>) <span class="kw">in</span>  [d,e,f,g<span class="op">+</span><span class="dv">1</span>,a,b,c]</span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a>  <span class="op">|</span> n <span class="op">&lt;</span>  <span class="dv">0</span>    <span class="ot">=</span> <span class="kw">let</span> [a,b,c,d,e,f,g] <span class="ot">=</span> fifths (n<span class="op">+</span><span class="dv">1</span>) <span class="kw">in</span>  [e,f,g,a,b,c,d<span class="op">-</span><span class="dv">1</span>]</span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a>  <span class="op">|</span> <span class="fu">otherwise</span> <span class="ot">=</span> <span class="fu">replicate</span> <span class="dv">7</span> <span class="dv">0</span></span></code></pre></div>
<p>Given this, we can easily define a Map of pitches to currently
active accidentals/alterations. List comprehension to the rescue!</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="ot">accidentals ::</span> <span class="dt">Int</span> <span class="ot">-&gt;</span> <span class="dt">Map</span> <span class="dt">Pitch.T</span> <span class="dt">Pitch.Relative</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>accidentals k <span class="ot">=</span> Map.fromList [ ((o, c), a)</span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a>                             <span class="op">|</span> o <span class="ot">&lt;-</span> [<span class="dv">0</span><span class="op">..</span>maxOctave]</span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a>                             , (c, a) <span class="ot">&lt;-</span> <span class="fu">zip</span> diatonicSteps <span class="op">$</span> fifths k</span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a>                             , a <span class="op">/=</span> <span class="dv">0</span></span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a>                             ] <span class="kw">where</span></span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a>  maxOctave <span class="ot">=</span> <span class="dv">9</span></span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a>  diatonicSteps <span class="ot">=</span> [<span class="dt">Pitch.C</span>, <span class="dt">Pitch.D</span>, <span class="dt">Pitch.E</span>, <span class="dt">Pitch.F</span>, <span class="dt">Pitch.G</span>,</span>
<span id="cb2-9"><a href="#cb2-9" aria-hidden="true" tabindex="-1"></a>                   <span class="dt">Pitch.A</span>, <span class="dt">Pitch.B</span>]</span></code></pre></div>
<p>The full source code for the haskore-braille (WIP) package
can be found on <a href="https://github.com/mlang/haskore-braille">GitHub</a>.</p>
<p>If you have any comments regarding the implementation, please
drop me a <a href="mailto:mlang@blind.guru">mail</a>.</p>]]></summary>
</entry>
<entry>
    <title>Bjarne Stoustrup talking about organisations that can raise expectations</title>
    <link href="https://blind.guru/blog/2015-04-14-raising-expectations.html" />
    <id>https://blind.guru/blog/2015-04-14-raising-expectations.html</id>
    <published>2015-04-14T00:00:00Z</published>
    <updated>2015-04-14T00:00:00Z</updated>
    <summary type="html"><![CDATA[<p>At time index 22:35, <a href="http://en.wikipedia.org/wiki/Bjarne_Stroustrup">Bjarne Stroustrup</a> explains in <a href="https://www.youtube.com/watch?v=Hdp87bNbs3A">this video</a> what he
thinks is very special about organisatrions like Cambridge or Bell Labs.
When I just heard him explain this, I couldn’t help but think of Debian.
This is exactly how I felt (and actually still do) when I joined Debian
as a Developer in 2002. This is, what makes Debian, amongst other things,
very special to me.</p>
<p>If you don’t want to watch the video, here is the excerpt I am talking about:</p>
<blockquote>
<p>One of the things that Cambridge could do, and later Bell Labs could do,
is somehow raise peoples expectations of themselves.
Raise the level that is considered acceptable.
You walk in and you see what people are doing, you see how people are doing,
you see how apparently easily they do it, and you see how nice they are while
doing it, and you realize, I better sharpen up my game.
This is something where you have to, you just have to get better.
Because, what is acceptable has changed.
And some organisations can do that, and well, most can’t, to that extent.
And I am very very lucky to be in a couple places that actually can increase
your level of ambition, in some sense, level of what is a good standard.</p>
</blockquote>]]></summary>
</entry>
<entry>
    <title>Why is Qt5 not displaying Braille?</title>
    <link href="https://blind.guru/blog/2015-03-23-qt-braille.html" />
    <id>https://blind.guru/blog/2015-03-23-qt-braille.html</id>
    <published>2015-03-23T00:00:00Z</published>
    <updated>2015-03-23T00:00:00Z</updated>
    <summary type="html"><![CDATA[<p>While evaluating the cross-platform accessibility of Qt5, I stumbled
across this deficiency:</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode c++"><code class="sourceCode cpp"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;QApplication&gt;</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;QTextEdit&gt;</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main<span class="op">(</span><span class="dt">int</span> argv<span class="op">,</span> <span class="dt">char</span> <span class="op">**</span>args<span class="op">)</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a>  <span class="ex">QApplication</span> app<span class="op">(</span>argv<span class="op">,</span> args<span class="op">);</span></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a>  <span class="ex">QTextEdit</span> textEdit<span class="op">;</span></span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a>  textEdit<span class="op">.</span>setText<span class="op">(</span><span class="st">u8&quot;</span><span class="sc">\u28FF</span><span class="st">&quot;</span><span class="op">);</span></span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a>  textEdit<span class="op">.</span>show<span class="op">();</span></span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> app<span class="op">.</span>exec<span class="op">();</span></span>
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>(compile with -std=c++11).</p>
<p>On my system, this “application” does not show the correct glyph always.
Sometimes, it renders a a white square with black border, i.e., the symbol
for unknown glyph. However, if I invoke the same executable
several times, sometimes, it renders the glyph correctly.</p>
<p>In other words: The glyph choosing mechansim is apparently non-deterministic!!!</p>
<p>UPDATE: Sune Vuorela figured out that I need to set
<span class="title-ref">QT_HARFBUZZ=old</span> in the environment for this bug to go away.
Apparently, harfbuzz-ng from Qt 5.3 is buggy.</p>]]></summary>
</entry>
<entry>
    <title>Data-binding MusicXML</title>
    <link href="https://blind.guru/blog/2014-12-14-xsdcxx-musicxml.html" />
    <id>https://blind.guru/blog/2014-12-14-xsdcxx-musicxml.html</id>
    <published>2014-12-14T00:00:00Z</published>
    <updated>2014-12-14T00:00:00Z</updated>
    <summary type="html"><![CDATA[<p>My long-term free software project (<a href="https://github.com/mlang/bmc">Braille Music Compiler</a>) just produced
some offspring! <a href="https://github.com/mlang/xsdcxx-musicxml">xsdcxx-musicxml</a> is now available on GitHub.</p>
<p>I used <a href="http://codesynthesis.com/projects/xsd/">CodeSynthesis XSD</a> to generate a rather complete object
model for MusicXML 3.0 documents. Some of the classes needed a bit
of manual adjustment, to make the client API really nice and tidy.</p>
<p>During the process, I have learnt (as is almost always the case when programming)
quite a lot. I have to say, once you got the hang of it, <span class="title-ref">CodeSynthesis XSD</span>
is really a very powerful tool. I definitely prefer having these
100k lines of code auto-generated from a XML Schema, instead of
having to implement small parts of it by hand.</p>
<p>If you are into MusicXML for any reason, and you like C++,
give this library a whirl. At least to me, it is what I was always looking for:
Rather type-safe, with a quite self-explanatory API.</p>
<p>For added ease of integration, <span class="title-ref">xsdcxx-musicxml</span> is sub-project friendly.
In other words, if your project uses CMake and Git, adding xsdcxx-musicxml as a
subproject is as easy as using <span class="title-ref">git submodule add</span> and putting
<span class="title-ref">add_subdirectory(xsdcxx-musicxml)</span> into your <span class="title-ref">CMakeLists.txt</span>.</p>
<p>Finally, if you want to see how this library can be put to use:
The MusicXML export functionality of BMC is all in one C++ source file: <a href="https://github.com/mlang/bmc/blob/master/musicxml.cpp">musicxml.cpp</a>.</p>]]></summary>
</entry>
<entry>
    <title>A simple C++11 concurrent workqueue</title>
    <link href="https://blind.guru/blog/2014-09-30-simple_cxx11_workqueue.html" />
    <id>https://blind.guru/blog/2014-09-30-simple_cxx11_workqueue.html</id>
    <published>2014-09-30T00:00:00Z</published>
    <updated>2014-09-30T00:00:00Z</updated>
    <summary type="html"><![CDATA[<p>For a little toy project of mine (a <a href="http://github.com/mlang/wikiwordfreq">wikipedia XML dump word counter</a>)
I wrote a little C++11 helper class to distribute work to all
available CPU cores. It took me many years to overcome
my fear of threading: In the past, whenever I toyed with
threaded code, I ended up having a lot of deadlocks, and generally being
confused. It appears that I finally have understood enough of this
crazyness to be able to come up with the small helper class below.</p>
<h1 id="the-problem">The problem</h1>
<p>We want to spread work amongst all available CPU cores.
There are no dependencies between items in our work queue.
So every thread can just pick up and process an item as soon as it is ready.</p>
<h1 id="the-solution">The solution</h1>
<p>This simple implementation makes use of C++11 threading primitives, lambda functions
and move semantics.
The idea is simple: You provide a function at construction time which
defines how to process one item of work. To pass work
to the queue, simply call the function operator of the object,
repeatedly. When the destructor is called (once the object reachs
the end of its scope), all remaining items are processed and
all background threads are joined.</p>
<p>The number of threads defaults to the value of <a href="">std::thread::hardware_concurrency()</a>.
This appears to work at least since GCC 4.9. Earlier tests have
shown that std::thread::hardware<span id="concurrency">concurrency</span>() always returned 1.
I don’t know when exactly GCC (or libstdc++, actually) started
to support this, but at least since GCC 4.9, it is usable.
Prerequisite on Linux is a mounted /proc.</p>
<p>The number of maximum items per thread in the queue defaults to 1.
If the queue is full, calls to the function operator will block.</p>
<p>So the most basic usage example is probably something like:</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode c++"><code class="sourceCode cpp"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main<span class="op">()</span> <span class="op">{</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">typedef</span> <span class="bu">std::</span>string <span class="dt">item_type</span><span class="op">;</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>  distributor<span class="op">&lt;</span><span class="dt">item_type</span><span class="op">&gt;</span> process<span class="op">([](</span><span class="dt">item_type</span> <span class="op">&amp;</span>item<span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>    <span class="co">// do work</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a>  <span class="op">});</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a>  <span class="cf">while</span> <span class="op">(</span><span class="co">/* input */</span><span class="op">)</span> process<span class="op">(</span><span class="bu">std::</span>move<span class="op">(</span><span class="co">/* item */</span><span class="op">));</span></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>That is about as simple as it can get, IMHO.</p>
<p>The code can be found in the GitHub project mentioned above.
However, since the class template is relatively short, here it is.</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode c++"><code class="sourceCode cpp"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;condition_variable&gt;</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;mutex&gt;</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;queue&gt;</span></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;stdexcept&gt;</span></span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;thread&gt;</span></span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;vector&gt;</span></span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> Type<span class="op">,</span> <span class="kw">typename</span> Queue <span class="op">=</span> <span class="bu">std::</span>queue<span class="op">&lt;</span>Type<span class="op">&gt;&gt;</span></span>
<span id="cb2-9"><a href="#cb2-9" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> distributor<span class="op">:</span> Queue<span class="op">,</span> <span class="bu">std::</span>mutex<span class="op">,</span> <span class="bu">std::</span>condition_variable <span class="op">{</span></span>
<span id="cb2-10"><a href="#cb2-10" aria-hidden="true" tabindex="-1"></a>  <span class="kw">typename</span> Queue<span class="op">::</span><span class="dt">size_type</span> capacity<span class="op">;</span></span>
<span id="cb2-11"><a href="#cb2-11" aria-hidden="true" tabindex="-1"></a>  <span class="dt">bool</span> done <span class="op">=</span> <span class="kw">false</span><span class="op">;</span></span>
<span id="cb2-12"><a href="#cb2-12" aria-hidden="true" tabindex="-1"></a>  <span class="bu">std::</span>vector<span class="op">&lt;</span><span class="bu">std::</span>thread<span class="op">&gt;</span> threads<span class="op">;</span></span>
<span id="cb2-13"><a href="#cb2-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-14"><a href="#cb2-14" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span><span class="op">:</span></span>
<span id="cb2-15"><a href="#cb2-15" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">typename</span> Function<span class="op">&gt;</span></span>
<span id="cb2-16"><a href="#cb2-16" aria-hidden="true" tabindex="-1"></a>  distributor<span class="op">(</span> Function function</span>
<span id="cb2-17"><a href="#cb2-17" aria-hidden="true" tabindex="-1"></a>             <span class="op">,</span> <span class="dt">unsigned</span> <span class="dt">int</span> concurrency <span class="op">=</span> <span class="bu">std::</span>thread::hardware_concurrency<span class="op">()</span></span>
<span id="cb2-18"><a href="#cb2-18" aria-hidden="true" tabindex="-1"></a>         <span class="op">,</span> <span class="kw">typename</span> Queue<span class="op">::</span><span class="dt">size_type</span> max_items_per_thread <span class="op">=</span> <span class="dv">1</span></span>
<span id="cb2-19"><a href="#cb2-19" aria-hidden="true" tabindex="-1"></a>         <span class="op">)</span></span>
<span id="cb2-20"><a href="#cb2-20" aria-hidden="true" tabindex="-1"></a>  <span class="op">:</span> capacity<span class="op">{</span>concurrency <span class="op">*</span> max_items_per_thread<span class="op">}</span></span>
<span id="cb2-21"><a href="#cb2-21" aria-hidden="true" tabindex="-1"></a>  <span class="op">{</span></span>
<span id="cb2-22"><a href="#cb2-22" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> <span class="op">(</span><span class="kw">not</span> concurrency<span class="op">)</span></span>
<span id="cb2-23"><a href="#cb2-23" aria-hidden="true" tabindex="-1"></a>      <span class="cf">throw</span> <span class="bu">std::</span>invalid_argument<span class="op">(</span><span class="st">&quot;Concurrency must be non-zero&quot;</span><span class="op">);</span></span>
<span id="cb2-24"><a href="#cb2-24" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> <span class="op">(</span><span class="kw">not</span> max_items_per_thread<span class="op">)</span></span>
<span id="cb2-25"><a href="#cb2-25" aria-hidden="true" tabindex="-1"></a>      <span class="cf">throw</span> <span class="bu">std::</span>invalid_argument<span class="op">(</span><span class="st">&quot;Max items per thread must be non-zero&quot;</span><span class="op">);</span></span>
<span id="cb2-26"><a href="#cb2-26" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-27"><a href="#cb2-27" aria-hidden="true" tabindex="-1"></a>    <span class="cf">for</span> <span class="op">(</span><span class="dt">unsigned</span> <span class="dt">int</span> count <span class="op">{</span><span class="dv">0</span><span class="op">};</span> count <span class="op">&lt;</span> concurrency<span class="op">;</span> count <span class="op">+=</span> <span class="dv">1</span><span class="op">)</span></span>
<span id="cb2-28"><a href="#cb2-28" aria-hidden="true" tabindex="-1"></a>      threads<span class="op">.</span>emplace_back<span class="op">(</span><span class="kw">static_cast</span><span class="op">&lt;</span><span class="dt">void</span> <span class="op">(</span>distributor<span class="op">::*)(</span>Function<span class="op">)&gt;</span></span>
<span id="cb2-29"><a href="#cb2-29" aria-hidden="true" tabindex="-1"></a>                           <span class="op">(&amp;</span>distributor<span class="op">::</span>consume<span class="op">),</span> <span class="kw">this</span><span class="op">,</span> function<span class="op">);</span></span>
<span id="cb2-30"><a href="#cb2-30" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb2-31"><a href="#cb2-31" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-32"><a href="#cb2-32" aria-hidden="true" tabindex="-1"></a>  distributor<span class="op">(</span>distributor <span class="op">&amp;&amp;)</span> <span class="op">=</span> <span class="cf">default</span><span class="op">;</span></span>
<span id="cb2-33"><a href="#cb2-33" aria-hidden="true" tabindex="-1"></a>  distributor <span class="op">&amp;</span><span class="kw">operator</span><span class="op">=(</span>distributor <span class="op">&amp;&amp;)</span> <span class="op">=</span> <span class="kw">delete</span><span class="op">;</span></span>
<span id="cb2-34"><a href="#cb2-34" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-35"><a href="#cb2-35" aria-hidden="true" tabindex="-1"></a>  <span class="op">~</span>distributor<span class="op">()</span></span>
<span id="cb2-36"><a href="#cb2-36" aria-hidden="true" tabindex="-1"></a>  <span class="op">{</span></span>
<span id="cb2-37"><a href="#cb2-37" aria-hidden="true" tabindex="-1"></a>    <span class="op">{</span></span>
<span id="cb2-38"><a href="#cb2-38" aria-hidden="true" tabindex="-1"></a>      <span class="bu">std::</span>lock_guard<span class="op">&lt;</span><span class="bu">std::</span>mutex<span class="op">&gt;</span> guard<span class="op">(*</span><span class="kw">this</span><span class="op">);</span></span>
<span id="cb2-39"><a href="#cb2-39" aria-hidden="true" tabindex="-1"></a>      done <span class="op">=</span> <span class="kw">true</span><span class="op">;</span></span>
<span id="cb2-40"><a href="#cb2-40" aria-hidden="true" tabindex="-1"></a>      notify_all<span class="op">();</span></span>
<span id="cb2-41"><a href="#cb2-41" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb2-42"><a href="#cb2-42" aria-hidden="true" tabindex="-1"></a>    <span class="cf">for</span> <span class="op">(</span><span class="kw">auto</span> <span class="op">&amp;&amp;</span>thread<span class="op">:</span> threads<span class="op">)</span> thread<span class="op">.</span>join<span class="op">();</span></span>
<span id="cb2-43"><a href="#cb2-43" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb2-44"><a href="#cb2-44" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-45"><a href="#cb2-45" aria-hidden="true" tabindex="-1"></a>  <span class="dt">void</span> <span class="kw">operator</span><span class="op">()(</span>Type <span class="op">&amp;&amp;</span>value<span class="op">)</span></span>
<span id="cb2-46"><a href="#cb2-46" aria-hidden="true" tabindex="-1"></a>  <span class="op">{</span></span>
<span id="cb2-47"><a href="#cb2-47" aria-hidden="true" tabindex="-1"></a>    <span class="bu">std::</span>unique_lock<span class="op">&lt;</span><span class="bu">std::</span>mutex<span class="op">&gt;</span> lock<span class="op">(*</span><span class="kw">this</span><span class="op">);</span></span>
<span id="cb2-48"><a href="#cb2-48" aria-hidden="true" tabindex="-1"></a>    <span class="cf">while</span> <span class="op">(</span>Queue<span class="op">::</span>size<span class="op">()</span> <span class="op">==</span> capacity<span class="op">)</span> wait<span class="op">(</span>lock<span class="op">);</span></span>
<span id="cb2-49"><a href="#cb2-49" aria-hidden="true" tabindex="-1"></a>    Queue<span class="op">::</span>push<span class="op">(</span><span class="bu">std::</span>forward<span class="op">&lt;</span>Type<span class="op">&gt;(</span>value<span class="op">));</span></span>
<span id="cb2-50"><a href="#cb2-50" aria-hidden="true" tabindex="-1"></a>    notify_one<span class="op">();</span></span>
<span id="cb2-51"><a href="#cb2-51" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb2-52"><a href="#cb2-52" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-53"><a href="#cb2-53" aria-hidden="true" tabindex="-1"></a><span class="kw">private</span><span class="op">:</span></span>
<span id="cb2-54"><a href="#cb2-54" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> Function<span class="op">&gt;</span></span>
<span id="cb2-55"><a href="#cb2-55" aria-hidden="true" tabindex="-1"></a>  <span class="dt">void</span> consume<span class="op">(</span>Function process<span class="op">)</span></span>
<span id="cb2-56"><a href="#cb2-56" aria-hidden="true" tabindex="-1"></a>  <span class="op">{</span></span>
<span id="cb2-57"><a href="#cb2-57" aria-hidden="true" tabindex="-1"></a>    <span class="bu">std::</span>unique_lock<span class="op">&lt;</span><span class="bu">std::</span>mutex<span class="op">&gt;</span> lock<span class="op">(*</span><span class="kw">this</span><span class="op">);</span></span>
<span id="cb2-58"><a href="#cb2-58" aria-hidden="true" tabindex="-1"></a>    <span class="cf">while</span> <span class="op">(</span><span class="kw">true</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb2-59"><a href="#cb2-59" aria-hidden="true" tabindex="-1"></a>      <span class="cf">if</span> <span class="op">(</span><span class="kw">not</span> Queue<span class="op">::</span>empty<span class="op">())</span> <span class="op">{</span></span>
<span id="cb2-60"><a href="#cb2-60" aria-hidden="true" tabindex="-1"></a>        Type item <span class="op">{</span> <span class="bu">std::</span>move<span class="op">(</span>Queue<span class="op">::</span>front<span class="op">())</span> <span class="op">};</span></span>
<span id="cb2-61"><a href="#cb2-61" aria-hidden="true" tabindex="-1"></a>        Queue<span class="op">::</span>pop<span class="op">();</span></span>
<span id="cb2-62"><a href="#cb2-62" aria-hidden="true" tabindex="-1"></a>        notify_one<span class="op">();</span></span>
<span id="cb2-63"><a href="#cb2-63" aria-hidden="true" tabindex="-1"></a>        lock<span class="op">.</span>unlock<span class="op">();</span></span>
<span id="cb2-64"><a href="#cb2-64" aria-hidden="true" tabindex="-1"></a>        process<span class="op">(</span>item<span class="op">);</span></span>
<span id="cb2-65"><a href="#cb2-65" aria-hidden="true" tabindex="-1"></a>        lock<span class="op">.</span>lock<span class="op">();</span></span>
<span id="cb2-66"><a href="#cb2-66" aria-hidden="true" tabindex="-1"></a>      <span class="op">}</span> <span class="cf">else</span> <span class="cf">if</span> <span class="op">(</span>done<span class="op">)</span> <span class="op">{</span></span>
<span id="cb2-67"><a href="#cb2-67" aria-hidden="true" tabindex="-1"></a>        <span class="cf">break</span><span class="op">;</span></span>
<span id="cb2-68"><a href="#cb2-68" aria-hidden="true" tabindex="-1"></a>      <span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb2-69"><a href="#cb2-69" aria-hidden="true" tabindex="-1"></a>        wait<span class="op">(</span>lock<span class="op">);</span></span>
<span id="cb2-70"><a href="#cb2-70" aria-hidden="true" tabindex="-1"></a>      <span class="op">}</span></span>
<span id="cb2-71"><a href="#cb2-71" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb2-72"><a href="#cb2-72" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb2-73"><a href="#cb2-73" aria-hidden="true" tabindex="-1"></a><span class="op">};</span></span></code></pre></div>
<p>If you have any comments regarding the implementation, please
drop me a <a href="mailto:mlang@blind.guru">mail</a>.</p>]]></summary>
</entry>
<entry>
    <title>exercism.io C++ track</title>
    <link href="https://blind.guru/blog/2014-09-02-cxx-exercism.html" />
    <id>https://blind.guru/blog/2014-09-02-cxx-exercism.html</id>
    <published>2014-09-02T00:00:00Z</published>
    <updated>2014-09-02T00:00:00Z</updated>
    <summary type="html"><![CDATA[<p><a href="http://exercism.io/">exercism.io</a> is a croud-sourced mentorship platform for learning to program.
In my opinion, they do a lot of things right. In particular, an exercise
on exercism.io consists of a descriptive README file and a set of test
cases implemented in the target programming language. The tests have
two positive sides: You learn to do test-driven development, which is good.
And you also have an automated validation suite. Of course, a test can
not give you feedback on your actual implementation, but at least
it can give you an idea if you have managed to implement what
was required of you. But that is not the end of it. Once you have submitted
a solution to a particular exercise, other users of exercism.io can
comment on your implementation. And you can, as soon as you have
submitted the first implementation, look at the solutions that other
people have submitted to that particular problem. So knowledge transfer
can happen both ways from there on: You can learn new things from
how other people have solved the same problem, and you can also
tell other people about things they might have done in a different
way. These comments are, somewhat appropriately, called nitpicks on exercism.io.</p>
<p>Now, exercism has recently gained a C++ track.
That track is particularily fun, because it is based on C++11, Boost, and CMake.
Things that are quite standard to C++ development these days.
And the use of C++11 and Boost makes some solutions really shine.</p>]]></summary>
</entry>
<entry>
    <title>Four new packages on the GNU Emacs Package Archive (ELPA)</title>
    <link href="https://blind.guru/blog/2014-06-25-gnu-elpa.html" />
    <id>https://blind.guru/blog/2014-06-25-gnu-elpa.html</id>
    <published>2014-06-25T00:00:00Z</published>
    <updated>2014-06-25T00:00:00Z</updated>
    <summary type="html"><![CDATA[<p>I have begun to push some of the Emacs Lisp Packages I have
been working on over the last years to <a href="http://elpa.gnu.org/">GNU ELPA</a>, the Emacs Lisp
Package Archive.</p>
<p>That means you can use “M-x list-packages RET” to install them in GNU Emacs 24.</p>
<h1 id="opensound-control-library">OpenSound Control library</h1>
<p>In 2007, I wrote <a href="http://en.wikipedia.org/wiki/OpenSound_Control">OSC</a> server and client support for Emacs.
I used it back then to communicate with <a href="http://supercollider.sourceforge.net/">SuperCollider</a> and related software.</p>
<p><a href="http://elpa.gnu.org/packages/osc.html">osc.el</a> is a rather simple package with no user visible functionality, as
it only provides a library for Emacs Lisp programmers.</p>
<p>It is probably most interesting to people wanting to remote-control
(modern) sound related software from with Emacs Lisp.</p>
<h1 id="texas-holdem-poker">Texas hold’em poker</h1>
<p>As my interest in poker has recently sparked again,
one thing led to another, so I began to write a poker
library for GNU Emacs. It was a very fun experience.</p>
<p>Version 0.1 of <a href="http://elpa.gnu.org/packages/poker.html">poker.el</a> can simulate a table of ten players. Bots do
make their own decisions, although the bot code is very simple.
The complete game is currently played in the minibuffer.
So there is definitely room for user interface enhancements, such as a poker
table mode for displaying a table in a buffer.</p>
<h1 id="weather-information-from-weather.noaa.gov">Weather information from weather.noaa.gov</h1>
<p>I started to write <a href="http://elpa.gnu.org/packages/metar.html">metar.el</a> in 2007 as well, but never
really finished it to a releaseable state. I use it personally
rather often, but never cleaned it up for a release. This has changed.</p>
<p>It plugs in with other GNU Emacs features that make use of your current location.
In particular, “M-x sunrise-sunset” and “M-x phases-of-moon” use the same
variables (calendar-latitude and calendar-longitude) to determine where you are.
“M-x metar” will determine the nearest airport weather station and
display the weather information provided by that station.</p>
<h1 id="chess">Chess</h1>
<p>Finally, after many many years of development separated by
uncountable amounts of hiatus, <a href="http://elpa.gnu.org/packages/chess.html">chess.el</a> is now out as version 2.0.3!</p>
<p>For a more detailed article about <a href="http://elpa.gnu.org/packages/chess.html">chess.el</a>, see <a href="http://blind.guru/emacs-chess.html">here</a>.</p>]]></summary>
</entry>
<entry>
    <title>Accessible single-player texas hold'em poker for iOS</title>
    <link href="https://blind.guru/blog/2014-05-07-THETA_Poker_Pro.html" />
    <id>https://blind.guru/blog/2014-05-07-THETA_Poker_Pro.html</id>
    <published>2014-05-07T00:00:00Z</published>
    <updated>2014-05-07T00:00:00Z</updated>
    <summary type="html"><![CDATA[<p>I have been looking for an App like this since I got my first iOS device in
december 2011. Finally, it is here! A single-player (bot-driven) poker
app for iOS, <a href="http://www.thetapoker.com/">THETA Poker Pro</a>, fully accessible and usable with <a href="http://www.apple.com/accessibility/ios/voiceover/">VoiceOver</a>.
<a href="http://www.applevis.com/">AppleVis</a> has <a href="http://www.applevis.com/apps/ios/games/theta-poker-pro-texas-hold-em">a review</a>.</p>
<p>It doesn’t happen <em>very</em> often, but App programmers in the iOS Universe
do indeed sometimes think about Accessibility support, and the APIs
provided by <a href="http://www.apple.com/">Apple</a> are useful enough to allow programmers to write
very accessible apps. You can say about Apple whatever you want,
currently, it is the company providing the best accessibility support on the market.
Why? Because they made accessibility a first-class citizen of their platform(s).
This is where policy helps. If you can dictate top-down that
you support people with disabilities, things actually
start to happen. If you have to ask, hope, and wait, like it is with
free software, things do not really progress as fast as the users need it.</p>
<p>Back to THETA Poker Pro: The default configuration is already very useable with VoiceOver.
However, if you want the cards placed on the board announced to you, so that
you do not have to discover them manually by touch, you can enable the
“Card Announcement” item in the Options menu. You can also set message delay
a bit slower, such that all messages are actually fully spoken and not cut off sometimes.
With these two settings adjusted, and maybe “Animation” set to “Very fast”,
the game feels extremely nice. There is actually nothing I would
want to change, which does not happen very often when I test
a program for its accessibility.</p>
<p>With these settings changed, game play is very smooth with VoiceOver, you basically
just have to tap your cards to check, tap the deck to fold, or tap
your chips to raise. Very simple, and these three “buttons” are on
the bottom of the screen, so rather easy and quick to find.
All other activity is automatically announced by VoiceOver.</p>
<p>I have played a few hundred hands already with this App. It is a wonderful
way to pass time. For instance, I don’t like to go to my
doctor, because I usually wait up to two or three hours. I had to pay
her a visit on monday. While waiting, I played “a few” hands, and
suddenly, I was already called in. When I came out again, I checked the
time and was rather surprised that yes, I have waited two hours again,
but this time, I didn’t notice! :-)</p>
<p>Special thanks go to the author(s) of this app.
It is a good example of an App that was not specially made for the blind,
but which feels like it was. Thanks, you’ve made my week!</p>
<h1 id="a-small-rant">A small rant</h1>
<p>OTOH, it makes me sad when I think about my beloved Linux platform and GUI accessibility.
We are stuck since 2004 with a bit of desktop support + a half-working
Firefox. During the D-Bus rewrite, quality of GUI accessibility
has dropped so much that I had to take time off from linux
gui accessibility to stay sane. It is back to where it was in 2006, yay,
but we haven’t made a lot of real progress in the last 8 years.
Granted, firefox has improved, but to my taste, not enough.
I still do all my email, shell work, programming and some other things on Linux of course,
but I notice that I do more and more casual stuff
on iOS, it is just sooo much more useable. I do almost all my
surfing with mobile safari, because it just works. Firefox works sometimes, and
some other times working with it feels so slow that I am actually getting
angry.</p>
<p>The scratch-your-own-itch philosophy combined with a very small margin group is
poison for success. We’d need much more funding, and people working
actively on this stuff as their day job, if we ever want to
be competitive with existing solutions.</p>]]></summary>
</entry>
<entry>
    <title>Accessible voting graphs</title>
    <link href="https://blind.guru/blog/2014-04-04-accessible-voting-graphs.html" />
    <id>https://blind.guru/blog/2014-04-04-accessible-voting-graphs.html</id>
    <published>2014-04-04T00:00:00Z</published>
    <updated>2014-04-04T00:00:00Z</updated>
    <summary type="html"><![CDATA[<p>It is that time of the year again, <a href="http://www.debian.org/">Debian</a> is <a href="http://www.debian.org/vote/2014/vote_001">electing the Project Leader</a>
for 2014/15. Whenever a Debian vote is in progress, I find
myself rather happy to rediscover that Debian is providing
<a href="https://vote.debian.org/~secretary/leader2014/index_txt.html">text mode voting graphs</a>. These are quite accessible
to me as a braille user. It is rather unusual for me as a blind
person to be able to access any graphs on the internet at all.</p>
<p>All this has been made possible by gnuplots ability
to generate text plots, and Manoj’s willingness to implement
it during his term as project secretary. Thanks to Gnuplot and Manoj,
and thanks to the current secretary for keeping this feature, it is (at least
to me) a very nice to have, and actually makes Debian rather unique.</p>
<p>I personally don’t know of any other major projects which
provide text graphs. We are indeed setting a very good example here.
It would be nice if other projects would adopt this as well.
This is bridging the digital divide for me.</p>
<p>For completeness sake I should probably mention that text graphs are not
an universal solution for blind users. Those of us who do not
use braille will probably have a very hard time extracting
any meaningful information from this ASCII character salad.
But to a braille user used to reading two dimensional information
from the screen, it does actually work rather well. Some solutions
from the 90s, when people didn’t have graphical terminals readily available
everywhere, are still very good accessibility workarounds.</p>]]></summary>
</entry>
<entry>
    <title>Accessible DNS hosting with LuaDNS</title>
    <link href="https://blind.guru/blog/2014-03-26-luadns.html" />
    <id>https://blind.guru/blog/2014-03-26-luadns.html</id>
    <published>2014-03-26T00:00:00Z</published>
    <updated>2014-03-26T00:00:00Z</updated>
    <summary type="html"><![CDATA[<p>I used to host my internet infrastructure at <a href="https://he.net/">Hurricane Electric</a>.
It all started in october 1998 with <a href="https://en.wikipedia.org/wiki/POP3">POP3</a>/<a href="https://en.wikipedia.org/wiki/SMTP">SMTP</a>, <a href="https://en.wikipedia.org/wiki/HTTP">HTTP</a> and <a href="https://en.wikipedia.org/wiki/DNS">DNS</a>.
In the coming years, I began to host all services except DNS on my own.
But I kept using <code>he.net</code> for its DNS management interface.
It was dead simple, and therefore accessible.
All they had was a basic textarea with <a href="https://www.isc.org/downloads/bind/">BIND</a> alike configuration in it.
I could log in to their admin interface and change my DNS records as desired.</p>
<p>A few years ago, they auto-upgraded my account to their
new shiny DNS panel, which, surprise surprise, is no longer accessible
with a simple text browser.
After a bit of bitching with support, they ended up downgrading
my account back to the old functionality, so I was happy again.
However, as you might guess, last time I needed to change
a DNS record, I found that the DNS panel has been ugpraded
yet again and is again no longer accessible to me.</p>
<p>So it was time to leave the sinking ship.
But I needed to find an accessible DNS hosting service.
Not an easy task, given that everyone seems to do more
or less the same thing these days.</p>
<h1 id="git-to-the-rescue">Git to the rescue!</h1>
<p>After a bit of web searching it became apparent that most
offers these days are not what I want.
I want a simple interface without any danger of accessibility issues.
In most cases, you can not test the DNS management interface
before signup. After a few dead ends, I took a step back and said to myself:
“So, what is it that I am actually looking for?
If this were a wishlist item, how would I like my workflow to be?”
And the answer came immediately: “I want my zonefiles in a git repo!”</p>
<p>So I decided to turn my search upside down and search exactly for that.
And guess what, I found exactly what I was looking for: <a href="http://luadns.com/">LuaDNS</a>.</p>
<p>LuaDNS has 5 nameservers in Europe, Asia and North America.
As the name implies, it offers a way to write your zone files
with <a href="https://www.lua.org/">Lua</a>. This can be quite helpful for programmatically generating
zones. However, it also supports BIND alike zone files, which is <a href="https://github.com/mlang/dns.git">what I use</a>.</p>
<p>The idea is simple: You create a <a href="https://git-scm.com/">Git</a> repository on <a href="https://github.com/">GitHub</a> or <a href="https://bitbucket.org/">BitBucket</a>
and let LuaDNS know where it is. A web hook can be setup
to automatically trigger zone rebuilds once you push to your repository.</p>
<p>So all my accessibility problems around DNS hosting are suddenly completely
gone.
Once I edited/commited my zone files and pushed to my repository, LuaDNS
will automatically pull from the repository and update my zones.</p>
<ul>
<li>I can edit my zones with my editor of choice without having to go through the web.</li>
<li>I have history for my DNS changes.</li>
<li>I can revert changes easily.</li>
<li>Changes can have descriptive commit log entries.</li>
<li>All the usual advantages of Git.</li>
</ul>
<p>And I will never have to fight with an inaccessible web interface again.
That said, LuaDNS has a web interface for administering account settings.
It works very nice with Lynx. I hope they keep it that way.</p>
<h1 id="current-luadns-limitations">Current LuaDNS limitations</h1>
<p>There are two things I don’t particularily like about LuaDNS currently:</p>
<ul>
<li>There are currently no <a href="https://en.wikipedia.org/wiki/List_of_DNS_record_types#AAAA">AAAA</a> records for their DNS servers.
This is apparently being worked on and is supposed to be fixed somewhere
around april 2014. Note that AAAA records are perfectly supported by
LuaDNS zone files, it is just that none of the DNS servers they provide to you
offers any AAAA records yet. So IPv6-only hosts might have trouble to reach your
site if they don’t use an IPv4 enabled recursor (a rather rare setup I guess).</li>
<li>Due to the way BIND alike zone files work in LuaDNS (<a href="https://en.wikipedia.org/wiki/List_of_DNS_record_types#SOA">SOA</a> records are autogenerated),
you can currently not sign your zones. I’ve been told <a href="https://en.wikipedia.org/wiki/DNSSEC">DNSSEC</a> is on the list
of things to work on at LuaDNS, so I am looking forward to see what they will
implement.</li>
</ul>
<p>The team is friendly and was very fast to react on a question via email.
Looks good, I’ll stay.</p>
<p>Now that I think of it, this article might be considered
an answer to Steve Kemps question <a href="http://blog.steve.org.uk/what_do_you_pay_for__and_what_would_you_pay_for_.html">what would you pay for</a>:
I’d pay for a VCS based DNS hosting solution that allows me to use DNSSEC, if
its web interface were kept clean and simple and therefore accessible.
However, I don’t mind a free account for low volume usage at all.
Especially if that makes it easy to test the service and make sure
it works as expected.</p>]]></summary>
</entry>
<entry>
    <title>grub-efi-amd64 on a MacBook Air</title>
    <link href="https://blind.guru/blog/2014-03-17-grub-efi-amd64-mba-upgrade.html" />
    <id>https://blind.guru/blog/2014-03-17-grub-efi-amd64-mba-upgrade.html</id>
    <published>2014-03-17T00:00:00Z</published>
    <updated>2014-03-17T00:00:00Z</updated>
    <summary type="html"><![CDATA[<p>When I installed <a href="https://www.debian.org/">Debian</a> on my MacBookAir4,1 in 2012, there was no way
to do it without manual intervention yet. I followed
a tutorial on how to boot <a href="https://www.gnu.org/software/grub/">GRUB</a> from the <span class="title-ref">EFI Boot</span> option
in the MacBook EFI Menu. I did not want to fiddle
with <a href="http://refit.sourceforge.net/">rEFIt</a>, and I didn’t want to boot GRUB by default.
When I want to boot Linux, I press the <span class="title-ref">Option key</span> during power up
and select <span class="title-ref">EFI Boot</span> from the Apple boot menu.</p>
<p>Unfortunately, I neglected to collect notes about how I
did it manually. However, Linux 3.2 is getting a bit old, so I
finally wanted to replace my manual boot configuration
with something handled by the package system.</p>
<p>In case you don’t have <code>/boot/efi</code> in <code>/etc/fstab</code> yet,
you need to mount <code>/dev/sda1</code> on <code>/boot/efi</code> for the following to work.</p>
<p>The documentation I found on the net suggested to just
reinstall <code>grub-efi-amd64</code> and everything should work.
That is not quite true. When I do</p>
<pre class="console"><code># apt-get install --reinstall grub-efi-amd64</code></pre>
<p>Nothing changes in <code>/boot/efi</code>.</p>
<p>I sort of expected that <code>/boot/efi/EFI/debian</code> would be
created, and the EFI image should be placed in there. However,
that did not happen. Why is that?</p>
<p>It turns out that when I installed <code>grub-efi-amd64</code> manually in 2012, I
created <code>/boot/efi/EFI/boot/bootx64.efi</code> which is the EFI fallback location,
and apparently exactly what I want on this MacBook which does not support
multiple boot options.
<a href="http://mjg59.dreamwidth.org/">Matthew Garrett</a> posted an interesting article called
<a href="http://mjg59.dreamwidth.org/4125.html">Booting with EFI</a> which sheds light on this issue, go and read it.</p>
<p>Looking at <code>/var/lib/dpkg/info/grub-efi-amd64.postinst</code> revealed
that <code>/boot/efi/EFI/debian</code> needs to be created manually first.
If this directory does not exist, <code>grub-efi-amd64</code> basically
does nothing on reinstall.</p>
<p>Running <code>grub-install</code> will actually create a new EFI image.
However, it is being created in the wrong place for this machine.</p>
<pre class="console"><code># grub-install --target=x86_64-efi</code></pre>
<p>does the trick. Now <code>/boot/efi/EFI/debian/grubx64.efi</code> gets
created. However, since I don’t want to make GRUB the default,
there is yet another manual step to do:</p>
<pre class="console"><code># cp /boot/efi/EFI/debian/grubx64.efi /boot/efi/EFI/boot/bootx64.efi</code></pre>
<p>Now I can select <span class="title-ref">EFI Boot</span> after pressing the <span class="title-ref">Option key</span> during
startup. GRUB is loaded and Linux 3.13 gets booted. Strike!</p>
<p>Looking more closely reveals that there is actually a way to
tell <code>grub-install</code> that it should install to
the fallback location directly. The <code>--removable</code> option does that.</p>
<p>For the faint of heart, what does <code>grub-install</code> actually do
on an EFI system? It does not directly write to the disk, therefore
it does not need a device specified. It looks for files in
<code>/boot/efi</code> and assumes the EFI partition is mounted there.</p>
<p>So for my use case, the correct way to upgrade to a current GRUB EFI image
should have been:</p>
<pre class="console"><code># grub-install --removable --target=x86_64-efi</code></pre>
<p>Meanwhile I’ve been made aware of <a href="https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=708430">Bug#708430</a>.
I guess it would be nice to have an option in <code>/etc/default/grub</code>
which would indicate that installation to the fallback location
is desired. While this is a rather ugly hack to work around a stupid
limitation, it is still what I’d like on this MacBook. At least
since I don’t have a triplle boot situation. Fallback location works
fine with just two OSes coexisting.</p>]]></summary>
</entry>
<entry>
    <title>Personal mail server</title>
    <link href="https://blind.guru/blog/2014-03-04-personal-mail-server.html" />
    <id>https://blind.guru/blog/2014-03-04-personal-mail-server.html</id>
    <published>2014-03-04T00:00:00Z</published>
    <updated>2014-03-04T00:00:00Z</updated>
    <summary type="html"><![CDATA[<p>I used to use <a href="http://www.fetchmail.info/">Fetchmail</a> and <a href="http://gnus.org/">Gnus</a> with its mail splitting capabilites
and <a href="http://gnus.org/manual/big-gnus.html#SEC194">nnml</a> backend to handle my private mail setup for many years.
This worked pretty fine since I am used to accessing my home server
through <a href="http://www.openssh.org/">SSH</a>. I have Gnus running inside of a <a href="http://savannah.gnu.org/projects/screen">GNU screen</a> session.
So I can check mail from remote by using a SSH terminal.</p>
<p>This works fine as long as I have a good SSH terminal on
a desktop or laptop computer. However, it does not work
very well on tablets or smaller mobile devices.</p>
<p>Additionally, mail splitting has become a performance burden over the years.
I do not want to wait for Gnus to sort incoming mail into different
folders while checking for new mail. That is something which should have
been done in the background already, and thats what we are going to
cover with the setup described below.</p>
<p>So I had to change my simple setup to accomodate for the new trends
in mobile computing.</p>
<p>The obvious core of such a setup is an IMAP server which receives and
stores your mail such that different clients can access it. So
the time of my Gnus nnml storage are definitely over.
Mail is no longer stored in and by my mail client.</p>
<h1 id="dovecot">Dovecot</h1>
<p>While there are several IMAP server solutions out there,
I find <a href="http://dovecot.org/">Dovecot</a> fits my needs quite nicely.</p>
<p>I’ve decided to store my mail in <a href="http://en.wikipedia.org/wiki/Maildir">Maildir</a> format in <code>~/Maildir</code>.
I prefer storing data like that in the home directory to avoid
having to backup separate files from <code>/var/</code>.
Maildir also features some index files which should help
performance in the long run.</p>
<p>Incoming mail will solely be delivered by <code>fetchmail</code> and should
be checked for spam. While I can probably configure <a href="http://www.exim.org/">Exim</a> to run <a href="http://spamassassin.apache.org/">SpamAssassin</a>
on mails before delivering them to Dovecot, there is a much more
elegant solution: the dovecot <a href="http://wiki2.dovecot.org/LDA">local delivery agent (LDA)</a>.
<code>/usr/lib/dovecot/deliver</code> takes mail from standard input and performs
Sieve filtering and updates the mail indexes. We will call
this executable more or less directly from <code>fetchmail</code>.</p>
<p>Incoming mail from mailing lists will be sorted into
different folders using <a href="http://en.wikipedia.org/wiki/Sieve_(mail_filtering_language)">Sieve</a>. Dovecot needs to
be told to enable the sieve plugin and to create new folders on demand.</p>
<p><code>/etc/dovecot/local.conf</code>:</p>
<pre><code>disable_plaintext_auth = yes
mail_location = maildir:~/Maildir
lda_mailbox_autocreate = yes
lda_mailbox_autosubscribe = yes
protocol lda {
  mail_plugins = sieve
}</code></pre>
<p>Sieve scripts are actually quite intuitive once you have a template to start from.</p>
<p><code>~/.dovecot.sieve</code>:</p>
<pre><code>require &quot;fileinto&quot;;

if exists &quot;X-Spam-Flag&quot; {
  # Store spam tagged by SpamAssassin into dedicated Spam folder
  if header :contains &quot;X-Spam-Flag&quot; &quot;YES&quot; {
    fileinto &quot;Spam&quot;;
  }
} elsif exists &quot;X-Cron-Env&quot; {
  # Store mails from Cron daemon in dedicated folder
  fileinto &quot;cron&quot;;
} elsif exists &quot;List-Id&quot; {
  # File list-mail into dedicated folders, matching on List-Id
  if header :contains &quot;List-Id&quot; &quot;boost-users.lists.boost.org&quot; {
    fileinto &quot;boost-users&quot;;
  } elsif header :contains &quot;List-Id&quot; &quot;brltty.mielke.cc&quot; {
    fileinto &quot;brltty&quot;;
  } elsif header :contains &quot;List-Id&quot; &quot;debian-accessibility.lists.debian.org&quot; {
    fileinto &quot;debian-accessibility&quot;;
  } elsif header :contains &quot;List-Id&quot; &quot;debian-devel-announce.lists.debian.org&quot; {
    fileinto &quot;debian-devel-announce&quot;;
  } elsif header :contains &quot;List-Id&quot; &quot;debian-devel.lists.debian.org&quot; {
    fileinto &quot;debian-devel&quot;;
  } elsif header :contains &quot;List-Id&quot; &quot;spirit-general.lists.sourceforge.net&quot; {
    fileinto &quot;spirit-general&quot;;
  }
  # ...
}</code></pre>
<h1 id="spamassassin">SpamAssassin</h1>
<p>Since I want automatic classification of spam messages, I use
SpamAssassin. Just install spamassasin and enable spamd
in <code>/etc/default/spamassassin</code>:</p>
<pre><code>ENABLE=1</code></pre>
<p>We will use <code>spamc</code> in the Fetchmail configuration.</p>
<h1 id="fetchmail">Fetchmail</h1>
<p>My <code>~/.fetchmailrc</code> is a straightforward list of some mailboxes to fetch mail from.
I use the <span class="title-ref">mda</span> directive to skip the MTA and send mail through SpamAssassin and
deliver it to Dovecot via its LDA mechanism.</p>
<p><code>~/.fetchmailrc</code>:</p>
<pre><code>set daemon 1200 # Poll at 10 minute intervals
poll blind.guru protocol IMAP: ssl;
# ... add more sources here ...

mda &quot;/usr/bin/spamc -u %T -e /usr/lib/dovecot/deliver -d %T&quot;</code></pre>
<p>To avoid spreading access information in too many configuration files
I am using the ability of Fetchmail to use <code>netrc</code> to retrieve account passwords.</p>
<p><code>~/.netrc</code>:</p>
<pre><code>machine blind.guru login mlang password &lt;hidden&gt;</code></pre>
<h1 id="gnus">Gnus</h1>
<p>I am using <a href="http://gnus.org/">Gnus</a> to read mail, newsgroups and RSS feeds since many years now.
It would be quite a mouthful to explain all the customizations I am using by
now. But there is one very important bit in the context of this article:
How to access the IMAP server? In my setup, Emacs and therefore Gnus
is running on the same machine as the IMAP server. So I can
avoid authentication at all. This configuration will avoid
unnecessary password prompts or caching.</p>
<p>In <code>~/.emacs</code> or <code>~/.gnus</code>:</p>
<pre class="emacs-lisp"><code>(setq gnus-secondary-select-methods &#39;((nnimap &quot;localhost&quot;
                                       (nnimap-stream shell)))
      nnimap-shell-program &quot;/usr/lib/dovecot/imap&quot;)</code></pre>
<p>With this you should be able to subscribe to your IMAP folders
from within Gnus with ease.</p>
<p>Sorting incoming mails into folders is now performed by the IMAP server
through Sieve scripts. Instead of changing Gnus’ configuration I now
edit <code>~/.dovecot.sieve</code> when I subscribe to a new mailing list.
If you add a new Sieve rule for a mailing list and the associated
folder does not exist yet, Dovecot will autocreate it, very convenient.</p>
<h1 id="mobile-devices">Mobile devices</h1>
<p>Now all that is left is a way for your mobile devices to
read and eventually send mail. This is very much dependant on your
network setup, so I am not going to go into any detail here.
If you are accessing your mail setup from a tablet in your local
network you might get away without tinkering with your router configuration.
If you want to read/send mail on the go
you need some way to get to your external IP. Either it is
stable enough or you need some dynamic DNS service. You will
definitely want to forward IMAP and maybe SMTP ports from your
router to your home server. If you don’t have an existing
SMTP server for your mobile device that accepts your outgoing
mails you can also set one up yourself and deliver outgoing mails
from your mobile device to the world with Exim or qmail.</p>
<p>I am personally using Exim since I am going with the default MTA for <a href="http://www.debian.org/">Debian</a>.
Configuring Exim to take mail from iOS devices was as simple
as enabling an appropriate authentication method and adding an
account to <code>/etc/exim4/passwd</code>. I have to admit though
that I don’t particularily like Exim’s configuration files.
That is why I ended up using dovecot’s LDA in the first place.</p>]]></summary>
</entry>
<entry>
    <title>I am a programming language</title>
    <link href="https://blind.guru/blog/2014-02-25-i-am-a-programming-language.html" />
    <id>https://blind.guru/blog/2014-02-25-i-am-a-programming-language.html</id>
    <published>2014-02-25T00:00:00Z</published>
    <updated>2014-02-25T00:00:00Z</updated>
    <summary type="html"><![CDATA[<p>I love learning about programming languages.
But this one really took me by surprise.</p>
<p>Yes, apparently there is a <a href="http://en.wikipedia.org/wiki/BrainFuck">BrainFuck</a> alike two-dimensional
esoteric programming language called <a href="http://esolangs.org/wiki/MarioLANG">MarioLANG</a>.</p>
<p>And <a href="https://github.com/">GitHub</a> even has <a href="https://github.com/mynery/mariolang.rb">an implementation</a> written in <a href="http://www.ruby-lang.org/">Ruby</a>.</p>
<p>I should really allocate a bit of spare time to write at least something
in myself.</p>]]></summary>
</entry>
<entry>
    <title>boost::python and boost::variant</title>
    <link href="https://blind.guru/blog/2014-02-08-boost_python-and-boost_variant.html" />
    <id>https://blind.guru/blog/2014-02-08-boost_python-and-boost_variant.html</id>
    <published>2014-02-08T00:00:00Z</published>
    <updated>2014-02-08T00:00:00Z</updated>
    <summary type="html"><![CDATA[<p>I have unsuccessfully tried to find a solution for the following problem on the
internet several times. Now that I have come at least closer to a usable
approach, I thought I’d document what I have found so that others trying to
achieve a similar thing can use this as a starting point.</p>
<p><a href="http://www.boost.org/doc/libs/1_55_0/libs/python/doc/index.html">Boost.Python</a> offers a very nice and flexible way to interface C++ data types
with <a href="http://www.python.org/">Python</a>. With just a few lines of code, and the proper
linker flags, you get a Python importable shared object
from your C++ compiler. This can be very productive.</p>
<p>However, there is one aspect of C++ data types that I couldn’t figure
out how to interface with Python, which are C++ <a href="http://en.wikipedia.org/wiki/Tagged_union">discriminated unions</a>, or more
specifically, heterogeneous containers. While Python has no problems
with containers containing objects of different types, C++ does not
make this very easy by default. Usually the problem is solved with
a container of pointers to a base class, and various subclasses with virtual
functions. However, this approach is not always practical, especially
if the different types of objects in an heterogeneous container
dont have many things in common. This is where <span class="title-ref">discriminated unions</span> come to
the rescue. They basically behave like a normal union in C, but have
an additional field which indicates the type of object
currently stored in the union. <a href="http://www.boost.org/doc/libs/1_55_0/doc/html/variant.html">Boost.Variant</a> does exactly that,
with a nice visitor interface added on top of it.</p>
<h1 id="heterogeneous-containers-in-c">Heterogeneous containers in C++</h1>
<p>If we put the boost::variant&lt;&gt; template inside a STL container like std::vector&lt;&gt;,
the result is a heterogeneous container. For the purpose of illustration,
lets implement such a container. The example below is
deliberately simple. In reality, the various types allowed
in your variant will probably have more fields then just one.</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode c++"><code class="sourceCode cpp"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;boost/variant.hpp&gt;</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;vector&gt;</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> a <span class="op">{</span> <span class="dt">int</span> x<span class="op">;</span> <span class="op">};</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> b <span class="op">{</span> <span class="bu">std::</span>string y<span class="op">;</span> <span class="op">};</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a><span class="kw">typedef</span> <span class="ex">boost::</span>variant<span class="op">&lt;</span>a<span class="op">,</span> b<span class="op">&gt;</span> variant<span class="op">;</span></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a><span class="kw">typedef</span> <span class="bu">std::</span>vector<span class="op">&lt;</span>variant<span class="op">&gt;</span> vector<span class="op">;</span></span></code></pre></div>
<p>To ease creation of these two types of objects,
we are going to write a few factory functions.
We are going to wrap them in Python later on.</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode c++"><code class="sourceCode cpp"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a>variant make_variant<span class="op">()</span> <span class="op">{</span> <span class="cf">return</span> variant<span class="op">();</span> <span class="op">}</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>vector make_vector<span class="op">()</span> <span class="op">{</span> <span class="cf">return</span> vector<span class="op">{</span>a<span class="op">(),</span> b<span class="op">(),</span> a<span class="op">()};</span> <span class="op">}</span></span></code></pre></div>
<h1 id="boost.python">Boost.Python</h1>
<p>Now lets create a Python module which exports the above functionality to Python.</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode c++"><code class="sourceCode cpp"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;boost/python/class.hpp&gt;</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;boost/python/def.hpp&gt;</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;boost/python/implicit.hpp&gt;</span></span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;boost/python/init.hpp&gt;</span></span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;boost/python/module.hpp&gt;</span></span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;boost/python/object.hpp&gt;</span></span>
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;boost/python/suite/indexing/vector_indexing_suite.hpp&gt;</span></span></code></pre></div>
<p><a href="http://www.boost.org/doc/libs/1_55_0/libs/python/doc/v2/indexing.html#vector_indexing_suite">vector_indexing_suite</a> apparently needs operator==
defined on the value<span id="type">type</span> of the container. In our case,
this is our boost::variant&lt;a, b&gt; type. Luckily, boost::variant&lt;&gt;
already provides operator==. However, that operator== relies
on operator== being defined for the underlying types.
Since equality comparison is probably useful for other
things as well, lets just create operator== for our two classes a and b.</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode c++"><code class="sourceCode cpp"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="dt">bool</span> <span class="kw">operator</span><span class="op">==(</span>a <span class="at">const</span> <span class="op">&amp;</span>lhs<span class="op">,</span> a <span class="at">const</span> <span class="op">&amp;</span>rhs<span class="op">)</span> <span class="op">{</span> <span class="cf">return</span> lhs<span class="op">.</span>x <span class="op">==</span> rhs<span class="op">.</span>x<span class="op">;</span> <span class="op">}</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a><span class="dt">bool</span> <span class="kw">operator</span><span class="op">==(</span>b <span class="at">const</span> <span class="op">&amp;</span>lhs<span class="op">,</span> b <span class="at">const</span> <span class="op">&amp;</span>rhs<span class="op">)</span> <span class="op">{</span> <span class="cf">return</span> lhs<span class="op">.</span>y <span class="op">==</span> rhs<span class="op">.</span>y<span class="op">;</span> <span class="op">}</span></span></code></pre></div>
<h2 id="convert-a-boostvariant-to-pyobject">Convert a boost::variant&lt;&gt; to <span class="title-ref">PyObject *</span></h2>
<p><a href="http://www.boost.org/doc/libs/1_55_0/libs/python/doc/index.html">Boost.Python</a> needs a way to convert our discriminated union to a Python object.
This code relies on Python class definitions being present for all underlying
variant types. We will define them later.</p>
<div class="sourceCode" id="cb5"><pre class="sourceCode c++"><code class="sourceCode cpp"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> variant_to_object <span class="op">:</span> <span class="ex">boost::</span>static_visitor<span class="op">&lt;</span>PyObject <span class="op">*&gt;</span> <span class="op">{</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a>  <span class="at">static</span> <span class="dt">result_type</span> convert<span class="op">(</span>variant <span class="at">const</span> <span class="op">&amp;</span>v<span class="op">)</span> <span class="op">{</span></span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> apply_visitor<span class="op">(</span>variant_to_object<span class="op">(),</span> v<span class="op">);</span></span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-6"><a href="#cb5-6" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">typename</span> T<span class="op">&gt;</span></span>
<span id="cb5-7"><a href="#cb5-7" aria-hidden="true" tabindex="-1"></a>  <span class="dt">result_type</span> <span class="kw">operator</span><span class="op">()(</span>T <span class="at">const</span> <span class="op">&amp;</span>t<span class="op">)</span> <span class="at">const</span> <span class="op">{</span></span>
<span id="cb5-8"><a href="#cb5-8" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> <span class="ex">boost::</span>python::incref<span class="op">(</span><span class="ex">boost::</span>python::object<span class="op">(</span>t<span class="op">).</span>ptr<span class="op">());</span></span>
<span id="cb5-9"><a href="#cb5-9" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb5-10"><a href="#cb5-10" aria-hidden="true" tabindex="-1"></a><span class="op">};</span></span></code></pre></div>
<p>And finally, lets create our Python module.</p>
<div class="sourceCode" id="cb6"><pre class="sourceCode c++"><code class="sourceCode cpp"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="ex">BOOST_</span>PYTHON_MODULE<span class="op">(</span>bpv<span class="op">)</span> <span class="op">{</span></span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> <span class="kw">namespace</span> <span class="ex">boost::</span>python<span class="op">;</span></span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a>  <span class="va">class_</span><span class="op">&lt;</span>a<span class="op">&gt;(</span><span class="st">&quot;a&quot;</span><span class="op">,</span> init<span class="op">&lt;</span>a<span class="op">&gt;()).</span>def<span class="op">(</span>init<span class="op">&lt;&gt;()).</span>def_readwrite<span class="op">(</span><span class="st">&quot;x&quot;</span><span class="op">,</span> <span class="op">&amp;</span>a<span class="op">::</span>x<span class="op">);</span></span>
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true" tabindex="-1"></a>  <span class="va">class_</span><span class="op">&lt;</span>b<span class="op">&gt;(</span><span class="st">&quot;b&quot;</span><span class="op">,</span> init<span class="op">&lt;</span>b<span class="op">&gt;()).</span>def<span class="op">(</span>init<span class="op">&lt;&gt;()).</span>def_readwrite<span class="op">(</span><span class="st">&quot;y&quot;</span><span class="op">,</span> <span class="op">&amp;</span>b<span class="op">::</span>y<span class="op">);</span></span>
<span id="cb6-6"><a href="#cb6-6" aria-hidden="true" tabindex="-1"></a>  to_python_converter<span class="op">&lt;</span>variant<span class="op">,</span> variant_to_object<span class="op">&gt;();</span></span>
<span id="cb6-7"><a href="#cb6-7" aria-hidden="true" tabindex="-1"></a>  implicitly_convertible<span class="op">&lt;</span>a<span class="op">,</span> variant<span class="op">&gt;();</span></span>
<span id="cb6-8"><a href="#cb6-8" aria-hidden="true" tabindex="-1"></a>  implicitly_convertible<span class="op">&lt;</span>b<span class="op">,</span> variant<span class="op">&gt;();</span></span>
<span id="cb6-9"><a href="#cb6-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-10"><a href="#cb6-10" aria-hidden="true" tabindex="-1"></a>  def<span class="op">(</span><span class="st">&quot;make_variant&quot;</span><span class="op">,</span> make_variant<span class="op">);</span></span>
<span id="cb6-11"><a href="#cb6-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-12"><a href="#cb6-12" aria-hidden="true" tabindex="-1"></a>  <span class="va">class_</span><span class="op">&lt;</span>vector<span class="op">&gt;(</span><span class="st">&quot;vector&quot;</span><span class="op">).</span>def<span class="op">(</span>vector_indexing_suite<span class="op">&lt;</span>vector<span class="op">,</span> <span class="kw">true</span><span class="op">&gt;());</span></span>
<span id="cb6-13"><a href="#cb6-13" aria-hidden="true" tabindex="-1"></a>  def<span class="op">(</span><span class="st">&quot;make_vector&quot;</span><span class="op">,</span> make_vector<span class="op">);</span></span>
<span id="cb6-14"><a href="#cb6-14" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<h1 id="compiling">Compiling</h1>
<p>Lets create a shared object for Python.</p>
<pre class="console"><code>$ g++ -std=c++11 -fPIC -shared $(python-config --includes) -o bpv.so file.cpp -lboost_python</code></pre>
<h1 id="running">Running</h1>
<p>We can load the module into Python and see what it does.</p>
<pre class="pycon"><code>&gt;&gt;&gt; import bpv
&gt;&gt;&gt; variant=bpv.make_variant()
&gt;&gt;&gt; variant
&lt;bpv.a object at 0x7f06bb2130c0&gt;
&gt;&gt;&gt; variant.x
0
&gt;&gt;&gt; variant.x=2
&gt;&gt;&gt; variant.x
2</code></pre>
<p>Nice. We can access the underlying type, and even modify it.</p>
<p>Lets see how our heterogeneous container wrapping code behaves.</p>
<pre class="pycon"><code>&gt;&gt;&gt; vector=bpv.make_vector()
&gt;&gt;&gt; vector
&lt;bpv.vector object at 0x7f20693289d0&gt;
&gt;&gt;&gt; len(vector)
3
&gt;&gt;&gt; list(vector)
[&lt;bpv.a object at 0x7f20693190c0&gt;, &lt;bpv.b object at 0x7f20693193d0&gt;, &lt;bpv.a object at 0x7f2069319440&gt;]</code></pre>
<p>So far, so good. This will at least make it possible to convert heterogeneous
containers from C++ to Python, which was my initial goal.</p>
<p>Unfortunately, contained objects are not treated as references.
Whenever retrieved, we get a copy. So in-place modification does not work.</p>
<pre class="pycon"><code>&gt;&gt;&gt; vector[0].x
0
&gt;&gt;&gt; vector[0].x=2
&gt;&gt;&gt; vector[0].x
0</code></pre>
<p>However, we can override an existing element with a modified copy.</p>
<pre class="pycon"><code>&gt;&gt;&gt; e0=vector[0]
&gt;&gt;&gt; type(e0)
&lt;class &#39;bpv.a&#39;&gt;
&gt;&gt;&gt; e0.x = 2
&gt;&gt;&gt; vector[0] = e0
&gt;&gt;&gt; vector[0].x
2</code></pre>
<p>And we can also use the append and extend methods of Python containers.</p>
<pre class="pycon"><code>&gt;&gt;&gt; len(vector)
3
&gt;&gt;&gt; vector.extend(vector)
&gt;&gt;&gt; vector.append(bpv.a())
&gt;&gt;&gt; len(vector)
7
&gt;&gt;&gt; len(filter(lambda x: type(x)==bpv.b, vector))
2
&gt;&gt;&gt; len(filter(lambda x: type(x)==bpv.a, vector))
5
&gt;&gt;&gt; map(lambda x: x.x, filter(lambda x: type(x)==bpv.a, vector))
[2, 0, 2, 0, 0]</code></pre>
<p>All that is missing for a perfect world is reference semantics for
container elements. If anyone has a hint on how to achieve this, please let me know.</p>]]></summary>
</entry>
<entry>
    <title>Comptine d'un autre été</title>
    <link href="https://blind.guru/blog/2011-04-01-comptine.html" />
    <id>https://blind.guru/blog/2011-04-01-comptine.html</id>
    <published>2011-04-01T00:00:00Z</published>
    <updated>2011-04-01T00:00:00Z</updated>
    <summary type="html"><![CDATA[<p>Recorded a short piano piece from the movie Amélie yesterday.</p>
<!--more-->
<p>This has definitely been fun! I've recorded a small piano piece from
the movie Amélie (2001). It is on YouTube, to make it easy for various
platforms to <a href="http://www.youtube.com/watch?v=n_Vtr6ThCnA">play it</a>.</p>]]></summary>
</entry>
<entry>
    <title>Martial arts for the blind?</title>
    <link href="https://blind.guru/blog/2010-03-18-wing-chun.html" />
    <id>https://blind.guru/blog/2010-03-18-wing-chun.html</id>
    <published>2010-03-18T00:00:00Z</published>
    <updated>2010-03-18T00:00:00Z</updated>
    <summary type="html"><![CDATA[<p>I might have found a martial arts technique that seems to have
good chances of working even if you are totally blind.</p>
<p>&lt;–!more–&gt;</p>
<p>Wing Chun promotes two principles which do indeed read and sound like it
might be exactly what a blind person wants to practice: <a href="http://en.wikipedia.org/wiki/Wing_Chun#Close_range">Close
range</a> and
<a href="http://en.wikipedia.org/wiki/Wing_Chun#Uncommitted_techniques">uncommitted
techniques</a>.
I can't really tell you more just now except what you can already read
on the Internet. Just one more very relevant pointer: <a href="http://en.wikipedia.org/wiki/Wing_Chun#Chi_sao">Chi
sao</a> (sticking hands).
The idea is to develop reflexes especially for close range combat, and
the principle is to always stay in contact with your opponent, something
that very much resonates with me (obviously, keeping in touch with your
opponent is exactly what you need if you have no sight at all).</p>]]></summary>
</entry>
<entry>
    <title>CAPTCHA: The great new legal way of getting rid of blind people</title>
    <link href="https://blind.guru/blog/2009-06-22-captcha.html" />
    <id>https://blind.guru/blog/2009-06-22-captcha.html</id>
    <published>2009-06-22T00:00:00Z</published>
    <updated>2009-06-22T00:00:00Z</updated>
    <summary type="html"><![CDATA[<p>I just tried to register a twitter account. After seven
unsuccessful attempts to unriddle the audio CAPTCHA I had to give up
before my anger would hurt anything in my proximity. This is a post in
rant mode, so be prepared, however, I think it has some valid points
seen from the perspective of those that fell victim to the recent
CAPTCHA movement.</p>
<p>&lt;–!more–&gt;</p>
<p>I hate CAPTCHAs, for the obvious reasons. At first, it
ment that I started to be excluded from all sorts of services on the
net, basically everything that requires me to register an account and
thinks of itself being leet or something. I find it particularily funny
(in the chinese sense) that CAPTCHAs started to emerge after the W3C's
Web Accessibility initiatives finally made some progress in educating
web designers. So while the internet is now officially accessible (at
least its easy to claim this today) they have now found a much better
way to exclude us blind people categorically. They just pretend we are
no humans anymore (thats actually nothing new in perceived real life,
but it feels new to me in information technology).</p>
<p>Now, of course, you will say, these days there are audio CAPTCHAs.
However, this is what I tried to use on twitter.com. They tell me they
are looking for two words I am supposed to enter, and I am also supposed
to not worry, the best guess is OK. As mentioned above, I tried this
seven times. With some attempts, I didn't understand a single word at
all, with other attempts, I understood way more than two words. It was
never marked clearly which of the excess words are supposed to be
ignored. No matter what I entered, I apparently failed to solve the
CAPTCHA and proof my humanity.</p>
<p>And I am even lucky, I tend to think of myself as someone that does
understand english quite well when listening to it, a ability that not
everyone has in my country that has german as its primary language.
Supposing that twitter is an international service and not really linked
to english as a primary communication language, the audio CAPTCHA is
also excluding all the people that do not speak/hear english very well.
Besides, this point doesnt matter, because I bet you can't solve that
CAPTCHA on first try even if you are a native speaker, its just too damn
crazy.</p>
<p>So, what to do? I have no idea. I guess my frustration will just grow
boundlessly. CAPTCHAs are the first events in IT that make me think
about my ability to do this job in the future. If these trends persists,
I dunno how I am supposed to take part in the Internet in the future.</p>]]></summary>
</entry>
<entry>
    <title>How to use Eclipse with Orca on Linux</title>
    <link href="https://blind.guru/blog/2008-10-30-eclipse.html" />
    <id>https://blind.guru/blog/2008-10-30-eclipse.html</id>
    <published>2008-10-30T00:00:00Z</published>
    <updated>2008-10-30T00:00:00Z</updated>
    <summary type="html"><![CDATA[<p>While my initial look at Eclipse a few months ago was a bit
disappointing, I gave it a second try a short while ago. Fortunately, it
turns out to be much easier than originally thought, Eclipse is really
pretty accessible once you know the important keyboard shortcuts.</p>
<!--more-->
<p>Most of the currently visible problems seem to be focus related, read this
article if you are a Eclipse Dev and want to get an insight into what
you could fix to make it even better!</p>
<p>Here is a list of the shortcuts I found very valuable as a blind eclipse
user:</p>
<ul>
<li>Alt+Shift+Q P: Jumps to "Package explorer", very useful if you
want to navigate to an editor window showing a particular class.</li>
<li>Alt+Shift+X J: Run your application.</li>
<li>Alt+Shift+Q X: Shows the Problems view. You invoke this after
building and/or running your app. The view contains a Tree of errors
and warnings, expand the collapsed items to see the actual
erorrs/warnings. Hitting return/enter on a error/warning jumps to
the location in an editor window and highlights the problematic
problematic expression (see next item)..</li>
<li>Ctrl+1: Quick Fix. If a problematic expression was highlighted this
gives you a list of things you can automatically do about it to fix
it. Once you press Ctrl+1 this window doesn't have focus, so you
need to hit TAB once immediately after Ctrl+1 to see the choices.
Select one by hitting return and the magic takes place.</li>
<li>Ctrl+SPACE: Complete a method while typing. This has the same
problem as quick fix, the popup window doesn't get focus
automatically, just hit TAB to get around this problem.</li>
<li>Alt+Shift+Q C: Go to console output window. I usually do this after
running my app to check if there was any unexpected output.</li>
<li>Ctrl+F6: Switch to next editor window. Sometimes, Eclipse looses
focus and you end up in nowhere land. Either F10 followed by escape
or Ctrl+F6 helps a lot here.</li>
</ul>]]></summary>
</entry>
<entry>
    <title>Reading from the monitor with a mobile phone</title>
    <link href="https://blind.guru/blog/2008-09-17-ocr.html" />
    <id>https://blind.guru/blog/2008-09-17-ocr.html</id>
    <published>2008-09-17T00:00:00Z</published>
    <updated>2008-09-17T00:00:00Z</updated>
    <summary type="html"><![CDATA[<p>Some of you might already know about this piece of software for
Symbian phones (for the N82 in particular) that does OCR directly from
the phones built-in camera. I have such a thing (a big thanks to my
employer) and find it very valueable in daily usage. But this is a story
about a use case that I never would have dared to hope for.</p>
<!--more-->
<p>I can use my
mobile phone to read the content of my monitor! This is the first time I
feel like experiencing technology from the 21st century. From now on, if
something fails unexpectedly I am no longer required to ask someone to
read whats displayed on the monitor, I have a new possibility to try
first. While this is not practical when you actually try to interact
with a program, it can at least help to figure out what error message is
displayed.</p>
<p>Yesterday evening I had a pretty simple job to do: Create a partition
table on a new 2GB CompactFlash card, transfer old partition content to
it and make the card bootable. So far, so good. I did what I needed to
do, and then slotted the CF-card into the test machine. After turning
the device on, the usual thing happened: nothing. Since the machine
didn't show up on my network with the IP address I configured,
something must have gone wrong. Damn. At this point you are usually
pretty stuck if you are blind and without a sighted coworker. While
serial consoles are a nice thing to have, PC BIOSes are usually a bitch
when it comes to working serial consoles. This test machine has a pretty
old BIOS too, so forget about that route. Since it was already past
midnight, there was no one around whom I could ask to read the monitor
content to me either. Which lead me to an idea: Why not use my <a href="http://www.knfbreader.com/">KNFB
Reader</a> to figure out whats going on?</p>
<p>To make a long story short: Yes, it works! I had to turn off the light
in my room to get optimal results, but after that, it basically works as
reliable as with print on paper! The tabular data displayed didn't get
read correct, but that was not what I was after. The last sentence my
phone said was what I needed to know:</p>
<blockquote>
<p>"Insert disk and press a key to continue"</p>
</blockquote>
<p>So while I haven't been able to fix the actual problem at hand (the
BIOS does not support CF cards larger than 1GB) I was at least able to
narrow the problem down to the BIOS not recognising my new CF card as
bootable media.</p>
<p>This opens up completely new possibilities of independence in my
profession.</p>
<p>Now who is going to put together a special version of
<a href="http://code.google.com/p/ocropus/">OCRopus(tm)</a> for mobile devices? A
coworker of mine is already thinking about writing a tool for doing
things like color analysis using a mobile phone camera. I think this is
a very exciting idea loaded with possibilities. The world needs more
practically oriented open source projects related to optical
recognition!</p>]]></summary>
</entry>

</feed>
