Zsh CLI Tutorial — getopts, Colors, Progress Bars & Todo App #26
Video: Zsh CLI Tutorial — getopts, Colors, Progress Bars & Todo App #26 by Taught by Celeste AI - AI Coding Coach
Watch full page →Zsh CLI Tutorial — getopts, Colors, Progress Bars & Todo App
This tutorial demonstrates how to create polished command-line tools in Zsh by parsing flags with getopts, adding colorful output using ANSI escape codes, and enhancing user experience with spinners and progress bars. It culminates in a complete todo app featuring subcommands and file-backed storage.
Code
#!/bin/zsh
# Usage function to display help message
usage() {
echo "Usage: $0 [-v] [-n NAME] [-h] <subcommand> [args]"
echo "Options:"
echo " -v Enable verbose mode"
echo " -n NAME Specify a name"
echo " -h Show this help message"
echo "Subcommands:"
echo " add <task> Add a new todo task"
echo " list List all tasks"
echo " done <task_num> Mark task as done"
echo " remove <task_num> Remove a task"
exit 2
}
# Color helper functions using ANSI escape codes
success() { echo -e "\e[32m$1\e[0m"; }
error() { echo -e "\e[31m$1\e[0m"; }
warn() { echo -e "\e[33m$1\e[0m"; }
info() { echo -e "\e[34m$1\e[0m"; }
# Spinner animation function
spinner() {
local pid=$1
local delay=0.1
local spinstr='|/-\'
while kill -0 $pid 2>/dev/null; do
for i in {1..4}; do
printf "\r%s" "${spinstr:i-1:1}"
sleep $delay
done
done
printf "\r"
}
# File to store todo tasks
TODO_FILE="$HOME/.todo.txt"
touch $TODO_FILE
# Parse options with getopts
verbose=0
name=""
while getopts "vn:h" opt; do
case $opt in
v) verbose=1 ;;
n) name=$OPTARG ;;
h) usage ;;
*) usage ;;
esac
done
shift $((OPTIND -1))
# Subcommand routing
case "$1" in
add)
shift
if [ -z "$1" ]; then
error "Please provide a task to add."
exit 1
fi
echo "[ ] $*" >> $TODO_FILE
success "Added task: $*"
;;
list)
if [ ! -s $TODO_FILE ]; then
info "No tasks found."
exit 0
fi
nl -w2 -s'. ' $TODO_FILE
;;
done)
shift
if ! [[ "$1" =~ ^[0-9]+$ ]]; then
error "Please provide a valid task number."
exit 1
fi
sed -i "${1}s/^\[ \]/[x]/" $TODO_FILE
success "Marked task #$1 as done."
;;
remove)
shift
if ! [[ "$1" =~ ^[0-9]+$ ]]; then
error "Please provide a valid task number."
exit 1
fi
sed -i "${1}d" $TODO_FILE
success "Removed task #$1."
;;
*)
usage
;;
esac
Key Points
- Use
getoptsin a while loop to parse command-line flags and access their values withOPTARG. - Shift positional parameters with
shift $((OPTIND -1))to handle subcommands and arguments after flags. - Enhance CLI output with ANSI escape codes for colors and define helper functions for consistent styling.
- Create spinner animations by overwriting the same line with rotating characters to indicate progress.
- Implement subcommand routing with a
casestatement and manage persistent data using plain text files andsedfor edits.