Lagrange v1.13: Curses TUI, Spartan, Emoji

There has been scattered progress on various fronts, which makes summarizing this release a bit challenging. The most significant new feature is a TUI for terminal emulators. However, it remains a work-in-progress and needs compatibility testing, but I find it quite useful already.

Curses TUI

There is now a text-mode version of Lagrange for the terminal.

Since the underpinnings of the UI are the same in the GUI and TUI versions, all features of the app are automatically available in both. I find this pretty cool — it further widens the set of platforms where the app can run.

I would still call this a Beta of sorts because as you might imagine, there are quite a few differences between desktop GUIs and the terminal, so there are many details to consider and adjust in the app. It's nowhere as much work as the mobile ports, though. I would compare it to the amount of differences between Mac and Windows, for instance. There's still much to improve, with the following missing in v1.13: color settings (e.g., VGA color and no-color modes), Emoji ASCII replacements, console mouse support, and basic usability things like Help and key shortcut status lines (cf. Nano).

To interact with links on pages, you are expected to use the home row key navigation method: first press F, and letters appear next to each link, so pressing one of those keys will open the link. Similarly, "hovering" on a link can be done by first pressing H. This way one can open a link-specific context menu: H, link letter, and then /. Granted, this is not optimal UX — mostly I'm just retrofitting parts of the GUI so things make better sense in the terminal. I expect to make some improvements here in the future.

I haven't settled on a binary distribution scheme for clagrange. On Linux, a separate AppImage would make sense, and on Windows clagrange.exe could be included with the GUI distribution. Mac probably needs a separate package, something like a custom Homebrew tap or just a zipped executable you can run from anywhere. For now, the TUI version is available via a source build: download the tarball and run ``. The README has more detailed build instructions.

All in all, I think the TUI version deserves to be on par with all the other variants of the app, given that Gemini is so well aligned with terminal/text interfaces. It'll just take a little while to see what works in practice and what kind of changes are still needed.

Basic usage

As there still isn't a terminal-focused Help page or a quick cheatsheet of the important keys, here's what you should know:

Focus the URL field             ^L
New tab                         T
Previous/next tab               [ ]
Open a link on the page         F (+ link key)
Reassign link keys              .
  (if too many links visible)
Navigate back/forward           Left/Right
Reload page                     R
Go to parent                    Sh-R
Show the page context menu      /
Show the File menu              ?
Toggle Bookmarks                1
Toggle Feeds                    2
Toggle History                  3
Toggle Identities               4
Toggle Outline                  5
Resize the sidebar              - =
Reset sidebar width             0
Dismiss dialogs/panels          ESC or ^G

These default keybindings assume a U.S. keyboard layout. The rest of the keys you can find listed in Preferences > Keys, and/or in the various context/popup menus.

Keyboard navigation

Making the TUI port necessitated seriously improving keyboard navigation of the interface.

In previous releases, only certain buttons have been reachable with the TAB key. In v1.13, all UI elements are keyboard-accessible: the sidebar gets input focus when opened, one can navigate lists and popup menus with the cursor keys (and PgUp/Dn, Home, End), an open sidebar can be quickly refocused with TAB, and there are new bindings for opening context menus and the menu bar menus.

The behavior is much better now, but this could still be polished further. I'm thinking at least the cursor keys should be supported in more contexts, and not just lists, menus, and for scrolling the page. Also, it's sometimes a little unclear where the input focus is, and assigning key bindings via Preferences > Keys is a bit clunky.

Spartan protocol

Occasionally there have been calls for encryption-free Gemini, with various motivations: a desire to get rid of the complexity of TLS, using really simple/slow hardware where encryption is infeasible, or simply not having a need to encrypt traffic, perhaps because one is on a private network. Gopher is always available as an option, but that comes with certain limitations and archaic assumptions.

Michael Lazar's Spartan protocol is a nice alternative that is simpler than Gemini but still flexible enough for advanced use cases. Spartan has no encryption so everything is transferred in the clear over basic TCP connections.

Spartan draws on ideas from gemini, gopher, and http to create something new, yet familiar. It strives to be simple, fun, and inspiring.

Version 1.13 adds full support for Spartan. When it comes to the UI, the biggest difference to Gemini is how user input is handled. Spartan has a special link type for input prompts, and following a prompt link brings up the basic text input dialog like with a Gemini 1x status. However, since Spartan also supports arbitrary binary uploads, the basic dialog can be expanded to the full upload UI that is also used for Titan, where you can more comfortably edit a longer piece of text and drag-and-drop a file from the system's file manager. This way we can handle short-form input, long-form text, and binary data.

With Spartan added, the list of supported protocols now looks like this:

Emoji coverage

A notable change in v1.13 is that the monochrome Noto Emoji font has been updated with characters for Unicode 14. This means all the Emoji defined in the last few years should appear in the app without having to install any additional fontpacks. If you've previously installed fontpacks for Emoji, now might be a good time to open "about:fonts" and delete the redundant fontpacks.

A noteworthy fix: the font library's index for looking up fontpacks based on missing glyphs was improved. Now it should find Emojis fonts in older releases of the app, too.



When adding a bookmark for a URL that has already been bookmarked, the Edit Bookmark dialog will open instead so a duplicate isn't created. The dialog now has a button for making the duplicate if that was the intent. Also, the URL field shows a pin indicator📌 if the current URL is already bookmarked. The indicator is clickable so there's a convenient way to add/edit a bookmark.

Viewing page source

A new context menu item and key binding were added for toggling between page source and the styled Gemtext view (Ctrl+Y or ⌘Y). Note that this does not yet take into account any filtering of the page contents, for example by MIME hooks or automatic Atom feed XML translations. That would be a useful future improvement.

Viewing Markdown documents as styled Gemtext

Now that there is a way to switch between the source text and the styled document, this can be used with Markdown as well. By default, Markdown pages are shown as source text. There are basically two reasons for this: 1) only a rather small subset of Markdown is supported because the app doesn't use a web view for showing documents; and 2) I don't want to encourage the use of Markdown instead of Gemtext, as that would make viewing content in other clients a worse experience.

Reopen last closed tab

By somewhat popular demand: reopening closed tabs. There is actually a tab undo stack, so multiple previously closed tabs can be reopened. However, the navigation history of the tabs is not restored, just the page that was last open.

Embedded CA trust store

It has already been possible to configure Lagrange to use a CA file/directory where trusted root certificates can be found, so server certificates generated by known CAs can be automatically trusted. This is pretty convenient when servers use Let's Encrypt certificates, for example. In v1.13, I've added a build option to specify the path of a "cacert.pem" file that will be included with the app's other resources, so configuring the CA file location manually is not necessary. In practice, I'm using the Mozilla CA certificate trust store:

📅 2022-05-03

🏷 Lagrange

CC-BY-SA 4.0

The original Gemtext version of this page can be accessed with a Gemini client: gemini://