diff --git a/config.el b/config.el index b5f4490..1685ad5 100644 --- a/config.el +++ b/config.el @@ -1744,38 +1744,59 @@ current frame." org-caldav-files '("~/org/personal.org" "~/org/work.org") org-caldav-sync-direction 'twoway) - ;; Baikal uses Digest auth. Pre-register credentials from ~/.authinfo - ;; so Emacs url package doesn't prompt interactively. - (defun my/caldav-setup-digest-auth () - "Pre-register Baikal Digest auth. HA1 = MD5(user:realm:pass) from authinfo. -Falls back to hardcoded hash if auth-source lookup fails. -url-digest-auth-storage format: ((\"server:port\" (\"realm\" user ha1)) ...)" - (require 'url-auth) - (let* ((user "martin") - (realm "BaikalDAV") - (server "cal.apps.sukany.cz:443") - (found (car (auth-source-search :host "cal.apps.sukany.cz" - :user user :max 1))) - (pass (when found - (let ((s (plist-get found :secret))) - (if (functionp s) (funcall s) s)))) - ;; Compute HA1 from authinfo password, or use pre-computed fallback - (ha1 (if pass - (md5 (concat user ":" realm ":" pass)) - ;; Fallback: MD5("martin:BaikalDAV:treasure-Hunter") - "7cf9c41c78f4986fd65948029bcc4743"))) - (if (boundp 'url-digest-auth-storage) - ;; Modern Emacs: inject into url-digest-auth-storage - (setq url-digest-auth-storage - (list (list server (list realm user ha1)))) - ;; Older Emacs: warn and skip - (message "org-caldav: url-digest-auth-storage not available, auth may fail")))) + (defun my/caldav-get-password (host user) + "Fetch plaintext password from auth-source for HOST and USER." + (let* ((found (car (auth-source-search :host host :user user :max 1))) + (s (when found (plist-get found :secret)))) + (when s (if (functionp s) (funcall s) s)))) + + (defun my/caldav-register-digest (user realm server plaintext-pass) + "Register Digest auth for USER@SERVER with realm REALM. +Stores HA1 = MD5(user:realm:pass) in url-digest-auth-storage." + (when (and (boundp 'url-digest-auth-storage) plaintext-pass) + (let ((ha1 (md5 (concat user ":" realm ":" plaintext-pass)))) + (setf (alist-get server url-digest-auth-storage nil nil #'equal) + (list (list realm user ha1)))))) (defun my/org-caldav-sync () - "Sync org-caldav after pre-registering Baikal Digest auth." + "Sync org-caldav: personal calendar (twoway) + family calendar (read-only)." (interactive) - (my/caldav-setup-digest-auth) - (org-caldav-sync))) + (require 'url-auth) + (let* ((host "cal.apps.sukany.cz") + (realm "BaikalDAV") + (srv "cal.apps.sukany.cz:443") + ;; Get passwords from ~/.authinfo: + ;; machine cal.apps.sukany.cz login martin password PASS + ;; machine cal.apps.sukany.cz login family password PASS + (pass-m (my/caldav-get-password host "martin")) + (pass-f (my/caldav-get-password host "family"))) + + ;; Fallback: pre-computed HA1 for martin if authinfo missing + (if pass-m + (my/caldav-register-digest "martin" realm srv pass-m) + (when (boundp 'url-digest-auth-storage) + (setf (alist-get srv url-digest-auth-storage nil nil #'equal) + (list (list realm "martin" "7cf9c41c78f4986fd65948029bcc4743"))))) + + ;; Sync personal calendar (twoway — new events go here) + (setq org-caldav-url "https://cal.apps.sukany.cz/dav.php/calendars/martin" + org-caldav-calendar-id "default" + org-caldav-inbox "~/org/caldav-inbox.org" + org-caldav-files '("~/org/personal.org" "~/org/work.org") + org-caldav-sync-direction 'twoway) + (org-caldav-sync) + + ;; Sync family calendar (fromcal = read-only, no writes back) + (when pass-f + (my/caldav-register-digest "family" realm srv pass-f)) + (setq org-caldav-url "https://cal.apps.sukany.cz/dav.php/calendars/family" + org-caldav-calendar-id "default" + org-caldav-inbox "~/org/family-calendar.org" + org-caldav-files nil + org-caldav-sync-direction 'fromcal) + (org-caldav-sync) + + (message "CalDAV sync complete: personal (twoway) + family (read-only)")))) (map! :leader "o c" #'my/org-caldav-sync) diff --git a/scripts/macos-install.sh b/scripts/macos-install.sh new file mode 100755 index 0000000..d67beb5 --- /dev/null +++ b/scripts/macos-install.sh @@ -0,0 +1,218 @@ +#!/usr/bin/env bash +# macos-install.sh — Bootstrap Doom Emacs development environment on macOS +# Run once on a fresh machine. Idempotent — safe to re-run. +# Usage: bash scripts/macos-install.sh + +set -euo pipefail + +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +RED='\033[0;31m' +NC='\033[0m' + +info() { echo -e "${GREEN}▶${NC} $*"; } +warn() { echo -e "${YELLOW}⚠${NC} $*"; } +error() { echo -e "${RED}✗${NC} $*"; } +section() { echo -e "\n${GREEN}══ $* ══${NC}"; } + +# ─── Homebrew ─────────────────────────────────────────────────────────────── +section "Homebrew" +if ! command -v brew &>/dev/null; then + info "Installing Homebrew..." + /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" +else + info "Homebrew already installed" +fi + +# ─── Core GNU tools (Doom prefers GNU over BSD) ────────────────────────────── +section "Core GNU tools" +brew install --quiet \ + coreutils \ + gnu-sed \ + findutils \ + grep \ + git \ + curl \ + wget \ + jq + +# ─── Doom Emacs prerequisites ──────────────────────────────────────────────── +section "Doom Emacs prerequisites" +brew install --quiet \ + cmake \ + libtool \ + automake \ + autoconf \ + pkg-config \ + texinfo \ + sqlite \ + tree-sitter + +# ─── Emacs (if not already installed) ─────────────────────────────────────── +section "Emacs" +if ! command -v emacs &>/dev/null; then + warn "Emacs not found. Install manually:" + warn " brew install --cask emacs # pre-built GUI" + warn " OR build from source with MacPorts/Homebrew for latest patches" +else + info "Emacs: $(emacs --version | head -1)" +fi + +# ─── Search tools (Doom/Vertico/Consult use these) ─────────────────────────── +section "Search & navigation tools" +brew install --quiet \ + fd \ + ripgrep \ + fzf \ + bat \ + the_silver_searcher + +# ─── Spell & grammar ───────────────────────────────────────────────────────── +section "Spell & grammar" +brew install --quiet \ + ispell \ + languagetool + +# ─── Email (mu4e + mbsync) ─────────────────────────────────────────────────── +section "Email — mu4e" +brew install --quiet \ + mu \ + isync + +# ─── PDF tools ─────────────────────────────────────────────────────────────── +section "PDF tools" +brew install --quiet \ + poppler \ + mupdf-tools + +# ─── Fonts (Doom uses nerd-fonts) ──────────────────────────────────────────── +section "Fonts" +brew install --quiet --cask \ + font-jetbrains-mono-nerd-font \ + font-fira-code-nerd-font \ + 2>/dev/null || warn "Font casks may need manual install from nerd-fonts" + +# ─── Perl ──────────────────────────────────────────────────────────────────── +section "Perl" +brew install --quiet perl + +# Install cpanm +if ! command -v cpanm &>/dev/null; then + info "Installing cpanm..." + curl -L https://cpanmin.us | perl - App::cpanminus +fi + +info "Installing Perl modules (LSP, Tidy, Critic)..." +cpanm --quiet --notest \ + Perl::LanguageServer \ + Perl::Tidy \ + Perl::Critic \ + App::perlimports \ + 2>/dev/null || warn "Some Perl modules failed — run cpanm manually if needed" + +# ─── Python ────────────────────────────────────────────────────────────────── +section "Python" +brew install --quiet \ + python \ + pyenv \ + ruff \ + uv + +# Pyright LSP +if ! command -v pyright &>/dev/null; then + info "Installing pyright..." + npm install -g pyright 2>/dev/null || warn "npm not found, install node first: brew install node" +fi + +# ─── Go ────────────────────────────────────────────────────────────────────── +section "Go" +brew install --quiet go + +info "Installing Go tools..." +go install golang.org/x/tools/gopls@latest 2>/dev/null || warn "gopls install failed" +go install golang.org/x/tools/cmd/goimports@latest 2>/dev/null || warn "goimports install failed" +go install github.com/go-delve/delve/cmd/dlv@latest 2>/dev/null || warn "delve install failed" + +# ─── Node.js (needed for some LSPs) ───────────────────────────────────────── +section "Node.js" +brew install --quiet node + +# ─── Ansible ───────────────────────────────────────────────────────────────── +section "Ansible" +brew install --quiet \ + ansible \ + ansible-lint + +# ─── Terraform ─────────────────────────────────────────────────────────────── +section "Terraform" +brew install --quiet \ + terraform \ + terraform-ls \ + tflint + +# ─── Containers (Podman) ───────────────────────────────────────────────────── +section "Podman / Containers" +brew install --quiet \ + podman \ + hadolint + +# ─── Kubernetes ────────────────────────────────────────────────────────────── +section "Kubernetes tools" +brew install --quiet \ + kubectl \ + kubectx + +# ─── Version control extras ────────────────────────────────────────────────── +section "Git extras" +brew install --quiet \ + git-delta \ + gh + +# ─── perltidy config (if missing) ──────────────────────────────────────────── +section "perltidy config" +if [ ! -f "$HOME/.perltidyrc" ]; then + info "Creating ~/.perltidyrc..." + cat > "$HOME/.perltidyrc" << 'PERLTIDY' +-l=100 +-i=4 +-ci=4 +-ce +-vt=0 +-cti=0 +-pt=0 +-bt=0 +-sbt=0 +-bbt=0 +-nsfs +-nolq +PERLTIDY +fi + +# ─── Doom Emacs setup ──────────────────────────────────────────────────────── +section "Doom Emacs" +if [ ! -d "$HOME/.emacs.d" ]; then + warn "Doom not installed. To install:" + warn " git clone --depth 1 https://github.com/doomemacs/doomemacs ~/.emacs.d" + warn " ~/.emacs.d/bin/doom install" +elif [ ! -d "$HOME/.doom.d" ]; then + warn "~/.doom.d missing. Clone your config:" + warn " git clone https://git.apps.sukany.cz/martin/emacs-doom ~/.doom.d" + warn " git clone https://git.apps.sukany.cz/martin/emacs-org ~/org" + warn " ~/.emacs.d/bin/doom sync" +else + info "Doom config found at ~/.doom.d" + info "Run: ~/.emacs.d/bin/doom sync" +fi + +# ─── Summary ───────────────────────────────────────────────────────────────── +section "Done" +echo "" +echo "Manual steps remaining:" +echo " 1. Create ~/.authinfo with CalDAV credentials" +echo " machine cal.apps.sukany.cz login martin password YOUR_PASS" +echo " 2. Configure mbsync: cp ~/.doom.d/examples/mbsyncrc ~/.mbsyncrc" +echo " 3. If Emacs built from source: sudo port install texinfo tree-sitter" +echo " 4. doom sync (in ~/.doom.d)" +echo " 5. doom doctor (check for remaining issues)" +echo "" +info "Installation complete."