WIP profile-, seq config and edit config support
This commit is contained in:
288
sequencer.sh
288
sequencer.sh
@@ -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,17 +43,21 @@ 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'
|
||||
_sqr_savePosExe= ;[ -t 1 ] && _sqr_savePosExe='\033[s'
|
||||
@@ -251,7 +260,7 @@ USAGE_EOF
|
||||
readonly _sqr_indentHelp=' : '
|
||||
readonly _sqr_indentExe=' '
|
||||
readonly _sqr_indentAppendHelp=' '
|
||||
echoinfo() {
|
||||
echoinfo() {
|
||||
if [ $_sqr_contextHelp -ne 0 ] ; then
|
||||
printf '%s' "$_sqr_indentAppendHelp"; echo "$@"
|
||||
else
|
||||
@@ -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
|
||||
|
||||
@@ -826,9 +1028,9 @@ sqr::main() {
|
||||
# Enable error backtracing
|
||||
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
|
||||
[ ${_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 "$@"
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user