WIP profile-, seq config and edit config support

This commit is contained in:
2022-05-23 22:43:22 +02:00
parent b11c7d2a3f
commit 8bd247759b

View File

@@ -1,5 +1,6 @@
#!/usr/bin/env bash
# shellcheck disable=SC2034 # variable not used
# shellcheck disable=SC1090 # follow non constant source
# Exit on error. Append "|| true" if you expect an error.
set -o errexit
@@ -28,9 +29,13 @@ set -o pipefail
# shellcheck disable=SC2015 # && || is not if else
readonly seq_invocation="$(printf '%q' "${0}")$( (($#)) && printf ' %q' "$@" || true)"
seq_args=
seq_configFile= # Filled by initSeqConfig
# May be overwritten by seq
seq_configFile="${seq_fileName}.cfg"
seq_configName="${seq_fileName}.cfg"
seq_configTemplate="${0%.*}.cfg.example"
seq_profileName=
_seq_profileList=
## Sequencer
readonly sqr_dir="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
@@ -38,16 +43,20 @@ set -o pipefail
readonly sqr_name="${sqr_file%%.*}"
readonly sqr_origin="$(cd -- "$(dirname -- \
"$(readlink -f -- "${BASH_SOURCE[0]}")")" && pwd)"
sqr_args=
_sqr_stepMax=512
_sqr_interactive=1
_sqr_debug=0
_sqr_dry=0
_sqr_verbose=0
_sqr_errno=0
_sqr_configEdit=0
readonly _sqr_configDirName=".seqs"
_sqr_configRoot="${HOME}/${_sqr_configDirName}"
_sqr_contextHelp=0
_sqr_contextExe=0
_sqr_debug=0
_sqr_dry=0
_sqr_editor=
_sqr_errno=0
_sqr_interactive=1
readonly _sqr_stepMax=512
_sqr_verbose=0
## Terminal position
_sqr_savePosAlias= ;[ -t 1 ] && _sqr_savePosAlias='\033[1A\033[1C\033[s\033[1B\033[1C'
@@ -303,7 +312,6 @@ running() {
# : either a variable name or
# -f : a function
exists() {
sqr::debugPause
local func=
local arg=
@@ -315,7 +323,6 @@ exists() {
func="${2:-}"
esac
done
sqr::debugContinue
if [[ -n "${func}" ]] ; then
declare -F "${func}" &>>/dev/null
else
@@ -494,7 +501,7 @@ endReturn() {
if [[ "${1:?}" =~ ${rex} ]] ; then
errorCode="${1:?}"
else
warning " [W] Ignoring invalid error code: $1"
warning "Ignoring invalid error code: $1"
fi
shift
;;
@@ -539,6 +546,23 @@ endReturn() {
fi
}
# endIfEmpty <VariableName> [DESCRIPTION]
# DESCRIPTION : Optional text for error
endIfEmpty() {
eval 'local ref=$'"${1:-}"
if [ -z "${ref:-}" ] ; then
if [ -n "${2:-}" ] ; then
error -- "$2"
error -a "Sequence stopped."
else
error -- "\${$1} must not be empty."
error -a "Sequence stopped."
fi
exit 6
fi
}
# checkStep <Step Number or Alias>
# return 0 - for invalid step
# return Step Number
@@ -594,6 +618,7 @@ step() {
# back reference variable of schema:
# alias_[ALIAS]=[STEP NUMBER]
parseAlias() {
sqr::debugPause
local i
for ((i=1; i<=_sqr_stepMax; i++)); do
# Check for alias definition
@@ -602,6 +627,7 @@ parseAlias() {
# Function returns step alias
eval '_sqr_alias_'"$("step_${i}_alias")"'='"$i"
done
sqr::debugContinue
}
# displayHelp [NO TEMPLATE] [STEP NUMBER OR ALIAS]
@@ -745,12 +771,164 @@ listSteps() {
[ ${#aList[@]} -ne 0 ] && printf '%s\n' "${aList[*]}"
}
# listProfiles [OPTION] [SEARCH]
# List all available profiles for current user
# [OPTION]
# -q : only check for profile support
listProfiles() {
local file=
local profiles=()
if [[ ${_sqr_configDirName} == $(basename "${_sqr_configRoot}") ]] ; then
error "${seq_name} does not have configuration profiles"
return 1
fi
[[ "${1:-}" == "-q" ]] && return 0
#for file in $(ls "${_sqr_configRoot}" 2>/dev/null); do
for file in "${_sqr_configRoot}"/* ; do
file="$(basename -- "${file}")"
[[ ${file%.*} =~ ^${1:-".*"} ]] && profiles+=("${file%.*}")
done
printf '%s\n' "${profiles[*]}"
}
# showVersion
showVersion() {
printf 'Sequencer %s\n' "${_sqr_versionString}"
printf 'Seq Revision %s\n' "${VERSION_SEQREV:-"-"}"
}
# initSeqConfig [OPTION] <NAME> [TEMPLATE]
# Create a configuration file in the users' home.
# Source it if already existent
# [OPTION]
# -p : <NAME> is subfolder used for profiles
# -t : Source config also if created from template
# -e : Create empty configuration if no template is found
# Return
# 0 : Sourced configuration or
# (-t) : created and sourced configuration from template
# 1 : Created configuration from template but not sourced
# 2 : Created empty configuration
# 3 : No configuration created
initSeqConfig() {
local arg
local answer=n
local retVal=255
local sourceAlways=0
local createEmpty=0
local seqProfiles=0
local configExists=
local configDir=
for arg in "$@" ; do
case "$1" in
-e)
createEmpty=1
shift ;;
-p)
seqProfiles=1
shift ;;
-t)
sourceAlways=1
shift ;;
esac
done
local configLoc="$_sqr_configRoot/$1"
if [[ $seqProfiles -ne 0 ]] ; then
[ -z "$seq_profileName" ] && seq_profileName=default
configLoc="$_sqr_configRoot/$1/${seq_profileName}.cfg"
fi
configDir="$(dirname -- "$configLoc")"
local configTemplate="$2"
# Don't create anything if only profiles should be listed
if [ -n "${_seq_profileList}" ] ; then
_sqr_configRoot="$configDir"
return 0
fi
_sqr_configRoot="$configDir"
if [ -s "$configLoc" ] ; then
info "Using configuration file: $configLoc"
seq_configFile="$configLoc"
. "$configLoc"
return 0
fi
# Ask for config creation if not existent
if ! quiet && ! dry ; then
sqr::echo " [i] Configuration $configLoc missing"
confirm "Create it now?" || return 3
fi
# Create config subdir in users home
if [ ! -e "$configDir/" ] ; then
sqr::echo -n "Creating $(realpath -- "$configDir")..."
# shellcheck disable=SC2015 # && || is not if else
exe install -m 700 -d "$configDir" && sqr::echo "Ok" || sqr::echo "Nok"
fi
# Config does not exist, check for template
if [ -s "$configTemplate" ] ; then
# Check first if there is an existing configuration at the templates position
configExists="$(dirname -- "$configTemplate")/$1"
if [ -s "$configExists" ] ; then
exe mv "$configExists" "$configLoc"
endReturn -o $? "Unable to use existing configuration: $configExists"
sqr::echo " [i] Using existing configuration: $configExists"
sqr::echo " (Moved to $configDir)"
. "$configLoc"
retVal=0
else
# Install new template to the final location
exe install -m 600 -T "$configTemplate" "$configLoc"
endReturn -o $? "Failed to create configuration"
if [ $sourceAlways -eq 0 ] ; then
if [ $_sqr_configEdit -eq 0 ] ; then
warning "Seq configuration created from template but not used"
warning -a "Please modify \"$configLoc\" first"
fi
retVal=1
else
warning "Using seq configuration from template $configTemplate"
warning -a " (Copied to $configDir)"
. "$configTemplate"
retVal=0
fi
fi
seq_configFile="$configLoc"
else
warning "Seq configuration template not found"
fi
if [ $createEmpty -ne 0 ] ; then
# Create empty config file
warning "Created empty configuration file $configLoc"
exe touch "$configLoc"
exe chmod 600 "$configLoc"
seq_configFile="$configLoc"
retVal=2
fi
# Give the user a chance to edit the create config file
if [ $retVal -eq 255 ]; then
error "No seq configuration created"
retVal=3
elif ! quiet && ! dry ; then
if confirm "Edit configuration file now?" ; then
exe editor "$configLoc"
. "$configLoc"
retVal=0
fi
fi
return $retVal
}
# exe <COMMAND>
# Handle dry run and verbose output for commands without pipe and/or redirects
exe() {
@@ -785,11 +963,17 @@ sqr::noEditor() {
}
sqr::main() {
local emptyCall=1
local quickStartOne=0
# options check
for arg in "$@" ; do
case "$1" in
case "${1:-}" in
--) # end parameter
shift && break;;
--config|-c) # open sequence configuration file
_sqr_configEdit=1
shift;;
--debug)
_sqr_debug="1"
shift ;;
@@ -798,24 +982,42 @@ sqr::main() {
shift ;;
--help|-h) # show only help
displayHelp 1 "${2:-}"
exit 0;;
exit 0 ;;
--liststeps|-ls)
shift
listSteps "${1:-}"
exit 0;;
exit 0 ;;
--profile|-p) # seq profile name
sqr_args+=" $1 ${2:-}"
shift
# Cover the case when only -p is given without profile name
if [ -z "${1:-}" ] ; then
seq_profileName=default
else
seq_profileName="$1" && shift
fi ;;
-pl) # List available profiles with search
shift
[[ ${LOG_LEVEL} -gt 1 ]] && LOG_LEVEL=1 # "only show errors"
_seq_profileList="${1:-".*"}"
[ -n "${1:-}" ] && shift
;;
--quiet|-q)
sqr_args+=" $1"
_sqr_interactive=0
shift ;;
--silent|-qq)
sqr_args+=" $1"
_sqr_interactive=0
LOG_LEVEL=0
shift ;;
--verbose|-v)
sqr_args+=" $1"
_sqr_verbose=1
shift ;;
--version) # version request
showVersion
exit 0;;
exit 0 ;;
esac
done
@@ -828,7 +1030,7 @@ sqr::main() {
fi
# Don't show help if only configuration should be edited
# TODO [ $SEQ_CONFIG_EDIT -ne 0 ] && [ -z "$1" ] && QUIET=2
[ ${_sqr_configEdit} -ne 0 ] && [ -z "${1:-}" ] && LOG_LEVEL=1
if [ -z "${1:-}" ] && [ $quickStartOne -eq 0 ] ; then
if ! quiet ; then
@@ -838,14 +1040,14 @@ sqr::main() {
# Assume starting at one for interactive mode
START=1
elif [ $quickStartOne -ne 0 ] ; then
EMPTYCALL=0
emptyCall=0
START=1
STEP_ARGS=( "$@" )
seq_args=( "$@" )
else
EMPTYCALL=0
emptyCall=0
read -r -a START <<< "$1"
shift
STEP_ARGS=( "$@" )
seq_args=( "$@" )
fi
# Determine system default editor
@@ -858,8 +1060,48 @@ sqr::main() {
## Fall back to error message
[ -z "${_sqr_editor}" ] && _sqr_editor="sqr::noEditor"
parseAlias
# run configuration for sequence only if available and if first step is valid
if exists -f seq_config ; then
# Create/edit configuration file
if [ $_sqr_configEdit -ne 0 ] ; then
# Suppress seq_config output for editing
quietSave=${LOG_LEVEL}
LOG_LEVEL=0
seq_config "${seq_args[@]}"
LOG_LEVEL=${quietSave}
if [ -w "$seq_configFile" ]; then
exe editor "$seq_configFile"
else
error "No configuration file available"
fi
[ ${emptyCall} -ne 0 ] && exit 0
fi
if checkStep "${START[0]}" >/dev/null ; then
if ! seq_config "${seq_args[@]}" ; then
error "Configuring sequence failed"
exit 1
fi
else
return 1
fi
elif [ ${_sqr_configEdit} -ne 0 ] ; then
error "Sequence does not have a configuration file"
return 1
fi
# Check for profile support
if [ -n "${_seq_profileList}" ]; then
listProfiles "${_seq_profileList}"; exit $?
elif [ -n "${seq_profileName}" ]; then
listProfiles -q || exit 1
fi
sqr::printf 'Running...\n'
seq_config 2>/dev/null || true
step 1 "$@"
}