From b249e237b6460a9c3014b3e2f722a3e8aab54065 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ensar=20Saraj=C4=8Di=C4=87?= Date: Sat, 12 Aug 2023 20:16:24 +0200 Subject: [PATCH] Add simple utility for time tracking --- symlinks/bin/t | 167 ++++++++++++++++++++++++ symlinks/config/fish/completions/t.fish | 28 ++++ 2 files changed, 195 insertions(+) create mode 100755 symlinks/bin/t create mode 100644 symlinks/config/fish/completions/t.fish diff --git a/symlinks/bin/t b/symlinks/bin/t new file mode 100755 index 0000000..dfbbb8f --- /dev/null +++ b/symlinks/bin/t @@ -0,0 +1,167 @@ +#!/usr/bin/env bash + +set -e + +. ~/.local/opt/script_utils/echo.sh + +usage () { + case $1 in + in) + usage_in; exit 0 ;; + out) + usage_out; exit 0 ;; + bal) + usage_bal; exit 0 ;; + esac + if [ ! -z "$1" ]; then + echo -e "Unknown command: $1 \n" + fi + echo "Basic time tracker." + echo "Generates input for ledger-cli time tracking" + echo -e "\nUsage: time COMMAND [options] [arguments] \n" + echo "Commands:" + echo " in - starts a new time entry" + echo " out - completes an old time entry" + echo " bal - outputs current timesheet" + echo "" + echo "Options:" + echo " -h --help - prints this help message (if one of commands is passed, prints help message for that command)" + echo " -v --verbose - enables verbose logging" + if [ ! -z "$1" ]; then + exit 1 + fi +} + +usage_in () { + echo "Time In" + echo "Starts a new time entry - requires a project" + echo -e "\nUsage: time in [options] [] \n" + echo "Arguments:" + echo " project - name of project tracking time to" + echo " comment - additional information - optional" + echo "" + echo "Options:" + echo " -h --help - prints this help message" + echo " -v --verbose - enables verbose logging" + echov "Examples:" + echov " > time in project:test" + echov "" + echov " > time in project:test parsing" +} + +usage_out () { + echo "Time Out" + echo "Stops an existing time entry - requires a project" + echo -e "\nUsage: time out [options] \n" + echo "Arguments:" + echo " project - name of project tracking time to" + echo "" + echo "Options:" + echo " -h --help - prints this help message" + echo " -v --verbose - enables verbose logging" + echov "Examples:" + echov " > time out project:test" +} + +usage_bal () { + echo "Time balance" + echo "Prints out current timesheet - takes in a project optionally" + echo -e "\nUsage: time bal [options] \n" + echo "Arguments:" + echo " project - name of project to get balance of" + echo "" + echo "Options:" + echo " -h --help - prints this help message" + echo " -v --verbose - enables verbose logging" + echov "Examples:" + echov " > time bal project:test" +} + +POSITIONAL=() +HELP=0 +VERBOSE=0 +while [[ $# -gt 0 ]]; do + key="$1" + + case $key in + -h|--help) + HELP=1 + shift # past argument + ;; + -v|--verbose) + VERBOSE=1 + shift # past argument + ;; + *) # unknown option + POSITIONAL+=("$1") # save it in an array for later + shift # past argument + ;; + esac +done + +COMMAND="${POSITIONAL[0]}" + +echov "Detected command: $COMMAND" + +if [ $HELP -eq 1 ]; then + usage $COMMAND + exit 0 +fi + +PROJECT="${POSITIONAL[1]}" +COMMENT="${POSITIONAL[2]}" + +echov "Project: $PROJECT" +echov "Comment: $COMMENT" + +if [ -z "$TIMESHEET_LEDGER_HOME" ]; then + echo "TIMESHEET_LEDGER_HOME variable not defined. It must point to a directory that hosts your main.journal as well as timesheets/ directory with yearly .journal files (e.g. timesheets/2023.journal)" + exit 1 +fi + +time_in () { + PROJECT=$1 + COMMENT=$2 + + LAST_ENTRY=$(grep "$PROJECT" "$TIMESHEET_LEDGER_HOME/timesheets/$(date +%Y).journal" | tail -1 | cut -f1 -d ' ') + if [ "$LAST_ENTRY" = "i" ]; then + echo "Timer for project $PROJECT was already started. Aborting..." + exit 1 + fi + echo "i $(date '+%Y-%m-%d %H:%M:%S') $PROJECT $COMMENT" >> "$TIMESHEET_LEDGER_HOME/timesheets/$(date +%Y).journal" +} + +time_out () { + PROJECT=$1 + + LAST_ENTRY=$(grep "$PROJECT" "$TIMESHEET_LEDGER_HOME/timesheets/$(date +%Y).journal" | tail -1 | cut -f1 -d ' ') + if [ -z "$LAST_ENTRY" ]; then + echo "Timer for project $PROJECT is not started. Aborting..." + exit 1 + fi + if [ "$LAST_ENTRY" = "O" ]; then + echo "Timer for project $PROJECT was already stopped. Aborting..." + exit 1 + fi + echo "O $(date '+%Y-%m-%d %H:%M:%S') $PROJECT" >> "$TIMESHEET_LEDGER_HOME/timesheets/$(date +%Y).journal" +} + +time_bal () { + PROJECT=$1 + + ledger -f "$TIMESHEET_LEDGER_HOME/main.journal" bal $1 +} + +case $COMMAND in + in) + time_in $PROJECT $COMMENT + ;; + out) + time_out $PROJECT + ;; + bal) + time_bal $PROJECT + ;; + *) + usage $COMMAND; exit 1 ;; +esac diff --git a/symlinks/config/fish/completions/t.fish b/symlinks/config/fish/completions/t.fish new file mode 100644 index 0000000..21169db --- /dev/null +++ b/symlinks/config/fish/completions/t.fish @@ -0,0 +1,28 @@ +function __fish-timesheets-available-projects + grep 'account Project:.*' "$TIMESHEET_LEDGER_HOME/config/02_accounts.dat" | cut -f2 -d ' ' +end + +function __fish-timesheets-existing-comments + ledger -f "$TIMESHEET_LEDGER_HOME/main.journal" payees ^Project +end + +function __fish_timesheets_arg_number -a number + set -l cmd (commandline -opc) + test (count $cmd) -eq $number +end + +complete -c t -x -l help -s h -d "print usage help" +complete -c t -x -l verbose -s v -d "verbose output" +complete -c t -x -n "__fish_use_subcommand" -a in -d "start tracking time for a project" +complete -c t -x -n "__fish_use_subcommand" -a out -d "stop tracking time for a project" +complete -c t -x -n "__fish_use_subcommand" -a bal -d "print current balance" + +# In +complete -c t -x -n "__fish_seen_subcommand_from in" -n "__fish_timesheets_arg_number 2" -a '(__fish-timesheets-available-projects)' +complete -c t -x -n "__fish_seen_subcommand_from in" -n "__fish_timesheets_arg_number 3" -a '(__fish-timesheets-existing-comments)' + +# Out +complete -c t -x -n "__fish_seen_subcommand_from out" -a '(__fish-timesheets-available-projects)' + +# Bal +complete -c t -x -n "__fish_seen_subcommand_from bal" -a '(__fish-timesheets-available-projects)'