Posts from July 14, 2026

Rogallo v0.7.0

2 min read; 10 GFI

Rogallo v0.7.0 is now available. The main changes in this release revolve around the display and navigation of links.

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.

Links, like any other UI element in the application that can receive "focus", can be navigated to using Tab and Shift+Tab. 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.

So now, by default, all links on a page get a numeric label:

Links with numeric labels

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 Enter to follow the link.

The input system is written to "wrap around", as it were. So if you type 1 the link with a label of 1 will be focused. If you then type 2, and if there's a link with a label of 12, it will be focused. If there are fewer than 12 links, the input chain resets, and 2 will be focused. The idea being: as you keep typing numbers, they concatenate until there's no matching link and then it starts fresh.

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 Tab 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.

Links with stripes

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.

Links how they used to look

I think this covers pretty much all the possible link navigation needs I can imagine anyone having.

As well as the above, other small changes in v0.7.0 include:

  • 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.
  • 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.
  • Also added the same to the history search palette.

I've also done more work on the website. The configuration section 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.

Wasat v0.6.0

1 min read; 8 GFI

Wasat v0.6.0 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 GeminiURI.

The typing issue is a simple enough one. The __init__ method for GeminiURI can take either a string or another GeminiURI as its argument. However, the type was actually specified as str | Self. In Rogallo, I want to have a sub-class of GeminiURI for one particular purpose, which will be passed an instance of GeminiURI. Something like this:

class KnownHost(GeminiURI):
    """A known host."""

From this, I want to be able to do:

[KnownHost(host) for host in self.known_hosts]

where known_hosts is typed as list[GeminiURI]. At this point, the type checker complains:

Argument 1 to "KnownHost" has incompatible type "GeminiURI"; expected "str | KnownHost"  [arg-type]

The error is correct, because the use of Self 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 str | GeminiURI. In my example above, KnownHost is a subclass of GeminiURI, so the type checker will be happy again.

The new method I've added is GeminiURI.with_default_scheme. This is a class method that acts as a more relaxed "constructor" for a GeminiURI. Again, in Rogallo, there are a few places where I'm taking some input, assuming it's going to be a gemini:// URI, checking if it's missing the scheme prefix, and then prefixing the string with gemini:// before creating a GeminiURI1. This means that Rogallo contains a few instances of this sort of code:

if ...: # ...we should treat some text as a URI but it isn't prefixed with "gemini://"
    uri = GeminiURI(f"{GEMINI_PREFIX}{text}")

It's a small difference, but from now on I'll be able to:

uri = GeminiURI.with_default_scheme(text)

This removes the need to check if there's a scheme already and it saves me having to import GEMINI_PREFIX, etc.


  1. GeminiURI will deliberately raise an exception if the scheme isn't gemini