2018-08-06 12:05:46 +02:00
|
|
|
# alot config loader is sensitive to leading space !
|
|
|
|
{ config, lib, pkgs, ... }:
|
|
|
|
|
|
|
|
with lib;
|
|
|
|
|
|
|
|
let
|
|
|
|
|
|
|
|
cfg = config.programs.alot;
|
|
|
|
|
2021-02-27 21:41:16 +01:00
|
|
|
enabledAccounts =
|
2020-05-01 22:33:05 +02:00
|
|
|
filter (a: a.notmuch.enable) (attrValues config.accounts.email.accounts);
|
2018-08-06 12:05:46 +02:00
|
|
|
|
2021-02-27 21:41:16 +01:00
|
|
|
# sorted: primary first
|
|
|
|
alotAccounts = sort (a: b: !(a.primary -> b.primary)) enabledAccounts;
|
|
|
|
|
2018-08-06 12:05:46 +02:00
|
|
|
boolStr = v: if v then "True" else "False";
|
|
|
|
|
2019-08-21 09:38:52 +02:00
|
|
|
mkKeyValue = key: value:
|
2020-05-01 22:33:05 +02:00
|
|
|
let value' = if isBool value then boolStr value else toString value;
|
|
|
|
in "${key} = ${value'}";
|
2019-08-21 09:38:52 +02:00
|
|
|
|
2020-05-01 22:33:05 +02:00
|
|
|
mk2ndLevelSectionName = name: "[" + name + "]";
|
2019-08-21 09:38:52 +02:00
|
|
|
|
|
|
|
tagSubmodule = types.submodule {
|
|
|
|
options = {
|
|
|
|
translated = mkOption {
|
|
|
|
type = types.nullOr types.str;
|
2023-07-01 01:30:13 +02:00
|
|
|
description = lib.mdDoc ''
|
2019-08-21 09:38:52 +02:00
|
|
|
Fixed string representation for this tag. The tag can be
|
|
|
|
hidden from view, if the key translated is set to
|
2023-07-01 01:30:13 +02:00
|
|
|
`""`, the empty string.
|
2019-08-21 09:38:52 +02:00
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
|
|
|
translation = mkOption {
|
|
|
|
type = types.nullOr types.str;
|
|
|
|
default = null;
|
2023-07-01 01:30:13 +02:00
|
|
|
description = lib.mdDoc ''
|
2019-08-21 09:38:52 +02:00
|
|
|
A pair of strings that define a regular substitution to
|
|
|
|
compute the string representation on the fly using
|
2023-07-01 01:30:13 +02:00
|
|
|
`re.sub`.
|
2019-08-21 09:38:52 +02:00
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
|
|
|
normal = mkOption {
|
|
|
|
type = types.nullOr types.str;
|
|
|
|
default = null;
|
|
|
|
example = "'','', 'white','light red', 'white','#d66'";
|
2023-07-01 01:30:13 +02:00
|
|
|
description = lib.mdDoc ''
|
2019-08-21 09:38:52 +02:00
|
|
|
How to display the tag when unfocused.
|
2023-07-01 01:30:13 +02:00
|
|
|
See <https://alot.readthedocs.io/en/latest/configuration/theming.html#tagstring-formatting>.
|
2019-08-21 09:38:52 +02:00
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
|
|
|
focus = mkOption {
|
|
|
|
type = types.nullOr types.str;
|
|
|
|
default = null;
|
2023-07-01 01:30:13 +02:00
|
|
|
description = lib.mdDoc "How to display the tag when focused.";
|
2019-08-21 09:38:52 +02:00
|
|
|
};
|
2020-05-01 22:33:05 +02:00
|
|
|
};
|
2019-08-21 09:38:52 +02:00
|
|
|
};
|
2018-08-06 12:05:46 +02:00
|
|
|
|
2020-05-01 22:33:05 +02:00
|
|
|
accountStr = account:
|
|
|
|
with account;
|
|
|
|
concatStringsSep "\n" ([ "[[${name}]]" ]
|
|
|
|
++ mapAttrsToList (n: v: n + "=" + v) ({
|
|
|
|
address = address;
|
|
|
|
realname = realName;
|
|
|
|
sendmail_command =
|
|
|
|
optionalString (alot.sendMailCommand != null) alot.sendMailCommand;
|
2023-03-22 11:25:02 +01:00
|
|
|
} // optionalAttrs (folders.sent != null) {
|
2020-05-01 22:33:05 +02:00
|
|
|
sent_box = "maildir" + "://" + maildir.absPath + "/" + folders.sent;
|
2023-03-22 11:25:02 +01:00
|
|
|
} // optionalAttrs (folders.drafts != null) {
|
2020-05-01 22:33:05 +02:00
|
|
|
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 {
|
2020-06-16 00:45:20 +02:00
|
|
|
options = {
|
|
|
|
programs.alot = {
|
|
|
|
enable = mkOption {
|
|
|
|
type = types.bool;
|
|
|
|
default = false;
|
|
|
|
example = true;
|
2023-07-01 01:30:13 +02:00
|
|
|
description = lib.mdDoc ''
|
2020-06-16 00:45:20 +02:00
|
|
|
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.
|
|
|
|
'';
|
|
|
|
};
|
2018-08-06 12:05:46 +02:00
|
|
|
|
2020-06-16 00:45:20 +02:00
|
|
|
hooks = mkOption {
|
|
|
|
type = types.lines;
|
|
|
|
default = "";
|
2023-07-01 01:30:13 +02:00
|
|
|
description = lib.mdDoc ''
|
2020-06-16 00:45:20 +02:00
|
|
|
Content of the hooks file.
|
|
|
|
'';
|
|
|
|
};
|
2018-08-06 12:05:46 +02:00
|
|
|
|
2020-06-16 00:45:20 +02:00
|
|
|
bindings = mkOption {
|
|
|
|
type = types.submodule {
|
|
|
|
options = {
|
|
|
|
global = mkOption {
|
|
|
|
type = types.attrsOf types.str;
|
|
|
|
default = { };
|
2023-07-01 01:30:13 +02:00
|
|
|
description = lib.mdDoc "Global keybindings.";
|
2020-06-16 00:45:20 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
bufferlist = mkOption {
|
|
|
|
type = types.attrsOf types.str;
|
|
|
|
default = { };
|
2023-07-01 01:30:13 +02:00
|
|
|
description = lib.mdDoc "Bufferlist mode keybindings.";
|
2020-06-16 00:45:20 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
search = mkOption {
|
|
|
|
type = types.attrsOf types.str;
|
|
|
|
default = { };
|
2023-07-01 01:30:13 +02:00
|
|
|
description = lib.mdDoc "Search mode keybindings.";
|
2020-06-16 00:45:20 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
envelope = mkOption {
|
|
|
|
type = types.attrsOf types.str;
|
|
|
|
default = { };
|
2023-07-01 01:30:13 +02:00
|
|
|
description = lib.mdDoc "Envelope mode keybindings.";
|
2020-06-16 00:45:20 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
taglist = mkOption {
|
|
|
|
type = types.attrsOf types.str;
|
|
|
|
default = { };
|
2023-07-01 01:30:13 +02:00
|
|
|
description = lib.mdDoc "Taglist mode keybindings.";
|
2020-06-16 00:45:20 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
thread = mkOption {
|
|
|
|
type = types.attrsOf types.str;
|
|
|
|
default = { };
|
2023-07-01 01:30:13 +02:00
|
|
|
description = lib.mdDoc "Thread mode keybindings.";
|
2020-06-16 00:45:20 +02:00
|
|
|
};
|
2018-08-06 12:05:46 +02:00
|
|
|
};
|
2020-06-16 00:45:20 +02:00
|
|
|
};
|
|
|
|
default = { };
|
2023-07-01 01:30:13 +02:00
|
|
|
description = lib.mdDoc ''
|
2020-06-16 00:45:20 +02:00
|
|
|
Keybindings.
|
|
|
|
'';
|
|
|
|
};
|
2018-08-06 12:05:46 +02:00
|
|
|
|
2020-06-16 00:45:20 +02:00
|
|
|
tags = mkOption {
|
|
|
|
type = types.attrsOf tagSubmodule;
|
|
|
|
default = { };
|
2023-07-01 01:30:13 +02:00
|
|
|
description = lib.mdDoc "How to display the tags.";
|
2020-06-16 00:45:20 +02:00
|
|
|
};
|
2018-08-06 12:05:46 +02:00
|
|
|
|
2020-06-16 00:45:20 +02:00
|
|
|
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;
|
2018-08-06 12:05:46 +02:00
|
|
|
};
|
2021-10-09 11:14:08 +02:00
|
|
|
example = literalExpression ''
|
2020-06-16 00:45:20 +02:00
|
|
|
{
|
|
|
|
auto_remove_unread = true;
|
|
|
|
ask_subject = false;
|
|
|
|
thread_indent_replies = 2;
|
|
|
|
}
|
|
|
|
'';
|
2023-07-01 01:30:13 +02:00
|
|
|
description = lib.mdDoc ''
|
2020-06-16 00:45:20 +02:00
|
|
|
Configuration options added to alot configuration file.
|
|
|
|
'';
|
2018-08-06 12:05:46 +02:00
|
|
|
};
|
2019-08-21 09:38:52 +02:00
|
|
|
|
2020-06-16 00:45:20 +02:00
|
|
|
extraConfig = mkOption {
|
|
|
|
type = types.lines;
|
|
|
|
default = "";
|
2023-07-01 01:30:13 +02:00
|
|
|
description = lib.mdDoc ''
|
2020-06-16 00:45:20 +02:00
|
|
|
Extra lines added to alot configuration file.
|
|
|
|
'';
|
2019-08-21 09:38:52 +02:00
|
|
|
};
|
|
|
|
};
|
|
|
|
|
2020-06-16 00:45:20 +02:00
|
|
|
accounts.email.accounts = mkOption {
|
|
|
|
type = with types; attrsOf (submodule (import ./alot-accounts.nix pkgs));
|
2018-08-06 12:05:46 +02:00
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
config = mkIf cfg.enable {
|
2020-05-01 22:33:05 +02:00
|
|
|
home.packages = [ pkgs.alot ];
|
2018-08-06 12:05:46 +02:00
|
|
|
|
|
|
|
xdg.configFile."alot/config".text = configFile;
|
|
|
|
|
2019-08-21 09:38:52 +02:00
|
|
|
xdg.configFile."alot/hooks.py" = mkIf (cfg.hooks != "") {
|
|
|
|
text = ''
|
2018-08-06 12:05:46 +02:00
|
|
|
# Generated by Home Manager.
|
2020-05-01 22:33:05 +02:00
|
|
|
'' + cfg.hooks;
|
2019-08-21 09:38:52 +02:00
|
|
|
};
|
2018-08-06 12:05:46 +02:00
|
|
|
};
|
|
|
|
}
|