Skip to content

Commit b23b9d7

Browse files
committed
WIP: apply/merge conflicts from outdated branch
- backend-api.shl: api spec for `ui#requestDirectoryImpl` - implement implement directory picker in gui and tty BUG/TODO: - requestChoiceImpl must implement repeat loop (move here from `user-interface.shl`) - add prompt about cancel to askDir
1 parent bf191f4 commit b23b9d7

File tree

5 files changed

+397
-2
lines changed

5 files changed

+397
-2
lines changed

sources/fs-root/opt/batocera-emulationstation/lib/ui/gui.shl

Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,3 +77,184 @@ function ui#requestDirectoryImpl
7777
}
7878

7979
# @endsection
80+
81+
# -----------
82+
# @section Form support
83+
84+
# @description
85+
# Repeat form until verified or canceled, place result in assoc `__form_result`
86+
function ui#runFormImpl
87+
{
88+
local __rawResult
89+
local -a __resultLines
90+
local __dialogStatus=1
91+
while [ "$__dialogStatus" != 0 ]; do
92+
__rawResult=$(
93+
"ui#baseDialog" --form --title="$1" \
94+
--separator=$'\n' --num-output --item-separator="|" \
95+
"${__FORM_ARGS[@]}" "${__FORM_DATA[@]}"
96+
)
97+
#shellcheck disable=2181 # not possible here for readability reasons
98+
if [ "$?" -gt 0 ]; then
99+
#dialog got canceled
100+
return 1
101+
fi
102+
readarray -t __resultLines <<< "$__rawResult"
103+
"ui#verifyFormVars" LOOP
104+
__dialogStatus="$?"
105+
done
106+
# apply transformations, if any
107+
"ui#verifyFormVars" RESULT __FORM_DATA
108+
109+
# write the 'real' lines into the result assoc
110+
local idx
111+
for idx in "${!__resultLines[@]}"; do
112+
varName="${__CONFIRM_PARAMETERS[$idx]}"
113+
[ "$varName" != "__skip__" ] || continue
114+
115+
__form_result["$varName"]="${__FORM_DATA[$idx]}"
116+
done
117+
}
118+
119+
# @description
120+
# While a form dialog window is build from input given to [ui:form](../user-interface.shl.md),
121+
# the code needs to keep track of the added fields to ensure that the results can be validated and returned correctly.
122+
# Missing a single argument in the field definitions for the underlying utility, `yad`, can have disastrous effects,
123+
# as it seems to operate on a purely index-based strategy while also splitting `option` arguments from `data`.
124+
# This means that missing just a single `initial data` argument for one field will shift **all** of the following
125+
# arguments left by one entry.
126+
#
127+
# This function makes sure the argument line remains consistent, regardless of field type. It also maintain meta
128+
# information about the form contents/variable names. This meta information is needed at the end when the user
129+
# clicks on OK/Confirm.
130+
#
131+
# **Full explanation**
132+
# Initial arguments represent button actions, combo value lists, the checked state of checkboxes etc,
133+
# However, they are **not** the text/label used as 'explanation'. These are part of an 'option'. Example:
134+
#
135+
# ```bash
136+
# yad --form --field="Some detail":LBL --field="Confirm":CHK true
137+
# ```
138+
#
139+
# One might expect that this yields a dialog with a label and a pre-checked checkbox. This is not what happens.
140+
# Labels do not use initial data, but the argument processing still requires it.
141+
# The label is the first field and does not have initial data following its `--field` argument,
142+
# so it takes the initial data given with index 0, which is 'true'.
143+
# The checkbox would have to take data index 1, but that does not exist, thus it remains unchecked.
144+
# Working variants of the example above:
145+
#
146+
#```bash
147+
# # interleaving initial data and fields
148+
# yad --form --field="Some detail":LBL '' --field="Confirm":CHK true
149+
#
150+
# #initial data at the end
151+
# yad --form --field="Some detail":LBL --field="Confirm":CHK '' true
152+
#```
153+
#
154+
# @arg $1 string field type
155+
# @arg $2 string name of the variable meant to contain the result
156+
# @arg $3 string field explanation
157+
# @arg $4 string initial data (optional) - will be passed as empty string if not given.
158+
# Please not that most fields are not functional without initial data.
159+
# The empty string only prevents the worst case, shifting values to unexpected places.
160+
function ui#formAddField
161+
{
162+
local fieldType="$1"
163+
local varName="$2"
164+
local message="$3"
165+
local iniData=${4:-''}
166+
167+
# Skip creation of long label. Needed to prevent recursion between 'ui#formAddField' and 'ui#formLabel'
168+
[ "$fieldType" != LBL ] || "ui#formLabel" message
169+
170+
__FORM_ARGS+=("--field=${message}:${fieldType:- }")
171+
__FORM_DATA+=("${iniData}")
172+
__CONFIRM_PARAMETERS+=("${varName}")
173+
}
174+
175+
# @endsection
176+
177+
# -----------
178+
# @section Implementation-specific helper functions
179+
180+
# @description
181+
# In form dialogs, question labels are normally placed in front of the inputs, in a tabular manner.
182+
# Sentences which are too long make the dialog look strange. To prevent this, the text must be moved
183+
# into a dedicated read-only label above the actual text.
184+
# This is what this function does: Any sentence longer than 3 words is declared as label instead.
185+
# This function meant to be called within the context of a running `form`.
186+
# First argument must be the name of the variable containing the sentence to check.
187+
# The variable's content will be modified accordingly.
188+
function ui#formLabel
189+
{
190+
local -n __label="$1"
191+
__label=$(lc "$__label")
192+
local __words=""
193+
_explode __words "$__label"
194+
if [ "${#__words[@]}" -gt 3 ]; then
195+
"ui#formAddField" LBL __skip__ "$__label"
196+
__label=""
197+
fi
198+
}
199+
200+
# @description
201+
# To be used from within 'ui#runFormImpl'. Goes over arrays and verifies content of __resultLines.
202+
# Behaviour of verifier functions can potentially be different in LOOP and RESULT modes:
203+
# - stdout in LOOP mode shall be used to change initial value when re-opening the form
204+
# - In RESULT mode, if required, a mapping of the form-internal keys to the expected output is to be done.
205+
# This is mostly the case for choice questions which get indices as raw values, but should return 'key' strings.
206+
#
207+
# When given `$2`, the output of verifiers is written at the array index corresponding to input.
208+
# For correct mapping of values to verifiers, a correctly populated array __CONFIRM_PARAMETERS is required.
209+
# It must be of the same length as `__resultLines` and map indices to var names, or use `__skip__` for lines to ignore.
210+
#
211+
# @arg $1 mode-string LOOP/RESULT
212+
# @arg $2 arr-name result array name
213+
function ui#verifyFormVars
214+
{
215+
if [ -v "$2" ]; then
216+
local -n resultArr="$2"
217+
else
218+
local -a resultArr
219+
fi
220+
local verifier varName adjustedValue
221+
local numErrors=0
222+
local idx
223+
for idx in "${!__resultLines[@]}"; do
224+
varName="${__CONFIRM_PARAMETERS[$idx]}"
225+
[ "$varName" != "__skip__" ] || continue
226+
227+
verifier=()
228+
_explode verifier "${__VERIFIERS[$varName]:-"ui#verifyPassActual"}"
229+
if ! adjustedValue=$(VMODE="$1" "${verifier[@]}" "${__resultLines[$idx]}" "${__FORM_DATA[$idx]}"); then
230+
(( ++numErrors ))
231+
fi
232+
233+
# shellcheck disable=2034 # either reference to outside, or local to swallow values (unused on purpose)
234+
resultArr[idx]="$adjustedValue"
235+
done
236+
return "$numErrors"
237+
}
238+
239+
# @description
240+
# Implementation of a verifier for choice-questions in forms.
241+
# @arg $1 name of array containing original choice keys (provided by ui:askChoice)
242+
# @arg $2 (changed) value of the current loop iteration/retry
243+
function ui#verifyChoice
244+
{
245+
local -n arr="$1"
246+
if [ "$VMODE" = "LOOP" ]; then
247+
# For now: Just re-build the choice list.
248+
# Later on: translate $2 into `^` at the right place to keep pre-selected value on restart
249+
_join \| "${arr[@]}"
250+
elif [ "$VMODE" = "RESULT" ]; then
251+
echo -n "${arr[$2]}"
252+
fi
253+
}
254+
255+
function ui#verifyPassActual
256+
{
257+
printf '%s' "$1"
258+
}
259+
260+
# @endsection

sources/fs-root/opt/batocera-emulationstation/lib/ui/tty.shl

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,3 +63,12 @@ function ui#requestDirectoryImpl
6363
}
6464

6565
# @endsection
66+
67+
# @section Form support
68+
69+
function ui#formAddField
70+
{
71+
_printException "Forms are not supported on TTY" && exit 1
72+
}
73+
74+
# @endsection

0 commit comments

Comments
 (0)