WIP added help and related functions

Some refactoring and shellcheck; TODO: template
This commit is contained in:
2022-05-18 18:42:12 +02:00
parent a67c92555d
commit b11c7d2a3f

View File

@@ -45,10 +45,17 @@ set -o pipefail
_sqr_dry=0
_sqr_verbose=0
_sqr_errno=0
_sqr_contextHelp=0
_sqr_contextExe=0
_sqr_editor=
sqr_editor=
## Terminal position
_sqr_savePosAlias= ;[ -t 1 ] && _sqr_savePosAlias='\033[1A\033[1C\033[s\033[1B\033[1C'
_sqr_savePosExe= ;[ -t 1 ] && _sqr_savePosExe='\033[s'
_sqr_savePos= ;[ -t 1 ] && _sqr_savePos='\033[3D\033[s\033[3C'
_sqr_restorePos= ;[ -t 1 ] && _sqr_restorePos='\033[u'
# Colors
## Terminal colors
col_black= ; [ -t 1 ] && col_black='\033[0;30m'
col_darkgrey= ; [ -t 1 ] && col_darkgrey='\033[1;30m'
col_red= ; [ -t 1 ] && col_red='\033[0;31m'
@@ -68,6 +75,46 @@ set -o pipefail
col_off= ;[ -t 1 ] && col_off='\033[0m' # No Color
}
helpSequencer() {
cat <<USAGE_EOF
Usage: ${seq_name} [OPTIONS] [STEP NUMBER(s) or ALIAS] [STEP ARGUMENTS]
[OPTIONS]
--all, -a : Run all steps regardless of continuity
--config, -c : Open sequence configuration file (also sets -qq)
--dry-run, -d : Only print to console what would be done
! Attention - Sequence must support this
--help, -h : Display help
--helpapi, -ha : Display help about build-in supporting functions
(e.g. exe,addconf,echerr,...)
--liststeps, -ls : List all step numbers and alias
--profile, -p : Sequence configuration profile name (default: "default")
(if supported by sequence)
-pl : List available profiles
--quiet, -q : Don't ask for permission to execute steps
If called without starting step number, only this help is shown
-qq : Same as --quiet but suppresses regular sequencer.sh output
--single, -s : Execute only one step
If more than one step is requested, only the first will be executed
--verbose, -v : Verbose output (use exe() function to call shell commands in seqs)
( e.g.: exe apt update )
--version : Display version of sequencer and revision of sequence
-- : End options marker
++ : Quick start step 1 (-qq) and skipping [STEP NUMBER(s) or ALIAS]
[STEP NUMBER"(s)" 1-${_sqr_stepMax} or ALIAS]
No STEP or ALIAS : assume 1 as starting point
Single STEP or ALIAS : starting point of sequential process
Multiple STEPS or ALIAS : execute only given steps
(e.g. $0 "2 4 12")
multiple steps need to be given as string
[STEP ARGUMENTS]
* : Arguments will be passed to selected steps and step infos as:
\$2 ...
\$1 is always the step number
USAGE_EOF
}
## Logging
{
LOG_LEVEL="${LOG_LEVEL:-3}" # 4 = debug -> 0 = fatal (stop)
@@ -199,6 +246,29 @@ set -o pipefail
tput setab 7 ;;
esac
}
# Echo additional line to info correctly indented
readonly _sqr_indentHelp=' : '
readonly _sqr_indentExe=' '
readonly _sqr_indentAppendHelp=' '
echoinfo() {
if [ $_sqr_contextHelp -ne 0 ] ; then
printf '%s' "$_sqr_indentAppendHelp"; echo "$@"
else
printf '%s' "$_sqr_indentExe"; echo "$@"
fi
}
# Echo info about step arguments
# Needs to be called first in _info() function
echoinfoArgs() {
echo -e "${_sqr_restorePos}$*"
if [ $_sqr_contextExe -ne 0 ]; then
printf '%s' "$_sqr_indentExe"
else
printf '%s' "$_sqr_indentHelp"
fi
}
}
## Traps
@@ -252,6 +322,11 @@ exists() {
[[ -n "${!1:-}" ]]
fi
}
# editor [FILE(s)..]
# Starts the detected system text editor
editor() {
"${_sqr_editor}" "$@"
}
# interactive
# Started with -q to use defaults for confirmations
interactive() {
@@ -277,10 +352,17 @@ dry() {
verbose() {
(( _sqr_verbose ))
}
contextHelp() {
(( _sqr_contextHelp ))
}
contextExe() {
(( _sqr_contextExe ))
}
### interactive
# confirm [OPTIONS] [--] [QUESTION]
# Default (empty character) = no
# Invalid character trigger the default
#
# [OPTIONS]
# -f : interactive even if quiet
@@ -290,7 +372,7 @@ verbose() {
confirm() {
sqr::debugPause
local arg=
local rexReply='^[Yy]$' # default no
local rexReply='^[Yy]+$' # default no
local inputHelp='[y/N] ' # default no
local noHelp=0
local force=0
@@ -306,7 +388,7 @@ confirm() {
noHelp=1
shift ;;
-y)
rexReply='^[Yy]*$' # default yes
rexReply='^[^Nn]*$' # default yes
inputHelp='[Y/n] ' # default yes
shift ;;
esac
@@ -390,8 +472,8 @@ getReturn() {
# endReturn [-f] [-o ERRORCODE] [MESSAGE]
# -f : force exit with $_sqr_errno without user input
# -o : override and check given error code
# MESSAGE : Custom error message
# -o : override and check given [ERRORCODE]
# [MESSAGE] : Custom error message
#
endReturn() {
local arg
@@ -445,9 +527,9 @@ endReturn() {
else
error -e "Return value ${errorCode} detected."
fi
if confirm -y "End sequence"; then
if confirm -y "End sequence" ; then
error -e "Sequence stopped"
exit "${errorCode}";
exit "${errorCode}"
else
# reset saved error code if user chooses to continue
_sqr_errno=0
@@ -457,6 +539,183 @@ endReturn() {
fi
}
# checkStep <Step Number or Alias>
# return 0 - for invalid step
# return Step Number
# Check sanitiy of step number or
# Check if alias exists
checkStep() {
local checkStep_rex='^[0-9]+$'
local checkStep_ref=""
# Check if string is a number or alias
if ! [[ "${1:-}" =~ ${checkStep_rex} ]] ; then
eval 'checkStep_ref=${_sqr_alias_'"${1:-}"'}'
# Catch special character after eval
if ! [[ "${checkStep_ref}" =~ ${checkStep_rex} ]] ; then
checkStep_ref=0
fi
else
checkStep_ref="$1"
fi
if (( checkStep_ref < 1 || checkStep_ref > _sqr_stepMax )) ; then
error "Invalid step: ${1:-}"
printf '0'
return 1
else
if exists -f "step_$checkStep_ref" ; then
printf '%s' "${checkStep_ref}"
return 0
else
# step doesn't exist
error "Invalid step: ${1:-}"
printf '0'
return 1
fi
fi
}
# step <Step Number of Alias>
# execute given step
step() {
local stepNo=0
local stepArgs=("$@")
if ! stepNo="$(checkStep "${1:-}")" ; then
return 1
else
"step_$stepNo" "${stepArgs[@]}"
fi
color
}
# Parse alias functions "step_[STEP NUBER]_alias" to create
# back reference variable of schema:
# alias_[ALIAS]=[STEP NUMBER]
parseAlias() {
local i
for ((i=1; i<=_sqr_stepMax; i++)); do
# Check for alias definition
exists -f "step_${i}_alias" || continue
# Function returns step alias
eval '_sqr_alias_'"$("step_${i}_alias")"'='"$i"
done
}
# displayHelp [NO TEMPLATE] [STEP NUMBER OR ALIAS]
# [NO TEMPLATE]
# 0 (default) : Ask for template creation
# 1 : Do not ask for template creation
# [STEP NUMBER OR ALIAS]
# [NO TEMPLATE] must be set
# Display step info function only for given step
#
# - Display sequencer help and, if available, sequence help
# - Cluster continous (more than 1) steps visually together
displayHelp() {
sqr::debugPause
local i
local answer
local clusterSize=0
local lastClusterSize=0
local createTemplate=1
local stepFound=0
local loopStart=0
local loopEnd="${_sqr_stepMax}"
_sqr_contextHelp=1
# check if help is requested for a single step
if [ -n "${2:-}" ]; then
parseAlias
loopStart="$(checkStep "$2")"
fi
if [[ "$loopStart" == "0" ]] ; then
helpSequencer
loopStart=1
else
# Output loop only for one step
loopEnd=$loopStart
fi
if [ -n "${1:-}" ] && [[ ${1:-} -eq 1 ]] ; then
createTemplate=0
fi
# check if step definition exists by looking for a step_*() function
for ((i=1; i<=_sqr_stepMax; i++)); do
if ! exists -f "step_${i}" ; then
continue
fi
stepFound=$i
break
done
if [[ "$stepFound" -eq 0 ]] ; then
printf '\n %s\n' "It seems ${0##*/} was called directly."
printf ' %s\n\n' "Please create a sequence script first."
if [ $createTemplate -ne 0 ] ; then
if confirm -- " Create a template now?" ; then
sqr::echo "TODO: createTemplate"
if [ $? -eq 0 ] ; then
printf '\n %s\n' "$TEMPLATE_NAME created."
else
printf '\n %s\n' "$TEMPLATE_NAME exists...Nothing to do!"
fi
else
printf '\n Nothing to do!\n'
fi
fi
exit 1
else
printf '\n %s\n' "Step (= alias) [STEP ARGS] : documentation"
for ((i=loopStart; i<=loopEnd; i++)); do
# Display step reference in help if step function exists
if ! exists -f "step_${i}" ; then
if [ $clusterSize -ne 0 ] ; then
# Mark the end of a cluster
lastClusterSize=$clusterSize
clusterSize=0
fi
continue
fi
((clusterSize+=1))
if [ $lastClusterSize -gt 1 ] ; then
# Add separation at the end of a cluster
lastClusterSize=0
echo
elif [[ $clusterSize -eq 1 ]]; then
# Add separation before the start of a cluster if it is not the first
exists -f "step_$((i+1))" && [[ $i -ne $stepFound ]] && echo
fi
printf ' %3s ' "$i"
# Display alias if exists
if exists -f "step_${i}_alias" ; then
echo -en " = ${col_orange}$("step_${i}_alias")${col_off}${_sqr_savePosAlias}"
# Newline only if step info() exists
exists -f "step_${i}_info" && printf '\n%s' "$_sqr_indentHelp"
else
echo -en " : ${_sqr_savePos}"
fi
# Display step help only if info function exists
if exists -f "step_${i}_info" ; then
"step_${i}_info" "$i"
else
echo
fi
color ""
done
echo
fi
_sqr_contextHelp=0
sqr::debugContinue
}
# listSteps [FILTER STRING]
# [FILTER STRING]
# show only steps and aliases starting with [FILTER STRING]
@@ -526,6 +785,8 @@ sqr::noEditor() {
}
sqr::main() {
local quickStartOne=0
# options check
for arg in "$@" ; do
case "$1" in
@@ -535,6 +796,9 @@ sqr::main() {
--dry-run|-d)
_sqr_dry=1
shift ;;
--help|-h) # show only help
displayHelp 1 "${2:-}"
exit 0;;
--liststeps|-ls)
shift
listSteps "${1:-}"
@@ -563,19 +827,40 @@ sqr::main() {
trap 'sqr::error_report "${FUNCNAME:-.}" ${LINENO}' ERR
fi
# Don't show help if only configuration should be edited
# TODO [ $SEQ_CONFIG_EDIT -ne 0 ] && [ -z "$1" ] && QUIET=2
if [ -z "${1:-}" ] && [ $quickStartOne -eq 0 ] ; then
if ! quiet ; then
# Empty -> show help
displayHelp
fi
# Assume starting at one for interactive mode
START=1
elif [ $quickStartOne -ne 0 ] ; then
EMPTYCALL=0
START=1
STEP_ARGS=( "$@" )
else
EMPTYCALL=0
read -r -a START <<< "$1"
shift
STEP_ARGS=( "$@" )
fi
# Determine system default editor
# Change with update-alternatives --config editor
sqr_editor="$(realpath -eq "/etc/alternatives/editor")"
_sqr_editor="$(realpath -eq "/etc/alternatives/editor")"
## Various fallbacks
[ -z "${sqr_editor}" ] && sqr_editor="$EDITOR"
[ -z "${sqr_editor}" ] && sqr_editor="$(command -v nano)"
[ -z "${sqr_editor}" ] && sqr_editor="$(command -v vi)"
[ -z "${_sqr_editor}" ] && _sqr_editor="$EDITOR"
[ -z "${_sqr_editor}" ] && _sqr_editor="$(command -v nano)"
[ -z "${_sqr_editor}" ] && _sqr_editor="$(command -v vi)"
## Fall back to error message
[ -z "${sqr_editor}" ] && sqr_editor="sqr::noEditor"
[ -z "${_sqr_editor}" ] && _sqr_editor="sqr::noEditor"
sqr::printf 'Running...\n'
seq_config 2>/dev/null || true
step_1 "$@"
step 1 "$@"
}
sqr::main "$@"