2025 Sept 8 โ Ephem Devlog 03
Hello, and welcome to the third devlog for Ephem! I'm headed towards 2.0.0 with one major feature addition staring me in the face at the moment: adding a YAML front-end to the SQLite3 chart database solidified in 1.0.0. What follows in this installment are the features that have appeared and disappeared, or rather transmuted into something else, and a tale of heartbreak over Unicode.
v2's command stack
I mentioned in the last devlog that I planned to move ephem asc
into its own package, which I have! It was a part of Ephem for purely sentimental reasons of being the seed of it all, but it really doesn't make sense to have a command solely to print one line of ephem now
. That's only one part of slimming down Ephem's features first laid out here. We're now looking at fewer commands that are each robust features on their own, with sensible but carefully shared optional flags via a helper function and a parent parser.
The current usage from -h
I'm dogfooding on my non-dev machines goes
usage: ephem [-h] [--list-offsets] [--db DB] {now,cast,cal,data} ...
Ephem is a tool for calculating astrological charts and monthly ephemerides.
positional arguments:
{now,cast,cal,data}
now ๐ calculate the chart of the moment
cast ๐ calculate an event or birth chart
cal ๐
calculate ephemeris table for a given or the current month
data ๐๏ธ manage chart database
options:
-h, --help show this help message and exit
--list-offsets list all ayanamsa offsets as index:key pairs
As you can see, three of the four commands are calculation using the Swiss Ephemeris, while data
is all SQLite (for now). Creating the cal
command was quite easy. I broke a 100+-line module called horoscope
into angles
and houses
since ephem cal
would have no use for angles.
What changed from v1:
- v1 had
ephem asc
. I'm not totally happy with the separate package now that I've implemented ayanamsa support inephem
. That'll be the last thing I add to it before laying it to rest as a truly Unix-y, "doing one thing well" utility. It's better than the initial rice script because default locale is configurable with my enemyconfigparser
. I just need to copy over my ayanamsa logic and the--list-offsets
option fromephem
and then it'll be done, I hope. - v1 had
ephem config
. This argparse logic now lives as a simple--save-config
option you can append toephem cast
orephem now
. If you're tinkering with display options, you may run these commands several times before landing on the look you like, so throwing on a flag rather than repeating the same meticulous chart data forephem config save
just makes sense.
terminal emulators, UTF-8, and Rich
The goal of ephem cal
is to make good on the CLI's name and replicate a table from The American Ephemeris, which looks like this:
I have the trans-century edition at midnight. A lot of people the noon version, which makes no sense to me at all, but just to make things extra clear, I specify the sidereal time show in the table is midnight, or 0hr
. I also exclude the asteroid Chiron, and I have no idea why The American Ephemeris includes it.
One limitation of v1 is just one of astrology. A horoscope is only ever a snapshot of a single moment, or more etymologically to "observe" (scope) the hour (horo). Ephemeris itself is from Ancient Greek แผฯฮฎฮผฮตฯฮฟฯ: fleeting, lasting one day (hemera). To get an idea of movement, especially direct or retrograde motion and the speed at which planets change signs, you really have to see it in context. I realized this when I created the dictionaries for individual horoscope entries (e.g. per object) to include its position the prior Julian minute and throw on an 'r'
afterwards if the current longitude < previous longitude.
Ephemerides are just daily horoscopes at a certain time (midnight or noon) compacted into table rows, so ephem cal
reuses much of the SwissEph code that goes into now
and cast
, except it only needs planetary data and nothing geocentric. Despite its name, the point of The American Ephemeris is to be useful to as many people as possible, so it's the work of astrologers (read: their software) to localize the data.
I restructured the file tree to have a bunch of directories and modules broken up from larger ones that makes importing functions and creating the cal
display module and command easier.
But about that cal
display module.
I think I need to break up with foot. It's the default terminal emulator in SwayWM, and I've had no reason to stray from it as a happy tmux user. I've especially loved it because it's the only terminal emulator I've used that lets me type Unicode characters with my QMK keymap. For some reason, though, this does not translate to consistent Unicode rendering, at least not with Rich, the library I'm using for ANSI colors and tables.
For cast
and now
, Unicode glyphs have rendered beautifully in the three emulators I test, foot, Alacritty, and WezTerm. But cal
makes visble use of Rich's table.box
method to match The American Ephemeris and just contain this dense information visually. It's worked out perfectly an Alacritty and Wezterm regardless of font.
Here's Alacritty with 0 config, just system monospace:
And Wezterm with IBM 3270:
But in my favorite terminal emulator, the one I daily drive, the one configured in Sway, the table comes out like this even with the most vanilla font choice of JetBrains Mono:
I don't think this is a Rich problem. This is about different approaches to Unicode support and me not wanting to see emojis in the terminal, especially not Google Noto's hideous, illegible rainbow signs. The latter means that I specify the Unicode version of each glyph with the invisible U+FE0E
selector. Yes, I did copy and paste them in from the astrological symbols Wikipedia article I have bookmarked for that specific purpose. I've coded astrological symbols into my mechanical keyboards from the start and even shared a QMK Unicode map for anyone to use, but I left the sign symbols without the text presentation selector for... I don't know. Minimalism? Maybe some people like their local sign emojis. I admit Apple wins here with the simple purple squares.
The point of the U+FE0E
selector is that it lengthens each Unicode symbol to taking up an extra column. Alacritty and WezTerm have ways of catching this that are opaque to me and understand each glyph as a single character; foot doesn't. Or the addition of Rich just makes it difficult for foot. It's likely been confused the whole time with ephem now
and ephem cast
and I just didn't catch it because display.chart
(their new shared output module) doesn't use Rich's table.box
method with a visible style.
Either way, instead of possibly wrecking my display.month
module for the terminal emulator I and a few others love, I just created an --ascii
flag that uses the truncated, three-character sign names and even the full names of each planet for good measure:
This, however, is inconsistent with the v1 display options and led to me slimming that down for uniformity! v1 had a --format {short,glyphs,name}
option that I really don't see anyone using, so I made a strong editorial choice that the only possible formats for chart
and now
are either
โ 16 Virgo 09 51
or with --ascii
Sun 16 Vir 09 51
No more futzing around!
what's next
YAML on top of SQLite. I'll talk about this more once I've actually implemented it, but the idea is for a charts/
directory of individual data .yml
files to mirror the contents of ephem.db
, which XDG-style lives in .local/share
if it's up to me.
This comes from literal years of trying to keep a client and research database anywhere but a spreadsheet, most bizarrely through Obsidian Dataview and currently in a Git repo of Astrolog plain text commands. This is the feature that scares me most because I think it's what my Virgo moon has been wanting for years and didn't realize she could be the one to create until now. Oh my god.
I'm trying to share more incremental updates on Mastodon now! At minimum I'll share devlog and newsletter links that are relevant to Ephem. Until next time, hopefully YAML-victorious.
๐ฆโโฌ