Files
vns/sns.sh
2017-05-09 07:18:14 -05:00

221 lines
6.6 KiB
Bash
Executable File

#!/bin/bash
XL_PRODUCT="Simple Note System"
XL_VER="v2a"
# Environment Constants
readonly SNS_STORE="$HOME/.local/sns"
readonly SNS_KEYFILE="$SNS_STORE/.pubkey"
readonly SNS_DEPS=("gpg2" "tree" "git")
readonly IFS=$'\n\t'
set -euo pipefail
readonly SNS_RED_COLOR='\033[1;31m'
readonly SNS_YELLOW_COLOR='\033[1;33m'
readonly SNS_RESET_COLOR='\033[0m'
# Erroneous Exit Constants
# Invocation Errors
readonly SNS_ERR_NO_STORE=5 # The sns store needs to be initialized
readonly SNS_ERR_NO_OPTS=10 # No mode argument was specified
readonly SNS_ERR_NS_ARGS=11 # The specified mode requires an argument
# Dependency Errors
readonly SNS_ERR_DEPS=20 # Base error - add the following codes
readonly SNS_ERR_NO_gpg2=1 # GPG is not installed
readonly SNS_ERR_NO_tree=2 # Tree is not installed
readonly SNS_ERR_NO_git=3 # Git is not installed
# Global Variables
typeset -i SNS_SID="$RANDOM"
typeset -a SNS_ACTION=("")
typeset -a MISSING_DEPS
typeset -i SNS_EXIT=0
declare SNS_PUBKEY=
# Function Definitions
# sns_printError Prints an error message
# sns_NoteHeader Prints standard note header to stdout
# sns_checkDeps Checks the system for required dependencies
# sns_checkStore Checks if $SNS_STORE exists
# sns_sanityCheck Wrapper for sns_checkDeps and sns_checkStore
# ----
# sns_initStore Initializes the SNS Store ( -i)
# sns_printHelp Prints help page ( -h)
# sns_list Lists all notes in `tree` format ( *)
# sns_create Creates note; calls sns_edit() ( -c)
# sns_edit Decrypts note to /tmp, calls editor, re-encrypts note ( -e)
# sns_print Prints note to stdout ( -p)
# sns_rm Deletes note from store ( -d)
# sns_gitPassthrough Passes through all instructions to git (git)
function sns_printError(){
printf "$SNS_RED_COLOR!$SNS_RESET_COLOR - %s\n" "$@"
}
function sns_NoteHeader(){
printf "%s\n%s\n" "Title:" "Date:"
}
function sns_checkDeps(){
local SNS_RETURN="true";
for DEP in "${SNS_DEPS[@]}"; do
if test ! -e "$(which "$DEP" 2>/dev/null)"; then
MISSING_DEPS+=("$DEP")
SNS_RETURN="false";
fi
done
"$SNS_RETURN";
}
function sns_checkStore(){
if [ -d "$SNS_STORE" ]; then true; else false; fi
}
function sns_sanityCheck {
if ! sns_checkDeps; then
SNS_EXIT="$SNS_ERR_DEPS"
for DEP in "${MISSING_DEPS[@]}"; do
local SNS_DEP_EC="\$ERR_NO_$DEP"
sns_printError "Dependency %s not in path." "$DEP";
SNS_EXIT+=${!SNS_DEP_EC}
done
fi
if [ -r "$SNS_STORE/.pubkey" ]; then
SNS_PUBKEY="$(cat "$SNS_STORE/.pubkey")"
elif ! sns_checkStore; then
if [ "$(echo "${SNS_ACTION[@]}" | awk '{print $1;}')" != "sns_initStore" ]; then
sns_printError "The sns store does not exist."
printf " - %s\n" "Please run \`sns -i [gpg-key]\` to initialize sns."
SNS_EXIT="$SNS_ERR_NO_STORE"
fi
fi
}
#----
function sns_initStore {
mkdir -p "$SNS_STORE"
echo "$@" | awk '{print $1}' > "$SNS_KEYFILE"
}
function sns_printHelp(){
printf "%s" "usage: sns [-cedlp] <notebook/section/name>"
printf "\n%s%s%s" "usage: sns " "git" " ..."
printf "\n%s" " sns [-hi]"
printf "\n%s" " -c | --create : Create note"
printf "\n%s" " -C | --config : Edit Config"
printf "\n%s" " -d | --delete : Delete note"
printf "\n%s" " -e | --edit : Open note for editing"
printf "\n%s" " -h | --help : Display this message"
printf "\n%s" " -i | --init : Write default config and initalize SNS store"
printf "\n%s" " -l | --list : List all notes in NOTEBOOK"
printf "\n%s" " -p | --print : Print note to console"
printf "\n\n"
}
function sns_list(){
# Change directories to fix tree header
cd "$SNS_STORE" || exit; cd .. || exit;
# Print the tree
tree -C --noreport --prune "$(echo "$@" | awk '{print $1}')"
}
function sns_create(){
# Make sure the note doesn't already exist
if [ -r "$SNS_STORE/$(echo "$@" | awk '{print $1}')" ]; then
sns_printError "Note already exists."
return
fi
# Print the standard header to a temporary note
sns_NoteHeader > /tmp/"$SNS_SID"
# Edit the new note
sns_edit "$(echo "$@" | awk '{print $1}')"
}
function sns_edit(){
# Make the function more readable
local readonly SNS_NOTE="$SNS_STORE/$(echo "$@" | awk '{print $1}')"
# Test if edit was called from create
if [ ! -r /tmp/"$SNS_SID" ]; then gpg2 -d -o /tmp/"$SNS_SID" "$SNS_NOTE"; fi
# Edit the note
vim /tmp/"$SNS_SID"
# Make sure the notebook/section exists
if [ ! -d "$(dirname "$SNS_NOTE")" ]; then mkdir -p "$(dirname "$SNS_NOTE")"; fi
# If the note previously existed, make a backup.
if [ -r "$SNS_NOTE" ]; then mv "$SNS_NOTE" "$SNS_NOTE.bk"; fi
# Re-encrypt it to the store
gpg2 -r "$SNS_PUBKEY" -o "$SNS_NOTE" -e /tmp/"$SNS_SID"
# If all went well, remove the backup
if [ -r "$SNS_NOTE" ]; then rm "$SNS_NOTE.bk"; fi
}
function sns_print(){
gpg2 -d "$SNS_STORE/$(echo "$@" | awk '{print $1}')"
}
function sns_rm(){
rm -f "$SNS_STORE/$(echo "$@" | awk '{print $1}')"
}
function sns_gitPassthrough(){
cd "$SNS_STORE" || exit;
git "$@";
}
# ----
function sns_argParse(){
ARGS=($@)
#echo "${#ARGS}"
SNS_ACTION=()
while getopts ":i:hc:e:p:d:" OPT; do
# If an option requiring an argument was passed without an argument,
# inform the user and set exit code to "$SNS_ERR_NS_ARGS"
case "${ARGS[!OPTIND]}" in
-i|-c|-e|-p|-d)
if [ "${#ARGS}" -lt 2 ]; then
sns_printError "A required argument was not given."
SNS_EXIT="$SNS_ERR_NS_ARGS"
return
fi
esac
case "$OPT" in
i)
SNS_ACTION=("sns_initStore" "$OPTARG");;
h)
SNS_ACTION=("sns_printHelp");;
c)
SNS_ACTION=("sns_create $OPTARG");;
e)
SNS_ACTION=("sns_edit $OPTARG");;
p)
SNS_ACTION=("sns_print $OPTARG");;
d)
SNS_ACTION=("sns_rm $OPTARG");;
esac
done
if [ "${#SNS_ACTION[@]}" -eq 0 ]; then
if [ "$(echo "$@" | awk '{print $1}')" == "git" ]; then
SNS_ACTION=($@)
else
if [ -d "$SNS_STORE/$*" ]; then
SNS_ACTION=("sns_list" "sns/$@")
else
SNS_ACTION=("sns_list" "sns")
fi
fi
fi
}
# Entry Point
printf "%s\n%s\n" "$XL_PRODUCT" "$XL_VER"
printf "\n"
sns_argParse "$@"
sns_sanityCheck
if [ "$SNS_EXIT" -eq 0 ]; then
eval "${SNS_ACTION[@]}"
fi
printf "\n"
exit "$SNS_EXIT"