
Description:
A simple CLI for managing tickets and tasks in a terminal environment.
Uses a small .csv to store created tickets.
Usage:
ticket <command> [arguments]
Commands:
list, -ls List all tickets
add, -a <text> Add a new ticket
del, -d <id> Delete a ticket
close, -c <id> Close a ticket
open, -o <id> Re-open a ticket
help, -h Show this help
Examples:
ticket add Buy milk
ticket -a “Walk the dog”
ticket close 3
ticket del 7
ticket list
#!/bin/bash
#
#######################
# GLOBAL VARIABLES
########################
DATA_FILE="$HOME/.ticket.csv"
DELIM="%"
VERSION="1.6"
####################
# COLOUR VARIABLES
####################
# Terminal Formatting
RESET="\033[0m"
BOLD="\033[1m"
# UI Colours
CLR_ERROR="\033[38;5;196m" # Bright Red
CLR_SUCCESS="\033[38;5;46m" # Bright Lime Green
CLR_INFO="\033[38;5;226m" # Gold
CLR_ACTION="\033[38;5;141m" # Light Purple / Lavender
CLR_LABEL="\033[38;5;81m" # Bright Sky Blue
CLR_LABEL2="\033[38;5;2m" # Dark Forest Green
CLR_PROMPT="${BOLD}\033[38;5;51m" # Aqua + Bold
CLR_TEXT="\033[38;5;254m" # Light Grey
CLR_FRAME="\033[38;5;245m" # Darker Grey
set -e
#######################
# Unicode box Chars
########################
H="─"
V="│"
TL="┌"
TR="┐"
BL="└"
BR="┘"
LT="├"
RT="┤"
TT="┬"
BT="┴"
CR="┼"
TH_FRAME="${CLR_FRAME}${TL}────${TT}─────────────────────${TT}────────${TT}───────────────────────────────────────────────────────────${TR}${RESET}"
MD_FRAME="${CLR_FRAME}${LT}────${CR}─────────────────────${CR}────────${CR}───────────────────────────────────────────────────────────${RT}${RESET}"
BH_FRAME="${CLR_FRAME}${BL}────${BT}─────────────────────${BT}────────${BT}───────────────────────────────────────────────────────────${BR}${RESET}"
ROW_PREFIX="${CLR_FRAME}${V}${RESET}"
############
# FUNCTIONS
#############
error() {
echo
echo -e " ${CLR_ERROR}Error: ${RESET}$1"
echo
}
ticket_action() {
echo
echo "────────────────────────"
echo -e " ▶ ${1}Ticket (${RESET}${BOLD}${2}${RESET}${1}) ${3}${RESET}"
echo "────────────────────────"
}
next_id() {
if [[ ! -s "$DATA_FILE" ]]; then
echo 1
return
fi
awk -F'%' '
$1 > max { max = $1 }
END { print max + 1 }
' "$DATA_FILE"
}
cmd_list() {
if [[ ! -s "$DATA_FILE" ]]; then
touch "$DATA_FILE"
fi
local FMT="$ROW_PREFIX %2s $ROW_PREFIX %-19s $ROW_PREFIX %-6s $ROW_PREFIX %-47s $ROW_PREFIX\n"
echo
echo -e "${TH_FRAME}"
printf "$FMT" "ID" "DATE" "STATE" "TICKET"
printf "%b" "$RESET"
echo -e "${MD_FRAME}"
if [[ ! -s "$DATA_FILE" ]]; then
echo " No current tickets"
echo -e "${MD_FRAME}"
fi
#framing check
first=1
while IFS="$DELIM" read -r id status datetime ticket; do
# Ifs to determine framing
if ((!first)); then
echo -e "${MD_FRAME}"
fi
first=0
# Setup Ticket Contents
printf "$ROW_PREFIX %2s $ROW_PREFIX %-19s $ROW_PREFIX " \
"$id" "$datetime"
#Ticket Colouring
if [[ "$status" == "OPEN" ]]; then
printf "%b%-6s%b" "$CLR_SUCCESS" "$status" "$RESET"
else
printf "%b%-6s%b" "$CLR_ERROR" "$status" "$RESET"
fi
# Ticket Description
printf " $ROW_PREFIX %s\n" "$ticket"
done <"$DATA_FILE"
echo -e "${BH_FRAME}"
echo
}
cmd_add() {
id=$(next_id)
status="OPEN"
datetime="$(date '+%Y-%m-%d / %H:%M')"
ticket="$*"
printf '%s%s%s%s%s%s%s\n' \
"$id" "$DELIM" \
"$status" "$DELIM" \
"$datetime" "$DELIM" \
"$ticket" >>"$DATA_FILE"
ticket_action ${CLR_SUCCESS} ${id} "Created"
}
cmd_delete() {
local delete_id="$1"
#
# Ensure the ID is numerical & Exists
#
# If Blank
if [[ -z "$delete_id" ]]; then
error "No Ticket ID Specified"
echo " Usage: ticket -d <id>"
echo
return 1
fi
# IF input isn't a number
if [[ ! $delete_id =~ ^[0-9]+$ ]]; then
error "${delete_id} is not a numerical value"
exit
fi
# If delete_id is 5, this searches specifically for "^5%"
# to ensure the delete_id exists in $DATA_FILE
if grep -q "^${delete_id}${DELIM}" "$DATA_FILE"; then
#
# Finish checks - continue Deleting
#
while IFS="$DELIM" read -r id status datetime ticket; do
if [[ "$id" != "$delete_id" ]]; then
printf '%s%%%s%%%s%%%s\n' \
"$id" "$status" "$datetime" "$ticket"
fi
done <"$DATA_FILE" >"$DATA_FILE.tmp"
mv "$DATA_FILE.tmp" "$DATA_FILE"
ticket_action ${CLR_ERROR} ${delete_id} "Deleted"
else
error "Ticket '$delete_id' does not exist."
fi
}
cmd_open() {
local open_id="$1"
# If Blank
if [[ -z "$open_id" ]]; then
error "No Ticket ID Specified"
echo " Usage: ticket -o <id>"
echo
return 1
fi
# IF input isn't a number
if [[ ! $open_id =~ ^[0-9]+$ ]]; then
error "${open_id} is not a numerical value"
return 1
fi
if grep -q "^${open_id}${DELIM}" "$DATA_FILE"; then
# Create the tempfile
>"$DATA_FILE.tmp"
while IFS="$DELIM" read -r id status datetime ticket; do
if [[ "$id" == "$open_id" ]]; then
if [[ "$status" == "OPEN" ]]; then
ticket_action "$CLR_ERROR" "$open_id" "Already Open"
echo
exit 0
else
status="OPEN"
fi
fi
#Append data to the temp file
printf '%s%%%s%%%s%%%s\n' \
"$id" "$status" "$datetime" "$ticket" >>"$DATA_FILE.tmp"
done <"$DATA_FILE"
#overwrite our csv
mv "$DATA_FILE.tmp" "$DATA_FILE"
ticket_action "$CLR_SUCCESS" "$open_id" "Opened"
echo
else
error "Ticket '$open_id' does not exist."
fi
}
cmd_close() {
local close_id="$1"
# If Blank
if [[ -z "$close_id" ]]; then
error "No Ticket ID Specified"
echo " Usage: ticket -c <id>"
echo
return 1
fi
# IF input isn't a number
if [[ ! $close_id =~ ^[0-9]+$ ]]; then
error "${close_id} is not a numerical value"
return 1
fi
if grep -q "^${close_id}${DELIM}" "$DATA_FILE"; then
# Create the tempfile
>"$DATA_FILE.tmp"
while IFS="$DELIM" read -r id status datetime ticket; do
if [[ "$id" == "$close_id" ]]; then
if [[ "$status" == "CLOSED" ]]; then
ticket_action "$CLR_ERROR" "$close_id" "Already Closed"
echo
exit 0
else
status="CLOSED"
fi
fi
printf '%s%%%s%%%s%%%s\n' \
"$id" "$status" "$datetime" "$ticket" >>"$DATA_FILE.tmp"
done <"$DATA_FILE"
mv "$DATA_FILE.tmp" "$DATA_FILE"
ticket_action "$CLR_ERROR" "$close_id" "Closed"
echo
else
error "Ticket '$close_id' does not exist."
fi
}
usage() {
echo -e "${BOLD}Odi's Ticket CLI v${VERSION}${RESET}"
echo
echo -e "${BOLD}Description:${RESET}"
echo -e "${CLR_TEXT} A simple CLI for managing tickets and tasks.${RESET}"
echo
echo -e "${BOLD}Usage:${RESET}"
echo -e " ${CLR_TEXT}ticket <command> [arguments]${RESET}"
echo
echo -e "${BOLD}Commands:${RESET}"
echo -e "${CLR_TEXT} list, -ls List all tickets"
echo -e " add, -a <text> Add a new ticket"
echo -e " del, -d <id> Delete a ticket"
echo -e " close, -c <id> Close a ticket"
echo -e " open, -o <id> Re-open a ticket"
echo -e " help, -h Show this help${RESET}"
echo
echo -e "${BOLD}Examples:${RESET}"
echo -e "${CLR_TEXT} ticket add Buy milk"
echo -e " ticket -a \"Walk the dog\""
echo -e " ticket close 3"
echo -e " ticket del 7"
echo -e " ticket list${RESET}"
echo
}
#############
# COMMANDS
##############
if [[ $# -eq 0 ]]; then
usage
exit 0
fi
case "${1:-}" in
add | -a)
shift
cmd_add "$@"
;;
delete | del | -d)
shift
cmd_delete "$1"
;;
close | -c)
shift
cmd_close "$@"
;;
open | -o)
shift
cmd_open "$@"
;;
list | -ls)
shift
cmd_list "$@"
;;
help | -h | --help)
usage
;;
*)
echo "Unknown command."
usage
exit 1
;;
esac
