diff --git a/README.md b/README.md index 8ed4e9e..a7e0cdf 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,38 @@ ![Screenshot](https://i.imgur.com/HjUO133.png) +## You're on the v2 development branch! +Notice: this branch is unstable and likely to change. Here's the v2 roadmap: + +- [x] add "focus mode" to keep track of the task you're currently working on +- [x] remove "later" / "backlog" feature that no one used +- [x] remove cringey motivation / demotivation / headline +- [x] maybe: add new motivation? +- [ ] ~~maybe: add time tracking? It's almost for free with the inclusion of the start/stop mechanism~~ +- [x] remove instant creation of non-existant tasks with "done" +- [x] read EDITOR variable, default to vi +- [x] add GuMo syntax to Feierabend +- [x] refactor entire codebase, make shellcheck report _nothing_ +- [ ] fix remaining shellcheck todos +- [ ] clean up other youth sins +- [ ] add better comments, remove bad comments +- [x] rename y.sh to y +- [ ] move things to proper directories (~/.local/bin, ~/.config/something?) +- [x] fix vanish/rm +- [ ] fix behaviour of deprioritizing (make callable without !) +- [ ] rename branch to main +- [ ] new screenshot +- [ ] fix rm/vanish completion (borken) +- [ ] make installable to any directory, with symlink from ~/.local/bin +- [ ] eliminate the need for BASEDIR +### setup.sh +- [ ] check if .local/bin exists on the path find a way to install if it doesn't (either create and add to PATH, or add ~/y to path) +- [ ] fail if things go wrong, don't write completion.sh to bashrc several times or without BASEDIR +- [ ] prompt for existing data repo, clone it automatically +- [ ] add color +- [ ] auto-create 'tomorrow' after cloning data repo because it's never committed + + ## Features + Ask yourself: "y the hell am I doing this?" with every new task + Semi-functional bash completion @@ -21,14 +53,11 @@ ## Usage + `y` -> show all tasks -+ `y do (today|tomorrow|later) Fix printer` -> Create new task, defaults to 'today', or move to today if it exists tomorrow or later ++ `y do (today|tomorrow) Fix printer` -> Create new task, defaults to 'today', or move to today if it exists tomorrow + `y done Fix printer` -> mark task as done + `y do Fix printer` (if task already exists) -> open task in Vim to add notes (absolutely not compatible with any other editor, nu-uh, sorry) (not sorry) + `y procrastinate Fix printer` -> move task to tomorrow -+ `y superprocrastinate Fix printer` -> move task to backlog + `y prioritize Fix printer` -> toggle mark task as important - -+ `y later` -> take a look at your backlog + `y feierabend` -> done for the day ## Setup diff --git a/completion.sh b/completion.sh index 8abde2c..6bdf98a 100644 --- a/completion.sh +++ b/completion.sh @@ -1,14 +1,11 @@ -#!/bin/bash -# i have no idea what i'm doing - _y() { local cur prev opts COMREPLY=() cur="${COMP_WORDS[COMP_CWORD]}" prev="${COMP_WORDS[COMP_CWORD-1]}" - opts="do done procrastinate proc superprocrastinate prio prioritize vanish rm later feierabend" + opts="do done procrastinate proc prio prioritize vanish rm feierabend start stop" case "${prev}" in - done|procrastinate|superprocrastinate|proc|prio|prioritize) + done|procrastinate|proc|start) IFS=$'\n' tmp=( $(compgen -W "$(ls ~/y/data/today)" -- "${COMP_WORDS[$COMP_CWORD]}" )) COMPREPLY=( "${tmp[@]// /\ }" ) return 0 @@ -18,8 +15,51 @@ _y() { COMPREPLY=( "${tmp[@]// /\ }" ) return 0 ;; - vanish) # extremely ghetto - opts="today tomorrow later" + + prio|prioritize) + # simplified: iterate filenames, strip leading "! " into 's', match prefix, and push appropriate completion + local match_cur="$cur" + local mode=0 # 0=return original, 1=return with leading "! ", 2=return stripped only (prev == '!') + if [[ "${COMP_WORDS[COMP_CWORD-1]}" == '!' ]]; then + mode=2 + match_cur="$cur" + elif [[ "$cur" == '!'* ]]; then + # user typed bang in same word: remove leading '!' and optional space + mode=1 + match_cur="${cur#\!}" + match_cur="${match_cur# }" + else + mode=0 + match_cur="$cur" + fi + + # iterate files and match stripped names by prefix + local f s out + while IFS= read -r f; do + [[ -z "$f" ]] && continue + if [[ "$f" == '! '* ]]; then + s="${f#\! }" + else + s="$f" + fi + # prefix match + if [[ "$s" == "$match_cur"* ]]; then + if [[ $mode -eq 1 ]]; then + out="! ${s}" + elif [[ $mode -eq 2 ]]; then + out="${s}" + else + out="${f}" + fi + COMPREPLY+=( "$out" ) + fi + done < <(ls -1 ~/y/data/today 2>/dev/null) + + return 0 + ;; + + vanish|rm) # extremely ghetto + opts="today tomorrow" case "${prev}" in today) IFS=$'\n' tmp=( $(compgen -W "$(ls ~/y/data/today)" -- "${COMP_WORDS[$COMP_CWORD]}" )) diff --git a/setup-legacy.sh b/setup-legacy.sh new file mode 100755 index 0000000..548abf7 --- /dev/null +++ b/setup-legacy.sh @@ -0,0 +1,67 @@ +#!/bin/bash + +BASEDIR=~/y +DATADIR=$BASEDIR/data/ + +printf "Creating nocolor symlink... " +if [ ! -h "$BASEDIR/y-nocolor.sh" ]; then + ln -s y.sh y-nocolor.sh + printf "Successful.\n" +else + printf "Symlink already exists!\n" +fi + +echo "Removing old stuff from .bashrc... " +sed -i '/alias y=/d' ~/.bashrc +sed -i '/y\/completion.sh/d' ~/.bashrc +# todo: feedback + +printf "Writing new aliases to .bashrc... " +if echo "alias y='$BASEDIR/y.sh'" >> ~/.bashrc; then + printf "Successful.\n" +else + printf "Error!\n" +fi + +printf "Writing completion stuff to .bashrc... " +if echo "source $BASEDIR/completion.sh" >> ~/.bashrc; then + printf "Successful.\n" +else + printf "Error!\n" +fi + +read -rp "Do you have an existing y data directory, e.g. in a Git repo? (yes/no) " yn +case $yn in + [Yy]* ) echo "Please manually copy/clone your data directory now." # to do: automatically clone if repo link is inserted + ;; + + * ) echo "A local Git repository will be initialized. If you want, set a remote." + + printf "Creating data directory... " + if [ ! -d "$DATADIR" ]; then + mkdir "$DATADIR" + printf "Successful.\n" # naja... + else + printf "Directory already exists!\n" + fi + + cd "$DATADIR" || exit 1 + + printf "Creating daily directories...\n" + for d in 'today' 'tomorrow' 'done' 'archive' 'started'; do + if ! [[ -d "$d" ]]; then + mkdir "$d" + printf " Directory '$d' created.\n" + else + printf " Directory '$d' already exists!\n" + + fi + done + git init + cd "$BASEDIR" || exit 1 + ;; +esac + +echo "Please run 'source ~/.bashrc' to enable bash completion (or start a new shell, or log out and back in)" +echo "Done." +exit diff --git a/setup.sh b/setup.sh index 23b0f59..acec86e 100755 --- a/setup.sh +++ b/setup.sh @@ -1,38 +1,29 @@ #!/bin/bash -BASEDIR=~/y -DATADIR=$BASEDIR/data/ +DATADIR="$HOME/.local/share/y" + +printf "Copying binary to ~/.local/bin... " +# TODO check if already present etc +cp ./y "$HOME/.local/bin/y" +printf "Successful.\n" printf "Creating nocolor symlink... " -if [ ! -h "$BASEDIR/y-nocolor.sh" ]; then - ln -s y.sh y-nocolor.sh +if [ ! -h "$HOME/.local/bin/y-nocolor" ]; then + ln -s "$HOME/.local/bin/y" "$HOME/.local/bin/y-nocolor" printf "Successful.\n" else printf "Symlink already exists!\n" fi -echo "Removing old stuff from .bashrc... " -sed -i '/alias y=/d' ~/.bashrc -sed -i '/y\/completion.sh/d' ~/.bashrc -# todo: feedback - -printf "Writing new aliases to .bashrc... " -echo "alias y='$BASEDIR/y.sh'" >> ~/.bashrc -if [ $? -eq 0 ]; then - printf "Successful.\n" -else - printf "Error!\n" -fi - +# TODO: can this go somewhere else? printf "Writing completion stuff to .bashrc... " -echo "source $BASEDIR/completion.sh" >> ~/.bashrc -if [ $? -eq 0 ]; then +if echo "source $BASEDIR/completion.sh" >> ~/.bashrc; then printf "Successful.\n" else printf "Error!\n" fi -read -p "Do you have an existing y data directory, e.g. in a Git repo? (yes/no) " yn +read -rp "Do you have an existing y data directory, e.g. in a Git repo? (yes/no) " yn case $yn in [Yy]* ) echo "Please manually copy/clone your data directory now." # to do: automatically clone if repo link is inserted ;; @@ -47,10 +38,10 @@ case $yn in printf "Directory already exists!\n" fi - cd "$DATADIR" + cd "$DATADIR" || exit 1 printf "Creating daily directories...\n" - for d in today tomorrow later done archive; do + for d in 'today' 'tomorrow' 'done' 'archive' 'started'; do if ! [[ -d "$d" ]]; then mkdir "$d" printf " Directory '$d' created.\n" @@ -60,7 +51,7 @@ case $yn in fi done git init - cd "$BASEDIR" + cd "$BASEDIR" || exit 1 ;; esac diff --git a/y b/y new file mode 100755 index 0000000..e1e39d9 --- /dev/null +++ b/y @@ -0,0 +1,394 @@ +#!/bin/bash + +# find the data directory: new and legacy +for dir in "$HOME/.local/share/y" "$HOME/y/data"; do + if [ -d "$dir" ]; then + DATADIR="$dir" + # TODO log as debug + #echo "Found datadir: $dir" + break + fi +done +if [ -z "$DATADIR" ]; then + echo "No data directory could be found! Aborting." + exit 1 +fi + +DOLLARNULL=$(echo "$0" | sed 's/.*\///') +if [[ ! "$DOLLARNULL" == *nocolor* ]]; then + + RED='\033[0;31m' + GREEN='\033[0;32m' + YELLOW='\033[1;33m' + BLUE='\033[1;34m' + MAGENTA='\033[1;35m' + BOLD='\033[1m' + NC='\033[0m' # No Color +fi + +print_tasks() { + if [[ ! -d "$DATADIR/$1" ]]; then + echo "Directory '$1' not found! Exiting." + exit 1 + fi + cd "$DATADIR"/"$1" || exit 1 + for f in *; do + NAME=$f + COMMENTSTRING="" + if [[ ! -d $f ]]; then + if [[ $NAME == "! "* ]]; then + NAME=$(echo "$NAME" | cut -c3-) + OUTPUTSTRING=$(printf "%s%-10s${RED}! ${NC}%s\n" "$3" "$2" "$NAME") + else + OUTPUTSTRING=$(printf "%s%-12s${NC}%s\n" "$3" "$2" "$NAME") + fi + # print the first line of a file, but not for 'done' tasks + if [[ -s $f ]] && [[ $1 != "done" ]]; then + COMMENTSTRING=$(printf "%15s ↳ $(head -1 "$f")") + fi + fi + echo -e "$OUTPUTSTRING" + if [ -n "$COMMENTSTRING" ]; then echo -e "$COMMENTSTRING"; fi + done +} + +add_task() { + DAY="$1" + shift + TASK="$*" + if _check_if_task_exists "$DAY" "$TASK"; then # open in editor if task already exists + if [[ -z $EDITOR ]]; then + export EDITOR=vi + fi + echo "Task '$TASK' exists, opening in $EDITOR..." + $EDITOR "$DATADIR"/"$DAY"/"$TASK" + exit 0 + fi + if [[ $DAY == "today" ]] && _check_if_task_exists 'tomorrow' "$TASK"; then # if tasks exists in tomorrow, move to today + echo "Task exists tomorrow - moving it to today" + mv "$DATADIR"/tomorrow/"$TASK" "$DATADIR"/today/"$TASK" + fi + # input validation should be good enough... + if [[ "$TASK" =~ ^\. ]] || [[ "$TASK" =~ [\*\/\;] ]]; then + echo "Error: a task name can not start with a . or contain any of the following characters: * / ;. Exiting." + exit 1 + fi + touch "$DATADIR"/"$DAY"/"$TASK" # create task + echo -e "'$TASK' added for ${GREEN}$DAY!${NC}" + } + +# helper functions, wow! +_check_if_task_started() { + if [[ ! "$(find "$DATADIR/started" -maxdepth 1 -type f)" ]]; then + return 1 + else + return 0 + fi + } + +_check_if_task_exists() { + # $1 is the day, rest is task name + day_to_check="$1" + shift + task_to_check="$*" + + if [[ -e "$DATADIR"/"$day_to_check"/"$task_to_check" ]]; then + return 0 + else + return 1 + fi +} + +_error_task_doesnt_exist() { + if [ -z "$1" ]; then + echo -e "${RED}Error${NC}: task doesn't exist!" + else + echo -e "${RED}Error${NC}: task '$*' doesn't exist!" + fi + exit 1 +} + +_parse_day_and_add_task() { + case "$2" in + today|tomorrow) + DAY=$2 + shift; shift + add_task "$DAY" "$@" + exit 0 + ;; + + "") + echo "Error: no task name given" + show_usage + exit 1 + ;; + *) + DAY=today + shift + add_task $DAY "$@" + exit 0 + ;; + esac + +} + +prioritize() { + # we're given a task starting with '! ', assuming we want to deprioritize + if [[ "$TASK" == "! "* ]] ; then + if [[ -e "$DATADIR/today/$TASK" ]]; then + mv "$DATADIR"/today/"$TASK" "$DATADIR"/today/"$(echo "$TASK" | cut -c3-)" + echo "De-prioritized task '$(echo "$TASK" | cut -c3-)'." + else + echo -e "${RED}Error${NC}: task '$*' doesn't exist!" + fi + # if no !, check if we have a matching prioritized task to deprioritize + elif [[ -e "$DATADIR/today/! ${TASK}" ]] ; then + mv "${DATADIR}/today/! ${TASK}" "${DATADIR}/today/${TASK}" + echo "De-prioritized task ${TASK}" + # if not, prioritize + else + mv "$DATADIR"/today/"$TASK" "$DATADIR"/today/!\ "$TASK" + echo "Prioritized task '! $TASK'." + fi +} + +next_day() { + # $1 for "today" or "yesterday" + cd "$DATADIR"/done || exit 1 + if [[ "$1" == "yesterday" ]]; then + DATE_OF_WORKDAY="$(date --date yesterday --iso-8601)" + else + DATE_OF_WORKDAY="$(date --iso-8601)" + fi + if [[ ! -d "$DATADIR"/archive/"$DATE_OF_WORKDAY" ]]; then + mkdir "$DATADIR"/archive/"$DATE_OF_WORKDAY" + fi + if [[ ! "$(find . -maxdepth 1 -type f)" ]]; then + echo "u did absolutely nothing $1." + else + echo -e "${GREEN}here's what u did ${1}${NC}" + printf \\n # show all files from 'done' + for f in *; do + if ! [[ -d $f ]]; then + for (( c=0; c < ${#f}; c++ )); do # super flashy magic effect thingy + # TODO shellcheck + # shellcheck disable=SC2059 + printf "${f:$c:1}" + sleep 0.05 + done + printf \\n + mv "$f" "$DATADIR"/archive/"$DATE_OF_WORKDAY" + sleep 0.5s + fi + done + echo -e "${YELLOW}Well done! 😊${NC}" + fi + find "$DATADIR/tomorrow" -type f ! -name ".*" -exec mv "{}" "$DATADIR/today/" \; 2> /dev/null # move task from tomorrow to today + + cd "$DATADIR" || exit 1 + COMMITMESSAGE="End of day $(date '+%F %T')" + echo "======== Begin Git log for commit '$COMMITMESSAGE' ========" >> "${DATADIR}/git.log" + git add --all >> "${DATADIR}/git.log" + printf "+ git commit... " + COMMITOUTPUT=$(git commit -m "$COMMITMESSAGE") + # TODO + # shellcheck disable=SC2181 + if [[ $? -eq 0 ]]; then + printf "${GREEN}%12s${NC}\n" "Successful" + echo "$COMMITOUTPUT" >> "${DATADIR}/git.log" + if [[ $(git remote show) ]] ; then + printf "+ git push... " + PUSHOUTPUT=$(git push -u origin 2>&1) + if [[ $? -eq 0 ]]; then + printf "${GREEN}%14s${NC}\n" "Successful" + echo "$COMMITOUTPUT" >> "${DATADIR}/git.log" + else + printf "${RED}%10s${NC}\n" "Failed" + echo "$PUSHOUTPUT" >> "${DATADIR}/git.log" + echo "$PUSHOUTPUT" + fi + fi + + else + printf "${RED}%8s${NC}\n" "Failed" + echo "$COMMITOUTPUT" >> "${DATADIR}/git.log" + echo "$COMMITOUTPUT" + fi + echo "========== End Git log for commit '$COMMITMESSAGE' ========" >> "${DATADIR}/git.log" + printf \\n + if [[ "$1" == "yesterday" ]]; then + echo "Have a great day! 🌞" + else + echo "Remember to stop your timetracking." + echo "Good night! 🌙" + fi +} + +procrastinate() { + _check_if_task_exists 'today' "$TASK" || _error_task_doesnt_exist "$TASK" + if ! _check_if_task_exists 'tomorrow' "$TASK"; then + mv "$DATADIR"/today/"$TASK" "$DATADIR"/tomorrow/"$TASK" + echo -e "'$TASK' moved to ${BLUE}tomorrow${NC}." + else + echo "'$TASK' already exists tomorrow!" + fi +} + +clean() { + read -rp "Are you SURE you want to irrecoverably delete ALL of your entries? (yes/no) " cleanyn + case $cleanyn in + [Yy]*) for i in 'today' 'tomorrow' 'done' 'archive' 'started'; do rm -rf "${DATADIR:?}"/"${i}"/*; done + rm "${DATADIR}/git.log" + echo "All entries deleted." + ;; + *) echo "Aborting." + exit 1 + ;; + esac +} + +show_usage() { + echo "y - the existentialist task manager" + echo "Usage: y -> show all tasks" + echo " y do (today|tomorrow) Fix printer -> Create new task, defaults to 'today'." + echo " y done Fix printer -> mark task as done" + echo " y do Fix printer (if task already exists) -> open task in Vim to add notes" + echo " y procrastinate Fix printer -> move task to tomorrow" + echo " y prioritize Fix printer -> toggle mark task as important" + echo " y vanish today|tomorrow Fix printer -> delete task" + echo " y gumo -> starting the day" + echo " y feierabend -> done for the day" +} + +# main script starts here! +# first: check if work has been started on anything / "focus mode" +if _check_if_task_started; then + if [ -z "$1" ]; then + echo -e "${BOLD}Focus!${NC}" + print_tasks started "Currently working on: " "$MAGENTA" + exit 0 + else + case "$1" in + do) + _parse_day_and_add_task $* + ;; + done) + TASK=$(basename "$(find data/started/ -type f)") + mv "${DATADIR}/started/${TASK}" "${DATADIR}/done/" + echo "Done: $TASK". + exit 0 + ;; + stop) + mv "$DATADIR"/started/* "$DATADIR"/today/ + echo "Stopped working on your task." + exit 0 + ;; + *) + echo "Not a valid command." + echo "You're currently working on a task. Use \`y stop\` to stop work on it." + exit 1 + esac + fi +fi + +# now for "normal mode" where no task has been started +if [ -z "$1" ]; then # if no arguments given, print all tasks today and tomorrow + # use the following syntax: directory name, day in "readable case" and name of color variable + print_tasks 'today' 'Today:' "$GREEN" + print_tasks 'tomorrow' 'Tomorrow:' "$BLUE" + print_tasks 'done' 'Done:' "$YELLOW" + exit 0 +fi + +### "normal" mode without any started tasks +case "$1" in + do) + _parse_day_and_add_task $* + ;; + + done) + if [ -z "$2" ]; then + echo "Error: no task name given" + show_usage + exit 1 + fi + shift; TASK="$*" + _check_if_task_exists 'today' "$TASK" || _error_task_doesnt_exist "$TASK" + mv "$DATADIR"/today/"$TASK" "$DATADIR"/done/ + echo "Done: $TASK." + ;; + + start) + if _check_if_task_started; then + echo "You're already working on a task!" + exit 1 + fi + if [ -z "$2" ]; then + echo "Error: no task name given" + show_usage + exit 1 + fi + shift; TASK="$*" + # create and start task if it doesn't exist + _check_if_task_exists 'today' "$TASK" || add_task 'today' "$TASK" + + mv "$DATADIR"/today/"$TASK" "$DATADIR"/started/ + echo "Started work on task $TASK." + ;; + prioritize|prio) + shift; TASK="$*" + prioritize + exit 0 + ;; + procrastinate|proc) + shift; TASK="$*" + procrastinate + exit 0 + ;; + feierabend) + next_day today + exit 0 + ;; + gumo) + next_day yesterday + exit 0 + ;; + clean) + clean + exit 0 + ;; + pull) + cd "$DATADIR" || exit 1 + echo "Pulling fresh data from $(git remote get-url --push origin)..." + git pull + exit 0 + ;; + vanish|rm) + if [[ "$2" == "today" || "$2" == "tomorrow" ]]; then + DAY="$2" + shift; shift + else + DAY="today" + shift + fi + TASK="$*" + cd "$DATADIR"/"$DAY" || exit 1 + + if rm "$TASK"; then + echo -e "Task '$TASK' has vanished." + exit 0 + else + echo "Removing task failed!" + exit 1 + fi + ;; + --help|-h) + show_usage + exit 0 + ;; + + *) echo "Not a valid command." + show_usage + exit 1 + ;; +esac diff --git a/y.sh b/y.sh deleted file mode 100755 index 11514d2..0000000 --- a/y.sh +++ /dev/null @@ -1,345 +0,0 @@ -#!/bin/bash - -MOTIVATION=("u should be proud of urself" "u r da man, man" "u da best" "look at u go" "nice work, yay" "u amazinggggggg" "u did good, kid" "this shit is bananas, B-A-N-A-N-A-S!" "the best there ever was" "u the real mvp" "now go treat yoself") -DEMOTIVATION=("u lazy piece of shit" "weeeell done *slow clap*" "son i am disappoint" "lauch" "u suck" "all you had to do was follow the damn train!" "the fuck is wrong with you" "try harder, pal" "congratulations on your spectacular failure" "hope ur proud of urself") -HEADLINE=("Frisch ans Werk, Freund!" "Morgenstund hat Gold im Mund!" "Wer wagt, gewinnt!" "Müßiggang ist aller Laster Anfang!" "Wer wagt, gewinnt!" "Den Tüchtigen gehört die Welt!" "Gib jedem Tag die Chance, der produktivste deines Lebens zu werden!" "Ich arbeite gern für meinen Konzern!" "You gotta do what you gotta do 👍" "Wir haben uns alle lieb im Betrieb!" "Der frühe Vogel fängt den Wurm!" "Die schönste Zeit... ist die Arbeit!" "Frage nicht, was dein Arbeitsplatz für dich tun kann - frage, was du für deinen Arbeitsplatz tun kannst!" "Die schönste Musik? - Der Sound der Fabrik!") - -BASEDIR=~/y -DEFAULTDATADIR=$BASEDIR/data - -if [ -z $DATADIR ]; then - DATADIR="$DEFAULTDATADIR" -fi - -# echo "DEBUG: current DATADIR: $DATADIR" - -DOLLARNULL=$(echo "$0" | sed 's/.*\///') -if [[ ! "$DOLLARNULL" == *nocolor* ]]; then - - RED='\033[0;31m' - GREEN='\033[0;32m' - YELLOW='\033[1;33m' - BLUE='\033[1;34m' - BOLD='\033[1m' - NC='\033[0m' # No Color -fi - -print_tasks() { - if [[ ! -d "$DATADIR/$1" ]]; then - echo "Directory '$1' not found! Exiting." - exit 1 - fi - cd $DATADIR/$1 - for f in *; do - NAME=$f - COMMENTSTRING="" - if [[ ! -d $f ]]; then - if [[ $NAME == "! "* ]]; then - NAME=$(echo $NAME | cut -c3-) - OUTPUTSTRING=$(printf "%s%-10s${RED}! ${NC}%s\n" "$3" "$2" "$NAME") - else - OUTPUTSTRING=$(printf "%s%-12s${NC}%s\n" "$3" "$2" "$NAME") - fi - # print the first line of a file, but not for 'done' tasks - if [[ -s $f ]] && [[ $1 != "done" ]]; then - COMMENTSTRING=$(printf "%15s ↳ $(head -1 "$f")") - fi - fi - echo -e "$OUTPUTSTRING" - if [ ! -z "$COMMENTSTRING" ]; then echo -e "$COMMENTSTRING"; fi - done -} - -print_motivation() { - MOTIVOUT=${MOTIVATION[$(shuf -i 0-$((${#MOTIVATION[@]}-1)) -n 1)]} - printf \\n - echo -e ${YELLOW}$MOTIVOUT${NC} - printf \\n -} - -print_demotivation() { - DEMOTIVOUT=${DEMOTIVATION[$(shuf -i 0-$((${#DEMOTIVATION[@]}-1)) -n 1)]} - printf \\n - echo -e ${RED}$DEMOTIVOUT${NC} - printf \\n -} - -add_task() { - DAY="$1" - shift - TASK="$@" - if [[ -e $DATADIR/$DAY/"$TASK" ]]; then # open in editor if task already exists - echo "Task '$TASK' exists, opening in editor..." - vi $DATADIR/$DAY/"$TASK" - exit 0 - fi - for SOURCEDAY in "tomorrow" "later"; do - if [[ $DAY == "today" ]] && [[ -e $DATADIR/$SOURCEDAY/"$TASK" ]]; then # if tasks exists in tomorrow or later, move to today - echo "Task exists in $SOURCEDAY - moving it to today" - mv $DATADIR/$SOURCEDAY/"$TASK" $DATADIR/today/"$TASK" - fi - done - # experimental ghetto input validation - if [[ "$TASK" =~ ^\. ]] || [[ "$TASK" =~ [\*\/\;] ]]; then - echo "Error: a task name can not start with a . or contain any of the following characters: * / ;. Exiting." - exit 1 - fi - touch $DATADIR/$DAY/"$TASK" # create task - echo -e "'$TASK' added for ${GREEN}$DAY!${NC}" - } - -prioritize() { - if ! [[ -e $DATADIR/today/"$TASK" ]]; then - echo "No such task!" - exit 1 - else - if [[ "$TASK" == "! "* ]]; then - mv "$DATADIR/today/$TASK" "$DATADIR/today/$(echo $TASK | cut -c3-)" - echo "De-prioritized task '$(echo $TASK | cut -c3-)'." - exit 0 - else - mv "$DATADIR/today/$TASK" "$DATADIR/today/! $TASK" - echo "Prioritized task '! $TASK'." - exit - fi - fi -} - -feierabend() { - cd $DATADIR/done - TODAYSDATE=$(date --iso-8601) - if [[ ! -d $DATADIR/archive/$TODAYSDATE ]]; then - mkdir $DATADIR/archive/$TODAYSDATE - fi - if [[ ! $(find . -maxdepth 1 -type f) ]]; then - echo "u did absolutely nothing today." - print_demotivation - else - echo -e "${GREEN}here's what u did today${NC}" - printf \\n # show all files from 'done' - for f in *; do - if ! [[ -d $f ]]; then - for (( c=0; c < ${#f}; c++ )); do # super flashy magic effect thingy - printf "${f:$c:1}" - sleep 0.05 - done - printf \\n - mv "$f" $DATADIR/archive/$TODAYSDATE - sleep 0.5s - fi - done - print_motivation - fi - find "$DATADIR/tomorrow" -type f ! -name ".*" -exec mv "{}" "$DATADIR/today/" \; 2> /dev/null # move task from tomorrow to today - -# unfinished 'show task age' thing -# the idea is to mark all tasks as important that are older than a week. this could be done on feierabend. -# CURRTIME=$(date +%s) -# for f in $DATADIR/today/*; do -# if [[ ! "$f" == "! *" ]]; then -# CHANGETIME=$(stat -c %Y "$f") -# echo "last change: $CHANGETIME, now: $CURRTIME" -# fi -# done - - cd $DATADIR - COMMITMESSAGE="Feierabend $(date '+%F %T')" - echo "======== Begin Git log for commit '$COMMITMESSAGE' ========" >> $BASEDIR/git.log - git add --all >> $BASEDIR/git.log - printf "+ git commit... " - COMMITOUTPUT=$(git commit -m "$COMMITMESSAGE") - if [[ $? -eq 0 ]]; then - printf "${GREEN}%12s${NC}\n" "Successful" - echo "$COMMITOUTPUT" >> $BASEDIR/git.log - if [[ $(git remote show) ]] ; then - printf "+ git push... " - PUSHOUTPUT=$(git push -u origin master 2>&1) - if [[ $? -eq 0 ]]; then - printf "${GREEN}%14s${NC}\n" "Successful" - echo "$COMMITOUTPUT" >> $BASEDIR/git.log - else - printf "${RED}%10s${NC}\n" "Failed" - echo "$PUSHOUTPUT" >> $BASEDIR/git.log - echo "$PUSHOUTPUT" - fi - fi - - else - printf "${RED}%8s${NC}\n" "Failed" - echo "$COMMITOUTPUT" >> $BASEDIR/git.log - echo "$COMMITOUTPUT" - fi - echo "========== End Git log for commit '$COMMITMESSAGE' ========" >> $BASEDIR/git.log - printf \\n - echo "Remember to stop your timetracking." - echo "Good night!" -} - -procrastinate() { - SOURCEDAY="today" - TARGETDAY=$1 - if [[ ! -e $DATADIR/today/"$TASK" ]] && [[ -e $DATADIR/tomorrow/"$TASK" ]]; then # if task doesn't exist today but only tomorrow, move from tomorrow to later - SOURCEDAY="tomorrow" - TARGETDAY="later" - fi - if [[ -e $DATADIR/$SOURCEDAY/"$TASK" ]]; then - if [[ ! -e $DATADIR/$TARGETDAY/"$TASK" ]]; then - mv $DATADIR/$SOURCEDAY/"$TASK" $DATADIR/$TARGETDAY/"$TASK" - echo -e "'$TASK' procrastinated until ${BLUE}$TARGETDAY.${NC}" - print_demotivation - else - echo "'$TASK' already exists $TARGETDAY!" - fi - else - show_usage - fi - exit 0 - -} - -clean() { - read -p "Are you SURE you want to irrecoverably delete ALL of your entries? (yes/no) " cleanyn - case $cleanyn in - [Yy]*) for i in today tomorrow later done; do rm -rf "$DATADIR"/$i/*; done - rm $BASEDIR/git.log - echo "All entries deleted." - exit 0 - ;; - *) echo "Aborting." - exit 1 - ;; - esac -} - -show_usage() { - echo "y - the existentialist task manager" - echo "Usage: y -> show all tasks" - echo " y do (today|tomorrow|later]) Fix printer -> Create new task, defaults to 'today'." - echo " y done Fix printer -> mark task as done" - echo " y do Fix printer (if task already exists) -> open task in Vim to add notes" - echo " y procrastinate Fix printer -> move task to tomorrow" - echo " y superprocrastinate Fix printer -> move task to backlog" - echo " y prioritize Fix printer -> toggle mark task as important" - echo " y vanish today|tomorrow|later Fix printer -> delete task" - echo " y later -> take a look at your backlog" - echo " y feierabend -> done for the day" - exit 0 -} - -if [ -z $1 ]; then # if no arguments given, print all tasks today and tomorrow - # use the following syntax: directory name, day in "readable case" and name of color variable - HEADLINEOUT=${HEADLINE[$(shuf -i 0-$((${#HEADLINE[@]}-1)) -n 1)]} - echo -e ${BOLD}$HEADLINEOUT${NC} - print_tasks today Today: $GREEN - print_tasks tomorrow Tomorrow: $BLUE - print_tasks done Done: $YELLOW -# print_tasks later Later $RED # in case one wants that... - exit 0 -fi - -case "$1" in - do) - - case "$2" in - today|tomorrow|later) # parse day - DAY=$2 - shift; shift - add_task $DAY "$@" - exit 0 - ;; - - "") - echo "Error: no task name given" - show_usage - exit 1 - ;; - *) - DAY=today - shift - add_task $DAY "$@" - ;; - esac - ;; - - - done) - if [ -z "$2" ]; then - echo "Error: no task name given" - show_usage - exit 1 - fi - shift; TASK="$@" - if ! [[ -e $DATADIR/today/"$TASK" ]]; then - add_task today "$TASK" - fi - mv $DATADIR/today/"$TASK" $DATADIR/done/ - printf \\n - echo "Done: $TASK." - print_motivation - ;; - - prioritize|prio) # still janky and beta - shift; TASK="$@" - prioritize - exit 0 - ;; - procrastinate|proc) - shift; TASK="$@" - procrastinate tomorrow - exit 0 - ;; - superprocrastinate) - shift; TASK="$@" - procrastinate later - exit 0 - ;; - later) - print_tasks later Later: $RED - exit 0 - ;; - feierabend) - feierabend - exit 0 - ;; - clean) - clean - exit 0 - ;; - pull) - cd "$DATADIR" - echo "Pulling fresh data from $(git remote get-url --push origin)..." - git pull - exit 0 - ;; - vanish|rm) # unfinished - do not use - if [[ "$2" == "today" || "$2" == "tomorrow" || "$2" == "later" ]]; then - DAY="$2" - shift; shift - TASK="$@" - cd "$DATADIR"/"$DAY" - rm "$TASK" - if [[ $? -eq 0 ]]; then - echo -e "Task '$TASK' has vanished." - else # debug - echo "rm has returned non-zero" - fi - exit 0 - else - echo "nö" - exit 1 - fi - cd $DATADIR/today/ - rm "$@" - echo "harharhar" - exit 0 - ;; - --help|-h) - show_usage - exit 0 - ;; - - *) echo "Not a valid command." - show_usage - exit 1 - ;; -esac