Compare commits
2 commits
master
...
module/neo
Author | SHA1 | Date | |
---|---|---|---|
0fa829cd11 | |||
f7dad7ef24 |
|
@ -383,6 +383,7 @@ in
|
||||||
(import ../programs/astroid-accounts.nix)
|
(import ../programs/astroid-accounts.nix)
|
||||||
(import ../programs/mbsync-accounts.nix)
|
(import ../programs/mbsync-accounts.nix)
|
||||||
(import ../programs/msmtp-accounts.nix)
|
(import ../programs/msmtp-accounts.nix)
|
||||||
|
(import ../programs/neomutt-accounts.nix)
|
||||||
(import ../programs/notmuch-accounts.nix)
|
(import ../programs/notmuch-accounts.nix)
|
||||||
(import ../programs/offlineimap-accounts.nix)
|
(import ../programs/offlineimap-accounts.nix)
|
||||||
]);
|
]);
|
||||||
|
|
|
@ -878,6 +878,13 @@ in
|
||||||
A new module is available: 'programs.vscode'.
|
A new module is available: 'programs.vscode'.
|
||||||
'';
|
'';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
time = "2018-11-26T20:42:42+00:00";
|
||||||
|
message = ''
|
||||||
|
A new module is available: 'programs.neomutt'.
|
||||||
|
'';
|
||||||
|
}
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,6 +52,7 @@ let
|
||||||
./programs/mbsync.nix
|
./programs/mbsync.nix
|
||||||
./programs/mercurial.nix
|
./programs/mercurial.nix
|
||||||
./programs/msmtp.nix
|
./programs/msmtp.nix
|
||||||
|
./programs/neomutt.nix
|
||||||
./programs/neovim.nix
|
./programs/neovim.nix
|
||||||
./programs/newsboat.nix
|
./programs/newsboat.nix
|
||||||
./programs/noti.nix
|
./programs/noti.nix
|
||||||
|
|
42
modules/programs/neomutt-accounts.nix
Normal file
42
modules/programs/neomutt-accounts.nix
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
{ config, lib, ... }:
|
||||||
|
|
||||||
|
with lib;
|
||||||
|
|
||||||
|
{
|
||||||
|
options.neomutt = {
|
||||||
|
enable = mkOption {
|
||||||
|
type = types.enum [ "none" "maildir" "imap" ];
|
||||||
|
default = "none";
|
||||||
|
description = ''
|
||||||
|
Whether to enable this account in NeoMutt and which
|
||||||
|
account protocol to use.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
imap.idle = mkOption {
|
||||||
|
type = types.bool;
|
||||||
|
default = false;
|
||||||
|
description = ''
|
||||||
|
If set, NeoMutt will attempt to use the IDLE extension.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
mailboxes = mkOption {
|
||||||
|
type = types.listOf types.str;
|
||||||
|
default = [];
|
||||||
|
example = ["github" "Lists/nix" "Lists/haskell-cafe"];
|
||||||
|
description = ''
|
||||||
|
A list of mailboxes.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
extraConfig = mkOption {
|
||||||
|
type = types.lines;
|
||||||
|
default = "";
|
||||||
|
example = "color status cyan default";
|
||||||
|
description = ''
|
||||||
|
Extra lines to add to the folder hook for this account.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
374
modules/programs/neomutt.nix
Normal file
374
modules/programs/neomutt.nix
Normal file
|
@ -0,0 +1,374 @@
|
||||||
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
|
with lib;
|
||||||
|
|
||||||
|
let
|
||||||
|
|
||||||
|
cfg = config.programs.neomutt;
|
||||||
|
|
||||||
|
# Accounts for which neomutt is enabled.
|
||||||
|
neomuttAccounts =
|
||||||
|
filter
|
||||||
|
(a: a.neomutt.enable != "none")
|
||||||
|
(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.string;
|
||||||
|
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.string;
|
||||||
|
example = "<left>";
|
||||||
|
description = "The key to bind.";
|
||||||
|
};
|
||||||
|
|
||||||
|
action = mkOption {
|
||||||
|
type = types.string;
|
||||||
|
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"];
|
||||||
|
|
||||||
|
# Path to the file that will contain the account folder-hook
|
||||||
|
# settings.
|
||||||
|
genAccountFileName = accountName:
|
||||||
|
"${config.xdg.configHome}/neomutt/account-${accountName}";
|
||||||
|
|
||||||
|
genCommonFolderHooks = account: with account;
|
||||||
|
let
|
||||||
|
smtpProto = if smtp.tls.enable then "smtps" else "smtp";
|
||||||
|
smtpBaseUrl = "${smtpProto}://${escape userName}@${smtp.host}";
|
||||||
|
passCmd = concatStringsSep " " passwordCommand;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
imap_user = null;
|
||||||
|
imap_pass = null;
|
||||||
|
imap_idle = null;
|
||||||
|
tunnel = null;
|
||||||
|
from = "'${address}'";
|
||||||
|
realname = "'${realName}'";
|
||||||
|
spoolfile = "'+${folders.inbox}'";
|
||||||
|
record = if folders.sent == null then null else "'+${folders.sent}'";
|
||||||
|
postponed = "'+${folders.drafts}'";
|
||||||
|
trash = "'+${folders.trash}'";
|
||||||
|
smtp_url = "'${smtpBaseUrl}'";
|
||||||
|
smtp_pass = "'`${passCmd}`'";
|
||||||
|
};
|
||||||
|
|
||||||
|
genFolderHookFile = account: customConf: with account;
|
||||||
|
{
|
||||||
|
target = genAccountFileName name;
|
||||||
|
source = pkgs.writeText "neomutt-account-${name}" (
|
||||||
|
concatStringsSep "\n" (
|
||||||
|
[ "# Generated by Home Manager.\n" ]
|
||||||
|
++ mapAttrsToList setOption (genCommonFolderHooks account // customConf)
|
||||||
|
++ optional (neomutt.extraConfig != "") neomutt.extraConfig
|
||||||
|
)
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
genMaildirAccountConfig = account: with account;
|
||||||
|
let
|
||||||
|
accountFileName = genAccountFileName name;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
mainConfig = ''
|
||||||
|
mailboxes ${account.maildir.absPath}/${folders.inbox}
|
||||||
|
folder-hook ${account.maildir.absPath}/ source ${accountFileName}
|
||||||
|
''
|
||||||
|
+ optionalString account.primary ''
|
||||||
|
source ${genAccountFileName name}
|
||||||
|
'';
|
||||||
|
|
||||||
|
folderHookFile = genFolderHookFile account {
|
||||||
|
folder = "'${account.maildir.absPath}'";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
genImapAccountConfig = account: with account;
|
||||||
|
let
|
||||||
|
imapProto = if imap.tls.enable then "imaps" else "imap";
|
||||||
|
imapBaseUrl = "${imapProto}://${userName}@${imap.host}";
|
||||||
|
imapBaseUrlEscape = "${imapProto}://${escape userName}@${imap.host}";
|
||||||
|
passCmd = concatStringsSep " " passwordCommand;
|
||||||
|
|
||||||
|
accountFileName = genAccountFileName name;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
mainConfig =
|
||||||
|
''
|
||||||
|
account-hook '${imapBaseUrl}/' " \
|
||||||
|
set imap_user='${userName}' \
|
||||||
|
set imap_pass='`${passCmd}`' \
|
||||||
|
unset tunnel"
|
||||||
|
mailboxes '${imapBaseUrlEscape}/${folders.inbox}'
|
||||||
|
folder-hook '${imapBaseUrlEscape}/' source ${accountFileName}"
|
||||||
|
''
|
||||||
|
+ optionalString account.primary ''
|
||||||
|
source ${genAccountFileName name}
|
||||||
|
'';
|
||||||
|
|
||||||
|
folderHookFile = genFolderHookFile account {
|
||||||
|
imap_user="'${userName}'";
|
||||||
|
imap_pass="'`${passCmd}`'";
|
||||||
|
imap_idle = yesno neomutt.imap.idle;
|
||||||
|
folder = "'${imapBaseUrlEscape}'";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
genAccountConfig = account: with account;
|
||||||
|
if account.neomutt.enable == "imap" && account.imap != null then
|
||||||
|
genImapAccountConfig account
|
||||||
|
else if account.neomutt.enable == "maildir" && account.maildir != null then
|
||||||
|
genMaildirAccountConfig account
|
||||||
|
else
|
||||||
|
null;
|
||||||
|
|
||||||
|
accountConfigs = map genAccountConfig neomuttAccounts;
|
||||||
|
|
||||||
|
neomuttrcStr =
|
||||||
|
let
|
||||||
|
|
||||||
|
gpgSection = ''
|
||||||
|
set crypt_use_gpgme = yes
|
||||||
|
set crypt_autosign = yes
|
||||||
|
set pgp_use_gpg_agent = yes
|
||||||
|
'';
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
accountsSection =
|
||||||
|
concatMapStringsSep "\n" (getAttr "mainConfig") accountConfigs;
|
||||||
|
|
||||||
|
mailCheckSection = ''
|
||||||
|
set mail_check_stats
|
||||||
|
set mail_check_stats_interval = ${toString cfg.checkStatsInterval}
|
||||||
|
'';
|
||||||
|
|
||||||
|
in
|
||||||
|
|
||||||
|
# Some defaults are left unconfigurable
|
||||||
|
''
|
||||||
|
# Generated by Home Manager.
|
||||||
|
|
||||||
|
set ssl_force_tls = yes
|
||||||
|
|
||||||
|
set mbox_type = Maildir
|
||||||
|
set sort = "${cfg.sort}"
|
||||||
|
set header_cache = "${config.xdg.cacheHome}/neomutt/headers/"
|
||||||
|
set message_cachedir = "${config.xdg.cacheHome}/neomutt/messages/"
|
||||||
|
set editor = "${cfg.editor}"
|
||||||
|
|
||||||
|
${optionalString cfg.gpg gpgSection}
|
||||||
|
|
||||||
|
${optionalString (cfg.checkStatsInterval != null) mailCheckSection}
|
||||||
|
|
||||||
|
set implicit_autoview = yes
|
||||||
|
|
||||||
|
alternative_order text/enriched text/plain text
|
||||||
|
|
||||||
|
set delete = yes
|
||||||
|
|
||||||
|
# Binds and macros
|
||||||
|
${bindSection}
|
||||||
|
${macroSection}
|
||||||
|
|
||||||
|
${optionalString cfg.sidebar.enable sidebarSection}
|
||||||
|
|
||||||
|
${optionalString (cfg.theme != null) "source ${cfg.theme}"}
|
||||||
|
|
||||||
|
${accountsSection}
|
||||||
|
|
||||||
|
# Extra configuration
|
||||||
|
${cfg.extraConfig}
|
||||||
|
'';
|
||||||
|
|
||||||
|
in
|
||||||
|
|
||||||
|
{
|
||||||
|
options = {
|
||||||
|
programs.neomutt = {
|
||||||
|
enable = mkEnableOption "the neomutt mail client";
|
||||||
|
|
||||||
|
gpg = mkOption {
|
||||||
|
type = types.bool;
|
||||||
|
default = false;
|
||||||
|
description = "Enable gpg support.";
|
||||||
|
};
|
||||||
|
|
||||||
|
sidebar = mkOption {
|
||||||
|
type = sidebarModule;
|
||||||
|
default = {};
|
||||||
|
description = "Options related to the sidebar.";
|
||||||
|
};
|
||||||
|
|
||||||
|
binds = mkOption {
|
||||||
|
type = types.listOf bindModule;
|
||||||
|
default = [];
|
||||||
|
description = "List of keybindings.";
|
||||||
|
};
|
||||||
|
|
||||||
|
macros = mkOption {
|
||||||
|
# I'm sharing the definition of bind, because the fields are pretty
|
||||||
|
# much the same
|
||||||
|
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.";
|
||||||
|
};
|
||||||
|
|
||||||
|
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.string;
|
||||||
|
default = "$EDITOR";
|
||||||
|
example = "${pkgs.nano}/bin/nano";
|
||||||
|
description = "Select the editor used for writing mail.";
|
||||||
|
};
|
||||||
|
|
||||||
|
theme = mkOption {
|
||||||
|
type = types.nullOr types.path;
|
||||||
|
default = null;
|
||||||
|
description = ''
|
||||||
|
Path to theme file. Warning this can contain any muttrc
|
||||||
|
configuration, including system calls.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
extraConfig = mkOption {
|
||||||
|
type = types.lines;
|
||||||
|
default = "";
|
||||||
|
description = "Extra configuration appended to the end.";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = mkIf cfg.enable {
|
||||||
|
assertions = [
|
||||||
|
(
|
||||||
|
let
|
||||||
|
badAccounts =
|
||||||
|
filter
|
||||||
|
(a: a.neomutt.enable == "maildir" && a.maildir == null)
|
||||||
|
neomuttAccounts;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
assertion = badAccounts == [];
|
||||||
|
message = "neomutt: Missing maildir configuration for accounts: "
|
||||||
|
+ concatMapStringsSep ", " (a: a.name) badAccounts;
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
(
|
||||||
|
let
|
||||||
|
badAccounts =
|
||||||
|
filter
|
||||||
|
(a: a.neomutt.enable == "imap" && a.imap == null)
|
||||||
|
neomuttAccounts;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
assertion = badAccounts == [];
|
||||||
|
message = "neomutt: Missing IMAP configuration for accounts: "
|
||||||
|
+ concatMapStringsSep ", " (a: a.name) badAccounts;
|
||||||
|
}
|
||||||
|
)
|
||||||
|
];
|
||||||
|
|
||||||
|
home.packages = [ pkgs.neomutt ];
|
||||||
|
|
||||||
|
home.file = map (getAttr "folderHookFile") accountConfigs;
|
||||||
|
|
||||||
|
xdg.configFile."neomutt/neomuttrc".text = neomuttrcStr;
|
||||||
|
};
|
||||||
|
}
|
Loading…
Reference in a new issue