update
This commit is contained in:
parent
4b222622fb
commit
577209f5e2
145
barg.sh
145
barg.sh
@ -8,22 +8,12 @@ if [ "${BASH_VERSINFO:-0}" -lt 4 ]; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# --- globals ---
|
# --- globals ---
|
||||||
|
BARG_VAR_SUFFIX="_arg"
|
||||||
declare -A BARG_PARSED_VALUES
|
declare -A BARG_PARSED_VALUES
|
||||||
declare -a BARG_PARSED_COMMANDS
|
declare -a BARG_PARSED_COMMANDS
|
||||||
declare -A BARG_SCHEMA
|
declare -A BARG_SCHEMA
|
||||||
declare -A BARG_ALIASES
|
declare -A BARG_ALIASES
|
||||||
BARG_HELP_ONLY=false
|
BARG_HELP_ONLY=false
|
||||||
BARG_GENERATE_VARS=false # new flag to control var file generation
|
|
||||||
|
|
||||||
# --- Auto-source generated ShellCheck stub vars ---
|
|
||||||
_barg_self="${BASH_SOURCE[0]}"
|
|
||||||
_barg_dir="$(cd "$(dirname "$_barg_self")" && pwd)"
|
|
||||||
_barg_stub="${_barg_dir}/$(basename "${_barg_self%.*}").vars.generated.sh"
|
|
||||||
if [[ -f "$_barg_stub" ]]; then
|
|
||||||
# shellcheck source=/dev/null
|
|
||||||
source "$_barg_stub"
|
|
||||||
fi
|
|
||||||
unset _barg_self _barg_dir _barg_stub
|
|
||||||
|
|
||||||
# --------------------------------------------------------------------
|
# --------------------------------------------------------------------
|
||||||
# Parse CLI args according to spec
|
# Parse CLI args according to spec
|
||||||
@ -123,8 +113,10 @@ parse_arguments() {
|
|||||||
local help_text="${elements[2]}"
|
local help_text="${elements[2]}"
|
||||||
schema["${id}.entryType"]="command"
|
schema["${id}.entryType"]="command"
|
||||||
schema["${id}.name"]="${aliases_str%%,*}"
|
schema["${id}.name"]="${aliases_str%%,*}"
|
||||||
|
schema["${id}.aliases"]="$aliases_str"
|
||||||
schema["${id}.help"]="$help_text"
|
schema["${id}.help"]="$help_text"
|
||||||
schema["${id}.args"]=""
|
schema["${id}.args"]=""
|
||||||
|
schema["${id}.cmds"]=""
|
||||||
|
|
||||||
if [[ ${#cmd_stack[@]} -eq 0 ]]; then
|
if [[ ${#cmd_stack[@]} -eq 0 ]]; then
|
||||||
aliases["cmd::root"]="$id"
|
aliases["cmd::root"]="$id"
|
||||||
@ -134,6 +126,10 @@ parse_arguments() {
|
|||||||
local parent="${cmd_stack[-1]}"
|
local parent="${cmd_stack[-1]}"
|
||||||
aliases["${parent}.cmd::${alias}"]="$id"
|
aliases["${parent}.cmd::${alias}"]="$id"
|
||||||
done
|
done
|
||||||
|
|
||||||
|
local parent="${cmd_stack[-1]}"
|
||||||
|
local parent_cmds="${schema["${parent}.cmds"]}"
|
||||||
|
schema["${parent}.cmds"]="${parent_cmds:+$parent_cmds,}$id"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
((level++))
|
((level++))
|
||||||
@ -193,6 +189,18 @@ parse_arguments() {
|
|||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
|
((entry_id++))
|
||||||
|
;;
|
||||||
|
note)
|
||||||
|
local id="$entry_id"
|
||||||
|
local text="${elements[1]}"
|
||||||
|
schema["${id}.entryType"]="note"
|
||||||
|
schema["${id}.text"]="$text"
|
||||||
|
|
||||||
|
# attach note to the current command
|
||||||
|
local parent="${cmd_stack[-1]}"
|
||||||
|
local notes="${schema["${parent}.notes"]}"
|
||||||
|
schema["${parent}.notes"]="${notes:+$notes,}$id"
|
||||||
((entry_id++))
|
((entry_id++))
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
@ -298,7 +306,6 @@ parse_arguments() {
|
|||||||
((token_idx++))
|
((token_idx++))
|
||||||
done
|
done
|
||||||
|
|
||||||
# extract
|
|
||||||
BARG_PARSED_COMMANDS=()
|
BARG_PARSED_COMMANDS=()
|
||||||
BARG_PARSED_VALUES=()
|
BARG_PARSED_VALUES=()
|
||||||
for cmd_id in "${cmd_stack[@]}"; do
|
for cmd_id in "${cmd_stack[@]}"; do
|
||||||
@ -311,9 +318,10 @@ parse_arguments() {
|
|||||||
for arg_id in "${arg_ids[@]}"; do
|
for arg_id in "${arg_ids[@]}"; do
|
||||||
local dest="${schema["${arg_id}.dest"]}"
|
local dest="${schema["${arg_id}.dest"]}"
|
||||||
local value="${schema["${arg_id}.value"]}"
|
local value="${schema["${arg_id}.value"]}"
|
||||||
|
local dest_val="${BARG_PARSED_VALUES[$dest]}"
|
||||||
local required="${schema["${arg_id}.required"]}"
|
local required="${schema["${arg_id}.required"]}"
|
||||||
local atype="${schema["${arg_id}.type"]}"
|
local atype="${schema["${arg_id}.type"]}"
|
||||||
if [[ -z "$value" && "$required" == "true" && "$BARG_HELP_ONLY" != "true" ]]; then
|
if [[ -z "$value" && -z "$dest_val" && "$required" == "true" && "$BARG_HELP_ONLY" != "true" ]]; then
|
||||||
echo "Error: Argument \"$dest\" required" >&2
|
echo "Error: Argument \"$dest\" required" >&2
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
@ -321,11 +329,7 @@ parse_arguments() {
|
|||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
if [[ -n "$value" ]]; then
|
if [[ -n "$value" ]]; then
|
||||||
if [[ -n "${BARG_PARSED_VALUES[$dest]}" ]]; then
|
BARG_PARSED_VALUES["$dest"]="$value"
|
||||||
BARG_PARSED_VALUES["${cmd_name}_${dest}"]="$value"
|
|
||||||
else
|
|
||||||
BARG_PARSED_VALUES["$dest"]="$value"
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
done
|
done
|
||||||
@ -346,7 +350,6 @@ barg_usage() {
|
|||||||
local -a cmd_path=("$@")
|
local -a cmd_path=("$@")
|
||||||
local cmd_id="${BARG_ALIASES["cmd::root"]}"
|
local cmd_id="${BARG_ALIASES["cmd::root"]}"
|
||||||
|
|
||||||
# resolve command path
|
|
||||||
if [[ ${#cmd_path[@]} -gt 0 ]]; then
|
if [[ ${#cmd_path[@]} -gt 0 ]]; then
|
||||||
for cmd_name in "${cmd_path[@]}"; do
|
for cmd_name in "${cmd_path[@]}"; do
|
||||||
local next_id="${BARG_ALIASES["${cmd_id}.cmd::${cmd_name}"]}"
|
local next_id="${BARG_ALIASES["${cmd_id}.cmd::${cmd_name}"]}"
|
||||||
@ -365,7 +368,14 @@ barg_usage() {
|
|||||||
echo "$help_text"
|
echo "$help_text"
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- list arguments ---
|
local cmd_notes="${BARG_SCHEMA["${cmd_id}.notes"]}"
|
||||||
|
if [[ -n "$cmd_notes" ]]; then
|
||||||
|
IFS=',' read -ra note_ids <<<"$cmd_notes"
|
||||||
|
for nid in "${note_ids[@]}"; do
|
||||||
|
echo " ${BARG_SCHEMA["${nid}.text"]}"
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
local cmd_args="${BARG_SCHEMA["${cmd_id}.args"]}"
|
local cmd_args="${BARG_SCHEMA["${cmd_id}.args"]}"
|
||||||
if [[ -n "$cmd_args" ]]; then
|
if [[ -n "$cmd_args" ]]; then
|
||||||
echo ""
|
echo ""
|
||||||
@ -394,35 +404,38 @@ barg_usage() {
|
|||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# --- list subcommands ---
|
local cmd_children="${BARG_SCHEMA["${cmd_id}.cmds"]}"
|
||||||
local has_subcommands=false
|
if [[ -n "$cmd_children" ]]; then
|
||||||
for key in "${!BARG_ALIASES[@]}"; do
|
echo ""
|
||||||
if [[ "$key" =~ ^${cmd_id}\.cmd::(.+)$ ]]; then
|
echo "Commands:"
|
||||||
if [[ "$has_subcommands" == "false" ]]; then
|
IFS=',' read -ra child_ids <<<"$cmd_children"
|
||||||
echo ""
|
for child_id in "${child_ids[@]}"; do
|
||||||
echo "Commands:"
|
local sub_name="${BARG_SCHEMA["${child_id}.name"]}"
|
||||||
has_subcommands=true
|
local sub_help="${BARG_SCHEMA["${child_id}.help"]}"
|
||||||
|
local sub_aliases="${BARG_SCHEMA["${child_id}.aliases"]}"
|
||||||
|
|
||||||
|
# split aliases and remove duplicates
|
||||||
|
IFS=',' read -ra alias_list <<<"$sub_aliases"
|
||||||
|
local alias_display=""
|
||||||
|
if ((${#alias_list[@]} > 1)); then
|
||||||
|
alias_display=" (aliases: ${alias_list[*]:1})"
|
||||||
fi
|
fi
|
||||||
local sub_cmd="${BASH_REMATCH[1]}"
|
|
||||||
local sub_id="${BARG_ALIASES[$key]}"
|
echo " ${sub_name}${alias_display}"
|
||||||
local sub_help="${BARG_SCHEMA["${sub_id}.help"]}"
|
|
||||||
echo " ${sub_cmd}"
|
|
||||||
[[ -n "$sub_help" ]] && echo " ${sub_help}"
|
[[ -n "$sub_help" ]] && echo " ${sub_help}"
|
||||||
fi
|
done
|
||||||
done
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
# --------------------------------------------------------------------
|
# --------------------------------------------------------------------
|
||||||
# Export parsed vars
|
# Export parsed vars
|
||||||
# --------------------------------------------------------------------
|
# --------------------------------------------------------------------
|
||||||
barg_export_vars() {
|
barg_export_vars() {
|
||||||
local k base
|
local k dest
|
||||||
|
: "${BARG_VAR_SUFFIX:=}"
|
||||||
for k in "${!BARG_PARSED_VALUES[@]}"; do
|
for k in "${!BARG_PARSED_VALUES[@]}"; do
|
||||||
declare -g "${k}=${BARG_PARSED_VALUES[$k]}"
|
dest="${k}${BARG_VAR_SUFFIX}"
|
||||||
if [[ "$k" =~ ^[^_]+_(.+)$ ]]; then
|
declare -g "${dest}=${BARG_PARSED_VALUES[$k]}"
|
||||||
base="${BASH_REMATCH[1]}"
|
|
||||||
[[ -z "${!base+x}" ]] && declare -g "${base}=${BARG_PARSED_VALUES[$k]}"
|
|
||||||
fi
|
|
||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -443,33 +456,6 @@ barg_dispatch() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
# --------------------------------------------------------------------
|
|
||||||
# Helper: collect all .dest and command_dest variants
|
|
||||||
# --------------------------------------------------------------------
|
|
||||||
_barg_collect_all_dests() {
|
|
||||||
local -n _schema=$1
|
|
||||||
local -A seen=()
|
|
||||||
for key in "${!_schema[@]}"; do
|
|
||||||
[[ $key =~ \.dest$ ]] || continue
|
|
||||||
local dest="${_schema[$key]}"
|
|
||||||
[[ -z "$dest" ]] && continue
|
|
||||||
seen[$dest]=1
|
|
||||||
done
|
|
||||||
for key in "${!_schema[@]}"; do
|
|
||||||
[[ $key =~ ^([0-9]+)\.name$ ]] || continue
|
|
||||||
local cmd_id="${BASH_REMATCH[1]}"
|
|
||||||
local cmd="${_schema[$key]}"
|
|
||||||
local args_str="${_schema[${cmd_id}.args]}"
|
|
||||||
[[ -z "$args_str" ]] && continue
|
|
||||||
IFS=',' read -r -a arg_ids <<<"$args_str"
|
|
||||||
for a in "${arg_ids[@]}"; do
|
|
||||||
local d="${_schema[${a}.dest]}"
|
|
||||||
[[ -n "$d" ]] && seen["${cmd}_${d}"]=1
|
|
||||||
done
|
|
||||||
done
|
|
||||||
printf '%s\n' "${!seen[@]}" | sort
|
|
||||||
}
|
|
||||||
|
|
||||||
# --------------------------------------------------------------------
|
# --------------------------------------------------------------------
|
||||||
# Entry point
|
# Entry point
|
||||||
# --------------------------------------------------------------------
|
# --------------------------------------------------------------------
|
||||||
@ -486,31 +472,6 @@ barg_run() {
|
|||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
local -a caller_stack=("${BASH_SOURCE[@]}")
|
|
||||||
local caller="${caller_stack[1]}"
|
|
||||||
local out_file="${caller%.*}.vars.generated.sh"
|
|
||||||
|
|
||||||
# Only generate when explicitly requested
|
|
||||||
if [[ "$BARG_GENERATE_VARS" == "true" || "$BARG_REGEN_VARS" == "1" ]]; then
|
|
||||||
mapfile -t vars < <(_barg_collect_all_dests BARG_SCHEMA)
|
|
||||||
{
|
|
||||||
echo "# ---- autogenerated: BARG vars for ShellCheck ----"
|
|
||||||
echo "# generated from $(basename "$caller")"
|
|
||||||
echo "# regenerate with: BARG_REGEN_VARS=1 ./$(basename "$caller") ..."
|
|
||||||
echo "# shellcheck disable=SC2034"
|
|
||||||
echo "if false; then"
|
|
||||||
echo " CLI_SPEC=()"
|
|
||||||
printf ' %s=\n' "${vars[@]}" | paste -sd' ' -
|
|
||||||
echo "fi"
|
|
||||||
} >"$out_file"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Source file if it already exists (not required to generate)
|
|
||||||
if [[ -f "$out_file" ]]; then
|
|
||||||
# shellcheck source=/dev/null
|
|
||||||
source "$out_file"
|
|
||||||
fi
|
|
||||||
|
|
||||||
barg_dispatch
|
barg_dispatch
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user