mirror of
https://github.com/nix-community/home-manager
synced 2024-11-10 15:14:26 +00:00
parent
d8d5f85ab7
commit
fba87f8998
10 changed files with 477 additions and 0 deletions
|
@ -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)
|
||||
]);
|
||||
|
|
|
@ -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'.
|
||||
'';
|
||||
}
|
||||
];
|
||||
};
|
||||
}
|
||||
|
|
|
@ -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 { })
|
||||
|
|
35
modules/programs/neomutt-accounts.nix
Normal file
35
modules/programs/neomutt-accounts.nix
Normal file
|
@ -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
|
||||
);
|
||||
};
|
||||
}
|
319
modules/programs/neomutt.nix
Normal file
319
modules/programs/neomutt.nix
Normal file
|
@ -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)}";
|
||||
};
|
||||
};
|
||||
}
|
|
@ -33,6 +33,7 @@ import nmt {
|
|||
// import ./modules/misc/xdg
|
||||
// import ./modules/misc/xsession
|
||||
// import ./modules/programs/firefox
|
||||
// import ./modules/programs/neomutt
|
||||
// import ./modules/programs/rofi
|
||||
// import ./modules/services/sxhkd
|
||||
// import ./modules/systemd
|
||||
|
|
3
tests/modules/programs/neomutt/default.nix
Normal file
3
tests/modules/programs/neomutt/default.nix
Normal file
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
neomutt-simple = ./neomutt.nix;
|
||||
}
|
37
tests/modules/programs/neomutt/hm-example.com-expected
Normal file
37
tests/modules/programs/neomutt/hm-example.com-expected
Normal file
|
@ -0,0 +1,37 @@
|
|||
# Generated by Home Manager.
|
||||
set ssl_force_tls = yes
|
||||
set certificate_file=/etc/ssl/certs/ca-certificates.crt
|
||||
|
||||
# GPG section
|
||||
set crypt_use_gpgme = yes
|
||||
set crypt_autosign = no
|
||||
set pgp_use_gpg_agent = yes
|
||||
set mbox_type = Maildir
|
||||
set sort = "threads"
|
||||
|
||||
# MTA section
|
||||
set smtp_pass='`password-command`'
|
||||
set smtp_url='smtps://home.manager@smtp.example.com'
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# MRA section
|
||||
set folder='/home/hm-user/Mail/hm@example.com'
|
||||
set from='hm@example.com'
|
||||
set postponed='+Drafts'
|
||||
set realname='H. M. Test'
|
||||
set record='+Sent'
|
||||
set spoolfile='+Inbox'
|
||||
set trash='+Trash'
|
||||
color status cyan default
|
||||
|
||||
|
||||
|
||||
# Extra configuration
|
||||
color status cyan default
|
||||
|
||||
# notmuch section
|
||||
set nm_default_uri = "notmuch:///home/hm-user/Mail"
|
||||
virtual-mailboxes "My INBOX" "notmuch://?query=tag:inbox"
|
27
tests/modules/programs/neomutt/neomutt-expected.conf
Normal file
27
tests/modules/programs/neomutt/neomutt-expected.conf
Normal file
|
@ -0,0 +1,27 @@
|
|||
# Generated by Home Manager.
|
||||
set header_cache = "/home/hm-user/.cache/neomutt/headers/"
|
||||
set message_cachedir = "/home/hm-user/.cache/neomutt/messages/"
|
||||
set editor = "$EDITOR"
|
||||
set implicit_autoview = yes
|
||||
|
||||
alternative_order text/enriched text/plain text
|
||||
|
||||
set delete = yes
|
||||
|
||||
# Binds
|
||||
|
||||
|
||||
# Macros
|
||||
|
||||
|
||||
|
||||
|
||||
# Extra configuration
|
||||
|
||||
|
||||
|
||||
# register account hm@example.com
|
||||
mailboxes "/home/hm-user/Mail/hm@example.com/Inbox"
|
||||
folder-hook /home/hm-user/Mail/hm@example.com/ " \
|
||||
source /home/hm-user/.config/neomutt/hm@example.com "
|
||||
source /home/hm-user/.config/neomutt/hm@example.com
|
46
tests/modules/programs/neomutt/neomutt.nix
Normal file
46
tests/modules/programs/neomutt/neomutt.nix
Normal file
|
@ -0,0 +1,46 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
{
|
||||
imports = [ ../../accounts/email-test-accounts.nix ];
|
||||
|
||||
config = {
|
||||
home.username = "hm-user";
|
||||
home.homeDirectory = "/home/hm-user";
|
||||
xdg.configHome = mkForce "/home/hm-user/.config";
|
||||
xdg.cacheHome = mkForce "/home/hm-user/.cache";
|
||||
|
||||
accounts.email.accounts = {
|
||||
"hm@example.com" = {
|
||||
primary = true;
|
||||
notmuch.enable = true;
|
||||
neomutt = {
|
||||
enable = true;
|
||||
extraConfig = ''
|
||||
color status cyan default
|
||||
'';
|
||||
};
|
||||
imap.port = 993;
|
||||
};
|
||||
};
|
||||
|
||||
programs.neomutt = {
|
||||
enable = true;
|
||||
vimKeys = false;
|
||||
};
|
||||
|
||||
nixpkgs.overlays = [
|
||||
(self: super: {
|
||||
neomutt = pkgs.writeScriptBin "dummy-neomutt" "";
|
||||
})
|
||||
];
|
||||
|
||||
nmt.script = ''
|
||||
assertFileExists home-files/.config/neomutt/neomuttrc
|
||||
assertFileExists home-files/.config/neomutt/hm@example.com
|
||||
assertFileContent home-files/.config/neomutt/neomuttrc ${./neomutt-expected.conf}
|
||||
assertFileContent home-files/.config/neomutt/hm@example.com ${./hm-example.com-expected}
|
||||
'';
|
||||
};
|
||||
}
|
Loading…
Reference in a new issue