diff --git a/modules/accounts/email.nix b/modules/accounts/email.nix index 5b1b912f1..063ffc258 100644 --- a/modules/accounts/email.nix +++ b/modules/accounts/email.nix @@ -379,6 +379,7 @@ in accounts = mkOption { type = types.attrsOf (types.submodule [ mailAccountOpts + (import ../programs/alot-accounts.nix) (import ../programs/mbsync-accounts.nix) (import ../programs/msmtp-accounts.nix) (import ../programs/notmuch-accounts.nix) diff --git a/modules/misc/news.nix b/modules/misc/news.nix index c2aefafda..3b44bdf77 100644 --- a/modules/misc/news.nix +++ b/modules/misc/news.nix @@ -815,6 +815,12 @@ in ''; } + { + time = "2018-09-28T21:38:48+00:00"; + message = '' + A new module is available: 'programs.alot'. + ''; + } ]; }; } diff --git a/modules/modules.nix b/modules/modules.nix index 1f056aa38..d8c2732e0 100644 --- a/modules/modules.nix +++ b/modules/modules.nix @@ -25,6 +25,7 @@ let ./misc/pam.nix ./misc/qt.nix ./misc/xdg.nix + ./programs/alot.nix ./programs/autorandr.nix ./programs/bash.nix ./programs/beets.nix diff --git a/modules/programs/alot-accounts.nix b/modules/programs/alot-accounts.nix new file mode 100644 index 000000000..ad7be0d88 --- /dev/null +++ b/modules/programs/alot-accounts.nix @@ -0,0 +1,32 @@ +{ config, lib, ... }: + +with lib; + +{ + options.alot = { + sendMailCommand = mkOption { + type = types.nullOr types.str; + description = '' + Command to send a mail. If msmtp is enabled for the account, + then this is set to + msmtpq --read-envelope-from --read-recipients. + ''; + }; + + extraConfig = mkOption { + type = types.lines; + default = ""; + description = '' + Extra settings to add to this Alot account configuration. + ''; + }; + }; + + config = mkIf config.notmuch.enable { + alot.sendMailCommand = mkOptionDefault ( + if config.msmtp.enable + then "msmtpq --read-envelope-from --read-recipients" + else null + ); + }; +} diff --git a/modules/programs/alot.nix b/modules/programs/alot.nix new file mode 100644 index 000000000..ea5a5d11b --- /dev/null +++ b/modules/programs/alot.nix @@ -0,0 +1,167 @@ +# alot config loader is sensitive to leading space ! +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.programs.alot; + + alotAccounts = filter (a: a.notmuch.enable) + (attrValues config.accounts.email.accounts); + + boolStr = v: if v then "True" else "False"; + + 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 (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"); + } + ) + ) + + "\n" + + alot.extraConfig; + + 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 + + ${cfg.extraConfig} + + [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. + ''; + }; + + 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. + ''; + }; + + extraConfig = mkOption { + type = types.lines; + default = '' + auto_remove_unread = True + ask_subject = False + handle_mouse = True + initial_command = "search tag:inbox AND NOT tag:killed" + input_timeout = 0.3 + prefer_plaintext = True + thread_indent_replies = 4 + ''; + description = '' + Extra lines added to alot configuration file. + ''; + }; + }; + + config = mkIf cfg.enable { + home.packages = [ pkgs.alot ]; + + xdg.configFile."alot/config".text = configFile; + + xdg.configFile."alot/hooks.py".text = + '' + # Generated by Home Manager. + '' + + cfg.hooks; + }; +}