diff --git a/modules/programs/alot.nix b/modules/programs/alot.nix
index 2b28f34ca..62d0720da 100644
--- a/modules/programs/alot.nix
+++ b/modules/programs/alot.nix
@@ -12,6 +12,55 @@ let
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}]]" ]
@@ -41,7 +90,7 @@ let
++ [ alot.extraConfig ]
++ [ "[[[abook]]]" ]
++ mapAttrsToList (n: v: n + "=" + v) alot.contactCompletion
- );
+ );
configFile =
let
@@ -52,8 +101,19 @@ let
# 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}
@@ -142,17 +202,39 @@ in
'';
};
+ 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 = literalExample ''
+ {
+ 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 = ''
- 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
- '';
+ default = "";
description = ''
Extra lines added to alot configuration file.
'';
@@ -164,10 +246,11 @@ in
xdg.configFile."alot/config".text = configFile;
- xdg.configFile."alot/hooks.py".text =
- ''
+ xdg.configFile."alot/hooks.py" = mkIf (cfg.hooks != "") {
+ text = ''
# Generated by Home Manager.
''
+ cfg.hooks;
+ };
};
}
diff --git a/tests/default.nix b/tests/default.nix
index 9eb5afcde..940126827 100644
--- a/tests/default.nix
+++ b/tests/default.nix
@@ -35,6 +35,7 @@ import nmt {
./modules/home-environment
./modules/misc/fontconfig
./modules/programs/alacritty
+ ./modules/programs/alot
./modules/programs/bash
./modules/programs/browserpass
./modules/programs/fish
diff --git a/tests/modules/programs/alot/alot-expected.conf b/tests/modules/programs/alot/alot-expected.conf
new file mode 100644
index 000000000..6d3ace4a3
--- /dev/null
+++ b/tests/modules/programs/alot/alot-expected.conf
@@ -0,0 +1,37 @@
+# Generated by Home Manager.
+# See http://alot.readthedocs.io/en/latest/configuration/config_options.html
+
+auto_remove_unread = True
+handle_mouse = True
+initial_command = search tag:inbox AND NOT tag:killed
+prefer_plaintext = True
+
+
+[tags]
+[bindings]
+
+
+[[bufferlist]]
+
+[[search]]
+
+[[envelope]]
+
+[[taglist]]
+
+[[thread]]
+
+
+[accounts]
+
+[[hm@example.com]]
+address=hm@example.com
+draft_box=maildir:///home/hm-user/Mail/hm@example.com/Drafts
+realname=H. M. Test
+sendmail_command=
+sent_box=maildir:///home/hm-user/Mail/hm@example.com/Sent
+auto_remove_unread = True
+ask_subject = False
+handle_mouse = True
+
+[[[abook]]]
diff --git a/tests/modules/programs/alot/alot.nix b/tests/modules/programs/alot/alot.nix
new file mode 100644
index 000000000..40028b7aa
--- /dev/null
+++ b/tests/modules/programs/alot/alot.nix
@@ -0,0 +1,36 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+{
+ imports = [ ../../accounts/email-test-accounts.nix ];
+
+ config = {
+ accounts.email.accounts = {
+ "hm@example.com" = {
+ primary = true;
+ notmuch.enable = true;
+ alot = {
+ contactCompletion = { };
+ extraConfig = ''
+ auto_remove_unread = True
+ ask_subject = False
+ handle_mouse = True
+ '';
+ };
+ imap.port = 993;
+ };
+ };
+
+ programs.alot = { enable = true; };
+
+ nixpkgs.overlays =
+ [ (self: super: { alot = pkgs.writeScriptBin "dummy-alot" ""; }) ];
+
+ nmt.script = ''
+ assertFileExists home-files/.config/alot/config
+ assertFileContent home-files/.config/alot/config ${./alot-expected.conf}
+ '';
+ };
+}
+
diff --git a/tests/modules/programs/alot/default.nix b/tests/modules/programs/alot/default.nix
new file mode 100644
index 000000000..9c912fdb4
--- /dev/null
+++ b/tests/modules/programs/alot/default.nix
@@ -0,0 +1 @@
+{ alot = ./alot.nix; }