Compare commits
No commits in common. "4f39c80e253a5714808ee8a165a5b64fb7dc7813" and "54be488d7389fa7350b799b0774f7d9a3ac7d428" have entirely different histories.
4f39c80e25
...
54be488d73
45 changed files with 797 additions and 1462 deletions
|
|
@ -1,9 +0,0 @@
|
||||||
root = true
|
|
||||||
|
|
||||||
[*.sh]
|
|
||||||
indent_style = space
|
|
||||||
indent_size = 4
|
|
||||||
|
|
||||||
[bin/*]
|
|
||||||
indent_style = space
|
|
||||||
indent_size = 4
|
|
||||||
|
|
@ -1,17 +1,9 @@
|
||||||
keys:
|
keys:
|
||||||
- &pickwick age13cfe8fhp4m978qlcur46vkkxepsl93ggwe53kmhue9xtpgr5zu5q4y6ln2
|
- &pickwick age13cfe8fhp4m978qlcur46vkkxepsl93ggwe53kmhue9xtpgr5zu5q4y6ln2
|
||||||
- &lemur age1pdk6dmyxqhdaja5d0nf8f9qjd43hmfahmkure5yrf8al9jyfmd8qfdxwl6
|
- &lemur age1pdk6dmyxqhdaja5d0nf8f9qjd43hmfahmkure5yrf8al9jyfmd8qfdxwl6
|
||||||
- &dango age15vscvpe79l287h8f3hssrj2r45xy0l3ns94zfue2fxlq43cqdsxq58vq3c
|
|
||||||
creation_rules:
|
creation_rules:
|
||||||
- path_regex: secrets/wb\.txt$
|
|
||||||
key_groups:
|
|
||||||
- age:
|
|
||||||
- *pickwick
|
|
||||||
- *lemur
|
|
||||||
- *dango
|
|
||||||
- path_regex: home/email/secrets.yaml$
|
- path_regex: home/email/secrets.yaml$
|
||||||
key_groups:
|
key_groups:
|
||||||
- age:
|
- age:
|
||||||
- *pickwick
|
- *pickwick
|
||||||
- *lemur
|
- *lemur
|
||||||
- *dango
|
|
||||||
|
|
|
||||||
5
bin/b
5
bin/b
|
|
@ -10,8 +10,9 @@ title=${2:-}
|
||||||
|
|
||||||
global="$HOME/Personal/bookmarks.txt"
|
global="$HOME/Personal/bookmarks.txt"
|
||||||
|
|
||||||
if [ -n "$url" ]; then
|
if [ -n "$url" ]
|
||||||
echo "$url $title" >>$global
|
then
|
||||||
|
echo "$url $title" >> $global
|
||||||
else
|
else
|
||||||
local="$PWD/bookmarks.txt"
|
local="$PWD/bookmarks.txt"
|
||||||
|
|
||||||
|
|
|
||||||
22
bin/cb
22
bin/cb
|
|
@ -19,17 +19,19 @@ WSL_paste() {
|
||||||
}
|
}
|
||||||
|
|
||||||
CYGWIN_copy() {
|
CYGWIN_copy() {
|
||||||
cat >/dev/clipboard
|
cat > /dev/clipboard
|
||||||
}
|
}
|
||||||
|
|
||||||
CYGWIN_paste() {
|
CYGWIN_paste() {
|
||||||
cat /dev/clipboard
|
cat /dev/clipboard
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
MAC_copy() {
|
MAC_copy() {
|
||||||
cat | pbcopy
|
cat | pbcopy
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
MAC_paste() {
|
MAC_paste() {
|
||||||
pbpaste
|
pbpaste
|
||||||
}
|
}
|
||||||
|
|
@ -83,20 +85,20 @@ detect_os() {
|
||||||
printf WSL
|
printf WSL
|
||||||
else
|
else
|
||||||
case "$(uname -s)" in
|
case "$(uname -s)" in
|
||||||
Linux*) printf LINUX ;;
|
Linux*) printf LINUX;;
|
||||||
Darwin*) printf MAC ;;
|
Darwin*) printf MAC;;
|
||||||
CYGWIN*) printf CYGWIN ;;
|
CYGWIN*) printf CYGWIN;;
|
||||||
esac
|
esac
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
function debug() {
|
function debug() {
|
||||||
stdin_is_a_pipe && echo "stdin_is_a_pipe: 1" >>/tmp/ono || echo "stdin_is_a_pipe: 0" >>/tmp/ono
|
stdin_is_a_pipe && echo "stdin_is_a_pipe: 1" >> /tmp/ono || echo "stdin_is_a_pipe: 0" >> /tmp/ono
|
||||||
stdin_is_a_tty && echo "stdin_is_a_tty: 1" >>/tmp/ono || echo "stdin_is_a_tty: 0" >>/tmp/ono
|
stdin_is_a_tty && echo "stdin_is_a_tty: 1" >> /tmp/ono || echo "stdin_is_a_tty: 0" >> /tmp/ono
|
||||||
stdin_is_pipe_like && echo "stdin_is_pipe_like: 1" >>/tmp/ono || echo "stdin_is_pipe_like: 0" >>/tmp/ono
|
stdin_is_pipe_like && echo "stdin_is_pipe_like: 1" >> /tmp/ono || echo "stdin_is_pipe_like: 0" >> /tmp/ono
|
||||||
stdout_is_pipe_like && echo "stdout_is_pipe_like: 1" >>/tmp/ono || echo "stdout_is_pipe_like: 0" >>/tmp/ono
|
stdout_is_pipe_like && echo "stdout_is_pipe_like: 1" >> /tmp/ono || echo "stdout_is_pipe_like: 0" >> /tmp/ono
|
||||||
stdout_is_a_tty && echo "stdout_is_a_tty: 1" >>/tmp/ono || echo "stdout_is_a_tty: 0" >>/tmp/ono
|
stdout_is_a_tty && echo "stdout_is_a_tty: 1" >> /tmp/ono || echo "stdout_is_a_tty: 0" >> /tmp/ono
|
||||||
echo >>/tmp/ono
|
echo >> /tmp/ono
|
||||||
}
|
}
|
||||||
|
|
||||||
main() {
|
main() {
|
||||||
|
|
|
||||||
|
|
@ -6,5 +6,7 @@ if [ $# == 1 ]; then
|
||||||
sleepsec=$1
|
sleepsec=$1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
sleep $sleepsec
|
sleep $sleepsec
|
||||||
pbcopy </dev/null
|
pbcopy < /dev/null
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,31 +0,0 @@
|
||||||
#!/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
|
|
||||||
|
|
@ -11,42 +11,42 @@ presentation_left_gaps=80
|
||||||
presentation_right_gaps=80
|
presentation_right_gaps=80
|
||||||
|
|
||||||
if [ "$1" == "on" ]; then
|
if [ "$1" == "on" ]; then
|
||||||
# Save original lines with line numbers
|
# Save original lines with line numbers
|
||||||
grep -n 'outer\.top\|outer\.bottom\|outer\.left\|outer\.right' "$CONFIG_FILE" >"$BACKUP_FILE"
|
grep -n 'outer\.top\|outer\.bottom\|outer\.left\|outer\.right' "$CONFIG_FILE" > "$BACKUP_FILE"
|
||||||
|
|
||||||
# Replace with presentation values
|
# Replace with presentation values
|
||||||
sed -i'' -e "s/^\([[:space:]]*outer\.top[[:space:]]*=\).*/\1 ${presentation_top_gaps}/" "$CONFIG_FILE"
|
sed -i'' -e "s/^\([[:space:]]*outer\.top[[:space:]]*=\).*/\1 ${presentation_top_gaps}/" "$CONFIG_FILE"
|
||||||
sed -i'' -e "s/^\([[:space:]]*outer\.bottom[[:space:]]*=\).*/\1 ${presentation_bottom_gaps}/" "$CONFIG_FILE"
|
sed -i'' -e "s/^\([[:space:]]*outer\.bottom[[:space:]]*=\).*/\1 ${presentation_bottom_gaps}/" "$CONFIG_FILE"
|
||||||
sed -i'' -e "s/^\([[:space:]]*outer\.left[[:space:]]*=\).*/\1 ${presentation_left_gaps}/" "$CONFIG_FILE"
|
sed -i'' -e "s/^\([[:space:]]*outer\.left[[:space:]]*=\).*/\1 ${presentation_left_gaps}/" "$CONFIG_FILE"
|
||||||
sed -i'' -e "s/^\([[:space:]]*outer\.right[[:space:]]*=\).*/\1 ${presentation_right_gaps}/" "$CONFIG_FILE"
|
sed -i'' -e "s/^\([[:space:]]*outer\.right[[:space:]]*=\).*/\1 ${presentation_right_gaps}/" "$CONFIG_FILE"
|
||||||
|
|
||||||
# Set dark wallpaper for presentation
|
# Set dark wallpaper for presentation
|
||||||
osascript -e 'tell application "System Events" to set picture of every desktop to "/Users/rayandrew/Pictures/Wallpapers/black-gray.jpg"' >/dev/null 2>&1
|
osascript -e 'tell application "System Events" to set picture of every desktop to "/Users/rayandrew/Pictures/Wallpapers/black-gray.jpg"' > /dev/null 2>&1
|
||||||
|
|
||||||
aerospace reload-config
|
aerospace reload-config
|
||||||
echo -n "Presentation mode ON"
|
echo -n "Presentation mode ON"
|
||||||
|
|
||||||
elif [ "$1" == "off" ]; then
|
elif [ "$1" == "off" ]; then
|
||||||
if [ ! -f "$BACKUP_FILE" ]; then
|
if [ ! -f "$BACKUP_FILE" ]; then
|
||||||
echo "Error: No backup found. Run 'presentation-mode on' first."
|
echo "Error: No backup found. Run 'presentation-mode on' first."
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Restore original values line by line
|
# Restore original values line by line
|
||||||
while IFS=: read -r line_num content; do
|
while IFS=: read -r line_num content; do
|
||||||
# Escape special characters for sed
|
# Escape special characters for sed
|
||||||
escaped_content=$(printf '%s\n' "$content" | sed 's/[&/\]/\\&/g')
|
escaped_content=$(printf '%s\n' "$content" | sed 's/[&/\]/\\&/g')
|
||||||
sed -i'' -e "${line_num}s/.*/${escaped_content}/" "$CONFIG_FILE"
|
sed -i'' -e "${line_num}s/.*/${escaped_content}/" "$CONFIG_FILE"
|
||||||
done <"$BACKUP_FILE"
|
done < "$BACKUP_FILE"
|
||||||
|
|
||||||
# Restore original wallpaper
|
# Restore original wallpaper
|
||||||
osascript -e 'tell application "System Events" to set picture of every desktop to "/Users/rayandrew/Pictures/Wallpapers/bluering.png"' >/dev/null 2>&1
|
osascript -e 'tell application "System Events" to set picture of every desktop to "/Users/rayandrew/Pictures/Wallpapers/bluering.png"' > /dev/null 2>&1
|
||||||
|
|
||||||
rm "$BACKUP_FILE"
|
rm "$BACKUP_FILE"
|
||||||
aerospace reload-config
|
aerospace reload-config
|
||||||
echo "Presentation mode OFF"
|
echo "Presentation mode OFF"
|
||||||
|
|
||||||
else
|
else
|
||||||
echo "Usage: presentation-mode [on|off]"
|
echo "Usage: presentation-mode [on|off]"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
|
||||||
336
bin/wb
336
bin/wb
|
|
@ -1,336 +0,0 @@
|
||||||
#!/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
|
|
||||||
## --------------------------------------------------------------------
|
|
||||||
|
|
@ -16,23 +16,23 @@ echo "Desired spaces: $DESIRED_SPACES"
|
||||||
yabai -m display --focus "$MAIN_DISPLAY"
|
yabai -m display --focus "$MAIN_DISPLAY"
|
||||||
|
|
||||||
if [ "$CURRENT_SPACE_COUNT" -lt "$DESIRED_SPACES" ]; then
|
if [ "$CURRENT_SPACE_COUNT" -lt "$DESIRED_SPACES" ]; then
|
||||||
MISSING_SPACES=$((DESIRED_SPACES - CURRENT_SPACE_COUNT))
|
MISSING_SPACES=$((DESIRED_SPACES - CURRENT_SPACE_COUNT))
|
||||||
echo "Creating $MISSING_SPACES spaces on display $MAIN_DISPLAY..."
|
echo "Creating $MISSING_SPACES spaces on display $MAIN_DISPLAY..."
|
||||||
|
|
||||||
for i in $(seq 1 $MISSING_SPACES); do
|
for i in $(seq 1 $MISSING_SPACES); do
|
||||||
yabai -m space --create
|
yabai -m space --create
|
||||||
echo "Created space $((CURRENT_SPACE_COUNT + i))"
|
echo "Created space $((CURRENT_SPACE_COUNT + i))"
|
||||||
done
|
done
|
||||||
elif [ "$CURRENT_SPACE_COUNT" -gt "$DESIRED_SPACES" ]; then
|
elif [ "$CURRENT_SPACE_COUNT" -gt "$DESIRED_SPACES" ]; then
|
||||||
EXTRA_SPACES=$((CURRENT_SPACE_COUNT - DESIRED_SPACES))
|
EXTRA_SPACES=$((CURRENT_SPACE_COUNT - DESIRED_SPACES))
|
||||||
echo "Removing $EXTRA_SPACES extra spaces from display $MAIN_DISPLAY..."
|
echo "Removing $EXTRA_SPACES extra spaces from display $MAIN_DISPLAY..."
|
||||||
|
|
||||||
# Get the last space on main display and destroy it
|
# Get the last space on main display and destroy it
|
||||||
for i in $(seq 1 $EXTRA_SPACES); do
|
for i in $(seq 1 $EXTRA_SPACES); do
|
||||||
LAST_SPACE=$(yabai -m query --spaces --display "$MAIN_DISPLAY" | jq 'map(select(."is-native-fullscreen" == false))[-1].index')
|
LAST_SPACE=$(yabai -m query --spaces --display "$MAIN_DISPLAY" | jq 'map(select(."is-native-fullscreen" == false))[-1].index')
|
||||||
yabai -m space --destroy "$LAST_SPACE"
|
yabai -m space --destroy "$LAST_SPACE"
|
||||||
echo "Destroyed space $LAST_SPACE"
|
echo "Destroyed space $LAST_SPACE"
|
||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "Total spaces on display $MAIN_DISPLAY: $(yabai -m query --spaces --display $MAIN_DISPLAY | jq 'length')"
|
echo "Total spaces on display $MAIN_DISPLAY: $(yabai -m query --spaces --display $MAIN_DISPLAY | jq 'length')"
|
||||||
|
|
|
||||||
|
|
@ -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'
|
'/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 = [
|
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 /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'
|
'exec-and-forget /run/current-system/sw/bin/sketchybar --trigger update_windows'
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -1,33 +0,0 @@
|
||||||
# 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
|
|
||||||
|
|
@ -1,2 +0,0 @@
|
||||||
[global]
|
|
||||||
log_format = "\u001B[2mdirenv: %s\u001B[0m"
|
|
||||||
|
|
@ -1,11 +1,5 @@
|
||||||
set fish_greeting
|
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
|
function sesh-sessions
|
||||||
set -l session (sesh list -t -c | fzf --height 40% --reverse --border-label ' sesh ' --border --prompt '⚡ ')
|
set -l session (sesh list -t -c | fzf --height 40% --reverse --border-label ' sesh ' --border --prompt '⚡ ')
|
||||||
commandline -f repaint
|
commandline -f repaint
|
||||||
|
|
|
||||||
|
|
@ -1,2 +0,0 @@
|
||||||
jorgebucaran/fisher
|
|
||||||
IlanCosman/tide@v6
|
|
||||||
|
|
@ -6,8 +6,6 @@ quit-after-last-window-closed = true
|
||||||
gtk-adwaita = false
|
gtk-adwaita = false
|
||||||
# font-family = ${system-font}
|
# font-family = ${system-font}
|
||||||
font-family = Consolas
|
font-family = Consolas
|
||||||
font-family = Symbols Nerd Font Mono
|
|
||||||
font-family = DejaVuSansM Nerd Font Mono
|
|
||||||
font-size = 14
|
font-size = 14
|
||||||
app-notifications = no-clipboard-copy
|
app-notifications = no-clipboard-copy
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,47 +0,0 @@
|
||||||
# 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
|
|
||||||
|
|
@ -1,55 +0,0 @@
|
||||||
# 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 *
|
|
||||||
|
|
@ -1,30 +0,0 @@
|
||||||
# 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
|
|
||||||
|
|
@ -1,38 +0,0 @@
|
||||||
# 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"
|
|
||||||
|
|
@ -1,39 +0,0 @@
|
||||||
# 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"
|
|
||||||
|
|
@ -1,93 +0,0 @@
|
||||||
# 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'
|
|
||||||
|
|
@ -1,65 +0,0 @@
|
||||||
# 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)"
|
|
||||||
|
|
@ -1,66 +0,0 @@
|
||||||
# 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 +0,0 @@
|
||||||
-- Ray Andrew
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
-- Ray Andrew
|
|
||||||
|
|
@ -150,7 +150,6 @@
|
||||||
age
|
age
|
||||||
ssh-to-age
|
ssh-to-age
|
||||||
nixfmt-rfc-style
|
nixfmt-rfc-style
|
||||||
shfmt
|
|
||||||
];
|
];
|
||||||
DIRENV_LOG_FORMAT = "";
|
DIRENV_LOG_FORMAT = "";
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -2,75 +2,219 @@
|
||||||
pkgs,
|
pkgs,
|
||||||
lib,
|
lib,
|
||||||
config,
|
config,
|
||||||
dots,
|
user,
|
||||||
|
home-dir,
|
||||||
...
|
...
|
||||||
}:
|
}:
|
||||||
|
|
||||||
{
|
{
|
||||||
|
imports = [
|
||||||
|
./neomutt
|
||||||
|
./mailcap.nix
|
||||||
|
];
|
||||||
|
|
||||||
options.custom.email = with lib; {
|
options.custom.email = with lib; {
|
||||||
enable = mkEnableOption "Enable email";
|
enable = mkEnableOption "Enable email";
|
||||||
davmail = mkEnableOption "Enable DavMail";
|
davmail = mkEnableOption "Enable DavMail";
|
||||||
mbsync = mkEnableOption "Enable Mbsync";
|
mbsync = mkEnableOption "Enable Mbsync";
|
||||||
neomutt = mkEnableOption "Enable NeoMutt";
|
|
||||||
mailcap = mkEnableOption "Enable mailcap";
|
|
||||||
};
|
};
|
||||||
|
|
||||||
config = lib.mkIf config.custom.email.enable {
|
config = lib.mkIf config.custom.email.enable {
|
||||||
# DavMail service (Exchange gateway)
|
|
||||||
services.davmail = {
|
services.davmail = {
|
||||||
enable = config.custom.email.davmail;
|
enable = config.custom.email.davmail;
|
||||||
configFile = "${dots}/config/davmail/davmail.properties";
|
settings = {
|
||||||
|
"davmail.mode" = "O365Manual";
|
||||||
|
"davmail.url" = "https://outlook.office365.com/EWS/Exchange.asmx";
|
||||||
|
# davmail.mode = "O365Modern";
|
||||||
|
"davmail.keepDelay" = 30;
|
||||||
|
# log4j.logger.davmail = "DEBUG";
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
# Mbsync service (mail sync)
|
programs = {
|
||||||
services.mbsync = {
|
neomutt = {
|
||||||
enable = config.custom.email.mbsync;
|
macros = [
|
||||||
configFile = "${dots}/config/mbsync/mbsyncrc";
|
{
|
||||||
frequency = "*:0/1";
|
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;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
# Install mail-related packages
|
services = {
|
||||||
home.packages =
|
mbsync = {
|
||||||
with pkgs;
|
enable = config.custom.email.mbsync;
|
||||||
[
|
frequency = "*:0/1";
|
||||||
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";
|
|
||||||
};
|
};
|
||||||
|
|
||||||
# mailcap symlink
|
accounts.email =
|
||||||
home.file = lib.mkIf config.custom.email.mailcap {
|
let
|
||||||
".mailcap".source = config.lib.file.mkOutOfStoreSymlink "${dots}/config/home/.mailcap";
|
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
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
})
|
||||||
|
]);
|
||||||
|
};
|
||||||
|
|
||||||
# Create mail directories
|
sops = {
|
||||||
home.activation.createMailDirs = lib.hm.dag.entryAfter [ "writeBoundary" ] ''
|
age.keyFile = "${home-dir}/.config/sops/age/keys.txt";
|
||||||
mkdir -p ~/mail/personal/Inbox
|
age.generateKey = true;
|
||||||
mkdir -p ~/mail/uchicago/Inbox
|
defaultSopsFile = ./secrets.yaml;
|
||||||
mkdir -p ~/.cache/neomutt/headers
|
secrets = {
|
||||||
mkdir -p ~/.cache/neomutt/messages
|
"personal" = { };
|
||||||
mkdir -p ~/.local/state
|
"uchicago" = { };
|
||||||
'';
|
};
|
||||||
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
48
home/email/mailcap.nix
Normal file
48
home/email/mailcap.nix
Normal file
|
|
@ -0,0 +1,48 @@
|
||||||
|
{
|
||||||
|
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
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
72
home/email/neomutt/colors.nix
Normal file
72
home/email/neomutt/colors.nix
Normal file
|
|
@ -0,0 +1,72 @@
|
||||||
|
{ 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
|
||||||
|
''
|
||||||
78
home/email/neomutt/default.nix
Normal file
78
home/email/neomutt/default.nix
Normal file
|
|
@ -0,0 +1,78 @@
|
||||||
|
{
|
||||||
|
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}
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
316
home/email/neomutt/keybind.nix
Normal file
316
home/email/neomutt/keybind.nix
Normal file
|
|
@ -0,0 +1,316 @@
|
||||||
|
{ 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,35 +1,31 @@
|
||||||
personal: ENC[AES256_GCM,data:MG1ryntM2YKyjb0YH/8GYg==,iv:SvwAc1dBl8wc1YWdnOuCNAb5RUNA2vLX87uzOGOaqec=,tag:ixVU3FWGpZqZx/1PD3/3KA==,type:str]
|
personal: ENC[AES256_GCM,data:aaZAYmnoQfGIH6bBneKtTA==,iv:xiy1eCyBhFulfRXGz0WDFLaqPj3kXsMD4Xkk7D4s5XA=,tag:Nk0KsgICo505VEMwVUt3TA==,type:str]
|
||||||
uchicago: ENC[AES256_GCM,data:LqZTprY/9Li8ab9i0dg=,iv:tLJHXwsoL7PnwonHlnXiaLahr0+fIizsoshE0GFbkn8=,tag:FT5brU6pW7xFxnzpBYU2jA==,type:str]
|
uchicago: ENC[AES256_GCM,data:3ZkuIfvzOkKfQD0iyTk=,iv:aCfFrxDM5Ly/qLdLAQkK2tOxb89dFkCc9RhN5GVSGRw=,tag:7D54pkVX2F6IhM38JOUFQg==,type:str]
|
||||||
sops:
|
sops:
|
||||||
|
kms: []
|
||||||
|
gcp_kms: []
|
||||||
|
azure_kv: []
|
||||||
|
hc_vault: []
|
||||||
age:
|
age:
|
||||||
- recipient: age13cfe8fhp4m978qlcur46vkkxepsl93ggwe53kmhue9xtpgr5zu5q4y6ln2
|
- recipient: age13cfe8fhp4m978qlcur46vkkxepsl93ggwe53kmhue9xtpgr5zu5q4y6ln2
|
||||||
enc: |
|
enc: |
|
||||||
-----BEGIN AGE ENCRYPTED FILE-----
|
-----BEGIN AGE ENCRYPTED FILE-----
|
||||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBxUjF4Nm0yVWFwMUM1Y2hn
|
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBMMTcwTEc5VTdEMlZSK1FI
|
||||||
SVRhUmEweDNVd3Z2NVpEVW1yaDRYaDhLZ0NZCjE3WkVTWXUrKzE1VGN5ZUtSb2VZ
|
c2VVdjJOc3B3V2RGS0pIVGQralJ4MGFwSkRvCm5mVTNxMHUzNythNHVyRG52bVYz
|
||||||
WnJFRkkwZmJKTm5OWlpMLzlCZHR6aE0KLS0tIFZ3UEFmcTJIYlcrUXhyU1hSMFRK
|
RVp2d1hKUnpucko1SG01SDdWNFZGV1EKLS0tIDB2OGF1UlUyN2xnRm1WR1RleUhN
|
||||||
MjhvU0NQamQzcE1sWG5FSmpoajdNc0UKslJWrvq4BIeMoZ6ZSA6anlldGOpUuXrL
|
S1hFWjhCMlNZVC83ZzR4NittcXlCQlUKQO6NHCMwWKwrfwwnwLK/sO4HO6ES+PyT
|
||||||
PV7pVpTihxWtzPbPV36oPRVoN3GzNZXUPJryExtUzdnufbhfu9LBTw==
|
dh3tRhPlv7/viO+MtHqUfQ5cbW+OWoic4prfK/UxIz5VeY331kpq+g==
|
||||||
-----END AGE ENCRYPTED FILE-----
|
-----END AGE ENCRYPTED FILE-----
|
||||||
- recipient: age1pdk6dmyxqhdaja5d0nf8f9qjd43hmfahmkure5yrf8al9jyfmd8qfdxwl6
|
- recipient: age1pdk6dmyxqhdaja5d0nf8f9qjd43hmfahmkure5yrf8al9jyfmd8qfdxwl6
|
||||||
enc: |
|
enc: |
|
||||||
-----BEGIN AGE ENCRYPTED FILE-----
|
-----BEGIN AGE ENCRYPTED FILE-----
|
||||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBOZ01sMXhvMG5BMmxwa3h1
|
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB0ajhrbkdqcmpRd2svYmNx
|
||||||
aXArSkxUNUkwOHAzQnlkYk4vVmEzckZkaFVzCnpYRmpqMW9QM29VTWFnc0NYTURj
|
dHIzRDJTTTVGV3VON0NBZnpaQTdGM2w4aXpNClNqb2Y4Qzg4OWx2a3FNdG5MY1ZQ
|
||||||
REp0OVNPN1lRRUdPWlQrTmhYcEZwbm8KLS0tIFI2dFBzbmQ4Q01PU1BLUXI5eXIy
|
R2dOSC9CdzBPM1I5b1lCVnptMGM3eUEKLS0tIGZRM1pSV3J0NlJvQUZBcTVNZGxy
|
||||||
Y0ZMMmJTOVRrbXpOVkYxektxOFFkZUEKcjX/wDMvuZ+PzfydOGOf938mCVcFFD/h
|
SS9qQlJiRU1EelZySWpNdWRiTms3ZncKkwp1WT9LWxnJb+yjilikTHRm1fbs89TU
|
||||||
nGdbXAoE+cD7/rmpaF0Bpm2WqWrkiAvE/csyaWV/HNzQ6JkXp/4jtQ==
|
1Xzy+GNiZbtm2I6e5XaaD+9d3PFvqqu0OdqrMrTMmiNAys0WhwB8Iw==
|
||||||
-----END AGE ENCRYPTED FILE-----
|
-----END AGE ENCRYPTED FILE-----
|
||||||
- recipient: age15vscvpe79l287h8f3hssrj2r45xy0l3ns94zfue2fxlq43cqdsxq58vq3c
|
lastmodified: "2025-03-04T21:54:28Z"
|
||||||
enc: |
|
mac: ENC[AES256_GCM,data:r+2SOcW7xLHee9kL8369yB6l/Z2XdnzGkeFygSrDgcZVfBfp/fT1xeMvu5tuu8aqsUeJ7lkFD2VKiBue95XSojdlM+5YyTerqdzLyMCRbkRivC3O2xXe90B4hVqm+twE9uu74mIznAQ2e0EO9E0MMlMNBo3EwsEcYA8gyVuB5mc=,iv:plNu3BircQ+kpPaXqlNvYlLAL5V5RX/yiETs+nY1pfw=,tag:7gVuOpzx5YsHtwodIRr4TQ==,type:str]
|
||||||
-----BEGIN AGE ENCRYPTED FILE-----
|
pgp: []
|
||||||
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
|
unencrypted_suffix: _unencrypted
|
||||||
version: 3.11.0
|
version: 3.9.4
|
||||||
|
|
|
||||||
|
|
@ -51,7 +51,6 @@
|
||||||
nerd-fonts.droid-sans-mono
|
nerd-fonts.droid-sans-mono
|
||||||
nerd-fonts.space-mono
|
nerd-fonts.space-mono
|
||||||
nerd-fonts.dejavu-sans-mono
|
nerd-fonts.dejavu-sans-mono
|
||||||
nerd-fonts.symbols-only
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -60,7 +60,6 @@
|
||||||
pandoc
|
pandoc
|
||||||
duckdb
|
duckdb
|
||||||
hyperfine
|
hyperfine
|
||||||
fastfetch
|
|
||||||
(pkgs.python311.withPackages (ppkgs: [
|
(pkgs.python311.withPackages (ppkgs: [
|
||||||
ppkgs.numpy
|
ppkgs.numpy
|
||||||
]))
|
]))
|
||||||
|
|
@ -70,18 +69,10 @@
|
||||||
})
|
})
|
||||||
imagemagick
|
imagemagick
|
||||||
spotify-player
|
spotify-player
|
||||||
eza
|
|
||||||
]
|
]
|
||||||
++ lib.optionals pkgs.stdenv.isDarwin [ coreutils ]
|
++ lib.optionals pkgs.stdenv.isDarwin [ coreutils ]
|
||||||
++ (lib.attrValues config.custom.shell.packages);
|
++ (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 = {
|
programs.bash = {
|
||||||
enable = true;
|
enable = true;
|
||||||
enableVteIntegration = true;
|
enableVteIntegration = true;
|
||||||
|
|
@ -112,8 +103,6 @@
|
||||||
enableFishIntegration = config.programs.fish.enable;
|
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."sesh".source = config.lib.file.mkOutOfStoreSymlink "${dots}/config/sesh";
|
||||||
xdg.configFile."yazi".source = config.lib.file.mkOutOfStoreSymlink "${dots}/config/yazi";
|
xdg.configFile."yazi".source = config.lib.file.mkOutOfStoreSymlink "${dots}/config/yazi";
|
||||||
xdg.configFile."spotify-player".source =
|
xdg.configFile."spotify-player".source =
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
{
|
{
|
||||||
pkgs,
|
pkgs,
|
||||||
home-dir,
|
|
||||||
...
|
...
|
||||||
}:
|
}:
|
||||||
{
|
{
|
||||||
|
|
@ -81,13 +80,6 @@
|
||||||
];
|
];
|
||||||
|
|
||||||
hm.custom = {
|
hm.custom = {
|
||||||
environment = {
|
|
||||||
enable = true;
|
|
||||||
variables = {
|
|
||||||
EDITOR = "nvim";
|
|
||||||
SOPS_AGE_KEY_FILE = "${home-dir}/.config/sops/age/keys.txt";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
emacs.enable = true;
|
emacs.enable = true;
|
||||||
neovim.enable = true;
|
neovim.enable = true;
|
||||||
latex.enable = true;
|
latex.enable = true;
|
||||||
|
|
@ -99,12 +91,5 @@
|
||||||
hammerspoon.enable = true;
|
hammerspoon.enable = true;
|
||||||
kitty.enable = true;
|
kitty.enable = true;
|
||||||
};
|
};
|
||||||
email = {
|
|
||||||
enable = true;
|
|
||||||
davmail = true;
|
|
||||||
neomutt = true;
|
|
||||||
mbsync = true;
|
|
||||||
mailcap = true;
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,6 @@ let
|
||||||
./shared.nix
|
./shared.nix
|
||||||
./${host}
|
./${host}
|
||||||
./${host}/hardware.nix
|
./${host}/hardware.nix
|
||||||
../modules/nixos
|
|
||||||
../nixos
|
../nixos
|
||||||
(
|
(
|
||||||
{ config, ... }:
|
{ config, ... }:
|
||||||
|
|
@ -60,7 +59,6 @@ let
|
||||||
imports = [
|
imports = [
|
||||||
inputs.nix-index-database.homeModules.nix-index
|
inputs.nix-index-database.homeModules.nix-index
|
||||||
inputs.sops-nix.homeManagerModules.sops
|
inputs.sops-nix.homeManagerModules.sops
|
||||||
../modules/home-manager
|
|
||||||
../home
|
../home
|
||||||
]
|
]
|
||||||
++ lib.optional (builtins.pathExists ./${host}/home.nix) ./${host}/home.nix;
|
++ lib.optional (builtins.pathExists ./${host}/home.nix) ./${host}/home.nix;
|
||||||
|
|
@ -116,7 +114,6 @@ let
|
||||||
modules = [
|
modules = [
|
||||||
./shared.nix
|
./shared.nix
|
||||||
./${host}
|
./${host}
|
||||||
../modules/darwin
|
|
||||||
../darwin
|
../darwin
|
||||||
(
|
(
|
||||||
{ config, ... }:
|
{ config, ... }:
|
||||||
|
|
@ -137,7 +134,6 @@ let
|
||||||
inputs.nix-index-database.homeModules.nix-index
|
inputs.nix-index-database.homeModules.nix-index
|
||||||
inputs.sops-nix.homeManagerModules.sops
|
inputs.sops-nix.homeManagerModules.sops
|
||||||
inputs.mac-app-util.homeManagerModules.default
|
inputs.mac-app-util.homeManagerModules.default
|
||||||
../modules/home-manager
|
|
||||||
../home
|
../home
|
||||||
]
|
]
|
||||||
++ lib.optional (builtins.pathExists ./${host}/home.nix) ./${host}/home.nix;
|
++ lib.optional (builtins.pathExists ./${host}/home.nix) ./${host}/home.nix;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,13 @@
|
||||||
{
|
{
|
||||||
|
inputs,
|
||||||
|
lib,
|
||||||
|
config,
|
||||||
|
pkgs,
|
||||||
|
system,
|
||||||
|
dots,
|
||||||
user,
|
user,
|
||||||
|
hm,
|
||||||
|
host,
|
||||||
...
|
...
|
||||||
}:
|
}:
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
||||||
{
|
|
||||||
imports = [
|
|
||||||
# Add darwin-specific custom modules here
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
@ -1,6 +0,0 @@
|
||||||
{
|
|
||||||
imports = [
|
|
||||||
./overrides
|
|
||||||
./environment.nix
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
@ -1,50 +0,0 @@
|
||||||
# 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);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,181 +0,0 @@
|
||||||
{
|
|
||||||
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";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
})
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
@ -1,6 +0,0 @@
|
||||||
{
|
|
||||||
imports = [
|
|
||||||
./davmail.nix
|
|
||||||
./mbsync.nix
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
@ -1,161 +0,0 @@
|
||||||
{
|
|
||||||
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";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
})
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
||||||
{
|
|
||||||
imports = [
|
|
||||||
# Add nixos-specific custom modules here
|
|
||||||
];
|
|
||||||
}
|
|
||||||
File diff suppressed because one or more lines are too long
Loading…
Reference in a new issue