#!/bin/bash - #=============================================================================== # # FILE: edit_tsu_blank # # USAGE: ./edit_tsu_blank # # DESCRIPTION: Edit a template for generating a tag and summary update email. # # OPTIONS: --- # REQUIREMENTS: --- # BUGS: --- # NOTES: Now obsolete but retained for reference # AUTHOR: Dave Morriss (djm), Dave.Morriss@gmail.com # VERSION: 0.0.11 # CREATED: 2016-06-16 10:58:32 # REVISION: 2021-09-16 12:51:18 # #=============================================================================== set -o nounset # Treat unset variables as an error SCRIPT=${0##*/} VERSION="0.0.11" # # Load library functions # LIB="$HOME/bin/function_lib.sh" [ -e "$LIB" ] || { echo "$SCRIPT: Unable to source functions"; exit 1; } # shellcheck source=/home/cendjm/bin/function_lib.sh source "$LIB" #=== FUNCTION ================================================================ # NAME: find_work # DESCRIPTION: Using 'grep' to count the number of un-edited lines in certain # files make a list of their names and the number of edits for # display in a 'select'. # PARAMETERS: 1 - the name of the directory holding the files # 2 - the prefix of each file to identify them exactly # 3 - the name of an array to hold the list # RETURNS: Nothing (uses a nameref argument) #=============================================================================== find_work () { local bd="${1:?Usage: find_work basedir prefix array}" local pf="${2:?Usage: find_work basedir prefix array}" local -n result="${3:?Usage: find_work basedir prefix array}" local -a work local elem count # Load all filenames into an array mapfile -t work < <(grep -E -c "^(summary|tags): *$" "$bd/$pf"*[^~]) # Add names containing work to the result array for elem in "${work[@]}"; do count="${elem##*:}" if [[ $count -gt 0 ]]; then printf -v count '%2d' "$count" # Add colour and a reset for the yellow to be added later result+=( "${elem%%:*}${reset} (${red}$count${reset} edits)" ) fi done } #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # # Check arguments # if [[ $# -ne 0 ]]; then echo "($SCRIPT Version $VERSION)" echo "Usage: $SCRIPT" exit fi # # Directories and files # BASEDIR="$HOME/HPR/Database" TSU="$BASEDIR/tsu" VALIDATOR="$BASEDIR/validate_edits.awk" STATUSFILE="$BASEDIR/tag_summary_actions.csv" PREFIX="tag_summary_updates_" # # Sanity checks # [ -d "$BASEDIR" ] || { echo "Unable to find directory $BASEDIR"; exit 1; } [ -d "$TSU" ] || { echo "Unable to find directory $TSU"; exit 1; } [ -e "$VALIDATOR" ] || { echo "File $VALIDATOR not found"; exit 1; } [ -e "$STATUSFILE" ] || { echo "File $STATUSFILE not found"; exit 1; } # # Colour codes # define_colours # # Using a function find which files have un-edited parts and save their names # and the number of edits in an array # declare -a choices find_work "$TSU" "${PREFIX}" choices # # There could be no files with edits # if [[ ${#choices[@]} -eq 0 ]]; then echo "${red}There are no files in need of editing!${reset}" exit 1 fi # # Prompt for a choice from the array of files, removing the path from each # choice for readability. (Sadly 'select' changed its behaviour in Bash # 5 necessitating this). Add a yellow colour code before the resulting # filename; there's already a reset after the name. # PS3="Enter a number: " echo "Files in need of editing:" # select choice in "${choices[@]##*/}" select choice in "${choices[@]/${TSU}\//${yellow}}" do break done retval=$? if [[ $retval -ne 0 ]]; then echo "${red}Selection aborted${reset}" exit 1 fi # # Since we removed the full path in the 'select' list 'choice' contains that # name rather than the file path, so we need to make it such a path. We also # need to remove the string "(X edits)" from the end, and all the colour codes # we added earlier, then edit the file. # # We include Vim settings for the text width and filetype, and perform # a search for the next field that needs work (using 'silent!' to stop nasty # error messages if there's nothing that matches). # # We use an Awk script to determine if the file contains any shows which have # already been updated by another person. We use the file $STATUSFILE which # gets updated every time a report is generated. # # Strip colour codes choice="${choice//$yellow/}" choice="${choice//$red/}" choice="${choice//$reset/}" # # Run the Awk validator, and if OK edit the file, otherwise try to explain # what's wrong. # choice="$TSU/${choice%% *}" if awk --assign "csv=$STATUSFILE" -f "$VALIDATOR" "$choice"; then csum1=$(md5sum < "$choice") echo "Editing $choice" vim +"set tw=100 ft=text" -c 'silent! /^\(summary\|tags\):\s*$' "$choice" csum2=$(md5sum < "$choice") if [[ $csum1 == "$csum2" ]]; then echo "${yellow}No change was made${reset}" exit fi else echo "${red}Errors found checking the file${reset}" echo "Show(s) in this file have already been updated in the database." echo "Somebody else has probably sent in an update for show(s) in the range." echo "The file ${yellow}${choice}${reset}" echo "has been edited automatically to comment out the updated show(s) and" echo "is now ready for editing in the usual way (rerun this script to do it)." echo "----" echo "(This error may also be caused by an internal fault when running" echo "awk. Check the file to be certain.)" exit 1 fi # # Perform a check on what is now in the file looking for lines that are too # long or with a bad show number # echo "${yellow}Checking show numbers and lengths of summaries and tags${reset}" re="^([A-Za-z]+): *(.*) *$" count=0; errors=0 while read -r line; do ((count++)) if [[ $line =~ $re ]]; then key="${BASH_REMATCH[1]}" value="${BASH_REMATCH[2]}" case $key in show) if [[ ! $value =~ [0-9]{1,4} ]]; then ((errors++)) printf '**Error**\n%02d: %s\n' "$count" "$line" echo "${blue}The show value must be a number (${#value})${reset}" fi ;; summary) if [[ ${#value} -gt 100 ]]; then ((errors++)) printf '**Error**\n%02d: %s\n' "$count" "$line" echo "${blue}Value too long (${#value}, should be 100 max)${reset}" fi ;; tags) if [[ ${#value} -gt 200 ]]; then ((errors++)) printf '**Error**\n%02d: %s\n' "$count" "$line" echo "${blue}Value too long (${#value}, should be 200 max)${reset}" fi ;; esac fi done < "$choice" # # Report a summary of the check # if [[ $errors -eq 0 ]]; then echo "${green}No errors found${reset}" else echo "${red}Found $errors errors${reset}" fi # # Make temporary files and set traps to delete them # TMP1=$(mktemp) || { echo "$SCRIPT: ${red}creation of temporary file failed!${reset}" exit 1 } trap 'cleanup_temp $TMP1' SIGHUP SIGINT SIGPIPE SIGTERM EXIT # # Make a temporary Awk script # cat > "$TMP1" <<'ENDAWK' BEGIN { shows = total = finished = todo = 0 } /^show:/ { shows++ } /^tags:\s*$/ { total++; todo++ } /^tags:\s*\S+/ { total++; finished++ } /^summary:\s*$/ { total++; todo++ } /^summary:\s*\S+/ { total++; finished++ } END { printf "shows=%d\n",shows printf "total=%d\n",total printf "finished=%d\n",finished printf "todo=%d\n",todo printf "left=%2.1f%%\n",(todo/total)*100 } ENDAWK # # Run the Awk script and make variables # declare shows total todo finished left eval "$(awk -f "$TMP1" "$choice")" # todo="$(grep -E -c "^(summary|tags):\s*$" "$choice")" # total="$(grep -E -c "^(summary|tags):" "$choice")" # completed="$(grep -E -c "^(summary|tags): *\w+" "$choice")" # # Is there still work to do on this file? # echo "${yellow}File statistics:${reset}" printf '%s%-19s %s%s\n' "${purple}" "Total shows:" "$shows" "${reset}" printf '%s%-19s %s%s\n' "${purple}" "Additions required:" "$total" "${reset}" printf '%s%-19s %s%s\n' "${purple}" "Already done:" "$finished" "${reset}" printf '%s%-19s %s%s\n' "${purple}" "Percent left:" "$left" "${reset}" case $todo in 0) echo "${green}All required work on this file has been done${reset}";; 1) echo "${red}There is still $todo tag/summary to add${reset}";; *) echo "${red}There are still $todo tags/summaries to add${reset}" esac exit # vim: syntax=sh:ts=8:sw=4:ai:et:tw=78:fo=tcrqn21