2024-11-17 03:48:51 +00:00
|
|
|
#!/usr/bin/env bash
|
|
|
|
|
|
|
|
set -e
|
|
|
|
|
|
|
|
DATE_FORMAT="%a, %d %b %Y %H:%M:%S %z"
|
|
|
|
BASEDIR=~/Notes
|
|
|
|
EDITOR="${EDITOR:-vim}"
|
|
|
|
|
|
|
|
if [ ! -d "$BASEDIR" ]; then
|
|
|
|
mkdir -p "$BASEDIR"
|
|
|
|
fi
|
|
|
|
|
|
|
|
die() {
|
|
|
|
echo "$@" 1>&2;
|
|
|
|
exit 1
|
|
|
|
}
|
|
|
|
|
|
|
|
uuid()
|
|
|
|
{
|
|
|
|
local N B T
|
|
|
|
|
|
|
|
for (( N=0; N < 16; ++N ))
|
|
|
|
do
|
|
|
|
B=$(( RANDOM%255 ))
|
|
|
|
|
|
|
|
if (( N == 6 ))
|
|
|
|
then
|
|
|
|
printf '4%x' $(( B%15 ))
|
|
|
|
elif (( N == 8 ))
|
|
|
|
then
|
|
|
|
local C='89ab'
|
|
|
|
printf '%c%x' ${C:$(( RANDOM%${#C} )):1} $(( B%15 ))
|
|
|
|
else
|
|
|
|
printf '%02x' $B
|
|
|
|
fi
|
|
|
|
|
|
|
|
for T in 3 5 7 9
|
|
|
|
do
|
|
|
|
if (( T == N ))
|
|
|
|
then
|
|
|
|
printf '-'
|
|
|
|
break
|
|
|
|
fi
|
|
|
|
done
|
|
|
|
done
|
|
|
|
|
|
|
|
echo
|
|
|
|
}
|
|
|
|
|
|
|
|
canonicalize() {
|
|
|
|
NAME="$1"
|
|
|
|
NAME="$(echo "$NAME" | tr '[:upper:]' '[:lower:]')"
|
|
|
|
NAME="$(echo "$NAME" | sed 's/[^a-z0-9]/_/g')"
|
|
|
|
|
|
|
|
echo "$NAME"
|
|
|
|
}
|
|
|
|
|
|
|
|
utc_timestamp() {
|
|
|
|
date -u +"%Y%m%d%H%M%S"
|
|
|
|
}
|
|
|
|
|
|
|
|
find_file_by_id() {
|
|
|
|
ID="$1"
|
|
|
|
|
|
|
|
{ grep -l -r -m1 "^X-Note-Id: $ID$" "$BASEDIR" || true; } | sort| head -1
|
|
|
|
}
|
|
|
|
|
|
|
|
assert_find_file_by_id() {
|
|
|
|
FILE="$(find_file_by_id "$1")"
|
|
|
|
|
|
|
|
if [ ! -f "$FILE" ]; then
|
|
|
|
die "Note with ID <$ID> not found"
|
|
|
|
fi
|
|
|
|
|
|
|
|
echo "$FILE"
|
|
|
|
}
|
|
|
|
|
|
|
|
list_entries() {
|
|
|
|
FILTER="\
|
|
|
|
BEGIN { \
|
|
|
|
message_id=0; \
|
|
|
|
subject=0; \
|
|
|
|
date=0; \
|
|
|
|
} \
|
|
|
|
match(\$0, /^X-Note-Id: .*$/) { \
|
|
|
|
if (message_id != 0) { \
|
|
|
|
if (subject !=0 && date != 0)\
|
|
|
|
print date, message_id, subject; \
|
|
|
|
subject = 0; \
|
|
|
|
date = 0; \
|
|
|
|
};\
|
|
|
|
message_id = substr(\$0, 12, RLENGTH-11); \
|
|
|
|
} \
|
|
|
|
match(\$0, /^Subject: .*$/) { \
|
|
|
|
if (subject != 0) { \
|
|
|
|
if (message_id != 0 && date != 0)\
|
|
|
|
print date, message_id, subject; \
|
|
|
|
message_id = 0; \
|
|
|
|
date = 0; \
|
|
|
|
}; \
|
|
|
|
subject = substr(\$0, 10, RLENGTH-9); \
|
|
|
|
} \
|
|
|
|
match(\$0, /^X-Date: .*$/) { \
|
|
|
|
if (date != 0) { \
|
|
|
|
if (message_id != 0 && subject != 0)\
|
|
|
|
print date, message_id, subject; \
|
|
|
|
subject = 0; \
|
|
|
|
message_id = 0; \
|
|
|
|
}; \
|
|
|
|
date = substr(\$0, 9, RLENGTH-8); \
|
|
|
|
} \
|
|
|
|
END { \
|
|
|
|
if (message_id != 0 && subject != 0 && date != 0)\
|
|
|
|
print date, message_id, subject;\
|
|
|
|
}\
|
|
|
|
"
|
|
|
|
|
2024-11-27 20:09:02 +00:00
|
|
|
grep -r -m 3 -h "^Subject:\|^X-Note-Id:\|^X-Date:" "$BASEDIR" --include="note.md" | awk "$FILTER" | sort | cut -d " " -f "2-"
|
2024-11-17 03:48:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
new_entry() {
|
|
|
|
NAME="$1"
|
|
|
|
CANONICAL_NAME="$(canonicalize "$NAME")"
|
|
|
|
FULL_NAME="$(utc_timestamp)-$CANONICAL_NAME"
|
|
|
|
NOTE_ID="$(uuid)"
|
|
|
|
|
|
|
|
NOTE_DIR="$BASEDIR/$FULL_NAME"
|
|
|
|
NOTE_FILE="$NOTE_DIR/note.md"
|
|
|
|
|
|
|
|
mkdir -p "$NOTE_DIR"
|
|
|
|
|
|
|
|
TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
|
|
|
|
|
|
|
|
{
|
|
|
|
echo "X-Date: $TIMESTAMP"
|
|
|
|
echo "X-Note-Id: $NOTE_ID"
|
|
|
|
echo "Subject: $NAME"
|
|
|
|
echo
|
|
|
|
} >> "$NOTE_FILE"
|
|
|
|
|
|
|
|
$EDITOR "$NOTE_FILE"
|
|
|
|
}
|
|
|
|
|
|
|
|
edit_entry() {
|
|
|
|
ID="$1"
|
|
|
|
FILENAME="$(assert_find_file_by_id "$ID")"
|
|
|
|
|
|
|
|
echo "$FILENAME"
|
|
|
|
|
|
|
|
$EDITOR "$FILENAME"
|
|
|
|
}
|
|
|
|
|
|
|
|
export_note() {
|
|
|
|
ID="$1"
|
|
|
|
FILENAME="$(assert_find_file_by_id "$ID")"
|
|
|
|
|
|
|
|
DIR="$2"
|
|
|
|
if [ -z "$DIR" ]; then
|
|
|
|
cat "$FILENAME"
|
|
|
|
else
|
|
|
|
die "Directory export not implemented"
|
|
|
|
fi
|
|
|
|
}
|
|
|
|
|
2024-11-18 02:37:24 +00:00
|
|
|
fzf_entry() {
|
|
|
|
NAME="$1"
|
|
|
|
ID="$(echo "$2" | cut -d " " -f 1)"
|
|
|
|
|
|
|
|
if [ -z "$ID" ]; then
|
|
|
|
if [ ! -z "$NAME" ]; then
|
|
|
|
new_entry "$NAME"
|
|
|
|
fi
|
|
|
|
else
|
|
|
|
edit_entry "$ID"
|
|
|
|
fi
|
|
|
|
}
|
2024-11-17 03:48:51 +00:00
|
|
|
|
|
|
|
usage() {
|
2024-11-18 02:37:24 +00:00
|
|
|
echo "$0 {--new,--list,--edit,--fzf,--help}"
|
2024-11-17 03:48:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
while (( "$#" )); do
|
|
|
|
case "$1" in
|
|
|
|
-n|--new)
|
|
|
|
shift
|
|
|
|
new_entry "$*"
|
|
|
|
exit 0
|
|
|
|
;;
|
|
|
|
-l|--list)
|
|
|
|
list_entries
|
|
|
|
exit 0
|
|
|
|
;;
|
|
|
|
-e|--edit)
|
|
|
|
if [ -z "$2" ]; then
|
2024-11-18 02:37:24 +00:00
|
|
|
exit 0
|
2024-11-17 03:48:51 +00:00
|
|
|
fi
|
|
|
|
edit_entry "$2"
|
|
|
|
exit 0
|
|
|
|
;;
|
2024-11-18 02:37:24 +00:00
|
|
|
-f|--fzf)
|
|
|
|
fzf_entry "$2" "$3"
|
|
|
|
exit 0
|
|
|
|
;;
|
2024-11-17 03:48:51 +00:00
|
|
|
-E|--export)
|
|
|
|
if [ -z "$2" ]; then
|
|
|
|
echo "Misssing arguments for $1"
|
|
|
|
exit 1
|
|
|
|
fi
|
|
|
|
export_note "$2" "$3"
|
|
|
|
exit 0
|
|
|
|
;;
|
2024-11-17 04:08:06 +00:00
|
|
|
-p|--preview)
|
|
|
|
if [ -z "$2" ]; then
|
|
|
|
echo "Misssing arguments for $1"
|
|
|
|
exit 1
|
|
|
|
fi
|
|
|
|
NOTE_ID="$(echo $2 | cut -d " " -f 1)"
|
2024-11-18 08:38:29 +00:00
|
|
|
export_note "$NOTE_ID" "" | fmt -s -w "$FZF_PREVIEW_COLUMNS"
|
2024-11-17 04:08:06 +00:00
|
|
|
exit 0
|
|
|
|
;;
|
2024-11-17 03:48:51 +00:00
|
|
|
-g|--graph)
|
|
|
|
get_graph
|
|
|
|
exit 0
|
|
|
|
;;
|
|
|
|
*)
|
|
|
|
usage
|
|
|
|
exit 1
|
|
|
|
;;
|
|
|
|
esac
|
|
|
|
|
|
|
|
done
|
|
|
|
|
|
|
|
usage
|
|
|
|
exit 1
|