diff --git a/CHANGELOG b/CHANGELOG index e12f80d..e4e1039 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,9 @@ v1.1 Added merge, rename options Enabled gpg-agent + +v1.2 + * Added import, duplicate options + * reworked delete option to support multiple deletions + * GNU Switches were never supported, and documentation has been updated to reflect this + * Reworked merge function diff --git a/DEBUG b/DEBUG index 9c323a3..0ed5941 100644 --- a/DEBUG +++ b/DEBUG @@ -1,4 +1,4 @@ -Vim Note System, v1.1 +Vim Note System, v1.2 The following is a table of exit codes diff --git a/README.md b/README.md index 45c90d7..4d5c243 100644 --- a/README.md +++ b/README.md @@ -15,16 +15,21 @@ but instead could use the tools already provided by the operating system. ================== usage: vns [-cedlp] - vns [-hi] - vns git ... + vns -I + vns -h + vns vns_git ... + + -c : Create note + -d : Delete note(s) + -e : Open note for editing + -h : Display this message + -i : import file as note + -I : Initialize note store + -l : List all notes in + -m : Merge two or more notes + -p : Print note to console + -r : Rename/move a note - -c | --create : Create note - -d | --delete : Delete note - -e | --edit : Open note for editing - -h | --help : Display this message - -i | --init : Initialize note store" - -l | --list : List all notes in - -p | --print : Print note to console ## Installing ### Dependencies diff --git a/vns b/vns old mode 100644 new mode 100755 index c4bd632..a0c083b --- a/vns +++ b/vns @@ -1,5 +1,5 @@ #!/usr/bin/env bash -# Vim Note System v1.1, a simple script for managing encrypted plaintext notes +# Vim Note System v1.5, a simple script for managing encrypted plaintext notes # Copyright (C) 2018 Jon Lewis # This program is free software; you can redistribute it and/or modify @@ -15,11 +15,10 @@ # You should have received a copy of the GNU General Public License along # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - set -euo pipefail # Terminate the script if anything goes wrong # http://redsymbol.net/articles/unofficial-bash-strict-mode/ -readonly VNS_PRODUCT="Vim Note System, v1.1" # String to print for reports +readonly VNS_PRODUCT="Vim Note System, v1.5" # String to print for reports readonly VNS_STORE="$HOME/.config/vns" # Where vns expects its note store readonly GPG_TTY="$(tty)" # Sets up gpg-agent for use @@ -31,12 +30,16 @@ vns_raise (){ local -r VNS_RED_COLOR='\033[0;31m' local -r VNS_RESET_COLOR='\033[0m' - printf "%s, %s\\n\\n" "$VNS_PRODUCT" + printf "%s\\n\\n" "$VNS_PRODUCT" printf "$VNS_RED_COLOR!$VNS_RESET_COLOR - %s\\n" "$1" 1>&2 exit "$2" } +vns_report () { + printf "%s\n" "$*" +} + vns_checkDeps (){ # checkDeps @@ -45,7 +48,7 @@ vns_checkDeps (){ readonly VNS_DEPS=("vim" "gpg2" "tree" "git") for DEP in "${VNS_DEPS[@]}"; do - if test ! -e "$(which "$DEP" 2>/dev/null)"; then + if test ! -e "$(command -v "$DEP" 2>/dev/null)"; then printf "%s " "$DEP" fi done @@ -79,13 +82,13 @@ vns_init () { # initStore # Prepares $VNS_STORE for use - if [ -d "$VNS_STORE/.git" ]; then + if [ -d "$VNS_STORE/.vns_git" ]; then vns_raise "Store already initialized" 2; fi mkdir -p "$VNS_STORE" cd "$VNS_STORE" || exit - git init >/dev/null + vns_git init >/dev/null } @@ -97,10 +100,10 @@ vns_printHelp (){ printf "%s" "usage: vns [-cedlp] " printf "\\n%s" " vns -I" printf "\\n%s" " vns -h" - printf "\\n%s" " vns git ..." + printf "\\n%s" " vns vns_git ..." printf "\\n" printf "\\n%s" " -c : Create note" - printf "\\n%s" " -d : Delete note" + printf "\\n%s" " -d : Delete note(s)" printf "\\n%s" " -e : Open note for editing" printf "\\n%s" " -h : Display this message" printf "\\n%s" " -i : import file as note" @@ -108,6 +111,7 @@ vns_printHelp (){ printf "\\n%s" " -l : List all notes in " printf "\\n%s" " -m : Merge two or more notes" printf "\\n%s" " -p : Print note to console" + printf "\\n%s" " -r : Rename/move a note" printf "\\n\\n" } @@ -144,21 +148,24 @@ vns_rm () { local -r VNS_BLUE_COLOR='\033[0;34m' local -r VNS_RESET_COLOR='\033[0m' - - # Verify $1 is bound - if [ -z "${*:1:1}" ]; then vns_raise "Insufficient arguments" 30; fi - - # Verify the note exists - if [ ! -r "$VNS_STORE/$1.gpg" ]; then - vns_raise "Note does not exist" 31; - 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" "$VNS_PRODUCT" - printf "$VNS_BLUE_COLOR!$VNS_RESET_COLOR - %s\\n" "Deleted $VNS_STORE/$1" + printf "%s\\n\\n" "$VNS_PRODUCT" + while [ "$#" -gt 0 ]; do + # Verify $1 is bound + if [ -z "${*:1:1}" ]; then vns_raise "Insufficient arguments" 30; fi + + # Verify the note exists + if [ ! -r "$VNS_STORE/$1.gpg" ]; then + vns_raise "Note does not exist" 31; + fi + # Delete the Note + vns_git rm "$VNS_STORE/$1.gpg" > /dev/null + vns_git commit -m "Deleted $1" > /dev/null + + # Report success + printf "$VNS_BLUE_COLOR!$VNS_RESET_COLOR - %s\\n" "Deleted $VNS_STORE/$1" + + shift + done } @@ -170,28 +177,30 @@ vns_create () { local -r VNS_RED_COLOR='\033[0;31m' local -r VNS_RESET_COLOR='\033[0m' - # Verify $1 is bound - if [ -z "${*:1:1}" ]; then vns_raise "Insufficient arguments" 40; fi - + if [ -z "${*:1:1}" ]; then + printf "usage: %s %s\n" "$(basename "$0")" "-c [notebook/section/](name)" + return + fi + # Refuse to overwrite a note - if [ -r "$VNS_STORE/$1.gpg" ]; then vns_raise "Note already exists" 41; fi - + if [ -r "$VNS_STORE/$1.gpg" ]; then vns_raise "Note already exists" 41; fi + # If the note belongs to a new notebook, create the notebook - if [ ! -d "$(dirname "$1")" ]; then mkdir -p "$VNS_STORE/$(dirname "$1")"; fi - + if [ ! -d "$(dirname "$1")" ]; then mkdir -p "$VNS_STORE/$(dirname "$1")"; fi + # Create-Edit the note - vim "$VNS_STORE/$1.gpg" - + vim "$VNS_STORE/$1.gpg" + # Warn the user if the note failed to encrypt - if ! grep "PGP" <<< "$(file "$VNS_STORE/$1.gpg")" > /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." - fi + if ! file "$VNS_STORE/$1.gpg" | grep "PGP" -qs; then + printf "$VNS_RED_COLOR!$VNS_RESET_COLOR - %s\\n %s\\n"\ + "The created note was not encrypted."\ + "Check your vim-gnupg setup." + fi - # Update Git - git add "$VNS_STORE/$1.gpg" > /dev/null - git commit -m "Added $1" > /dev/null + # Update vns_git + vns_git add "$VNS_STORE/$1.gpg" > /dev/null + vns_git commit -m "Added $1" > /dev/null } @@ -209,9 +218,9 @@ vns_edit () { # Edit the specified note vim "$VNS_STORE/$1.gpg" - # Update Git - git add "$VNS_STORE/$1.gpg" > /dev/null - git commit -m "Edited $1" > /dev/null + # Update vns_git + vns_git add "$VNS_STORE/$1.gpg" > /dev/null + vns_git commit -m "Edited $1" > /dev/null } vns_import () { @@ -219,21 +228,20 @@ vns_import () { # import (src) (dest) # If src is the path to a file, and dest is a valid note name, # import src dest copies an encrypted version of src to the note store + pwd + if [ "$#" -lt 2 ]; then + printf "usage: %s %s\n" "$(basename "$0")" "-i (source) (destination)" + return + fi - if [ -z "${*:1:1}" ]; then - vns_raise "No source file specified" 90 - - elif [ -z "${*:2:2}" ]; then - vns_raise "No destination name specified" 91 - - elif [ ! -f "$1" ]; then + if [ ! -f "$1" ]; then vns_raise "Cannot read $1" 92 elif [ -f "$VNS_STORE/$2" ]; then printf "%s" "Note already exists. Overwrite? (Y/N) " local response; read -r response case "$response" in - Yy) + Y|y) rm "$VNS_STORE/$2";; *) vns_raise "User declined overwrite" 0;; @@ -245,9 +253,9 @@ vns_import () { gpg2 -r "$gpg_key" -o "$VNS_STORE/$2.gpg" -e "$1" - git add "$VNS_STORE/$2.gpg" - git commit -m "Imported file $1 as $2" - + vns_git add "$VNS_STORE/$2.gpg" + vns_git commit -m "Imported file $1 as $2" + } vns_print () { @@ -272,7 +280,7 @@ vns_mv () { if [ ! -r "$VNS_STORE/$1.gpg" ]; then vns_raise "Cannot read $1" 71; fi if [ -r "$VNS_STORE/$2.gpg" ]; then vns_raise "Note $2 already exists" 72; fi - git mv "$VNS_STORE/$1.gpg" "$VNS_STORE/$2.gpg" + vns_git mv "$VNS_STORE/$1.gpg" "$VNS_STORE/$2.gpg" } @@ -282,50 +290,66 @@ vns_merge () { # If notes[] is an array of note names and output is a new note name, # merge (output) (notes[]) concatenates notes[] into output. - if [ -z "${*:1}" ]; then vns_raise "No output specified" 81; fi - if [ -z "${*:2}" ]; then vns_raise "No inputs specified" 84; fi + if [ "$#" -lt 2 ]; then + printf "usage: %s %s\n" "$(basename "$0")" "-m (output) (notes...)" + return + fi + if [ -r "$VNS_STORE/$1.gpg" ]; then vns_raise "Output file already exists." 82; fi - - # Make output file if [ ! -r "$VNS_STORE/$2.gpg" ]; then vns_raise "Could not read $2" 83; fi - cp "$VNS_STORE/$2.gpg" "$VNS_STORE/$1.gpg" + local -r GPG_RECIP="$(gpg --list-only -v -d "$VNS_STORE/$2.gpg" 2>&1 | grep -oP "(?<=public key is ).*")" - local -r GPG_RECIP="$(gpg --list-only -v -d "$VNS_STORE/$1.gpg" 2>&1 | cut -f 5 -d " ")" + vns_gpgcat () { + for note in "$@"; do + if [ ! -r "$VNS_STORE/$note.gpg" ]; then + rm "$VNS_STORE/$1.gpg" + vns_raise "Could not read $note" 83; + fi + + printf "File: %s\n" "$note" + gpg2 --batch -d "$VNS_STORE/$note.gpg" + printf "\n" + done + } - for note in "${@:3}"; do - if [ ! -r "$VNS_STORE/$note.gpg" ]; then - rm "$VNS_STORE/$1.gpg" - vns_raise "Could not read $note" 83; - fi - - gpg2 --batch --yes -r "$GPG_RECIP" -o "$VNS_STORE/$1.gpg" -e <<< "$(gpg2 -d "$VNS_STORE/$1.gpg") $(gpg2 -d "$VNS_STORE/$note.gpg")" - done - - for note in "${@:2}"; do - git rm "$VNS_STORE/$note.gpg" - done + vns_gpgcat "${@:2}" | gpg2 --batch --yes -r "$GPG_RECIP" -o "$VNS_STORE/$1.gpg" -e + + vns_git add "$VNS_STORE/$1.gpg" - git add "$VNS_STORE/$1.gpg" + printf "%s" "Remove old notes? (y/N) " + local response; read -r response + case "$response" in + Y|y) + for note in "${@:2}"; do + vns_git rm "$VNS_STORE/$note.gpg" + done;; + esac - git commit -m "merged files ${*:2} into $1" + vns_git commit -m "merged files ${*:2} into $1" + vns_report "Successfully merged files ${*:2} into $1" } vns_duplicate () { - if [ -z "${*:1:1}" ]; then - vns_raise "No source note specified" 100 - elif [ -z "${*:2:2}" ]; then - vns_raise "No destination name specified" 101 + if [ "$#" -lt 2 ]; then + vns_report "usage: $(basename "$0") -u (source) (destination)" + return + fi + #if [ -z "${*:1:1}" ]; then + # vns_raise "No source note specified" 100 +# + # elif [ -z "${*:2:2}" ]; then + # vns_raise "No destination name specified" 101 - elif [ ! -f "$VNS_STORE/$1" ]; then + if [ ! -f "$VNS_STORE/$1.gpg" ]; then vns_raise "Cannot read $1" 102 - elif [ -f "$VNS_STORE/$2" ]; then + elif [ -f "$VNS_STORE/$2.gpg" ]; then printf "%s" "Note already exists. Overwrite? (Y/N) " local response; read -r response case "$response" in - Yy) - rm "$VNS_STORE/$2";; + Y|y) + rm "$VNS_STORE/$2.gpg";; *) vns_raise "User declined overwrite" 0;; esac @@ -333,18 +357,21 @@ vns_duplicate () { cp "$VNS_STORE/$1.gpg" "$VNS_STORE/$2.gpg" - git add "$VNS_STORE/$2" + vns_git add "$VNS_STORE/$2.gpg" } + +vns_git () { + cd "$VNS_STORE" || _raise "FIXME" + git "$@" +} + 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 @@ -354,13 +381,14 @@ vns () { ["-h"]="vns_printHelp" ["-I"]="vns_init"\ ["-i"]="vns_import" ["-m"]="vns_merge"\ ["-p"]="vns_print" ["-r"]="vns_mv"\ - ["-u"]="vns_duplicate" ["git"]="git" ) + ["-u"]="vns_duplicate" ["git"]="vns_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