bash v2
This commit is contained in:
parent
6726f04f77
commit
dacb3aeb09
100
barg
Normal file → Executable file
100
barg
Normal file → Executable file
@ -1,55 +1,61 @@
|
||||
# barg - Bash argument parser + tiny CLI framework
|
||||
# Bash 5+
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# --- helpers -----------------------------------------------------------------
|
||||
join() {
|
||||
local out="" sep=""
|
||||
for x in "$@"; do [[ -n "$x" ]] && {
|
||||
out+="${sep}${x}"
|
||||
sep="."
|
||||
}; done
|
||||
for x in "$@"; do
|
||||
if [[ -n "$x" ]]; then
|
||||
out+="${sep}${x}"
|
||||
sep="."
|
||||
fi
|
||||
done
|
||||
printf '%s' "$out"
|
||||
}
|
||||
|
||||
# --- tokenizer ---------------------------------------------------------------
|
||||
tokenize_argv() {
|
||||
local prog=$1
|
||||
shift
|
||||
TOKENS=()
|
||||
TOKENS+=("root::${prog}")
|
||||
local -a args=("$@")
|
||||
while ((${#args[@]})); do
|
||||
local t=${args[0]}
|
||||
args=("${args[@]:1}")
|
||||
if [[ "$t" == "--" ]]; then
|
||||
TOKENS+=("rest::${args[*]}")
|
||||
TOKENS=("root::dev")
|
||||
local -a argv=("$@")
|
||||
|
||||
while ((${#argv[@]})); do
|
||||
local token=${argv[0]}
|
||||
argv=("${argv[@]:1}")
|
||||
|
||||
# Rest
|
||||
if [[ "$token" == "--" ]]; then
|
||||
TOKENS+=("rest::${argv[*]}")
|
||||
break
|
||||
fi
|
||||
if [[ "$t" == --* ]]; then
|
||||
local kv=${t#--}
|
||||
local key=${kv%%=*}
|
||||
TOKENS+=("narg::${key}")
|
||||
[[ "$kv" == *"="* ]] && TOKENS+=("value::${kv#*=}")
|
||||
|
||||
# Named Argument + Value: Option or Flag (long form)
|
||||
if [[ "$token" == --* ]]; then
|
||||
local key=${token#--}
|
||||
TOKENS+=("narg::${key%%=*}")
|
||||
[[ "$key" == *"="* ]] && TOKENS+=("value::${key#*=}")
|
||||
continue
|
||||
fi
|
||||
if [[ "$t" == -* ]]; then
|
||||
local sv=${t#-}
|
||||
local flags=${sv%%=*}
|
||||
local val=
|
||||
[[ "$sv" == *"="* ]] && val=${sv#*=}
|
||||
local i ch
|
||||
for ((i = 0; i < ${#flags}; i++)); do
|
||||
ch=${flags:i:1}
|
||||
TOKENS+=("narg::${ch}")
|
||||
|
||||
# Named Argument + Value: Option or Flag (short form)
|
||||
if [[ "$token" == -* ]]; then
|
||||
local key=${token#-}
|
||||
local flags=${key%%=*}
|
||||
local value=
|
||||
[[ "$key" == *"="* ]] && value=${key#*=}
|
||||
|
||||
local index flag
|
||||
for ((index = 0; index < ${#flags}; index++)); do
|
||||
flag=${flags:index:1}
|
||||
TOKENS+=("narg::${flag}")
|
||||
done
|
||||
[[ -n "$val" ]] && TOKENS+=("value::${val}")
|
||||
|
||||
[[ -n "$value" ]] && TOKENS+=("value::${value}")
|
||||
continue
|
||||
fi
|
||||
TOKENS+=("unk::${t}")
|
||||
|
||||
# Unknown: Command, Positional or Value
|
||||
TOKENS+=("unk::${token}")
|
||||
done
|
||||
}
|
||||
|
||||
# --- schema + parse ----------------------------------------------------------
|
||||
declare -A S A
|
||||
|
||||
_generate_schema() {
|
||||
@ -57,29 +63,37 @@ _generate_schema() {
|
||||
A=()
|
||||
local spec_name=$1
|
||||
local -n SPEC_REF="$spec_name"
|
||||
|
||||
local _id=100
|
||||
local -a pos=() cmds=()
|
||||
|
||||
local root_added_help=0
|
||||
|
||||
for entry in "${SPEC_REF[@]}"; do
|
||||
IFS=';' read -r -a parts <<<"$entry"
|
||||
case "${parts[0]}" in
|
||||
IFS=';' read -r -a elements <<<"$entry"
|
||||
case "${elements[0]}" in
|
||||
command)
|
||||
local id=$_id
|
||||
((_id++))
|
||||
IFS=',' read -r -a aliases <<<"${parts[1]}"
|
||||
IFS=',' read -r -a aliases <<<"${elements[1]}"
|
||||
|
||||
# Schema
|
||||
S["$id.entryType"]="command"
|
||||
S["$id.name"]="${aliases[0]}"
|
||||
S["$id.help"]="${parts[2]}"
|
||||
S["$id.help"]="${elements[2]}"
|
||||
S["$id.args"]=""
|
||||
|
||||
# Aliases
|
||||
if ((${#cmds[@]} == 0)); then
|
||||
A["cmd::root"]=$id
|
||||
else
|
||||
local last=$((${#cmds[@]} - 1))
|
||||
for alias in "${aliases[@]}"; do A["$(join "${cmds[$last]}" "cmd::${alias}")"]=$id; done
|
||||
for alias in "${aliases[@]}"; do
|
||||
A["$(join "${cmds[$last]}" "cmd::${alias}")"]=$id
|
||||
done
|
||||
fi
|
||||
|
||||
# Control
|
||||
cmds+=("$id")
|
||||
pos+=(0)
|
||||
|
||||
@ -108,12 +122,12 @@ _generate_schema() {
|
||||
argument)
|
||||
local id=$_id
|
||||
((_id++))
|
||||
IFS=',' read -r -a aliases <<<"${parts[1]}"
|
||||
IFS=',' read -r -a aliases <<<"${elements[1]}"
|
||||
local name="${aliases[0]}"
|
||||
local dest="$name" required="false" atype="positional" value="" help=""
|
||||
local i kv k v
|
||||
for ((i = 2; i < ${#parts[@]}; i++)); do
|
||||
kv=${parts[i]}
|
||||
for ((i = 2; i < ${#elements[@]}; i++)); do
|
||||
kv=${elements[i]}
|
||||
if [[ "$kv" == *":"* ]]; then
|
||||
k=${kv%%:*}
|
||||
v=${kv#*:}
|
||||
@ -156,7 +170,7 @@ _generate_schema() {
|
||||
esac
|
||||
;;
|
||||
*)
|
||||
printf 'Error: Invalid entry type: "%s"\n' "${parts[0]}" >&2
|
||||
printf 'Error: Invalid entry type: "%s"\n' "${elements[0]}" >&2
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
|
||||
Loading…
Reference in New Issue
Block a user