212 lines
3.2 KiB
Bash
212 lines
3.2 KiB
Bash
|
#!/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;\
|
||
|
}\
|
||
|
"
|
||
|
|
||
|
grep -r -h "^Subject:\|^X-Note-Id:\|^X-Date:" "$BASEDIR" | awk "$FILTER" | sort | cut -d " " -f "2-"
|
||
|
}
|
||
|
|
||
|
|
||
|
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
|
||
|
}
|
||
|
|
||
|
|
||
|
usage() {
|
||
|
echo "$0 {--new,--list,--edit,--help}"
|
||
|
}
|
||
|
|
||
|
while (( "$#" )); do
|
||
|
case "$1" in
|
||
|
-n|--new)
|
||
|
shift
|
||
|
new_entry "$*"
|
||
|
exit 0
|
||
|
;;
|
||
|
-l|--list)
|
||
|
list_entries
|
||
|
exit 0
|
||
|
;;
|
||
|
-e|--edit)
|
||
|
if [ -z "$2" ]; then
|
||
|
echo "Misssing argument for $1"
|
||
|
exit 1
|
||
|
fi
|
||
|
edit_entry "$2"
|
||
|
exit 0
|
||
|
;;
|
||
|
-E|--export)
|
||
|
if [ -z "$2" ]; then
|
||
|
echo "Misssing arguments for $1"
|
||
|
exit 1
|
||
|
fi
|
||
|
export_note "$2" "$3"
|
||
|
exit 0
|
||
|
;;
|
||
|
-g|--graph)
|
||
|
get_graph
|
||
|
exit 0
|
||
|
;;
|
||
|
*)
|
||
|
usage
|
||
|
exit 1
|
||
|
;;
|
||
|
esac
|
||
|
|
||
|
done
|
||
|
|
||
|
usage
|
||
|
exit 1
|