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