Skip to content

Commit dc69c3b

Browse files
committed
interactive: substring filter for the board picker
When BOARD is not set on the command line, the interactive board picker shows all 400+ boards alphabetically with no built-in way to narrow the list down. Finding a known board by typing only its first letter (the default dialog behaviour) is impractical when several share a prefix. Prepend a sentinel `[set filter]` entry at the top of the menu that opens a dialog --inputbox; the substring is matched case-insensitively against both the board name and its short description. Once a filter is active, a second sentinel `[clear filter]` appears alongside, and the first sentinel shows the current filter and match count. Implementation notes: - A separate dialog button (e.g. --help-button) was tried first but it doesn't fit in an 80x24 terminal alongside the existing OK / Show CSC.. / Cancel triplet -- dialog returns 255 ("screen too small") before the user can react. A sentinel menu entry has no such constraint and keeps the existing button layout intact. - Filter state survives the existing CSC/WIP/EOS toggle and re-filtering on a fresh full list, so toggling expert mode does not lose the substring. - Filtering iterates the cached arr_all_board_options in pure bash (no subshells), so it stays cheap regardless of how many times the user re-opens the inputbox. Assisted-by: Claude:claude-opus-4.7
1 parent fbd165b commit dc69c3b

1 file changed

Lines changed: 50 additions & 2 deletions

File tree

lib/functions/configuration/interactive.sh

Lines changed: 50 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,9 @@ function interactive_config_ask_board_list() {
135135

136136
declare WIP_BUTTON='CSC/WIP/EOS/TVB'
137137
declare STATE_DESCRIPTION=' - boards with high level of software maturity'
138+
declare BOARD_FILTER=''
139+
declare FILTER_TAG='[set filter]'
140+
declare CLEAR_TAG='[clear filter]'
138141
declare temp_rc
139142
temp_rc=$(mktemp) # @TODO: this is a _very_ early call to mktemp - no TMPDIR set yet - it needs to be cleaned-up somehow
140143

@@ -151,6 +154,41 @@ function interactive_config_ask_board_list() {
151154
get_list_of_all_buildable_boards arr_all_board_names arr_all_board_options dict_all_board_types dict_all_board_source_files dict_all_board_descriptions # invoke
152155
board_list_needs_refresh=no
153156
fi
157+
158+
# Apply substring filter (case-insensitive, matches name and description) and
159+
# prepend a sentinel entry that opens an --inputbox to set/change/clear the filter.
160+
# arr_all_board_options is a flat sequence of (tag, item) pairs as dialog expects.
161+
declare -a arr_menu_options=()
162+
if [[ -n "${BOARD_FILTER}" ]]; then
163+
declare lc_filter="${BOARD_FILTER,,}"
164+
declare i tag item hay
165+
declare -a arr_filter_hits=()
166+
for ((i = 0; i < ${#arr_all_board_options[@]}; i += 2)); do
167+
tag="${arr_all_board_options[i]}"
168+
item="${arr_all_board_options[i + 1]}"
169+
# Match against board name + raw description (from dict_all_board_descriptions),
170+
# not against arr_all_board_options' item which carries dialog --colors escapes
171+
# (\Z1...\Zn) and a leading "(type)" badge - those would cause false positives
172+
# for searches like "conf", "wip" or "z1".
173+
hay="${tag} ${dict_all_board_descriptions["${tag}"]}"
174+
hay="${hay,,}"
175+
if [[ "${hay}" == *"${lc_filter}"* ]]; then
176+
arr_filter_hits+=("${tag}" "${item}")
177+
fi
178+
done
179+
declare match_count=$((${#arr_filter_hits[@]} / 2))
180+
arr_menu_options=(
181+
"${FILTER_TAG}" "\Z1change filter (current: ${BOARD_FILTER}, ${match_count}/${#arr_all_board_names[@]} boards)\Zn"
182+
"${CLEAR_TAG}" "\Z1clear filter, show all ${#arr_all_board_names[@]} boards\Zn"
183+
"${arr_filter_hits[@]}"
184+
)
185+
else
186+
arr_menu_options=(
187+
"${FILTER_TAG}" "\Z1filter boards by substring of name or description\Zn"
188+
"${arr_all_board_options[@]}"
189+
)
190+
fi
191+
154192
echo > "${temp_rc}" # zero out the rcfile to start
155193
if [[ $WIP_STATE != supported ]]; then # be if wip csc etc included. I personally disagree here.
156194
cat <<- 'EOF' > "${temp_rc}"
@@ -166,9 +204,9 @@ function interactive_config_ask_board_list() {
166204
DIALOGRC=$temp_rc \
167205
dialog_if_terminal_set_vars --title "Choose a board" --backtitle "$backtitle" --scrollbar \
168206
--colors --extra-label "Show $WIP_BUTTON" --extra-button \
169-
--menu "Select the target board. Displaying:\n$STATE_DESCRIPTION" $TTY_Y $TTY_X $((TTY_Y - 8)) "${arr_all_board_options[@]}"
170-
set_interactive_config_value BOARD "${DIALOG_RESULT}"
207+
--menu "Select the target board. Displaying:\n$STATE_DESCRIPTION" $TTY_Y $TTY_X $((TTY_Y - 8)) "${arr_menu_options[@]}"
171208
declare STATUS=${DIALOG_EXIT_CODE}
209+
declare RESULT="${DIALOG_RESULT}"
172210

173211
if [[ $STATUS == 3 ]]; then
174212
if [[ $WIP_STATE == supported ]]; then
@@ -188,6 +226,16 @@ function interactive_config_ask_board_list() {
188226
board_list_needs_refresh=yes # WIP_STATE changed - rescan to include/exclude wip/csc/eos/tvb
189227
continue
190228
elif [[ $STATUS == 0 ]]; then
229+
if [[ "${RESULT}" == "${FILTER_TAG}" ]]; then
230+
dialog_if_terminal_set_vars --title "Filter boards" --backtitle "$backtitle" \
231+
--inputbox "Case-insensitive substring of board name or description. Empty value clears." 8 "${TTY_X}" "${BOARD_FILTER}"
232+
[[ ${DIALOG_EXIT_CODE} == 0 ]] && BOARD_FILTER="${DIALOG_RESULT}"
233+
continue
234+
elif [[ "${RESULT}" == "${CLEAR_TAG}" ]]; then
235+
BOARD_FILTER=''
236+
continue
237+
fi
238+
set_interactive_config_value BOARD "${RESULT}"
191239
break
192240
else
193241
exit_with_error "You cancelled interactive config" "Build cancelled, board not chosen"

0 commit comments

Comments
 (0)