AgiNG v0.3.0

Posted on 2025-03-22 09:30 +0000 in Coding • Tagged with Python, terminal, textual, Norton Guide • 2 min read

I've just released AgiNG v0.3.0. The main focus of this release was to get some searching added to the application. Similar to what I added to WEG back in the day, I wanted three types of searching:

  • Current entry search.
  • Current guide-wide search.
  • All registered guides-wide search.

The current entry search is done with a simple modal input, and for now the searching is always case-insensitive (I was going to add a switch for this but it sort of felt unnecessary and I liked how clean the input is).

Entry search

The search is started by pressing /, and if a hit is found n will take you through all subsequent matches.

As always, if you're not sure of the keys, you'll find them in the help screen or via the command palette:

Looking up search in the command palette

Guide-wide and all-guide searching is done in the same dialog. To search guide-wide you enter what you want to find and untick "All Guides".

Setting up a guide search

With that, the search will stick to the current guide.

Guide-wide search running

As will be obvious, searching all guides that have been registered with AgiNG is as simple as ticking "All Guides". Then when you search it'll take a walk through every entry of every guide you've added to the guide directory in the application.

Gide-wide searching

Global searching is accessed with Ctrl+/ or via the command palette.

Finding global search

With this added, I think that's most of the major functionality I wanted for AgiNG. I imagine there's a few more tweaks I'll think of (for example: I think adding regex search to the global search screen could be handy), but I don't think there's any more big features it needs.

AgiNG can be installed with pip or (ideally) pipx from PyPi. It can also be installed with Homebrew by tapping davep/homebrew and then installing aging:

$ brew tap davep/homebrew
$ brew install aging

The source is available on GitHub.


AgiNG

Posted on 2025-03-12 08:00 +0000 in Coding • Tagged with Python, terminal, textual, Norton Guide • 4 min read

AgiNG

It seems I really do still have this need to create new terminal-based projects at the moment. There's been Braindrop, then Peplum, then after that came Hike. While I'm still tweaking and adding to them, and also using them to refine a wee library I'm building up that forms the core of my latest apps, I felt I still had this one app that I needed to finally build.

Since the 1990s I've had this mild obsession with building tools for maintaining access to Norton Guide files. I've written readers for GNU/Linux (which also works on macOS too), OS/2, Windows, GNU Emacs, and also or the web (in multiple incarnations). Those builds have covered a few languages, including C, C++, Pascal, JavaScript and Emacs Lisp.

I'd never written a Python library or application for it though.

So when I first saw Textual mentioned in passing on Twitter a few years back, way back in the 0.1 days, I thought that could be the thing that would push me over the edge. In anticipation of that, back in 2021, I initially developed ngdb.py. This is a library that provides the core Norton Guide reading code for Python applications and could form the basis for other tools.

As a test for this I then wrote ng2web (which works, but I think still needs a bit of tidying up -- something I'm aiming to do in the next few weeks).

Meanwhile, the journey with Textual itself kicked off, happened, and came to an end; and yet somehow I'd never got round to building the thing I'd initially looked at Textual for: a terminal-based Norton Guide reader that looked nice and modern (by terminal standards). When I initially joined Textualize the owner had actually said they wanted me to build this as test of the framework, to essentially start out by employing me to create some Free Software that would help dogfood the library, but that seemed to get forgotten.

Fast forward to the start of this month and I finally felt it was time to tackle this. The result is AgiNG1.

AgiNG in action

As of v0.1.0 it has most of the features you'd expect from a usable Norton Guide reader, including:

  • An ability to add guide files to an in-application directory.
  • The ability open and navigate a guide.
  • Full see-also support, etc.
  • Full translation of characters as were under MS-DOS into the terminal.
  • The ability to copy entry text or source to the clipboard.
  • The ability to copy save entry text or source to a file.
  • Access to a guide's credits.

AgiNG showing a long entry

I still need to write some proper documentation for the application, but meanwhile all commands and key shortcuts can be discovered either via the help screen:

AgiNG help

or by pulling up the command palette:

AgiNG command palette

Hopefully the workings of the application will be fairly obvious to anyone who is familiar with Norton Guide files; if anything isn't making sense I'm more than happy to answer questions or take suggestions for improvements.

One wee feature I want to call out, that I felt was important to add, was a "classic view" facility. The thing with Norton Guide files is they were mostly created in the very late 1980s and early-to-mid 1990s. People would often get creative with the colouring within them, but in many cases the colouring assumed the default Norton Guide application. Its colours were white text on a blue background. So sometimes other colouring was done assuming that background.

You can see an example of this here, with an entry in a guide being viewed using the default textual-dark theme:

Entry in textual-dark

Notice the colouring in the syntax section. This is more obvious if the application is switched to one of the light themes:

Entry in solarized-light

With a nod to this issue in mind, I added the "classic view" for entries (which is a sticky setting -- turn it on and it stays on until you turn it off):

Classic view in action

A little hard on the eyes, I think, but also filled with nostalgia!

Talking of themes, all the usual application themes are available, here's a wee selection:

Nord Textual Light Gruvbox Solarize Light Monokai

AgiNG is licensed GPL-3.0 and available via GitHub and also via PyPi. If you have an environment that has pipx installed you should be able to get up and going with:

$ pipx install aging

It can also be installed with Homebrew by tapping davep/homebrew and then installing aging:

$ brew tap davep/homebrew
$ brew install aging

Expect to see more updates in the near future; as with other recent projects this is very much something I'm going to be dabbling with and improving as time goes on.


  1. If you're wondering about the name, it's nothing more than a word that happens to have NG in it, and also a mild pun about this being an ageing hypertext help system; with the spelling acknowledging Peter Norton's nationality. 


Hike

Posted on 2025-02-14 09:22 +0000 in Coding • Tagged with Python, terminal, textual • 1 min read

Hike

The run of writing new terminal-based tools that I want still keeps going. First there was Braindrop, then there was Peplum, and now, released today, there's Hike.

Hike is yet another terminal-based Markdown browser. While it's far from the first, and unlikely to be the last, it's mine and it looks and works exactly how I need. Perhaps it'll be your sort of thing too?

Hike viewing its README

This initial release has a bunch of handy features, including things like:

  • A command line where file names, URLs and commands can be entered.
  • A persistent history for the command line.
  • A local file browser.
  • A simple bookmarking system.
  • A browsing history.
  • Commands for quickly loading and viewing files held on GitHub, GitLab, Codeberg and Bitbucket.

As there's a lot to discover in the application, I've tried to make the help screen as comprehensive as possible:

Hike help

and there's also the command palette to help with discovering commands and the keys that are associated with them:

The command palette in action

Once again, themes are supported so no matter your taste you should find something that's easy on your eyes:

Dark Light Tokyo Night Solarized Light

Hike is licensed GPL-3.0 and available via GitHub and also via PyPi. If you have an environment that has pipx installed you should be able to get up and going with:

$ pipx install hike

It can also be installed with Homebrew by tapping davep/homebrew and then installing hike:

$ brew tap davep/homebrew
$ brew install hike

Expect to see more updates in the near future; this is very much an ongoing tinker project.


Peplum

Posted on 2025-01-25 14:21 +0000 in Coding • Tagged with Python, terminal, textual • 3 min read

Peplum

I seem to be back in the swing of writing handy (for me) little terminal-based applications again. Having not long since released Braindrop (which I'm still working on and tinkering with; it'll get more features in the near future, for sure), I had an idea for another tool I'd like to have: something for looking through, searching, and filtering Python PEPs.

As with anyone who is interested in what's happening with Python itself, I subscribe to the RSS feed of the latest Python PEPs, but I also wanted something that would let me look back at older ones in a way that worked "just so" ("just so" being "what feels right for me", of course). Having finished the main work on Braindrop I realised that the general layout of its UI would work here, as would the filtering and searching approach I used.

From this idea Peplum was born!

Peplum in action

In this first release I've simply concentrated on all things to do with grabbing the list of PEPs and presenting them in a useful way; adding various forms of filtering them; adding the ability to search the metadata; that sort of thing. I aim to keep developing this out over the next few weeks and months, adding things like the ability to make notes, to locally view the text of a PEP, perhaps even to mark PEPs as unread and read, etc.

As I mentioned earlier, much of the design was driven by what I did with Braindrop, so once again I've tried my very best to make it keyboard-friendly and as much as possible keyboard-first. This sometimes means having to work against how Textual works, but generally that isn't too tricky to do. I'm once again making heavy use of the command palette and also ensuring that all commands that have corresponding keyboard bindings are documented in the help screen.

Peplum Help

There's enough common code between Peplum and Braindrop, when it comes to this aspect of building a Textual application, that I'm minded to spin it out into a little library of its own. I'm going to sit on this code for a wee while and see how it develops, but I can see me taking this approach with future applications and doing this will stop the need to copy and paste.

It might also be useful to others building with Textual.

Also as with Braindrop, themes are a thing, and the theme setting is sticky so you can set it the once and stick with that you like. Here's some examples:

Nord Catppuccin Latte Tokyo Night

That's a small selection of the themes, with more to explore.

While working on this project I managed to find a couple more bugs in Textual, including a fun way to get transparent backgrounds to get out of sync and also a way to get an easy crash out of OptionList if it's set to width: auto.

What was even more fun was I sort of discovered a bug in the Python PEP API. Thanks to Hugo noticing my "huh, weird" post on Fosstodon, there's now an issue for it as well as a PR in the works. In retrospect I should have raised an issue myself; instead I fell into that "they obviously know what they're doing so it must be like this for a reason" trap.

Lesson relearned: it's always better to ask and get an answer, than to assume a thing is how it is for a reason you don't know; which I guess is a version of Linus' law really.

So that's v0.1.0 out in the wild. I'm pleased with how it's turned out and there's more to come. It's licensed GPL-3.0 and available via GitHub and also via PyPi. If you have an environment that has pipx installed you should be able to get up and going with:

$ pipx install peplum

It can also be installed with Homebrew by tapping davep/homebrew and then installing peplum:

$ brew tap davep/homebrew
$ brew install peplum

I'm going to be making good use of this and working on it more; I hope it's useful to someone else. :-)


Braindrop

Posted on 2025-01-03 16:24 +0000 in Coding • Tagged with Python, terminal, textual • 3 min read

Braindrop

A touch over a year ago I did the initial work on an application called Tinboard, a terminal-based client for the Pinboard bookmarking service. I had a lot of fun building it and it was an application that I used on a near-daily basis. However, around August last year I realised it was time for me to move on from Pinboard and try something new; based on various recommendations I settled on Raindrop.

As mentioned in the other blog post, Raindrop offered more or less everything I had with Pinboard and so the move was fairly straightforward. The one thing that was missing though was an application similar to Tinboard.

So, late on last year, with my winter break approaching, I decided to start from scratch and build a "Tinboard for Raindrop", which I'm calling Braindrop.

This was going to be a bit of an adventure too. Since being laid off from Textualize earlier in 2024 I'd not been following its development quite as closely as I used to, and had also run into some issues and bugs with it since that time; moreover, as well as various bugs appearing, some breaking changes had also been made. As such this was going to be a process where I'd wrap my head around what's happened with the framework over the prior six months or so.

Given all this, over the past couple of weeks I've been spending a few hours a day doing some for-pleasure coding and v0.1.0 of Braindrop is the result.

Main display

As much as possible I've tried to keep the look and feel similar to that of Tinboard, while also doing my best to avoid some of the "ah, I wish I hadn't done it this way" design decisions I'd made. As of the time of writing I'm very pleased with the result.

The edit dialog

One thing I did want to do is ensure that the application was as keyboard-friendly as possible, while also still allowing use of the mouse. Textual can sometimes get that wrong and I ran into an example of this while trying to ensure that there's good in-application help. Somewhat recently Textual added a built-in help system which, sadly, can't easily be used by and navigated by someone using the keyboard. So instead I've recreated the help system I built into Tinboard, while adopting the documentation standard that Textual had settled on (which, coincidentally, was kind of similar to what I did in Tinboard to start with).

The help dialog

As with Tinboard, I've also made sure to make full use of the command palette, with every action that makes sense having a keyboard hotkey as well as a command in the palette. I also took things a little further and made sure that the hotkeys are shown in the command palette for easier discovery.

The command palette

I've also made sure that Textual's new theme system is available for easy use; so out goes dark/light mode toggling and in comes a collection of different themes. Here's a wee selection as an example:

Example theme 1 Example theme 2 Example theme 3 Example theme 4

That's a small selection of the themes, with more to explore.

There's a few more things I want to do before I consider the application v1.0-ready, but it's already in use by me and working well. As I decide what else I want to add to it I'm building up a list of TODO items.

Given that my day job these days is quite varied, isn't quite so coding-intensive, and isn't always related to all things Python, it's actually been fun to sit down and hack up a pure Python application from scratch again. It's also helped me discover a couple or so fresh bugs in Textual (which I've reported, of course) and given me the opportunity to PR some trivial fixes as I've noticed typos and stuff as I go.

Anyway; that's v0.1.0 out in the wild. I'm pleased with how it's turned out and there's more to come. It's licensed GPL-3.0 and available via GitHub and also via PyPi. If you have an environment that has pipx installed you should be able to get up and going with:

$ pipx install braindrop

It can also be installed with Homebrew by tapping davep/homebrew and then installing braindrop:

$ brew tap davep/homebrew
$ brew install braindrop

I hope this is useful to someone else. :-)


Tinboard v0.14.0

Posted on 2024-05-14 08:02 +0100 in Coding • Tagged with Python, terminal, textual, YouTube • 1 min read

I've just released Tinboard v0.14.0. This release adds a feature that a user requested, where you can set the default values for the privacy and read-later status of a new bookmark:

The application settings dialog

So, any time you create a new bookmark, the edit dialog will use those values by default. It's a feature that makes perfect sense but I didn't think to add it early on because... well, I set the defaults to my preference.

Tinboard can be installed with pip or (ideally) pipx from PyPi. It can also be installed with Homebrew by tapping davep/homebrew and then installing tinboard:

$ brew tap davep/homebrew
$ brew install tinboard

The source is available on GitHub.


Tinboard v0.12.0

Posted on 2024-04-18 16:46 +0100 in Coding • Tagged with Python, terminal, textual, YouTube • 2 min read

Tinboard has turned into a tool I use pretty much every day; it's probably my most-used Textual/Python-developed application at this point. This is causing me to think more and more about how I can add things to it that are related to the core purpose, but are also outside of the main "interface with Pinboard" thing.

A thing with keeping bookmarks for a long time is that some of them go stale, go away. Some will just plain 404, others the whole site will disappear. If I find myself going back to a bookmark and seeing this is the case, I'll hit the Wayback Machine and see if there's an archive there.

So I got to thinking: what if I add the ability to perform this check into Tinboard itself? So I did just that.

Now, in the application, if you press w with a bookmark highlighted, it will check with the Wayback Machine to see if the bookmark is in the archive. If it isn't you see this:

No archive result

On the other hand, if it is in the archive, you'll see something like this:

Is in the archive result

I sense this is going to be the first step in a couple of features related to this. I'm thinking that I may go on to add a "swap the URL for this bookmark with the Wayback Machine archive URL" feature, which will be handy for those bookmarks that have one away, and it would also be useful to look at the options for a "please archive a copy of this bookmark" feature.

But, for now, v0.12.0 is available and has this handy (for me anyway) first step.

Tinboard can be installed with pip or (ideally) pipx from PyPi. It can also be installed with Homebrew by tapping davep/homebrew and then installing tinboard:

$ brew tap davep/homebrew
$ brew install tinboard

The source is available on GitHub.


PISpy v0.6.0

Posted on 2024-04-17 11:30 +0100 in Coding • Tagged with Python, terminal, textual, YouTube • 1 min read

Back in the very early days of the Textual adventure, within the first month or so of working on the framework, we had a period of dogfooding. One of the projects I wrote during that time was a little tool I called PISpy.

The initial version was pretty much a quick hack; during that dogfooding period I did my best to try and develop a new project every couple of days. Since then I've let PISpy descend into bit rot.

In the last week or so I've turned my attention back to it and made an effort to tidy up the code, tidy it some more, and some more, and even some more.

This morning I put the finishing touches to these changes and released v0.6.0.

PISpy in action

PISpy can be installed with pip or (ideallty) pipx from PyPI. It can also be installed with Homebrew by tapping davep/homebrew and then installing pispy:

$ brew tap davep/homebrew
$ brew install pispy

The source is available on GitHub.


Tinboard v0.11.0

Posted on 2024-04-09 15:43 +0100 in Coding • Tagged with Python, terminal, textual, YouTube • 1 min read

While my time working on Textual might have come to an end, my time working with Textual hasn't. Three days back I experimented with Textual's newly-added "inline mode":

In doing so I extended the application so that it's possible to run tinboard add and quickly enter a new bookmark and then carry on in the terminal, without needing to "go fullscreen". I'll admit it's of limited use, but it seemed like a good shakedown of the feature and in working on it I was able to discover a couple of bugs (#4385, #4403).

The effect of this is this:

Tinboard inline addition in action

Tinboard can be installed with pip or (ideally) pipx from PyPi. It can also be installed with Homebrew by tapping davep/homebrew and then installing tinboard:

$ brew tap davep/homebrew
$ brew install tinboard

The source is available on GitHub.


Homebrew all the Python things

Posted on 2024-03-10 14:12 +0000 in Coding • Tagged with Python, terminal, textual, Homebrew, Makefile • 4 min read

Over the past year and a half I've written a lot of Python code, and a lot of that Python code has been Textual applications; most of those Textual applications have been very quick demonstration or test applications built to help support someone asking for help; some of them have been less-trivial applications written in my own time and for my own use and amusement. Of them I'd say there are two near-daily-drivers, and a couple that I either have more plans for, or like to maintain just for the hell of it.

Those latter applications are all ones that I've deployed to PyPI, and because of that are all ones that I've recommenced be installed using pipx. During that time though I've had half an inclination to make them installable via Homebrew. While probably not installable from the core Homebrew repository1, at least installable from a "tap"2 that's under my own GitHub account or something.

To this end I've had a blog post about packaging Python apps for Homebrew saved in Pinboard for a while now, and every time I look at it I think "this is a lot of faff, maybe later". Today was that "later".

As it turned out, it was way easier than I first realised. The evolution of today pretty much went like this:

Deciding to use a single repository as the "tap"

The blog post above seemed to suggest that for every application repository you want a tap for, you probably want a parallel homebrew--prefixed repository. This in turn would suggest that every time someone wants to install one of your tools, they'd need to add a new tap3. As I looked at it this seemed like way too much faff, so in the end I decided to create a single repository that I'd keep all my formula files in. The naming of homebrew-homebrew meant that the tap name would simply be davep/homebrew.

Simple and clean, I think: things for homebrew, things that can be installed via homebrew, that come from davep. To add the tap it's simply:

$ brew tap davep/homebrew

Ensuring that all my applications and libraries publish source

Although it seems that it might be (possibly, maybe, perhaps, who can tell?) deprecated, it looked like homebrew-pypi-poet was a tool I'd need to do all the heavy work on making the formula file. A quick test threw up a problem where it was complaining that my test package (one of my own applications) didn't have an sdist. Sure enough, through nothing more than never having bothered to make it happen, the source of my libraries and applications wasn't been uploaded to PyPI when I published.

So I went through some of my repositories and fixed that, making patch releases as I went.

Making a Makefile to let me be lazy

The next thing to do was to figure out the most lazy way of building the formula files. From what I could see the main steps to making all of this work were:

  • Make a venv and activate it
  • Install homebrew-pypi-poet
  • Install the package you want to package for Homebrew
  • Run poet to make the formula

Seemed simple enough. For all sorts of lazy reasons I still tend to use pipenv to get things done quickly, and that seemed to work fine here too. I'm also a fan of PIPENV_VENV_IN_PROJECT=true which makes things clean and tidy, so I figured a rule in a Makefile like this:

clean:
        rm -rf .venv
        rm -f Pipfile Pipfile.lock
        pipenv --python 3.12
        pipenv install --dev homebrew-pypi-poet

would be fine to make a clean venv ready to build the formula, and then I'd have a rule for the package itself that depended on the above, like this:

oshit: clean
        pipenv install oshit
        pipenv run poet -f oshit > Formula/oshit.rb

Fixing the package description

The above was great, and worked really well. But there was one issue that I could see: the resulting formula file always had this desc inside it:

desc "Shiny new formula"

From what I could see there was no way to tell poet what I wanted the description to be, and neither did I want to have to remember to edit that line each time I regenerated the formula file. So sed to the rescue then I guess, with this sort of thing:

sed -i '' 's/Shiny new formula/The actual text I want/' Formula/coolapp.rb

The result

The result of all of this is that I now have a repository that I or anyone else can use as a tap to be able to install my stuff using the brew command. So now if you want a little Hacker News reader for the terminal but you don't want to be messing with installing pipx and the like, but you do use brew on your machine, it's just this:

$ brew tap davep/homebrew
$ brew install oshit

Fingers crossed it all "just works" when I next upgrade one of those packages. I will, of course, have to remember to go into davep/homebrew-homebrew and make the-app for the relevant application, and then commit and push the changes, but that's really not too difficult to remember and do.

Hopefully it'll then all just work.


  1. I do actually have one package in Homebrew, but it wasn't me who put it there. 

  2. I really like Homebrew as a tool for getting stuff installed, by oh my gods the naming of things in its ecosystem is terrible and confusing! 

  3. No, really, I mean it, this naming convention is kinda cringe right?