From 2c459210834e92d26a69cc9e4e847a5f98bb8035 Mon Sep 17 00:00:00 2001 From: Jon Lewis Date: Thu, 1 Feb 2018 16:47:03 -0600 Subject: [PATCH] Refactored script to match new scripting style --- vns | 249 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ vns.sh | 215 ------------------------------------------------- 2 files changed, 249 insertions(+), 215 deletions(-) create mode 100755 vns delete mode 100755 vns.sh diff --git a/vns b/vns new file mode 100755 index 0000000..8f20c99 --- /dev/null +++ b/vns @@ -0,0 +1,249 @@ +#!/usr/bin/env bash +XL_PRODUCT="Vim Note System" +XL_VER="1.0b1" + +# Environment Constants +readonly VNS_STORE="$HOME/.config/vns" + +readonly IFS=$'\n\t' + +# ASCII Color Codes +readonly VNS_RED_COLOR='\033[0;31m' +readonly VNS_BLUE_COLOR='\033[0;34m' +readonly VNS_RESET_COLOR='\033[0m' + +# Fail on unsuccessful command pipes and unset variables +set -euo pipefail + +# Erroneous Exit Codes +# |Code| Meaning | +# |----|-----------------------------------------| +# | 5 | The vns store needs to be initialized | +# | 11 | Insufficient arguments | +# | 15 | No editor specified in environment | +# | 20 | Missing dependency | +# | 31 | Note already exists | +# | 41 | Note not found | + +vns_raise (){ + + # raise (message) (exit code) + # Prints error (message) to stderr, then exits with (exit code) + + printf "%s, %s\n\n" "$XL_PRODUCT" "$XL_VER" + printf "$VNS_RED_COLOR!$VNS_RESET_COLOR - %s\n" "$1" 1>&2 + exit "$2" + +} + +vns_checkDeps (){ + + # checkDeps + # Prints a list of unbound variables + + readonly VNS_DEPS=("vim" "gpg2" "tree" "git") + + for DEP in "${VNS_DEPS[@]}"; do + if test ! -e "$(which "$DEP" 2>/dev/null)"; then + printf "%s " "$DEP" + fi + done + +} + +vns_sanityCheck () { + + # sanityCheck + # Terminates script if environment is not suitable for vns + + # --- Dependencies --- + # Get list of missing dependencies + local MISSING; MISSING="$(vns_checkDeps)" + + # If that list is not empty, inform the user and exit on code 20 + if [ -n "$MISSING" ]; then + vns_raise "Missing Dependencies: $MISSING" 20 + fi + + # --- Store --- + # Verify that the note store has been initialized + if [ ! -d "$VNS_STORE" ]; then + vns_raise "The vns store needs to be initialized (hint: -i)" 5 + fi + +} + +#---- +vns_init () { + + # initStore + # Prepares $VNS_STORE for use + + mkdir -p "$VNS_STORE" + cd "$VNS_STORE" || exit + git init >/dev/null + +} + +vns_printHelp (){ + + # printHelp + # Prints help information to stdout + + printf "%s" "usage: vns [-cedlp] " + printf "\n%s" " vns -i " + printf "\n%s" " vns -h" + printf "\n%s%s%s" "usage: vns " "git" " ..." + + printf "\n%s" " -c | --create : Create note" + 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 VNS store" + printf "\n%s" " -l | --list : List all notes in NOTEBOOK" + printf "\n%s" " -p | --print : Print note to console" + printf "\n\n" + +} + +vns_list () { + + # list (notebook) + # Prints a tree containing all notes in the notebook + # If no notebook is specified, the entire store is used + + # Check for default behavior + if [ -z "${@:1:1}" ]; then + readonly NOTEBOOK="" + printf "%s\n" "Store" + else + readonly NOTEBOOK="$1" + printf "%s\n" "$1" + fi + + tree -C --noreport --prune "$VNS_STORE/$NOTEBOOK"\ + | tail -n +2\ + | sed s/\.gpg//g + +} + +vns_rm () { + + # rm (note) + # removes (note) from the store + + # Verify $1 is bound + if [ -z "${@:1:1}" ]; then vns_raise "Insufficient arguments" 11; fi + + # Verify the note exists + if [ ! -r "$VNS_STORE/$1.gpg" ]; then + vns_raise "Note does not exist" 41; + fi + # Delete the Note + git rm "$VNS_STORE/$1.gpg" > /dev/null + git commit -m "Deleted $1" > /dev/null + + # Report success + printf "%s, %s\n\n" "$XL_PRODUCT" "$XL_VER" + printf "$VNS_BLUE_COLOR!$VNS_RESET_COLOR - %s\n" "Deleted $VNS_STORE/$1" + +} + +vns_create () { + + # create (note) + # Edit a previously non-existant note + + # Verify $1 is bound + if [ -z "${@:1:1}" ]; then vns_raise "Insufficient arguments" 11; fi + + # Refuse to overwrite a note + if [ -r "$VNS_STORE/$1.gpg" ]; then vns_raise "Note already exists" 31; fi + + # If the note belongs to a new notebook, create the notebook + if [ ! -d "$(dirname "$1")" ]; then mkdir -p "$VNS_STORE/$(dirname "$1")"; fi + + # Create-Edit the note + vim "$VNS_STORE/$1.gpg" + + # Update Git + git add "$VNS_STORE/$1.gpg" > /dev/null + git commit -m "Added $1" > /dev/null + +} + +vns_edit () { + + # edit (note) + # edit (note) in the store + + # Verify $1 is bound + if [ -z "${@:1:1}" ]; then vns_raise "Insufficient arguments" 11; fi + + # Refuse to edit non-existant notes + if [ ! -r "$VNS_STORE/$1.gpg" ]; then vns_raise "Note not found: $1" 41; fi + + # Edit the specified note + vim "$VNS_STORE/$1.gpg" + + # Warn the user if the note failed to encrypt + if ! grep "PGP" <<< "$(file "$VNS_STORE/$1")" > /dev/null; then + printf "$VNS_RED_COLOR!$VNS_RESET_COLOR - %s\n %s\n"\ + "The created note was not encrypted."\ + "Check your vim-gnupg setup." + + # Update Git + git add "$VNS_STORE/$1.gpg" > /dev/null + git commit -m "Edited $1" > /dev/null +} + +vns_print () { + + # print (note) + # print the given note to stdout + + # Verify $1 is bound + if [ -z "${@:1:1}" ]; then vns_raise "Insufficient arguments" 11; fi + + # Decrypt the specified note + gpg2 -d "$VNS_STORE/$1.gpg" + +} + +# ---- +vns () { + + # Bypass sanity check if told to initialize store + if [ "$*" != "-i" ]; then + vns_sanityCheck; + # Change Directory to Store for Git passthrough + cd $VNS_STORE || exit; + fi + + + + # Default action is to list all notes + if [ -z "${@:1:1}" ]; then vns_list ""; exit 0; fi + + # List of valid arguments + declare -A -r ACTIONS=( ["-c"]="vns_create" ["-d"]="vns_rm"\ + ["-e"]="vns_edit" ["-l"]="vns_list"\ + ["-h"]="vns_printHelp" ["-i"]="vns_init"\ + ["-p"]="vns_print"\ + ["git"]="git" ) + + # If given an invalid argument, inform the user and exit on code 10 + # Otherwise, perform the corresponding action + if ! test "${ACTIONS["$1"]+isset}"; then + vns_raise "Invalid argument: $1" 10 + else + "${ACTIONS["$1"]}" "${@:2}" + fi + + # Print an extra newline just in case + # printf "\n"; + + exit 0; +} + +vns "$@" diff --git a/vns.sh b/vns.sh deleted file mode 100755 index e77904c..0000000 --- a/vns.sh +++ /dev/null @@ -1,215 +0,0 @@ -#!/bin/bash -XL_PRODUCT="Vim Note System" -XL_VER="1.0a2" - -# Environment Constants -readonly VNS_STORE="$HOME/.local/vns" -readonly VNS_KEYFILE="$VNS_STORE/.pubkey" -readonly IFS=$'\n\t' -set -euo pipefail - -readonly VNS_RED_COLOR='\033[1;31m' -readonly VNS_YELLOW_COLOR='\033[1;33m' -readonly VNS_RESET_COLOR='\033[0m' - -# Erroneous Exit Constants - - # Invocation Errors - readonly VNS_ERR_NO_STORE=5 # The vns store needs to be initialized - readonly VNS_ERR_NO_OPTS=10 # No mode argument was specified - readonly VNS_ERR_NS_ARGS=11 # The specified mode requires an argument - readonly VNS_ERR_NO_EDTR=15 # No editor specified in environment - # Dependency Errors - readonly VNS_ERR_DEPS=20 # Base error - add the following codes - readonly VNS_ERR_NO_gpg2=1 # GPG is not installed - readonly VNS_ERR_NO_tree=2 # Tree is not installed - readonly VNS_ERR_NO_git=3 # Git is not installed - -# Global Variables -typeset -a VNS_ACTION=("") -typeset -a MISSING_DEPS -typeset -i VNS_EXIT=0 -declare VNS_PUBKEY= -# Function Definitions -# vns_index Print the $1th index of array ${2[@]} (friendly to -euo) -# vns_printError Prints an error message -# vns_NoteHeader Prints standard note header to stdout -# vns_checkDeps Checks the system for required dependencies -# vns_checkStore Checks if $VNS_STORE exists -# vns_sanityCheck Wrapper for vns_checkDeps and vns_checkStore -# ---- -# vns_initStore Initializes the VNS Store ( -i) -# vns_printHelp Prints help page ( -h) -# vns_list Lists all notes in `tree` format ( *) -# vns_create Creates note; calls vns_edit() ( -c) -# vns_edit Decrypts note to /tmp, calls editor, re-encrypts note ( -e) -# vns_print Prints note to stdout ( -p) -# vns_rm Deletes note from store ( -d) -# vns_gitPassthrough Passes through all instructions to git (git) - -function vns_index(){ - echo "$@" | awk -v i="$(($1+1))" '{print $i}' -} -function vns_printError(){ - printf "$VNS_RED_COLOR!$VNS_RESET_COLOR - %s\n" "$@" -} -function vns_NoteHeader(){ - printf "%s\n%s\n" "Title:" "Date:" -} -function vns_checkDeps(){ - local VNS_RETURN="true"; - for DEP in "${VNS_DEPS[@]}"; do - if test ! -e "$(which "$DEP" 2>/dev/null)"; then - MISSING_DEPS+=("$DEP") - VNS_RETURN="false"; - fi - done - "$VNS_RETURN"; -} -function vns_checkStore(){ - if [ -d "$VNS_STORE" ]; then true; else false; fi -} -function vns_sanityCheck { - if ! vns_checkDeps; then - VNS_EXIT="$VNS_ERR_DEPS" - for DEP in "${MISSING_DEPS[@]}"; do - local VNS_DEP_EC="\$ERR_NO_$DEP" - vns_printError "Dependency %s not in path." "$DEP"; - VNS_EXIT+=${!VNS_DEP_EC} - done - fi - - if [ -r "$VNS_STORE/.pubkey" ]; then - VNS_PUBKEY="$(cat "$VNS_STORE/.pubkey")" - elif ! vns_checkStore; then - if [ "$(vns_index "1" "${VNS_ACTION[@]}")" != "vns_initStore" ]; then - vns_printError "The vns store does not exist." - printf " - %s\n" "Please run \`vns -i [gpg-key]\` to initialize vns." - VNS_EXIT="$VNS_ERR_NO_STORE" - fi - fi -} -#---- -function vns_initStore { - mkdir -p "$VNS_STORE" - echo "$@" | awk '{print $1}' > "$VNS_KEYFILE" -} -function vns_printHelp(){ - printf "%s" "usage: vns [-cedlp] " - printf "\n%s" " vns -i " - printf "\n%s" " vns -h" - printf "\n%s%s%s" "usage: vns " "git" " ..." - - printf "\n%s" " -c | --create : Create note" - 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 VNS store" - printf "\n%s" " -l | --list : List all notes in NOTEBOOK" - printf "\n%s" " -p | --print : Print note to console" - printf "\n\n" -} -function vns_list(){ - # Print the tree - tree -C --noreport --prune "$VNS_STORE/$(vns_index "1" "$@")" | tail -n +2 | sed s/\.gpg//g -} - -function vns_rm(){ - local readonly VNS_NOTE; VNS_NOTE="$VNS_STORE/$(vns_index "1" "$@").gpg" - echo "Deleting $VNS_NOTE" - rm -f "$VNS_NOTE" -} -function vns_create(){ - local readonly VNS_NOTE; VNS_NOTE="$VNS_STORE/$(vns_index "1" "$@").gpg" - # Make sure the note doesn't already exist - if [ -r "$VNS_NOTE" ]; then - vns_printError "Note already exists." - else - if [ ! -d "$(dirname "$VNS_NOTE")" ]; then - mkdir -p "$(dirname "$VNS_NOTE")" - fi - vns_NoteHeader | gpg2 -e -r "$VNS_PUBKEY" -o "$VNS_NOTE" - vns_edit "$@" - fi -} - -function vns_edit(){ - # Make the function more readable - local readonly VNS_NOTE; VNS_NOTE="$VNS_STORE/$(vns_index "1" "$@").gpg" - # Edit the note - vim "$VNS_NOTE" -} -function vns_print(){ - gpg2 -d "$VNS_STORE/$(vns_index "1" "$@").gpg" -} -function vns_gitPassthrough(){ - cd "$VNS_STORE" || exit; - git "$@"; -} -# ---- -function vns_argParse(){ - ARGS=($@) - #echo "${#ARGS}" - VNS_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 "$VNS_ERR_NS_ARGS" - case "${ARGS[!OPTIND]}" in - -i|-c|-e|-p|-d) - if [ "${#ARGS}" -lt 2 ]; then - vns_printError "A required argument was not given." - VNS_EXIT="$VNS_ERR_NS_ARGS" - return - fi - esac - case "$OPT" in - i) - VNS_ACTION=("vns_initStore" "$OPTARG");; - h) - VNS_ACTION=("vns_printHelp");; - c) - VNS_ACTION=("vns_create $OPTARG");; - e) - VNS_ACTION=("vns_edit $OPTARG");; - p) - VNS_ACTION=("vns_print $OPTARG");; - d) - VNS_ACTION=("vns_rm $OPTARG");; - esac - done - - if [ "${#VNS_ACTION[@]}" -eq 0 ]; then - if [ "$(vns_index "1" "$@")" == "git" ]; then - VNS_ACTION=($@) - else - if [ -d "$VNS_STORE/$*" ]; then - VNS_ACTION=("vns_list" "$@") - else - VNS_ACTION=("vns_list" "") - fi - fi - fi -} - -# Entry Point -printf "%s, %s\n" "$XL_PRODUCT" "$XL_VER" -printf "\n" -cd "$VNS_STORE" || exit; - -readonly VNS_EDITOR="vim" -readonly VNS_DEPS=("vim" "gpg2" "tree" "git") - - - - - -vns_argParse "$@" -vns_sanityCheck -if [ "$VNS_EXIT" -eq 0 ]; then - eval "${VNS_ACTION[@]}" -fi - -printf "\n" - -exit "$VNS_EXIT"