#!/usr/bin/env bash # note (clean + dedupe, fixed slug logic) # needs: fzf, rg # likes: batcat # written mostly by chatgpt (ai) in april 2026 # brex production set -euo pipefail NOTES_DIR="${NOTES_DIR:-$HOME/notes}" EDITOR="${EDITOR:-hx}" # deps for cmd in fzf rg; do if ! command -v "$cmd" &>/dev/null; then echo "Error: $cmd is required" >&2 exit 1 fi done mkdir -p "$NOTES_DIR" today() { date +"%Y-%m-%d" } slugify() { local input="${1:-}" input="$(echo "$input" \ | tr '[:upper:]' '[:lower:]' \ | tr -cd 'a-z0-9 -' \ | tr ' ' '-' \ | sed 's/-\+/-/g' \ | sed 's/^-//' \ | sed 's/-$//')" echo "$input" } open_note_fzf() { local file file=$( find "$NOTES_DIR" -maxdepth 1 -type f -name '*.md' \ -printf '%T@ %p\n' \ | sort -nr \ | cut -d' ' -f2- \ | fzf --prompt="notes> " \ --preview="batcat --style=minimal --color=always {} 2>/dev/null || cat {}" \ --height=80% \ --reverse ) [[ -z "$file" ]] && return "$EDITOR" "$file" } search_notes() { local query="${1:-}" local selection file line selection=$( rg -i -m1 --no-heading --line-number --color=always "${query:-}" "$NOTES_DIR" \ | fzf --ansi \ --delimiter : \ --prompt="search> " \ --preview='batcat --style=numbers --color=always {1} --highlight-line {2} 2>/dev/null || cat {1}' \ --bind "change:reload:rg -i -m1 --no-heading --line-number --color=always {q} '$NOTES_DIR' || true" \ --phony \ --query "$query" \ --height=80% \ --reverse ) [[ -z "$selection" ]] && return file="${selection%%:*}" line="${selection#*:}" line="${line%%:*}" "$EDITOR" "$file" "+$line" } create_note() { local text="$*" local title slug file [[ -z "$text" ]] && return title="$text" # robust slug: full text → slugify → trim to 5 parts slug="$(slugify "$text" | cut -d- -f1-5)" [[ -z "$slug" ]] && slug="note" file="$NOTES_DIR/$(today)-$slug.md" # dedupe: reopen if exists if [[ -f "$file" ]]; then "$EDITOR" "$file" return fi cat > "$file" < "$file" <