Skip to content

Enhancements — Menu-Driven CLI App

Extend the task manager with filtering, due dates, and export.

Enhancement 1 — Due Dates

Add an optional due date to tasks:

# Extended format: id:status:priority:due_date:description
# due_date is YYYY-MM-DD or empty

cmd_add() {
    local desc="" priority="$DEFAULT_PRIORITY" due=""

    while [[ "${1:-}" =~ ^- ]]; do
        case "$1" in
            --priority|-p) priority="$2"; shift ;;
            --due|-d)      due="$2"; shift ;;
            *) echo "Unknown: $1" >&2; return 1 ;;
        esac
        shift
    done
    desc="${1:-}"
    [[ -z "$desc" ]] && { printf "Description: "; read -r desc; }

    echo "${id}:pending:${priority}:${due}:${desc}" >> "$DB_FILE"
}

# In cmd_list(), highlight overdue tasks in red
is_overdue() {
    local due="$1"
    [[ -z "$due" ]] && return 1
    local today
    today=$(date '+%Y-%m-%d')
    [[ "$due" < "$today" ]]
}

Add --filter and search subcommands:

cmd_filter() {
    local status="${1:-}" priority="${2:-}"

    while IFS=: read -r id st pri desc; do
        [[ -z "$id" || "$id" =~ ^# ]] && continue
        [[ -n "$status"   && "$st"  != "$status"   ]] && continue
        [[ -n "$priority" && "$pri" != "$priority"  ]] && continue
        printf "%-4s  %-8s  %-8s  %s\n" "$id" "$st" "$pri" "$desc"
    done < "$DB_FILE"
}

cmd_search() {
    local query="${1:?search requires a query}"
    grep -i ":.*${query}" "$DB_FILE" |
    while IFS=: read -r id status priority desc; do
        printf "%-4s  %-8s  %-8s  %s\n" "$id" "$status" "$priority" "$desc"
    done
}

Usage:

bash taskman.sh filter --status pending --priority high
bash taskman.sh search "grocery"

Enhancement 3 — Export to CSV / Markdown

cmd_export() {
    local format="${1:-csv}"
    case "$format" in
        csv)
            echo "id,status,priority,description"
            while IFS=: read -r id status priority desc; do
                [[ "$id" =~ ^# ]] && continue
                echo "${id},${status},${priority},\"${desc}\""
            done < "$DB_FILE"
            ;;
        md)
            echo "| ID | Status | Priority | Task |"
            echo "|-----|--------|----------|------|"
            while IFS=: read -r id status priority desc; do
                [[ "$id" =~ ^# ]] && continue
                local sym="○"
                [[ "$status" == "done" ]] && sym="✓"
                echo "| $id | $sym | $priority | $desc |"
            done < "$DB_FILE"
            ;;
    esac
}

Enhancement 4 — Statistics

Show task completion statistics:

cmd_stats() {
    local total=0 done=0 high=0 overdue=0

    while IFS=: read -r id status priority desc; do
        [[ "$id" =~ ^[0-9]+$ ]] || continue
        (( total++ )) || true
        [[ "$status"   == "done" ]] && (( done++ )) || true
        [[ "$priority" == "high" ]] && (( high++ )) || true
    done < "$DB_FILE"

    local pct=0
    (( total > 0 )) && pct=$(( done * 100 / total ))

    echo ""
    echo "=== Task Statistics ==="
    printf "  Total:      %d\n" "$total"
    printf "  Done:       %d (%d%%)\n" "$done" "$pct"
    printf "  Pending:    %d\n" "$(( total - done ))"
    printf "  High prio:  %d\n" "$high"

    # Progress bar
    local bar_done=$(( pct / 5 )) bar_left=$(( 20 - pct / 5 ))
    printf "  Progress:   [%s%s] %d%%\n" \
        "$(printf '█%.0s' $(seq 1 $bar_done))" \
        "$(printf '░%.0s' $(seq 1 $bar_left))" \
        "$pct"
}

Enhancement 5 — Multiple Lists / Projects

Support named lists (like folders for tasks):

# Store in ~/.local/share/taskman/<list>.db
TASKMAN_DIR="${HOME}/.local/share/taskman"
LIST="${TASKMAN_LIST:-default}"
DB_FILE="${TASKMAN_DIR}/${LIST}.db"

cmd_lists() {
    echo "Available lists:"
    find "$TASKMAN_DIR" -name '*.db' | while read -r f; do
        local name count
        name="$(basename "$f" .db)"
        count=$(grep -c '^[0-9]' "$f" 2>/dev/null || echo 0)
        printf "  %-20s (%d tasks)\n" "$name" "$count"
    done
}

# Switch list: TASKMAN_LIST=work bash taskman.sh list

Enhancement 6 — Readline-Enhanced Input

Use readline for history and tab completion in the interactive menu:

# In interactive mode, use history for task descriptions
HISTFILE="${SCRIPT_DIR}/.taskman_history"
set -o history

get_input_with_history() {
    local prompt="$1"
    local REPLY
    read -r -e -p "$prompt" REPLY
    history -s "$REPLY"
    echo "$REPLY"
}

The -e flag to read enables readline line-editing (arrow keys, history navigation).


testing | solution