calfw capture: smart time prompt (single/multi-day, timed/all-day)

- Start time prompt: empty = all-day, HH:MM = timed
- End prompt: HH:MM (same day), YYYY-MM-DD (multi-day), YYYY-MM-DD HH:MM
- All formats match what ox-icalendar/org-caldav export correctly
- Set org-icalendar-timezone to Europe/Prague
- Set org-icalendar-with-timestamps to active
This commit is contained in:
2026-02-25 15:47:35 +01:00
parent 05516c8e9e
commit 218a38d819

View File

@@ -324,6 +324,11 @@
"* %?\n%(my/calfw-capture-timestamp)\n" "* %?\n%(my/calfw-capture-timestamp)\n"
:empty-lines 1)))) :empty-lines 1))))
;; Ensure ox-icalendar exports active timestamps with times correctly
(after! ox-icalendar
(setq org-icalendar-with-timestamps 'active
org-icalendar-timezone "Europe/Prague"))
;;; ============================================================ ;;; ============================================================
;;; ORG MODE — AGENDA ;;; ORG MODE — AGENDA
@@ -1593,18 +1598,55 @@ Skip for beamer exports — beamer uses adjustbox on plain tabular."
:demand t :demand t
:config :config
;; org-capture integration: "a" to add event on selected date ;; org-capture integration: "a" to add event on selected date
;; Prompts for time range; empty = all-day event ;; Prompts for start/end time; empty = all-day event
;; Uses active timestamp with time range for timed events,
;; or date-range (-->--) for multi-day events.
(defun my/calfw-capture-timestamp () (defun my/calfw-capture-timestamp ()
"Build org timestamp for selected calfw date with optional time prompt." "Build org timestamp for selected calfw date with optional time prompt.
Formats matching what org-caldav/ox-icalendar export correctly:
- All-day single: <2026-02-26 Thu>
- Timed single day: <2026-02-26 Thu 14:00-15:30>
- All-day multi: <2026-02-26 Thu>--<2026-02-28 Sat>
- Timed multi-day: <2026-02-26 Thu 15:00>--<2026-02-28 Sat 22:00>"
(let* ((date (calfw-cursor-to-nearest-date)) (let* ((date (calfw-cursor-to-nearest-date))
(y (calendar-extract-year date)) (y (calendar-extract-year date))
(m (calendar-extract-month date)) (m (calendar-extract-month date))
(d (calendar-extract-day date)) (d (calendar-extract-day date))
(dow (calendar-day-name (encode-time 0 0 0 d m y) nil t)) (dow (calendar-day-name (encode-time 0 0 0 d m y) nil t))
(time (read-string "Time (e.g. 14:00-15:30, empty=all-day): "))) (start-time (read-string "Start time (HH:MM, empty=all-day): "))
(if (string-empty-p time) (end-input (unless (string-empty-p start-time)
(format "<%04d-%02d-%02d %s>" y m d dow) (read-string "End time or end date (HH:MM / YYYY-MM-DD / YYYY-MM-DD HH:MM, empty=same day open): "))))
(format "<%04d-%02d-%02d %s %s>" y m d dow time)))) (cond
;; All-day event (no time given)
((string-empty-p start-time)
(let ((end-date (read-string "End date for multi-day (YYYY-MM-DD, empty=single day): ")))
(if (string-empty-p end-date)
(format "<%04d-%02d-%02d %s>" y m d dow)
(let* ((parsed (parse-time-string (concat end-date " 00:00")))
(ed (nth 3 parsed)) (em (nth 4 parsed)) (ey (nth 5 parsed))
(edow (calendar-day-name (encode-time 0 0 0 ed em ey) nil t)))
(format "<%04d-%02d-%02d %s>--<%04d-%02d-%02d %s>" y m d dow ey em ed edow)))))
;; Timed event - check if end contains a date (multi-day)
((and end-input (not (string-empty-p end-input))
(string-match "^[0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\}" end-input))
;; Multi-day with times
(let* ((end-time-part (if (string-match " \\([0-9]\\{2\\}:[0-9]\\{2\\}\\)" end-input)
(match-string 1 end-input) ""))
(end-date-part (substring end-input 0 10))
(parsed (parse-time-string (concat end-date-part " 00:00")))
(ed (nth 3 parsed)) (em (nth 4 parsed)) (ey (nth 5 parsed))
(edow (calendar-day-name (encode-time 0 0 0 ed em ey) nil t)))
(if (string-empty-p end-time-part)
(format "<%04d-%02d-%02d %s %s>--<%04d-%02d-%02d %s>"
y m d dow start-time ey em ed edow)
(format "<%04d-%02d-%02d %s %s>--<%04d-%02d-%02d %s %s>"
y m d dow start-time ey em ed edow end-time-part))))
;; Same-day timed event with end time (HH:MM)
((and end-input (not (string-empty-p end-input)))
(format "<%04d-%02d-%02d %s %s-%s>" y m d dow start-time end-input))
;; Same-day timed event, no end time
(t
(format "<%04d-%02d-%02d %s %s>" y m d dow start-time)))))
(setq calfw-org-capture-template (setq calfw-org-capture-template
'("c" "Calendar event" entry '("c" "Calendar event" entry