Compare commits
3 commits
54be488d73
...
4f39c80e25
| Author | SHA1 | Date | |
|---|---|---|---|
| 4f39c80e25 | |||
| a88fde31cb | |||
| 9e8182da6a |
45 changed files with 1462 additions and 797 deletions
9
.editorconfig
Normal file
9
.editorconfig
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
root = true
|
||||
|
||||
[*.sh]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
|
||||
[bin/*]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
|
|
@ -1,9 +1,17 @@
|
|||
keys:
|
||||
- &pickwick age13cfe8fhp4m978qlcur46vkkxepsl93ggwe53kmhue9xtpgr5zu5q4y6ln2
|
||||
- &lemur age1pdk6dmyxqhdaja5d0nf8f9qjd43hmfahmkure5yrf8al9jyfmd8qfdxwl6
|
||||
- &dango age15vscvpe79l287h8f3hssrj2r45xy0l3ns94zfue2fxlq43cqdsxq58vq3c
|
||||
creation_rules:
|
||||
- path_regex: secrets/wb\.txt$
|
||||
key_groups:
|
||||
- age:
|
||||
- *pickwick
|
||||
- *lemur
|
||||
- *dango
|
||||
- path_regex: home/email/secrets.yaml$
|
||||
key_groups:
|
||||
- age:
|
||||
- *pickwick
|
||||
- *lemur
|
||||
- *dango
|
||||
|
|
|
|||
3
bin/b
3
bin/b
|
|
@ -10,8 +10,7 @@ title=${2:-}
|
|||
|
||||
global="$HOME/Personal/bookmarks.txt"
|
||||
|
||||
if [ -n "$url" ]
|
||||
then
|
||||
if [ -n "$url" ]; then
|
||||
echo "$url $title" >>$global
|
||||
else
|
||||
local="$PWD/bookmarks.txt"
|
||||
|
|
|
|||
2
bin/cb
2
bin/cb
|
|
@ -26,12 +26,10 @@ CYGWIN_paste() {
|
|||
cat /dev/clipboard
|
||||
}
|
||||
|
||||
|
||||
MAC_copy() {
|
||||
cat | pbcopy
|
||||
}
|
||||
|
||||
|
||||
MAC_paste() {
|
||||
pbpaste
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,5 @@ if [ $# == 1 ]; then
|
|||
sleepsec=$1
|
||||
fi
|
||||
|
||||
|
||||
sleep $sleepsec
|
||||
pbcopy </dev/null
|
||||
|
||||
|
|
|
|||
31
bin/git-apply-patch
Executable file
31
bin/git-apply-patch
Executable file
|
|
@ -0,0 +1,31 @@
|
|||
#!/usr/bin/env bash
|
||||
# Interactive git patch applier - finds git repos and applies patch from stdin
|
||||
|
||||
# Save stdin (the patch) to a temp file
|
||||
patch_file=$(mktemp /tmp/patch.XXXXXX)
|
||||
cat >"$patch_file"
|
||||
|
||||
# Find git repos and select with fzf
|
||||
repo=$(find ~/projects ~/code ~/dotfiles ~ -maxdepth 3 -type d -name ".git" 2>/dev/null |
|
||||
sed 's/\/.git$//' |
|
||||
sort -u |
|
||||
fzf --prompt="Select repo to apply patch: " --height=40% --reverse)
|
||||
|
||||
if [ -z "$repo" ]; then
|
||||
echo "No repo selected, patch saved to: $patch_file"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cd "$repo" || exit 1
|
||||
echo "Applying patch to: $repo"
|
||||
git apply "$patch_file"
|
||||
status=$?
|
||||
|
||||
if [ $status -eq 0 ]; then
|
||||
echo "Patch applied successfully!"
|
||||
rm "$patch_file"
|
||||
else
|
||||
echo "Failed to apply patch. Patch saved to: $patch_file"
|
||||
fi
|
||||
|
||||
exit $status
|
||||
336
bin/wb
Executable file
336
bin/wb
Executable file
|
|
@ -0,0 +1,336 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
thisFile=$(realpath "$0")
|
||||
DOTFILES="${DOTFILES:-$HOME/dotfiles}"
|
||||
BOOKMARKS_FILE="${DOTFILES}/secrets/wb.txt"
|
||||
|
||||
# Decrypt bookmarks from sops
|
||||
getBookmarks() {
|
||||
if [[ -f "${BOOKMARKS_FILE}" ]]; then
|
||||
# Unencrypted file (for development/testing)
|
||||
cat "${BOOKMARKS_FILE}"
|
||||
elif [[ -f "${BOOKMARKS_FILE%.txt}.enc" ]]; then
|
||||
# Encrypted file
|
||||
sops --decrypt --input-type binary "${BOOKMARKS_FILE%.txt}.enc" 2>/dev/null
|
||||
else
|
||||
echo "Error: No bookmarks file found" >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Defaults
|
||||
isCopy=0
|
||||
editMode=0
|
||||
q=""
|
||||
noFuzzy=0
|
||||
queryMode=0
|
||||
|
||||
if ! type fzf >/dev/null 2>&1; then
|
||||
noFuzzy=1
|
||||
fi
|
||||
|
||||
cleanup() {
|
||||
rm -f /tmp/.wb
|
||||
clear-pbcopy 60 &
|
||||
}
|
||||
|
||||
trap cleanup EXIT
|
||||
|
||||
bks() {
|
||||
getBookmarks | awk '!/^[[:space:]]*#/ && !/^[[:space:]]*$/ {print $1}'
|
||||
}
|
||||
|
||||
execute() {
|
||||
# --------------------------------------------------------------------
|
||||
# If key == $q, then it's a match, then we do the following:
|
||||
# a. Copy the "url" to the clipboard (with "pbcopy" in Mac or
|
||||
# "clip" in Linux). How do we know it's a Mac, we just simply
|
||||
# check if there's a ~/Music folder in your homedir. If
|
||||
# there is, it's likely a Mac, else it's Linux.
|
||||
# b. I have a "clear-pbcopy" script that basically clears the
|
||||
# clipboard after 20 seconds (for security reason) because
|
||||
# you don't want to accidentally copy-paste your personal
|
||||
# links in your email or your chat applications. It is as simple as
|
||||
# a oneline command:
|
||||
# "sleep 20; echo "nothing-here" | pbcopy"
|
||||
# c. If the first argument is "-c" then we mean we just want to
|
||||
# copy the string to the clipboard, so we just continue
|
||||
# d. Then we see if the "url" contains "http" or "www", if so
|
||||
# we open it with ~/bin/browser. You must have your own
|
||||
# "browser" script that opens your favorite web browser, e.g.
|
||||
# in Mac, my "~/bin/browser" contains:
|
||||
# open -a /Applications/Firefox.app $*
|
||||
# However, if the "url" does not contain http/www,
|
||||
# e.g. the key and url line is like this:
|
||||
# mytodofile ~/Documents/mytodofile.txt
|
||||
# then I open it "open" command line provided by Mac
|
||||
# d. We are done (exiting)
|
||||
# --------------------------------------------------------------------
|
||||
|
||||
echo ""
|
||||
|
||||
# ---------------------- a
|
||||
echo " copying $url"
|
||||
echo "$url" | cb
|
||||
|
||||
# ---------------------- b
|
||||
if type clear-pbcopy >/dev/null 2>&1; then
|
||||
clear-pbcopy 60 &
|
||||
fi
|
||||
|
||||
# ---------------------- c
|
||||
if [ $isCopy == 1 ]; then
|
||||
echo " Copied to clipboard"
|
||||
echo ""
|
||||
exit
|
||||
fi
|
||||
|
||||
# ---------------------- d
|
||||
echo " open $url"
|
||||
x-open $url
|
||||
|
||||
# ---------------------- d
|
||||
echo ""
|
||||
exit
|
||||
}
|
||||
|
||||
fuzzy() {
|
||||
# Use awk to parse bookmarks in a single pass (much faster than bash loop)
|
||||
formatted=$(getBookmarks | awk '
|
||||
# Skip decorative headers and section dividers
|
||||
/^#[-=~# ]*$/ || /^# *--/ || /^##+/ { next }
|
||||
|
||||
# Accumulate description and extract tags from comments
|
||||
/^#[^#]/ {
|
||||
sub(/^# */, "")
|
||||
desc = desc (desc ? " " : "") $0
|
||||
# Extract @tags
|
||||
n = split($0, words, " ")
|
||||
for (i = 1; i <= n; i++) {
|
||||
if (words[i] ~ /^@/) {
|
||||
tags = tags (tags ? " " : "") words[i]
|
||||
}
|
||||
}
|
||||
next
|
||||
}
|
||||
|
||||
# Handle bookmark lines (non-comment, non-empty)
|
||||
/^[^#[:space:]]/ {
|
||||
key = $1
|
||||
# Skip @-prefixed keys
|
||||
if (key ~ /^@/) { desc = ""; tags = ""; next }
|
||||
|
||||
# Get URL (everything after first field)
|
||||
url = $0
|
||||
sub(/^[^ \t]+[ \t]+/, "", url)
|
||||
|
||||
# Clean description
|
||||
gsub(/\n/, " ", desc)
|
||||
if (desc == "") desc = "-"
|
||||
if (tags == "") tags = "-"
|
||||
|
||||
print key "\t" url "\t" desc "\t" tags
|
||||
|
||||
desc = ""
|
||||
tags = ""
|
||||
}
|
||||
')
|
||||
|
||||
selected_line=$(echo "$formatted" |
|
||||
fzf -i --with-nth=1 \
|
||||
--delimiter=$'\t' \
|
||||
--query="$q" \
|
||||
--prompt="🔍 Select bookmark: " \
|
||||
--preview='bash -c "url=\$(echo {} | cut -f2); desc=\$(echo {} | cut -f3); tags=\$(echo {} | cut -f4); echo -e \"\$url\n\nDesc: \$desc\n\nTags: \$tags\""' \
|
||||
--preview-window=down:12:wrap)
|
||||
|
||||
if [[ -n "$selected_line" ]]; then
|
||||
IFS=$'\t' read -r key url _ <<<"$selected_line"
|
||||
execute "$url"
|
||||
else
|
||||
echo " No selection made"
|
||||
echo ""
|
||||
fi
|
||||
}
|
||||
|
||||
help() {
|
||||
echo ""
|
||||
echo "Usage: wb [-c] [-e] <key> [key2] [key3] ..."
|
||||
echo ""
|
||||
echo "Options:"
|
||||
echo " -c Copy to clipboard without opening"
|
||||
echo " -e Edit the bookmarks file"
|
||||
echo " -nf No Fuzzy Match"
|
||||
echo " -h Show help"
|
||||
echo ""
|
||||
echo "Examples:"
|
||||
echo " wb cnn # Open the cnn bookmark"
|
||||
echo " wb -c gmail # Copy Gmail URL without opening"
|
||||
echo " wb 230 zoom # Open bookmark matching '230.*zoom'"
|
||||
echo " wb ai sci zoom # Open bookmark matching 'ai.*sci.*zoom'"
|
||||
echo ""
|
||||
}
|
||||
|
||||
# --------------------------------------------------------------------
|
||||
# [ 70-char wide ]
|
||||
# 34567890123456789012345678901234567890123456789012345678901234567890
|
||||
# 1 2 3 4 5 6 7
|
||||
# --------------------------------------------------------------------
|
||||
|
||||
# --------------------------------------------------------------------
|
||||
# 0. Setup $thisFile and
|
||||
# if "wb" is called with no arguments, then
|
||||
# just open this "wb" file with "e" --> emacs
|
||||
# You can change "e" to "vi" or other text editor
|
||||
# --------------------------------------------------------------------
|
||||
|
||||
# Parse arguments
|
||||
args=()
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
-c)
|
||||
isCopy=1
|
||||
;;
|
||||
-e)
|
||||
editMode=1
|
||||
;;
|
||||
-h | --help)
|
||||
help
|
||||
exit 0
|
||||
;;
|
||||
-nf)
|
||||
noFuzzy=1
|
||||
;;
|
||||
-q)
|
||||
queryMode=1
|
||||
;;
|
||||
-*)
|
||||
echo "Unknown option: $1"
|
||||
exit 1
|
||||
;;
|
||||
*)
|
||||
args+=("$1")
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
# Build pattern from multiple arguments (e.g., "wb 230 si te" -> "230.*si.*te")
|
||||
if [ ${#args[@]} -gt 0 ]; then
|
||||
q="${args[0]}"
|
||||
for ((i = 1; i < ${#args[@]}; i++)); do
|
||||
q="$q.*${args[$i]}"
|
||||
done
|
||||
fi
|
||||
|
||||
if [[ $editMode == 1 ]]; then
|
||||
encFile="${BOOKMARKS_FILE%.txt}.enc"
|
||||
if [[ -f "$encFile" ]]; then
|
||||
echo "Editing encrypted bookmarks file"
|
||||
# Decrypt to the .txt file (matches .sops.yaml path_regex), edit, re-encrypt
|
||||
trap "rm -f '${BOOKMARKS_FILE}'" EXIT
|
||||
sops --decrypt --input-type binary --output-type binary "$encFile" >"${BOOKMARKS_FILE}"
|
||||
${EDITOR:-vim} "${BOOKMARKS_FILE}"
|
||||
sops --encrypt --input-type binary --output-type binary "${BOOKMARKS_FILE}" >"$encFile"
|
||||
rm -f "${BOOKMARKS_FILE}"
|
||||
echo "Saved and re-encrypted"
|
||||
elif [[ -f "${BOOKMARKS_FILE}" ]]; then
|
||||
echo "Editing ${BOOKMARKS_FILE}"
|
||||
${EDITOR:-vim} "${BOOKMARKS_FILE}"
|
||||
else
|
||||
echo "Error: No bookmarks file found"
|
||||
exit 1
|
||||
fi
|
||||
exit
|
||||
fi
|
||||
|
||||
if [[ $queryMode == 1 ]]; then
|
||||
if [[ -z "$q" ]]; then
|
||||
bs=$(bks)
|
||||
else
|
||||
bs=$(bks | grep -i "$q")
|
||||
fi
|
||||
num=$(echo "$bs" | wc -l | tr -d ' ')
|
||||
bs=$(echo "$bs" | tr '\n' ',' | sed 's/,$//' | sed 's/,/, /g')
|
||||
echo "$num bookmarks: ($bs)"
|
||||
exit
|
||||
fi
|
||||
|
||||
if [[ $q == "" ]]; then
|
||||
if [[ $noFuzzy == 1 ]]; then
|
||||
help
|
||||
else
|
||||
fuzzy
|
||||
fi
|
||||
exit
|
||||
fi
|
||||
|
||||
## --------------------------------------------------------------------
|
||||
## 1. Find all bookmarks matching the pattern using regex
|
||||
## Store matches in /tmp/.wb (using awk for speed)
|
||||
## --------------------------------------------------------------------
|
||||
tempFile=/tmp/.wb
|
||||
getBookmarks | awk -v pattern="$q" '
|
||||
!/^[[:space:]]*#/ && !/^[[:space:]]*$/ && $1 ~ pattern {print}
|
||||
' >"$tempFile"
|
||||
hitCount=$(wc -l <"$tempFile" | tr -d ' ')
|
||||
|
||||
## --------------------------------------------------------------------
|
||||
## 2. Handle results based on hit count
|
||||
## --------------------------------------------------------------------
|
||||
|
||||
# No hits found
|
||||
if [ $hitCount -eq 0 ]; then
|
||||
echo ""
|
||||
if [[ $noFuzzy == 1 ]]; then
|
||||
echo " '$q' not found"
|
||||
echo " Available bookmarks matching pattern:"
|
||||
bks | grep -iE "$q" | cat -n
|
||||
else
|
||||
fuzzy
|
||||
fi
|
||||
echo ""
|
||||
exit
|
||||
fi
|
||||
|
||||
# Multiple hits - check for exact match first
|
||||
if [ $hitCount -gt 1 ]; then
|
||||
exactHit=0
|
||||
while read -r key url misc; do
|
||||
if [[ "$key" == "$q" ]]; then
|
||||
exactHit=1
|
||||
echo "$key $url" >"$tempFile"
|
||||
break
|
||||
fi
|
||||
done <"$tempFile"
|
||||
if [ $exactHit -eq 1 ]; then
|
||||
hitCount=1
|
||||
fi
|
||||
fi
|
||||
|
||||
# Still multiple hits - show options or use fuzzy
|
||||
if [ $hitCount -gt 1 ]; then
|
||||
if [[ $noFuzzy == 1 ]]; then
|
||||
echo ""
|
||||
echo " Multiple matches for '$q':"
|
||||
sort "$tempFile" | while read -r key url misc; do
|
||||
echo " $key"
|
||||
done
|
||||
echo ""
|
||||
else
|
||||
fuzzy
|
||||
fi
|
||||
exit
|
||||
fi
|
||||
|
||||
# Single hit - execute
|
||||
if [ $hitCount -eq 1 ]; then
|
||||
read -r key url _ <"$tempFile"
|
||||
execute "$url"
|
||||
fi
|
||||
|
||||
## --------------------------------------------------------------------
|
||||
## 5. Bookmarks are now stored in secrets/wb.txt (or secrets/wb.enc when encrypted)
|
||||
## To encrypt: sops --encrypt --input-type binary --output-type binary secrets/wb.txt > secrets/wb.enc
|
||||
## Then remove secrets/wb.txt
|
||||
## --------------------------------------------------------------------
|
||||
|
|
@ -13,7 +13,7 @@ exec-on-workspace-change = ['/bin/bash', '-c',
|
|||
'/run/current-system/sw/bin/sketchybar --trigger aerospace_workspace_changed FOCUSED_WORKSPACE=$AEROSPACE_FOCUSED_WORKSPACE PREV_WORKSPACE=$AEROSPACE_PREV_WORKSPACE && /etc/profiles/per-user/rayandrew/bin/aerospace-scratchpad hook pull-window $AEROSPACE_PREV_WORKSPACE $AEROSPACE_FOCUSED_WORKSPACE'
|
||||
]
|
||||
on-focus-changed = [
|
||||
'move-mouse window-lazy-center',
|
||||
# 'move-mouse window-lazy-center',
|
||||
'exec-and-forget /bin/bash -c /run/current-system/sw/bin/sketchybar --trigger front_app_switched',
|
||||
'exec-and-forget /run/current-system/sw/bin/sketchybar --trigger update_windows'
|
||||
]
|
||||
|
|
|
|||
33
config/davmail/davmail.properties
Normal file
33
config/davmail/davmail.properties
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
# DavMail configuration
|
||||
# See: http://davmail.sourceforge.net/serversetup.html
|
||||
|
||||
davmail.server=true
|
||||
davmail.disableUpdateCheck=true
|
||||
davmail.mode=O365Manual
|
||||
davmail.url=https://outlook.office365.com/EWS/Exchange.asmx
|
||||
davmail.keepDelay=30
|
||||
|
||||
# Ports
|
||||
davmail.caldavPort=1080
|
||||
davmail.imapPort=1143
|
||||
davmail.ldapPort=1389
|
||||
davmail.popPort=1110
|
||||
davmail.smtpPort=1025
|
||||
|
||||
# Logging
|
||||
davmail.logFilePath=/tmp/davmail.log
|
||||
davmail.logFileSize=1MB
|
||||
|
||||
# OAuth token storage
|
||||
davmail.oauth.tokenFilePath=/Users/rayandrew/.local/state/davmail-tokens
|
||||
|
||||
# Log levels
|
||||
log4j.logger.davmail=WARN
|
||||
log4j.logger.httpclient.wire=WARN
|
||||
log4j.logger.org.apache.commons.httpclient=WARN
|
||||
log4j.rootLogger=WARN
|
||||
|
||||
# log4j.logger.davmail=DEBUG
|
||||
# log4j.logger.httpclient.wire=DEBUG
|
||||
# log4j.logger.org.apache.commons.httpclient=DEBUG
|
||||
# log4j.rootLogger=DEBUG
|
||||
2
config/direnv/direnv.toml
Normal file
2
config/direnv/direnv.toml
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
[global]
|
||||
log_format = "\u001B[2mdirenv: %s\u001B[0m"
|
||||
|
|
@ -1,5 +1,11 @@
|
|||
set fish_greeting
|
||||
|
||||
# Bootstrap Fisher (reads plugins from fish_plugins)
|
||||
if not functions -q fisher
|
||||
curl -sL https://raw.githubusercontent.com/jorgebucaran/fisher/main/functions/fisher.fish | source
|
||||
fisher update
|
||||
end
|
||||
|
||||
function sesh-sessions
|
||||
set -l session (sesh list -t -c | fzf --height 40% --reverse --border-label ' sesh ' --border --prompt '⚡ ')
|
||||
commandline -f repaint
|
||||
|
|
|
|||
2
config/fish/fish_plugins
Normal file
2
config/fish/fish_plugins
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
jorgebucaran/fisher
|
||||
IlanCosman/tide@v6
|
||||
|
|
@ -6,6 +6,8 @@ quit-after-last-window-closed = true
|
|||
gtk-adwaita = false
|
||||
# font-family = ${system-font}
|
||||
font-family = Consolas
|
||||
font-family = Symbols Nerd Font Mono
|
||||
font-family = DejaVuSansM Nerd Font Mono
|
||||
font-size = 14
|
||||
app-notifications = no-clipboard-copy
|
||||
|
||||
|
|
|
|||
47
config/home/.mailcap
Normal file
47
config/home/.mailcap
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
# Mailcap - MIME type handlers for neomutt and other mail clients
|
||||
|
||||
# HTML - terminal inline view (for auto_view)
|
||||
text/html; w3m -dump -T text/html %s; copiousoutput
|
||||
# HTML - open in browser
|
||||
text/html; open %s; nametemplate=%s.html
|
||||
|
||||
# Plain text
|
||||
text/plain; TERM=xterm-256color less %s
|
||||
text/*; TERM=xterm-256color less %s
|
||||
|
||||
# PDF
|
||||
application/pdf; zathura %s
|
||||
application/pdf; open %s
|
||||
|
||||
# Images - terminal (kitty protocol works in ghostty)
|
||||
image/*; kitten icat --clear %s
|
||||
image/*; open %s
|
||||
|
||||
# Video
|
||||
video/*; iina %s
|
||||
video/*; open %s
|
||||
|
||||
# Audio
|
||||
audio/*; mpv --no-video %s
|
||||
audio/*; open %s
|
||||
|
||||
# Microsoft Office - Word
|
||||
application/msword; open %s
|
||||
application/vnd.openxmlformats-officedocument.wordprocessingml.document; open %s
|
||||
|
||||
# Microsoft Office - Excel
|
||||
application/vnd.ms-excel; open %s
|
||||
application/vnd.openxmlformats-officedocument.spreadsheetml.sheet; open %s
|
||||
|
||||
# Microsoft Office - PowerPoint
|
||||
application/vnd.ms-powerpoint; open %s
|
||||
application/vnd.openxmlformats-officedocument.presentationml.presentation; open %s
|
||||
|
||||
# Archives - show contents
|
||||
application/zip; unzip -l %s; copiousoutput
|
||||
application/x-tar; tar -tvf %s; copiousoutput
|
||||
application/gzip; tar -tzvf %s; copiousoutput
|
||||
application/x-bzip2; tar -tjvf %s; copiousoutput
|
||||
|
||||
# Fallback - open with default macOS app
|
||||
application/*; open %s
|
||||
55
config/mbsync/mbsyncrc
Normal file
55
config/mbsync/mbsyncrc
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
# mbsync configuration
|
||||
# Run: mbsync -a
|
||||
|
||||
# Personal Gmail account
|
||||
IMAPAccount personal
|
||||
Host imap.gmail.com
|
||||
User raydreww@gmail.com
|
||||
PassCmd "sops -d --extract '[\"personal\"]' ~/dotfiles/home/email/secrets.yaml"
|
||||
TLSType IMAPS
|
||||
CertificateFile /etc/ssl/certs/ca-certificates.crt
|
||||
|
||||
IMAPStore personal-remote
|
||||
Account personal
|
||||
|
||||
MaildirStore personal-local
|
||||
Path ~/mail/personal/
|
||||
Inbox ~/mail/personal/Inbox
|
||||
SubFolders Verbatim
|
||||
|
||||
Channel personal
|
||||
Far :personal-remote:
|
||||
Near :personal-local:
|
||||
Create Both
|
||||
Expunge Both
|
||||
Patterns * !"[Airmail]/Done" !"[Airmail]/Snooze" !"[Airmail]/To Do" !"[Airmail]/Send Later" !"[Gmail]/All Mail" !"[Gmail]/Important" !"[Gmail]/Starred" !"[Gmail]/Bin"
|
||||
Remove None
|
||||
SyncState *
|
||||
|
||||
|
||||
# UChicago account (via DavMail)
|
||||
IMAPAccount uchicago
|
||||
Host 127.0.0.1
|
||||
Port 1143
|
||||
User rayandrew@uchicago.edu
|
||||
PassCmd "sops -d --extract '[\"uchicago\"]' ~/dotfiles/home/email/secrets.yaml"
|
||||
TLSType None
|
||||
AuthMechs LOGIN
|
||||
Timeout 0
|
||||
|
||||
IMAPStore uchicago-remote
|
||||
Account uchicago
|
||||
|
||||
MaildirStore uchicago-local
|
||||
Path ~/mail/uchicago/
|
||||
Inbox ~/mail/uchicago/Inbox
|
||||
SubFolders Verbatim
|
||||
|
||||
Channel uchicago
|
||||
Far :uchicago-remote:
|
||||
Near :uchicago-local:
|
||||
Create Both
|
||||
Expunge Both
|
||||
Patterns * !"[Airmail]/Done" !"[Airmail]/Snooze" !"[Airmail]/To Do" !"[Airmail]/Send Later"
|
||||
Remove None
|
||||
SyncState *
|
||||
30
config/msmtp/config
Normal file
30
config/msmtp/config
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
# msmtp configuration
|
||||
# Default settings for all accounts
|
||||
|
||||
defaults
|
||||
auth on
|
||||
tls on
|
||||
tls_trust_file /etc/ssl/certs/ca-certificates.crt
|
||||
logfile ~/.local/state/msmtp.log
|
||||
|
||||
# Personal Gmail account
|
||||
account personal
|
||||
host smtp.gmail.com
|
||||
from raydreww@gmail.com
|
||||
user raydreww@gmail.com
|
||||
passwordeval "sops -d --extract '[\"personal\"]' ~/dotfiles/home/email/secrets.yaml"
|
||||
tls_starttls off
|
||||
|
||||
# UChicago account (via DavMail)
|
||||
account uchicago
|
||||
host 127.0.0.1
|
||||
port 1025
|
||||
from rayandrew@uchicago.edu
|
||||
user rayandrew@uchicago.edu
|
||||
passwordeval "sops -d --extract '[\"uchicago\"]' ~/dotfiles/home/email/secrets.yaml"
|
||||
auth plain
|
||||
tls off
|
||||
tls_starttls off
|
||||
|
||||
# Default account
|
||||
account default : uchicago
|
||||
38
config/neomutt/accounts/personal
Normal file
38
config/neomutt/accounts/personal
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
# Personal Gmail account configuration
|
||||
unmailboxes *
|
||||
|
||||
set ssl_force_tls = yes
|
||||
set certificate_file = /etc/ssl/certs/ca-certificates.crt
|
||||
|
||||
# GPG
|
||||
set crypt_autosign = yes
|
||||
set crypt_opportunistic_encrypt = no
|
||||
set pgp_use_gpg_agent = yes
|
||||
set mbox_type = Maildir
|
||||
set sort = "threads"
|
||||
|
||||
# Account settings
|
||||
set folder = '~/mail/personal'
|
||||
set from = 'raydreww@gmail.com'
|
||||
set realname = 'Ray Andrew'
|
||||
set spoolfile = '+Inbox'
|
||||
set postponed = '+Drafts'
|
||||
set record = '+Sent'
|
||||
set trash = '+Trash'
|
||||
|
||||
# PGP settings
|
||||
set use_from = yes
|
||||
set pgp_verify_sig = yes
|
||||
set pgp_sign_as = 0x07AA5254804C009F
|
||||
set pgp_timeout = 3600
|
||||
|
||||
# Mailboxes
|
||||
named-mailboxes "p/inbox" =Inbox
|
||||
named-mailboxes "p/drafts" =Drafts
|
||||
named-mailboxes "p/sent" =Sent
|
||||
named-mailboxes "p/important" =Important
|
||||
named-mailboxes "p/trash" =Trash
|
||||
named-mailboxes "p/archive" =Archive
|
||||
|
||||
# Signature
|
||||
set signature = "~/.config/neomutt/signatures/personal"
|
||||
39
config/neomutt/accounts/uchicago
Normal file
39
config/neomutt/accounts/uchicago
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
# UChicago account configuration (via DavMail)
|
||||
unmailboxes *
|
||||
|
||||
set ssl_force_tls = no
|
||||
set certificate_file = /etc/ssl/certs/ca-certificates.crt
|
||||
|
||||
# GPG
|
||||
set crypt_autosign = no
|
||||
set crypt_opportunistic_encrypt = no
|
||||
set pgp_use_gpg_agent = yes
|
||||
set mbox_type = Maildir
|
||||
set sort = "threads"
|
||||
|
||||
# Account settings
|
||||
set folder = '~/mail/uchicago'
|
||||
set from = 'rayandrew@uchicago.edu'
|
||||
set realname = 'Ray Andrew'
|
||||
set spoolfile = '+Inbox'
|
||||
set postponed = '+Drafts'
|
||||
set record = '+Sent'
|
||||
set trash = '+Trash'
|
||||
|
||||
# PGP settings
|
||||
set use_from = yes
|
||||
set pgp_sign_as = 0xEEF04CFFE9DFE5FC
|
||||
set pgp_verify_sig = yes
|
||||
set pgp_timeout = 3600
|
||||
|
||||
# Mailboxes
|
||||
named-mailboxes "u/inbox" =Inbox
|
||||
named-mailboxes "u/drafts" =Drafts
|
||||
named-mailboxes "u/sent" =Sent
|
||||
named-mailboxes "u/important" =Important
|
||||
named-mailboxes "u/trash" =Trash
|
||||
named-mailboxes "u/archive" =Archive
|
||||
named-mailboxes "u/teaching" =Teaching
|
||||
|
||||
# Signature
|
||||
set signature = "~/.config/neomutt/signatures/uchicago"
|
||||
93
config/neomutt/colors
Normal file
93
config/neomutt/colors
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
# NeoMutt color scheme - Noctis Azureus
|
||||
# Based on noctis_azureus_ghostty.lua palette
|
||||
# Requires: set color_directcolor = yes
|
||||
|
||||
# Mono settings
|
||||
mono bold bold
|
||||
mono underline underline
|
||||
mono indicator reverse
|
||||
mono error bold
|
||||
|
||||
# General colors - using exact hex from palette
|
||||
color normal '#becfda' default
|
||||
color error '#e66533' default
|
||||
color tilde '#051b29' default
|
||||
color message '#49d6e9' default
|
||||
color markers '#e66533' '#ffffff'
|
||||
color attachment '#becfda' default
|
||||
color search '#051b29' '#49e9a6'
|
||||
color status '#e4b781' '#041520'
|
||||
color indicator '#051b29' '#49d6e9'
|
||||
color tree '#49d6e9' default
|
||||
|
||||
# Sidebar
|
||||
color sidebar_indicator '#051b29' '#49d6e9'
|
||||
color sidebar_highlight '#e4b781' '#0c3f5f'
|
||||
color sidebar_divider '#475e6c' default
|
||||
color sidebar_flagged '#e66533' default
|
||||
color sidebar_new '#49e9a6' default
|
||||
color sidebar_ordinary '#becfda' default
|
||||
|
||||
# Header colors
|
||||
color header '#49ace9' default ".*"
|
||||
color header '#df769b' default "^(From)"
|
||||
color header '#49d6e9' default "^(Subject)"
|
||||
color header '#becfda' default "^(CC|BCC)"
|
||||
color hdrdefault '#49e9a6' default
|
||||
|
||||
# Quoted text (conversation depth)
|
||||
color quoted '#49e9a6' default
|
||||
color quoted1 '#49ace9' default
|
||||
color quoted2 '#49d6e9' default
|
||||
color quoted3 '#e4b781' default
|
||||
color quoted4 '#e66533' default
|
||||
color quoted5 '#e97749' default
|
||||
color signature '#49e9a6' default
|
||||
|
||||
# Body patterns
|
||||
color body '#e97749' default "[\-\.+_a-zA-Z0-9]+@[\-\.a-zA-Z0-9]+"
|
||||
color body '#49ace9' default "(https?|ftp)://[\-\.,/%~_:?&=\#a-zA-Z0-9]+"
|
||||
color body '#49e9a6' default "\`[^\`]*\`"
|
||||
color body '#49ace9' default "^# \.*"
|
||||
color body '#49d6e9' default "^## \.*"
|
||||
color body '#49e9a6' default "^### \.*"
|
||||
color body '#e4b781' default "^(\t| )*(-|\\*) \.*"
|
||||
color body '#49d6e9' default "[;:][-o][)/(|]"
|
||||
color body '#49d6e9' default "[;:][)(|]"
|
||||
color body '#49d6e9' default "[ ][*][^*]*[*][ ]?"
|
||||
color body '#49d6e9' default "[ ]?[*][^*]*[*][ ]"
|
||||
color body '#e66533' default "(BAD signature)"
|
||||
color body '#49d6e9' default "(Good signature)"
|
||||
color body '#475e6c' default "^gpg: Good signature .*"
|
||||
color body '#e4b781' default "^gpg: "
|
||||
color body '#e4b781' '#e66533' "^gpg: BAD signature from.*"
|
||||
mono body bold "^gpg: Good signature"
|
||||
|
||||
# Index colors
|
||||
color index '#becfda' default '.*'
|
||||
color index_author '#df769b' default '.*'
|
||||
color index_number '#49ace9' default
|
||||
color index_subject '#49d6e9' default '.*'
|
||||
color index_date '#475e6c' default
|
||||
color index_size '#475e6c' default
|
||||
color index_flags '#49e9a6' default '.*'
|
||||
|
||||
# New mail - highlighted with bg_highlight
|
||||
color index '#e4b781' '#0c3f5f' "~N"
|
||||
color index_author '#df769b' '#0c3f5f' "~N"
|
||||
color index_subject '#49d6e9' '#0c3f5f' "~N"
|
||||
|
||||
# Flagged mail
|
||||
color index '#e66533' default "~F"
|
||||
color index_author '#e66533' default "~F"
|
||||
|
||||
# Deleted mail
|
||||
color index '#475e6c' default "~D"
|
||||
color index_author '#475e6c' default "~D"
|
||||
color index_subject '#475e6c' default "~D"
|
||||
|
||||
# Tagged mail
|
||||
color index '#49e9a6' default "~T"
|
||||
color index_author '#49e9a6' default "~T"
|
||||
|
||||
color progress '#051b29' '#49d6e9'
|
||||
65
config/neomutt/keybinds
Normal file
65
config/neomutt/keybinds
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
# NeoMutt keybindings
|
||||
|
||||
# Attachment
|
||||
bind attach <return> view-mailcap
|
||||
bind attach l view-mailcap
|
||||
|
||||
# Editor
|
||||
bind editor <space> noop
|
||||
bind editor <Tab> complete-query
|
||||
bind editor ^T complete
|
||||
|
||||
# Pager
|
||||
bind pager c imap-fetch-mail
|
||||
bind pager j next-line
|
||||
bind pager k previous-line
|
||||
bind pager J next-entry
|
||||
bind pager K previous-entry
|
||||
bind pager l view-attachments
|
||||
bind pager,attach h exit
|
||||
bind pager \031 previous-line
|
||||
bind pager \005 next-line
|
||||
bind pager,browser gg top-page
|
||||
bind pager,browser G bottom-page
|
||||
|
||||
# Index
|
||||
bind index G last-entry
|
||||
bind index g noop
|
||||
bind index gg first-entry
|
||||
bind index D delete-message
|
||||
bind index U undelete-message
|
||||
bind index L limit
|
||||
bind index h noop
|
||||
bind index l display-message
|
||||
bind index R group-reply
|
||||
bind index \031 previous-undeleted
|
||||
bind index \005 next-undeleted
|
||||
bind index <tab> sync-mailbox
|
||||
bind index <space> collapse-thread
|
||||
|
||||
# Browser
|
||||
bind browser h goto-parent
|
||||
bind browser l select-entry
|
||||
bind browser,pager,index n search-next
|
||||
bind browser,pager,index N search-opposite
|
||||
|
||||
# Navigation (half page)
|
||||
bind index,pager,browser d half-down
|
||||
bind index,pager,browser u half-up
|
||||
|
||||
# Sidebar
|
||||
bind index,pager \Cp sidebar-prev
|
||||
bind index,pager \Cn sidebar-next
|
||||
bind index,pager o sidebar-open
|
||||
bind index,pager B sidebar-toggle-visible
|
||||
|
||||
# Misc
|
||||
bind index,pager @ compose-to-sender
|
||||
bind index,pager D purge-message
|
||||
|
||||
# Macros
|
||||
macro index,pager a ":set confirmappend=no delete=yes\n<tag-prefix><save-message>=Archive\n<sync-mailbox>:set confirmappend=yes delete=ask-yes\n"
|
||||
macro index,pager n "<tag-prefix><clear-flag>N<untag-pattern>.<enter>\n"
|
||||
macro attach O "<enter-command>unset wait_key<enter><shell-escape>rm -f /tmp/mutt-attach<enter><save-entry><kill-line>/tmp/mutt-attach<enter>^A"
|
||||
macro attach,pager A "|git apply<enter>" "Apply git patch"
|
||||
macro attach,pager P "|git-apply-patch<enter>" "Apply git patch (interactive)"
|
||||
66
config/neomutt/neomuttrc
Normal file
66
config/neomutt/neomuttrc
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
# NeoMutt main configuration
|
||||
|
||||
# Cache
|
||||
set header_cache = "~/.cache/neomutt/headers/"
|
||||
set message_cachedir = "~/.cache/neomutt/messages/"
|
||||
|
||||
# Editor
|
||||
set editor = "emacs -nw"
|
||||
set edit_headers = yes
|
||||
|
||||
# General settings
|
||||
set color_directcolor = yes
|
||||
set implicit_autoview = yes
|
||||
set crypt_use_gpgme = yes
|
||||
alternative_order text/enriched text/plain text
|
||||
set delete = yes
|
||||
set abort_key = "<Esc>"
|
||||
|
||||
# Sidebar
|
||||
set sidebar_visible
|
||||
set sidebar_format = "%D%?F? [%F]?%* %?N?%N/?%S"
|
||||
set mail_check_stats
|
||||
|
||||
# Status bar, date format
|
||||
set status_chars = " *%A"
|
||||
set status_format = "[ Folder: %D ] [%r%m messages%?n? (%n new)?%?d? (%d to delete)?%?t? (%t tagged)? ]%>─%?p?( %p postponed )?"
|
||||
set date_format = "%d.%m.%Y %H:%M"
|
||||
set sort = threads
|
||||
set sort_aux = reverse-last-date-received
|
||||
set uncollapse_jump
|
||||
set sort_re
|
||||
set index_format = "%4C %Z %{%b %d} %-15.15L %?E?(%E)&? %s"
|
||||
set reply_regexp = "^(([Rr][Ee]?(\[[0-9]+\])?: *)?(\[[^]]+\] *)?)*"
|
||||
set quote_regexp = "^( {0,4}[>|:#%]| {0,4}[a-z0-9]+[>|]+)+"
|
||||
set send_charset = "utf-8:iso-8859-1:us-ascii"
|
||||
set charset = "utf-8"
|
||||
set arrow_cursor = "no"
|
||||
|
||||
# Pager View Options
|
||||
set pager_index_lines = 10
|
||||
set pager_context = 3
|
||||
set pager_stop
|
||||
set menu_scroll
|
||||
set tilde
|
||||
unset markers
|
||||
|
||||
# MTA (mail transfer agent)
|
||||
set sendmail = 'msmtpq --read-envelope-from --read-recipients'
|
||||
|
||||
# Include keybindings
|
||||
source ~/.config/neomutt/keybinds
|
||||
source ~/.config/neomutt/colors
|
||||
|
||||
# Account switching macros
|
||||
macro index,pager <f2> "<sync-mailbox><enter-command>source ~/.config/neomutt/accounts/uchicago<enter><change-folder>!<enter>"
|
||||
macro index,pager <f3> "<sync-mailbox><enter-command>source ~/.config/neomutt/accounts/personal<enter><change-folder>!<enter>"
|
||||
|
||||
# Register accounts for folder hooks
|
||||
named-mailboxes "p" "~/mail/personal/Inbox"
|
||||
folder-hook ~/mail/personal/ "source ~/.config/neomutt/accounts/personal"
|
||||
|
||||
named-mailboxes "u" "~/mail/uchicago/Inbox"
|
||||
folder-hook ~/mail/uchicago/ "source ~/.config/neomutt/accounts/uchicago"
|
||||
|
||||
# Source primary account (personal)
|
||||
source ~/.config/neomutt/accounts/personal
|
||||
1
config/neomutt/signatures/personal
Normal file
1
config/neomutt/signatures/personal
Normal file
|
|
@ -0,0 +1 @@
|
|||
-- Ray Andrew
|
||||
1
config/neomutt/signatures/uchicago
Normal file
1
config/neomutt/signatures/uchicago
Normal file
|
|
@ -0,0 +1 @@
|
|||
-- Ray Andrew
|
||||
|
|
@ -150,6 +150,7 @@
|
|||
age
|
||||
ssh-to-age
|
||||
nixfmt-rfc-style
|
||||
shfmt
|
||||
];
|
||||
DIRENV_LOG_FORMAT = "";
|
||||
};
|
||||
|
|
|
|||
|
|
@ -2,219 +2,75 @@
|
|||
pkgs,
|
||||
lib,
|
||||
config,
|
||||
user,
|
||||
home-dir,
|
||||
dots,
|
||||
...
|
||||
}:
|
||||
|
||||
{
|
||||
imports = [
|
||||
./neomutt
|
||||
./mailcap.nix
|
||||
];
|
||||
|
||||
options.custom.email = with lib; {
|
||||
enable = mkEnableOption "Enable email";
|
||||
davmail = mkEnableOption "Enable DavMail";
|
||||
mbsync = mkEnableOption "Enable Mbsync";
|
||||
neomutt = mkEnableOption "Enable NeoMutt";
|
||||
mailcap = mkEnableOption "Enable mailcap";
|
||||
};
|
||||
|
||||
config = lib.mkIf config.custom.email.enable {
|
||||
# DavMail service (Exchange gateway)
|
||||
services.davmail = {
|
||||
enable = config.custom.email.davmail;
|
||||
settings = {
|
||||
"davmail.mode" = "O365Manual";
|
||||
"davmail.url" = "https://outlook.office365.com/EWS/Exchange.asmx";
|
||||
# davmail.mode = "O365Modern";
|
||||
"davmail.keepDelay" = 30;
|
||||
# log4j.logger.davmail = "DEBUG";
|
||||
};
|
||||
configFile = "${dots}/config/davmail/davmail.properties";
|
||||
};
|
||||
|
||||
programs = {
|
||||
neomutt = {
|
||||
macros = [
|
||||
{
|
||||
map = [
|
||||
"index"
|
||||
"pager"
|
||||
];
|
||||
key = "<f2>";
|
||||
action = "<sync-mailbox><enter-command>source ~/.config/neomutt/uchicago<enter><change-folder>!<enter>";
|
||||
}
|
||||
{
|
||||
map = [
|
||||
"index"
|
||||
"pager"
|
||||
];
|
||||
key = "<f3>";
|
||||
action = "<sync-mailbox><enter-command>source ~/.config/neomutt/personal<enter><change-folder>!<enter>";
|
||||
}
|
||||
];
|
||||
};
|
||||
mbsync.enable = true;
|
||||
msmtp = {
|
||||
enable = true;
|
||||
};
|
||||
};
|
||||
|
||||
services = {
|
||||
mbsync = {
|
||||
# Mbsync service (mail sync)
|
||||
services.mbsync = {
|
||||
enable = config.custom.email.mbsync;
|
||||
configFile = "${dots}/config/mbsync/mbsyncrc";
|
||||
frequency = "*:0/1";
|
||||
};
|
||||
|
||||
# Install mail-related packages
|
||||
home.packages =
|
||||
with pkgs;
|
||||
[
|
||||
isync # mbsync
|
||||
msmtp
|
||||
sops # for password decryption
|
||||
age # for sops age backend
|
||||
]
|
||||
++ lib.optionals config.custom.email.neomutt [
|
||||
# Wrapper script for neomutt with truecolor support
|
||||
(writeShellScriptBin "neomutt" ''
|
||||
export TERMINFO_DIRS="${ncurses}/share/terminfo''${TERMINFO_DIRS:+:$TERMINFO_DIRS}"
|
||||
exec env TERM=xterm-direct ${neomutt}/bin/neomutt "$@"
|
||||
'')
|
||||
]
|
||||
++ lib.optionals config.custom.email.mailcap [
|
||||
mailcap
|
||||
w3m # HTML rendering
|
||||
zathura # PDF viewer
|
||||
kitty # for kitten icat
|
||||
];
|
||||
|
||||
# Symlink config files
|
||||
xdg.configFile = {
|
||||
"msmtp".source = config.lib.file.mkOutOfStoreSymlink "${dots}/config/msmtp";
|
||||
"neomutt".source = config.lib.file.mkOutOfStoreSymlink "${dots}/config/neomutt";
|
||||
"isyncrc".source = config.lib.file.mkOutOfStoreSymlink "${dots}/config/mbsync/mbsyncrc";
|
||||
};
|
||||
|
||||
accounts.email =
|
||||
let
|
||||
cat = lib.getExe' pkgs.coreutils "cat";
|
||||
in
|
||||
rec {
|
||||
maildirBasePath = "${home-dir}/mail";
|
||||
accounts = lib.mkMerge ([
|
||||
{
|
||||
"personal" = {
|
||||
userName = "raydreww@gmail.com";
|
||||
address = "raydreww@gmail.com";
|
||||
realName = "Ray Andrew";
|
||||
primary = !config.custom.email.davmail;
|
||||
signature = {
|
||||
text = ''
|
||||
-- Ray Andrew
|
||||
'';
|
||||
showSignature = "append";
|
||||
};
|
||||
passwordCommand = "${cat} ${config.sops.secrets."personal".path}";
|
||||
gpg = {
|
||||
key = "1913ECC8FD7076BC8330E11607AA5254804C009F";
|
||||
signByDefault = true;
|
||||
};
|
||||
smtp = {
|
||||
host = "smtp.gmail.com";
|
||||
};
|
||||
imap = {
|
||||
host = "imap.gmail.com";
|
||||
};
|
||||
mbsync = {
|
||||
enable = true;
|
||||
create = "both";
|
||||
expunge = "both";
|
||||
patterns = [
|
||||
"*"
|
||||
"!\"[Airmail]/Done\""
|
||||
"!\"[Airmail]/Snooze\""
|
||||
"!\"[Airmail]/To Do\""
|
||||
"!\"[Airmail]/Send Later\""
|
||||
"!\"[Gmail]/All Mail\""
|
||||
"!\"[Gmail]/Important\""
|
||||
"!\"[Gmail]/Starred\""
|
||||
"!\"[Gmail]/Bin\""
|
||||
];
|
||||
};
|
||||
msmtp = {
|
||||
enable = true;
|
||||
};
|
||||
neomutt = rec {
|
||||
enable = true;
|
||||
mailboxName = "p";
|
||||
extraConfig = ''
|
||||
set use_from = yes
|
||||
set pgp_verify_sig = yes
|
||||
set pgp_sign_as = 0x07AA5254804C009F
|
||||
set pgp_timeout = 3600
|
||||
named-mailboxes "${mailboxName}/inbox" =Inbox
|
||||
named-mailboxes "${mailboxName}/drafts" =Drafts
|
||||
named-mailboxes "${mailboxName}/sent" =Sent
|
||||
named-mailboxes "${mailboxName}/important" =Important
|
||||
named-mailboxes "${mailboxName}/trash" =Trash
|
||||
named-mailboxes "${mailboxName}/archive" =Archive
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
||||
(lib.mkIf config.custom.email.davmail {
|
||||
"uchicago" = {
|
||||
userName = "rayandrew@uchicago.edu";
|
||||
address = "rayandrew@uchicago.edu";
|
||||
realName = "Ray Andrew";
|
||||
primary = true;
|
||||
signature = {
|
||||
text = ''
|
||||
-- Ray Andrew
|
||||
'';
|
||||
showSignature = "append";
|
||||
};
|
||||
passwordCommand = "${cat} ${config.sops.secrets."uchicago".path}";
|
||||
gpg = {
|
||||
key = "0BADFAD0FB93296C84956F9CEEF04CFFE9DFE5FC";
|
||||
signByDefault = false;
|
||||
};
|
||||
smtp = {
|
||||
host = "127.0.0.1";
|
||||
port = 1025;
|
||||
tls = {
|
||||
enable = false;
|
||||
certificatesFile = null;
|
||||
};
|
||||
};
|
||||
imap = {
|
||||
host = "127.0.0.1";
|
||||
port = 1143;
|
||||
tls.enable = false;
|
||||
};
|
||||
mbsync = {
|
||||
enable = true;
|
||||
create = "both";
|
||||
expunge = "both";
|
||||
patterns = [
|
||||
"*"
|
||||
"!\"[Airmail]/Done\""
|
||||
"!\"[Airmail]/Snooze\""
|
||||
"!\"[Airmail]/To Do\""
|
||||
"!\"[Airmail]/Send Later\""
|
||||
];
|
||||
extraConfig.account = {
|
||||
TLSType = "None";
|
||||
AuthMechs = "LOGIN";
|
||||
Timeout = 0;
|
||||
};
|
||||
};
|
||||
msmtp = {
|
||||
enable = true;
|
||||
extraConfig = {
|
||||
auth = "plain";
|
||||
};
|
||||
};
|
||||
neomutt = rec {
|
||||
enable = true;
|
||||
mailboxName = "u";
|
||||
extraConfig = ''
|
||||
set use_from = yes
|
||||
set pgp_sign_as = 0xEEF04CFFE9DFE5FC
|
||||
set pgp_verify_sig = yes
|
||||
set pgp_timeout = 3600
|
||||
named-mailboxes "${mailboxName}/inbox" =Inbox
|
||||
named-mailboxes "${mailboxName}/drafts" =Drafts
|
||||
named-mailboxes "${mailboxName}/sent" =Sent
|
||||
named-mailboxes "${mailboxName}/important" =Important
|
||||
named-mailboxes "${mailboxName}/trash" =Trash
|
||||
named-mailboxes "${mailboxName}/archive" =Archive
|
||||
named-mailboxes "${mailboxName}/teaching" =Teaching
|
||||
'';
|
||||
};
|
||||
};
|
||||
})
|
||||
]);
|
||||
# mailcap symlink
|
||||
home.file = lib.mkIf config.custom.email.mailcap {
|
||||
".mailcap".source = config.lib.file.mkOutOfStoreSymlink "${dots}/config/home/.mailcap";
|
||||
};
|
||||
|
||||
sops = {
|
||||
age.keyFile = "${home-dir}/.config/sops/age/keys.txt";
|
||||
age.generateKey = true;
|
||||
defaultSopsFile = ./secrets.yaml;
|
||||
secrets = {
|
||||
"personal" = { };
|
||||
"uchicago" = { };
|
||||
};
|
||||
};
|
||||
# Create mail directories
|
||||
home.activation.createMailDirs = lib.hm.dag.entryAfter [ "writeBoundary" ] ''
|
||||
mkdir -p ~/mail/personal/Inbox
|
||||
mkdir -p ~/mail/uchicago/Inbox
|
||||
mkdir -p ~/.cache/neomutt/headers
|
||||
mkdir -p ~/.cache/neomutt/messages
|
||||
mkdir -p ~/.local/state
|
||||
'';
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,48 +0,0 @@
|
|||
{
|
||||
pkgs,
|
||||
lib,
|
||||
config,
|
||||
...
|
||||
}:
|
||||
|
||||
let
|
||||
w3m = lib.getExe pkgs.w3m;
|
||||
zathura = lib.getExe config.programs.zathura.package;
|
||||
# term = lib.getExe config.programs.kitty.package;
|
||||
term = lib.getExe config.programs.wezterm.package;
|
||||
in
|
||||
{
|
||||
options.custom.email = with lib; {
|
||||
mailcap = mkEnableOption "Enable mailcap";
|
||||
};
|
||||
|
||||
config = lib.mkIf config.custom.email.mailcap {
|
||||
home.packages = with pkgs; [
|
||||
mailcap
|
||||
];
|
||||
|
||||
home.file.".mailcap" = {
|
||||
text = ''
|
||||
# HTML
|
||||
text/html; ${w3m} -sixel -o tmp_dir=~/.cache/w3m -o auto_image=TRUE -o display_image=1 -T text/html %s; nametemplate=%s.html
|
||||
# text/html; ${w3m} -o inline_img_protocol=4 -o tmp_dir=~/.cache/w3m -o auto_image=TRUE -o display_image=1 -T text/html %s; nametemplate=%s.html
|
||||
|
||||
# This second one is chosen by auto_view due to the copiousoutput tag
|
||||
text/html; ${w3m} -I %{charset} -T text/html -cols 140 -o tmp_dir=~/.cache/w3m -o display_link_number=1 -dump; copiousoutput
|
||||
text/plain; nvim %s
|
||||
|
||||
#PDFs
|
||||
application/x-pdf; ${zathura} '%s'; test=test -n "$DISPLAY"
|
||||
application/pdf; ${zathura} '%s'; test=test -n "$DISPLAY"
|
||||
|
||||
message/rfc822; nvim %s
|
||||
|
||||
#Images
|
||||
# image/png; /usr/bin/feh %s
|
||||
# image/jpeg; /usr/bin/feh %s
|
||||
# image/*; (clear && ${term} +kitten icat %s); needsterminal
|
||||
image/*; (clear && ${term} imgcat %s); needsterminal
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
@ -1,72 +0,0 @@
|
|||
{ pkgs, ... }:
|
||||
|
||||
''
|
||||
# Header colors:
|
||||
color header blue default ".*"
|
||||
color header brightmagenta default "^(From)"
|
||||
color header brightcyan default "^(Subject)"
|
||||
color header brightwhite default "^(CC|BCC)"
|
||||
|
||||
mono bold bold
|
||||
mono underline underline
|
||||
mono indicator reverse
|
||||
mono error bold
|
||||
color normal default default
|
||||
color indicator brightyellow default # currently selected message. default makes bar clear, disabled arrow to save space.
|
||||
color sidebar_highlight red default
|
||||
color sidebar_divider brightblack black
|
||||
color sidebar_flagged red black
|
||||
color sidebar_new green black
|
||||
color normal brightyellow default
|
||||
color error red default
|
||||
color tilde black default
|
||||
color message cyan default
|
||||
color markers red white
|
||||
color attachment white default
|
||||
color search brightmagenta default
|
||||
color status brightyellow black
|
||||
color hdrdefault brightgreen default
|
||||
color quoted green default
|
||||
color quoted1 blue default
|
||||
color quoted2 cyan default
|
||||
color quoted3 yellow default
|
||||
color quoted4 red default
|
||||
color quoted5 brightred default
|
||||
color signature brightgreen default
|
||||
color bold black default
|
||||
color underline black default
|
||||
color normal default default
|
||||
|
||||
color body brightred default "[\-\.+_a-zA-Z0-9]+@[\-\.a-zA-Z0-9]+" # Email addresses
|
||||
color body brightblue default "(https?|ftp)://[\-\.,/%~_:?&=\#a-zA-Z0-9]+" # URL
|
||||
color body green default "\`[^\`]*\`" # Green text between ` and `
|
||||
color body brightblue default "^# \.*" # Headings as bold blue
|
||||
color body brightcyan default "^## \.*" # Subheadings as bold cyan
|
||||
color body brightgreen default "^### \.*" # Subsubheadings as bold green
|
||||
color body yellow default "^(\t| )*(-|\\*) \.*" # List items as yellow
|
||||
color body brightcyan default "[;:][-o][)/(|]" # emoticons
|
||||
color body brightcyan default "[;:][)(|]" # emoticons
|
||||
color body brightcyan default "[ ][*][^*]*[*][ ]?" # more emoticon?
|
||||
color body brightcyan default "[ ]?[*][^*]*[*][ ]" # more emoticon?
|
||||
color body red default "(BAD signature)"
|
||||
color body cyan default "(Good signature)"
|
||||
color body brightblack default "^gpg: Good signature .*"
|
||||
color body brightyellow default "^gpg: "
|
||||
color body brightyellow red "^gpg: BAD signature from.*"
|
||||
mono body bold "^gpg: Good signature"
|
||||
# mohttps://neomutt.org/code/config_vars.htmlno body bold "^gpg: BAD signature from.*"
|
||||
color body red default "([a-z][a-z0-9+-]*://(((([a-z0-9_.!~*'();:&=+$,-]|%[0-9a-f][0-9a-f])*@)?((([a-z0-9]([a-z0-9-]*[a-z0-9])?)\\.)*([a-z]([a-z0-9-]*[a-z0-9])?)\\.?|[0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+)(:[0-9]+)?)|([a-z0-9_.!~*'()$,;:@&=+-]|%[0-9a-f][0-9a-f])+)(/([a-z0-9_.!~*'():@&=+$,-]|%[0-9a-f][0-9a-f])*(;([a-z0-9_.!~*'():@&=+$,-]|%[0-9a-f][0-9a-f])*)*(/([a-z0-9_.!~*'():@&=+$,-]|%[0-9a-f][0-9a-f])*(;([a-z0-9_.!~*'():@&=+$,-]|%[0-9a-f][0-9a-f])*)*)*)?(\\?([a-z0-9_.!~*'();/?:@&=+$,-]|%[0-9a-f][0-9a-f])*)?(#([a-z0-9_.!~*'();/?:@&=+$,-]|%[0-9a-f][0-9a-f])*)?|(www|ftp)\\.(([a-z0-9]([a-z0-9-]*[a-z0-9])?)\\.)*([a-z]([a-z0-9-]*[a-z0-9])?)\\.?(:[0-9]+)?(/([-a-z0-9_.!~*'():@&=+$,]|%[0-9a-f][0-9a-f])*(;([-a-z0-9_.!~*'():@&=+$,]|%[0-9a-f][0-9a-f])*)*(/([-a-z0-9_.!~*'():@&=+$,]|%[0-9a-f][0-9a-f])*(;([-a-z0-9_.!~*'():@&=+$,]|%[0-9a-f][0-9a-f])*)*)*)?(\\?([-a-z0-9_.!~*'();/?:@&=+$,]|%[0-9a-f][0-9a-f])*)?(#([-a-z0-9_.!~*'();/?:@&=+$,]|%[0-9a-f][0-9a-f])*)?)[^].,:;!)? \t\r\n<>\"]"
|
||||
|
||||
# Default index colors:
|
||||
color index yellow default '.*'
|
||||
color index_author red default '.*'
|
||||
color index_number blue default
|
||||
color index_subject cyan default '.*'
|
||||
|
||||
# For new mail:
|
||||
color index brightyellow black "~N"
|
||||
color index_author brightred black "~N"
|
||||
color index_subject brightcyan black "~N"
|
||||
|
||||
color progress black cyan
|
||||
''
|
||||
|
|
@ -1,78 +0,0 @@
|
|||
{
|
||||
pkgs,
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}:
|
||||
|
||||
let
|
||||
keybinds = import ./keybind.nix rec {
|
||||
inherit config lib pkgs;
|
||||
};
|
||||
colors = import ./colors.nix rec {
|
||||
inherit config lib pkgs;
|
||||
};
|
||||
in
|
||||
{
|
||||
|
||||
options.custom.email = with lib; {
|
||||
neomutt = mkEnableOption "Enable NeoMutt";
|
||||
};
|
||||
|
||||
config = lib.mkIf (config.custom.email.enable && config.custom.email.neomutt) {
|
||||
xsession.windowManager.i3.config =
|
||||
let
|
||||
i3config = config.xsession.windowManager.i3.config;
|
||||
in
|
||||
{
|
||||
keybindings = lib.mkOptionDefault {
|
||||
"${i3config.modifier}+m" =
|
||||
"exec --no-startup-id ${i3config.terminal} -e ${config.programs.neomutt.package}/bin/neomutt";
|
||||
};
|
||||
};
|
||||
|
||||
programs.neomutt = {
|
||||
enable = true;
|
||||
vimKeys = false;
|
||||
sort = "threads";
|
||||
unmailboxes = true;
|
||||
binds = keybinds.binds ++ [ ];
|
||||
macros = keybinds.macros ++ [ ];
|
||||
extraConfig = ''
|
||||
set abort_key = "<Esc>"
|
||||
|
||||
# set editor = "nvim"
|
||||
set editor = "emacs -nw"
|
||||
|
||||
set edit_headers = yes
|
||||
set sidebar_visible
|
||||
set sidebar_format = "%D%?F? [%F]?%* %?N?%N/?%S"
|
||||
set mail_check_stats
|
||||
# set new_mail_command="notify-send 'New Email' '%n new messages, %u unread.' &"
|
||||
|
||||
# status bar, date format, finding stuff etc.
|
||||
set status_chars = " *%A"
|
||||
# set status_format = "[ Folder: %f ] [%r%m messages%?n? (%n new)?%?d? (%d to delete)?%?t? (%t tagged)? ]%>─%?p?( %p postponed )?"
|
||||
set status_format = "[ Folder: %D ] [%r%m messages%?n? (%n new)?%?d? (%d to delete)?%?t? (%t tagged)? ]%>─%?p?( %p postponed )?"
|
||||
set date_format = "%d.%m.%Y %H:%M"
|
||||
set uncollapse_jump
|
||||
set sort_re
|
||||
set reply_regexp = "^(([Rr][Ee]?(\[[0-9]+\])?: *)?(\[[^]]+\] *)?)*"
|
||||
set quote_regexp = "^( {0,4}[>|:#%]| {0,4}[a-z0-9]+[>|]+)+"
|
||||
set send_charset = "utf-8:iso-8859-1:us-ascii"
|
||||
set charset = "utf-8"
|
||||
set arrow_cursor = "no" # Change `color indicator` depending
|
||||
|
||||
# Pager View Options
|
||||
set pager_index_lines = 10 # Shows 10 lines of index when pager is active
|
||||
set pager_context = 3
|
||||
set pager_stop
|
||||
set menu_scroll
|
||||
set tilde
|
||||
unset markers
|
||||
|
||||
${colors}
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
@ -1,316 +0,0 @@
|
|||
{ pkgs, ... }:
|
||||
|
||||
{
|
||||
binds = [
|
||||
{
|
||||
map = [ "attach" ];
|
||||
key = "<return>";
|
||||
action = "view-mailcap";
|
||||
}
|
||||
{
|
||||
map = [ "attach" ];
|
||||
key = "l";
|
||||
action = "view-mailcap";
|
||||
}
|
||||
# {
|
||||
# map = [ "attach" ];
|
||||
# key = "O";
|
||||
# action = "<enter-command>unset wait_key<enter><shell-escape>rm -f /tmp/mutt-attach<enter><save-entry><kill-line>/tmp/mutt-attach<enter>^A";
|
||||
# }
|
||||
{
|
||||
map = [ "editor" ];
|
||||
key = "<space>";
|
||||
action = "noop";
|
||||
}
|
||||
{
|
||||
map = [ "pager" ];
|
||||
key = "c";
|
||||
action = "imap-fetch-mail";
|
||||
}
|
||||
{
|
||||
map = [ "index" ];
|
||||
key = "G";
|
||||
action = "last-entry";
|
||||
}
|
||||
{
|
||||
map = [ "index" ];
|
||||
key = "g";
|
||||
action = "noop";
|
||||
}
|
||||
{
|
||||
map = [ "index" ];
|
||||
key = "gg";
|
||||
action = "first-entry";
|
||||
}
|
||||
{
|
||||
map = [
|
||||
"pager"
|
||||
"attach"
|
||||
];
|
||||
key = "h";
|
||||
action = "exit";
|
||||
}
|
||||
{
|
||||
map = [ "pager" ];
|
||||
key = "j";
|
||||
action = "next-line";
|
||||
}
|
||||
{
|
||||
map = [ "pager" ];
|
||||
key = "k";
|
||||
action = "previous-line";
|
||||
}
|
||||
{
|
||||
map = [ "pager" ];
|
||||
key = "l";
|
||||
action = "view-attachments";
|
||||
}
|
||||
{
|
||||
map = [ "index" ];
|
||||
key = "D";
|
||||
action = "delete-message";
|
||||
}
|
||||
{
|
||||
map = [ "index" ];
|
||||
key = "U";
|
||||
action = "undelete-message";
|
||||
}
|
||||
{
|
||||
map = [ "index" ];
|
||||
key = "L";
|
||||
action = "limit";
|
||||
}
|
||||
{
|
||||
map = [ "index" ];
|
||||
key = "h";
|
||||
action = "noop";
|
||||
}
|
||||
{
|
||||
map = [
|
||||
"browser"
|
||||
"pager"
|
||||
"index"
|
||||
];
|
||||
key = "n";
|
||||
action = "search-next";
|
||||
}
|
||||
{
|
||||
map = [
|
||||
"browser"
|
||||
"pager"
|
||||
"index"
|
||||
];
|
||||
key = "N";
|
||||
action = "search-opposite";
|
||||
}
|
||||
{
|
||||
map = [ "index" ];
|
||||
key = "l";
|
||||
action = "display-message";
|
||||
}
|
||||
{
|
||||
map = [ "browser" ];
|
||||
key = "h";
|
||||
action = "goto-parent";
|
||||
}
|
||||
{
|
||||
map = [ "browser" ];
|
||||
key = "l";
|
||||
action = "select-entry";
|
||||
}
|
||||
{
|
||||
map = [
|
||||
"pager"
|
||||
"browser"
|
||||
];
|
||||
key = "gg";
|
||||
action = "top-page";
|
||||
}
|
||||
{
|
||||
map = [
|
||||
"pager"
|
||||
"browser"
|
||||
];
|
||||
key = "G";
|
||||
action = "bottom-page";
|
||||
}
|
||||
{
|
||||
map = [
|
||||
"index"
|
||||
"pager"
|
||||
"browser"
|
||||
];
|
||||
key = "d";
|
||||
action = "half-down";
|
||||
}
|
||||
{
|
||||
map = [
|
||||
"index"
|
||||
"pager"
|
||||
"browser"
|
||||
];
|
||||
key = "u";
|
||||
action = "half-up";
|
||||
}
|
||||
{
|
||||
map = [ "index" ];
|
||||
key = "R";
|
||||
action = "group-reply";
|
||||
}
|
||||
{
|
||||
map = [ "index" ];
|
||||
key = "\\031";
|
||||
action = "previous-undeleted";
|
||||
}
|
||||
{
|
||||
map = [ "index" ];
|
||||
key = "\\005";
|
||||
action = "next-undeleted";
|
||||
}
|
||||
{
|
||||
map = [ "pager" ];
|
||||
key = "\\031";
|
||||
action = "previous-line";
|
||||
}
|
||||
{
|
||||
map = [ "pager" ];
|
||||
key = "\\005";
|
||||
action = "next-line";
|
||||
}
|
||||
{
|
||||
map = [ "editor" ];
|
||||
key = "<Tab>";
|
||||
action = "complete-query";
|
||||
}
|
||||
{
|
||||
map = [
|
||||
"index"
|
||||
"pager"
|
||||
];
|
||||
key = "\\Ck";
|
||||
action = "sidebar-prev";
|
||||
}
|
||||
{
|
||||
map = [
|
||||
"index"
|
||||
"pager"
|
||||
];
|
||||
key = "\\Cj";
|
||||
action = "sidebar-next";
|
||||
}
|
||||
{
|
||||
map = [
|
||||
"index"
|
||||
"pager"
|
||||
];
|
||||
key = "\\Co";
|
||||
action = "sidebar-open";
|
||||
}
|
||||
{
|
||||
map = [
|
||||
"index"
|
||||
"pager"
|
||||
];
|
||||
key = "\\Cp";
|
||||
action = "sidebar-prev-new";
|
||||
}
|
||||
{
|
||||
map = [
|
||||
"index"
|
||||
"pager"
|
||||
];
|
||||
key = "\\Cn";
|
||||
action = "sidebar-next-new";
|
||||
}
|
||||
{
|
||||
map = [
|
||||
"index"
|
||||
"pager"
|
||||
];
|
||||
key = "B";
|
||||
action = "sidebar-toggle-visible";
|
||||
}
|
||||
{
|
||||
map = [
|
||||
"index"
|
||||
"pager"
|
||||
];
|
||||
key = "@";
|
||||
action = "compose-to-sender";
|
||||
}
|
||||
{
|
||||
map = [
|
||||
"index"
|
||||
"pager"
|
||||
];
|
||||
key = "D";
|
||||
action = "purge-message";
|
||||
}
|
||||
{
|
||||
map = [ "index" ];
|
||||
key = "<tab>";
|
||||
action = "sync-mailbox";
|
||||
}
|
||||
{
|
||||
map = [ "index" ];
|
||||
key = "<space>";
|
||||
action = "collapse-thread";
|
||||
}
|
||||
{
|
||||
map = [ "editor" ];
|
||||
key = "<Tab>";
|
||||
action = "complete-query";
|
||||
}
|
||||
{
|
||||
map = [ "editor" ];
|
||||
key = "^T";
|
||||
action = "complete";
|
||||
}
|
||||
# {
|
||||
# map = [
|
||||
# "index"
|
||||
# "pager"
|
||||
# ];
|
||||
# key = "<f2>";
|
||||
# action = "<sync-mailbox><enter-command>source ~/.config/neomutt/accounts/uchicago<enter><change-folder>!<enter>";
|
||||
# }
|
||||
# {
|
||||
# map = [
|
||||
# "index"
|
||||
# "pager"
|
||||
# ];
|
||||
# key = "<f3>";
|
||||
# action = "<sync-mailbox><enter-command>source ~/.config/neomutt/accounts/personal<enter><change-folder>!<enter>";
|
||||
# }
|
||||
# {
|
||||
# map = [ "attach" ];
|
||||
# key = "V";
|
||||
# action = "<pipe-entry>iconv -c --to-code=UTF8 > ~/.cache/mutt-mail.html<enter><shell-escape>xdg-open ~/.cache/mutt-mail.html<enter>";
|
||||
# }
|
||||
];
|
||||
macros = [
|
||||
{
|
||||
map = [
|
||||
"index"
|
||||
"pager"
|
||||
];
|
||||
key = "a";
|
||||
action = ":set confirmappend=no delete=yes\\n<tag-prefix><save-message>=Archive\\n<sync-mailbox>:set confirmappend=yes delete=ask-yes\\n";
|
||||
}
|
||||
{
|
||||
map = [
|
||||
"index"
|
||||
"pager"
|
||||
];
|
||||
key = "n";
|
||||
action = "<tag-prefix><clear-flag>N<untag-pattern>.<enter>\\n";
|
||||
}
|
||||
{
|
||||
map = [
|
||||
"attach"
|
||||
];
|
||||
key = "O";
|
||||
action = "<enter-command>unset wait_key<enter><shell-escape>rm -f /tmp/mutt-attach<enter><save-entry><kill-line>/tmp/mutt-attach<enter>^A";
|
||||
}
|
||||
];
|
||||
}
|
||||
|
|
@ -1,31 +1,35 @@
|
|||
personal: ENC[AES256_GCM,data:aaZAYmnoQfGIH6bBneKtTA==,iv:xiy1eCyBhFulfRXGz0WDFLaqPj3kXsMD4Xkk7D4s5XA=,tag:Nk0KsgICo505VEMwVUt3TA==,type:str]
|
||||
uchicago: ENC[AES256_GCM,data:3ZkuIfvzOkKfQD0iyTk=,iv:aCfFrxDM5Ly/qLdLAQkK2tOxb89dFkCc9RhN5GVSGRw=,tag:7D54pkVX2F6IhM38JOUFQg==,type:str]
|
||||
personal: ENC[AES256_GCM,data:MG1ryntM2YKyjb0YH/8GYg==,iv:SvwAc1dBl8wc1YWdnOuCNAb5RUNA2vLX87uzOGOaqec=,tag:ixVU3FWGpZqZx/1PD3/3KA==,type:str]
|
||||
uchicago: ENC[AES256_GCM,data:LqZTprY/9Li8ab9i0dg=,iv:tLJHXwsoL7PnwonHlnXiaLahr0+fIizsoshE0GFbkn8=,tag:FT5brU6pW7xFxnzpBYU2jA==,type:str]
|
||||
sops:
|
||||
kms: []
|
||||
gcp_kms: []
|
||||
azure_kv: []
|
||||
hc_vault: []
|
||||
age:
|
||||
- recipient: age13cfe8fhp4m978qlcur46vkkxepsl93ggwe53kmhue9xtpgr5zu5q4y6ln2
|
||||
enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBMMTcwTEc5VTdEMlZSK1FI
|
||||
c2VVdjJOc3B3V2RGS0pIVGQralJ4MGFwSkRvCm5mVTNxMHUzNythNHVyRG52bVYz
|
||||
RVp2d1hKUnpucko1SG01SDdWNFZGV1EKLS0tIDB2OGF1UlUyN2xnRm1WR1RleUhN
|
||||
S1hFWjhCMlNZVC83ZzR4NittcXlCQlUKQO6NHCMwWKwrfwwnwLK/sO4HO6ES+PyT
|
||||
dh3tRhPlv7/viO+MtHqUfQ5cbW+OWoic4prfK/UxIz5VeY331kpq+g==
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBxUjF4Nm0yVWFwMUM1Y2hn
|
||||
SVRhUmEweDNVd3Z2NVpEVW1yaDRYaDhLZ0NZCjE3WkVTWXUrKzE1VGN5ZUtSb2VZ
|
||||
WnJFRkkwZmJKTm5OWlpMLzlCZHR6aE0KLS0tIFZ3UEFmcTJIYlcrUXhyU1hSMFRK
|
||||
MjhvU0NQamQzcE1sWG5FSmpoajdNc0UKslJWrvq4BIeMoZ6ZSA6anlldGOpUuXrL
|
||||
PV7pVpTihxWtzPbPV36oPRVoN3GzNZXUPJryExtUzdnufbhfu9LBTw==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
- recipient: age1pdk6dmyxqhdaja5d0nf8f9qjd43hmfahmkure5yrf8al9jyfmd8qfdxwl6
|
||||
enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB0ajhrbkdqcmpRd2svYmNx
|
||||
dHIzRDJTTTVGV3VON0NBZnpaQTdGM2w4aXpNClNqb2Y4Qzg4OWx2a3FNdG5MY1ZQ
|
||||
R2dOSC9CdzBPM1I5b1lCVnptMGM3eUEKLS0tIGZRM1pSV3J0NlJvQUZBcTVNZGxy
|
||||
SS9qQlJiRU1EelZySWpNdWRiTms3ZncKkwp1WT9LWxnJb+yjilikTHRm1fbs89TU
|
||||
1Xzy+GNiZbtm2I6e5XaaD+9d3PFvqqu0OdqrMrTMmiNAys0WhwB8Iw==
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBOZ01sMXhvMG5BMmxwa3h1
|
||||
aXArSkxUNUkwOHAzQnlkYk4vVmEzckZkaFVzCnpYRmpqMW9QM29VTWFnc0NYTURj
|
||||
REp0OVNPN1lRRUdPWlQrTmhYcEZwbm8KLS0tIFI2dFBzbmQ4Q01PU1BLUXI5eXIy
|
||||
Y0ZMMmJTOVRrbXpOVkYxektxOFFkZUEKcjX/wDMvuZ+PzfydOGOf938mCVcFFD/h
|
||||
nGdbXAoE+cD7/rmpaF0Bpm2WqWrkiAvE/csyaWV/HNzQ6JkXp/4jtQ==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
lastmodified: "2025-03-04T21:54:28Z"
|
||||
mac: ENC[AES256_GCM,data:r+2SOcW7xLHee9kL8369yB6l/Z2XdnzGkeFygSrDgcZVfBfp/fT1xeMvu5tuu8aqsUeJ7lkFD2VKiBue95XSojdlM+5YyTerqdzLyMCRbkRivC3O2xXe90B4hVqm+twE9uu74mIznAQ2e0EO9E0MMlMNBo3EwsEcYA8gyVuB5mc=,iv:plNu3BircQ+kpPaXqlNvYlLAL5V5RX/yiETs+nY1pfw=,tag:7gVuOpzx5YsHtwodIRr4TQ==,type:str]
|
||||
pgp: []
|
||||
- recipient: age15vscvpe79l287h8f3hssrj2r45xy0l3ns94zfue2fxlq43cqdsxq58vq3c
|
||||
enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBQdVV6Vy9pRmg1ZjR5c01w
|
||||
L1JWWDF6U05RNnNGTjF1VEN6ZCt6SENod2xJCjA1QngrQnJXMi9BdFByT3FPSVVR
|
||||
eUEyd29YQXphZ2VuTmorOWU4MjZ1TmMKLS0tIFNSZG5iV21MSHVBNkZoZW5pV09k
|
||||
eS9JTWRDaVZVN2hLcVF1S2NTdk1TWGMKVnpl9T5ZycSlJmE8M8QY62kxDp5lgagF
|
||||
D6hxceNiqvgGg+GwIRXoVYiVhmNAE1R9dVTyMlAfFa2pxGg7JrPj1A==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
lastmodified: "2025-12-02T05:42:16Z"
|
||||
mac: ENC[AES256_GCM,data:95V5+/M85gUaeJD8UhkMZCcMbYEnEBIA3qFDSDd0ZoxXQkw+IXy3/C8rV9QPK/Bq/Hv3fPWbs+0CwH5GqhjfaoIlVgo3MBlk6Z1iSuw7MTy8vGOBFWpYBrObib8f9yYIZ74CrpvCHHoFtqP5cKevmHsCvgrJpbkw4gZIhZVkjLk=,iv:0/v8QzgZYc/VMei0qP1PlK4oc4b2ch5VoBEW3P3gXxU=,tag:rFTyhSixSzl1BOIhGDJo+g==,type:str]
|
||||
unencrypted_suffix: _unencrypted
|
||||
version: 3.9.4
|
||||
version: 3.11.0
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@
|
|||
nerd-fonts.droid-sans-mono
|
||||
nerd-fonts.space-mono
|
||||
nerd-fonts.dejavu-sans-mono
|
||||
nerd-fonts.symbols-only
|
||||
];
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -60,6 +60,7 @@
|
|||
pandoc
|
||||
duckdb
|
||||
hyperfine
|
||||
fastfetch
|
||||
(pkgs.python311.withPackages (ppkgs: [
|
||||
ppkgs.numpy
|
||||
]))
|
||||
|
|
@ -69,10 +70,18 @@
|
|||
})
|
||||
imagemagick
|
||||
spotify-player
|
||||
eza
|
||||
]
|
||||
++ lib.optionals pkgs.stdenv.isDarwin [ coreutils ]
|
||||
++ (lib.attrValues config.custom.shell.packages);
|
||||
|
||||
home.shellAliases = {
|
||||
ls = "eza";
|
||||
ll = "eza -la --icons --git";
|
||||
la = "eza -a --icons";
|
||||
lt = "eza --tree --level=2 --icons";
|
||||
};
|
||||
|
||||
programs.bash = {
|
||||
enable = true;
|
||||
enableVteIntegration = true;
|
||||
|
|
@ -103,6 +112,8 @@
|
|||
enableFishIntegration = config.programs.fish.enable;
|
||||
};
|
||||
|
||||
xdg.configFile."direnv/direnv.toml".source =
|
||||
config.lib.file.mkOutOfStoreSymlink "${dots}/config/direnv/direnv.toml";
|
||||
xdg.configFile."sesh".source = config.lib.file.mkOutOfStoreSymlink "${dots}/config/sesh";
|
||||
xdg.configFile."yazi".source = config.lib.file.mkOutOfStoreSymlink "${dots}/config/yazi";
|
||||
xdg.configFile."spotify-player".source =
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
{
|
||||
pkgs,
|
||||
home-dir,
|
||||
...
|
||||
}:
|
||||
{
|
||||
|
|
@ -80,6 +81,13 @@
|
|||
];
|
||||
|
||||
hm.custom = {
|
||||
environment = {
|
||||
enable = true;
|
||||
variables = {
|
||||
EDITOR = "nvim";
|
||||
SOPS_AGE_KEY_FILE = "${home-dir}/.config/sops/age/keys.txt";
|
||||
};
|
||||
};
|
||||
emacs.enable = true;
|
||||
neovim.enable = true;
|
||||
latex.enable = true;
|
||||
|
|
@ -91,5 +99,12 @@
|
|||
hammerspoon.enable = true;
|
||||
kitty.enable = true;
|
||||
};
|
||||
email = {
|
||||
enable = true;
|
||||
davmail = true;
|
||||
neomutt = true;
|
||||
mbsync = true;
|
||||
mailcap = true;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ let
|
|||
./shared.nix
|
||||
./${host}
|
||||
./${host}/hardware.nix
|
||||
../modules/nixos
|
||||
../nixos
|
||||
(
|
||||
{ config, ... }:
|
||||
|
|
@ -59,6 +60,7 @@ let
|
|||
imports = [
|
||||
inputs.nix-index-database.homeModules.nix-index
|
||||
inputs.sops-nix.homeManagerModules.sops
|
||||
../modules/home-manager
|
||||
../home
|
||||
]
|
||||
++ lib.optional (builtins.pathExists ./${host}/home.nix) ./${host}/home.nix;
|
||||
|
|
@ -114,6 +116,7 @@ let
|
|||
modules = [
|
||||
./shared.nix
|
||||
./${host}
|
||||
../modules/darwin
|
||||
../darwin
|
||||
(
|
||||
{ config, ... }:
|
||||
|
|
@ -134,6 +137,7 @@ let
|
|||
inputs.nix-index-database.homeModules.nix-index
|
||||
inputs.sops-nix.homeManagerModules.sops
|
||||
inputs.mac-app-util.homeManagerModules.default
|
||||
../modules/home-manager
|
||||
../home
|
||||
]
|
||||
++ lib.optional (builtins.pathExists ./${host}/home.nix) ./${host}/home.nix;
|
||||
|
|
|
|||
|
|
@ -1,13 +1,5 @@
|
|||
{
|
||||
inputs,
|
||||
lib,
|
||||
config,
|
||||
pkgs,
|
||||
system,
|
||||
dots,
|
||||
user,
|
||||
hm,
|
||||
host,
|
||||
...
|
||||
}:
|
||||
{
|
||||
|
|
|
|||
5
modules/darwin/default.nix
Normal file
5
modules/darwin/default.nix
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
imports = [
|
||||
# Add darwin-specific custom modules here
|
||||
];
|
||||
}
|
||||
6
modules/home-manager/default.nix
Normal file
6
modules/home-manager/default.nix
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
imports = [
|
||||
./overrides
|
||||
./environment.nix
|
||||
];
|
||||
}
|
||||
50
modules/home-manager/environment.nix
Normal file
50
modules/home-manager/environment.nix
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
# Home Manager environment module
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}:
|
||||
let
|
||||
inherit (lib)
|
||||
mkEnableOption
|
||||
mkOption
|
||||
mkIf
|
||||
types
|
||||
;
|
||||
|
||||
cfg = config.custom.environment;
|
||||
|
||||
# Convert attrset to shell export statements
|
||||
toShellExports =
|
||||
vars:
|
||||
lib.concatStringsSep "\n" (lib.mapAttrsToList (name: value: ''export ${name}="${value}"'') vars);
|
||||
|
||||
# Convert attrset to fish set statements
|
||||
toFishSets =
|
||||
vars:
|
||||
lib.concatStringsSep "\n" (lib.mapAttrsToList (name: value: ''set -gx ${name} "${value}"'') vars);
|
||||
in
|
||||
{
|
||||
options.custom.environment = {
|
||||
enable = mkEnableOption "custom environment configuration";
|
||||
|
||||
variables = mkOption {
|
||||
type = types.attrsOf types.str;
|
||||
default = { };
|
||||
description = "Environment variables to set across all shells.";
|
||||
example = {
|
||||
EDITOR = "nvim";
|
||||
SOPS_AGE_KEY_FILE = "$HOME/.config/sops/age/keys.txt";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
home.sessionVariables = cfg.variables;
|
||||
|
||||
# Also add to shell configs for immediate availability
|
||||
programs.bash.bashrcExtra = lib.mkAfter (toShellExports cfg.variables);
|
||||
programs.zsh.initContent = lib.mkAfter (toShellExports cfg.variables);
|
||||
programs.fish.shellInit = lib.mkAfter (toFishSets cfg.variables);
|
||||
};
|
||||
}
|
||||
181
modules/home-manager/overrides/davmail.nix
Normal file
181
modules/home-manager/overrides/davmail.nix
Normal file
|
|
@ -0,0 +1,181 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
let
|
||||
inherit (lib)
|
||||
getExe
|
||||
mapAttrsRecursive
|
||||
mkDefault
|
||||
mkEnableOption
|
||||
mkIf
|
||||
mkMerge
|
||||
mkOption
|
||||
optionalAttrs
|
||||
types
|
||||
;
|
||||
|
||||
cfg = config.services.davmail;
|
||||
|
||||
isDarwin = pkgs.stdenv.isDarwin;
|
||||
isLinux = pkgs.stdenv.isLinux;
|
||||
|
||||
javaProperties = pkgs.formats.javaProperties { };
|
||||
|
||||
generatedSettingsFile = javaProperties.generate "davmail.properties" cfg.settings;
|
||||
|
||||
# Use configFile if provided, otherwise use generated settings
|
||||
settingsFile = if cfg.configFile != null then cfg.configFile else generatedSettingsFile;
|
||||
in
|
||||
{
|
||||
disabledModules = [ "services/davmail.nix" ];
|
||||
|
||||
meta.maintainers = [ lib.maintainers.bmrips ];
|
||||
|
||||
options.services.davmail = {
|
||||
enable = mkEnableOption "DavMail, an MS Exchange gateway.";
|
||||
|
||||
package = lib.mkPackageOption pkgs "davmail" { };
|
||||
|
||||
configFile = mkOption {
|
||||
type = types.nullOr types.path;
|
||||
default = null;
|
||||
description = ''
|
||||
Path to a custom davmail.properties configuration file.
|
||||
If set, this file will be used instead of generating one from settings.
|
||||
'';
|
||||
example = "~/.config/davmail/davmail.properties";
|
||||
};
|
||||
|
||||
imitateOutlook = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = "Whether DavMail pretends to be Outlook.";
|
||||
example = true;
|
||||
};
|
||||
|
||||
settings = mkOption {
|
||||
type = javaProperties.type;
|
||||
default = { };
|
||||
description = ''
|
||||
Davmail configuration. Refer to
|
||||
<http://davmail.sourceforge.net/serversetup.html>
|
||||
and <http://davmail.sourceforge.net/advanced.html>
|
||||
for details on supported values.
|
||||
'';
|
||||
example = {
|
||||
"davmail.url" = "https://outlook.office365.com/EWS/Exchange.asmx";
|
||||
"davmail.allowRemote" = true;
|
||||
"davmail.imapPort" = 55555;
|
||||
"davmail.bindAddress" = "10.0.1.2";
|
||||
"davmail.smtpSaveInSent" = true;
|
||||
"davmail.folderSizeLimit" = 10;
|
||||
"davmail.caldavAutoSchedule" = false;
|
||||
"log4j.logger.rootLogger" = "DEBUG";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable (mkMerge [
|
||||
# Common configuration for all platforms
|
||||
{
|
||||
home.packages = [ cfg.package ];
|
||||
}
|
||||
|
||||
# Default settings (only when configFile is not provided)
|
||||
(mkIf (cfg.configFile == null) {
|
||||
services.davmail.settings =
|
||||
mapAttrsRecursive (_: mkDefault) {
|
||||
"davmail.server" = true;
|
||||
"davmail.disableUpdateCheck" = true;
|
||||
"davmail.logFilePath" = "${config.xdg.stateHome}/davmail.log";
|
||||
"davmail.logFileSize" = "1MB";
|
||||
"davmail.mode" = "auto";
|
||||
"davmail.url" = "https://outlook.office365.com/EWS/Exchange.asmx";
|
||||
"davmail.caldavPort" = 1080;
|
||||
"davmail.imapPort" = 1143;
|
||||
"davmail.ldapPort" = 1389;
|
||||
"davmail.popPort" = 1110;
|
||||
"davmail.smtpPort" = 1025;
|
||||
|
||||
"davmail.oauth.tokenFilePath" = "${config.xdg.stateHome}/davmail-tokens";
|
||||
|
||||
"log4j.logger.davmail" = "WARN";
|
||||
"log4j.logger.httpclient.wire" = "WARN";
|
||||
"log4j.logger.org.apache.commons.httpclient" = "WARN";
|
||||
"log4j.rootLogger" = "WARN";
|
||||
}
|
||||
// optionalAttrs cfg.imitateOutlook {
|
||||
"davmail.oauth.clientId" = "d3590ed6-52b3-4102-aeff-aad2292ab01c";
|
||||
"davmail.oauth.redirectUri" = "urn:ietf:wg:oauth:2.0:oob";
|
||||
};
|
||||
})
|
||||
|
||||
# Linux-specific: systemd user service
|
||||
(mkIf isLinux {
|
||||
systemd.user.services.davmail = {
|
||||
Unit = {
|
||||
Description = "DavMail POP/IMAP/SMTP Exchange Gateway";
|
||||
After = [
|
||||
"graphical-session.target"
|
||||
"network.target"
|
||||
];
|
||||
};
|
||||
Install.WantedBy = [ "graphical-session.target" ];
|
||||
Service = {
|
||||
Type = "exec";
|
||||
ExecStart = "${getExe cfg.package} ${settingsFile}";
|
||||
Restart = "on-failure";
|
||||
|
||||
CapabilityBoundingSet = [ "" ];
|
||||
DeviceAllow = [ "" ];
|
||||
LockPersonality = true;
|
||||
NoNewPrivileges = true;
|
||||
PrivateDevices = true;
|
||||
PrivateTmp = true;
|
||||
PrivateUsers = true;
|
||||
ProtectClock = true;
|
||||
ProtectControlGroups = true;
|
||||
ProtectSystem = "strict";
|
||||
ProtectHostname = true;
|
||||
ProtectKernelLogs = true;
|
||||
ProtectKernelModules = true;
|
||||
ProtectKernelTunables = true;
|
||||
ProtectProc = "invisible";
|
||||
RemoveIPC = true;
|
||||
RestrictAddressFamilies = [
|
||||
"AF_INET"
|
||||
"AF_INET6"
|
||||
"AF_UNIX"
|
||||
];
|
||||
RestrictNamespaces = true;
|
||||
RestrictRealtime = true;
|
||||
RestrictSUIDSGID = true;
|
||||
SystemCallArchitectures = "native";
|
||||
SystemCallFilter = "@system-service";
|
||||
SystemCallErrorNumber = "EPERM";
|
||||
UMask = "0077";
|
||||
};
|
||||
};
|
||||
})
|
||||
|
||||
# Darwin-specific: launchd agent
|
||||
(mkIf isDarwin {
|
||||
launchd.agents.davmail = {
|
||||
enable = true;
|
||||
config = {
|
||||
ProgramArguments = [
|
||||
"${getExe cfg.package}"
|
||||
"${settingsFile}"
|
||||
];
|
||||
KeepAlive = true;
|
||||
RunAtLoad = true;
|
||||
StandardErrorPath = "/tmp/davmail.err.log";
|
||||
StandardOutPath = "/tmp/davmail.out.log";
|
||||
};
|
||||
};
|
||||
})
|
||||
]);
|
||||
}
|
||||
6
modules/home-manager/overrides/default.nix
Normal file
6
modules/home-manager/overrides/default.nix
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
imports = [
|
||||
./davmail.nix
|
||||
./mbsync.nix
|
||||
];
|
||||
}
|
||||
161
modules/home-manager/overrides/mbsync.nix
Normal file
161
modules/home-manager/overrides/mbsync.nix
Normal file
|
|
@ -0,0 +1,161 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
let
|
||||
inherit (lib)
|
||||
concatStringsSep
|
||||
mkIf
|
||||
mkMerge
|
||||
mkOption
|
||||
optionalAttrs
|
||||
types
|
||||
;
|
||||
|
||||
cfg = config.services.mbsync;
|
||||
|
||||
isDarwin = pkgs.stdenv.isDarwin;
|
||||
isLinux = pkgs.stdenv.isLinux;
|
||||
|
||||
mbsyncOptions = [
|
||||
"--all"
|
||||
]
|
||||
++ lib.optional cfg.verbose "--verbose"
|
||||
++ lib.optional (cfg.configFile != null) "--config ${cfg.configFile}";
|
||||
|
||||
mbsyncCommand = "${cfg.package}/bin/mbsync ${concatStringsSep " " mbsyncOptions}";
|
||||
|
||||
# Convert systemd calendar format to launchd interval (approximate)
|
||||
# Format like "*:0/5" means every 5 minutes
|
||||
# We'll parse simple cases, default to 5 minutes
|
||||
parseFrequencyToSeconds =
|
||||
freq:
|
||||
let
|
||||
# Try to extract minute interval from patterns like "*:0/5" or "*:*:0/30"
|
||||
parts = builtins.match ".*\\*/([0-9]+).*" freq;
|
||||
in
|
||||
if parts != null then (lib.toInt (builtins.head parts)) * 60 else 300;
|
||||
|
||||
in
|
||||
{
|
||||
disabledModules = [ "services/mbsync.nix" ];
|
||||
|
||||
meta.maintainers = [ lib.maintainers.pjones ];
|
||||
|
||||
options.services.mbsync = {
|
||||
enable = lib.mkEnableOption "mbsync";
|
||||
|
||||
package = lib.mkPackageOption pkgs "isync" { };
|
||||
|
||||
frequency = mkOption {
|
||||
type = types.str;
|
||||
default = "*:0/5";
|
||||
description = ''
|
||||
How often to run mbsync. On Linux, this value is passed to the systemd
|
||||
timer configuration as the onCalendar option. See
|
||||
{manpage}`systemd.time(7)` for more information about the format.
|
||||
On Darwin, this is converted to an approximate interval in seconds.
|
||||
'';
|
||||
};
|
||||
|
||||
verbose = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = ''
|
||||
Whether mbsync should produce verbose output.
|
||||
'';
|
||||
};
|
||||
|
||||
configFile = mkOption {
|
||||
type = types.nullOr types.path;
|
||||
default = null;
|
||||
description = ''
|
||||
Optional configuration file to link to use instead of
|
||||
the default file ({file}`~/.mbsyncrc`).
|
||||
'';
|
||||
};
|
||||
|
||||
preExec = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
example = "mkdir -p %h/mail";
|
||||
description = ''
|
||||
An optional command to run before mbsync executes. This is
|
||||
useful for creating the directories mbsync is going to use.
|
||||
'';
|
||||
};
|
||||
|
||||
postExec = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
example = "\${pkgs.mu}/bin/mu index";
|
||||
description = ''
|
||||
An optional command to run after mbsync executes successfully.
|
||||
This is useful for running mailbox indexing tools.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable (mkMerge [
|
||||
# Linux-specific: systemd user service and timer
|
||||
(mkIf isLinux {
|
||||
systemd.user.services.mbsync = {
|
||||
Unit = {
|
||||
Description = "mbsync mailbox synchronization";
|
||||
};
|
||||
|
||||
Service = {
|
||||
Type = "oneshot";
|
||||
ExecStart = mbsyncCommand;
|
||||
}
|
||||
// (optionalAttrs (cfg.postExec != null) {
|
||||
ExecStartPost = cfg.postExec;
|
||||
})
|
||||
// (optionalAttrs (cfg.preExec != null) {
|
||||
ExecStartPre = cfg.preExec;
|
||||
});
|
||||
};
|
||||
|
||||
systemd.user.timers.mbsync = {
|
||||
Unit = {
|
||||
Description = "mbsync mailbox synchronization";
|
||||
};
|
||||
|
||||
Timer = {
|
||||
OnCalendar = cfg.frequency;
|
||||
Unit = "mbsync.service";
|
||||
};
|
||||
|
||||
Install = {
|
||||
WantedBy = [ "timers.target" ];
|
||||
};
|
||||
};
|
||||
})
|
||||
|
||||
# Darwin-specific: launchd agent
|
||||
(mkIf isDarwin {
|
||||
launchd.agents.mbsync = {
|
||||
enable = true;
|
||||
config =
|
||||
let
|
||||
# Build a script that handles pre/post exec
|
||||
mbsyncScript = pkgs.writeShellScript "mbsync-wrapper" ''
|
||||
set -e
|
||||
${lib.optionalString (cfg.preExec != null) cfg.preExec}
|
||||
${mbsyncCommand}
|
||||
${lib.optionalString (cfg.postExec != null) cfg.postExec}
|
||||
'';
|
||||
in
|
||||
{
|
||||
ProgramArguments = [ "${mbsyncScript}" ];
|
||||
StartInterval = parseFrequencyToSeconds cfg.frequency;
|
||||
RunAtLoad = true;
|
||||
StandardErrorPath = "/tmp/mbsync.err.log";
|
||||
StandardOutPath = "/tmp/mbsync.out.log";
|
||||
};
|
||||
};
|
||||
})
|
||||
]);
|
||||
}
|
||||
5
modules/nixos/default.nix
Normal file
5
modules/nixos/default.nix
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
imports = [
|
||||
# Add nixos-specific custom modules here
|
||||
];
|
||||
}
|
||||
22
secrets/wb.enc
Normal file
22
secrets/wb.enc
Normal file
File diff suppressed because one or more lines are too long
Loading…
Reference in a new issue