Add & implement askNecessaryQuestions

This commit is contained in:
Rezart Qelibari
2022-02-04 14:10:57 +01:00
parent 366047fb20
commit 948f995f57
5 changed files with 389 additions and 1 deletions

View File

@@ -19,7 +19,7 @@ function getFilteredModules() {
if [ "${#module}" -eq 0 ]; then if [ "${#module}" -eq 0 ]; then
echo "${allModules[@]}" echo "${allModules[@]}"
else else
local modulesToKeep=() local mod modulesToKeep=()
for mod in "${allModules[@]}"; do for mod in "${allModules[@]}"; do
local foundAtIndex="${module[(Ie)${mod}]}" local foundAtIndex="${module[(Ie)${mod}]}"
if [ "${inverse}" != 'true' -a "${foundAtIndex}" -gt 0 ]; then if [ "${inverse}" != 'true' -a "${foundAtIndex}" -gt 0 ]; then
@@ -32,6 +32,130 @@ function getFilteredModules() {
fi fi
} }
function runModule() {
local mod="$1"
shift
${_DIR:-.}/${mod} "$@"
}
function parseQuestionLine() {
local questionType parameterName question value arguments args
local -A typeMap=([i]=info [p]=password [c]=confirm [s]=select)
[ -z "${line}" ] && return
[ "${line[2]}" != ':' ] && return 10
questionType="${typeMap[${line[1]}]}"
[ -z "${questionType}" ] && return 11
# remove question type
[ "${line[3]}" = ' ' ] && line="${line:3}" || line="${line:2}"
line=("${(s.=.)line[@]}")
parameterName="${line[1]}"
[ -z "${parameterName}" ] && return 12
[ "${parameterName[1]}" = '-' ] && return 13
# remove parameter name
line="${(j.=.)${(@)line:1}}"
line=("${(s. #.)line}")
question="${line[1]}"
[ -z "${question}" ] && return 14
# remove question part
line="${(j. #.)${(@)line:1}}"
if [ -n "${line}" ]; then
arguments=("${(s.;.)line}")
for arg in "${arguments[@]}"; do
arg=("${(s.:.)arg}")
[ -z "${arg[1]}" ] && return 15
arg[1]="`trim "${arg[1]}"`"
arg[2]="`trim "${arg[2]}"`"
questionType+=";${(j.:.)arg}"
done
fi
printf -v value '%s\n%s' "${question}" "${questionType}"
questions+=("${parameterName}" "${value}")
}
function populateQuestionsWithModuleRequiredInformation() {
for line in "${(f)$(runModule "${mod}" --show-required-information)}"; do
parseQuestionLine
done
}
function convertQuestionArgsToAskUserArgs() {
local arg argName argValue
local instructions=("${(s.;.)questionArgs}")
local questionType="${instructions[1]}"
shift instructions
if [ "${questionType}" = 'info' ]; then
args=(info)
elif [ "${questionType}" = 'password' ]; then
args=('-p' info)
elif [ "${questionType}" = 'confirm' ]; then
args=(confirm)
elif [ "${questionType}" = 'select' ]; then
for arg in "${instructions[@]}"; do
arg=("${(s.:.)arg}")
[ "${#arg}" -lt 2 ] && continue
argName="${arg[1]}"
argValue="${arg[2]}"
[ "${argName}" != 'choose from' ] && continue
choices=("${(s.,.)argValue}")
done
[ "${#choices}" -ge 1 ] || return 10
args=(choose)
fi
}
function askUserQuestion() {
local choices
local questionAndArgs=("${(f)questions[$questionID]}") args=()
local question="${questionAndArgs[1]}" questionArgs="${questionAndArgs[2]}"
convertQuestionArgsToAskUserArgs
askUser "${args[@]}" "${question}"
value="${REPLY}"
}
function generateConfigKeysFromQuestionID() {
setopt localoptions extendedglob
[ $# -lt 2 -o -z "$1" -o -z "$2" ] && return
local modName="${1}" questID="${2}"
modName="${${${${modName//-##/_}/#_/}/%_/}//[^A-Za-z_]/}"
questID="${${${${questID//-##/_}/#_/}/%_/}//[^A-Za-z_]/}"
configkeys=("${modName}" questions "${questID}")
}
function answerQuestionsFromConfigOrAskUser() {
local questionID
config setappname "de.astzweig.macos.system-setup"
for questionID in "${(k)questions[@]}"; do
local value configkeys=()
generateConfigKeysFromQuestionID "${mod}" "${questionID}"
value="`config read "${configkeys[@]}"`"
if [ -z "${value}" ]; then
askUserQuestion
config write "${value}" "${configkeys[@]}"
fi
answers+=("${mod}_${questionID}" "${value}")
done
}
function askNecessaryQuestions() {
local mod
local -A answers
for mod in "${modulesToInstall[@]}"; do
local -A questions=()
populateQuestionsWithModuleRequiredInformation
answerQuestionsFromConfigOrAskUser
done
}
function main() { function main() {
eval "`docopts -f -V - -h - : "$@" <<- USAGE eval "`docopts -f -V - -h - : "$@" <<- USAGE
Usage: $0 [options] [<module>...] Usage: $0 [options] [<module>...]
@@ -50,9 +174,11 @@ function main() {
local modulesToInstall=(`getFilteredModules`) local modulesToInstall=(`getFilteredModules`)
ensureDocopts ensureDocopts
autoloadZShLib autoloadZShLib
askNecessaryQuestions
hio debug "Current working dir is: `pwd`" hio debug "Current working dir is: `pwd`"
} }
if [[ "${ZSH_EVAL_CONTEXT}" == toplevel ]]; then if [[ "${ZSH_EVAL_CONTEXT}" == toplevel ]]; then
_DIR="${0:A:h}"
main main
fi fi

View File

@@ -0,0 +1,63 @@
Describe 'answerQuestionsFromConfigOrAskUser'
Include ./install.sh
mod="testmod"
It 'does nothing if module has no questions'
declare -A questions=()
When call answerQuestionsFromConfigOrAskUser
The output should eq ''
The variable 'questions' should eq ''
The status should be success
End
It 'asks the user if the question is not in the config'
declare -A questions=([question-one]=$'What is your favorite color?\ninfo')
Data 'blue'
config() {}
When call answerQuestionsFromConfigOrAskUser
The output should eq "What is your favorite color? "
The status should be success
End
It 'does not ask the user if the question is stored in the config'
declare -A questions=([question-one]=$'What is your favorite color?\ninfo')
config() { [ "${1}" = read ] && echo red; }
When call answerQuestionsFromConfigOrAskUser
The output should eq ''
The status should be success
End
It 'stores the answer in the answers array if asking user'
declare -A answers
declare -A questions=([question-one]=$'What is your favorite color?\ninfo')
config() {}
Data 'blue'
When call answerQuestionsFromConfigOrAskUser
The output should eq "What is your favorite color? "
The variable "answers[${mod}_question-one]" should eq 'blue'
The status should be success
End
It 'stores the answer in the answers array if retrieving from config'
declare -A answers
declare -A questions=([question-one]=$'What is your favorite color?\ninfo')
config() { [ "${1}" = read ] && echo red; }
When call answerQuestionsFromConfigOrAskUser
The output should eq ''
The variable "answers[${mod}_question-one]" should eq 'red'
The status should be success
End
It 'stores the user answer to config'
declare -A answers
declare -A questions=([question-one]=$'What is your favorite color?\ninfo')
writtenValue=""
Data 'red'
config() { [ "${1}" = read ] && return; [ "${1}" = write ] && writtenValue="${2}" }
When call answerQuestionsFromConfigOrAskUser
The output should eq "What is your favorite color? "
The variable "answers[${mod}_question-one]" should eq 'red'
Assert test "${writtenValue}" = 'red'
The status should be success
End
End

View File

@@ -0,0 +1,52 @@
Describe 'convertQuestionArgsToAskUserArgs'
Include ./install.sh
It 'converts info to info'
args=()
choices=()
questionArgs='info'
When call convertQuestionArgsToAskUserArgs
The output should eq ''
The variable args should eq 'info'
The variable choices should eq ''
The status should be success
End
It 'converts password to -p info'
args=() choices=() questionArgs='password'
When call convertQuestionArgsToAskUserArgs
The variable args should eq '-p info'
The variable choices should eq ''
End
It 'converts confirm to confirm'
args=() choices=() questionArgs='confirm'
When call convertQuestionArgsToAskUserArgs
The variable args should eq 'confirm'
The variable choices should eq ''
End
It 'returns if type is select but no choose from arg is provided'
args=() choices=() questionArgs='select'
When call convertQuestionArgsToAskUserArgs
The variable args should eq ''
The variable choices should eq ''
The status should eq 10
End
It 'converts select to choose'
args=() choices=() questionArgs='select;choose from:blue,light green,red'
When call convertQuestionArgsToAskUserArgs
The variable args should eq 'choose'
The variable choices should eq 'blue light green red'
The variable '#choices' should eq 3
End
It 'finds choose from arg even if many args are provided'
args=() choices=() questionArgs='select;first arg:red;choose from:blue,light green,red;after arg:nine;after arg:nine;'
When call convertQuestionArgsToAskUserArgs
The variable args should eq 'choose'
The variable choices should eq 'blue light green red'
The variable '#choices' should eq 3
End
End

View File

@@ -0,0 +1,59 @@
Describe 'generateConfigKeysFromQuestionID'
Include ./install.sh
It 'does nothing if given no arguments'
declare -A configkeys=()
When call generateConfigKeysFromQuestionID ''
The output should eq ''
The variable 'configkeys' should eq ''
The status should be success
End
It 'does nothing if question id is empty'
declare configkeys=()
When call generateConfigKeysFromQuestionID 'somemod' ''
The output should eq ''
The variable 'configkeys' should eq ''
The status should be success
End
It 'generates key when given module name and question id'
declare configkeys=()
When call generateConfigKeysFromQuestionID 'somemod' 'somekey'
The output should eq ''
The variable 'configkeys' should eq 'somemod questions somekey'
The status should be success
End
It 'replaces minus with underscore'
declare configkeys=()
When call generateConfigKeysFromQuestionID 'some-mod' 'somekey'
The output should eq ''
The variable 'configkeys' should eq 'some_mod questions somekey'
The status should be success
End
It 'replaces multiple minus with single underscore'
declare configkeys=()
When call generateConfigKeysFromQuestionID 'some---mod' 'so--mekey'
The output should eq ''
The variable 'configkeys' should eq 'some_mod questions so_mekey'
The status should be success
End
It 'replaces underscores at the begin and end of string'
declare configkeys=()
When call generateConfigKeysFromQuestionID '--some-mod' '--somekey-'
The output should eq ''
The variable 'configkeys' should eq 'some_mod questions somekey'
The status should be success
End
It 'removes all chars but [A-Za-z_]'
declare configkeys=()
When call generateConfigKeysFromQuestionID '*some≠{mod' '?`somekey'
The output should eq ''
The variable 'configkeys' should eq 'somemod questions somekey'
The status should be success
End
End

View File

@@ -0,0 +1,88 @@
Describe 'parseQuestionLine'
Include ./install.sh
It 'does nothing if the line is empty'
line=''
When call parseQuestionLine
The output should eq ''
The status should be success
End
It 'does nothing if the line does not have a question type'
line='some value here'
When call parseQuestionLine
The output should eq ''
The status should eq 10
End
It 'does nothing if the line does not have a valid question type'
line='z: some value here'
When call parseQuestionLine
The output should eq ''
The status should eq 11
End
It 'does nothing if the line does not have a parameter name'
line='i: '
When call parseQuestionLine
The output should eq ''
The status should eq 12
End
It 'does nothing if the parameter name starts with a dash'
line='i: -parameter-name=Is this my question?'
When call parseQuestionLine
The output should eq ''
The status should eq 13
End
It 'does nothing if the line does not have a question'
line='i: parameter-name='
When call parseQuestionLine
The output should eq ''
The status should eq 14
End
It 'extends outer questions associative array with question'
declare -A questions
line='i: parameter-name=What parameter do you like? #'
When call parseQuestionLine
The output should eq ''
The line 1 of variable 'questions[parameter-name]' should eq 'What parameter do you like?'
The line 2 of variable 'questions[parameter-name]' should eq info
The status should be success
End
It 'does nothing if an argument does not contain a name'
declare -A questions
line='i: parameter-name=What parameter do you like? # some arg = some value;;'
When call parseQuestionLine
The output should eq ''
The variable 'questions' should eq ''
The status should eq 15
End
It 'writes question type to outer questions associative array'
declare -A questions
line='s: parameter-name=What parameter do you like? # choose from: blue,red,light green; default: blue'
When call parseQuestionLine
The line 2 of variable 'questions[parameter-name]' should eq 'select;choose from:blue,red,light green;default:blue'
End
End
Describe "parseQuestionLine type renaming"
Include ./install.sh
Parameters
i info
p password
c confirm
s select
End
It "converts $1 to $2"
declare -A questions
line="${1}: parameter-name=What parameter do you like? #"
When call parseQuestionLine
The line 2 of variable 'questions[parameter-name]' should eq "$2"
End
End