From 63278454f8007cd3352641738c130ed82ca8fe3f Mon Sep 17 00:00:00 2001 From: Arpit Chakladar Date: Sat, 10 Oct 2026 05:37:39 +0530 Subject: feat(office/calcurse)!: deleted calcurse BREAKING CHANGES: removed calcurse module, office.calcurse options won't work anymore --- modules/office/calcurse/assertions.nix | 13 -- modules/office/calcurse/calcurse-sync.sh | 281 ------------------------------- modules/office/calcurse/conf | 42 ----- modules/office/calcurse/default.nix | 154 ----------------- modules/office/calcurse/hooks/post-save | 16 -- modules/office/calcurse/hooks/pre-load | 16 -- modules/office/calcurse/keys | 51 ------ 7 files changed, 573 deletions(-) delete mode 100644 modules/office/calcurse/assertions.nix delete mode 100644 modules/office/calcurse/calcurse-sync.sh delete mode 100644 modules/office/calcurse/conf delete mode 100644 modules/office/calcurse/default.nix delete mode 100644 modules/office/calcurse/hooks/post-save delete mode 100644 modules/office/calcurse/hooks/pre-load delete mode 100644 modules/office/calcurse/keys diff --git a/modules/office/calcurse/assertions.nix b/modules/office/calcurse/assertions.nix deleted file mode 100644 index bd7778e..0000000 --- a/modules/office/calcurse/assertions.nix +++ /dev/null @@ -1,13 +0,0 @@ -# Validates calcurse sub-options require the main module to be enabled -{ config, ... }: -let - cfg = config.office.calcurse; -in -{ - assertions = [ - { - assertion = !cfg.sync.enable || cfg.enable; - message = "office.calcurse.sync.enable requires office.calcurse.enable."; - } - ]; -} diff --git a/modules/office/calcurse/calcurse-sync.sh b/modules/office/calcurse/calcurse-sync.sh deleted file mode 100644 index 737ebfb..0000000 --- a/modules/office/calcurse/calcurse-sync.sh +++ /dev/null @@ -1,281 +0,0 @@ -#!/usr/bin/env bash -# Keeps calcurse's data directory in git, so you can back it up / sync -# it across machines via a remote (e.g. a private GitHub repo). -# -# Usage: -# calcurse-sync init [remote-url] Turn the calcurse data dir into a git -# repo and (optionally) attach a remote. -# Safe to re-run — no-ops if a repo -# already exists. If no remote is given, -# falls back to $CALCURSE_SYNC_REMOTE, -# then (if interactive) a prompt. -# calcurse-sync sync Commit any changes and push. Initializes -# the repo automatically on first run. -# calcurse-sync pull Pull down changes from the remote. -# calcurse-sync status Show git status of the data directory. -# calcurse-sync remote Add/update the remote after the fact. -# calcurse-sync help Show this message. -# -# Defaults to $XDG_DATA_HOME/calcurse (usually ~/.local/share/calcurse). -# Override with $CALCURSE_DATA_DIR if yours lives elsewhere. -# Override the default remote used on first init with $CALCURSE_SYNC_REMOTE. - -set -euo pipefail - -DATA_DIR="${CALCURSE_DATA_DIR:-${XDG_DATA_HOME:-$HOME/.local/share}/calcurse}" -BRANCH="master" -SYNC_TIMEOUT="8" # seconds before a network op gives up - -info() { printf '\033[1;34m==>\033[0m %s\n' "$*"; } -warn() { printf '\033[1;33m==> warning:\033[0m %s\n' "$*" >&2; } -error() { printf '\033[1;31m==> error:\033[0m %s\n' "$*" >&2; } -die() { - error "$*" - exit 1 -} - -require_git() { - command -v git >/dev/null 2>&1 || - die "git is not installed or not on PATH. Install it and try again." -} - -require_data_dir() { - if [ ! -d "$DATA_DIR" ]; then - die "calcurse data directory not found at: $DATA_DIR -Run calcurse at least once so it can create its data files, or set -CALCURSE_DATA_DIR to point at the right location." - fi -} - -require_repo() { - if [ ! -d "$DATA_DIR/.git" ]; then - die "no git repository found in $DATA_DIR -Run 'calcurse-sync init' first to set one up." - fi -} - -repo_exists() { - [ -d "$DATA_DIR/.git" ] -} - -has_remote() { - git -C "$DATA_DIR" remote get-url origin >/dev/null 2>&1 -} - -has_upstream() { - git -C "$DATA_DIR" rev-parse --abbrev-ref --symbolic-full-name '@{u}' >/dev/null 2>&1 -} - -# e.g. "25th May, 2026 at 12:34 PM" -readable_timestamp() { - local day suffix month_year time_part - - day=$(date +%-d) - case "$day" in - 1 | 21 | 31) suffix="st" ;; - 2 | 22) suffix="nd" ;; - 3 | 23) suffix="rd" ;; - *) suffix="th" ;; - esac - - month_year=$(date +"%B, %Y") - time_part=$(date +"%I:%M %p" | sed 's/^0//') - - printf '%s%s %s at %s' "$day" "$suffix" "$month_year" "$time_part" -} - -# Initializes the git repo, makes an initial commit if there's anything to -# commit, and attaches a remote. The remote is resolved in this order: -# explicit arg > $CALCURSE_SYNC_REMOTE > interactive prompt (tty only) > -# skipped. Shared by `init` (explicit/manual) and `sync`/activation -# (automatic, first-run-on-a-new-device). -do_init() { - local remote_url="${1:-${CALCURSE_SYNC_REMOTE:-}}" - - info "No git repository found in $DATA_DIR — initializing one." - git -C "$DATA_DIR" init -b "$BRANCH" >/dev/null - - # calcurse sometimes drops lock/swap files in here; keep them out of git - if [ ! -e "$DATA_DIR/.gitignore" ]; then - cat >"$DATA_DIR/.gitignore" <<'EOF' -*.lock -*.swp -EOF - fi - - git -C "$DATA_DIR" add -A - if ! git -C "$DATA_DIR" diff --cached --quiet; then - git -C "$DATA_DIR" commit -m "sync: $(readable_timestamp)" >/dev/null - info "Created initial commit." - else - warn "Nothing to commit yet (data directory is empty)." - fi - - if [ -z "$remote_url" ] && [ -t 0 ]; then - read -r -p "Remote URL to push to (leave blank to skip): " remote_url - fi - - if [ -n "$remote_url" ]; then - git -C "$DATA_DIR" remote add origin "$remote_url" - info "Pushing initial commit to $remote_url" - if git -C "$DATA_DIR" push -u origin "$BRANCH"; then - info "Repo initialized and pushed." - else - error "Push failed. The remote was still added — check the URL and your" - error "credentials, then try 'calcurse-sync sync' again." - exit 1 - fi - else - warn "No remote configured. This repo will only track history locally" - warn "until you run 'calcurse-sync remote ' (or set CALCURSE_SYNC_REMOTE)." - fi -} - -cmd_init() { - require_git - require_data_dir - - if repo_exists; then - info "Repository already exists in $DATA_DIR — nothing to do." - return 0 - fi - - do_init "${1:-}" -} - -cmd_remote() { - require_git - require_repo - - local url="${1:-}" - [ -n "$url" ] || die "usage: calcurse-sync remote " - - if has_remote; then - git -C "$DATA_DIR" remote set-url origin "$url" - info "Updated remote 'origin' to $url" - else - git -C "$DATA_DIR" remote add origin "$url" - info "Added remote 'origin' pointing to $url" - fi -} - -cmd_sync() { - require_git - require_data_dir - - if ! repo_exists; then - do_init - return 0 - fi - - cd "$DATA_DIR" - git add -A - - if ! git diff --cached --quiet; then - git commit -m "sync: $(readable_timestamp)" >/dev/null - info "Committed changes." - else - info "No local changes to commit." - fi - - if ! has_remote; then - warn "No remote configured for this repo — commit saved locally only." - warn "Run 'calcurse-sync remote ' to enable pushing." - return 0 - fi - - if has_upstream && [ -z "$(git log '@{u}..HEAD' --oneline)" ]; then - info "Already up to date with the remote." - return 0 - fi - - info "Pushing to remote..." - if has_upstream; then - push_cmd=(timeout "$SYNC_TIMEOUT" git push) - else - push_cmd=(timeout "$SYNC_TIMEOUT" git push -u origin "$BRANCH") - fi - - if "${push_cmd[@]}"; then - info "Sync complete." - else - status=$? - if [ "$status" -eq 124 ]; then - warn "Push timed out after ${SYNC_TIMEOUT}s — commit saved locally, will" - warn "retry on next sync." - return 0 - fi - error "Push failed." - error "This usually means the remote has commits you don't have locally" - error "(e.g. synced from another machine). Run 'calcurse-sync pull'" - error "to merge them in, then sync again. If that's not it, check your" - error "network connection and git credentials." - exit "$status" - fi -} - -cmd_pull() { - require_git - require_data_dir - require_repo - - if ! has_remote; then - warn "no remote configured for this repo — skipping pull." - return 0 - fi - - cd "$DATA_DIR" - - if [ -n "$(git status --porcelain)" ]; then - warn "You have uncommitted changes in $DATA_DIR." - warn "Run 'calcurse-sync sync' first so a pull can't clobber them." - die "aborting pull to avoid data loss." - fi - - info "Pulling from remote (timeout ${SYNC_TIMEOUT}s)..." - if timeout "$SYNC_TIMEOUT" git pull --rebase origin "$BRANCH"; then - info "Up to date." - else - status=$? - if [ "$status" -eq 124 ]; then - warn "Pull timed out after ${SYNC_TIMEOUT}s — continuing with local data." - warn 'Set $CALCURSE_SYNC_TIMEOUT to a higher value if your connection' - warn "is just slow, not down." - return 0 - fi - error "Pull failed — likely a merge conflict." - error "Resolve conflicts manually in $DATA_DIR, then run:" - error " git -C \"$DATA_DIR\" rebase --continue" - error "(or 'git rebase --abort' to back out)." - exit 1 - fi -} - -cmd_status() { - require_git - require_data_dir - require_repo - - git -C "$DATA_DIR" status -} - -cmd_help() { - sed -n '2,20p' "$0" | sed 's/^# \{0,1\}//' -} - -main() { - local sub="${1:-help}" - shift || true - - case "$sub" in - init) cmd_init "$@" ;; - sync) cmd_sync "$@" ;; - pull) cmd_pull "$@" ;; - status) cmd_status "$@" ;; - remote) cmd_remote "$@" ;; - help | -h | --help) cmd_help ;; - *) die "unknown command: $sub (try 'calcurse-sync help')" ;; - esac -} - -main "$@" diff --git a/modules/office/calcurse/conf b/modules/office/calcurse/conf deleted file mode 100644 index 1868cc6..0000000 --- a/modules/office/calcurse/conf +++ /dev/null @@ -1,42 +0,0 @@ -# Appearance -appearance.calendarview=monthly -appearance.compactpanels=no -appearance.defaultpanel=calendar -appearance.layout=1 -appearance.headerline=yes -appearance.eventseparator=yes -appearance.dayseparator=yes -appearance.emptyline=yes -appearance.emptyday=-- -appearance.notifybar=yes -appearance.sidebarwidth=0 -appearance.theme=green on black -appearance.todoview=show-completed -appearance.headingpos=right-justified - -# Daemon -daemon.enable=yes -daemon.log=no - -# Format -format.inputdate=2 -format.notifydate=%a %F -format.notifytime=%T -format.appointmenttime=%H:%M -format.outputdate=%D -format.dayheading=%B %e, %Y - -# General -general.autogc=yes -general.autosave=yes -general.confirmdelete=yes -general.confirmquit=no -general.firstdayofweek=monday -general.multipledays=yes -general.periodicsave=0 -general.systemevents=yes - -# Notification -notification.warning=300 -notification.command=notify-send -a calcurse -i "@@CALCURSE_ICON@@" -u critical "Calcurse" "$(calcurse -n | tail -1 | cut -d ' ' -f5-)" -notification.notifyall=flagged-only diff --git a/modules/office/calcurse/default.nix b/modules/office/calcurse/default.nix deleted file mode 100644 index 0555ec6..0000000 --- a/modules/office/calcurse/default.nix +++ /dev/null @@ -1,154 +0,0 @@ -# Text-based calendar and scheduling application -{ - config, - lib, - pkgs, - ... -}: -let - cfg = config.office.calcurse; - icons = config.desktop.icons.apps; - - calcurseSync = pkgs.writeShellScriptBin "calcurse-sync" (builtins.readFile ./calcurse-sync.sh); - - calcurse = pkgs.symlinkJoin { - name = "calcurse-wrapped"; - paths = [ - config.terminal.bash.package - pkgs.calcurse - pkgs.libnotify - ] - ++ lib.optionals config.development.nixvim.enable [ config.development.nixvim.package ] - ++ lib.optionals cfg.sync.enable [ calcurseSync ]; - nativeBuildInputs = [ pkgs.makeWrapper ]; - postBuild = '' - ${lib.optionalString config.development.nixvim.enable '' - wrapProgram $out/bin/calcurse --set PAGER "nvim" - ''} - ${lib.optionalString cfg.sync.enable '' - wrapProgram $out/bin/calcurse-sync \ - --prefix PATH : ${ - lib.makeBinPath [ - config.development.git.package - pkgs.coreutils - pkgs.gnused - ] - } \ - ${lib.optionalString (cfg.sync.remote != null) '' - --set CALCURSE_SYNC_REMOTE ${lib.escapeShellArg cfg.sync.remote} - ''} - ''} - ''; - meta = { - mainProgram = "calcurse"; - }; - }; -in -{ - imports = [ ./assertions.nix ]; - - options.office.calcurse = { - enable = lib.mkEnableOption "Enables calcurse."; - package = lib.mkOption { - type = lib.types.package; - readOnly = true; - default = calcurse; - description = "The calcurse package to use."; - }; - sync = lib.mkOption { - type = lib.types.submodule { - options = { - enable = lib.mkEnableOption "Enables git-backed syncing of the calcurse data directory (builds calcurse-sync, installs the sync hooks, and runs an initial 'calcurse-sync init' on activation)."; - remote = lib.mkOption { - type = lib.types.nullOr lib.types.str; - default = null; - description = "Git remote URL for the calcurse data directory. Use an https:// URL if 'credential' is configured. When set, calcurse-sync uses it automatically on first init instead of prompting."; - }; - credential = lib.mkOption { - type = lib.types.submodule { - options = { - username = lib.mkOption { - type = lib.types.nullOr lib.types.str; - default = null; - description = "Username for HTTPS git authentication against the calcurse remote."; - }; - password-gopass-secret = lib.mkOption { - type = lib.types.nullOr lib.types.str; - default = null; - description = "gopass entry path holding the password or token used for HTTPS git authentication against the calcurse remote. E.g. 'git/calcurse-sync'."; - }; - }; - }; - default = { }; - description = "Credentials for HTTPS git authentication."; - }; - }; - }; - default = { }; - description = "Git-backed syncing configuration."; - }; - }; - - config = lib.mkMerge [ - (lib.mkIf cfg.enable { - home.packages = [ cfg.package ]; - xdg.configFile."calcurse/conf" = { - text = builtins.replaceStrings [ "@@CALCURSE_ICON@@" ] [ icons.calcurse ] ( - builtins.readFile ./conf - ); - force = true; - }; - xdg.configFile."calcurse/keys" = { - source = ./keys; - force = true; - }; - }) - (lib.mkIf (cfg.enable && config.terminal.kitty.enable) { - xdg.desktopEntries."calcurse" = { - name = "calcurse"; - exec = "${lib.getExe config.terminal.kitty.package} --class calcurse -e ${lib.getExe cfg.package}"; - icon = icons.calcurse; - categories = [ - "Office" - "Calendar" - ]; - comment = "Text-based calendar and scheduling application"; - terminal = false; - type = "Application"; - }; - }) - (lib.mkIf cfg.sync.enable { - xdg.configFile."calcurse/hooks/pre-load" = { - source = ./hooks/pre-load; - executable = true; - force = true; - }; - xdg.configFile."calcurse/hooks/post-save" = { - source = ./hooks/post-save; - executable = true; - force = true; - }; - - programs.git.includes = lib.mkIf config.development.git.enable [ - { - condition = "gitdir:${config.xdg.dataHome}/calcurse/"; - contents = { - user = { - name = "Calcurse of ${config.home.username}"; - email = "${config.home.username}@calcurse.localhost"; - }; - commit.gpgSign = false; - tag.gpgSign = false; - } - // lib.optionalAttrs (cfg.sync.credential.password-gopass-secret != null) { - credential.helper = "!f() { echo username=${lib.escapeShellArg cfg.sync.credential.username}; echo password=\"$(${lib.getExe config.security.gopass.package} show -o ${lib.escapeShellArg cfg.sync.credential.password-gopass-secret})\"; }; f"; - }; - } - ]; - - home.activation.calcurseSyncInit = lib.hm.dag.entryAfter [ "writeBoundary" ] '' - run ${lib.getExe cfg.package} init || true - ''; - }) - ]; -} diff --git a/modules/office/calcurse/hooks/post-save b/modules/office/calcurse/hooks/post-save deleted file mode 100644 index 5d2ab1d..0000000 --- a/modules/office/calcurse/hooks/post-save +++ /dev/null @@ -1,16 +0,0 @@ -#!/usr/bin/env bash -# Commits and pushes the calcurse data dir after every save. -# -# Hooks hand calcurse's terminal over to whatever they run and calcurse -# waits for them to exit before redrawing, so this backgrounds the actual -# sync instead of blocking the UI on a git push. Output goes to a log -# file rather than stdout/stderr, since hooks aren't meant to be -# interactive. - -log="${XDG_DATA_HOME:-$HOME/.local/share}/calcurse/hooks.log" - -( - printf '[%s] post-save\n' "$(date '+%Y-%m-%d %H:%M:%S')" - calcurse-sync sync -) >>"$log" 2>&1 & -disown diff --git a/modules/office/calcurse/hooks/pre-load b/modules/office/calcurse/hooks/pre-load deleted file mode 100644 index bd87af3..0000000 --- a/modules/office/calcurse/hooks/pre-load +++ /dev/null @@ -1,16 +0,0 @@ -#!/usr/bin/env bash -# Pulls the latest calcurse data before calcurse reads it, so a fresh -# session (or a ^R reload) starts from wherever you last left off on -# another machine. -# -# Runs synchronously, unlike post-save, since the point is to have -# up-to-date data before it's loaded. Never fails calcurse's startup, -# though: if the pull can't complete (offline, no remote configured -# yet, a conflict), calcurse just opens with whatever's on disk. - -log="${XDG_DATA_HOME:-$HOME/.local/share}/calcurse/hooks.log" - -{ - printf '[%s] pre-load\n' "$(date '+%Y-%m-%d %H:%M:%S')" - calcurse-sync pull -} >>"$log" 2>&1 || true diff --git a/modules/office/calcurse/keys b/modules/office/calcurse/keys deleted file mode 100644 index eab415b..0000000 --- a/modules/office/calcurse/keys +++ /dev/null @@ -1,51 +0,0 @@ -# Calcurse keys configuration file - vim-like bindings -# actions and valid keys; bindings are `action key1 key2 ...` lines. - -generic-cancel ESC -generic-select SPC -generic-credits @ -generic-help ? -generic-quit q -generic-save w -generic-reload R -generic-copy y -generic-paste p -generic-change-view TAB -generic-prev-view KEY_BTAB -generic-import i -generic-export x -generic-goto g -generic-other-cmd O -generic-config-menu C -generic-redraw ^R -generic-add-appt A -generic-add-todo I -generic-prev-day H -generic-next-day L -generic-prev-week K -generic-next-week J -generic-prev-month ^H -generic-next-month ^L -generic-prev-year ^K -generic-next-year ^J -generic-scroll-down ^D -generic-scroll-up ^U -generic-goto-today G -generic-command : -move-right l -move-left h -move-down j -move-up k -start-of-week 0 -end-of-week $ -add-item a -del-item d -edit-item e -view-item v -pipe-item | -flag-item ! -repeat . -edit-note n -view-note > -raise-priority + -lower-priority - -- cgit v1.2.3