Rostgaard.IT

← Home

Using Nextcloud calendar in Emacs

created: Wed Oct 21 2020

If you don't care about an introduction to my issue, please click here to get to the implementation details.

So, having recently bought a new computer, I decided to install Arch and get Doom emacs up and running probably. The problem (mostly with Arch) is that I couldn't find any

Implementation #

The problem is that we want emacs-calfw to support caldav, which is the format we get from the Nextcloud server. This is a 'easy' fix by using org-caldav

# For doom emacs this to your ~/.doom.d/packages.el  
(package! org-caldav)


# ~/.doom.d/config.el
(use-package org-caldav
:init
;; This is the sync on close function; it also prompts for save after syncing so
;; no late changes get lost
(defun org-caldav-sync-at-close ()
(org-caldav-sync)
(save-some-buffers))

;; This is the delayed sync function; it waits until emacs has been idle for
;; "secs" seconds before syncing. The delay is important because the caldav-sync
;; can take five or ten seconds, which would be painful if it did that right at save.
;; This way it just waits until you've been idle for a while to avoid disturbing
;; the user.
(defvar org-caldav-sync-timer nil
"Timer that `org-caldav-push-timer' used to reschedule itself, or nil.")
(defun org-caldav-sync-with-delay (secs)
(when org-caldav-sync-timer
(cancel-timer org-caldav-sync-timer))
(setq org-caldav-sync-timer
(run-with-idle-timer
(* 1 secs) nil 'org-caldav-sync)))

;; Actual calendar configuration edit this to meet your specific needs
(setq org-caldav-url "https://[SERVER]/remote.php/dav/calendars/[USERNAME]/")
(setq org-caldav-calendars
'((:calendar-id "personal"
:files ("~/location/for/calendar/personal-cal.org")
:inbox "~/location/for/calendar/personal-caldav-inbox.org")))
(setq org-caldav-backup-file "~/location/for/calendar/org-caldav/org-caldav-backup.org")
(setq org-caldav-save-directory "~/location/for/calendar/org-caldav/")

:config
(setq org-icalendar-alarm-time 1)
;; This makes sure to-do items as a category can show up on the calendar
(setq org-icalendar-include-todo t)
;; This ensures all org "deadlines" show up, and show up as due dates
(setq org-icalendar-use-deadline '(event-if-todo event-if-not-todo todo-due))
;; This ensures "scheduled" org items show up, and show up as start times
(setq org-icalendar-use-scheduled '(todo-start event-if-todo event-if-not-todo))
;; Add the delayed save hook with a five minute idle timer
(add-hook 'after-save-hook
(lambda ()
(when (eq major-mode 'org-mode)
(org-caldav-sync-with-delay 300))))
;; Add the close emacs hook
(add-hook 'kill-emacs-hook 'org-caldav-sync-at-close)

To avoid having to write username and password in everytime you want to sync a new session you can create or edit a .netrc file in your home directory (documentation):

vim ~/.netrc

and then write:

machine https://[SERVER-URL]/ # e.g: https://cloud.example.net/
login [username]
password [password]

Then you run:

M-x org-caldav-sync

to sync your appointmens with your inbox.

Now look at your ~/location/for/calendar/personal-caldav-inbox.org file and check that the file has been updated with your calendar details.

We now need to let emacs-calfw know about out new org files (which it can read). To do this, add this config.el file:

(defun my-open-calendar ()
(interactive)
(cfw:open-calendar-buffer
:contents-sources
(list
(cfw:org-create-source "Green") ; org-agenda source
;(cfw:ical-create-source "nextcloud" "https://cloud.rostgaard.it/remote.php/dav/calendars/root/personal?export" "IndianRed") ; google calendar ICS
(cfw:ical-create-source "nextcloud" "https://cloud.rostgaard.it/remote.php/dav/calendars/root/personal" "IndianRed") ; google calendar ICS
;(cfw:ical-create-source "gcal" "https://..../basic.ics" "IndianRed") ; google calendar ICS
)))

And because in denmark the work week starts monday I want to show monday as the first day:

(setq calendar-day-name-array
["Monday" "Tuesday" "Wednesday" "Thursday" "Friday" "Saturday" "Sunday"])

← Home