From 6ad3cfe2e7997b448a16d7791cf57e484e72b43d Mon Sep 17 00:00:00 2001 From: Steven Baltakatei Sandoval Date: Wed, 7 Aug 2024 09:45:31 +0000 Subject: [PATCH] feat(unitproc/palign.sh):Add script to align path lists --- unitproc/palign.sh | 129 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 129 insertions(+) create mode 100755 unitproc/palign.sh diff --git a/unitproc/palign.sh b/unitproc/palign.sh new file mode 100755 index 0000000..99bad70 --- /dev/null +++ b/unitproc/palign.sh @@ -0,0 +1,129 @@ +#!/bin/bash +# Desc: Aligns path elements with spaces +# Usage: palign.sh [path] +# find . -type f | palign.sh +# Input: stdin paths newline-delimited paths (forward-slash delimited) +# psargs paths word-delimited paths (forward-slash delimited) +# Output: stdout +# Depends: Bash 5.1.16 +# Version: 0.0.1 + +yell() { echo "$0: $*" >&2; } # print script path and all args to stderr +die() { yell "$*"; exit 111; } # same as yell() but non-zero exit status +must() { "$@" || die "cannot $*"; } # runs args as command, reports args if command fails +read_stdin() { + # Desc: Consumes stdin; outputs as stdout lines + # Input: stdin (consumes) + # Output: stdout (newline delimited) + # return 0 stdin read + # return 1 stdin not present + # Example: printf "foo\nbar\n" | read_stdin + # Depends: GNU bash (version 5.1.16), GNU Coreutils 8.32 (cat) + # Version: 0.1.1 + # Attrib: Steven Baltakatei Sandoval (2024-01-29). reboil.com + local input_stdin output; + + # Store stdin + if [[ -p /dev/stdin ]]; then + input_stdin="$(cat -)" || { + echo "FATAL:Error reading stdin." 1>&2; return 1; }; + else + return 1; + fi; + + # Store as output array elements + ## Read in stdin + if [[ -n $input_stdin ]]; then + while read -r line; do + output+=("$line"); + done < <(printf "%s\n" "$input_stdin") || { + echo "FATAL:Error parsing stdin."; return 1; }; + fi; + + # Print to stdout + printf "%s\n" "${output[@]}"; + + return 0; +}; # read stdin to stdout lines +read_psarg() { + # Desc: Reads arguments; outputs as stdout lines + # Input: args + # Output: stdout (newline delimited) + # Example: read_psarg "$@" + # Depends: GNU bash (version 5.1.16) + # Version: 0.0.1 + local input_psarg output; + + # Store arguments + if [[ $# -gt 0 ]]; then + input_psarg="$*"; + fi; + + # Store as output array elements + ## Read in positional arguments + if [[ -n $input_psarg ]]; then + for arg in "$@"; do + output+=("$arg"); + done; + fi; + + # Print to stdout + printf "%s\n" "${output[@]}"; +}; # read positional argument to stdout lines +calculate_max_lengths() { + # Calculate maximum lengths of each hierarchical level + # Input: psargs paths + # Output: stdout ints path element lengths (single line of space-separated ints) + local -a paths=("$@"); + local lengths; + + for path in "${paths[@]}"; do + IFS='/' read -r -a parts <<< "$path"; + # Analyze path element lengths + for i in "${!parts[@]}"; do + # Save max path element lengths for previously analyzed paths + # Note: $(( condition ? value_true : value_false )) + # condition: ${#parts[$i]} > ${lengths[$i]:-0} is path element longer than previously seen corresponding paths? + # value_true: ${#parts[$i]} save new max length + # value_false ${lengths[$i]:-0} use previous value (or init with 0 if never seen before) + lengths[$i]=$(( ${#parts[$i]} > ${lengths[$i]:-0} ? ${#parts[$i]} : ${lengths[$i]:-0} )); + done; + done; + echo "${lengths[@]}"; +}; # Get maximum lengths of path elements as space-separated ints +align_paths() { + # Align paths + # Input: stdin + # Output: stdout + # Depends: calculate_max_lengths() + local -a paths lengths; + + # Read stdin + while read -r line; do + paths+=("$line"); + done < <(read_stdin); + + IFS=" " read -r -a lengths <<< "$(calculate_max_lengths "${paths[@]}")"; + + for path in "${paths[@]}"; do + IFS='/' read -r -a parts <<< "$path"; + formatted_path=""; + for i in "${!parts[@]}"; do + if [[ $i -gt 0 ]]; then + formatted_path+="/"; + fi; + formatted_path+="${parts[$i]}"; + if [[ $i -lt $((${#parts[@]} - 1)) ]]; then + formatted_path+=$(printf "%*s" $((${lengths[$i]} - ${#parts[$i]} + 1)) ""); + fi; + done; + echo "$formatted_path"; + done; +}; # Function to format and align paths +main() { + { read_stdin; read_psarg "$@"; } | align_paths; +}; # Call the function with the file paths +main "$@"; + +# Author: Steven Baltakatei Sandoval +# License; GPLv3+ -- 2.30.2