Skip to content

Commit 5d07f5a

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 ed43613 commit 5d07f5a

File tree

7 files changed

+400
-6
lines changed

7 files changed

+400
-6
lines changed

.settings/com.eclipsesource.jshint.ui.prefs

Lines changed: 0 additions & 2 deletions
This file was deleted.

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

Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,3 +108,184 @@ function ui#requestInputImpl
108108
}
109109

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

102102
# @endsection
103+
104+
# @section Form support
105+
106+
function ui#formAddField
107+
{
108+
_printException "Forms are not supported on TTY" && exit 1
109+
}
110+
111+
# @endsection

0 commit comments

Comments
 (0)