dotfiles/office/.config/neomutt/keys/bind
Marty Oehme a1a12cc54c
neomutt: Add html-email creation pipeline to compose menu
Hitting `,m` in the compose menu creates a dual txt/html email group
when the highlighted file is written in (djot) markdown.

Delete the original message afterwards to create a fully functional html
email with plaintext fallback.

Completely taken from: https://tom.wemyss.net/posts/neomutt-markdown-email/
with many thanks. What an amazing use of pipelines in neomutt!
2025-09-21 10:29:17 +02:00

236 lines
9.3 KiB
Text

bind generic,index,editor,pager,compose <f1> help
set abort_key = "<Esc>" # overwrite default, frankly insane, <C-g> combination
# NOTE: For operations where message/thread are both possible:
# Generally the lower-case letter will operate on the WHOLE thread
# while the upper-case letter will operate on a specific message in the thread.
# e.g. t -> tag thread / T -> tag message
# dd -> delete thread / dD -> delete message
# go 'back' with h but only close the app with q
bind index,pager,attach,browser,query,alias,compose q exit
bind pager,attach,browser,query,alias,compose h exit
# view manipulation
bind attach,browser,index,pager \CF next-page
bind attach,browser,index,pager \CB previous-page
bind attach,browser,index,pager \Cu half-up
bind attach,browser,index,pager \Cd half-down
bind browser,index,pager \Ce next-line
bind browser,index,pager \Cy previous-line
bind index zz current-middle
bind index zt current-top
bind index zb current-bottom
# line navigation
bind index,attach,browser,query G last-entry
bind index,attach,browser,query gg first-entry
bind pager G bottom
bind pager gg top
bind attach,browser,query,compose j next-entry
bind attach,browser,query,compose k previous-entry
bind index j next-undeleted
bind index k previous-undeleted
bind pager j next-line
bind pager k previous-line
bind index,pager \Cn next-entry
bind index,pager \Cp previous-entry
# tagging
macro index J <tag-thread> "tag current and select next entry"
macro index K ":set resolve=no<enter><tag-thread><previous-undeleted>:set resolve=yes<enter>" "tag current and select previous entry"
macro index t ":set resolve=no<enter><tag-thread>:set resolve=yes<enter>" "tag current thread"
macro index T ":set resolve=no<enter><tag-entry>:set resolve=yes<enter>" "tag current entry"
# flagging
bind index,pager ,F set-flag
bind index,pager ,fc clear-flag
bind index,pager ,\cf clear-flag
bind index,pager ,ff flag-message
bind index ,fs toggle-new # can't toggle new WHILE reading a msg
macro index ,S "T~U<enter><tag-prefix><clear-flag>N<untag-pattern>.<enter>" "mark all messages as read"
bind index,pager ,fl edit-label # set X-Label Header
# sorting
bind index <space>s sort-mailbox
bind index <space>S sort-reverse
# threads
bind index l display-message
bind index <return> display-message
bind index h collapse-thread
bind index <space><space> collapse-thread # TODO: Remove in favor of learning za?
bind pager,index + link-threads
bind pager,index - break-thread
bind pager,index gt next-thread
bind pager,index gT previous-thread
bind pager,index za collapse-thread
bind pager,index zA collapse-all
bind pager,index zr reconstruct-thread
bind pager,index zR entire-thread
# message manipulation
bind index,pager dD delete-message
bind index,pager dd delete-thread
bind index,pager dt delete-subthread
bind index,pager u undelete-thread
bind index,pager U undelete-message
# TODO: Figure out
macro index D ";:set resolve=no<enter><clear-flag>!<save-message>=Archive<enter><enter><sync-mailbox><enter><enter-command>echo 'Message deleted'<enter>:set resolve=yes<enter>" "Quick Delete"
macro index A ";:set resolve=no<enter><clear-flag>!<save-message>=Archive<enter><enter><sync-mailbox><enter><enter-command>echo 'Message archived'<enter>:set resolve=yes<enter>" "Quick Archive"
# Saner copy/move dialogs
macro index,pager ,c "<copy-message>?<toggle-mailboxes>" "copy a message to a mailbox"
macro index,pager ,m "<tag-thread><tag-prefix><save-message>?<toggle-mailboxes>" "move thread to a mailbox"
macro index,pager ,M "<save-message>?<toggle-mailboxes>" "move a message to a mailbox"
# search navigation
bind generic,index,attach,browser,pager n search-next # next result
bind generic,index,attach,browser,pager N search-opposite # previous result
bind generic,index / search
bind generic,index ? search-reverse
bind index,alias,query \C_ limit # ^/ to search and limit
bind index \\ vfolder-from-query # notmuch search
macro index <space>/ "<limit>all\n" "show all messages (undo limit)"
bind index ,/ show-limit
# sidebar and folders
macro index,pager <space>f "<change-folder>?" "change folder"
macro index,pager <space>F "<change-vfolder>?" "change virtual folder"
bind browser,query <return> select-entry
bind browser,query l select-entry
bind index,pager <space>e sidebar-toggle-visible # TODO: or map to L?
bind index,pager <space>E sidebar-toggle-virtual
bind index,pager e sidebar-open
bind index,pager ] sidebar-next
bind index,pager [ sidebar-prev
bind index,pager } sidebar-next-new
bind index,pager { sidebar-prev-new
# message functions
# send to editor or send to editor with ALL headers etc
macro index,pager <space>h "<pipe-message>nvim '+setlocal buftype=nofile'<enter>" "send message to editor"
bind index,pager <space>H view-raw-message
bind index,pager H display-toggle-weed
bind index,pager v view-attachments
bind index,pager,attach,compose | pipe-message
# reading a message
bind pager ,q toggle-quoted
# editor
bind editor <left> backward-char
bind editor <right> forward-char
bind editor \cb backward-char
bind editor \cf forward-char
bind editor \ca bol
bind editor \ce eol
bind editor \cw kill-word
bind editor \cu kill-line
bind editor <up> history-up
bind editor <down> history-down
bind editor \cp history-up
bind editor \cn history-down
bind editor \cr history-search
# address book functions
bind editor <Tab> complete-query
bind editor \ct complete
# add contact to Khard address book
macro index,pager ,a \
"<pipe-message>khard add-email<return>" \
"add the sender email address to khard"
# sending
bind index,pager mm mail
bind index,pager mM recall-message # edit last from drafts
bind index,pager,attach mr group-reply # answer all
bind index,pager,attach mR reply # answer SINGLE person
bind index,pager,attach mf forward-message
# composing
bind compose y send-message
bind compose e edit-message
bind compose p print-entry
bind compose P postpone-message
bind compose ,t edit-to
bind compose ,y edit-type
bind compose ,f edit-from
bind compose ,s edit-subject
bind compose ,c edit-cc
bind compose ,b edit-bcc
bind compose ,p edit-fcc
bind compose c pgp-menu
bind compose r rename-file
bind compose | filter-entry # TODO: figure out the difference to pipe-entry
bind compose K move-up
bind compose J move-down
macro compose a '<enter-command>source "neomutt-filer attach"|<enter>' "Attach with file manager"
bind compose d edit-description
bind compose D detach-file
bind compose l view-attach
bind compose <return> view-attach
bind compose t tag-entry
bind compose gg group-alternatives
bind compose gr group-related
bind compose gl group-multilingual
bind compose gu ungroup-attachment
macro attach s '<enter-command>source "neomutt-filer saveto ~/downloads"|<enter>' "Save attachment to dir"
bind attach <return> view-mailcap
bind attach l view-mailcap
# questions
# https://github.com/ceuk/mutt_dotfiles/blob/master/.config/mutt/keys/binds.muttrc
# macro index \# "<edit-label>\n" "Mark as Complete"
# macro index <return> "<display-message>\n<skip-headers>\n"
# macro index x "<limit>all\n" "show all messages (undo limit)"
# macro index \ci "<limit>~F\n" "Limit by flagged"
# Write (djot-flavored) markdown and instantly transform it into a TXT/HTML result
# HTML-enabled email readers display that and others can still enjoy a txt representation
macro compose ,m \
"<enter-command>set pipe_decode<enter>\
<pipe-message>pandoc -f gfm -t plain -o /tmp/msg.txt<enter>\
<pipe-message>pandoc -s -f gfm --standalone --embed-resources -o /tmp/msg.html --template email<enter>\
<enter-command>unset pipe_decode<enter>\
<attach-file>/tmp/msg.txt<enter>\
<attach-file>/tmp/msg.html<enter>\
<tag-entry><previous-entry><tag-entry><group-alternatives>" \
"Convert markdown to HTML5 and plaintext alternative content types"
#
#
# # mailbox navigation
macro index,pager gi "<change-folder>=Inbox<enter>" "go to inbox"
# macro index,pager gs "<change-folder>=Sent<enter>" "go to sent"
# macro index,pager gd "<change-folder>=Drafts<enter>" "go to drafts"
# macro index,pager gt "<change-folder>=Trash<enter>" "go to trash"
# macro index,pager ga "<change-folder>=Archive<enter>" "go to archive"
# macro index,pager gj "<change-folder>=Junk<enter>" "go to junk"
# # pager navigation
# bind pager,attach h exit
# bind pager l view-attachments
# bind pager k previous-line
# bind pager j next-line
# bind pager gg top
# bind pager G bottom
#
# # markdown to html for composition
# # TODO: Check if this is working - F is a spelling mistake no?
# macro compose ,m "F pandoc -s -f markdown -t html \ny^T^Utext/html; charset=UTF-8\n" "Convert from MD to HTML"
#
#
# # since we unbound the original g
# bind index,pager r noop # to avoid accidentally sending replies
# bind index,pager rr group-reply
# bind index,pager ro reply
# # open urls found in the e-mail
# macro index,pager \CU "<enter-command> unset pipe_decode<enter><pipe-message>extract_url | fzf | clip<enter>" "get URLs"
#
# # Refresh far imap email
# macro index O "<sync-mailbox><shell-escape>export MBSYNC_PRE=true; neomutt-syncmail<enter>" "refresh all e-mail"
#
# # Send mail to taskwarrior
# macro index,pager ,T "<pipe-message>neomutt-2task -c -d -t<enter>" "add mail as task to taskwarrior with custom description and tags"
# macro index,pager ,t "<pipe-message>neomutt-2task -c<enter>" "add mail as task to taskwarrior"