Recent Posts

BagOfStuff v2.0.0

1 min read; 9 GFI

I've just made a small update to BagOfStuff, my little support library for my personal Python-based FOSS projects. This release makes some more changes to the history classes, adding an add_or_replace method, and also making some improvements to the type hinting by basing the classes on MutableSequence rather than Sequence.

While the history classes were originally intended to feel immutable, it's obvious that they're really not. The idea was that stuff gets added to them, stuff falls off the other end, and stuff might disappear depending on the context and when stuff gets added. The general idea was that direct manipulation was something that wouldn't happen. So I'd started out with them inheriting from Sequence, and so implying they were a read-only interface.

Given this acknowledgement, they now inherit from MutableSequence. This means that some extra (dunder) methods are added, and it also means that some extra exceptions can be raised. For example: setting slices to iterables isn't supported and will raise a NotImplementedError. Some other slice-based operations aren't supported either.

While this is close to a breaking change, it's fine for my use of this code. However, I had to make one big breaking change: I'd written clear so that it returned Self1. The interface expected by MutableSequence is one that returns None. So to strictly comply with that interface, I've changed the return type.

With this being a breaking change, I've bumped the library version to v2.0.0. While it's really a small change, and only one I'd notice, there's no getting away from the fact that the API has changed. That deserves a major version bump.


  1. I tend to prefer that a method that might return None actually return Self; it allows for chaining. I recognise that there are other schools of thought about this in the Python world; I'm not a member of those schools. 

Rogallo v1.11.0

2 min read; 10 GFI

A quick little update to Rogallo, bumping to v1.11.0. This release is mainly in support of people who like to use the mouse as much as, if not more than, the keyboard; and also in support of people who might wish to reclaim a couple of lines of display for actual content.

The main change in this release is that I've swapped out the header line that Rogallo used to have (which used the stock Textual Header widget) and replaced it with a mouse-friendly toolbar.

The new Rogallo toolbar

The thinking behind this was twofold: first, the current header wasn't really very useful, showing just the name of the application and the version number. I would hope, really, that most people know what application it is they're running, so having the name there wasn't super useful. Secondly, while Rogallo aims to be keyboard-friendly -- ideally keyboard-first -- it also aims to be mouse-friendly where possible. The problem with the mouse-friendly approach is that a lot of application commands were, for the mouse user, locked behind the command palette. While not impossible to navigate and use, it wasn't the smoothest experience.

So I've swapped that header out for a configurable toolbar of command buttons. The content of the toolbar is set using the toolbar_contents setting in the configuration file. The default set looks like this:

[
    ["GoHome", "\u2302"],
    ["Reload", "\u21bb"],
    ["Backward", "\u25c0\u25c0"],
    ["Forward", "\u25b6\u25b6"],
    ["GoToParent", "\u2191"],
    ["GoToRoot", "\u21c8"],
    ["SearchHistory", "\u25f7"],
    ["SearchBookmarks", "\u2605"],
    ["ToggleView", "\u21cb"]
]

The value in the first position for each button is the name of a bindable command. The second value is the text to place on the button itself. If you simply want to use the command's name, rather than a pair of values, you can just use the command name. So suppose you wanted to use Reload, Backward and Forward as-is, you could set things like this:

[
    ["GoHome", "\u2302"],
    "Reload",
    "Backward",
    "Forward",
    ["GoToParent", "\u2191"],
    ["GoToRoot", "\u21c8"],
    ["SearchHistory", "\u25f7"],
    ["SearchBookmarks", "\u2605"],
    ["ToggleView", "\u21cb"]
]

In addition to this setting, I've also added some other toolbar-related settings. There is:

"toolbar_visible": true

which controls if the toolbar is visible at all. So if you're a keyboard-only kind of user and you want that extra line back, just set that to false.

There is also:

"toolbar_tooltips": true,

which controls the tooltips that will appear when you hover over a button in the toolbar. These are there to explain what each button does, and to also show you what keyboard binding is associated with each one. If the tooltips get irritating, set this to false so they don't appear.

Lastly, there is:

"toolbar_can_get_focus": false

As I've said: the toolbar is added in support of people who use the mouse a fair bit. This means that, by default, it can't be interacted with using the keyboard. This makes sense in that each of the commands will have a keyboard binding, so it makes more sense to simply use that. However, if you really must use the toolbar with the keyboard, you can set this setting to true to enable it. When set this way, you can navigate into the toolbar and switch focus to each of those buttons using the normal Tab and Shift+Tab navigation keys.

One other little configuration feature can also be used to reclaim an extra line in the display. If you have no need for the footer of the application (where some important keys are shown), you can turn it off with:

"footer_visible": true

Set it to false and you get one more line of content.

Rogallo v1.10.0

1 min read; 10 GFI

Rogallo v1.10.0 has been released. This is a pretty small release, with a bug fix to navigation, and an improvement to how navigable Markdown documents are if viewed in the application.

In Rogallo v1.8.0 I made some changes to how Markdown documents are shown, if they're encountered and detected in Geminispace (or any of the other protocol spaces that might let you know the content type of a document). Whereas originally the document was shown in its raw form (marked up with syntax highlighting), v1.8.0 moved to using a fully-rendered form thanks to the internal Markdown widget.

But, as I've mentioned elsewhere in this blog, I wasn't 100% happy with this. The main problem is that the Markdown widget supplied by Textual is pretty unfriendly to keyboard navigation, and I want as much of Rogallo to be navigable with the keyboard as is possible.

To solve this I've created md2gemtext and started using it here in Rogallo. This means that, by default, from now on, any time a Markdown document is received by Rogallo, the content is converted into Gemtext before being displayed. The big advantage here is that links are far easier to see and follow and the document as a whole looks more in keeping with most other pages you'll visit.

Markdown rendered as a Gemtext document

I'm sensitive to the fact that some folk might prefer the previous method of viewing Markdown, so this feature is configurable. If you'd prefer the widget-based rendering instead, set this value:

"convert_markdown_to_gemtext": true

to false.

Markdown rendered in a full Markdown widget

The other change in this release is a fix to how navigation history is saved and restored. For a couple or so weeks now, on occasion, I was finding that when I ran up Rogallo again, navigated from the restored page, and then used Backward, I would end up somewhere else. It was intermittent and, for a while, hard to pin down. Mostly I'd notice this while rapidly closing and opening Rogallo while working on some other feature. Eventually I figured out the sequence of events causing the problem and it was an easy enough fix.

Recently I found - 6

1 min read; 10 GFI

Introduction

An occasional collection of things I've recently found on the Internet and added to my bookmarks.

The Nex Protocol standard

The specification for the Nex protocol, another "small web" protocol. Having discovered this, I added support for it to Rogallo.

The App Store Rejection of the Week That Was, in Fact, a Correct Rejection

It's got everything: claims of unfair treatment, claims of unfair portrayal of an application, claims of copying by AI, tarot nonsense, astrology nonsense, the works. Well worth a read.

Stowaway

See what's above you, in the sky, and hop on board and see how the world looks to them.

GEBible

The author does seem to fully admit that the whole thing is vibe-coded, but... it is a pretty handy resource for cross-checking various Bible translations. Useful for those times you want to find some vile nonsense, or cross-reference issues.

On AI Coding and Its Discontents

I'm still trying to decide if this is a totally made-up story or not. The whole thing about "there was a bug in production so I was told I might get fired" sounds so damn toxic... On the other hand, even if it's 100% fake, I get the concern that is likely being spun here.

Do not talk to me about AI

A PDF with the design of cards you can give out, asking people not to talk to you about AI.

md2gemtext - A library for converting Markdown to Gemtext

1 min read; 10 GFI

Following on from html2gemtext, the inevitable has happened: I couldn't let the Markdown side of things remain unaddressed. While Rogallo v1.8.0 added some extra rendering of Markdown to make it look more "pretty", I felt it really needed to be handled so it had more utility. Being fully navigable, even by keyboard, seems more important than pretty tables.

So md2gemtext now exists as a library on PyPI. I have two plans for this. While I fully intend to shake up the Markdown support in Rogallo -- either replacing the use of the Textual Markdown widget to display it, or at least giving the user a configuration option to decide how Markdown is displayed -- I also want to pay some attention to my (currently rather simple) Gemini-based log and use this library to build a tool that will convert my blog's Markdown content into Gemtext that looks just how I want it.

As with html2gemtext, this is an early version of this library, and I'm sure there will be edge cases I'll have missed and will want to tidy up. But at the moment the results are looking promising.

I'm once again in a place where I'm actually half-seriously thinking that much of what Hike does could be built into Rogallo, if I were to simply add http(s) support there.

BagOfStuff v1.3.0

1 min read; 11 GFI

For a wee while now I've been trying to nail down a weirdness with the navigation history in Rogallo. I never felt it was a difficult issue to deal with, but it was also one of those issues that I could never obviously recreate at will, and it only seemed to happen while I was busy working on something else.

Yesterday evening I finally managed to come up with a way to always recreate it and, having done so, the solution seems pretty straightforward1. In order to implement the tweak I want, I need to be able to truncate the navigation history, and of course do so in a non-destructive way.

So the history classes in BagOfStuff v1.3.0 have grown clone and truncate methods. This will allow me to duplicate a history, truncate it at its current location, then save it, without affecting the working copy.


  1. Why do I feel like I'll regret saying that? 

Rogallo v1.9.0

2 min read; 10 GFI

Another update to Rogallo, another new protocol! The main change in v1.9.0 is the addition of support for the Nex protocol.

Nex support in action

As with any other supported protocol, entering a nex:// URI into the command line will cause Rogallo to load up the response in the viewer and render it. Nex is kind of fun in that it's almost a plain text system, by default, but the expectation is that any text/plain document that has => at the start of a line will have those lines be treated just like Gemtext links. So, in Rogallo, when you visit a page, and that page is text/plain, the result will be rendered like it's very simplistic Gemtext that only supports links.

Also, as per the Nex specification, the MIME type of a document is worked out from the extension of the file it points at; so if you happen to get a Gemtext or Markdown file back from a nex:// URI, this will be suitably rendered.

Another addition is a SaveSource command (bound to Ctrl+s by default). As you can probably work out from the name, this will save the source of the document you're currently viewing.

Saving the content of a page

A small housekeeping addition in this release is the cleaning of the content cache. When you start up Rogallo, in the background, any cache entries that have exceeded their time-to-live (something you can set in the configuration file) will be removed. If this results in any cache directories being left empty, they will also be removed. This should result in a nice clean cache directory that's easier to navigate and manage, if you want to go diving into it.

I've also added a small experimental development tool, mostly for myself but it might be something someone else wants to play with. I realised a few days ago that it could be fun to include screenshots of Rogallo in action in my Gemini capsule. The thing is: Gemtext doesn't allow for inline images. What it does allow for, and many clients support, is ANSI escape sequences. Meanwhile, Rogallo is a terminal-based application; its whole method of display is ANSI escape sequences. As such, it should be trivial to capture the sequences for any given screen and just include them in a Gemtext page.

I tried it out and it works a treat! So, if you happen to have ROGALLO_SCREENSHOTS in your environment and it's set to any non-empty value, pressing Ctrl+Shift+F12 writes the current screen to ~/rogallo-screenshot.ansi.

Yes, it's all horribly hard-coded: the key combination is hard-coded (and probably only good for more modern terminal emulators), and the name of the file is hard-coded. As I said: it's a development tool that's there for my own use. I might make it a little more generic in the future.

One final tweak to this release is a fix to the ToggleView command, which stopped letting you view the source of a Gopher map. That ability is now back.

SmolServe v1.1.0

1 min read; 9 GFI

Currently, I'm working on adding support for the Nex Protocol to Rogallo. Having Port1900 as the client library, and having done the bulk of the work in Rogallo, I needed things in place to be able to add some nex://-related documentation too -- which is where SmolServe comes in.

So I've dropped v1.1.0 on PyPI, which adds support for running up a simple just-good-enough Nex server (although, to be fair, Nex is so simple this is probably a fully capable one just by the very nature of how trivial the protocol is).

Now to get back to polishing that Rogallo PR...

Port1900 - An async Python client library for the Nex protocol

1 min read; 10 GFI

It's that time again. Time to add another small web protocol to Rogallo. This time it's one I stumbled across a few days ago: the Nex protocol. This one is very simple and straightforward and it seemed like a shame not to support it.

So, as I have with Gemini, Spartan, Gopher and Finger, I've added a dedicated library for dealing with the associated URI, and to provide a client for talking to the server.

The documentation can be found on the dedicated site.

Rogallo v1.8.0

4 min read; 11 GFI

I've released v1.8.0 of Rogallo. This release has a bit of an accidental emphasis on control of how things are rendered in the main viewer.

Markdown

While Rogallo is, of course, primarily aimed at loading and rendering Gemtext documents, I have written it so that it'll try and display anything whose content type matches text/*. In most cases this will result in something being shown as plain text and, as of v1.6.0, it will also attempt to add some syntax highlighting where appropriate. So, if you happened to come across a Markdown file in Geminispace, and the server told Rogallo that it was a Markdown file, it would look something like this:

Viewing highlighted raw Markdown

Simply put: raw Markdown but syntax-highlighted.

The thing is, Rogallo contains everything needed to actually render the Markdown; it's carrying that code around due to it being built on top of the Textual framework, so it seemed a shame to not use it. So as of this version, if a Markdown file is encountered, by default it'll be shown as a full Markdown widget.

Viewing rendered Markdown

HTML

Having added the above, I got to thinking that it might be interesting to consider other text/* types that I could render in a more Rogallo-friendly way. The next that came to mind was text/html. While it's not going to be that common to encounter HTML on the end of a gemini:// connection, it's not impossible. Initially I did consider going via a route that had me turn the HTML into Markdown and then use the Markdown widget to show the result, but in the end I decided to turn it into Gemtext instead; in part because it's a fun challenge, and in part because it feels more in keeping with the Geminispace aesthetic1.

So, whereas before, if you landed on some HTML in Geminispace, you'd see this:

Viewing raw HTML

From now on you'll see something more like this:

Viewing HTML rendered as Gemtext

This HTML to Gemtext support is still in its infancy so I imagine there's going to be a lot of fun corner cases that don't quite work out, but for me the utility makes it worth working on.

Extended ToggleView

Until now the ToggleView command (bound to F4 by default) simply toggled Gemini-based Gemtext and Gopher maps between their rendered and raw views (acting as a sort of "view source" command). With the addition of richer rendering of Markdown and HTML it will also toggle those content types. The point here being, if you really need to look at the raw content of a Markdown or HTML document found in Geminispace, it's still there for you.

The HandOffToOperatingSystem command

A key feature of Rogallo is the automatic handing off of URIs and MIME types that it can't directly handle. On occasion, though, I find myself wanting to do the same hand-off with a document I'm successfully viewing in Rogallo. This was easy enough to do with the CopyLocationToClipboard command (bound to Ctrl+Shift+c by default), pasting the URI into my normal web browser and going from there. But it felt like this should be a command in its own right.

So now there's HandOffToOperatingSystem (bound to Ctrl+Shift+o by default), which will ask your environment to open the current URI.

Hiding some pre-formatted text

Yesterday, I saw a post on Station which was talking about the site logo. The main thrust of it being, while the logo is cool and all, it does use up a fair bit of vertical space that you have to get past to get to the content. I can see this being an a11y issue in some situations, if nothing else.

The Station logo taking up space

So I got to thinking: in the case of Station, the author of the site has been kind enough to give the pre-formatted text block some alt-text2, so that means it's possible to have a targeted filter for such well-designed sites. Given this, I've added a method of filtering out pre-formatted blocks, keyed on a URI and alt-text. So now, with the addition of this to my configuration:

"hide_preformatted": [
    [
        "gemini://station.martinrue.com/",
        "Station logo"
    ]
]

I can get straight to the content when landing at the Station:

Station without the logo

ℹ️ Note

I did hesitate before adding this. There's a part of me that was thinking "but the creator of the site has designed the site this way, does it make sense to override their choice?" -- but then I decided that, if Geminispace is about anything, it's about privacy, freedom and control over your experience of it. Moreover, using this is a choice on the client side, and like I say, it's in part an a11y feature.

Gopher cache support

More as an accident of how I was working on things than a conscious choice, the only protocols in Rogallo that also used the content cache were Gemini and Spartan. With this release of Rogallo I've extended it to Gopher responses too. I've made a point of not using the cache for any response that is going to be the result of a search, as that feels like something that's often going to have more dynamic content.

Small Gopher fix

Talking of Gopher: there's also a small fix to Gopher responses in this release. When looking for responses that indicated an error from Gopher servers, Rogallo was a little too keen in how it worked, which could result in a plain text response, that just happened to have a 3 in the first column of any line, being seen as a Gopher map that indicated an error.

This is now fixed.


  1. Which also has me wanting, longer-term, to do the same for Markdown. While using the Markdown widget is neat and all, I think it would be far more in keeping with the purpose of this project to turn Markdown into Gemtext. 

  2. As I write more Gemtext myself, I'm going to do my very best to always do the same.