A new project to make it easy to manage notes from the command line. This does more than jot and serves a different purpose. Initial commit.

This commit is contained in:
Storm Dragon
2019-07-12 19:09:13 -04:00
parent fadf9e7864
commit 2e1ce6d1c3

226
notestorm Executable file
View File

@@ -0,0 +1,226 @@
#!/bin/bash
# notestorm
# Description: Easily take and read notes from the CLI.
#
# Copyright 2019, F123 Consulting, <information@f123.org>
# Copyright 2019, Storm Dragon, <storm_dragon@linux-a11y.org>
#
# This is free software; you can redistribute it and/or modify it under the
# terms of the GNU General Public License as published by the Free
# Software Foundation; either version 3, or (at your option) any later
# version.
#
# This software is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this package; see the file COPYING. If not, write to the Free
# Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301, USA.
#
#--code--
# the gettext essentials
export TEXTDOMAIN=notestorm
export TEXTDOMAINDIR=/usr/share/locale
source gettext.sh
# Log writing function
log() {
# Usage: command | log for just stdout.
# Or command |& log for stderr and stdout.
while read -r line ; do
echo "$line" | tee -a "$logFile" &> /dev/null
done
}
# Log file name is ~/.cache/scriptname
logFile="${HOME}/.cache/${0##*/}"
# Functions section
infobox() {
# Returns: None
# Shows the provided message on the screen with no buttons.
local continue
dialog --infobox "$*" 10 80
read -n1 -t $messageTimeout continue
}
yesno() {
# Returns: Yes or No
# Args: Question to user.
# Called in if $(yesno) == "Yes"
# Or variable=$(yesno)
dialog --backtitle "$(gettext "Press 'Enter' for \"yes\" or 'Escape' for \"no\".")" --yesno "$*" 10 80 --stdout
if [[ $? -eq 0 ]]; then
echo "Yes"
else
echo "No"
fi
}
menulist() {
# Args: Tag, description.
# returns: selected tag
dialog --backtitle "$(gettext "Use the up and down arrow keys to find the option you want, then press enter to select it.")" \
--cancel-label "Exit" \
--extra-button \
--extra-label "Edit" \
--help-button \
--help-label "Delete" \
--ok-label "View" \
--no-tags \
--menu "$(gettext "Please select one")" 0 0 0 $@ --stdout
}
add_note() {
# Notes are named based on number of seconds since 1970.
# If the note exists it is incremented until the name is available.
local noteName=$(date '+%s')
while [ -f "${xdgPath}/notestorm/notes/${noteName}.md" ]; do
((noteName++))
done
$editor "${xdgPath}/notestorm/notes/${noteName}.md"
if [ -f "${xdgPath}/notestorm/notes/${noteName}.md" ]; then
infobox "Note added."
else
infobox "Note canceled."
fi
}
delete_note() {
local text="$(head -1 "$1")"
local answer="$(yesno "$(gettext "Really delete note starting with text") \"$text\"?")"
if [ "$answer" == "Yes" ]; then
rm -f "$1"
infobox "$(gettext "Note deleted.")"
else
infobox "$(gettext "Action canceled.")"
fi
}
display_note() {
markdown "$1" | eval "$pager"
}
edit_note() {
local oldMd5="$(md5sum "$1")"
$editor "$1"
local newMd5="$(md5sum "$1")"
if [ "$oldMd5" != "$newMd5" ]; then
infobox "$(gettext "Changes saved.")"
else
infobox "$(gettext "Changes discarded.")"
fi
}
# Configuration section
# Available arguments in both long and short versions stored in associative array.
declare -A argList=(
[n]="new")
# Make the args a continuous string.
short="${!argList[*]}"
short="${short// /}"
long="${argList[*]}"
long="${long// /}"
editor="${EDITOR:-nano}"
messageTimeout=${messageTimeout:-1}
# Set pager
if command -v w3m &> /dev/null ; then
pager="w3m -T text/html"
elif command -v elinks &> /dev/null ; then
pager="elinks -force-html"
elif command -v lynx &> /dev/null ; then
pager="lynx -force_html"
else
pager="${PAGER:-more}"
fi
xdgPath="${XDG_CONFIG_HOME:-$HOME/.config}"
#set up the notes directory
mkdir -p "${xdgPath}/notestorm/notes"
# Keep track of the number of arguments passed to the program.
argNum=$#
# Settings to improve accessibility of dialog.
export DIALOGOPTS='--insecure --no-lines --visit-items'
# Dialog custom configuration file
export DIALOGRC="${xdgPath}/notestorm/dialogrc"
# Generate dialogrc if it does not exist.
if ! [ -e "$DIALOGRC" ]; then
dialog --create-rc "$DIALOGRC"
# Add keybindings to dialogrc
echo >> "$DIALOGRC"
echo "# Edit keybinding" >> "$DIALOGRC"
echo "bindkey menu ~E EXTRA" >> "$DIALOGRC"
fi
# Code section
if ! options=$(getopt -o "$short" -l "$long" -n "notestorm" -- "$@"); then
gettext -e "Usage: notestorm launch interactive session.\n"
gettext -e -- "-n or --new add a new note without opening an interactive session.\n"
echo
gettext -e "You can use markdown syntax in notes.\n"
gettext -e "Notes are named numerically. they can be renamed and will still show up so long as they end with a .md extension.\n"
gettext "Notes are saved in "
echo "${xdgPath}/notestorm/notes"
exit 1
fi
eval set -- "$options"
while [ $# -gt 0 ]; do
case "$1" in
"-n"|"--new") add_note;;
esac
shift
done
# If there were args, the program was controled by those and we do not need the menu.
if [ $argNum -gt 0 ]; then
exit 0
fi
while [ "$action" != "exit" ]; do
# Get a list of notes
mapfile -t notes < <(find "$xdgPath/notestorm/notes" -type f -iname '*.md')
# Generate the note menu:
unset noteMenu
declare -a noteMenu
for i in "${notes[@]}" ; do
noteMenu+=("$i")
noteMenu+=("$(head -1 "${i}")")
done
# Create menu of actions and notes.
ifs="$IFS"
IFS=$'\n'
action="$(menulist \
"add_note" "$(gettext "New note")" \
"${noteMenu[@]}" \
"exit" "$(gettext "Exit")")"
dialogCode=$?
IFS="$ifs"
if [ -z "$action" ]; then
action="exit"
fi
# Run selected action
case "${action}" in
"add_note") add_note;;
"exit") exit 0;;
*)
case $dialogCode in
0) display_note "${action}";;
2) delete_note "${action#HELP }";;
3) edit_note "${action}";;
esac;;
esac
done
exit 0