horologion was the wrong book

The Horologion is the Book of Hours: the fixed portions of the services
themselves. This shows the day's commemorations, its fast and its season,
which is a Menologion. Naming it for a book whose contents it does not carry
was a real error and worth the churn to correct.

typikon already uses the word internally, for menologion.py and the data file
it loads. That is not a collision: typikon provides a menologion, this
displays one.

Renamed throughout, not just the repo: the two scripts, the QML component and
its three qmldir modules, MENOLOGION_COLORS, ~/.config/menologion/colors.json,
the eww widgets and scss variables, the waybar class. Verified standalone and
embedded in a foreign shell, and the smoke suite still passes.

Also drops the em dashes from the prose.
This commit is contained in:
funkpower
2026-09-18 10:52:56 -04:00
parent 7beb53fc94
commit be81c682cb
16 changed files with 133 additions and 134 deletions
+29 -30
View File
@@ -1,11 +1,11 @@
# horologion
# menologion
Desktop front ends for [`typikon`](https://git.pumpin.online/funkpower/typikon)
— the Orthodox liturgical day on your desktop, in Hyprland (Quickshell),
waybar or eww.
Desktop front ends for [`typikon`](https://git.pumpin.online/funkpower/typikon).
The Orthodox liturgical day on your desktop, in Hyprland (Quickshell), waybar
or eww.
Everything is computed locally by `typikon`, so none of this touches the
network, and the widget re-reads only when the date rolls over — the answer
network, and the widget re-reads only when the date rolls over. The answer
changes at midnight and at no other moment.
![The widget during the Nativity Fast](docs/nativity-fast.png)
@@ -22,8 +22,8 @@ $ typikon --set-default rocor # or antiochian, oca, greece, ...
Then:
```console
$ git clone https://git.pumpin.online/funkpower/horologion
$ cd horologion && ./bin/horologion-install
$ git clone https://git.pumpin.online/funkpower/menologion
$ cd menologion && ./bin/menologion-install
```
That links rather than copies, so `git pull` updates what you are running. Pass
@@ -34,19 +34,19 @@ That links rather than copies, so `git pull` updates what you are running. Pass
A desktop widget for Hyprland and anything else Quickshell runs on.
```console
$ quickshell -p ~/.config/quickshell/horologion/shell.qml
$ quickshell -p ~/.config/quickshell/menologion/shell.qml
```
It sits on the background layer, so it behaves like part of the wallpaper —
It sits on the background layer, so it behaves like part of the wallpaper:
always under your windows, never stealing a click.
To drop it into a shell you already have, link this directory in beside your
own and import it by path:
```qml
import "horologion/modules"
import "menologion/modules"
Horologion {}
Menologion {}
```
The imports inside are relative, so the widget always resolves its own
@@ -57,16 +57,16 @@ Three pieces, each usable on its own:
| | |
|---|---|
| `services/Typikon.qml` | a singleton wrapping the CLI — bind to it from anything |
| `services/Typikon.qml` | a singleton wrapping the CLI; bind to it from anything |
| `services/Theme.qml` | colours, from JSON, with defaults for every key |
| `modules/Horologion.qml` | the widget |
| `modules/Menologion.qml` | the widget |
Set a jurisdiction per-widget if you want one different from your default:
```qml
import "horologion/services" // for Typikon
import "menologion/services" // for Typikon
Horologion {
Menologion {
Component.onCompleted: Typikon.jurisdiction = "moscow"
}
```
@@ -76,25 +76,24 @@ you look at what Great Week will ask of you before it arrives.
### Colours
`Theme.qml` reads `~/.config/horologion/colors.json`, or whatever
`HOROLOGION_COLORS` points at, and watches it for changes. Every key has a
`Theme.qml` reads `~/.config/menologion/colors.json`, or whatever
`MENOLOGION_COLORS` points at, and watches it for changes. Every key has a
default, so the widget is legible with no file at all. See
`quickshell/colors.example.json` — the flat shape most theme generators
`quickshell/colors.example.json`, the flat shape most theme generators
already emit.
## waybar
```jsonc
"custom/typikon": {
"exec": "horologion-waybar",
"exec": "menologion-waybar",
"return-type": "json",
"interval": 1800,
"on-click": "typikon --days 7"
}
```
The module's CSS class is the fast level — `.xerophagy`, `.wine_oil`, `.fish`
— so a day's discipline reads off the colour without reading the text.
The module's CSS class is the fast level (`.xerophagy`, `.wine_oil`, `.fish`), so a day's discipline reads off the colour without reading the text.
`.obligatory` is added only where a particular law actually binds, which under
the Typikon is never: the Orthodox Church keeps the fast as tradition, not as
precept. `waybar/style.css` has a starting palette.
@@ -102,18 +101,18 @@ precept. `waybar/style.css` has a starting palette.
Change what the text says with `--format`:
```console
$ horologion-waybar --format '{emoji} {fastLabel}'
$ horologion-waybar -j moscow --format '{emoji} {churchDate}'
$ menologion-waybar --format '{emoji} {fastLabel}'
$ menologion-waybar -j moscow --format '{emoji} {churchDate}'
```
## eww
```lisp
(include "horologion/horologion.yuck")
(include "menologion/menologion.yuck")
```
Then `(horologion)` for the full panel or `(horologion-bar)` for one line.
`horologion.scss` carries the styling; its colours are `!default` variables, so
Then `(menologion)` for the full panel or `(menologion-bar)` for one line.
`menologion.scss` carries the styling; its colours are `!default` variables, so
set your own before the `@import`.
## What it shows
@@ -123,7 +122,7 @@ the week ahead, and Pascha.
**The church date is always in the corner.** On the new calendar it echoes the
wall calendar; on the old it is the answer you came for. Below, ROCOR on 7
January — which is 25 December, and the Nativity.
January, which is 25 December, and the Nativity.
![The Nativity on the old calendar](docs/old-calendar.png)
@@ -133,12 +132,12 @@ days at a time, and a widget that leads with "Post-festive Day of the
Exaltation" for a week has told you nothing.
**The legend is built from the week in view**, not hardcoded, because the
levels a tradition uses are its own — six under the Typikon, three under
Ruthenian particular law — and the words for them differ too. Great Week uses
levels a tradition uses are its own: six under the Typikon, three under
Ruthenian particular law, and the words for them differ too. Great Week uses
nearly all of them:
![Great and Holy Week](docs/great-week.png)
## Licence
GPL-2.0-only — see [LICENSE](LICENSE).
GPL-2.0-only. See [LICENSE](LICENSE).
@@ -9,12 +9,12 @@ binhome="${HOME}/.local/bin"
usage() {
cat <<USAGE
horologion-install [quickshell|waybar|eww|bin|all]
menologion-install [quickshell|waybar|eww|bin|all]
quickshell link quickshell/ into a quickshell config as horologion/
quickshell link quickshell/ into a quickshell config as menologion/
waybar link the bar script and print the module to merge
eww link eww/ into your eww config
bin link horologion-waybar into ~/.local/bin
bin link menologion-waybar into ~/.local/bin
all bin + whichever of the three are already configured
USAGE
@@ -37,7 +37,7 @@ link() {
}
do_bin() {
link "$src/bin/horologion-waybar" "$binhome/horologion-waybar"
link "$src/bin/menologion-waybar" "$binhome/menologion-waybar"
case ":$PATH:" in
*":$binhome:"*) ;;
*) echo " note: $binhome is not on your PATH" >&2 ;;
@@ -45,43 +45,43 @@ do_bin() {
}
do_quickshell() {
link "$src/quickshell" "$config/quickshell/horologion"
link "$src/quickshell" "$config/quickshell/menologion"
cat <<'NOTE'
Add to your shell.qml:
import qs.horologion.modules
import qs.menologion.modules
...
Horologion {}
Menologion {}
Or run it on its own:
quickshell -p ~/.config/quickshell/horologion/shell.qml
quickshell -p ~/.config/quickshell/menologion/shell.qml
NOTE
}
do_waybar() {
link "$src/waybar/style.css" "$config/waybar/horologion.css"
link "$src/waybar/style.css" "$config/waybar/menologion.css"
cat <<'NOTE'
Add "custom/typikon" to a modules list, merge waybar/config.jsonc into
your config, and @import "horologion.css" from your style.css.
your config, and @import "menologion.css" from your style.css.
NOTE
}
do_eww() {
link "$src/eww" "$config/eww/horologion"
link "$src/eww" "$config/eww/menologion"
cat <<'NOTE'
Add to your eww.yuck: (include "horologion/horologion.yuck")
Add to your eww.scss: @import "horologion/horologion.scss";
Then put (horologion) in a window, or (horologion-bar) in a bar.
Add to your eww.yuck: (include "menologion/menologion.yuck")
Add to your eww.scss: @import "menologion/menologion.scss";
Then put (menologion) in a window, or (menologion-bar) in a bar.
NOTE
}
require_typikon() {
command -v typikon >/dev/null 2>&1 && return 0
echo "horologion: typikon is not on PATH." >&2
echo "menologion: typikon is not on PATH." >&2
echo " pipx install git+https://git.pumpin.online/funkpower/typikon" >&2
exit 1
}
@@ -2,7 +2,7 @@
"""waybar custom module — the liturgical day in the bar.
"custom/typikon": {
"exec": "horologion-waybar",
"exec": "menologion-waybar",
"return-type": "json",
"interval": 1800,
"on-click": "typikon --days 7"
-62
View File
@@ -1,62 +0,0 @@
// horologion — colours are variables so you can point them at your own theme.
// Defaults are a neutral dark set; override them before the @import.
$horologion-fg: #ebdbb2 !default;
$horologion-fg-dim: #a89984 !default;
$horologion-accent: #d3869b !default;
$horologion-red: #fb4934 !default;
$horologion-yellow: #fabd2f !default;
$horologion-surface: #282828 !default;
$horologion-overlay: #504945 !default;
.horologion {
background-color: rgba(40, 40, 40, 0.82);
border: 1px solid $horologion-overlay;
border-radius: 14px;
padding: 14px;
color: $horologion-fg;
min-width: 400px;
.glyph-big { font-size: 28px; }
.glyph { font-size: 15px; }
.title {
font-weight: bold;
font-size: 13px;
&.feast { color: $horologion-accent; }
}
.sub {
font-size: 10px;
color: $horologion-yellow;
&.obligatory { color: $horologion-red; font-weight: bold; }
}
.cycle {
font-size: 10px;
font-style: italic;
color: rgba(168, 153, 132, 0.8);
}
.fast { font-size: 11px; color: $horologion-fg-dim; }
.rule {
background-color: rgba(80, 73, 69, 0.6);
min-height: 1px;
}
.weekday { font-size: 11px; color: $horologion-yellow; }
.day {
font-size: 10px;
color: $horologion-fg-dim;
&.feast { color: $horologion-accent; }
}
.pascha { font-size: 10px; color: $horologion-fg-dim; }
}
.horologion-bar {
.glyph { font-size: 14px; }
.title { font-size: 12px; }
}
+62
View File
@@ -0,0 +1,62 @@
// menologion — colours are variables so you can point them at your own theme.
// Defaults are a neutral dark set; override them before the @import.
$menologion-fg: #ebdbb2 !default;
$menologion-fg-dim: #a89984 !default;
$menologion-accent: #d3869b !default;
$menologion-red: #fb4934 !default;
$menologion-yellow: #fabd2f !default;
$menologion-surface: #282828 !default;
$menologion-overlay: #504945 !default;
.menologion {
background-color: rgba(40, 40, 40, 0.82);
border: 1px solid $menologion-overlay;
border-radius: 14px;
padding: 14px;
color: $menologion-fg;
min-width: 400px;
.glyph-big { font-size: 28px; }
.glyph { font-size: 15px; }
.title {
font-weight: bold;
font-size: 13px;
&.feast { color: $menologion-accent; }
}
.sub {
font-size: 10px;
color: $menologion-yellow;
&.obligatory { color: $menologion-red; font-weight: bold; }
}
.cycle {
font-size: 10px;
font-style: italic;
color: rgba(168, 153, 132, 0.8);
}
.fast { font-size: 11px; color: $menologion-fg-dim; }
.rule {
background-color: rgba(80, 73, 69, 0.6);
min-height: 1px;
}
.weekday { font-size: 11px; color: $menologion-yellow; }
.day {
font-size: 10px;
color: $menologion-fg-dim;
&.feast { color: $menologion-accent; }
}
.pascha { font-size: 10px; color: $menologion-fg-dim; }
}
.menologion-bar {
.glyph { font-size: 14px; }
.title { font-size: 12px; }
}
+7 -7
View File
@@ -1,10 +1,10 @@
;; horologion — the liturgical day for eww
;; menologion — the liturgical day for eww
;;
;; Include this from your own eww.yuck:
;;
;; (include "horologion/horologion.yuck")
;; (include "menologion/menologion.yuck")
;;
;; and put (horologion) in a window, or (horologion-bar) in a bar. Set a
;; and put (menologion) in a window, or (menologion-bar) in a bar. Set a
;; jurisdiction by adding `--jurisdiction <name>` to both defpoll commands
;; below; leaving them as they are follows whatever `typikon --set-default`
;; wrote.
@@ -22,8 +22,8 @@
`typikon --json --days 6 --date $(date -d tomorrow +%F)`)
;; ── the one-line version, for a bar
(defwidget horologion-bar []
(box :class "horologion-bar"
(defwidget menologion-bar []
(box :class "menologion-bar"
:space-evenly false
:spacing 6
(label :class "glyph" :text {typikon-day.emoji ?: ""})
@@ -32,8 +32,8 @@
:text {typikon-day.title ?: "typikon?"})))
;; ── the full panel
(defwidget horologion []
(box :class "horologion"
(defwidget menologion []
(box :class "menologion"
:orientation "v"
:space-evenly false
:spacing 8
+2 -2
View File
@@ -1,3 +1,3 @@
module horologion.modules
module menologion.modules
Panel 1.0 Panel.qml
Horologion 1.0 Horologion.qml
Menologion 1.0 Menologion.qml
+1 -1
View File
@@ -1,2 +1,2 @@
module horologion
module menologion
singleton Config 1.0 Config.qml
+3 -3
View File
@@ -8,16 +8,16 @@ import Quickshell.Io
// rest of your desktop.
//
// Every key has a default, so the widget is legible with no file at all. Point
// HOROLOGION_COLORS at your own, or drop one at the path below. The shape is
// MENOLOGION_COLORS at your own, or drop one at the path below. The shape is
// the flat sixteen-colour kind most theme generators already emit.
Singleton {
id: root
readonly property string path: {
const env = Quickshell.env("HOROLOGION_COLORS");
const env = Quickshell.env("MENOLOGION_COLORS");
return env && env !== ""
? env
: Quickshell.env("HOME") + "/.config/horologion/colors.json";
: Quickshell.env("HOME") + "/.config/menologion/colors.json";
}
property var c: ({})
+1 -1
View File
@@ -1,3 +1,3 @@
module horologion.services
module menologion.services
singleton Typikon 1.0 Typikon.qml
singleton Theme 1.0 Theme.qml
+3 -3
View File
@@ -11,7 +11,7 @@ import "services"
// A runnable widget on its own — `quickshell -p quickshell/shell.qml`.
//
// It sits on the background layer, so it behaves like part of the wallpaper:
// always under your windows, never stealing a click. Drop the Horologion
// always under your windows, never stealing a click. Drop the Menologion
// component into an existing shell instead if you already have one.
ShellRoot {
Variants {
@@ -22,7 +22,7 @@ ShellRoot {
screen: modelData
WlrLayershell.layer: WlrLayer.Background
WlrLayershell.namespace: "horologion"
WlrLayershell.namespace: "menologion"
exclusionMode: ExclusionMode.Ignore
color: "transparent"
@@ -36,7 +36,7 @@ ShellRoot {
id: content
anchors.fill: parent
Horologion {
Menologion {
// Leave empty to follow `typikon --set-default`, or name a
// jurisdiction here: "rocor", "antiochian", "oca", ...
Component.onCompleted: Typikon.jurisdiction = ""
+2 -2
View File
@@ -22,7 +22,7 @@ ShellRoot {
screen: Quickshell.screens[0]
WlrLayershell.layer: WlrLayer.Overlay
WlrLayershell.namespace: "horologion-shot"
WlrLayershell.namespace: "menologion-shot"
exclusionMode: ExclusionMode.Ignore
color: "transparent"
@@ -49,7 +49,7 @@ ShellRoot {
anchors.topMargin: 34
width: Config.width
Horologion {
Menologion {
Component.onCompleted: {
const j = Quickshell.env("SHOT_JURISDICTION");
const d = Quickshell.env("SHOT_DATE");
+4 -4
View File
@@ -9,8 +9,8 @@
set -uo pipefail
root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
waybar="$root/bin/horologion-waybar"
install="$root/bin/horologion-install"
waybar="$root/bin/menologion-waybar"
install="$root/bin/menologion-install"
pass=0 fail=0
tmp="$(mktemp -d)"
trap 'rm -rf "$tmp"' EXIT
@@ -63,9 +63,9 @@ check "--help without typikon" 0 env PATH=/usr/bin:/bin "$install" --
check "an unknown subcommand" 2 "$install" nonsense
mkdir -p "$tmp/a/.config/quickshell" "$tmp/a/.config/waybar"
check "a clean run with eww absent" 0 env HOME="$tmp/a" XDG_CONFIG_HOME="$tmp/a/.config" "$install" all
mkdir -p "$tmp/b/.local/bin" "$tmp/b/.config"; : > "$tmp/b/.local/bin/horologion-waybar"
mkdir -p "$tmp/b/.local/bin" "$tmp/b/.config"; : > "$tmp/b/.local/bin/menologion-waybar"
check "a real file at the target" 1 env HOME="$tmp/b" XDG_CONFIG_HOME="$tmp/b/.config" "$install" all
[ -L "$tmp/a/.local/bin/horologion-waybar" ] \
[ -L "$tmp/a/.local/bin/menologion-waybar" ] \
&& ok "the clean run actually linked" || bad "the clean run actually linked"
echo
+2 -2
View File
@@ -2,8 +2,8 @@
// "custom/typikon", and merge the block below.
{
"custom/typikon": {
"exec": "horologion-waybar",
// Add -j to pin a jurisdiction, e.g. "horologion-waybar -j rocor".
"exec": "menologion-waybar",
// Add -j to pin a jurisdiction, e.g. "menologion-waybar -j rocor".
// Without it, whatever `typikon --set-default` wrote is used.
"return-type": "json",
// The answer changes at midnight and at no other moment, so this is only
+1 -1
View File
@@ -1,4 +1,4 @@
/* horologion — waybar styling for the custom/typikon module.
/* menologion — waybar styling for the custom/typikon module.
*
* The module's class is the fast level, so a day's discipline can be read off
* the colour without reading the text. `.obligatory` is added only where a