From d579633ff9915a8f4058d5c439281097e92380a8 Mon Sep 17 00:00:00 2001 From: Felipe Silva Date: Sun, 3 Mar 2024 14:12:42 -0300 Subject: [PATCH] khal: fix contact integration (#4836) * khal: fix contact integration - Add tests for contact+khal - Make options `color`/`priority` available for contact accounts * khal: add separate calendar for each contact collection A contact account may have multiple VCARD collections, but Khal doesn't search recursively. Collection folder names must be hardcoded, and each has its own calendar. - Add khal.collections option for contact accounts - Default to previous setup for accounts with a single collection - Add tests * khal: specify how priority is defined by Khal See https://khal.readthedocs.io/en/latest/configure.html --- modules/accounts/contacts.nix | 1 + modules/programs/khal-accounts.nix | 34 +++++++++++++++++++ modules/programs/khal-calendar-accounts.nix | 34 ------------------- modules/programs/khal-contact-accounts.nix | 15 ++++++++ modules/programs/khal.nix | 23 ++++++++++--- tests/modules/programs/khal/config.nix | 30 ++++++++++++++++ .../programs/khal/khal-config-expected | 21 ++++++++++++ 7 files changed, 120 insertions(+), 38 deletions(-) create mode 100644 modules/programs/khal-contact-accounts.nix diff --git a/modules/accounts/contacts.nix b/modules/accounts/contacts.nix index 83f57d8e2..272594b18 100644 --- a/modules/accounts/contacts.nix +++ b/modules/accounts/contacts.nix @@ -126,6 +126,7 @@ in { contactOpts (import ../programs/vdirsyncer-accounts.nix) (import ../programs/khal-accounts.nix) + (import ../programs/khal-contact-accounts.nix) ]); default = { }; description = "List of contacts."; diff --git a/modules/programs/khal-accounts.nix b/modules/programs/khal-accounts.nix index ad94adc99..cf04a65c0 100644 --- a/modules/programs/khal-accounts.nix +++ b/modules/programs/khal-accounts.nix @@ -13,5 +13,39 @@ with lib; Keep khal from making any changes to this account. ''; }; + + color = mkOption { + type = types.nullOr (types.enum [ + "black" + "white" + "brown" + "yellow" + "dark gray" + "dark green" + "dark blue" + "light gray" + "light green" + "light blue" + "dark magenta" + "dark cyan" + "dark red" + "light magenta" + "light cyan" + "light red" + ]); + default = null; + description = '' + Color in which events in this calendar are displayed. + ''; + example = "light green"; + }; + + priority = mkOption { + type = types.int; + default = 10; + description = '' + Priority of a calendar used for coloring (calendar with highest priority is preferred). + ''; + }; }; } diff --git a/modules/programs/khal-calendar-accounts.nix b/modules/programs/khal-calendar-accounts.nix index 6910d627a..0a56ba816 100644 --- a/modules/programs/khal-calendar-accounts.nix +++ b/modules/programs/khal-calendar-accounts.nix @@ -20,39 +20,5 @@ with lib; type is set to discover. ''; }; - - color = mkOption { - type = types.nullOr (types.enum [ - "black" - "white" - "brown" - "yellow" - "dark gray" - "dark green" - "dark blue" - "light gray" - "light green" - "light blue" - "dark magenta" - "dark cyan" - "dark red" - "light magenta" - "light cyan" - "light red" - ]); - default = null; - description = '' - Color in which events in this calendar are displayed. - ''; - example = "light green"; - }; - - priority = mkOption { - type = types.int; - default = 10; - description = '' - Priority of a calendar used for coloring. - ''; - }; }; } diff --git a/modules/programs/khal-contact-accounts.nix b/modules/programs/khal-contact-accounts.nix new file mode 100644 index 000000000..c58ed4d6b --- /dev/null +++ b/modules/programs/khal-contact-accounts.nix @@ -0,0 +1,15 @@ +{ config, lib, ... }: + +with lib; + +{ + options.khal = { + collections = mkOption { + type = types.nullOr (types.listOf types.str); + default = null; + description = '' + VCARD collections to be searched for contact birthdays. + ''; + }; + }; +} diff --git a/modules/programs/khal.nix b/modules/programs/khal.nix index 8fc0e0892..c8037e53b 100644 --- a/modules/programs/khal.nix +++ b/modules/programs/khal.nix @@ -12,13 +12,25 @@ let khalCalendarAccounts = filterAttrs (_: a: a.khal.enable) config.accounts.calendar.accounts; - khalContactAccounts = mapAttrs (_: v: v // { type = "birthdays"; }) - (filterAttrs (_: a: a.khal.enable) config.accounts.contact.accounts); + # a contact account may have multiple collections, each a separate calendar + expandContactAccount = name: acct: + if acct.khal.collections != null then + listToAttrs (map (c: { + name = "${name}-${c}"; + value = recursiveUpdate acct { khal.thisCollection = c; }; + }) acct.khal.collections) + else { + ${name} = acct; + }; + + khalContactAccounts = concatMapAttrs expandContactAccount + (mapAttrs (_: v: recursiveUpdate v { khal.type = "birthdays"; }) + (filterAttrs (_: a: a.khal.enable) config.accounts.contact.accounts)); khalAccounts = khalCalendarAccounts // khalContactAccounts; primaryAccount = findSingle (a: a.primary) null null - (mapAttrsToList (n: v: v // { name = n; }) khalAccounts); + (mapAttrsToList (n: v: v // { name = n; }) khalCalendarAccounts); definedAttrs = filterAttrs (_: v: !isNull v); @@ -30,6 +42,9 @@ let "path = ${ value.local.path + "/" + (optionalString (value.khal.type == "discover") value.khal.glob) + + (optionalString + (value.khal.type == "birthdays" && value.khal ? thisCollection) + value.khal.thisCollection) }" ] ++ optional (value.khal.readOnly) "readonly = True" ++ [ (toKeyValueIfDefined (getAttrs [ "type" "color" "priority" ] value.khal)) @@ -153,7 +168,7 @@ in { locale = mkOption { type = lib.types.submodule { options = localeOptions; }; description = '' - khal locale settings. + khal locale settings. ''; default = { }; }; diff --git a/tests/modules/programs/khal/config.nix b/tests/modules/programs/khal/config.nix index a2eb8bf13..50218e15a 100644 --- a/tests/modules/programs/khal/config.nix +++ b/tests/modules/programs/khal/config.nix @@ -32,6 +32,36 @@ }; }; + accounts.contact = { + basePath = "$XDG_CONFIG_HOME/card"; + accounts = { + testcontacts = { + khal = { + enable = true; + collections = [ "default" "automaticallyCollected" ]; + }; + local.type = "filesystem"; + local.fileExt = ".vcf"; + name = "testcontacts"; + remote = { + type = "http"; + url = "https://example.com/contacts.vcf"; + }; + }; + + testcontactsNoCollections = { + khal.enable = true; + local.type = "filesystem"; + local.fileExt = ".vcf"; + name = "testcontactsNoCollections"; + remote = { + type = "http"; + url = "https://example.com/contacts.vcf"; + }; + }; + }; + }; + test.stubs = { khal = { }; }; nmt.script = '' diff --git a/tests/modules/programs/khal/khal-config-expected b/tests/modules/programs/khal/khal-config-expected index 361db2d68..a4cf7a30e 100644 --- a/tests/modules/programs/khal/khal-config-expected +++ b/tests/modules/programs/khal/khal-config-expected @@ -7,6 +7,27 @@ type=calendar +[[testcontacts-automaticallyCollected]] +path = /home/hm-user/$XDG_CONFIG_HOME/card/testcontacts/automaticallyCollected +priority=10 +type=birthdays + + + +[[testcontacts-default]] +path = /home/hm-user/$XDG_CONFIG_HOME/card/testcontacts/default +priority=10 +type=birthdays + + + +[[testcontactsNoCollections]] +path = /home/hm-user/$XDG_CONFIG_HOME/card/testcontactsNoCollections/ +priority=10 +type=birthdays + + + [default] default_calendar=test highlight_event_days=true