Add a read-only 42-day occurrence agenda with keyboard navigation, six-week paging, exact return-to-grid focus, search and calendar overlays, and bounded recurrence expansion. Keep agenda state outside persistence, document month-only mutations, and cover empty windows, filtering, overlays, navigation, rendering, and terminal restoration.
78 lines
4.1 KiB
Markdown
78 lines
4.1 KiB
Markdown
# Nocal
|
|
|
|
Nocal is a fast, local-first C++20 month calendar designed for the Linux
|
|
terminal and Hyprland. It presents appointments inside a six-week month grid and
|
|
inherits its colors from your terminal theme.
|
|
|
|
This repository currently contains the first local-calendar vertical slice:
|
|
date/domain logic, guarded atomic iCalendar persistence, add/edit/delete forms,
|
|
a responsive ANSI terminal UI with month and agenda views, tests, and Linux
|
|
launch integration. See [the product specification](docs/PRODUCT.md),
|
|
[architecture](docs/ARCHITECTURE.md), and [roadmap](docs/ROADMAP.md).
|
|
|
|
## Controls
|
|
|
|
Use arrow keys or `h j k l` to move, `PageUp`/`PageDown` or `p`/`n` to change
|
|
month, and `t` for today. On a day with appointments, `Tab` and `Shift-Tab`
|
|
move focus through them and `Enter` opens the appointment reader. In the
|
|
reader, arrows/Vim keys or Tab variants browse the day's appointments and
|
|
`Esc` returns to the month. Press `g` to open a read-only 42-day agenda starting
|
|
on the selected date. Arrows, `j`/`k`, or Tab variants choose an occurrence;
|
|
`Enter` returns to the month at that exact occurrence. `PageUp`/`PageDown` or
|
|
`p`/`n` shift the agenda by 42 days, while `Esc` or `g` returns without changing
|
|
the month selection. Press `c` to open the calendar picker; arrows or
|
|
`j`/`k` select a calendar and `Enter` toggles its in-session visibility. Press
|
|
`a` to add an appointment. Focus an
|
|
appointment and press `e` to edit it or `d` to delete it. Forms use `Tab` and
|
|
`Shift-Tab` (or arrows) between fields, `Space` for the all-day toggle,
|
|
`Ctrl-S` to save, and `Esc` to cancel. Back in the calendar, `u` undoes the
|
|
last successful mutation and `Ctrl-R` redoes it. Press `/` to search titles,
|
|
descriptions, locations, and calendar IDs. Search results use arrows or
|
|
`j`/`k`; `Enter` jumps to the exact occurrence and `Esc` returns to the month.
|
|
The calendar picker and search are also available over the agenda with `c` and
|
|
`/`. Add, edit, and delete remain month-view workflows.
|
|
Press `?` for help and `q` to quit.
|
|
|
|
## Build and run
|
|
|
|
```sh
|
|
nix-shell --run 'meson setup build && meson compile -C build'
|
|
./build/nocal --demo
|
|
```
|
|
|
|
Run the tests with `meson test -C build --print-errorlogs`. Nocal reads
|
|
`$XDG_DATA_HOME/nocal/calendar.ics` by default (falling back to
|
|
`~/.local/share/nocal/calendar.ics`), or accepts another `.ics` path as its
|
|
positional argument. `--demo` adds a few unsaved sample appointments and
|
|
`--print` emits a non-interactive frame.
|
|
|
|
Nocal expands and safely round-trips a focused iCalendar recurrence subset:
|
|
daily, weekly, monthly, and yearly rules with interval, count or until, common
|
|
weekly/monthly/yearly selectors, `EXDATE`, floating times, UTC, and system IANA
|
|
`TZID` names. Recurring instances are individually navigable; edit and delete
|
|
clearly operate on the entire series.
|
|
|
|
Search expands recurring matches within five years on either side of the
|
|
currently selected date. This finite window keeps unbounded recurrence rules
|
|
responsive while one-time and recurring results share the same chronological
|
|
result list. Agenda recurrence expansion is bounded to its visible 42-day
|
|
window. Hidden calendars are excluded consistently from the month grid,
|
|
agenda, appointment focus, and search. Visibility and agenda position are
|
|
session-only presentation state; saves always retain events from hidden
|
|
calendars.
|
|
|
|
Calendars containing features this version cannot preserve—such as `RDATE`,
|
|
detached recurrence overrides, ordinal `BYDAY`, embedded `VTIMEZONE`
|
|
definitions, alarms, or attendees—remain browsable but read-only. This guard
|
|
prevents a local edit from silently discarding unknown data.
|
|
|
|
Every replacement checks that the source has not changed since it was loaded.
|
|
If another Nocal instance or an external editor changes the file, the mutation
|
|
is rejected and the in-memory change is rolled back. Successful replacements
|
|
retain the immediately previous bytes as `calendar.ics.bak`. Run
|
|
`nocal --restore-backup [CALENDAR.ics]` for an explicit, atomic recovery; the
|
|
backup itself is kept so recovery can be repeated.
|
|
|
|
For a popup calendar binding and version-specific Hyprland rules, see
|
|
[Hyprland integration](docs/HYPRLAND.md).
|