Commit Diff


commit - b2d211e257e62cc26771f6c7c0a03f769cbf9e67
commit + 9b3607f385b48c6ca46fbf109a7d1494d9d62e91
blob - 22c869e34745765b2ac68bdac81f13bf7f7a1131
blob + 7b7b904f44a1e10913447b03385d8bebaa8469d9
--- flake.lock
+++ flake.lock
@@ -222,11 +222,11 @@
         ]
       },
       "locked": {
-        "lastModified": 1785046085,
-        "narHash": "sha256-UiK+mmZJuLWQVhJ5b2wDzogIYWAesyRm6LA3h3Ulh3Y=",
+        "lastModified": 1785650611,
+        "narHash": "sha256-q4kR7g+pCcz6NASvoVPYu+CWWUurX03wogtBqGmR4h0=",
         "owner": "nix-community",
         "repo": "nix-index-database",
-        "rev": "11665045df8b9938ef811a3bfdc65cffb02b4b70",
+        "rev": "dbc756c9d7287de19b3e0e38c928c47510d42c3e",
         "type": "github"
       },
       "original": {
@@ -250,11 +250,11 @@
     },
     "nixpkgs_2": {
       "locked": {
-        "lastModified": 1785542685,
-        "narHash": "sha256-sjfvXMbG5pCFgpvw2OZAFcZiTvrppCWvnB6cuGrSY08=",
+        "lastModified": 1785602060,
+        "narHash": "sha256-z7D96eESRM4CPV/XtwpwFn8IDdfLAmxz6lVWrGYXvR4=",
         "owner": "NixOS",
         "repo": "nixpkgs",
-        "rev": "f8e81fc7eb063db454f563cdd596fb96a5ad1497",
+        "rev": "a5cbcfe954791221bfffe2307f7d1a1bf61a871e",
         "type": "github"
       },
       "original": {
blob - 9d0922aaac136a9cb988b9a43f5943812b27d150
blob + 42305fe90d50f021c9cf3b13443db25b478c1d1e
--- hosts/void/default.nix
+++ hosts/void/default.nix
@@ -173,6 +173,7 @@
       go-org
       ugrep
       teip
+      remind
     ];
 
     lsp = [
blob - 7efd1b43011b2098ff2203f10f440961dea36b4d
blob + 7351ec6c1dff5df04c90a3028d14ff9881a1ad9a
Binary files hosts/work/overlays/config/shell/rc/todo and hosts/work/overlays/config/shell/rc/todo differ
blob - /dev/null
blob + 6bb1a2ee3e68b3ab77934b0f2fafe0525b43603e (mode 644)
--- /dev/null
+++ modules/mixins/dotfiles/bin/adhoc
@@ -0,0 +1,70 @@
+#!/bin/bash
+
+# Simple reminder tool that stores reminders in a file and triggers notify-send alerts
+# Usage: adhoc <time> "<message>"
+# Examples:
+#   adhoc 30m "Take a break"
+#   adhoc 18:50 "Time to leave"
+
+# Configuration
+REMINDER_FILE="$HOME/.adhoc"
+LOG_FILE="$HOME/.adhoc_history"
+
+# Check if parameters are provided
+if [ $# -lt 2 ]; then
+	echo "Usage: adhoc <time> \"<message>\""
+	echo "Time formats: 30s, 5m, 2h, 1d, or HH:MM"
+	exit 1
+fi
+
+# Parse time and message
+TIME="$1"
+MESSAGE="$2"
+
+# Check if the time is in HH:MM format
+if [[ "$TIME" =~ ^([0-1][0-9]|2[0-3]):([0-5][0-9])$ ]]; then
+	# Calculate seconds until the specified time
+	CURRENT_TIME=$(date +%s)
+	TARGET_TIME=$(date -d "$(date +%Y-%m-%d) $TIME" +%s)
+
+	# If the target time is already passed for today, schedule for tomorrow
+	if [ "$TARGET_TIME" -le "$CURRENT_TIME" ]; then
+		TARGET_TIME=$(date -d "$(date -d 'tomorrow' +%Y-%m-%d) $TIME" +%s)
+	fi
+
+	SECONDS=$((TARGET_TIME - CURRENT_TIME))
+	TRIGGER_TIME=$(date -d "@$TARGET_TIME" "+%Y-%m-%d %H:%M:%S")
+	SLEEP_ARG="${SECONDS}s"
+else
+	# Handle relative time formats (30s, 5m, 2h, 1d)
+	case "$TIME" in
+	*s) SECONDS="${TIME%s}" ;;
+	*m) SECONDS=$((${TIME%m} * 60)) ;;
+	*h) SECONDS=$((${TIME%h} * 3600)) ;;
+	*d) SECONDS=$((${TIME%d} * 86400)) ;;
+	*) SECONDS="$TIME" ;;
+	esac
+
+	TRIGGER_TIME=$(date -d "+$SECONDS seconds" "+%Y-%m-%d %H:%M:%S")
+	SLEEP_ARG="$TIME"
+fi
+
+# Create the reminder files if they don't exist
+touch "$REMINDER_FILE"
+touch "$LOG_FILE"
+
+# Log the reminder
+echo "[$TRIGGER_TIME] $MESSAGE" >>"$LOG_FILE"
+
+# Schedule the notification
+(
+	sleep "$SLEEP_ARG"
+	notify-send -u critical "Reminder" "$MESSAGE"
+	echo "Completed: [$TRIGGER_TIME] $MESSAGE" >>"$LOG_FILE"
+	# Remove from active reminders file once completed
+	sed -i "\|^\[$TRIGGER_TIME\] $MESSAGE$|d" "$REMINDER_FILE"
+) &
+
+# Show confirmation
+echo "Reminder set for $TRIGGER_TIME: $MESSAGE"
+echo "[$TRIGGER_TIME] $MESSAGE" >>"$REMINDER_FILE"
blob - 3abdb0da00dc3e83d27aa335baa8ddeb5e20351a (mode 755)
blob + 3abdb0da00dc3e83d27aa335baa8ddeb5e20351a (mode 644)
blob - 41d647eeb13ecc9d3ad59e042a8f619a1707e649 (mode 644)
blob + /dev/null
--- modules/mixins/dotfiles/bin/remind
+++ /dev/null
@@ -1,70 +0,0 @@
-#!/bin/bash
-
-# Simple reminder tool that stores reminders in a file and triggers notify-send alerts
-# Usage: remind <time> "<message>"
-# Examples:
-#   remind 30m "Take a break"
-#   remind 18:50 "Time to leave"
-
-# Configuration
-REMINDER_FILE="$HOME/.reminders"
-LOG_FILE="$HOME/.remind_history"
-
-# Check if parameters are provided
-if [ $# -lt 2 ]; then
-	echo "Usage: remind <time> \"<message>\""
-	echo "Time formats: 30s, 5m, 2h, 1d, or HH:MM"
-	exit 1
-fi
-
-# Parse time and message
-TIME="$1"
-MESSAGE="$2"
-
-# Check if the time is in HH:MM format
-if [[ "$TIME" =~ ^([0-1][0-9]|2[0-3]):([0-5][0-9])$ ]]; then
-	# Calculate seconds until the specified time
-	CURRENT_TIME=$(date +%s)
-	TARGET_TIME=$(date -d "$(date +%Y-%m-%d) $TIME" +%s)
-
-	# If the target time is already passed for today, schedule for tomorrow
-	if [ "$TARGET_TIME" -le "$CURRENT_TIME" ]; then
-		TARGET_TIME=$(date -d "$(date -d 'tomorrow' +%Y-%m-%d) $TIME" +%s)
-	fi
-
-	SECONDS=$((TARGET_TIME - CURRENT_TIME))
-	TRIGGER_TIME=$(date -d "@$TARGET_TIME" "+%Y-%m-%d %H:%M:%S")
-	SLEEP_ARG="${SECONDS}s"
-else
-	# Handle relative time formats (30s, 5m, 2h, 1d)
-	case "$TIME" in
-	*s) SECONDS="${TIME%s}" ;;
-	*m) SECONDS=$((${TIME%m} * 60)) ;;
-	*h) SECONDS=$((${TIME%h} * 3600)) ;;
-	*d) SECONDS=$((${TIME%d} * 86400)) ;;
-	*) SECONDS="$TIME" ;;
-	esac
-
-	TRIGGER_TIME=$(date -d "+$SECONDS seconds" "+%Y-%m-%d %H:%M:%S")
-	SLEEP_ARG="$TIME"
-fi
-
-# Create the reminder files if they don't exist
-touch "$REMINDER_FILE"
-touch "$LOG_FILE"
-
-# Log the reminder
-echo "[$TRIGGER_TIME] $MESSAGE" >>"$LOG_FILE"
-
-# Schedule the notification
-(
-	sleep "$SLEEP_ARG"
-	notify-send -u critical "Reminder" "$MESSAGE"
-	echo "Completed: [$TRIGGER_TIME] $MESSAGE" >>"$LOG_FILE"
-	# Remove from active reminders file once completed
-	sed -i "\|^\[$TRIGGER_TIME\] $MESSAGE$|d" "$REMINDER_FILE"
-) &
-
-# Show confirmation
-echo "Reminder set for $TRIGGER_TIME: $MESSAGE"
-echo "[$TRIGGER_TIME] $MESSAGE" >>"$REMINDER_FILE"
blob - /dev/null
blob + c876c2724b81176988c8696578b2a4bb7bff9af4 (mode 644)
--- /dev/null
+++ modules/mixins/dotfiles/bin/rem
@@ -0,0 +1,2 @@
+#!/bin/sh
+exec remind "$@" "$HOME/notes/.reminders"
blob - becf9654abe51bdf504df35118bcb9542922fd7d
blob + b9637c538618c5589595bf0ead7bce1464f92c89
--- modules/mixins/dotfiles/bin/todo-notify
+++ modules/mixins/dotfiles/bin/todo-notify
@@ -1,14 +1,16 @@
 #!/bin/bash
 
-TODO_FILE="$HOME/notes/todo.txt"
-current_date=""
+TODO_FILE="$HOME/notes/todo.org"
+in_todos=false
 
 while IFS= read -r line || [[ -n "$line" ]]; do
-	if [[ "$line" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2} ]]; then
-		current_date="$line"
-	elif [[ "$line" =~ ^todo:\ (.*)$ ]]; then
+	if [[ "$line" == '* todo.txt' ]]; then
+		in_todos=true
+	elif $in_todos && [[ "$line" =~ ^\*\  ]]; then
+		break
+	elif $in_todos && [[ "$line" =~ ^\*\*\ TODO\ (.*)$ ]]; then
 		todo_message="${BASH_REMATCH[1]}"
-		notify-send "$current_date" "$todo_message"
+		notify-send "todo.txt" "$todo_message"
 		wait
 	fi
 done <"$TODO_FILE"
blob - c1a40b791aae5a46775184fe7997bfc28ac2c2a2
blob + 5eef5aca610bebe3e58f146e3e1128082f16d8cf
--- modules/mixins/dotfiles/bin/todomenu
+++ modules/mixins/dotfiles/bin/todomenu
@@ -1,29 +1,46 @@
 #!/bin/bash
 
-TODO_FILE="$HOME/notes/todo.txt"
+TODO_FILE="$HOME/notes/todo.org"
+TODO_CATEGORY='* todo.txt'
 
 [ ! -f "$TODO_FILE" ] && exit 1
 
-selected=$(awk '{
-    if (/^[0-9]{4}-[0-9]{2}-[0-9]{2}/) {
-        date = substr($0, 1, 10)
-        getline
-        if (/^todo:/) {
-            match($0, /^todo: (.*)/, arr)
-            printf "%s\n", arr[1]
-        }
+selected=$(awk '
+    $0 == "* todo.txt" { in_todos = 1; next }
+    in_todos && /^\* / { exit }
+    in_todos && /^\*\* TODO / {
+        sub(/^\*\* TODO /, "")
+        print
     }
-}' "$TODO_FILE" | dmenu "$@")
+' "$TODO_FILE" | dmenu "$@")
 
 [ -z "$selected" ] && exit 0
 
 task="$selected"
 
-if ! grep -q "^todo: $task$" "$TODO_FILE"; then
+if ! awk -v task="$task" '
+	$0 == "* todo.txt" { in_todos = 1; next }
+	in_todos && /^\* / { exit }
+	in_todos && $0 == "** TODO " task { found = 1; exit }
+	END { exit !found }
+' "$TODO_FILE"; then
 	tmp=$(mktemp)
-	printf "%s\ntodo: %s\n\n" "$(date --rfc-3339=s)" "$task" > "$tmp"
-	cat "$TODO_FILE" >> "$tmp"
-	mv "$tmp" "$TODO_FILE"
+	awk -v category="$TODO_CATEGORY" -v task="$task" -v created="$(date --rfc-3339=seconds)" '
+		$0 == category && !inserted {
+			print
+			printf "** TODO %s\n   CREATED: [%s]\n", task, created
+			inserted = 1
+			next
+		}
+		{ print }
+		END {
+			if (!inserted) {
+				print ""
+				print category
+				printf "** TODO %s\n   CREATED: [%s]\n", task, created
+			}
+		}
+	' "$TODO_FILE" >"$tmp" && mv "$tmp" "$TODO_FILE"
 else
 	action=$(printf "copy to clipboard\nmark as done\nopen in firefox" | dmenu -p "$task" "$@")
 	case "$action" in
@@ -31,8 +48,17 @@ else
 		echo "$task" | wl-copy
 		;;
 	"mark as done")
-		offset=$(grep -bo "^todo: $task$" "$TODO_FILE" | head -1 | cut -d: -f1)
-		printf 'done:' | dd of="$TODO_FILE" bs=1 seek="$offset" conv=notrunc 2>/dev/null
+		tmp=$(mktemp)
+		awk -v task="$task" '
+			$0 == "* todo.txt" { in_todos = 1 }
+			in_todos && /^\* / && $0 != "* todo.txt" { in_todos = 0 }
+			in_todos && $0 == "** TODO " task && !updated {
+				print "** DONE " task
+				updated = 1
+				next
+			}
+			{ print }
+		' "$TODO_FILE" >"$tmp" && mv "$tmp" "$TODO_FILE"
 		;;
 	"open in firefox")
 		firefox "$task"
blob - 207e362df6c6ca8a0c63d8232184d6e6dedc5c88
blob + 0357f28f304b4b281da631160b7d6111471507a7
--- modules/mixins/dotfiles/bin/yank-to-todo
+++ modules/mixins/dotfiles/bin/yank-to-todo
@@ -1,6 +1,7 @@
 #!/usr/bin/env bash
 
-todo_file=~/notes/todo.txt
+todo_file="$HOME/notes/todo.org"
+todo_category='* todo.txt'
 
 if [[ -n "$1" ]]; then
 	url="$1"
@@ -20,8 +21,22 @@ if [[ ! "$url" =~ ^https?:// ]]; then
 fi
 
 tmp=$(mktemp)
-printf "%s\ntodo: %s\n\n" "$(date --rfc-3339=s)" "$url" >"$tmp"
-cat "$todo_file" >>"$tmp"
+awk -v category="$todo_category" -v task="$url" -v created="$(date --rfc-3339=seconds)" '
+	$0 == category && !inserted {
+		print
+		printf "** TODO %s\n   CREATED: [%s]\n", task, created
+		inserted = 1
+		next
+	}
+	{ print }
+	END {
+		if (!inserted) {
+			print ""
+			print category
+			printf "** TODO %s\n   CREATED: [%s]\n", task, created
+		}
+	}
+' "$todo_file" >"$tmp"
 if mv "$tmp" "$todo_file"; then
 	notify-send "Saved" "$url"
 else
blob - aec7f8499b54f29144a90a11d0f93df6bcfdc752
blob + 9dd1f1dabcb84621f66c6b2e8bd13f9d6cf1e7af
--- modules/mixins/dotfiles/config/mpv/mpv.conf
+++ modules/mixins/dotfiles/config/mpv/mpv.conf
@@ -26,7 +26,7 @@ resume-playback
 resume-playback-check-mtime
 
 script-opts=ytdl_hook-ytdl_path=yt-dlp
-ytdl-format=bestvideo[height<=?1080][fps<=?60][vcodec!=?vp9][vcodec!=?av1]+bestaudio/best
+ytdl-format=bestvideo[height<=?720][fps<=?60][vcodec!=?vp9][vcodec!=?av1]+bestaudio/best
 
 # Without downmix sometimes speech is really drowned out by environmental
 # noise.
blob - c6739f65c64a9d26eae9282f3b8b19163dde6003
blob + bc596b33875054a4b88f8c2f7099d880402a2419
--- modules/mixins/dotfiles/config/shell/rc/aliased-short-names
+++ modules/mixins/dotfiles/config/shell/rc/aliased-short-names
@@ -132,3 +132,6 @@ alias pad='pass add'
 alias ped='pass edit'
 
 alias alpash='alpaca_shell'
+
+alias remn='rem -n'
+alias remc='rem -ncm'
blob - 4d3c6be1ec709889b38f43df5eda0bffc70d47c7
blob + eeb0549aaaecb7e34685a7cfb34bcf7af93c29da
--- modules/mixins/dotfiles/config/shell/rc/todo
+++ modules/mixins/dotfiles/config/shell/rc/todo
@@ -1,18 +1,50 @@
 #!/bin/sh
 
-f=~/notes/todo.txt
+f=~/notes/todo.org
 t=${TMPDIR:-/tmp}/ta.$$
 
-alias tt='rg -N -B 1 "^todo:" "$f"'
 alias tn='todo-notify'
 
+tt() {
+	awk '
+		$0 == "* todo.txt" { in_todos = 1; next }
+		in_todos && /^\* / { exit }
+		in_todos && /^\*\* TODO / {
+			sub(/^\*\* TODO /, "")
+			task = $0
+			next
+		}
+		in_todos && task != "" && /^   CREATED: / {
+			sub(/^   CREATED: /, "")
+			entries[++count] = "\033[2;36m" $0 "\033[0m\n\033[1;32mTODO:\033[0m " task
+			task = ""
+		}
+		END {
+			limit = count < 10 ? count : 10
+			for (i = limit; i >= 1; i--)
+				print entries[i] "\n"
+		}
+	' "$f"
+}
+
 ta() {
-	{
-		date '+%Y-%m-%d %H:%M:%S'
-		printf 'todo: \n'
-		echo
-	} >|"$t"
-	[ -f "$f" ] && cat "$f" >>"$t"
+	if [ -f "$f" ]; then
+		awk -v created="$(date --rfc-3339=seconds)" '
+			$0 == "* todo.txt" && !inserted {
+				print
+				printf "** TODO \n   CREATED: [%s]\n", created
+				inserted = 1
+				next
+			}
+			{ print }
+			END {
+				if (!inserted)
+					printf "\n* todo.txt\n** TODO \n   CREATED: [%s]\n", created
+			}
+		' "$f" >"$t"
+	else
+		printf '* todo.txt\n** TODO \n   CREATED: [%s]\n' "$(date --rfc-3339=seconds)" >"$t"
+	fi
 	\mv "$t" "$f"
 	neatvi "$f"
 }
blob - fbc057bbe55e42f1406661b5b336e05f7ab907f7
blob + 1dfe9aa120b68246eaec96f362eb1b0c9dba7774
--- modules/mixins/dotfiles/home/ne/insert-todo
+++ modules/mixins/dotfiles/home/ne/insert-todo
@@ -1 +1 @@
-InsertString todo:
+InsertString ** TODO
blob - 4ac9b294b75ad8b71b71325a5bacffe68786c8fa
blob + 218608405391c71ce952faf833c4dca129d70ab2
--- modules/mixins/dotfiles/home/ne/replace-todo-with-done
+++ modules/mixins/dotfiles/home/ne/replace-todo-with-done
@@ -1,4 +1,4 @@
 MoveSOL
-Find todo
-ReplaceOnce done
+Find ** TODO
+ReplaceOnce ** DONE
 MoveSOL
blob - e9dfba9b5f090df95fcf40d5f45a4d4edc76db88
blob + a0f68221089b43d1c3fbf60469eb039261673c23
--- modules/mixins/dotfiles/home/neatvi
+++ modules/mixins/dotfiles/home/neatvi
@@ -1,21 +1,21 @@
-" q t : toggle between todo/done
+" q t : toggle between TODO/DONE
 rs \t
-s/todo/__SWAP__/
-s/done/todo/
-s/__SWAP__/done/
+s/\*\* TODO /__SWAP__/
+s/\*\* DONE /\*\* TODO /
+s/__SWAP__/\*\* DONE /
 .
 
-" q i : set as todo
+" q i : set as TODO
 rs \i
-s/^/todo: /
+s/^/** TODO /
 .
 
-" q o : set as done
+" q o : set as DONE
 rs \o
-s/^/done: /
+s/^/** DONE /
 .
 
-" q n : go to next todo
+" q n : go to next TODO
 rs \n
-/todo/
+/^\*\* TODO /
 .