Add checklist.sh scrpt

This commit is contained in:
shutkin.k 2025-05-24 09:36:35 +03:00
parent 75ed1c111a
commit f566f8d9d0
1 changed files with 211 additions and 0 deletions

211
checklist.sh Executable file
View File

@ -0,0 +1,211 @@
#!/bin/bash
# Check if file argument is provided
if [ $# -ne 1 ]; then
echo "Usage: $0 <path_to_file>"
exit 1
fi
FILE="$1"
# Check if file exists
if [ ! -f "$FILE" ]; then
echo "Error: File '$FILE' not found"
exit 1
fi
# Terminal control functions
hide_cursor() {
printf '\033[?25l'
}
show_cursor() {
printf '\033[?25h'
}
move_cursor() {
printf '\033[%d;%dH' "$1" "$2"
}
clear_screen() {
printf '\033[2J'
printf '\033[H'
}
cleanup() {
show_cursor
clear_screen
echo "Goodbye!"
exit 0
}
# Trap to ensure cursor is restored on exit
trap cleanup EXIT INT TERM
# Hide cursor at start
hide_cursor
# Parse the file and store tasks
declare -a categories=()
declare -A tasks=()
declare -A checked=()
declare -a display_items=() # Store display items in order
current_category=""
task_counter=0
while IFS= read -r line; do
if [[ $line =~ ^@(.+)$ ]]; then
current_category="${BASH_REMATCH[1]}"
categories+=("$current_category")
display_items+=("CATEGORY:$current_category")
elif [[ -n "$line" && -n "$current_category" ]]; then
task_key="${current_category}_${task_counter}"
tasks["$task_key"]="$line"
checked["$task_key"]=false
display_items+=("TASK:$task_key")
((task_counter++))
fi
done < "$FILE"
# Current selection
current_selection=0
total_items=${#display_items[@]}
header_lines=3
# Initial display
initial_display() {
clear_screen
echo "Checklist - Use ↑/↓ to navigate, SPACE to toggle, q to quit"
echo "File: $FILE"
echo "=================================================="
for i in "${!display_items[@]}"; do
item="${display_items[$i]}"
if [[ $item =~ ^CATEGORY:(.+)$ ]]; then
category="${BASH_REMATCH[1]}"
echo "@$category"
elif [[ $item =~ ^TASK:(.+)$ ]]; then
task_key="${BASH_REMATCH[1]}"
checkbox="[ ]"
if [ "${checked[$task_key]}" = true ]; then
checkbox="[✓]"
fi
echo " $checkbox ${tasks[$task_key]}"
fi
echo # Empty line after each item
done
}
# Update single line
update_line() {
local line_num=$((header_lines + 1 + ($1 * 2))) # *2 because of empty lines
move_cursor $line_num 1
printf '\033[K' # Clear line
item="${display_items[$1]}"
if [[ $item =~ ^CATEGORY:(.+)$ ]]; then
category="${BASH_REMATCH[1]}"
if [ $1 -eq $current_selection ]; then
printf '\033[7m@%s\033[0m' "$category"
else
printf '@%s' "$category"
fi
elif [[ $item =~ ^TASK:(.+)$ ]]; then
task_key="${BASH_REMATCH[1]}"
checkbox="[ ]"
if [ "${checked[$task_key]}" = true ]; then
checkbox="[✓]"
fi
task_line=" $checkbox ${tasks[$task_key]}"
if [ $1 -eq $current_selection ]; then
printf '\033[7m%s\033[0m' "$task_line"
else
printf '%s' "$task_line"
fi
fi
}
# Update only the checkbox part of a task line
update_checkbox() {
local line_num=$((header_lines + 1 + ($1 * 2)))
local task_key="${BASH_REMATCH[1]}"
item="${display_items[$1]}"
if [[ $item =~ ^TASK:(.+)$ ]]; then
task_key="${BASH_REMATCH[1]}"
checkbox="[ ]"
if [ "${checked[$task_key]}" = true ]; then
checkbox="[✓]"
fi
# Move to checkbox position (column 3) and update just the checkbox
move_cursor $line_num 3
if [ $1 -eq $current_selection ]; then
printf '\033[7m%s\033[0m' "$checkbox"
else
printf '%s' "$checkbox"
fi
fi
}
# Get the task key at current selection
get_current_task_key() {
item="${display_items[$current_selection]}"
if [[ $item =~ ^TASK:(.+)$ ]]; then
echo "${BASH_REMATCH[1]}"
else
echo ""
fi
}
# Show initial display
initial_display
# Highlight first item
update_line 0
# Main loop
prev_selection=0
while true; do
# Read single character
IFS= read -rsn1 input
# Handle different input cases
if [[ $input == $'\x1b' ]]; then
# ESC sequence - read next two characters
IFS= read -rsn2 input
case $input in
'[A') # Up arrow
if [ $current_selection -gt 0 ]; then
prev_selection=$current_selection
((current_selection--))
update_line $prev_selection
update_line $current_selection
fi
;;
'[B') # Down arrow
if [ $current_selection -lt $((total_items - 1)) ]; then
prev_selection=$current_selection
((current_selection++))
update_line $prev_selection
update_line $current_selection
fi
;;
esac
elif [[ $input == ' ' ]]; then
# Space bar - toggle checkbox
task_key=$(get_current_task_key)
if [ -n "$task_key" ]; then
if [ "${checked[$task_key]}" = true ]; then
checked["$task_key"]=false
else
checked["$task_key"]=true
fi
# Only update the checkbox, not the entire line
update_checkbox $current_selection
fi
elif [[ $input == 'q' ]] || [[ $input == 'Q' ]]; then
# Quit - cleanup will be called by trap
exit 0
fi
done