bash v4: working auto cmd
This commit is contained in:
parent
4f243a31c9
commit
dac3ac8662
489
barg.sh
Executable file
489
barg.sh
Executable file
@ -0,0 +1,489 @@
|
|||||||
|
# --- globals ---
|
||||||
|
declare -A BARG_PARSED_VALUES
|
||||||
|
declare -a BARG_PARSED_COMMANDS
|
||||||
|
declare -A BARG_SCHEMA
|
||||||
|
declare -A BARG_ALIASES
|
||||||
|
BARG_HELP_ONLY=false
|
||||||
|
|
||||||
|
# --- parse_arguments: take spec... '--' args... ; tokenize array; i=0 ---
|
||||||
|
parse_arguments() {
|
||||||
|
# split "$@" into spec_input and args by a literal "--" separator
|
||||||
|
local -a spec_input=()
|
||||||
|
local -a args=()
|
||||||
|
local seen_sep=false
|
||||||
|
for item in "$@"; do
|
||||||
|
if [[ $seen_sep == false && "$item" == "--" ]]; then
|
||||||
|
seen_sep=true
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
if [[ $seen_sep == false ]]; then
|
||||||
|
spec_input+=("$item")
|
||||||
|
else
|
||||||
|
args+=("$item")
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Local storage
|
||||||
|
local -A schema=()
|
||||||
|
local -A aliases=()
|
||||||
|
local -a tokens=()
|
||||||
|
|
||||||
|
# Tokenize input into tagged tokens (format: tag::value)
|
||||||
|
tokenize() {
|
||||||
|
local -a in=("$@")
|
||||||
|
tokens=()
|
||||||
|
tokens+=("root::root")
|
||||||
|
|
||||||
|
local i=0
|
||||||
|
while [[ $i -lt ${#in[@]} ]]; do
|
||||||
|
local token="${in[$i]}"
|
||||||
|
|
||||||
|
# Rest arguments after "--"
|
||||||
|
if [[ "$token" == "--" ]]; then
|
||||||
|
((i++))
|
||||||
|
local rest_args=()
|
||||||
|
while [[ $i -lt ${#in[@]} ]]; do
|
||||||
|
rest_args+=("${in[$i]}")
|
||||||
|
((i++))
|
||||||
|
done
|
||||||
|
if [[ ${#rest_args[@]} -gt 0 ]]; then
|
||||||
|
tokens+=("rest::${rest_args[*]}")
|
||||||
|
fi
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Long option: --key or --key=value
|
||||||
|
if [[ "$token" =~ ^--(.+)$ ]]; then
|
||||||
|
local full="${BASH_REMATCH[1]}"
|
||||||
|
if [[ "$full" =~ ^([^=]+)=(.*)$ ]]; then
|
||||||
|
tokens+=("narg::${BASH_REMATCH[1]}")
|
||||||
|
tokens+=("value::${BASH_REMATCH[2]}")
|
||||||
|
else
|
||||||
|
tokens+=("narg::${full}")
|
||||||
|
fi
|
||||||
|
((i++))
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Short option(s): -k -abc or -k=value
|
||||||
|
if [[ "$token" =~ ^-(.+)$ ]]; then
|
||||||
|
local full="${BASH_REMATCH[1]}"
|
||||||
|
if [[ "$full" =~ ^([^=]+)=(.*)$ ]]; then
|
||||||
|
local flags="${BASH_REMATCH[1]}"
|
||||||
|
local value="${BASH_REMATCH[2]}"
|
||||||
|
for ((j = 0; j < ${#flags}; j++)); do
|
||||||
|
tokens+=("narg::${flags:$j:1}")
|
||||||
|
done
|
||||||
|
tokens+=("value::${value}")
|
||||||
|
else
|
||||||
|
for ((j = 0; j < ${#full}; j++)); do
|
||||||
|
tokens+=("narg::${full:$j:1}")
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
((i++))
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Unknown: could be command, positional, or value
|
||||||
|
tokens+=("unk::${token}")
|
||||||
|
((i++))
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
# Generate schema from spec (unchanged body except local arrays initialized)
|
||||||
|
generate_schema() {
|
||||||
|
local -a spec_array=("$@")
|
||||||
|
local entry_id=100
|
||||||
|
local level=-1
|
||||||
|
local -a cmd_stack=()
|
||||||
|
local -a pos_stack=()
|
||||||
|
|
||||||
|
for entry in "${spec_array[@]}"; do
|
||||||
|
IFS=';' read -ra elements <<<"$entry"
|
||||||
|
local entry_type="${elements[0]}"
|
||||||
|
|
||||||
|
case "$entry_type" in
|
||||||
|
command)
|
||||||
|
local id="$entry_id"
|
||||||
|
local aliases_str="${elements[1]}"
|
||||||
|
local help_text="${elements[2]}"
|
||||||
|
|
||||||
|
schema["${id}.entryType"]="command"
|
||||||
|
schema["${id}.name"]="${aliases_str%%,*}"
|
||||||
|
schema["${id}.help"]="$help_text"
|
||||||
|
schema["${id}.args"]=""
|
||||||
|
|
||||||
|
if [[ ${#cmd_stack[@]} -eq 0 ]]; then
|
||||||
|
aliases["cmd::root"]="$id"
|
||||||
|
else
|
||||||
|
IFS=',' read -ra alias_list <<<"$aliases_str"
|
||||||
|
for alias in "${alias_list[@]}"; do
|
||||||
|
local parent="${cmd_stack[-1]}"
|
||||||
|
aliases["${parent}.cmd::${alias}"]="$id"
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
((level++))
|
||||||
|
cmd_stack+=("$id")
|
||||||
|
pos_stack+=(0)
|
||||||
|
((entry_id++))
|
||||||
|
;;
|
||||||
|
|
||||||
|
end)
|
||||||
|
((level--))
|
||||||
|
unset 'cmd_stack[-1]'
|
||||||
|
unset 'pos_stack[-1]'
|
||||||
|
;;
|
||||||
|
|
||||||
|
argument)
|
||||||
|
local id="$entry_id"
|
||||||
|
local aliases_str="${elements[1]}"
|
||||||
|
local arg_name="${aliases_str%%,*}"
|
||||||
|
|
||||||
|
schema["${id}.entryType"]="argument"
|
||||||
|
schema["${id}.name"]="$arg_name"
|
||||||
|
schema["${id}.dest"]="$arg_name"
|
||||||
|
schema["${id}.required"]="false"
|
||||||
|
schema["${id}.type"]="positional"
|
||||||
|
|
||||||
|
for ((i = 2; i < ${#elements[@]}; i++)); do
|
||||||
|
local element="${elements[$i]}"
|
||||||
|
if [[ "$element" =~ ^([^:]+):(.*)$ ]]; then
|
||||||
|
local attr_key="${BASH_REMATCH[1]}"
|
||||||
|
local attr_value="${BASH_REMATCH[2]}"
|
||||||
|
if [[ "$attr_key" == "default" ]]; then
|
||||||
|
schema["${id}.value"]="$attr_value"
|
||||||
|
else
|
||||||
|
schema["${id}.${attr_key}"]="$attr_value"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
schema["${id}.${element}"]="true"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
local parent="${cmd_stack[-1]}"
|
||||||
|
local cmd_args="${schema["${parent}.args"]}"
|
||||||
|
if [[ -n "$cmd_args" ]]; then
|
||||||
|
schema["${parent}.args"]="${cmd_args},${id}"
|
||||||
|
else
|
||||||
|
schema["${parent}.args"]="$id"
|
||||||
|
fi
|
||||||
|
|
||||||
|
local arg_type="${schema["${id}.type"]}"
|
||||||
|
case "$arg_type" in
|
||||||
|
positional)
|
||||||
|
local pos="${pos_stack[-1]}"
|
||||||
|
aliases["${parent}.pos::${pos}"]="$id"
|
||||||
|
((pos_stack[-1] = pos + 1))
|
||||||
|
;;
|
||||||
|
rest)
|
||||||
|
aliases["${parent}.rest"]="$id"
|
||||||
|
;;
|
||||||
|
option | flag)
|
||||||
|
IFS=',' read -ra alias_list <<<"$aliases_str"
|
||||||
|
for alias in "${alias_list[@]}"; do
|
||||||
|
aliases["${parent}.narg::${alias}"]="$id"
|
||||||
|
done
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
((entry_id++))
|
||||||
|
;;
|
||||||
|
|
||||||
|
*)
|
||||||
|
echo "Error: Invalid entry type: $entry_type" >&2
|
||||||
|
return 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
# Parse tokens based on schema
|
||||||
|
process_tokens() {
|
||||||
|
local -a cmd_stack=()
|
||||||
|
local -a pos_stack=()
|
||||||
|
local token_idx=0
|
||||||
|
|
||||||
|
local root_id="${aliases["cmd::root"]}"
|
||||||
|
cmd_stack+=("$root_id")
|
||||||
|
pos_stack+=(0)
|
||||||
|
|
||||||
|
# help-only detection at token level
|
||||||
|
BARG_HELP_ONLY=false
|
||||||
|
local help_present=false other_narg=false
|
||||||
|
for t in "${tokens[@]}"; do
|
||||||
|
local tag="${t%%::*}"
|
||||||
|
local tok="${t#*::}"
|
||||||
|
if [[ "$tag" == "narg" ]]; then
|
||||||
|
if [[ "$tok" == "h" || "$tok" == "help" ]]; then
|
||||||
|
help_present=true
|
||||||
|
else
|
||||||
|
other_narg=true
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
if [[ "$help_present" == true && "$other_narg" == false ]]; then
|
||||||
|
BARG_HELP_ONLY=true
|
||||||
|
fi
|
||||||
|
|
||||||
|
while [[ $token_idx -lt ${#tokens[@]} ]]; do
|
||||||
|
local tagged_token="${tokens[$token_idx]}"
|
||||||
|
local token_tag="${tagged_token%%::*}"
|
||||||
|
local token="${tagged_token#*::}"
|
||||||
|
|
||||||
|
if [[ "$token_tag" == "root" ]]; then
|
||||||
|
schema["${root_id}.name"]="$token"
|
||||||
|
((token_idx++))
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
local found=false
|
||||||
|
local level
|
||||||
|
for ((level = ${#cmd_stack[@]} - 1; level >= 0; level--)); do
|
||||||
|
local entry_id=""
|
||||||
|
local current_cmd="${cmd_stack[$level]}"
|
||||||
|
|
||||||
|
case "$token_tag" in
|
||||||
|
rest) entry_id="${aliases["${current_cmd}.rest"]}" ;;
|
||||||
|
narg) entry_id="${aliases["${current_cmd}.narg::${token}"]}" ;;
|
||||||
|
unk)
|
||||||
|
entry_id="${aliases["${current_cmd}.cmd::${token}"]}"
|
||||||
|
if [[ -z "$entry_id" && $level -eq $((${#cmd_stack[@]} - 1)) ]]; then
|
||||||
|
local pos="${pos_stack[$level]}"
|
||||||
|
entry_id="${aliases["${current_cmd}.pos::${pos}"]}"
|
||||||
|
if [[ -n "$entry_id" ]]; then
|
||||||
|
((pos_stack[level] = pos + 1))
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
if [[ -z "$entry_id" ]]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
local entry_type="${schema["${entry_id}.entryType"]}"
|
||||||
|
|
||||||
|
case "$entry_type" in
|
||||||
|
command)
|
||||||
|
cmd_stack+=("$entry_id")
|
||||||
|
pos_stack+=(0)
|
||||||
|
;;
|
||||||
|
argument)
|
||||||
|
local arg_type="${schema["${entry_id}.type"]}"
|
||||||
|
local value=""
|
||||||
|
case "$arg_type" in
|
||||||
|
rest | positional) value="$token" ;;
|
||||||
|
flag) value="true" ;;
|
||||||
|
option)
|
||||||
|
local next_idx=$((token_idx + 1))
|
||||||
|
if [[ $next_idx -ge ${#tokens[@]} ]]; then
|
||||||
|
echo "Error: No value provided for option: $token" >&2
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
local next_tagged="${tokens[$next_idx]}"
|
||||||
|
local next_tag="${next_tagged%%::*}"
|
||||||
|
local next_token="${next_tagged#*::}"
|
||||||
|
if [[ "$next_tag" != "value" && "$next_tag" != "unk" ]]; then
|
||||||
|
echo "Error: Expected value for option, got: $next_token ($next_tag)" >&2
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
value="$next_token"
|
||||||
|
((token_idx++))
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
schema["${entry_id}.value"]="$value"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
found=true
|
||||||
|
break
|
||||||
|
done
|
||||||
|
|
||||||
|
if [[ "$found" == "false" ]]; then
|
||||||
|
echo "Warning: Invalid argument: \"$token\" ($token_tag). Skipping..." >&2
|
||||||
|
fi
|
||||||
|
|
||||||
|
((token_idx++))
|
||||||
|
done
|
||||||
|
|
||||||
|
# Extract results into global variables
|
||||||
|
BARG_PARSED_COMMANDS=()
|
||||||
|
BARG_PARSED_VALUES=()
|
||||||
|
|
||||||
|
for cmd_id in "${cmd_stack[@]}"; do
|
||||||
|
local cmd_name="${schema["${cmd_id}.name"]}"
|
||||||
|
local cmd_args="${schema["${cmd_id}.args"]}"
|
||||||
|
BARG_PARSED_COMMANDS+=("$cmd_name")
|
||||||
|
|
||||||
|
[[ -z "$cmd_args" ]] && continue
|
||||||
|
|
||||||
|
IFS=',' read -ra arg_ids <<<"$cmd_args"
|
||||||
|
for arg_id in "${arg_ids[@]}"; do
|
||||||
|
local name="${schema["${arg_id}.name"]}"
|
||||||
|
local dest="${schema["${arg_id}.dest"]}"
|
||||||
|
local value="${schema["${arg_id}.value"]}"
|
||||||
|
local required="${schema["${arg_id}.required"]}"
|
||||||
|
local atype="${schema["${arg_id}.type"]}"
|
||||||
|
|
||||||
|
if [[ -z "$value" && "$required" == "true" && "$BARG_HELP_ONLY" != "true" ]]; then
|
||||||
|
echo "Error: Argument \"$name\" is required in command \"$cmd_name\"" >&2
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Do not set "false"/"0" defaults for flags
|
||||||
|
if [[ "$atype" == "flag" && ("$value" == "false" || "$value" == "0") ]]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -n "$value" ]]; then
|
||||||
|
if [[ -n "${BARG_PARSED_VALUES[$dest]}" ]]; then
|
||||||
|
BARG_PARSED_VALUES["${cmd_name}_${dest}"]="$value"
|
||||||
|
else
|
||||||
|
BARG_PARSED_VALUES["$dest"]="$value"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
done
|
||||||
|
|
||||||
|
# Copy schema and aliases to global for usage generation
|
||||||
|
for key in "${!schema[@]}"; do BARG_SCHEMA["$key"]="${schema[$key]}"; done
|
||||||
|
for key in "${!aliases[@]}"; do BARG_ALIASES["$key"]="${aliases[$key]}"; done
|
||||||
|
}
|
||||||
|
|
||||||
|
tokenize "${args[@]}"
|
||||||
|
generate_schema "${spec_input[@]}" || return 1
|
||||||
|
process_tokens
|
||||||
|
}
|
||||||
|
|
||||||
|
# --- usage unchanged except minor safety ---
|
||||||
|
barg_usage() {
|
||||||
|
local cmd_path=("$@")
|
||||||
|
|
||||||
|
local cmd_id="${BARG_ALIASES["cmd::root"]}"
|
||||||
|
local current_name="${BARG_SCHEMA["${cmd_id}.name"]}"
|
||||||
|
|
||||||
|
if [[ ${#cmd_path[@]} -gt 0 ]]; then
|
||||||
|
for cmd_name in "${cmd_path[@]}"; do
|
||||||
|
local next_id="${BARG_ALIASES["${cmd_id}.cmd::${cmd_name}"]}"
|
||||||
|
if [[ -z "$next_id" ]]; then
|
||||||
|
echo "Error: Unknown command: $cmd_name" >&2
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
cmd_id="$next_id"
|
||||||
|
current_name="$cmd_name"
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
local help_text="${BARG_SCHEMA["${cmd_id}.help"]}"
|
||||||
|
echo "Usage: ${cmd_path[*]} [OPTIONS] [COMMANDS]"
|
||||||
|
[[ -n "$help_text" ]] && {
|
||||||
|
echo ""
|
||||||
|
echo "$help_text"
|
||||||
|
}
|
||||||
|
|
||||||
|
local cmd_args="${BARG_SCHEMA["${cmd_id}.args"]}"
|
||||||
|
if [[ -n "$cmd_args" ]]; then
|
||||||
|
echo ""
|
||||||
|
echo "Arguments:"
|
||||||
|
IFS=',' read -ra arg_ids <<<"$cmd_args"
|
||||||
|
for arg_id in "${arg_ids[@]}"; do
|
||||||
|
local arg_name="${BARG_SCHEMA["${arg_id}.name"]}"
|
||||||
|
local arg_type="${BARG_SCHEMA["${arg_id}.type"]}"
|
||||||
|
local arg_help="${BARG_SCHEMA["${arg_id}.help"]}"
|
||||||
|
local required="${BARG_SCHEMA["${arg_id}.required"]}"
|
||||||
|
local default="${BARG_SCHEMA["${arg_id}.value"]}"
|
||||||
|
|
||||||
|
local prefix=" "
|
||||||
|
case "$arg_type" in
|
||||||
|
flag | option) prefix=" --${arg_name}" ;;
|
||||||
|
positional) prefix=" <${arg_name}>" ;;
|
||||||
|
rest) prefix=" -- <${arg_name}...>" ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
local suffix=""
|
||||||
|
[[ "$required" == "true" ]] && suffix=" (required)"
|
||||||
|
[[ -n "$default" ]] && suffix="${suffix} [default: $default]"
|
||||||
|
|
||||||
|
echo "${prefix}${suffix}"
|
||||||
|
[[ -n "$arg_help" ]] && echo " ${arg_help}"
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
local has_subcommands=false
|
||||||
|
for key in "${!BARG_ALIASES[@]}"; do
|
||||||
|
if [[ "$key" =~ ^${cmd_id}\.cmd::(.+)$ ]]; then
|
||||||
|
if [[ "$has_subcommands" == "false" ]]; then
|
||||||
|
echo ""
|
||||||
|
echo "Commands:"
|
||||||
|
has_subcommands=true
|
||||||
|
fi
|
||||||
|
local sub_cmd="${BASH_REMATCH[1]}"
|
||||||
|
local sub_id="${BARG_ALIASES[$key]}"
|
||||||
|
local sub_help="${BARG_SCHEMA["${sub_id}.help"]}"
|
||||||
|
echo " ${sub_cmd}"
|
||||||
|
[[ -n "$sub_help" ]] && echo " ${sub_help}"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
# --- export parsed values into variables before dispatch ---
|
||||||
|
barg_export_vars() {
|
||||||
|
local prefix="${1:-}"
|
||||||
|
local k
|
||||||
|
for k in "${!BARG_PARSED_VALUES[@]}"; do
|
||||||
|
declare -g "${prefix}${k}=${BARG_PARSED_VALUES[$k]}"
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
# --- dispatch: export then call handler ---
|
||||||
|
barg_dispatch() {
|
||||||
|
local cmd_path=""
|
||||||
|
local func_name="cmd"
|
||||||
|
|
||||||
|
for ((i = 1; i < ${#BARG_PARSED_COMMANDS[@]}; i++)); do
|
||||||
|
local cmd="${BARG_PARSED_COMMANDS[$i]}"
|
||||||
|
func_name="${func_name}_${cmd}"
|
||||||
|
cmd_path="${cmd_path} ${cmd}"
|
||||||
|
done
|
||||||
|
|
||||||
|
if declare -f "$func_name" >/dev/null 2>&1; then
|
||||||
|
barg_export_vars
|
||||||
|
"$func_name"
|
||||||
|
else
|
||||||
|
echo "Error: No handler found for command:${cmd_path}" >&2
|
||||||
|
echo "Expected function: ${func_name}" >&2
|
||||||
|
echo ""
|
||||||
|
barg_usage "${BARG_PARSED_COMMANDS[@]:1}"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# --- entrypoint: pass args as array with separator, honor help-only ---
|
||||||
|
barg_run() {
|
||||||
|
local -a spec=("${!1}")
|
||||||
|
shift
|
||||||
|
|
||||||
|
if ! parse_arguments "${spec[@]}" -- "$@" 2>&1; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$BARG_HELP_ONLY" == "true" || "${BARG_PARSED_VALUES[help]}" == "true" ]]; then
|
||||||
|
barg_usage "${BARG_PARSED_COMMANDS[@]:1}"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
barg_dispatch
|
||||||
|
}
|
||||||
|
|
||||||
|
# --- getters ---
|
||||||
|
barg_get() {
|
||||||
|
local key="$1"
|
||||||
|
echo "${BARG_PARSED_VALUES[$key]}"
|
||||||
|
}
|
||||||
|
|
||||||
|
barg_has() {
|
||||||
|
local key="$1"
|
||||||
|
local val="${BARG_PARSED_VALUES[$key]}"
|
||||||
|
[[ "$val" == "true" || "$val" == "1" ]]
|
||||||
|
}
|
||||||
82
cli.sh
Executable file
82
cli.sh
Executable file
@ -0,0 +1,82 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# Example: dev CLI tool using BARG framework
|
||||||
|
|
||||||
|
# Source the BARG framework
|
||||||
|
source ./barg.sh
|
||||||
|
|
||||||
|
# Define your CLI specification
|
||||||
|
CLI_SPEC=(
|
||||||
|
"command;dev;Dev Container Management Tool"
|
||||||
|
"argument;help,h;type:flag;help:Show help message"
|
||||||
|
"argument;global;type:flag;help:Enable global mode"
|
||||||
|
|
||||||
|
"command;build;Build a dev container"
|
||||||
|
"argument;from;type:option;dest:fromName;help:Name of the base container"
|
||||||
|
"argument;name;type:positional;required;help:Name of the container"
|
||||||
|
"argument;nametwo;help:Secondary name"
|
||||||
|
"argument;image,i;type:option;required;dest:imageName;help:Base image"
|
||||||
|
"argument;include,I;type:option;repeatable;dest:includePaths;help:Include paths"
|
||||||
|
"argument;verbose,v;type:flag;repeatable;default:0;help:Increase verbosity (-v, -vv, ...)"
|
||||||
|
"argument;quiet,q;type:flag;default:false;help:Suppress all output"
|
||||||
|
"argument;cmd;type:rest;help:Command and args to run inside the container"
|
||||||
|
"argument;name;dest:nameOpt;type:option;help:Building container name"
|
||||||
|
|
||||||
|
"command;container;Nested container configuration"
|
||||||
|
"argument;dev;type:flag;help:Development mode"
|
||||||
|
"argument;name;required;help:Container name"
|
||||||
|
"argument;cmd;type:rest;dest:cmdRest;help:Command to run"
|
||||||
|
"end"
|
||||||
|
"end"
|
||||||
|
|
||||||
|
"command;stop;Stop a dev container"
|
||||||
|
"argument;name;type:positional;required;help:Name of the container"
|
||||||
|
"argument;kill,k;type:flag;default:false;help:Force kill the container"
|
||||||
|
"end"
|
||||||
|
|
||||||
|
"end"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Command handlers - implement your logic here!
|
||||||
|
|
||||||
|
# Root command handler
|
||||||
|
cmd() {
|
||||||
|
echo "Dev Container Tool"
|
||||||
|
echo "Use --help to see available commands"
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd_build() {
|
||||||
|
# now available directly:
|
||||||
|
# $name, $imageName, $fromName, $quiet, $verbose, $cmd, $nameOpt, $includePaths ...
|
||||||
|
echo "Building container: $name"
|
||||||
|
echo " Base image: $imageName"
|
||||||
|
[[ -n "$fromName" ]] && echo " From: $fromName"
|
||||||
|
[[ "$verbose" == "true" ]] && echo " Verbose mode enabled"
|
||||||
|
[[ "$quiet" == "true" ]] && echo " Quiet mode enabled"
|
||||||
|
[[ -n "$cmd" ]] && echo " Command: $cmd"
|
||||||
|
echo "Container built successfully!"
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd_build_container() {
|
||||||
|
# $name is the build-level name, container's name appears as $container_name due to collision resolution
|
||||||
|
echo "Building nested container configuration"
|
||||||
|
echo " Parent container: $name"
|
||||||
|
echo " Child container: $container_name"
|
||||||
|
echo " Image: $imageName"
|
||||||
|
[[ "$dev" == "true" ]] && echo " Development mode: ON"
|
||||||
|
[[ -n "$cmdRest" ]] && echo " Command: $cmdRest"
|
||||||
|
echo "Nested container configured!"
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd_stop() {
|
||||||
|
echo "Stopping container: $name"
|
||||||
|
if [[ "$kill" == "true" ]]; then
|
||||||
|
echo " Force killing..."
|
||||||
|
else
|
||||||
|
echo " Graceful shutdown..."
|
||||||
|
fi
|
||||||
|
echo "Container stopped!"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Run the CLI with all arguments
|
||||||
|
barg_run CLI_SPEC[@] "$@"
|
||||||
Loading…
Reference in New Issue
Block a user