e7484103b9
===================================================================== A follow-up to V5 focused on hardening the environment system and expanding the ZSH logging/caching toolkit. No migration required from v5.0.x, though note the log-level reorganization below may quiet some messages at lower verbosities. --- New Features ------------------------- - persistent cross-runtime cache for ZSH-type scwrypts; extends the v5.0 runtime speedup cache to survive between runs with automatic hash-based invalidation (toggle via SCWRYPTS__ZSH_CACHE_ENABLED) - new 'trace' log level (5) and echo.trace, plus '-v VARNAME' state injection for echo.debug / echo.trace to surface variable values inline - additional scwrypts output formats: 'raw' and 'logfmt' (alongside pretty and json) - normalize.boolean utility for consistent truthy/falsey handling across ZSH-type scwrypts - utils.fzf.file-select for directory-scoped file selection prompts - automatic dependency wrappers providing default arguments, GNU coreutil resolution, and scwrypts trace on wrapped commands --- Changes ------------------------------ - log levels reorganized; success / status / reminder messages now emit at level 3, so lower verbosities will show fewer of these - environment library restructured around get-user-json as the single source of truth (replaces the previous user module and cache-output) - utility renames for consistency: user.Yn / user.yN (from utils.*) - utils.fail and utils.abort deprecated in favor of echo.error and echo.error.user-abort --- Bug Fixes ---------------------------- - CI runs now resolve config lookup-paths (.dotted.path) to their environment variable before reading, fixing false "not set" reports and invalid-export errors for lookup-path checks in CI - hardened environment type detection so array-valued configs reprint correctly after their first check - corrected exit-code capture in the cache layer (now reflects the cached command, not the downstream output filter) - scwrypt exit code now survives the logging pipeline - assorted script fixes (efs unmount file listing, postgres run-sql file discovery)
138 lines
4.0 KiB
Bash
138 lines
4.0 KiB
Bash
#
|
|
# when you don't need to check any special negative cases,
|
|
# you can simply set up your PARSERS=() array and other local
|
|
# variable declarations, then run the following line:
|
|
#
|
|
# eval "$ZSHPARSEARGS"
|
|
#
|
|
# This will populate variables, run all validators, and handle
|
|
# the special '--help' case, forcing an early 'return 0' after
|
|
# parsing the args.
|
|
#
|
|
ZSHPARSEARGS='
|
|
utils.parse $@ || {
|
|
local ERROR_CODE=$?
|
|
case $ERROR_CODE in
|
|
( -1 ) return 0 ;; # -h | --help
|
|
( * ) return $ERROR_CODE ;;
|
|
esac
|
|
}
|
|
'
|
|
|
|
utils.parse() {
|
|
#
|
|
# Parses all arguments using PARSERS array; return value breaks the typical
|
|
# success/failure code paradigm:
|
|
#
|
|
# returns 0 if all arguments were parsed successfully (success)
|
|
# returns >0 a count of every argument which failed to parse successfully (failure)
|
|
#
|
|
# returns -1 if parent program should "return 0" immediately (success, but signal program end; e.g. --help should print usage and return 0)
|
|
#
|
|
# other _negative return codes_ can be processed in any custom way
|
|
#
|
|
#
|
|
# Makes argument parsing reusable in zsh. Best-practice argument
|
|
# parsing involves looping across the $@ args, processing and 'shift'-ing
|
|
# arguments until there are none left, but this can lead to a lot
|
|
# of boilerplate. While there _are_ utilities to try and simplify this,
|
|
# I've found their API to be quite complex and inconsistent across
|
|
# different environments.
|
|
#
|
|
# By including "parser" functions in the 'PARSERS=()' array, you can
|
|
# perform parsing logic (first element is highest priority, last element is
|
|
# lowest priority). A sample parser function is defined below.
|
|
#
|
|
# If variable values are set in the caller function, proper usage requires
|
|
# declaration of "local VARIABLE_NAME" in that parent caller _before_
|
|
# invoking 'utils.zshparseargs $@'
|
|
#
|
|
local PARSER VALID_PARSERS=()
|
|
local DEFAULT_PARSERS=()
|
|
|
|
[[ ${DEFAULT_PARSERS[@]-1} =~ ^utils.parse.help$ ]] \
|
|
&& local NO_DEFAULT_PARSERS=true # autosetup preloads default parsers
|
|
|
|
[ ${NO_DEFAULT_PARSERS} ] || {
|
|
# automatically includes 'MY_FUNCTION.parse()' as 1st parser when parsing for 'MY_FUNCTION()'
|
|
[[ ${funcstack[2]} =~ ^[(]eval[)]$ ]] \
|
|
&& PARSERS=(${funcstack[3]}.parse ${PARSERS}) \
|
|
|| PARSERS=(${funcstack[2]}.parse ${PARSERS}) \
|
|
;
|
|
|
|
PARSERS+=(utils.parse.args utils.parse.help)
|
|
}
|
|
|
|
for PARSER in ${PARSERS[@]}
|
|
do
|
|
command -v ${PARSER} &>/dev/null || continue
|
|
command -v ${PARSER}.safety &>/dev/null || {
|
|
VALID_PARSERS+=(${PARSER})
|
|
continue
|
|
}
|
|
|
|
${PARSER}.safety && VALID_PARSERS+=(${PARSER})
|
|
done
|
|
|
|
for PARSER in ${VALID_PARSERS[@]}
|
|
do
|
|
command -v ${PARSER}.usage &>/dev/null && ${PARSER}.usage &>/dev/null
|
|
done
|
|
|
|
local EARLY_ESCAPE_CODE _S ERRORS=0 POSITIONAL_ARGS=0
|
|
while [[ $# -gt 0 ]]
|
|
do
|
|
_S=0
|
|
for PARSER in ${VALID_PARSERS[@]}
|
|
do
|
|
${PARSER} $@
|
|
((_S+=$?))
|
|
|
|
[ ${EARLY_ESCAPE_CODE} ] && return ${EARLY_ESCAPE_CODE}
|
|
|
|
[[ ${_S} -gt 0 ]] && break
|
|
done
|
|
|
|
[[ ${_S} -gt 0 ]] \
|
|
|| echo.error "unknown argument '$1'" \
|
|
|| ((_S+=1))
|
|
|
|
|
|
[[ ${_S} -le $# ]] \
|
|
|| echo.error "invalid value(s) for '$1'" \
|
|
|| _S=$#
|
|
|
|
shift ${_S}
|
|
done
|
|
|
|
for PARSER in ${VALID_PARSERS[@]}
|
|
do
|
|
command -v ${PARSER}.validate &>/dev/null || continue
|
|
|
|
${PARSER}.validate
|
|
done
|
|
|
|
utils.check-errors
|
|
}
|
|
|
|
#####################################################################
|
|
### default parsers #################################################
|
|
#####################################################################
|
|
|
|
# while it is not recommended to leave so many comments on YOUR parser
|
|
# functions, these defaults provide verbose comments to provide you
|
|
# how-to-write-parser-functions reference
|
|
#
|
|
# refer to them in-order if you are trying to write a parser for the
|
|
# first time
|
|
|
|
source "${0:a:h}/parse.help.zsh"
|
|
source "${0:a:h}/parse.args.zsh"
|
|
|
|
|
|
#####################################################################
|
|
### the easy-but-removed way to go ##################################
|
|
#####################################################################
|
|
|
|
source "${0:a:h}/parse.autosetup.zsh"
|