From 6b5020927fbb0a041f54c2224d4734e97cf78097 Mon Sep 17 00:00:00 2001 From: Arpit Chakladar Date: Wed, 15 Jul 2026 21:55:29 +0530 Subject: feat: reworked the structure for communication/neomutt Using neomutt as the module for email instead of just "email" as used previously. "email" was ambigious in that it was too vague on what it was supposed to do with email, now neomutt clearly specifies that we plan to use neomutt as our email client. However mbsync and notmuch are still used under the hood that is not reflected in the module name "neomutt". This is fine as they only serve the purpose of downloading and querying the emails which may be considered a background feature. --- modules/communication/neomutt/default.nix | 429 +----------------------------- 1 file changed, 9 insertions(+), 420 deletions(-) (limited to 'modules/communication/neomutt/default.nix') diff --git a/modules/communication/neomutt/default.nix b/modules/communication/neomutt/default.nix index be3045d..34147fd 100644 --- a/modules/communication/neomutt/default.nix +++ b/modules/communication/neomutt/default.nix @@ -1,431 +1,20 @@ -# neomutt - Terminal email client -{ - config, - lib, - pkgs, - ... -}: -let - neomuttDesktopItem = pkgs.makeDesktopItem { - name = "neomutt"; - desktopName = "NeoMutt"; - exec = "${lib.getExe config.programs.kitty.package} -e ${lib.getExe config.programs.neomutt.package}"; - icon = "kitty"; - categories = [ - "Network" - "Email" - ]; - comment = "Terminal email client"; - terminal = false; - type = "Application"; - }; -in +{ config, lib, ... }: + { imports = [ + ./account + ./sync + ./neomutt.nix ./assertions.nix ./theme.nix ]; + options.communication.neomutt = { - enable = lib.mkEnableOption "Enables neomutt."; + enable = lib.mkEnableOption "Email suite (neomutt + mbsync + notmuch)"; }; config = lib.mkIf config.communication.neomutt.enable { - xdg.mimeApps.defaultApplications = { - "x-scheme-handler/mailto" = "neomutt.desktop"; - }; - - home.packages = [ - pkgs.urlscan - pkgs.w3m - neomuttDesktopItem - ]; - - xdg.configFile."neomutt/mailcap".text = '' - text/html; w3m -dump -T text/html '%s'; copiousoutput; nametemplate=%s.html - text/html; $BROWSER '%s'; nametemplate=%s.html - image/*; xdg-open '%s' & - application/pdf; xdg-open '%s'; nametemplate=%s.pdf - video/*; xdg-open '%s' & - audio/*; xdg-open '%s' & - application/*; xdg-open '%s' & - ''; - - xdg.configFile."neomutt/flag_legend.txt".text = '' - NeoMutt Index Flags - =================== - - Message state ($flag_chars) -- unchanged defaults - N New - unread, arrived since you last checked - O Old - unread, but seen in a previous session - D Deleted - marked for deletion (pending expunge) - d Att-del - has attachments marked for deletion - ! Flagged - important (toggle with F) - * Tagged - selected for a bulk operation (toggle with t) - r Replied - you've replied to this message - (blank) - read, nothing else notable - - Cryptography ($crypt_chars) -  Verified - signed, and the signature checks out -  Encrypted - PGP/SMIME encrypted -  Signed - PGP/SMIME signed (unverified) -  PGP key - message contains a PGP public key - (blank) - no cryptography info - - Addressing ($to_chars) -  To you only - sent to you and only you -  To (with others) - you're in the To: list, among others -  Cc only - you're only in the Cc: list -  From you - sent by you -  Mailing list - sent to a list you're subscribed to - (blank) - not in To/Cc (e.g. Bcc, unlisted) - - Press q to close. - ''; - - programs.neomutt = { - sidebar.enable = true; - sort = "reverse-threads"; - vimKeys = true; - unmailboxes = true; - checkStatsInterval = 20; - - extraConfig = '' - set menu_scroll = yes - - # cancel any prompt/command-line entry with Esc, vim-style - set abort_key = "" - - # attachments: use our mailcap for dedicated openers, - # and auto-render html/images inline where sensible - set mailcap_path = "~/.config/neomutt/mailcap" - auto_view text/html image/png image/jpeg image/gif application/pdf - ''; - - binds = [ - # --- sidebar navigation (vim: k=up, j=down) --- - { - map = [ - "index" - "pager" - ]; - key = "\\CK"; - action = "sidebar-prev"; - } - { - map = [ - "index" - "pager" - ]; - key = "\\CJ"; - action = "sidebar-next"; - } - { - # select the highlighted mailbox directly, no Ctrl+O needed - map = [ - "index" - "pager" - ]; - key = "o"; - action = "sidebar-open"; - } - - # --- open / go deeper (vim: l = right/forward) --- - { - map = [ "index" ]; - key = ""; - action = "display-message"; - } - { - map = [ "index" ]; - key = "l"; - action = "display-message"; - } - { - map = [ "browser" ]; - key = ""; - action = "select-entry"; - } - { - map = [ "browser" ]; - key = "l"; - action = "select-entry"; - } - { - map = [ "attach" ]; - key = ""; - action = "view-attach"; - } - { - map = [ "attach" ]; - key = "l"; - action = "view-attach"; - } - { - map = [ - "alias" - "query" - ]; - key = ""; - action = "select-entry"; - } - - # --- back / exit (vim: h = left/back) --- - { - map = [ "pager" ]; - key = "h"; - action = "exit"; - } - { - map = [ "browser" ]; - key = "h"; - action = "exit"; - } - { - map = [ "attach" ]; - key = "h"; - action = "exit"; - } - { - map = [ "index" ]; - key = "h"; - action = "collapse-thread"; - } - - # --- pager line scrolling (vim: j/k move by line) --- - { - map = [ "pager" ]; - key = "j"; - action = "next-line"; - } - { - map = [ "pager" ]; - key = "k"; - action = "previous-line"; - } - { - # kept from before: jump straight to the next unread message, - # extends the h/l "back/forward" metaphor already in use - map = [ "pager" ]; - key = "l"; - action = "next-unread"; - } - - # --- top/bottom of buffer (vim: gg/G -- NOT 0/$, which mean - # start/end of *line* in vim and would be a false friend here) --- - { - map = [ "index" ]; - key = "gg"; - action = "first-entry"; - } - { - map = [ "index" ]; - key = "G"; - action = "last-entry"; - } - { - map = [ "pager" ]; - key = "gg"; - action = "top"; - } - { - map = [ "pager" ]; - key = "G"; - action = "bottom"; - } - { - map = [ "browser" ]; - key = "gg"; - action = "first-entry"; - } - { - map = [ "browser" ]; - key = "G"; - action = "last-entry"; - } - - # --- page scrolling (vim: Ctrl-f/b full page, Ctrl-d/u half page) --- - { - map = [ "pager" ]; - key = "\\Cf"; - action = "next-page"; - } - { - map = [ "pager" ]; - key = "\\Cb"; - action = "previous-page"; - } - { - map = [ "pager" ]; - key = "\\Cd"; - action = "half-down"; - } - { - map = [ "pager" ]; - key = "\\Cu"; - action = "half-up"; - } - { - # index has no half-page concept, so Ctrl-d/u fall back to - # the same full-page scroll as Ctrl-f/b - map = [ "index" ]; - key = "\\Cf"; - action = "next-page"; - } - { - map = [ "index" ]; - key = "\\Cb"; - action = "previous-page"; - } - { - map = [ "index" ]; - key = "\\Cd"; - action = "half-down"; - } - { - map = [ "index" ]; - key = "\\Cu"; - action = "half-up"; - } - - # --- search (vim: / forward, ? backward, n/N repeat) --- - { - map = [ - "index" - "pager" - ]; - key = "/"; - action = "search"; - } - { - map = [ - "index" - "pager" - ]; - key = "?"; - action = "search-reverse"; - } - { - map = [ - "index" - "pager" - ]; - key = "n"; - action = "search-next"; - } - { - map = [ - "index" - "pager" - ]; - key = "N"; - action = "search-opposite"; - } - - { - map = [ - "index" - "pager" - ]; - key = "u"; - action = "undelete-message"; - } - - # --- copy (vim: yy yank -- non-destructive, unlike save-message - # which moves/deletes the original) --- - { - map = [ "index" ]; - key = "y"; - action = "noop"; - } - { - map = [ "index" ]; - key = "yy"; - action = "copy-message"; - } - - # --- tagging (vim: v/V visual select single/whole block) --- - # NOTE: this overrides neomutt's default "v" (view-attachments). - # Attachments are still reachable from the pager/index via the - # mailcap auto-view or the attach menu, but if you want plain - # "v" back for view-attachments, just delete these two binds. - { - map = [ "index" ]; - key = "v"; - action = "tag-entry"; - } - { - map = [ "index" ]; - key = "V"; - action = "tag-thread"; - } - - # --- mailbox switching (vim: gt = next tab) --- - { - map = [ "index" ]; - key = "gt"; - action = "next-unread-mailbox"; - } - - # --- filter/limit (vim: gf to 'find' or 'filter') --- - { - map = [ "index" ]; - key = "gf"; - action = "limit"; - } - - # --- filter/limit (vim: gf to 'find' or 'filter') --- - { - map = [ "index" ]; - key = "gF"; - action = "limit"; - } - - # --- help message to show functions and keybindings --- - { - map = [ - "index" - "pager" - "browser" - "attach" - ]; - key = "g?"; - action = "help"; - } - ]; - - macros = [ - { - map = [ - "index" - "pager" - ]; - key = "O"; - action = "mbsync -a"; - } - { - # gx: extract links from the current message and open one, vim-netrw style - map = [ - "index" - "pager" - ]; - key = "gx"; - action = "urlscan"; - } - { - map = [ - "index" - "pager" - ]; - key = "gl"; - action = "less ~/.config/neomutt/flag_legend.txt"; - } - { - # ZZ: save and quit, vim-style (sync mailbox, then quit) - map = [ "index" ]; - key = "ZZ"; - action = ""; - } - ]; - }; + accounts.email.maildirBasePath = "${config.home.homeDirectory}/.local/share/mail"; + home.sessionVariables.MAILDIR = config.accounts.email.maildirBasePath; }; } -- cgit v1.2.3