aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--modules/communication/neomutt/.neomuttrc20
-rw-r--r--modules/communication/neomutt/account/.neomuttrc4
-rw-r--r--modules/communication/neomutt/account/default.nix36
-rw-r--r--modules/communication/neomutt/account/flavors/gmail/.neomuttrc2
-rw-r--r--modules/communication/neomutt/account/flavors/gmail/default.nix28
-rw-r--r--modules/communication/neomutt/account/options.nix8
-rw-r--r--modules/communication/neomutt/account/sync-channel.nix11
-rw-r--r--modules/communication/neomutt/default.nix52
-rw-r--r--modules/communication/neomutt/lib.nix18
-rw-r--r--modules/communication/neomutt/mail/mbsync.nix89
10 files changed, 91 insertions, 177 deletions
diff --git a/modules/communication/neomutt/.neomuttrc b/modules/communication/neomutt/.neomuttrc
index bc6779a..dee49a8 100644
--- a/modules/communication/neomutt/.neomuttrc
+++ b/modules/communication/neomutt/.neomuttrc
@@ -1,33 +1,20 @@
-# Read messages in Neovim. `-` makes Neovim read the message from
-# stdin and -R prevents accidental edits to message content.\
-
-# Return directly to the index when Neovim exits and do not prepend
-# NeoMutt’s pager status line to the message passed to Neovim.
set noprompt_after
set pager_format = ""
-# Base16 OneDark Dark terminal colors for neomutt
-# Each column in the index receives a distinct color to keep the UI organized.
set menu_scroll = yes
set pager_stop = yes
-# Enable custom From headers and ask for confirmation/editing
set use_from = yes
set reverse_name = yes
set autoedit = no
set edit_headers = yes
-# cancel any prompt/command-line entry with Esc, vim-style
set abort_key = "<Esc>"
-# attachments: use our mailcap for dedicated openers,
-# and auto-render html/images inline where sensible
set mailcap_path = "~/.config/neomutt/mailcap"
auto_view text/plain
alternative_order text/html image/png image/jpeg image/gif application/pdf
-# Nerd Font icon-based flag/attachment/crypto indicators
-# order: new, old, deleted, flagged, replied, old(unused), tagged, encrypt, ...
set flag_chars = "󰓹󰀼󰆴󰁟󰇰󰇮󰍩󰍨󰇱󰗚"
set to_chars = " "
set crypt_chars = " "
@@ -35,10 +22,8 @@ set attach_format = "%u%D%I %t%4n %T%.40d %> [%m/%M, %e%?C?, %C?, %s] "
set index_format = " %5C │ %Z │ %{%d/%m/%y %H:%M} │ %-25.25a │ %s%* "
-# Hide the keybindings help bar at the top to save vertical space
-set help = no
+set help = yes
-# Status bar with Nerd Font icons per field
set status_format = "  Unread: %5u │ 󰛏 New: %5n │  Tagged: %5t │  Filter: %V │  Sorted By: %s "
# --- Basic UI Colors --------------------------------------------------
@@ -62,7 +47,6 @@ color tree magenta default # base03 (Thread arrows)
color index white default # base05
# --- Index Columns (The Multi-Color Table) ----------------------------
-# Applies distinct colors to specific columns for ALL messages (~A)
color index_number cyan default "~A" # base05 (Fixed: was brightblack)
color index_date green default "~A" # base0B (Green)
color index_flags red default "~A" # base08 (Red)
@@ -75,8 +59,6 @@ color index_tag cyan default # base0C (Message tags, %G)
color index_tags cyan default # 󰓼 base0C (Transformed tags, %g %J)
# --- Index Message States ---------------------------------------------
-# By targeting *only* `index_subject`, you preserve your multi-color
-# columns while still easily identifying unread or flagged emails.
color index_subject blue default "~U" # Unread: Blue (base0D)
color index_subject blue default "~N" # 󰄯 New: Blue (base0D)
color index_subject red default "~F" # Flagged: Red (base08)
diff --git a/modules/communication/neomutt/account/.neomuttrc b/modules/communication/neomutt/account/.neomuttrc
index 2f8c9f2..37dc9aa 100644
--- a/modules/communication/neomutt/account/.neomuttrc
+++ b/modules/communication/neomutt/account/.neomuttrc
@@ -1,2 +1,2 @@
-macro index,pager gs "<enter-command>set my_wait_key=$wait_key wait_key=no<enter><sync-mailbox><shell-escape>neomutt-sync @@QUICK_CHANNEL@@<enter><sync-mailbox><enter-command>set wait_key=$my_wait_key<enter>"
-macro index,pager gS "<enter-command>set my_wait_key=$wait_key wait_key=no<enter><sync-mailbox><shell-escape>neomutt-sync @@FULL_CHANNEL@@<enter><sync-mailbox><enter-command>set wait_key=$my_wait_key<enter>"
+macro index,pager gs "<enter-command>set my_wait_key=$wait_key wait_key=no<enter><sync-mailbox><shell-escape>neomutt-sync @@QUICK_GROUP@@<enter><sync-mailbox><enter-command>set wait_key=$my_wait_key<enter>"
+macro index,pager gS "<enter-command>set my_wait_key=$wait_key wait_key=no<enter><sync-mailbox><shell-escape>neomutt-sync @@FULL_GROUP@@<enter><sync-mailbox><enter-command>set wait_key=$my_wait_key<enter>"
diff --git a/modules/communication/neomutt/account/default.nix b/modules/communication/neomutt/account/default.nix
index 07a4b89..1d8046a 100644
--- a/modules/communication/neomutt/account/default.nix
+++ b/modules/communication/neomutt/account/default.nix
@@ -2,6 +2,7 @@
{ config, lib, ... }:
let
cfg = config.communication.neomutt;
+ mbsyncGroupNames = (import ../lib.nix { inherit lib; }).mbsyncGroupNames;
in
{
imports = [
@@ -47,10 +48,10 @@ in
inherit (accountInformation.folders) inbox trash;
}
// lib.optionalAttrs (accountInformation.folders.drafts != null) {
- drafts = accountInformation.folders.drafts;
+ inherit (accountInformation.folders) drafts;
}
// lib.optionalAttrs (accountInformation.folders.sent != null) {
- sent = accountInformation.folders.sent;
+ inherit (accountInformation.folders) sent;
};
neomutt = {
@@ -62,14 +63,43 @@ in
mbsync = {
enable = true;
create = accountInformation.mbsync.create;
+ expunge = "both";
patterns = accountInformation.mbsync.patterns;
flatten = accountInformation.mbsync.flatten;
extraConfig = {
- account = accountInformation.mbsync.extraConfig.account;
+ account = {
+ PipelineDepth = 50;
+ }
+ // accountInformation.mbsync.extraConfig.account;
channel = accountInformation.mbsync.extraConfig.channel;
local = accountInformation.mbsync.extraConfig.local;
remote = accountInformation.mbsync.extraConfig.remote;
};
+
+ groups =
+ let
+ group = mbsyncGroupNames accountName;
+
+ mkChannels =
+ sync:
+ lib.mapAttrs (local: remote: {
+ farPattern = remote;
+ nearPattern = local;
+ extraConfig = {
+ Create = "Near";
+ Expunge = "Both";
+ Sync = sync;
+ SyncState = "*";
+ };
+ }) accountInformation.mbsync.folders.map;
+ in
+ {
+ "${group.full}".channels = mkChannels "All";
+ "${group.quick}".channels = mkChannels [
+ "Pull"
+ "New"
+ ];
+ };
};
notmuch = {
diff --git a/modules/communication/neomutt/account/flavors/gmail/.neomuttrc b/modules/communication/neomutt/account/flavors/gmail/.neomuttrc
index c87bba0..2106b65 100644
--- a/modules/communication/neomutt/account/flavors/gmail/.neomuttrc
+++ b/modules/communication/neomutt/account/flavors/gmail/.neomuttrc
@@ -1,2 +1,2 @@
-mailboxes =Inbox ="[Gmail]/Drafts" ="[Gmail]/Sent Mail" ="[Gmail]/Spam" ="[Gmail]/Trash"
+mailboxes =inbox =drafts =sent =spam =trash
unset record
diff --git a/modules/communication/neomutt/account/flavors/gmail/default.nix b/modules/communication/neomutt/account/flavors/gmail/default.nix
index b0b7733..ea696b2 100644
--- a/modules/communication/neomutt/account/flavors/gmail/default.nix
+++ b/modules/communication/neomutt/account/flavors/gmail/default.nix
@@ -8,25 +8,25 @@
{
config = lib.mkIf (config.flavor == "gmail.com") {
folders = {
- inbox = lib.mkDefault "Inbox";
- drafts = lib.mkDefault "[Gmail]/Drafts";
- sent = lib.mkDefault "[Gmail]/Sent Mail";
- trash = lib.mkDefault "[Gmail]/Trash";
+ inbox = lib.mkDefault "inbox";
+ drafts = lib.mkDefault "drafts";
+ sent = lib.mkDefault "sent";
+ trash = lib.mkDefault "trash";
};
mbsync = {
create = lib.mkDefault "maildir";
- patterns = lib.mkDefault [
- "INBOX"
- "[Gmail]/Drafts"
- "[Gmail]/Sent Mail"
- "[Gmail]/Spam"
- ];
+ patterns = lib.mkDefault [ "INBOX" ];
+ folders.map = lib.mkDefault {
+ inbox = "INBOX";
+ drafts = "[Gmail]/Drafts";
+ sent = "[Gmail]/Sent Mail";
+ spam = "[Gmail]/Spam";
+ trash = "[Gmail]/Trash";
+ };
extraConfig.channel = {
Sync = lib.mkDefault "All";
CopyArrivalDate = lib.mkDefault "yes";
- Expunge = lib.mkDefault "Both";
- SyncState = lib.mkDefault "*";
};
};
@@ -34,8 +34,8 @@
notmuch.neomutt.virtual-mailboxes = lib.mkDefault [
{
- name = "All Mail";
- query = "folder:${name}/Inbox or folder:\"${name}/[Gmail]/Sent Mail\"";
+ name = "all";
+ query = "folder:${name}/inbox or folder:\"${name}/sent\"";
}
];
};
diff --git a/modules/communication/neomutt/account/options.nix b/modules/communication/neomutt/account/options.nix
index 676f8b0..3090db2 100644
--- a/modules/communication/neomutt/account/options.nix
+++ b/modules/communication/neomutt/account/options.nix
@@ -121,6 +121,14 @@
description = "Flatten hierarchy delimiter.";
};
+ folders = {
+ map = lib.mkOption {
+ type = lib.types.attrsOf lib.types.str;
+ default = { };
+ description = "Local folder name -> remote folder name, for folders that should be renamed locally.";
+ };
+ };
+
extraConfig = {
account = lib.mkOption {
type = lib.types.attrsOf (
diff --git a/modules/communication/neomutt/account/sync-channel.nix b/modules/communication/neomutt/account/sync-channel.nix
index 2252594..cb966c8 100644
--- a/modules/communication/neomutt/account/sync-channel.nix
+++ b/modules/communication/neomutt/account/sync-channel.nix
@@ -5,20 +5,19 @@
...
}:
let
-
- mbsyncNamesFromName = (import ../lib.nix { inherit lib; }).mbsyncNamesFromName;
+ mbsyncGroupNames = (import ../lib.nix { inherit lib; }).mbsyncGroupNames;
in
{
config = lib.mkIf config.enable {
neomutt.extraConfig =
let
- mbsyncNames = mbsyncNamesFromName name;
+ group = mbsyncGroupNames name;
in
builtins.replaceStrings
- [ "@@QUICK_CHANNEL@@" "@@FULL_CHANNEL@@" ]
+ [ "@@QUICK_GROUP@@" "@@FULL_GROUP@@" ]
[
- mbsyncNames.channels.quick
- mbsyncNames.channels.full
+ group.quick
+ group.full
]
(builtins.readFile ./.neomuttrc);
};
diff --git a/modules/communication/neomutt/default.nix b/modules/communication/neomutt/default.nix
index 6189b23..40c8950 100644
--- a/modules/communication/neomutt/default.nix
+++ b/modules/communication/neomutt/default.nix
@@ -8,16 +8,7 @@
let
cfg = config.communication.neomutt;
icons = config.desktop.icons.apps;
-
- mbsyncNamesFromName = (import ./lib.nix { inherit lib; }).mbsyncNamesFromName;
-
- fullSyncChannels = lib.mapAttrsToList (name: account: (mbsyncNamesFromName name).channels.full) (
- lib.filterAttrs (name: account: account.enable) cfg.accounts
- );
-
- quickSyncChannels = lib.mapAttrsToList (name: account: (mbsyncNamesFromName name).channels.quick) (
- lib.filterAttrs (name: account: account.enable) cfg.accounts
- );
+ mbsyncGroupNames = (import ./lib.nix { inherit lib; }).mbsyncGroupNames;
neomuttSyncScript = pkgs.writeShellApplication {
name = "neomutt-sync";
@@ -34,27 +25,26 @@ let
text = builtins.readFile ./neomutt-sync.sh;
};
- neomuttSyncDaemon = pkgs.writeShellApplication {
- name = "neomutt-sync-daemon";
- runtimeInputs = [
- config.terminal.bash.package
- pkgs.coreutils
- pkgs.procps
- config.programs.mbsync.package
- config.programs.notmuch.package
- ];
- text =
- builtins.replaceStrings
- [
- "@@QUICK_CHANNELS@@"
- "@@FULL_CHANNELS@@"
- ]
- [
- (lib.concatStringsSep "," quickSyncChannels)
- (lib.concatStringsSep "," fullSyncChannels)
- ]
- (builtins.readFile ./neomutt-sync-daemon.sh);
- };
+ neomuttSyncDaemon =
+ let
+ accountNames = lib.attrNames (lib.filterAttrs (_: a: a.enable) cfg.accounts);
+ groupsFor = kind: lib.concatStringsSep "," (map (n: (mbsyncGroupNames n).${kind}) accountNames);
+ in
+ pkgs.writeShellApplication {
+ name = "neomutt-sync-daemon";
+ runtimeInputs = [
+ config.terminal.bash.package
+ pkgs.coreutils
+ pkgs.procps
+ config.programs.mbsync.package
+ config.programs.notmuch.package
+ ];
+ text =
+ lib.replaceStrings
+ [ "@@QUICK_GROUPS@@" "@@FULL_GROUPS@@" ]
+ [ (groupsFor "quick") (groupsFor "full") ]
+ (builtins.readFile ./neomutt-sync-daemon.sh);
+ };
neomuttLauncher = pkgs.writeShellApplication {
name = "neomutt-launcher";
diff --git a/modules/communication/neomutt/lib.nix b/modules/communication/neomutt/lib.nix
index 253ada8..7b85e5e 100644
--- a/modules/communication/neomutt/lib.nix
+++ b/modules/communication/neomutt/lib.nix
@@ -1,20 +1,14 @@
# some basic common utility functions for neomutt
{ lib, ... }:
{
- mbsyncNamesFromName =
- name:
+ mbsyncGroupNames =
+ accountName:
let
- channelNameBase = lib.replaceStrings [ "@" "." ] [ "-" "_" ] name;
+ base = lib.replaceStrings [ "@" "." ] [ "-" "_" ] accountName;
in
{
- base = channelNameBase;
- channels = {
- full = "${channelNameBase}-full";
- quick = "${channelNameBase}-quick";
- };
- servers = {
- remote = "${channelNameBase}-remote";
- local = "${channelNameBase}-local";
- };
+ inherit base;
+ full = "${base}-full";
+ quick = "${base}-quick";
};
}
diff --git a/modules/communication/neomutt/mail/mbsync.nix b/modules/communication/neomutt/mail/mbsync.nix
index b93b134..66964e0 100644
--- a/modules/communication/neomutt/mail/mbsync.nix
+++ b/modules/communication/neomutt/mail/mbsync.nix
@@ -6,98 +6,9 @@
}:
let
cfg = config.communication.neomutt;
-
- mbsyncNamesFromName = (import ../lib.nix { inherit lib; }).mbsyncNamesFromName;
-
- mbsyncValue =
- value:
- if lib.isList value then
- lib.concatStringsSep " " (map mbsyncValue value)
- else if lib.isBool value then
- lib.hm.booleans.yesNo value
- else if lib.isInt value then
- toString value
- else if lib.isString value then
- if builtins.match ".* .*" value != null then ''"${lib.escape [ ''"'' ] value}"'' else value
- else
- throw "Unsupported mbsync value";
-
- mbsyncSection = name: attrs: ''
- ${name}
- ${lib.concatStringsSep "\n" (lib.mapAttrsToList (n: v: "${n} ${mbsyncValue v}") attrs)}
- '';
-
- mbsyncAccount =
- account:
- let
- mbsyncNames = mbsyncNamesFromName account.name;
- in
- lib.concatStringsSep "\n" [
- (mbsyncSection "IMAPAccount ${mbsyncNames.base}" (
- {
- Host = account.imap.host;
- User = account.userName;
- PipelineDepth = 50;
- TLSType =
- if !account.imap.tls.enable then
- "None"
- else if account.imap.tls.useStartTls then
- "STARTTLS"
- else
- "IMAPS";
- }
- // lib.optionalAttrs (account.passwordCommand != null) {
- PassCmd = toString account.passwordCommand;
- }
- // lib.optionalAttrs (account.imap.tls.certificatesFile != null) {
- CertificateFile = toString account.imap.tls.certificatesFile;
- }
- // lib.optionalAttrs (account.imap.port != null) {
- Port = account.imap.port;
- }
- ))
-
- (mbsyncSection "IMAPStore ${mbsyncNames.servers.remote}" {
- Account = mbsyncNames.base;
- })
-
- (mbsyncSection "MaildirStore ${mbsyncNames.servers.local}" {
- Path = "${account.maildir.absPath}/";
- Inbox = "${account.maildir.absPath}/${account.folders.inbox}";
- SubFolders = "Verbatim";
- })
-
- (mbsyncSection "Channel ${mbsyncNames.channels.quick}" {
- Far = ":${mbsyncNames.servers.remote}:\"INBOX\"";
- Near = ":${mbsyncNames.servers.local}:\"INBOX\"";
- Create = "Near";
- Expunge = "None";
- Sync = [
- "Pull"
- "New"
- ];
- SyncState = "*";
- })
-
- (mbsyncSection "Channel ${mbsyncNames.channels.full}" {
- Far = ":${mbsyncNames.servers.remote}:";
- Near = ":${mbsyncNames.servers.local}:";
- Patterns = account.mbsync.patterns;
- Create = "Near";
- Expunge = "Both";
- Sync = "All";
- SyncState = "*";
- })
- ];
-
- accounts = lib.filter (account: account.enable && account.mbsync.enable) (
- lib.attrValues config.accounts.email.accounts
- );
in
{
config = lib.mkIf cfg.enable {
programs.mbsync.enable = true;
-
- xdg.configFile."mbsync/.mbsyncrc".text = lib.concatStringsSep "\n" (map mbsyncAccount accounts);
};
}