#!/usr/bin/env bash set -euo pipefail # POS: tree — Show the pos CLI command tree: categories, commands, and subcommands # POS_FLAGS: --depth source "$(dirname "$0")/../lib/common.sh" 2>/dev/null || source "$(dirname "$0")/common.sh" usage() { cat < — parent "/" is the root. add() { local parent="$1" word="$2" type="$3" desc="$4" path if [ "$parent" = "/" ]; then path="$word"; else path="$parent/$word"; fi children["$parent"]+=" $word" meta["$path"]="$type|$desc" } for f in "$self"/pos-*; do [ -x "$f" ] || continue name="${f##*/pos-}" desc="$(sed -n '/^# POS: /{s/^# POS: //;p;q}' "$f")" desc="${desc#*— }" sc="$(sed -n '/^# POS_SUBCMDS: /{s/^# POS_SUBCMDS: //;p;q}' "$f")" words=(${name//-/ }) parent="/" for ((i=0; i<${#words[@]}; i++)); do word="${words[$i]}" if [ "$parent" = "/" ]; then path="$word"; else path="$parent/$word"; fi if [ $((i + 1)) -eq ${#words[@]} ]; then add "$parent" "$word" "tool" "$desc" else [ -n "${meta[$path]:-}" ] || add "$parent" "$word" "cat" "" fi parent="$path" done for s in $sc; do add "$parent" "$s" "sub" "" done done # pad = widest "pos " leaf, so descriptions align for p in "${!meta[@]}"; do case "${meta[$p]%%|*}" in tool|sub) len=$(( ${#p} + 4 )) [ "$len" -gt "$maxw" ] && maxw=$len ;; esac done render() { local parent="$1" prefix="$2" lvl="$3" if [ -n "$depth" ] && [ "$lvl" -ge "$depth" ]; then return; fi local -a kids mapfile -t kids < <(printf '%s\n' ${children[$parent]:-} | sort -u) local i word path type desc conn nextpref last for ((i=0; i<${#kids[@]}; i++)); do word="${kids[$i]}" if [ "$parent" = "/" ]; then path="$word"; else path="$parent/$word"; fi last=$(( i == ${#kids[@]} - 1 )) if [ "$last" -eq 1 ]; then conn="└── "; nextpref="$prefix "; else conn="├── "; nextpref="$prefix│ "; fi type="${meta[$path]%%|*}" desc="${meta[$path]#*|}" case "$type" in cat) printf '%s%s%s/\n' "$prefix" "$conn" "$word" render "$path" "$nextpref" $((lvl+1)) ;; tool) printf '%s%s%-*s# %s\n' "$prefix" "$conn" "$((maxw+1))" "pos ${path//\// }" "$desc" if [ -n "${children[$path]:-}" ]; then render "$path" "$nextpref" $((lvl+1)) fi ;; sub) printf '%s%s%s\n' "$prefix" "$conn" "pos ${path//\// }" ;; esac done } printf 'pos\n' render "/" "" 1