# alot config loader is sensitive to leading space ! { config, lib, pkgs, ... }: with lib; let cfg = config.programs.alot; enabledAccounts = filter (a: a.notmuch.enable) (attrValues config.accounts.email.accounts); # sorted: primary first alotAccounts = sort (a: b: !(a.primary -> b.primary)) enabledAccounts; boolStr = v: if v then "True" else "False"; mkKeyValue = key: value: let value' = if isBool value then boolStr value else toString value; in "${key} = ${value'}"; mk2ndLevelSectionName = name: "[" + name + "]"; tagSubmodule = types.submodule { options = { translated = mkOption { type = types.nullOr types.str; description = '' Fixed string representation for this tag. The tag can be hidden from view, if the key translated is set to `""`, the empty string. ''; }; translation = mkOption { type = types.nullOr types.str; default = null; description = '' A pair of strings that define a regular substitution to compute the string representation on the fly using `re.sub`. ''; }; normal = mkOption { type = types.nullOr types.str; default = null; example = "'','', 'white','light red', 'white','#d66'"; description = '' How to display the tag when unfocused. See . ''; }; focus = mkOption { type = types.nullOr types.str; default = null; description = "How to display the tag when focused."; }; }; }; accountStr = account: with account; concatStringsSep "\n" ([ "[[${name}]]" ] ++ mapAttrsToList (n: v: n + "=" + v) ({ address = address; realname = realName; sendmail_command = optionalString (alot.sendMailCommand != null) alot.sendMailCommand; } // optionalAttrs (folders.sent != null) { sent_box = "maildir" + "://" + maildir.absPath + "/" + folders.sent; } // optionalAttrs (folders.drafts != null) { draft_box = "maildir" + "://" + maildir.absPath + "/" + folders.drafts; } // optionalAttrs (aliases != [ ]) { aliases = concatStringsSep "," aliases; } // optionalAttrs (gpg != null) { gpg_key = gpg.key; encrypt_by_default = if gpg.encryptByDefault then "all" else "none"; sign_by_default = boolStr gpg.signByDefault; } // optionalAttrs (signature.showSignature != "none") { signature = pkgs.writeText "signature.txt" signature.text; signature_as_attachment = boolStr (signature.showSignature == "attach"); }) ++ [ alot.extraConfig ] ++ [ "[[[abook]]]" ] ++ mapAttrsToList (n: v: n + "=" + v) alot.contactCompletion); configFile = let bindingsToStr = attrSet: concatStringsSep "\n" (mapAttrsToList (n: v: "${n} = ${v}") attrSet); in '' # Generated by Home Manager. # See http://alot.readthedocs.io/en/latest/configuration/config_options.html ${generators.toKeyValue { inherit mkKeyValue; } cfg.settings} ${cfg.extraConfig} [tags] '' + (let submoduleToAttrs = m: filterAttrs (name: v: name != "_module" && v != null) m; in generators.toINI { mkSectionName = mk2ndLevelSectionName; } (mapAttrs (name: x: submoduleToAttrs x) cfg.tags)) + '' [bindings] ${bindingsToStr cfg.bindings.global} [[bufferlist]] ${bindingsToStr cfg.bindings.bufferlist} [[search]] ${bindingsToStr cfg.bindings.search} [[envelope]] ${bindingsToStr cfg.bindings.envelope} [[taglist]] ${bindingsToStr cfg.bindings.taglist} [[thread]] ${bindingsToStr cfg.bindings.thread} [accounts] ${concatStringsSep "\n\n" (map accountStr alotAccounts)} ''; in { options = { programs.alot = { enable = mkOption { type = types.bool; default = false; example = true; description = '' Whether to enable the Alot mail user agent. Alot uses the Notmuch email system and will therefore be automatically enabled for each email account that is managed by Notmuch. ''; }; package = mkPackageOption pkgs "alot" { }; hooks = mkOption { type = types.lines; default = ""; description = '' Content of the hooks file. ''; }; bindings = mkOption { type = types.submodule { options = { global = mkOption { type = types.attrsOf types.str; default = { }; description = "Global keybindings."; }; bufferlist = mkOption { type = types.attrsOf types.str; default = { }; description = "Bufferlist mode keybindings."; }; search = mkOption { type = types.attrsOf types.str; default = { }; description = "Search mode keybindings."; }; envelope = mkOption { type = types.attrsOf types.str; default = { }; description = "Envelope mode keybindings."; }; taglist = mkOption { type = types.attrsOf types.str; default = { }; description = "Taglist mode keybindings."; }; thread = mkOption { type = types.attrsOf types.str; default = { }; description = "Thread mode keybindings."; }; }; }; default = { }; description = '' Keybindings. ''; }; tags = mkOption { type = types.attrsOf tagSubmodule; default = { }; description = "How to display the tags."; }; settings = mkOption { type = with types; let primitive = either (either (either str int) bool) float; in attrsOf primitive; default = { initial_command = "search tag:inbox AND NOT tag:killed"; auto_remove_unread = true; handle_mouse = true; prefer_plaintext = true; }; example = literalExpression '' { auto_remove_unread = true; ask_subject = false; thread_indent_replies = 2; } ''; description = '' Configuration options added to alot configuration file. ''; }; extraConfig = mkOption { type = types.lines; default = ""; description = '' Extra lines added to alot configuration file. ''; }; }; accounts.email.accounts = mkOption { type = with types; attrsOf (submodule (import ./alot-accounts.nix pkgs)); }; }; config = mkIf cfg.enable { home.packages = [ cfg.package ]; xdg.configFile."alot/config".text = configFile; xdg.configFile."alot/hooks.py" = mkIf (cfg.hooks != "") { text = '' # Generated by Home Manager. '' + cfg.hooks; }; }; }