From dacc07136c74ebe3e702391eb07112bbc5328e80 Mon Sep 17 00:00:00 2001
From: Matthieu Coudron <mattator@gmail.com>
Date: Sun, 30 Sep 2018 18:06:02 +0900
Subject: [PATCH] astroid: add module

Astroid is a notmuch/gtk based MUA: https://github.com/astroidmail/astroid
---
 modules/accounts/email.nix                    |   1 +
 modules/misc/news.nix                         |   7 +
 modules/modules.nix                           |   1 +
 modules/programs/astroid-accounts.nix         |  33 +++++
 modules/programs/astroid-config-template.json | 113 +++++++++++++++
 modules/programs/astroid.nix                  | 131 ++++++++++++++++++
 6 files changed, 286 insertions(+)
 create mode 100644 modules/programs/astroid-accounts.nix
 create mode 100644 modules/programs/astroid-config-template.json
 create mode 100644 modules/programs/astroid.nix

diff --git a/modules/accounts/email.nix b/modules/accounts/email.nix
index 063ffc258..857622c08 100644
--- a/modules/accounts/email.nix
+++ b/modules/accounts/email.nix
@@ -380,6 +380,7 @@ in
       type = types.attrsOf (types.submodule [
         mailAccountOpts
         (import ../programs/alot-accounts.nix)
+        (import ../programs/astroid-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 ff668cabe..a6c435b93 100644
--- a/modules/misc/news.nix
+++ b/modules/misc/news.nix
@@ -816,6 +816,13 @@ in
           A new module is available: 'programs.tmux'.
         '';
       }
+
+      {
+        time = "2018-11-18T18:55:15+00:00";
+        message = ''
+          A new module is available: 'programs.astroid'.
+        '';
+      }
     ];
   };
 }
diff --git a/modules/modules.nix b/modules/modules.nix
index 6a508553a..d3cf343aa 100644
--- a/modules/modules.nix
+++ b/modules/modules.nix
@@ -27,6 +27,7 @@ let
     ./misc/xdg.nix
     ./programs/alot.nix
     ./programs/autorandr.nix
+    ./programs/astroid.nix
     ./programs/bash.nix
     ./programs/beets.nix
     ./programs/browserpass.nix
diff --git a/modules/programs/astroid-accounts.nix b/modules/programs/astroid-accounts.nix
new file mode 100644
index 000000000..bc94a301d
--- /dev/null
+++ b/modules/programs/astroid-accounts.nix
@@ -0,0 +1,33 @@
+{ config, lib, ... }:
+
+with lib;
+
+{
+  options.astroid = {
+    enable = mkEnableOption "Astroid";
+
+    sendMailCommand = mkOption {
+      type = types.str;
+      description = ''
+        Command to send a mail. If msmtp is enabled for the account,
+        then this is set to
+        <command>msmtpq --read-envelope-from --read-recipients</command>.
+      '';
+    };
+
+    extraConfig = mkOption {
+      type = types.attrs;
+      default = {};
+      example = { select_query = ""; };
+      description = ''
+        Extra settings to add to this astroid account configuration.
+      '';
+    };
+  };
+
+  config = mkIf config.notmuch.enable {
+    astroid.sendMailCommand = mkIf config.msmtp.enable (
+      mkOptionDefault "msmtpq --read-envelope-from --read-recipients"
+    );
+  };
+}
diff --git a/modules/programs/astroid-config-template.json b/modules/programs/astroid-config-template.json
new file mode 100644
index 000000000..87e3f764f
--- /dev/null
+++ b/modules/programs/astroid-config-template.json
@@ -0,0 +1,113 @@
+{
+    "astroid": {
+        "config": {
+            "version": "11"
+        },
+        "debug": {
+            "dryrun_sending": "false"
+        },
+        "hints": {
+            "level": "0"
+        },
+        "log": {
+            "syslog": "false",
+            "stdout": "true",
+            "level": "info"
+        }
+    },
+    "startup": {
+        "queries": {
+            "inbox": "tag:inbox"
+        }
+    },
+    "terminal": {
+        "height": "10",
+        "font_description": "default"
+    },
+    "thread_index": {
+        "page_jump_rows": "6",
+        "sort_order": "newest",
+        "cell": {
+            "font_description": "default",
+            "line_spacing": "2",
+            "date_length": "10",
+            "message_count_length": "4",
+            "authors_length": "20",
+            "subject_color": "#807d74",
+            "subject_color_selected": "#000000",
+            "background_color_selected": "",
+            "background_color_marked": "#fff584",
+            "background_color_marked_selected": "#bcb559",
+            "tags_length": "80",
+            "tags_upper_color": "#e5e5e5",
+            "tags_lower_color": "#333333",
+            "tags_alpha": "0.5",
+            "hidden_tags": "attachment,flagged,unread"
+        }
+    },
+    "general": {
+        "time": {
+            "clock_format": "local",
+            "same_year": "%b %-e",
+            "diff_year": "%x"
+        }
+    },
+    "editor": {
+        "charset": "utf-8",
+        "save_draft_on_force_quit": "true",
+        "attachment_words": "attach",
+        "attachment_directory": "~",
+        "markdown_processor": "marked"
+    },
+    "mail": {
+        "reply": {
+            "quote_line": "Excerpts from %1's message of %2:",
+            "mailinglist_reply_to_sender": "true"
+        },
+        "forward": {
+            "quote_line": "Forwarding %1's message of %2:",
+            "disposition": "inline"
+        },
+        "sent_tags": "sent",
+        "message_id_fqdn": "",
+        "message_id_user": "",
+        "user_agent": "default",
+        "send_delay": "2",
+        "close_on_success": "false",
+        "format_flowed": "false"
+    },
+    "poll": {
+        "interval": "60",
+        "always_full_refresh": "false"
+    },
+    "attachment": {
+        "external_open_cmd": "xdg-open"
+    },
+    "thread_view": {
+        "open_html_part_external": "false",
+        "preferred_type": "plain",
+        "preferred_html_only": "false",
+        "allow_remote_when_encrypted": "false",
+        "open_external_link": "xdg-open",
+        "default_save_directory": "~",
+        "indent_messages": "false",
+        "gravatar": {
+            "enable": "true"
+        },
+        "mark_unread_delay": "0.5",
+        "expand_flagged": "true"
+    },
+    "crypto": {
+        "gpg": {
+            "path": "gpg2",
+            "always_trust": "true",
+            "enabled": "true"
+        }
+    },
+    "saved_searches": {
+        "show_on_startup": "false",
+        "save_history": "true",
+        "history_lines_to_show": "15",
+        "history_lines": "1000"
+    }
+}
diff --git a/modules/programs/astroid.nix b/modules/programs/astroid.nix
new file mode 100644
index 000000000..45c35fa95
--- /dev/null
+++ b/modules/programs/astroid.nix
@@ -0,0 +1,131 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+with builtins;
+
+let
+
+  cfg = config.programs.astroid;
+
+  astroidAccounts =
+    filterAttrs
+      (n: v: v.astroid.enable)
+      config.accounts.email.accounts;
+
+  boolOpt = b: if b then "true" else "false";
+
+  accountAttr = account: with account; {
+    email = address;
+    name = realName;
+    sendmail = astroid.sendMailCommand;
+    additional_sent_tags = "";
+    default = boolOpt primary;
+    save_drafts_to = folders.drafts;
+    save_sent = "true";
+    save_sent_to = folders.sent;
+    select_query = "";
+  }
+  // optionalAttrs (signature.showSignature != "none") {
+    signature_attach = boolOpt (signature.showSignature == "attach");
+    signature_default_on = boolOpt (signature.showSignature != "none");
+    signature_file = pkgs.writeText "signature.txt" signature.text;
+    signature_file_markdown = "false";
+    signature_separate = "true";  # prepends '--\n' to the signature
+  }
+  // optionalAttrs (gpg != null) {
+    always_gpg_sign = boolOpt gpg.signByDefault;
+    gpgkey = gpg.key;
+  }
+  // astroid.extraConfig;
+
+  # See https://github.com/astroidmail/astroid/wiki/Configuration-Reference
+  configFile = mailAccounts:
+    let
+      template = fromJSON (readFile ./astroid-config-template.json);
+      astroidConfig = foldl' recursiveUpdate template [
+        {
+          astroid.notmuch_config = "${config.xdg.configHome}/notmuch/notmuchrc";
+          accounts = mapAttrs (n: accountAttr) astroidAccounts;
+          crypto.gpg.path = "${pkgs.gnupg}/bin/gpg";
+        }
+        cfg.extraConfig
+        cfg.externalEditor
+      ];
+    in
+      builtins.toJSON astroidConfig;
+
+in
+
+{
+  options = {
+    programs.astroid = {
+      enable = mkEnableOption "Astroid";
+
+      pollScript = mkOption {
+        type = types.str;
+        default = "";
+        example = "mbsync gmail";
+        description = ''
+          Script to run to fetch/update mails.
+        '';
+      };
+
+      externalEditor = mkOption {
+        type = types.nullOr types.str;
+        default = null;
+        # Converts it into JSON that can be merged into the configuration.
+        apply = cmd:
+          optionalAttrs (cmd != null) {
+            editor = {
+              "external_editor" = "true";
+              "cmd" = cmd;
+            };
+          };
+        example = "nvim-qt -- -c 'set ft=mail' '+set fileencoding=utf-8' '+set ff=unix' '+set enc=utf-8' '+set fo+=w' %1";
+        description = ''
+          You can use <code>%1</code>, <code>%2</code>, and
+          <code>%3</code> to refer respectively to:
+          <orderedlist numeration="arabic">
+            <listitem><para>file name</para></listitem>
+            <listitem><para>server name</para></listitem>
+            <listitem><para>socket ID</para></listitem>
+          </orderedlist>
+          See <link xlink:href='https://github.com/astroidmail/astroid/wiki/Customizing-editor' />.
+        '';
+      };
+
+      extraConfig = mkOption {
+        type = types.attrs;
+        default = {};
+        example = { poll.interval = 0; };
+        description = ''
+          JSON config that will override the default Astroid configuration.
+        '';
+      };
+    };
+  };
+
+  config = mkIf cfg.enable {
+    home.packages =  [ pkgs.astroid ];
+
+    xdg.configFile."astroid/config".source =
+      pkgs.runCommand "out.json"
+        {
+          json = configFile astroidAccounts;
+          preferLocalBuild = true;
+          allowSubstitutes = false;
+        }
+        ''
+          echo -n "$json" | ${pkgs.jq}/bin/jq . > $out
+        '';
+
+    xdg.configFile."astroid/poll.sh" = {
+      executable = true;
+      text = ''
+        # Generated by Home Manager
+
+        ${cfg.pollScript}
+      '';
+    };
+  };
+}