diff options
author | Matthieu Coudron <mattator@gmail.com> | 2020-01-22 00:52:01 +0100 |
---|---|---|
committer | Robert Helgesson <robert@rycee.net> | 2020-01-26 20:46:44 +0100 |
commit | fba87f899870c7c8fa412efeb2bcb6c31ac21e32 (patch) | |
tree | 29b2c48f4f0943625f7e20a96f71da26dafb5663 /modules | |
parent | d8d5f85ab7ca29d106429f6b7041f222e326978c (diff) |
neomutt: add module
PR #1002
Diffstat (limited to 'modules')
-rw-r--r-- | modules/accounts/email.nix | 1 | ||||
-rw-r--r-- | modules/misc/news.nix | 7 | ||||
-rw-r--r-- | modules/modules.nix | 1 | ||||
-rw-r--r-- | modules/programs/neomutt-accounts.nix | 35 | ||||
-rw-r--r-- | modules/programs/neomutt.nix | 319 |
5 files changed, 363 insertions, 0 deletions
diff --git a/modules/accounts/email.nix b/modules/accounts/email.nix index cc9d0dc2813..b3a9db947a9 100644 --- a/modules/accounts/email.nix +++ b/modules/accounts/email.nix @@ -391,6 +391,7 @@ in (import ../programs/getmail-accounts.nix) (import ../programs/mbsync-accounts.nix) (import ../programs/msmtp-accounts.nix) + (import ../programs/neomutt-accounts.nix) (import ../programs/notmuch-accounts.nix) (import ../programs/offlineimap-accounts.nix) ]); diff --git a/modules/misc/news.nix b/modules/misc/news.nix index 63c865b637d..6b01617fc55 100644 --- a/modules/misc/news.nix +++ b/modules/misc/news.nix @@ -1311,6 +1311,13 @@ in A new module is available: 'services.grobi'. ''; } + + { + time = "2020-01-26T19:37:57+00:00"; + message = '' + A new module is available: 'programs.neomutt'. + ''; + } ]; }; } diff --git a/modules/modules.nix b/modules/modules.nix index dbb3f1dfee3..64418dbae11 100644 --- a/modules/modules.nix +++ b/modules/modules.nix @@ -78,6 +78,7 @@ let (loadModule ./programs/mercurial.nix { }) (loadModule ./programs/mpv.nix { }) (loadModule ./programs/msmtp.nix { }) + (loadModule ./programs/neomutt.nix { }) (loadModule ./programs/neovim.nix { }) (loadModule ./programs/newsboat.nix { }) (loadModule ./programs/noti.nix { }) diff --git a/modules/programs/neomutt-accounts.nix b/modules/programs/neomutt-accounts.nix new file mode 100644 index 00000000000..a374f1167bd --- /dev/null +++ b/modules/programs/neomutt-accounts.nix @@ -0,0 +1,35 @@ +{ config, lib, ... }: + +with lib; + +{ + options.neomutt = { + enable = mkEnableOption "NeoMutt"; + + sendMailCommand = mkOption { + type = types.nullOr types.str; + default = null; + example = "msmtpq --read-envelope-from --read-recipients"; + description = '' + Command to send a mail. If not set, neomutt will be in charge of sending mails. + ''; + }; + + extraConfig = mkOption { + type = types.lines; + default = ""; + example = "color status cyan default"; + description = '' + Extra lines to add to the folder hook for this account. + ''; + }; + }; + + config = mkIf config.neomutt.enable { + neomutt.sendMailCommand = mkOptionDefault ( + if config.msmtp.enable + then "msmtpq --read-envelope-from --read-recipients" + else null + ); + }; +} diff --git a/modules/programs/neomutt.nix b/modules/programs/neomutt.nix new file mode 100644 index 00000000000..1f7022e0aca --- /dev/null +++ b/modules/programs/neomutt.nix @@ -0,0 +1,319 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.programs.neomutt; + + neomuttAccounts = filter (a: a.neomutt.enable) + (attrValues config.accounts.email.accounts); + + sidebarModule = types.submodule { + options = { + enable = mkEnableOption "sidebar support"; + + width = mkOption { + type = types.int; + default = 22; + description = "Width of the sidebar"; + }; + + shortPath = mkOption { + type = types.bool; + default = true; + description = '' + By default sidebar shows the full path of the mailbox, but + with this enabled only the relative name is shown. + ''; + }; + + format = mkOption { + type = types.str; + default = "%B%?F? [%F]?%* %?N?%N/?%S"; + description = '' + Sidebar format. Check neomutt documentation for details. + ''; + }; + }; + }; + + bindModule = types.submodule { + options = { + map = mkOption { + type = types.enum [ + "alias" + "attach" + "browser" + "compose" + "editor" + "generic" + "index" + "mix" + "pager" + "pgp" + "postpone" + "query" + "smime" + ]; + default = "index"; + description = "Select the menu to bind the command to."; + }; + + key = mkOption { + type = types.str; + example = "<left>"; + description = "The key to bind."; + }; + + action = mkOption { + type = types.str; + example = "<enter-command>toggle sidebar_visible<enter><refresh>"; + description = "Specify the action to take."; + }; + }; + }; + + yesno = x: if x then "yes" else "no"; + setOption = n: v: if v == null then "unset ${n}" else "set ${n}=${v}"; + escape = replaceStrings ["%"] ["%25"]; + + accountFilename = account: + config.xdg.configHome + "/neomutt/" + account.name; + + genCommonFolderHooks = account: with account; + { + from = "'${address}'"; + realname = "'${realName}'"; + spoolfile = "'+${folders.inbox}'"; + record = if folders.sent == null then null else "'+${folders.sent}'"; + postponed = "'+${folders.drafts}'"; + trash = "'+${folders.trash}'"; + }; + + mtaSection = account: with account; + let + passCmd = concatStringsSep " " passwordCommand; + in + if neomutt.sendMailCommand != null then { + sendmail = "'${neomutt.sendMailCommand}'"; + } else let + smtpProto = if smtp.tls.enable then "smtps" else "smtp"; + smtpBaseUrl = "${smtpProto}://${escape userName}@${smtp.host}"; + in { + smtp_url = "'${smtpBaseUrl}'"; + smtp_pass = "'`${passCmd}`'"; + }; + + genMaildirAccountConfig = account: with account; + let + folderHook = + mapAttrsToList setOption ( + genCommonFolderHooks account + // { folder = "'${account.maildir.absPath}'"; } + ) + ++ optional (neomutt.extraConfig != "") neomutt.extraConfig; + in + '' + ${concatStringsSep "\n" folderHook} + ''; + + registerAccount = account: with account; + '' + # register account ${name} + mailboxes "${account.maildir.absPath}/${folders.inbox}" + folder-hook ${account.maildir.absPath}/ " \ + source ${accountFilename account} " + ''; + + mraSection = account: with account; + if account.maildir != null + then genMaildirAccountConfig account + else throw "Only maildir is supported at the moment"; + + optionsStr = attrs: + concatStringsSep "\n" (mapAttrsToList setOption attrs); + + + sidebarSection = '' + # Sidebar + set sidebar_visible = yes + set sidebar_short_path = ${yesno cfg.sidebar.shortPath} + set sidebar_width = ${toString cfg.sidebar.width} + set sidebar_format = '${cfg.sidebar.format}' + ''; + + bindSection = + concatMapStringsSep + "\n" + (bind: "bind ${bind.map} ${bind.key} \"${bind.action}\"") + cfg.binds; + + macroSection = + concatMapStringsSep + "\n" + (bind: "macro ${bind.map} ${bind.key} \"${bind.action}\"") + cfg.macros; + + mailCheckSection = '' + set mail_check_stats + set mail_check_stats_interval = ${toString cfg.checkStatsInterval} + ''; + + notmuchSection = account: with account; '' + # notmuch section + set nm_default_uri = "notmuch://${config.accounts.email.maildirBasePath}" + virtual-mailboxes "My INBOX" "notmuch://?query=tag:inbox" + ''; + + accountStr = account: with account; '' + # Generated by Home Manager. + set ssl_force_tls = yes + set certificate_file=${config.accounts.email.certificatesFile} + + # GPG section + set crypt_use_gpgme = yes + set crypt_autosign = ${yesno (gpg.signByDefault or false)} + set pgp_use_gpg_agent = yes + set mbox_type = ${if maildir != null then "Maildir" else "mbox"} + set sort = "${cfg.sort}" + + # MTA section + ${optionsStr (mtaSection account)} + + ${optionalString (cfg.checkStatsInterval != null) mailCheckSection} + + ${optionalString cfg.sidebar.enable sidebarSection} + + # MRA section + ${mraSection account} + + # Extra configuration + ${account.neomutt.extraConfig} + '' + + optionalString (account.signature.showSignature != "none") '' + set signature = ${pkgs.writeText "signature.txt" account.signature.text} + '' + + optionalString account.notmuch.enable (notmuchSection account); + +in + +{ + options = { + programs.neomutt = { + enable = mkEnableOption "the NeoMutt mail client"; + + sidebar = mkOption { + type = sidebarModule; + default = {}; + description = "Options related to the sidebar."; + }; + + binds = mkOption { + type = types.listOf bindModule; + default = []; + description = "List of keybindings."; + }; + + macros = mkOption { + type = types.listOf bindModule; + default = []; + description = "List of macros."; + }; + + sort = mkOption { + type = types.enum [ + "date" + "date-received" + "from" + "mailbox-order" + "score" + "size" + "spam" + "subject" + "threads" + "to" + ]; + default = "threads"; + description = "Sorting method on messages."; + }; + + vimKeys = mkOption { + type = types.bool; + default = false; + description = "Enable vim-like bindings."; + }; + + checkStatsInterval = mkOption { + type = types.nullOr types.int; + default = null; + example = 60; + description = "Enable and set the interval of automatic mail check."; + }; + + editor = mkOption { + type = types.str; + default = "$EDITOR"; + description = "Select the editor used for writing mail."; + }; + + settings = mkOption { + type = types.attrsOf types.str; + default = {}; + description = "Extra configuration appended to the end."; + }; + + extraConfig = mkOption { + type = types.lines; + default = ""; + description = "Extra configuration appended to the end."; + }; + }; + }; + + config = mkIf cfg.enable { + home.packages = [ pkgs.neomutt ]; + home.file = let + rcFile = account: { + "${accountFilename account}".text = accountStr account; + }; + in + foldl' (a: b: a // b) {} (map rcFile neomuttAccounts); + + xdg.configFile."neomutt/neomuttrc" = mkIf (neomuttAccounts != []) { + text = + let + primary = filter (a: a.primary) neomuttAccounts; + in + '' + # Generated by Home Manager. + set header_cache = "${config.xdg.cacheHome}/neomutt/headers/" + set message_cachedir = "${config.xdg.cacheHome}/neomutt/messages/" + set editor = "${cfg.editor}" + set implicit_autoview = yes + + alternative_order text/enriched text/plain text + + set delete = yes + + # Binds + ${bindSection} + + # Macros + ${macroSection} + + ${optionalString cfg.vimKeys "source ${pkgs.neomutt}/share/doc/neomutt/vim-keys/vim-keys.rc"} + + # Extra configuration + ${optionsStr cfg.settings} + + ${cfg.extraConfig} + '' + + + concatMapStringsSep "\n" registerAccount neomuttAccounts + + + # source primary account + "source ${accountFilename (builtins.head primary)}"; + }; + }; +} |