<?xml version='1.0' encoding='UTF-8'?>
<rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/" version="2.0">
  <channel>
    <title>davep</title>
    <link>https://blog.davep.org</link>
    <description>Latest posts from davep</description>
    <atom:link href="https://blog.davep.org/feed.xml" rel="self"/>
    <docs>http://www.rssboard.org/rss-specification</docs>
    <generator>python-feedgen</generator>
    <language>en</language>
    <lastBuildDate>Sat, 18 Jul 2026 15:46:33 +0000</lastBuildDate>
    <item>
      <title>Rogallo v0.10.0</title>
      <link>https://blog.davep.org/2026/07/18/rogallo-v0-10-0.html</link>
      <description>&lt;p&gt;&lt;a href="https://rogallo.davep.dev/" rel="noopener noreferrer" target="_blank"&gt;Rogallo&lt;/a&gt;
&lt;a href="https://rogallo.davep.dev/changelog/#v0100" rel="noopener noreferrer" target="_blank"&gt;v0.10.0&lt;/a&gt; is now available. This
release has a number of changes, including some new features, some changes
to the user interface, and a couple of quality-of-life improvements.&lt;/p&gt;
&lt;h2 id="maximum-document-width"&gt;Maximum document width&lt;/h2&gt;
&lt;p&gt;Amongst some feedback someone left &lt;a href="gemini://station.martinrue.com/davep/666afe3d00074b079d2529ac0f4953b8" rel="noopener noreferrer" target="_blank"&gt;on a slightly unrelated post over on
&lt;code&gt;station&lt;/code&gt;&lt;/a&gt;
there was mention of how a document &lt;em&gt;"should"&lt;/em&gt; wrap at around 72 characters.
While no rationale was given for the "should" part, I was happy enough to
accept that this could be a preference for some people. With this in mind,
I've added &lt;a href="https://rogallo.davep.dev/configuration/#maximum-document-width" rel="noopener noreferrer" target="_blank"&gt;a configuration option to set a maximum width for
documents&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;While, personally, I prefer Rogallo's default behaviour (I work in an
environment where I can resize a window, and I'm capable of doing it), I can
appreciate that someone might want to cap it. So for folk who prefer this,
they can now make Rogallo look like this (with &lt;code&gt;maximum_document_width&lt;/code&gt; set
to &lt;code&gt;80&lt;/code&gt;):&lt;/p&gt;
&lt;p&gt;&lt;img alt="Max document width in action" height="1984" loading="lazy" src="https://blog.davep.org/attachments/2026/07/18/max-doc-width.webp#centre" width="2054" /&gt;&lt;/p&gt;
&lt;p&gt;For the moment this can only be set via the configuration file. At some
point I might make this more of a dynamic thing. I can imagine this being
something handy, or at least fun, to change up as you're viewing different
content.&lt;/p&gt;
&lt;h2 id="link-jump-timeout"&gt;Link jump timeout&lt;/h2&gt;
&lt;p&gt;The same feedback "suggested" that the link jumping facility that Rogallo
has should have a timeout that clears the buildup of the number being looked
for. This seemed like a reasonable thing to ask for. So, before, if you
typed &lt;kbd&gt;1&lt;/kbd&gt;, a link with a label of &lt;code&gt;1&lt;/code&gt; would be selected. If you did
nothing for a while, and then typed &lt;kbd&gt;2&lt;/kbd&gt;, a link with the label of
&lt;code&gt;12&lt;/code&gt; would be highlighted. With the new timeout (set to 1 second by default,
configurable in the configuration file), if you type &lt;kbd&gt;1&lt;/kbd&gt; and then
&lt;kbd&gt;2&lt;/kbd&gt; more than a second later, first link &lt;code&gt;1&lt;/code&gt; will be selected, then
link &lt;code&gt;2&lt;/code&gt; will be selected. On the other hand, if you type &lt;kbd&gt;1&lt;/kbd&gt; then
&lt;kbd&gt;2&lt;/kbd&gt; within a second, &lt;code&gt;12&lt;/code&gt; will be selected.&lt;/p&gt;
&lt;p&gt;Setting the timeout to &lt;code&gt;0&lt;/code&gt; disables this and Rogallo's link jumping facility
will work as it did before.&lt;/p&gt;
&lt;h2 id="failed-input-recovery"&gt;Failed input recovery&lt;/h2&gt;
&lt;p&gt;With this new feature, if you send input text to a capsule and it rejects it
for some reason, the input will be held on to. If you then visit the same
URI again, the input dialog will be pre-populated with what you attempted to
send a moment ago. This gives you the opportunity to edit anything wrong
with the submission and try again.&lt;/p&gt;
&lt;h2 id="added-all-application-commands-to-the-command-line"&gt;Added all application commands to the command line&lt;/h2&gt;
&lt;p&gt;If you prefer to use Rogallo's command line more than the command palette,
I've now ensured that &lt;a href="https://rogallo.davep.dev/configuration/#keyboard-bindings" rel="noopener noreferrer" target="_blank"&gt;all bindable application
commands&lt;/a&gt; can be
accessed via the command line. There's a difference in their form, to stay
in keeping with the command line. So whereas in the command palette you'd
run &lt;code&gt;GoHome&lt;/code&gt; by typing &lt;code&gt;go home&lt;/code&gt;, in the command line it becomes a
&lt;code&gt;!&lt;/code&gt;-prefixed snake-case command: &lt;code&gt;!go_home&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;All possible commands are listed in the help screen if it's brought up while
the command line has focus.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Help showing commands" height="2368" loading="lazy" src="https://blog.davep.org/attachments/2026/07/18/cli-help.webp#centre" width="2310" /&gt;&lt;/p&gt;
&lt;h2 id="capsule-navigation-commands"&gt;Capsule navigation commands&lt;/h2&gt;
&lt;p&gt;Rogallo now has two new commands for quickly navigating within the current
capsule path. &lt;code&gt;GoToParent&lt;/code&gt; will navigate up a level in the path of the
current URI, and &lt;code&gt;GoToRoot&lt;/code&gt; will go to the root of the capsule.&lt;/p&gt;
&lt;h2 id="visited-vs-non-visited-links"&gt;Visited vs non-visited links&lt;/h2&gt;
&lt;p&gt;The icon for links is now used to show if a link is already in the location
history (and so has been visited before), or not:&lt;/p&gt;
&lt;p&gt;&lt;img alt="Visited and non-visited links" height="228" loading="lazy" src="https://blog.davep.org/attachments/2026/07/18/link-colours.webp#centre" width="692" /&gt;&lt;/p&gt;
&lt;p&gt;Here you can see that &lt;code&gt;Account settings&lt;/code&gt; isn't in the visit history, but the
other two links are. I was going to do the whole link, but I've never been a
fan of how web browsers do this, so I've gone with just the icon. I've also
made it subtle but still noticeable. So far, I'm much preferring this; I
don't need it blasting out the difference, I just need it to be enough for
me to notice&lt;sup id="fnref:378-1"&gt;&lt;a class="footnote-ref" href="#fn:378-1"&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;h2 id="swapped-around-history-and-bookmark-tools"&gt;Swapped around history and bookmark tools&lt;/h2&gt;
&lt;p&gt;Until now the "history" and "bookmarks" shortcut keys advertised in the
footer brought up the sidebar-based management widgets. This made sense when
that's all I had in Rogallo. For a while now though I've had palette-based
search tools for both history and bookmarks. Normally I want to search for
and select a bookmark or history item way more than I want to manage those
lists. So I've relegated the sidebar-based tools to a secondary position and
placed the palette-based search tools up front.&lt;/p&gt;
&lt;p&gt;This also means that the default bindings have changed a bit. As always, you
can discover the bindings &lt;a href="https://rogallo.davep.dev/#bindings" rel="noopener noreferrer" target="_blank"&gt;with &lt;code&gt;rogallo
bindings&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="conclusion"&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;I know I've nodded towards this before, but I think I'm getting close to
making a v1.0.0 release. I want to daily-drive for a few more days, and I'd
also like to expand &lt;a href="https://rogallo.davep.dev" rel="noopener noreferrer" target="_blank"&gt;the website&lt;/a&gt;. I'd &lt;em&gt;also&lt;/em&gt;
like to build a Gemini/Gemtext-based site for Rogallo -- it'd be pretty
weird if I only documented it in http(s)space. I won't let those wishes
become blockers for moving to calling Rogallo "stable", but it would be nice
to have.&lt;/p&gt;
&lt;div class="footnote"&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id="fn:378-1"&gt;
&lt;p&gt;I do recognise that there's an &lt;a href="https://blog.davep.org/tag/a11y/"&gt;a11y&lt;/a&gt; issue here with the
subtle difference; there's some work to be done at some point to allow
for a high-contrast theme that will resolve this sort of issue.&amp;#160;&lt;a class="footnote-backref" href="#fnref:378-1" title="Jump back to footnote 1 in the text"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description>
      <guid isPermaLink="false">https://blog.davep.org/2026/07/18/rogallo-v0-10-0.html</guid>
      <category>Coding</category>
      <category>Coding</category>
      <category>Gemini Protocol</category>
      <category>PyPI</category>
      <category>Python</category>
      <category>Rogallo</category>
      <category>gemtext</category>
      <category>smolweb</category>
      <category>textual</category>
      <pubDate>Sat, 18 Jul 2026 16:44:46 +0100</pubDate>
    </item>
    <item>
      <title>Wasat v0.8.0</title>
      <link>https://blog.davep.org/2026/07/18/wasat-v0-8-0.html</link>
      <description>&lt;p&gt;&lt;a href="https://wasat.davep.dev/" rel="noopener noreferrer" target="_blank"&gt;Wasat&lt;/a&gt;
&lt;a href="https://wasat.davep.dev/changelog/#v080" rel="noopener noreferrer" target="_blank"&gt;v0.8.0&lt;/a&gt; is now available. This
provides a small update to the &lt;code&gt;GeminiURI&lt;/code&gt; class, adding three utility
properties for extra URI manipulation.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;without_query&lt;/code&gt; - gives the URI minus any attached query&lt;/li&gt;
&lt;li&gt;&lt;code&gt;parent&lt;/code&gt; - gives the parent path of the current URI (also minus the query)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;root&lt;/code&gt; - gives the root path for the current URI (also minus the query)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In each case, the result is a fresh &lt;code&gt;GeminiURI&lt;/code&gt; instance.&lt;/p&gt;
&lt;p&gt;These are added because I'm aiming to add "go to parent" and "go to root"
commands to &lt;a href="https://rogallo.davep.dev/" rel="noopener noreferrer" target="_blank"&gt;Rogallo&lt;/a&gt;.&lt;/p&gt;</description>
      <guid isPermaLink="false">https://blog.davep.org/2026/07/18/wasat-v0-8-0.html</guid>
      <category>Python</category>
      <category>Coding</category>
      <category>Gemini Protocol</category>
      <category>PyPI</category>
      <category>Python</category>
      <category>smolweb</category>
      <category>wasat</category>
      <pubDate>Sat, 18 Jul 2026 10:23:11 +0100</pubDate>
    </item>
    <item>
      <title>Terminal bean soup</title>
      <link>https://blog.davep.org/2026/07/17/terminal-bean-soup.html</link>
      <description>&lt;p&gt;I'm sure most people reading this will be familiar with the concept of "bean
soup theory". In case anyone isn't, &lt;a href="https://en.wikipedia.org/wiki/Glossary_of_2020s_slang#B" rel="noopener noreferrer" target="_blank"&gt;here's how Wikipedia describes
it&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;A specific phenomenon described as a 'What about me' effect. An individual
watches a video that doesn't pertain to them, but finds a way to make it
about them anyway. Stems from a 2023 TikTok recipe for bean soup, with
commenters saying "What if I don't like beans?"&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I feel there's a very specific set of folk who love to "bean soup" anything
relating to terminals, and it's common to have them turn up in your mentions
if you happen to do &lt;em&gt;anything&lt;/em&gt; in the terminal, or for the terminal, that
isn't about their purist opinions and how everything &lt;em&gt;must&lt;/em&gt; be a Vim clone,
or worse.&lt;/p&gt;
&lt;p&gt;I first encountered this when &lt;a href="https://blog.davep.org/2022/10/05/on-to-something-new-redux.html"&gt;I started working at
Textualize&lt;/a&gt;. Unsurprisingly,
given the point, purpose and focus of &lt;a href="https://blog.davep.org/tag/textual/"&gt;Textual&lt;/a&gt;, some folk
would turn up in the Discord server, in the issues, in the discussions, in
the mentions of posts in various places, and post their &lt;em&gt;very important
opinions&lt;/em&gt; about how TUI software &lt;em&gt;must&lt;/em&gt; work. Not... discuss their
preferences, or offer suggestions (there were plenty of people who were
pleasant like that, they were lovely to converse with), no: their engagement
was written as if every word that was mashed into their keyboard was a
well-crafted, handed-from-on-high RFC-like holy document that &lt;strong&gt;MUST&lt;/strong&gt; and
&lt;strong&gt;SHOULD&lt;/strong&gt; be followed&lt;sup id="fnref:391-1"&gt;&lt;a class="footnote-ref" href="#fn:391-1"&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;If I was being very charitable I could cut them some slack. If you're
building a framework for building applications for the terminal, there's a
good reason to make it at least possible for the application authors to
follow recognised best practice and to stick with hard-won conventions.
Indeed, Textual has some design choices that I think are deeply questionable
and misguided and I objected to them on more than one occasion. So, yeah, if
I was being charitable, I could cut them some slack.&lt;/p&gt;
&lt;p&gt;I could... if they weren't such arseholes about it.&lt;/p&gt;
&lt;p&gt;This gets worse though if you're building an application for the terminal,
especially if it's built as Free Software and the motivation is &lt;em&gt;to build
something for yourself and be kind enough to share&lt;/em&gt;. It irks the hell out of
me when I build some application for myself, as a TUI, and then someone
turns up and starts complaining about &lt;em&gt;my&lt;/em&gt; choice of default key bindings,
that work in &lt;em&gt;my&lt;/em&gt; choice of terminal emulator and &lt;em&gt;my&lt;/em&gt; configuration for
that emulator.&lt;/p&gt;
&lt;p&gt;It's even worse when they do it in a way where they have to show their &lt;em&gt;very
deep knowledge&lt;/em&gt; of terminals, and how they're very proud of just how lacking
in features and progress their own choice of terminal emulator is.&lt;/p&gt;
&lt;p&gt;Dude...&lt;sup id="fnref:391-2"&gt;&lt;a class="footnote-ref" href="#fn:391-2"&gt;2&lt;/a&gt;&lt;/sup&gt; I know. I've used physical terminals. I've written COBOL on a
minicomputer using a line editor on some honking great dumb all-green
all-in-one box. I've even written code on a terminal using fan-fold paper.
I've used all sorts of terminal emulators. I spent well over a decade doing
shit inside &lt;code&gt;rxvt&lt;/code&gt; which was running on my GNU/Linux server while displaying
on my Windows desktop machine.&lt;/p&gt;
&lt;p&gt;I've &lt;a href="https://github.com/Textualize/textual-key-recorder" rel="noopener noreferrer" target="_blank"&gt;installed and tested plenty of terminal
emulators&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I'm well aware of the conventions and expectations. If
&lt;kbd&gt;Ctrl&lt;/kbd&gt;+&lt;kbd&gt;C&lt;/kbd&gt; doesn't quit... that is &lt;strong&gt;my choice&lt;/strong&gt;. It's not
ignorance, it's not a lack of history with this stuff, it's a choice. For my
software.&lt;/p&gt;
&lt;p&gt;So when you turn up and feel the need to tell me that some function keys
might not work in some terminal on some GNU/Linux box... I get it, you don't
like beans. If that's the case, how about you either don't make my hobby all
about &lt;em&gt;your&lt;/em&gt; tastes and how I should build my application to suit you, or
how about you RTFM and configure my application so it works in your choice
of terminal?&lt;/p&gt;
&lt;p&gt;I mean... we know you won't. We know you don't even care about the
application I'm having tons of fun building, that I'm spending time in a
joyous flow-state creating and tinkering with. You just care about making
the post all about you and your purity. We know you just care about showing
how smart you are.&lt;/p&gt;
&lt;p&gt;We know you just can't resist the urge to reply-guy&lt;sup id="fnref:391-3"&gt;&lt;a class="footnote-ref" href="#fn:391-3"&gt;3&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;We get it: you don't like bean soup. Nobody cares. Nobody asked.&lt;/p&gt;
&lt;div class="footnote"&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id="fn:391-1"&gt;
&lt;p&gt;That reminds me: one day I should write a rant about the folk who obsess about the &lt;em&gt;"Zen of Python"&lt;/em&gt;.&amp;#160;&lt;a class="footnote-backref" href="#fnref:391-1" title="Jump back to footnote 1 in the text"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:391-2"&gt;
&lt;p&gt;Let's be honest: it's &lt;em&gt;always&lt;/em&gt; a dude.&amp;#160;&lt;a class="footnote-backref" href="#fnref:391-2" title="Jump back to footnote 2 in the text"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:391-3"&gt;
&lt;p&gt;Let's be honest: it's &lt;em&gt;always&lt;/em&gt; a guy.&amp;#160;&lt;a class="footnote-backref" href="#fnref:391-3" title="Jump back to footnote 3 in the text"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description>
      <guid isPermaLink="false">https://blog.davep.org/2026/07/17/terminal-bean-soup.html</guid>
      <category>Tech</category>
      <category>Coding</category>
      <category>FOSS</category>
      <category>Free Software</category>
      <category>terminal</category>
      <category>textual</category>
      <pubDate>Fri, 17 Jul 2026 20:54:32 +0100</pubDate>
    </item>
    <item>
      <title>Solar halo</title>
      <link>https://blog.davep.org/2026/07/17/solar-halo.html</link>
      <description>&lt;p&gt;I forgot to post this yesterday. I was out on a lunch walk and noticed the
clouds in the sky were looking like the right kind for some &lt;a href="https://www.atoptics.org.uk/" rel="noopener noreferrer" target="_blank"&gt;atmospheric
optical&lt;/a&gt; fun. Sure enough, I looked up, and...&lt;/p&gt;
&lt;p&gt;&lt;img alt="22 degree halo" height="720" loading="lazy" src="https://blog.davep.org/attachments/2026/07/17/halo.webp#centre" width="1280" /&gt;&lt;/p&gt;
&lt;p&gt;A nice partial &lt;a href="https://www.atoptics.org.uk/halo/circular.htm" rel="noopener noreferrer" target="_blank"&gt;22&amp;deg;
halo&lt;/a&gt;. It's been a wee while
since I last saw one.&lt;/p&gt;</description>
      <guid isPermaLink="false">https://blog.davep.org/2026/07/17/solar-halo.html</guid>
      <category>Life</category>
      <category>atmospheric optics</category>
      <category>photography</category>
      <category>solar halo</category>
      <pubDate>Fri, 17 Jul 2026 18:07:52 +0100</pubDate>
    </item>
    <item>
      <title>Rogallo v0.9.0</title>
      <link>https://blog.davep.org/2026/07/16/rogallo-v0-9-0.html</link>
      <description>&lt;p&gt;I've released &lt;a href="https://rogallo.davep.dev/changelog/#v090" rel="noopener noreferrer" target="_blank"&gt;v0.9.0&lt;/a&gt; of
&lt;a href="https://rogallo.davep.dev/" rel="noopener noreferrer" target="_blank"&gt;Rogallo&lt;/a&gt;. The first big change in this release
is the addition of syntax highlighting to pre-formatted text.&lt;/p&gt;
&lt;p&gt;Much like in Markdown, Gemtext also supports pre-formatted text bounded by
code fences. Gemtext supports the concept of "alt-text" for such text, like
this:&lt;/p&gt;
&lt;div class="highlight" data-lang="gemtext"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;```python
def hello(name: str = &amp;quot;World&amp;quot;) -&amp;gt; str:
    return f&amp;quot;Hello, {name}!&amp;quot;
```
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Until now Rogallo would simply show the text as-is (with some styling to
make it stand out from normal paragraphs). From this release, if there is
alt-text for the pre-formatted block, and if it's the name of a supported
language, the content will have syntax highlighting applied.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Pre-text with syntax highlighting" height="1984" loading="lazy" src="https://blog.davep.org/attachments/2026/07/16/pre-highlight.webp#centre" width="1798" /&gt;&lt;/p&gt;
&lt;p&gt;If you're curious which languages are supported, it should be &lt;a href="https://pygments.org/languages/" rel="noopener noreferrer" target="_blank"&gt;anything that
Pygments supports&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Another significant change is to the user input dialog. As &lt;a href="https://blog.davep.org/2026/07/16/wasat-v0-7-0.html"&gt;mentioned in an
earlier post&lt;/a&gt;, the Gemini protocol imposes
limits on how much text can be submitted to a capsule. As documented, the
limit is for a resulting URI of 1024 bytes&lt;sup id="fnref:376-1"&gt;&lt;a class="footnote-ref" href="#fn:376-1"&gt;1&lt;/a&gt;&lt;/sup&gt;. To save someone typing out a
long entry, only to have it lost&lt;sup id="fnref:376-2"&gt;&lt;a class="footnote-ref" href="#fn:376-2"&gt;2&lt;/a&gt;&lt;/sup&gt;, I've added a count of how much input
is left available (calculated from the size of the URI that would result):&lt;/p&gt;
&lt;p&gt;&lt;img alt="The input count" height="1984" loading="lazy" src="https://blog.davep.org/attachments/2026/07/16/input-count.webp#centre" width="1894" /&gt;&lt;/p&gt;
&lt;p&gt;To help ensure that the user doesn't submit too much, I've also added an
error display if you go over the limit, which also refuses to submit the
input.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Too much input" height="1984" loading="lazy" src="https://blog.davep.org/attachments/2026/07/16/too-much.webp#centre" width="1894" /&gt;&lt;/p&gt;
&lt;p&gt;With these in place it should be a lot harder to run into an unexpected loss
of input.&lt;/p&gt;
&lt;p&gt;One final tweak is a small change to the optional link stripe system &lt;a href="https://blog.davep.org/2026/07/14/rogallo-v0-7-0.html"&gt;I
recently added&lt;/a&gt;. While playing around with
some other themes, I noticed that the styling didn't show up well, or at
all, in many of them. So I've changed it a little so it now shows in all
available themes. I'm still not convinced it's quite right -- I'll play some
more. But at least now it's visible in all cases.&lt;/p&gt;
&lt;div class="footnote"&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id="fn:376-1"&gt;
&lt;p&gt;Although I've already &lt;a href="gemini://station.martinrue.com/davep/d23d9c4731eb461bba2db4b20bb18a6e" rel="noopener noreferrer" target="_blank"&gt;encountered one capsule that limits to 1022,
from what I can
tell&lt;/a&gt;.&amp;#160;&lt;a class="footnote-backref" href="#fnref:376-1" title="Jump back to footnote 1 in the text"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:376-2"&gt;
&lt;p&gt;Right away I'm now thinking it &lt;em&gt;might&lt;/em&gt; be a good idea to re-populate
the input dialog in such a situation. I'll have to remember to make that
a TODO issue.&amp;#160;&lt;a class="footnote-backref" href="#fnref:376-2" title="Jump back to footnote 2 in the text"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description>
      <guid isPermaLink="false">https://blog.davep.org/2026/07/16/rogallo-v0-9-0.html</guid>
      <category>Coding</category>
      <category>Coding</category>
      <category>Gemini Protocol</category>
      <category>PyPI</category>
      <category>Python</category>
      <category>Rogallo</category>
      <category>gemtext</category>
      <category>smolweb</category>
      <category>textual</category>
      <pubDate>Thu, 16 Jul 2026 20:10:35 +0100</pubDate>
    </item>
    <item>
      <title>Wasat v0.7.0</title>
      <link>https://blog.davep.org/2026/07/16/wasat-v0-7-0.html</link>
      <description>&lt;p&gt;The &lt;a href="https://geminiprotocol.net/docs/protocol-specification.gmi" rel="noopener noreferrer" target="_blank"&gt;Gemini
Protocol&lt;/a&gt; makes
it clear that &lt;a href="https://geminiprotocol.net/docs/protocol-specification.gmi#requests" rel="noopener noreferrer" target="_blank"&gt;the maximum length of a URI, when making a request, is 1024
bytes&lt;/a&gt;.
This has implications for how large a user's input can be when responding to
a &lt;code&gt;1x&lt;/code&gt; response. Because of this, I'd like to update
&lt;a href="https://blog.davep.org/tag/rogallo/"&gt;Rogallo&lt;/a&gt; so that it lets the user know how much space they
have left as they type in their input.&lt;/p&gt;
&lt;p&gt;With this in mind I've released
&lt;a href="https://wasat.davep.dev/changelog/#v070" rel="noopener noreferrer" target="_blank"&gt;v0.7.0&lt;/a&gt; of
&lt;a href="https://wasat.davep.dev/" rel="noopener noreferrer" target="_blank"&gt;Wasat&lt;/a&gt;. This adds the following to &lt;code&gt;GeminiURI&lt;/code&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;GeminiURI.MAXIMUM_LENGTH&lt;/code&gt; -- a constant for the maximum length of a
  Gemini URI (as mentioned above: 1024).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;len()&lt;/code&gt; support -- if you ask for the &lt;code&gt;len&lt;/code&gt; of an instance of &lt;code&gt;GeminiURI&lt;/code&gt;
  it will return the length of the full URI.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GeminiURI.bytes_left&lt;/code&gt; is a property that tells you how many bytes are
  left until the limit, given the current URI.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GeminiURI.too_long&lt;/code&gt; is a boolean property that flags if the current URI
  is too long to send to a Gemini capsule.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This should give me all I need to add some guardrails to the user input
dialog in Rogallo.&lt;/p&gt;</description>
      <guid isPermaLink="false">https://blog.davep.org/2026/07/16/wasat-v0-7-0.html</guid>
      <category>Python</category>
      <category>Coding</category>
      <category>Gemini Protocol</category>
      <category>PyPI</category>
      <category>Python</category>
      <category>smolweb</category>
      <category>wasat</category>
      <pubDate>Thu, 16 Jul 2026 17:07:52 +0100</pubDate>
    </item>
    <item>
      <title>Gemtext v1.0.0</title>
      <link>https://blog.davep.org/2026/07/16/gemtext-v1-0-0.html</link>
      <description>&lt;p&gt;I've bumped &lt;a href="https://gemtext.davep.dev/" rel="noopener noreferrer" target="_blank"&gt;Gemtext&lt;/a&gt; to
&lt;a href="https://gemtext.davep.dev/changelog/#v100" rel="noopener noreferrer" target="_blank"&gt;v1.0.0&lt;/a&gt;. I've gone from "this is
test code" to "this is stable code" mostly because the library is so simple
and I'm unlikely to add any radically new features to it&lt;sup id="fnref:389-1"&gt;&lt;a class="footnote-ref" href="#fn:389-1"&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;This bump also has one small addition: I've added &lt;a href="https://gemtext.davep.dev/gemtext/#gemtext.PreFormatted.alt_text" rel="noopener noreferrer" target="_blank"&gt;an &lt;code&gt;alt_text&lt;/code&gt;
property&lt;/a&gt;
to &lt;a href="https://gemtext.davep.dev/gemtext/#gemtext.PreFormatted" rel="noopener noreferrer" target="_blank"&gt;the &lt;code&gt;PreFormatted&lt;/code&gt;
class&lt;/a&gt;. This exists
to capture and make available any text that comes after the pre-formatted
text marker. For example, this text:&lt;/p&gt;
&lt;div class="highlight" data-lang="gemtext"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;```python
print(&amp;quot;Hello, World!&amp;quot;)
```
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;will now result in:&lt;/p&gt;
&lt;div class="highlight" data-lang="python"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;PreFormatted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;print(&amp;quot;Hello, World!&amp;quot;)&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;alt_text&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;python&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If/when I &lt;a href="https://github.com/davep/rogallo/issues/151" rel="noopener noreferrer" target="_blank"&gt;add syntax highlighting of pre-formatted text blocks to
Rogallo&lt;/a&gt;, this new property
will make that possible.&lt;/p&gt;
&lt;div class="footnote"&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id="fn:389-1"&gt;
&lt;p&gt;I was thinking about adding a Gemtext builder class at some point,
but I can't see a use for it any time soon. Perhaps v2.0.0.&amp;#160;&lt;a class="footnote-backref" href="#fnref:389-1" title="Jump back to footnote 1 in the text"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description>
      <guid isPermaLink="false">https://blog.davep.org/2026/07/16/gemtext-v1-0-0.html</guid>
      <category>Python</category>
      <category>Coding</category>
      <category>Gemini Protocol</category>
      <category>PyPI</category>
      <category>Python</category>
      <category>gemtext</category>
      <category>smolweb</category>
      <pubDate>Thu, 16 Jul 2026 08:58:50 +0100</pubDate>
    </item>
    <item>
      <title>Rogallo v0.8.0</title>
      <link>https://blog.davep.org/2026/07/15/rogallo-v0-8-0.html</link>
      <description>&lt;p&gt;&lt;a href="https://rogallo.davep.dev/" rel="noopener noreferrer" target="_blank"&gt;Rogallo&lt;/a&gt;
&lt;a href="https://rogallo.davep.dev/changelog/#v080" rel="noopener noreferrer" target="_blank"&gt;v0.8.0&lt;/a&gt; is now available. This
release includes a small bug fix, a big change to how external links and
unhandled MIME types are dealt with, and a further improvement to link
navigation.&lt;/p&gt;
&lt;p&gt;First the big change: hand-off of unhandled content and trust. Until now, if
Rogallo was met with a URI it didn't know how to handle, or met with a MIME
type it isn't designed to deal with, it would simply hand it off to the
browser in your environment. This is generally handy as it means that, when
you're browsing &lt;a href="https://blog.davep.org/tag/gemtext/"&gt;gemtext&lt;/a&gt; content, if you meet a link that
takes you to a conventional website, the link will (normally) be opened in
your browser.&lt;/p&gt;
&lt;p&gt;There are, of course, any number of schemes that form part of a URI. While
Rogallo might commonly be handing off &lt;code&gt;http&lt;/code&gt; and &lt;code&gt;https&lt;/code&gt; URIs, there's no
reason why it can't be handing off a &lt;code&gt;finger&lt;/code&gt; or a &lt;code&gt;mailto&lt;/code&gt; or whatever. Or,
potentially, something a wee bit more dodgy like a &lt;code&gt;javascript&lt;/code&gt; URI. While
some web browsers don't allow that sort of thing by default (Safari, for
example, blocks it unless configured otherwise), others might, and this
&lt;em&gt;could&lt;/em&gt; result in a nasty surprise.&lt;/p&gt;
&lt;p&gt;So now Rogallo has a confirmation step that lets you allow a scheme this
once, this and every subsequent time, or just cancel out.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Confirm a scheme" height="1792" loading="lazy" src="https://blog.davep.org/attachments/2026/07/15/scheme-confirm.webp#centre" width="1798" /&gt;&lt;/p&gt;
&lt;p&gt;By default the trusted schemes (the ones you say "always" on) are saved in a
&lt;code&gt;trusted_schemes&lt;/code&gt; file in the data directory.&lt;/p&gt;
&lt;p&gt;Similar to the above: if, via a URI that Rogallo can handle, it meets a MIME
type it can't handle, it will also pass it off to your operating system.
I've added similar protection there too.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Confirm MIME type" height="1792" loading="lazy" src="https://blog.davep.org/attachments/2026/07/15/mime-type-confirm.webp#centre" width="1798" /&gt;&lt;/p&gt;
&lt;p&gt;In this case any MIME types marked as trusted are dropped into a
&lt;code&gt;trusted_mime_types&lt;/code&gt; file in the data directory.&lt;/p&gt;
&lt;div class="admonition admonition-note"&gt;
&lt;div class="admonition-title"&gt;ℹ️ Note&lt;/div&gt;
&lt;div class="admonition-content"&gt;
&lt;p&gt;If such a MIME type is allowed, it is &lt;em&gt;passed off to your operating system
to handle&lt;/em&gt;. If you'd like to tell Rogallo to try and internally handle a
MIME type, you can set that by configuring the &lt;a href="https://rogallo.davep.dev/configuration/#displayable-content-types" rel="noopener noreferrer" target="_blank"&gt;displayable content
types&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;I feel these changes help remove any possible footguns previously caused by
unquestionably handing off URIs to the wider environment.&lt;/p&gt;
&lt;p&gt;Another change I've made is to add even more link navigation. This sort of
follows on from &lt;a href="https://blog.davep.org/2026/07/14/rogallo-v0-7-0.html"&gt;yesterday's release&lt;/a&gt; where
I added labelled jumps to links. Again, the usual method of moving between
links is to use &lt;kbd&gt;Tab&lt;/kbd&gt; and &lt;kbd&gt;Shift&lt;/kbd&gt;+&lt;kbd&gt;Tab&lt;/kbd&gt;. The
problem with those keys is they navigate you through &lt;em&gt;all&lt;/em&gt; widgets in the UI
that can receive focus. So, if you keep tapping &lt;kbd&gt;Tab&lt;/kbd&gt;, you'll
navigate out of the viewer and into the next available widget, once you
reach the last link.&lt;/p&gt;
&lt;p&gt;With this release I've added some extra keys which can be used to constantly
cycle around the links while you're inside the viewer. These are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;kbd&gt;Left&lt;/kbd&gt;, &lt;kbd&gt;Shift&lt;/kbd&gt;+&lt;kbd&gt;Up&lt;/kbd&gt;, &lt;kbd&gt;L&lt;/kbd&gt; to go
  backwards through the links.&lt;/li&gt;
&lt;li&gt;&lt;kbd&gt;Right&lt;/kbd&gt;, &lt;kbd&gt;Shift&lt;/kbd&gt;+&lt;kbd&gt;Down&lt;/kbd&gt;, &lt;kbd&gt;l&lt;/kbd&gt; to go
  forwards through the links.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;While these might not be to everyone's taste (I'm already getting very used
to using &lt;kbd&gt;Left&lt;/kbd&gt; and &lt;kbd&gt;Right&lt;/kbd&gt;), they do add another set of
options for link navigation.&lt;/p&gt;
&lt;p&gt;The final change is a simple bug fix, where the command line history simply
wasn't being saved and loaded correctly. From now on it should save
correctly and allow navigation of the history using the cursor keys.&lt;/p&gt;
&lt;p&gt;With these changes in place, I feel I'm actually getting close to bumping up
to a v1.0.0 release. While there are still things I want to add (there are
currently a handful of TODO items in the issues), I see these as
nice-to-have items that I want to do later on, rather than as must-have
items that preclude considering Rogallo a viable daily-driver.&lt;/p&gt;
&lt;p&gt;I'll see how the next day or so goes.&lt;/p&gt;</description>
      <guid isPermaLink="false">https://blog.davep.org/2026/07/15/rogallo-v0-8-0.html</guid>
      <category>Coding</category>
      <category>Coding</category>
      <category>Gemini Protocol</category>
      <category>PyPI</category>
      <category>Python</category>
      <category>Rogallo</category>
      <category>gemtext</category>
      <category>smolweb</category>
      <category>textual</category>
      <pubDate>Wed, 15 Jul 2026 19:56:57 +0100</pubDate>
    </item>
    <item>
      <title>Rogallo v0.7.0</title>
      <link>https://blog.davep.org/2026/07/14/rogallo-v0-7-0.html</link>
      <description>&lt;p&gt;&lt;a href="https://rogallo.davep.dev/" rel="noopener noreferrer" target="_blank"&gt;Rogallo&lt;/a&gt;
&lt;a href="https://rogallo.davep.dev/changelog/#v070" rel="noopener noreferrer" target="_blank"&gt;v0.7.0&lt;/a&gt; is &lt;a href="https://pypi.org/project/rogallo/" rel="noopener noreferrer" target="_blank"&gt;now
available&lt;/a&gt;. The main changes in this
release revolve around the display and navigation of links.&lt;/p&gt;
&lt;p&gt;The aim of Rogallo, as a "TUI" application, is that it is usable purely with
the keyboard, and also very usable with the mouse too. So far I think I've
managed to hit that mark, but I felt that things weren't quite as smooth as
they could be when it came to navigating links.&lt;/p&gt;
&lt;p&gt;Links, like any other UI element in the application that can receive
"focus", can be navigated to using &lt;kbd&gt;Tab&lt;/kbd&gt; and
&lt;kbd&gt;Shift&lt;/kbd&gt;+&lt;kbd&gt;Tab&lt;/kbd&gt;. This is fine if there's just a handful of
links in a page, but more than that and having to repeatedly press tab gets
a bit boring. Meanwhile, if you have a mouse or other pointing device to
hand, it's easy to scroll and click. I wanted to try and have a similar
keyboard-based speedup available.&lt;/p&gt;
&lt;p&gt;So now, by default, all links on a page get a numeric label:&lt;/p&gt;
&lt;p&gt;&lt;img alt="Links with numeric labels" height="1984" loading="lazy" src="https://blog.davep.org/attachments/2026/07/14/links-with-labels.webp#centre" width="1894" /&gt;&lt;/p&gt;
&lt;p&gt;To jump to a link, while the viewer has focus, simply type the number. When
you do so, the corresponding link will be focused, then you just need to hit
&lt;kbd&gt;Enter&lt;/kbd&gt; to follow the link.&lt;/p&gt;
&lt;p&gt;The input system is written to "wrap around", as it were. So if you type
&lt;kbd&gt;1&lt;/kbd&gt; the link with a label of &lt;code&gt;1&lt;/code&gt; will be focused. If you then type
&lt;kbd&gt;2&lt;/kbd&gt;, and if there's a link with a label of &lt;code&gt;12&lt;/code&gt;, it will be
focused. If there are fewer than 12 links, the input chain resets, and &lt;code&gt;2&lt;/code&gt;
will be focused. The idea being: as you keep typing numbers, they
concatenate until there's no matching link and then it starts fresh.&lt;/p&gt;
&lt;p&gt;I was quite keen on having the labels over to the right, so they didn't
disturb the layout of the main body of text, but there's a small downside
with this: if you have a lot of links next to each other it's not always
obvious which link and which label go together. While getting close to your
desired link should be good enough (you can then still hit &lt;kbd&gt;Tab&lt;/kbd&gt; to
get to your chosen link), I felt something else could be done to give some
help. So I added an option to turn on alternating background stripes for
links.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Links with stripes" height="1984" loading="lazy" src="https://blog.davep.org/attachments/2026/07/14/links-with-stripes.webp#centre" width="1894" /&gt;&lt;/p&gt;
&lt;p&gt;If all of this seems a bit too cluttered, especially if you're the sort of
person who is mouse-first or mouse-heavy with the terminal, there's still
the option to turn off both the labels and the stripes and have Rogallo look
like it did before.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Links how they used to look" height="1984" loading="lazy" src="https://blog.davep.org/attachments/2026/07/14/links-like-before.webp#centre" width="1894" /&gt;&lt;/p&gt;
&lt;p&gt;I think this covers pretty much all the possible link navigation needs I can
imagine anyone having.&lt;/p&gt;
&lt;p&gt;As well as the above, other small changes in v0.7.0 include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Fixed a cosmetic issue with the truncation of the current location shown
  in the viewer panel, if the location is longer than the available space is
  wide.&lt;/li&gt;
&lt;li&gt;The suggestions provided in the command line now include hosts found in
  the "known hosts" trust store. So if you are trying to remember a location
  you visited long ago, and you never bookmarked it and it's fallen out of
  the location history, it's still there as a reminder/hint/completion.&lt;/li&gt;
&lt;li&gt;Also added the same to the history search palette.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I've also done more work on &lt;a href="https://rogallo.davep.dev/" rel="noopener noreferrer" target="_blank"&gt;the website&lt;/a&gt;. The
&lt;a href="https://rogallo.davep.dev/configuration/" rel="noopener noreferrer" target="_blank"&gt;configuration section&lt;/a&gt; now covers
pretty much everything you can modify that changes how Rogallo works. I
still want to add more to the site -- mostly concentrating on explaining
some key features -- but I felt that anyone using Rogallo right now would be
most interested in how they can tailor it to their own taste.&lt;/p&gt;</description>
      <guid isPermaLink="false">https://blog.davep.org/2026/07/14/rogallo-v0-7-0.html</guid>
      <category>Coding</category>
      <category>Coding</category>
      <category>Gemini Protocol</category>
      <category>PyPI</category>
      <category>Python</category>
      <category>Rogallo</category>
      <category>gemtext</category>
      <category>smolweb</category>
      <category>textual</category>
      <pubDate>Tue, 14 Jul 2026 18:45:28 +0100</pubDate>
    </item>
    <item>
      <title>Wasat v0.6.0</title>
      <link>https://blog.davep.org/2026/07/14/wasat-v0-6-0.html</link>
      <description>&lt;p&gt;&lt;a href="https://wasat.davep.dev/" rel="noopener noreferrer" target="_blank"&gt;Wasat&lt;/a&gt;
&lt;a href="https://wasat.davep.dev/changelog/#v060" rel="noopener noreferrer" target="_blank"&gt;v0.6.0&lt;/a&gt; is now available. This is
another quick update that fixes a small typing issue and also adds a handy
new method I've been meaning to add to
&lt;a href="https://wasat.davep.dev/library/uri/#wasat.uri.GeminiURI" rel="noopener noreferrer" target="_blank"&gt;&lt;code&gt;GeminiURI&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The typing issue is a simple enough one. The &lt;code&gt;__init__&lt;/code&gt; method for
&lt;code&gt;GeminiURI&lt;/code&gt; can take either a string or another &lt;code&gt;GeminiURI&lt;/code&gt; as its argument.
However, the type was actually specified as &lt;code&gt;str | Self&lt;/code&gt;. In
&lt;a href="https://rogallo.davep.dev/" rel="noopener noreferrer" target="_blank"&gt;Rogallo&lt;/a&gt;, I want to have a sub-class of
&lt;code&gt;GeminiURI&lt;/code&gt; for one particular purpose, which will be passed an instance of
&lt;code&gt;GeminiURI&lt;/code&gt;. Something like this:&lt;/p&gt;
&lt;div class="highlight" data-lang="python"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;KnownHost&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;GeminiURI&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;A known host.&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;From this, I want to be able to do:&lt;/p&gt;
&lt;div class="highlight" data-lang="python"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;KnownHost&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;host&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;known_hosts&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;where &lt;code&gt;known_hosts&lt;/code&gt; is typed as &lt;code&gt;list[GeminiURI]&lt;/code&gt;. At this point, the type
checker complains:&lt;/p&gt;
&lt;div class="highlight" data-lang="text"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;Argument 1 to &amp;quot;KnownHost&amp;quot; has incompatible type &amp;quot;GeminiURI&amp;quot;; expected &amp;quot;str | KnownHost&amp;quot;  [arg-type]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The error is correct, because the use of &lt;code&gt;Self&lt;/code&gt; is saying "this needs to be
an instance of my class". There's no reason why it needs to work this way,
so I've relaxed the type to &lt;code&gt;str | GeminiURI&lt;/code&gt;. In my example above,
&lt;code&gt;KnownHost&lt;/code&gt; is a subclass of &lt;code&gt;GeminiURI&lt;/code&gt;, so the type checker will be happy
again.&lt;/p&gt;
&lt;p&gt;The new method I've added is &lt;code&gt;GeminiURI.with_default_scheme&lt;/code&gt;. This is a
class method that acts as a more relaxed "constructor" for a &lt;code&gt;GeminiURI&lt;/code&gt;.
Again, in Rogallo, there are a few places where I'm taking some input,
assuming it's going to be a &lt;code&gt;gemini://&lt;/code&gt; URI, checking if it's missing the
scheme prefix, and then prefixing the string with &lt;code&gt;gemini://&lt;/code&gt; before
creating a &lt;code&gt;GeminiURI&lt;/code&gt;&lt;sup id="fnref:387-1"&gt;&lt;a class="footnote-ref" href="#fn:387-1"&gt;1&lt;/a&gt;&lt;/sup&gt;. This means that Rogallo contains a few instances
of this sort of code:&lt;/p&gt;
&lt;div class="highlight" data-lang="python"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="c1"&gt;# ...we should treat some text as a URI but it isn&amp;#39;t prefixed with &amp;quot;gemini://&amp;quot;&lt;/span&gt;
    &lt;span class="n"&gt;uri&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;GeminiURI&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;GEMINI_PREFIX&lt;/span&gt;&lt;span class="si"&gt;}{&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;It's a small difference, but from now on I'll be able to:&lt;/p&gt;
&lt;div class="highlight" data-lang="python"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;uri&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;GeminiURI&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;with_default_scheme&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This removes the need to check if there's a scheme already &lt;em&gt;and&lt;/em&gt; it saves me
having to import &lt;code&gt;GEMINI_PREFIX&lt;/code&gt;, etc.&lt;/p&gt;
&lt;div class="footnote"&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id="fn:387-1"&gt;
&lt;p&gt;&lt;code&gt;GeminiURI&lt;/code&gt; will deliberately raise an exception if the scheme isn't &lt;code&gt;gemini&lt;/code&gt;.&amp;#160;&lt;a class="footnote-backref" href="#fnref:387-1" title="Jump back to footnote 1 in the text"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description>
      <guid isPermaLink="false">https://blog.davep.org/2026/07/14/wasat-v0-6-0.html</guid>
      <category>Python</category>
      <category>Coding</category>
      <category>Gemini Protocol</category>
      <category>PyPI</category>
      <category>Python</category>
      <category>smolweb</category>
      <category>wasat</category>
      <pubDate>Tue, 14 Jul 2026 12:14:35 +0100</pubDate>
    </item>
    <item>
      <title>Wasat v0.5.0</title>
      <link>https://blog.davep.org/2026/07/13/wasat-v0-5-0.html</link>
      <description>&lt;p&gt;Another quick update to &lt;a href="https://wasat.davep.dev/" rel="noopener noreferrer" target="_blank"&gt;Wasat&lt;/a&gt;, my &lt;a href="https://blog.davep.org/tag/gemini-protocol/"&gt;Gemini
Protocol&lt;/a&gt; client library for
&lt;a href="https://blog.davep.org/category/python/"&gt;Python&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;With &lt;a href="https://wasat.davep.dev/changelog/#v050" rel="noopener noreferrer" target="_blank"&gt;v0.5.0&lt;/a&gt; I've added a method
for getting the list of currently-trusted hosts, and also added a public
property to the client class for getting access to the trust store object.&lt;/p&gt;
&lt;p&gt;Generally these shouldn't be required, shouldn't be something you'd normally
want to work with; I've added them because I thought it might be another
useful way of populating the suggested completions facility in the command
line inside &lt;a href="https://blog.davep.org/tag/rogallo/"&gt;Rogallo&lt;/a&gt;. The idea being: if you're trying to
remember the name of a capsule you've visited before, and it might have
fallen out of the location history, its trust status might still be recorded
so it can complete from there.&lt;/p&gt;</description>
      <guid isPermaLink="false">https://blog.davep.org/2026/07/13/wasat-v0-5-0.html</guid>
      <category>Python</category>
      <category>Coding</category>
      <category>Gemini Protocol</category>
      <category>PyPI</category>
      <category>Python</category>
      <category>smolweb</category>
      <category>wasat</category>
      <pubDate>Mon, 13 Jul 2026 19:31:36 +0100</pubDate>
    </item>
    <item>
      <title>Let down by Openreach (again)</title>
      <link>https://blog.davep.org/2026/07/13/let-down-by-openreach-again.html</link>
      <description>&lt;p&gt;I &lt;em&gt;knew&lt;/em&gt; &lt;a href="https://blog.davep.org/2026/06/13/full-fibre-might-be-back-on.html"&gt;it was too good to be
true&lt;/a&gt;. While a little bit of
me hoped it was going to happen this time, mostly I was expecting it to not
happen.&lt;/p&gt;
&lt;p&gt;It didn't happen.&lt;/p&gt;
&lt;p&gt;Today was the day when &lt;a href="https://blog.davep.org/tag/openreach/"&gt;Openreach&lt;/a&gt; were supposed to turn up
again and deliver me a full fibre connection. The engineer was booked to
turn up some time between 08:00 and 13:00 (as before). I was ready at 08:00.
I was ready &lt;em&gt;before&lt;/em&gt; 08:00 if I'm honest.&lt;/p&gt;
&lt;p&gt;By 12:00 there was no sign of them. Despite there being an hour left to go,
I'd written them off as a no-show again. I &lt;em&gt;was&lt;/em&gt; wrong this time though.
There was a knock on the door about 10 minutes later.&lt;/p&gt;
&lt;p&gt;The engineer introduced himself, said he needed to go for a walk around
first to get a feel for how and where the work needed to happen, and to
figure out where the fibre was to come from (I kind of feel like this would
be the sort of thing they'd know up front, but it's not my job and I trust
them to know it).&lt;/p&gt;
&lt;p&gt;Another 5 minutes and he's back... to tell me they can't do the job because
the pole the fibre needs to come from is too far away. O_o&lt;/p&gt;
&lt;p&gt;Now, I'm not going to get annoyed at this chap; presumably someone should
have done some sort of site survey beforehand. Presumably this was the sort
of thing that should have happened &lt;a href="https://blog.davep.org/2026/05/26/let-down-by-openreach-and-ee.html"&gt;before the previous attempt to deliver
the product&lt;/a&gt;?&lt;/p&gt;
&lt;p&gt;So now I'm still without fibre, but with part of the job done. He installed
the wee box that goes inside the house, and also the wee box that goes on
the outside of the house. Of course, he drilled a hole and hooked them both
up. So now I'm down an electrical socket, but have gained a box with a
little red light that tells me I don't have full fibre.&lt;/p&gt;
&lt;p&gt;He left assuring me that, having done this, it ensures that the actual
delivery of the cable is turned into a priority. I can't say I'm that
convinced, having sort of been here before. Some time later I got this text
message:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;We're sorry we couldn't get you connected today. The job is a bit more
complex than usual.&lt;/p&gt;
&lt;p&gt;We are going to get it sorted though and promise Full Fibre's worth the
wait. We'll be back in touch in the next few days.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Again, I'm not convinced, having sort of been here before.&lt;/p&gt;
&lt;p&gt;If I was a little more cynical and a little more prone to seeing a
conspiracy where there was just a cock-up, I'd almost be tempted to
entertain the idea that they turned up and fitted the box knowing full well
that there was no fibre to be hooked up. Doing half a job is starting the
job, after all. Presumably on some sheet somewhere that looks better than
failing to do the job a second time.&lt;/p&gt;
&lt;p&gt;I'm going to give them a couple of days to get back to me, as per the
message, and then I think it's time to chase up &lt;a href="https://blog.davep.org/tag/ee/"&gt;EE&lt;/a&gt; and ask why,
once again, they've failed to deliver me a product they promised me was
available.&lt;/p&gt;</description>
      <guid isPermaLink="false">https://blog.davep.org/2026/07/13/let-down-by-openreach-again.html</guid>
      <category>Life</category>
      <category>BT</category>
      <category>Broadband</category>
      <category>Business</category>
      <category>EE</category>
      <category>Openreach</category>
      <pubDate>Mon, 13 Jul 2026 15:40:59 +0100</pubDate>
    </item>
    <item>
      <title>Rogallo v0.6.0</title>
      <link>https://blog.davep.org/2026/07/12/rogallo-v0-6-0.html</link>
      <description>&lt;p&gt;I've just released &lt;a href="https://github.com/davep/rogallo" rel="noopener noreferrer" target="_blank"&gt;Rogallo&lt;/a&gt; v0.6.0, which
contains the last big feature that was missing to make it a viable
daily-driver &lt;a href="https://blog.davep.org/tag/gemini-protocol/"&gt;Gemini Protocol&lt;/a&gt; client. That feature?
Client certificates.&lt;/p&gt;
&lt;p&gt;From now on, if you visit a capsule that requests a client certificate,
rather than an error being shown, a dialog will pop up:&lt;/p&gt;
&lt;p&gt;&lt;img alt="Simple dialog" height="2208" loading="lazy" src="https://blog.davep.org/attachments/2026/07/12/simple-cert.webp#centre" width="2182" /&gt;&lt;/p&gt;
&lt;p&gt;When you select the &lt;code&gt;Create&lt;/code&gt; button, the certificate will be created and
then, from then on, when you visit the capsule, that client certificate will
be used.&lt;/p&gt;
&lt;p&gt;As you might have noticed, there are "advanced options" available too. Most
are just optional values that go into the certificate itself:&lt;/p&gt;
&lt;p&gt;&lt;img alt="The advanced options" height="2208" loading="lazy" src="https://blog.davep.org/attachments/2026/07/12/advanced-cert.webp#centre" width="2182" /&gt;&lt;/p&gt;
&lt;p&gt;The two advanced options that mostly affect how all of this works are the
scope and the transient option. The transient option means that the
certificate is only good for the lifetime of this run of Rogallo. If you
close Rogallo, the certificate will be discarded. In almost all cases,
you'll want to leave this turned off.&lt;/p&gt;
&lt;p&gt;The scope toggle affects the scoping of the certificate. As I've &lt;a href="https://blog.davep.org/2026/07/12/wasat-v0-4-0.html"&gt;been able
to understand&lt;/a&gt;, the strict reading of the
Gemini Protocol says that a certificate should be scoped to the host, port,
and &lt;em&gt;path&lt;/em&gt; where it was first requested and generated for. However, out in
the real world, it seems there are applications built for the protocol that
don't work well with that approach. With this in mind, I've built Rogallo to
always scope to just the domain and port, by default. If you want a
particular certificate to follow the strict letter of the specification,
turn the &lt;em&gt;"Scope to domain/port"&lt;/em&gt; option off.&lt;/p&gt;
&lt;p&gt;With all that in place, it should now be possible to use Rogallo with any
Gemini application that needs client-side authentication. For the last
couple of days, I've been using it to successfully play AstroBotany, for
example.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Logged in to AstroBotany" height="2208" loading="lazy" src="https://blog.davep.org/attachments/2026/07/12/logged-in.webp#centre" width="2182" /&gt;&lt;/p&gt;
&lt;p&gt;As I said: with this in place, I believe Rogallo has all of the basic
requirements of a Gemini protocol client covered. I'm not quite ready to
call it v1.0.0 just yet -- there's a fair bit of testing and tweaking I
still want to do, and I can see that, when it comes to certificates for
example, there's some extra error handling I need to throw in. Additionally,
the "advanced" version of the certificate create dialog is kind of tall for
many terminals; I think I might need to play with the layout a bit.&lt;/p&gt;
&lt;p&gt;Also, as I've mentioned a few times: I want to get proper documentation
written and hosted on a dedicated site.&lt;/p&gt;
&lt;p&gt;Back to this release: there's also a handful of other QoL changes and fixes.
These include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Any page that is opened from an in-page link is now always retrieved from
  the remote location, bypassing any cached copy. The idea being that, if
  someone is actively navigating documents, they will want the freshest
  version of the new page.&lt;/li&gt;
&lt;li&gt;Fixed the layout of list items. Before now, the text wasn't wrapping,
  while, at the same time, space was being made for the text as if it was
  being wrapped.&lt;/li&gt;
&lt;li&gt;The bookmark search palette is no longer available if there are no
  bookmarks to search (the idea being that not being available is less
  confusing than being available but empty).&lt;/li&gt;
&lt;li&gt;The connection timeout, read timeout, and maximum number of redirects can
  now be set in the configuration file.&lt;/li&gt;
&lt;li&gt;The title area of the viewer now has a key icon that appears if a page is
  using a client certificate.&lt;/li&gt;
&lt;li&gt;Pages that require a client-side certificate are never added to the cache
  (the idea being that such pages are more likely to have dynamic content,
  and so the freshest version should always be loaded).&lt;/li&gt;
&lt;li&gt;Reworked what is recorded in navigation and location history to ensure
  that what is saved is the landing URI, not the URI that was first visited.
  This solves the problem of what happens during redirections, and so also
  solves the issue of what happens with &lt;code&gt;10&lt;/code&gt;/&lt;code&gt;11&lt;/code&gt; response inputs (having
  the resulting query appear in history could result in duplicated
  "submissions" to whatever app was in use).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;With these enhancements and fixes in place, I'm going to &lt;a href="gemini://astrobotany.mozz.us/public/ccd9fe566703411fa6065a9935fb6832/m1" rel="noopener noreferrer" target="_blank"&gt;keep tending my
plant&lt;/a&gt;,
and &lt;a href="gemini://station.martinrue.com/davep" rel="noopener noreferrer" target="_blank"&gt;posting away on Station&lt;/a&gt;, as a
way of continuing to shake down the application. With that in mind, if
anyone knows of any other sites and apps I should be testing against out in
Geminispace, do let me know!&lt;/p&gt;</description>
      <guid isPermaLink="false">https://blog.davep.org/2026/07/12/rogallo-v0-6-0.html</guid>
      <category>Coding</category>
      <category>Coding</category>
      <category>Gemini Protocol</category>
      <category>PyPI</category>
      <category>Python</category>
      <category>Rogallo</category>
      <category>gemtext</category>
      <category>smolweb</category>
      <category>textual</category>
      <pubDate>Sun, 12 Jul 2026 12:01:17 +0100</pubDate>
    </item>
    <item>
      <title>Wasat v0.4.0</title>
      <link>https://blog.davep.org/2026/07/12/wasat-v0-4-0.html</link>
      <description>&lt;p&gt;By this point today I was hoping to have released a new version of
&lt;a href="https://blog.davep.org/tag/rogallo/"&gt;Rogallo&lt;/a&gt;, complete with client certificate support. It is
more or less all there and ready to go, but I ran into a small problem,
something which confused me.&lt;/p&gt;
&lt;p&gt;You see, according to &lt;a href="https://geminiprotocol.net/docs/protocol-specification.gmi" rel="noopener noreferrer" target="_blank"&gt;the documentation for the Gemini
Protocol&lt;/a&gt;, when
there's a request by a capsule for a client certificate, that certificate
should be scoped to the host, port &lt;em&gt;and path and all paths below it&lt;/em&gt;. So
that means that if &lt;code&gt;example.com/foo&lt;/code&gt; causes a certificate to be requested,
it's good for &lt;code&gt;example.com/foo&lt;/code&gt; and &lt;code&gt;example.com/foo/bar&lt;/code&gt;, but it isn't
valid for &lt;code&gt;example.com/other&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Makes sense.&lt;/p&gt;
&lt;p&gt;The problem I ran into pretty quickly, with my implementation of this in
Wasat and Rogallo, was this: I hit a site (a microblogging site of sorts)
that had a joining page at &lt;code&gt;example.com/join&lt;/code&gt;. Once you joined up and set
your user name, you'd normally land at &lt;code&gt;example.com/me&lt;/code&gt;. They're sibling
paths and so should &lt;em&gt;not&lt;/em&gt; use the same certificate. However, this was done
via redirection, so I did some work to "clone" a certificate when there's a
redirection.&lt;/p&gt;
&lt;p&gt;But then it got more complicated. The site also lets you follow other
people. This means that if you visit &lt;code&gt;example.com/other-user&lt;/code&gt; you should
also still have the client certificate in place so the capsule knows who you
are (because client certificates are also, in effect, session cookies, as I
understand it), so you can perform the follow. Again, this is a sibling
path, and there's no redirection, so the certificate is no good because, at
this point, it's scoped to &lt;code&gt;example.com/join&lt;/code&gt; and &lt;code&gt;example.com/me&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Meanwhile: testing this with &lt;a href="https://gmi.skyjake.fi/lagrange/" rel="noopener noreferrer" target="_blank"&gt;Lagrange&lt;/a&gt;,
it had no such problem whatsoever. How was it getting around this issue? Was
I doing something wrong? Was I misreading the specification for the
protocol? Was Lagrange being a bit more relaxed about its certificate scope?&lt;/p&gt;
&lt;p&gt;After doing some digging, it would seem that it's the latter. It looks like
it, and perhaps other clients, take a pragmatic approach to certificate
scopes and generally scope them to the host and port alone, ignoring the
path (in the case of Lagrange it seems to sort of actually divorce the
certificates from the URIs anyway, treating certificates more as identities
you can associate with any capsule, etc).&lt;/p&gt;
&lt;p&gt;Given this, at least for now, I'm going to take that approach. Any time a
certificate needs to be generated in Rogallo, I'm going to give the user the
option (on by default) to scope the certificate to the whole host/port
combination. Later on I might add the ability to fully manage certificates
(right now that can be done by editing the certificates file in the data
directory, but a proper UI for it would be nice).&lt;/p&gt;
&lt;p&gt;Which brings me to this release of Wasat.
&lt;a href="https://wasat.davep.dev/changelog/#v040" rel="noopener noreferrer" target="_blank"&gt;v0.4.0&lt;/a&gt; adds some extra
functionality to
&lt;a href="https://wasat.davep.dev/library/uri/#wasat.uri.GeminiURI" rel="noopener noreferrer" target="_blank"&gt;&lt;code&gt;GeminiURI&lt;/code&gt;&lt;/a&gt; that
allows changing and removing individual parts of the URI. There's a new
&lt;a href="https://wasat.davep.dev/library/uri/#wasat.uri.GeminiURI.replace" rel="noopener noreferrer" target="_blank"&gt;&lt;code&gt;replace&lt;/code&gt;
method&lt;/a&gt;
that can be used to create a clone of a URI with various parts changed.
Also, if you just want to change one specific part or simply prefer method
chaining approaches, I've also added more &lt;code&gt;with_&lt;/code&gt; methods similar to the
pre-existing &lt;a href="https://wasat.davep.dev/library/uri/#wasat.uri.GeminiURI.with_query" rel="noopener noreferrer" target="_blank"&gt;&lt;code&gt;with_query&lt;/code&gt;
method&lt;/a&gt;,
so now there's also
&lt;a href="https://wasat.davep.dev/library/uri/#wasat.uri.GeminiURI.with_host" rel="noopener noreferrer" target="_blank"&gt;&lt;code&gt;with_host&lt;/code&gt;&lt;/a&gt;,
&lt;a href="https://wasat.davep.dev/library/uri/#wasat.uri.GeminiURI.with_port" rel="noopener noreferrer" target="_blank"&gt;&lt;code&gt;with_port&lt;/code&gt;&lt;/a&gt;
and
&lt;a href="https://wasat.davep.dev/library/uri/#wasat.uri.GeminiURI.with_path" rel="noopener noreferrer" target="_blank"&gt;&lt;code&gt;with_path&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;With these in place I can go back to Rogallo and carry on with the last bits
of work I want to do on client certificate support, with Wasat making it
easy for me to clone up and chop and change URIs to suit the scoping
requirements.&lt;/p&gt;</description>
      <guid isPermaLink="false">https://blog.davep.org/2026/07/12/wasat-v0-4-0.html</guid>
      <category>Python</category>
      <category>Coding</category>
      <category>Gemini Protocol</category>
      <category>PyPI</category>
      <category>Python</category>
      <category>smolweb</category>
      <category>wasat</category>
      <pubDate>Sun, 12 Jul 2026 10:12:59 +0100</pubDate>
    </item>
    <item>
      <title>Wasat v0.3.0</title>
      <link>https://blog.davep.org/2026/07/11/wasat-v0-3-0.html</link>
      <description>&lt;p&gt;&lt;a href="https://wasat.davep.dev/" rel="noopener noreferrer" target="_blank"&gt;Wasat&lt;/a&gt;
&lt;a href="https://wasat.davep.dev/changelog/#v030" rel="noopener noreferrer" target="_blank"&gt;v0.3.0&lt;/a&gt; is now available. This is
a pretty small update, but one that's going to be useful in the next release
of &lt;a href="https://blog.davep.org/tag/rogallo/"&gt;Rogallo&lt;/a&gt;. I've now got client certificate support up and
going in the application, and I thought it might be useful to show the user
if a given page is using a client certificate or not (and, perhaps, at some
point, make the details of the certificate available as part of some page
information dialog).&lt;/p&gt;
&lt;p&gt;With this in mind, I've added &lt;code&gt;client_cert_path&lt;/code&gt; and &lt;code&gt;client_cert_used&lt;/code&gt;
properties to the &lt;code&gt;Response&lt;/code&gt; class. The former is the path to the
certificate used (if one was used), the latter is a simple boolean flag to
say if a certificate was used at all.&lt;/p&gt;
&lt;p&gt;Of course, &lt;code&gt;client_cert_path&lt;/code&gt; could be used for both purposes as it'll be
&lt;code&gt;None&lt;/code&gt; if one isn't used, but &lt;code&gt;client_cert_used&lt;/code&gt; will read better in code if
that's all that's needed.&lt;/p&gt;</description>
      <guid isPermaLink="false">https://blog.davep.org/2026/07/11/wasat-v0-3-0.html</guid>
      <category>Python</category>
      <category>Coding</category>
      <category>Gemini Protocol</category>
      <category>PyPI</category>
      <category>Python</category>
      <category>smolweb</category>
      <category>wasat</category>
      <pubDate>Sat, 11 Jul 2026 14:40:00 +0100</pubDate>
    </item>
    <item>
      <title>Wasat v0.2.0</title>
      <link>https://blog.davep.org/2026/07/10/wasat-v0-2-0.html</link>
      <description>&lt;p&gt;I've made a quick update to &lt;a href="https://wasat.davep.dev/" rel="noopener noreferrer" target="_blank"&gt;Wasat&lt;/a&gt;, my async
&lt;a href="https://blog.davep.org/tag/gemini-protocol/"&gt;Gemini Protocol&lt;/a&gt; client library for
&lt;a href="https://blog.davep.org/category/python/"&gt;Python&lt;/a&gt;. Now that I'm at a point where I want to add
client certificates to &lt;a href="https://blog.davep.org/tag/rogallo/"&gt;Rogallo&lt;/a&gt;, I'm essentially shaking
down the support for this in Wasat.&lt;/p&gt;
&lt;p&gt;One thing I wanted right away was a certificate that, in effect, never
expires. So with this release of Wasat I've added an option where the days
to expire can be set to &lt;code&gt;None&lt;/code&gt;, which results in the expiration date being
set to 9999-12-31.&lt;/p&gt;</description>
      <guid isPermaLink="false">https://blog.davep.org/2026/07/10/wasat-v0-2-0.html</guid>
      <category>Python</category>
      <category>Coding</category>
      <category>Gemini Protocol</category>
      <category>PyPI</category>
      <category>Python</category>
      <category>smolweb</category>
      <category>wasat</category>
      <pubDate>Fri, 10 Jul 2026 11:37:37 +0100</pubDate>
    </item>
    <item>
      <title>Rogallo v0.5.0</title>
      <link>https://blog.davep.org/2026/07/10/rogallo-v0-5-0.html</link>
      <description>&lt;p&gt;As mentioned in &lt;a href="https://blog.davep.org/2026/06/28/rogallo-v0-4-0.html"&gt;the last release&lt;/a&gt;, I've
been afk for a week and a bit, enjoying some downtime over in the
Netherlands. Although... it wasn't &lt;em&gt;exactly&lt;/em&gt; all afk. I did &lt;a href="https://blog.davep.org/2026/03/28/hello-macbook-air-again.html"&gt;take a keyboard
with me&lt;/a&gt; and, while time
permitted, I did tinker on &lt;a href="https://github.com/davep/rogallo" rel="noopener noreferrer" target="_blank"&gt;Rogallo&lt;/a&gt;.
That's resulted in quite a few TODO items being ticked off, and quite a few
changes and improvements being made.&lt;/p&gt;
&lt;h2 id="visible-mime-type"&gt;Visible MIME type&lt;/h2&gt;
&lt;p&gt;It's a small tweak, but I found it useful. The status bar of the main viewer
panel now shows the MIME type of the document currently being viewed.
Normally it will be showing &lt;code&gt;text/gemini&lt;/code&gt;:&lt;/p&gt;
&lt;p&gt;&lt;img alt="text/gemini" height="170" loading="lazy" src="https://blog.davep.org/attachments/2026/07/10/text-gemini.webp#centre" width="348" /&gt;&lt;/p&gt;
&lt;p&gt;but Rogallo can show some other &lt;code&gt;text/&lt;/code&gt; types too, so this will also make it
obvious what you're looking at:&lt;/p&gt;
&lt;p&gt;&lt;img alt="text/plain" height="190" loading="lazy" src="https://blog.davep.org/attachments/2026/07/10/text-plain.webp#centre" width="352" /&gt;&lt;/p&gt;
&lt;p&gt;You might also notice that, depending on the theme being used, the "correct"
MIME type gets a "this is fine" colour whereas anything else is in a more
"neutral" colour.&lt;/p&gt;
&lt;h2 id="better-handling-of-textplain-and-friends"&gt;Better handling of &lt;code&gt;text/plain&lt;/code&gt; and friends&lt;/h2&gt;
&lt;p&gt;Now, if a document comes in that isn't &lt;code&gt;text/gemini&lt;/code&gt;, there is no attempt to
parse and render it as Gemtext; it's just shown as a simple block of plain
text.&lt;/p&gt;
&lt;h2 id="mime-type-handling-of-local-files"&gt;MIME type handling of local files&lt;/h2&gt;
&lt;p&gt;Given the above changes, Rogallo now makes an effort to guess the MIME type
of any local file you view. This should help ensure that only Gemtext files
get parsed and rendered as such.&lt;/p&gt;
&lt;h2 id="os-hand-off-for-other-mime-types"&gt;OS hand-off for other MIME types&lt;/h2&gt;
&lt;p&gt;Where possible, when confronted with a MIME type that Rogallo can't handle,
it will attempt to hand it off to your environment's main web browser. While
not ideal, I have no wish to turn Rogallo into a terminal-based general
content browser/viewer; this is all about Gemini and Gemtext.&lt;/p&gt;
&lt;h2 id="history-enhancements"&gt;History enhancements&lt;/h2&gt;
&lt;p&gt;The history list has been updated to allow the removal of individual items,
and also clearing down the whole history.&lt;/p&gt;
&lt;h2 id="added-home-page-support"&gt;Added home page support&lt;/h2&gt;
&lt;p&gt;It's now possible to set a home page with either a &lt;code&gt;SetHome&lt;/code&gt; (which prompts
for a URI) or a &lt;code&gt;SetHomeToCurrentLocation&lt;/code&gt; (it does what it says) command.
There is also a &lt;code&gt;GoHome&lt;/code&gt; command that takes you to the home page you've set.
The default bindings for all of these can be found by either running
&lt;code&gt;rogallo bindings&lt;/code&gt;, or by viewing the help screen; pulling up the command
palette is also an option.&lt;/p&gt;
&lt;h2 id="added-support-for-bookmarks"&gt;Added support for bookmarks&lt;/h2&gt;
&lt;p&gt;Bookmarks are now supported. The &lt;code&gt;ToggleBookmarks&lt;/code&gt; will show/hide the
bookmarks list. &lt;code&gt;AddLocationToBookmarks&lt;/code&gt; will add the current location to
the bookmarks. &lt;code&gt;SearchBookmarks&lt;/code&gt; lets you search the bookmarks.&lt;/p&gt;
&lt;h2 id="more-command-line-suggestions"&gt;More command line suggestions&lt;/h2&gt;
&lt;p&gt;The completion suggestion facility in the application's command line (where
you enter URIs or commands) has been enhanced to include suggestions from
the navigation history, the location visit history and the bookmarks. This
should make it a little easier to enter a URI you're trying to remember.&lt;/p&gt;
&lt;h2 id="added-a-history-search"&gt;Added a history search&lt;/h2&gt;
&lt;p&gt;Having added the &lt;code&gt;SearchBookmarks&lt;/code&gt; command, it made sense to also add a
&lt;code&gt;SearchHistory&lt;/code&gt; command too. So with that you can quickly search all the
locations you've visited (within the limits of the history) and head back to
one.&lt;/p&gt;
&lt;h2 id="optimised-gemtext-rendering"&gt;Optimised Gemtext rendering&lt;/h2&gt;
&lt;p&gt;While not something that should generally be obvious to the user, the
Gemtext rendering engine has been optimised a little to reduce the number of
&lt;a href="https://blog.davep.org/tag/textual/"&gt;Textual&lt;/a&gt; widgets used to display a document by consolidating
all adjacent plain paragraphs.&lt;/p&gt;
&lt;h2 id="cleaned-up-quoted-paragraphs"&gt;Cleaned up quoted paragraphs&lt;/h2&gt;
&lt;p&gt;I've cleaned up an issue with adjacent quoted paragraphs. Until now there
was an empty line between each quote; this spoiled the layout.&lt;/p&gt;
&lt;h2 id="view-source-and-ansi-escape-sequences"&gt;View source and ANSI escape sequences&lt;/h2&gt;
&lt;p&gt;Some Gemini sites use ANSI escape sequences to add colour to pages. While
this isn't, as far as I can tell, part of the standard for Gemtext, it's a
simple thing to support and so Rogallo has supported rendering this for a
while; if a page has colours, they'll be used.&lt;/p&gt;
&lt;p&gt;This meant that if you asked to view the source of a page, you'd also see
that rendered in colour. I felt that wasn't in the spirit of viewing the
source.&lt;/p&gt;
&lt;p&gt;So now, if viewing a page like this:&lt;/p&gt;
&lt;p&gt;&lt;img alt="My glower" height="1664" loading="lazy" src="https://blog.davep.org/attachments/2026/07/10/colour-garden.webp#centre" width="1656" /&gt;&lt;/p&gt;
&lt;p&gt;When you go to view the source, instead of all of the colours still being
rendered, you now get to see which ANSI escape codes were used where:&lt;/p&gt;
&lt;p&gt;&lt;img alt="ANSI source" height="1664" loading="lazy" src="https://blog.davep.org/attachments/2026/07/10/colour-garden-source.webp#centre" width="1656" /&gt;&lt;/p&gt;
&lt;h2 id="viewer-auto-focus"&gt;Viewer auto-focus&lt;/h2&gt;
&lt;p&gt;One small change is that, any time a document is loaded (from bookmarks,
history, the command line, etc), the viewer now gains focus. Something I
kept forgetting to do and finally I got fed up with having to tab over to
the viewer each time.&lt;/p&gt;
&lt;h2 id="content-cache"&gt;Content cache&lt;/h2&gt;
&lt;p&gt;Rogallo now has a content cache for pages loaded from capsules (the aim is
to never bother caching content loaded from the filesystem). Any page that
is loaded with a success status code (&lt;code&gt;20&lt;/code&gt;) gets cached, and when you go
back to it, if it's within the TTL of the cache entry (by default set to one
hour), the content of the page will be loaded from the cache rather than
making a fresh request.&lt;/p&gt;
&lt;p&gt;Using the &lt;code&gt;Reload&lt;/code&gt; command &lt;em&gt;always&lt;/em&gt; bypasses the cache.&lt;/p&gt;
&lt;p&gt;There is also a &lt;code&gt;ClearCache&lt;/code&gt; command which will delete all cached data.&lt;/p&gt;
&lt;p&gt;The TTL of the cache can be changed in the configuration file by updating
the value for &lt;code&gt;cache_ttl&lt;/code&gt;. Also, if you don't wish to ever use a cache, you
can set &lt;code&gt;with_cache&lt;/code&gt; to &lt;code&gt;false&lt;/code&gt; to disable it.&lt;/p&gt;
&lt;h2 id="whats-next"&gt;What's next&lt;/h2&gt;
&lt;p&gt;With all of the above, I feel this gets Rogallo close to being v1.0.0-ready.
Not quite, but very close. The main addition that still needs to be tackled
is &lt;a href="https://github.com/davep/rogallo/issues/11" rel="noopener noreferrer" target="_blank"&gt;client-side certificates&lt;/a&gt;. I
don't anticipate this being too tricky, it's just more a case of needing to
play around with the code I've got so far, and needing to think about how to
implement it in a TUI-friendly way (if, indeed, there are any considerations
there at all).&lt;/p&gt;
&lt;p&gt;For now though, as long as you don't need a client-side certificate, there's
plenty to play with and try out.&lt;/p&gt;</description>
      <guid isPermaLink="false">https://blog.davep.org/2026/07/10/rogallo-v0-5-0.html</guid>
      <category>Coding</category>
      <category>Coding</category>
      <category>Gemini Protocol</category>
      <category>PyPI</category>
      <category>Python</category>
      <category>Rogallo</category>
      <category>gemtext</category>
      <category>smolweb</category>
      <category>textual</category>
      <pubDate>Fri, 10 Jul 2026 10:16:36 +0100</pubDate>
    </item>
    <item>
      <title>A view of Whitby</title>
      <link>https://blog.davep.org/2026/07/09/a-view-of-whitby.html</link>
      <description>&lt;p&gt;I'm back home, back in Scotland, after a touch over a week in the
Netherlands. It's been a great week. Much like &lt;a href="https://blog.davep.org/2026/06/29/a-view-of-the-wash.html"&gt;on the flight
out&lt;/a&gt;, from the aircraft, I managed to
get a view of a part of the UK I like. This time it was
&lt;a href="https://blog.davep.org/tag/whitby/"&gt;Whitby&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Whitby" height="3024" loading="lazy" src="https://blog.davep.org/attachments/2026/07/09/whitby.webp#centre" width="4032" /&gt;&lt;/p&gt;
&lt;p&gt;While likely not immediately obvious, it is there. It was a lot more obvious
with the naked eye. Zooming in a bit...&lt;/p&gt;
&lt;p&gt;&lt;img alt="Whitby detail" height="377" loading="lazy" src="https://blog.davep.org/attachments/2026/07/09/whitby-detail.webp#centre" width="621" /&gt;&lt;/p&gt;
&lt;p&gt;The track confirms that we were in a good position for such a view:&lt;/p&gt;
&lt;p&gt;&lt;img alt="Track of our flight" height="686" loading="lazy" src="https://blog.davep.org/attachments/2026/07/09/track.webp#centre" width="859" /&gt;&lt;/p&gt;
&lt;p&gt;While I didn't grab a photo (I wasn't in a window seat this time so it
wasn't so easy to keep track of where we were), I also managed to see
Scarborough -- a place where I spent &lt;em&gt;many&lt;/em&gt; summer holidays as a child in
the 1970s.&lt;/p&gt;
&lt;p&gt;Sadly I did miss a view of Newcastle, as when we got close to there, we took
a left-hand turn and all I could see out of our windows was sky.&lt;/p&gt;
&lt;p&gt;Perhaps next time...&lt;/p&gt;</description>
      <guid isPermaLink="false">https://blog.davep.org/2026/07/09/a-view-of-whitby.html</guid>
      <category>Life</category>
      <category>Whitby</category>
      <category>Yorkshire</category>
      <category>flying</category>
      <category>life</category>
      <category>photography</category>
      <category>travel</category>
      <pubDate>Thu, 09 Jul 2026 09:34:23 +0100</pubDate>
    </item>
    <item>
      <title>textual-enhanced v1.6.0</title>
      <link>https://blog.davep.org/2026/07/06/textual-enhanced-v1-6-0.html</link>
      <description>&lt;p&gt;I've just made a small update to
&lt;a href="https://textual-enhanced.davep.dev/" rel="noopener noreferrer" target="_blank"&gt;&lt;code&gt;textual-enhanced&lt;/code&gt;&lt;/a&gt;, my core library
used for most of my &lt;a href="https://blog.davep.org/tag/textual/"&gt;Textual&lt;/a&gt;-based applications. In v1.6.0
I've extended the "constructor" for
&lt;a href="https://textual-enhanced.davep.dev/library-contents/dialogs/#textual_enhanced.dialogs.ModalInput" rel="noopener noreferrer" target="_blank"&gt;&lt;code&gt;ModalInput&lt;/code&gt;&lt;/a&gt;
to allow passing in optional values for &lt;code&gt;password&lt;/code&gt;, &lt;code&gt;suggester&lt;/code&gt;, &lt;code&gt;title&lt;/code&gt; and
&lt;code&gt;sub_title&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Most of the time I just want to quickly call on &lt;code&gt;ModalInput&lt;/code&gt; to get input
from the user. If I need anything more fancy, I roll my own dialog. But in
some work I'm doing on &lt;a href="https://blog.davep.org/tag/rogallo/"&gt;Rogallo&lt;/a&gt;, it would be helpful for me
to at least set the &lt;code&gt;suggester&lt;/code&gt;. So, without adding &lt;em&gt;every&lt;/em&gt; optional
parameter for the Textual &lt;code&gt;Input&lt;/code&gt; widget, I've extended what can be passed
in to what I think will be a useful subset for my applications.&lt;/p&gt;</description>
      <guid isPermaLink="false">https://blog.davep.org/2026/07/06/textual-enhanced-v1-6-0.html</guid>
      <category>Python</category>
      <category>Coding</category>
      <category>Python</category>
      <category>textual</category>
      <category>textual-enhanced</category>
      <pubDate>Mon, 06 Jul 2026 10:31:10 +0200</pubDate>
    </item>
    <item>
      <title>BagOfStuff v1.2.0</title>
      <link>https://blog.davep.org/2026/07/03/bagofstuff-v1-2-0.html</link>
      <description>&lt;p&gt;Quick bump to &lt;a href="https://bagofstuff.davep.dev/" rel="noopener noreferrer" target="_blank"&gt;BagOfStuff&lt;/a&gt;. v1.2.0 adds
something I totally forgot &lt;a href="https://blog.davep.org/2026/07/02/bagofstuff-v1-1-0.html"&gt;yesterday&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;While adding the &lt;code&gt;del&lt;/code&gt; method to the history classes, to make it easier for
me to manipulate them as if they had the interface of a Python list, I
totally forgot to add a &lt;code&gt;clear&lt;/code&gt; method. &lt;a href="https://blog.davep.org/tag/rogallo/"&gt;Rogallo&lt;/a&gt; will need
to be able to 100% clear history, as well as remove individual entries in
the history, so that's kind of needed too.&lt;/p&gt;
&lt;p&gt;It's there now.&lt;/p&gt;</description>
      <guid isPermaLink="false">https://blog.davep.org/2026/07/03/bagofstuff-v1-2-0.html</guid>
      <category>Python</category>
      <category>BagOfStuff</category>
      <category>Coding</category>
      <category>Python</category>
      <pubDate>Fri, 03 Jul 2026 11:27:07 +0200</pubDate>
    </item>
  </channel>
</rss>
