From eea04f0d918ea319aaa03eba3316c8670f048b76 Mon Sep 17 00:00:00 2001 From: Sergey Palcheh Date: Sat, 23 Aug 2025 22:04:29 +0600 Subject: [PATCH] added separation of wine/proton display by groups --- winehelper | 142 ++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 112 insertions(+), 30 deletions(-) diff --git a/winehelper b/winehelper index 78c3322..2bf6b38 100755 --- a/winehelper +++ b/winehelper @@ -847,7 +847,7 @@ init_wine_ver () { unpack "$wine_package" "$WH_DIST_DIR/" try_remove_file "$wine_package" - # Handle Proton's 'files' subdirectory structure by moving contents up + # Управление структурой подкаталога Proton "files", перемещая содержимое вверх if [[ -d "$WINEDIR/files" ]]; then print_info "Обнаружена структура каталогов Proton, исправляем пути..." mv "$WINEDIR"/files/* "$WINEDIR/" @@ -1638,50 +1638,132 @@ select_wine_version() { WINE_METADATA_FILE="$WH_TMP_DIR/wine_metadata.json" [[ ! -f "$WINE_METADATA_FILE" ]] && fatal "Файл метаданных WINE не найден." - local jq_filter + local arch_filter_jq if [[ "$WINEARCH" == "win64" ]]; then print_info "Фильтруем версии для 64-битного префикса..." # Для 64-битных префиксов показываем сборки с 'amd64', 'x86_64', 'wow64' # или те, у которых нет явного указания на 32-битную архитектуру. - jq_filter=' - .[] | .[] | - select( - (.name | test("amd64|x86_64|wow64")) or - (.name | test("i[3-6]86|x86(?!_64)") | not) - ) | .name - ' + arch_filter_jq='select((.name | test("amd64|x86_64|wow64")) or (.name | test("i[3-6]86|x86(?!_64)") | not))' else # win32 print_info "Фильтруем версии для 32-битного префикса..." # Для 32-битных префиксов показываем только сборки с явным указанием 32-битной архитектуры. - jq_filter=' - .[] | .[] | - select(.name | test("i[3-6]86|x86(?!_64)")) | .name - ' + arch_filter_jq='select(.name | test("i[3-6]86|x86(?!_64)"))' fi - # Создание единого, отсортированного списка версий - local versions=() - mapfile -t versions < <(jq -r "$jq_filter" "$WINE_METADATA_FILE" | sort -V -r | uniq) + local options=() + local total_versions_found=0 - if [[ ${#versions[@]} -eq 0 ]]; then + # --- System --- + options+=("--- System ---") + options+=("system") + + # --- Other versions from JSON --- + local group_keys + mapfile -t group_keys < <(jq -r 'keys_unsorted | .[]' "$WINE_METADATA_FILE") + + for key in "${group_keys[@]}"; do + local group_versions + mapfile -t group_versions < <(jq -r --arg key "$key" '.[$key] | .[] | '"$arch_filter_jq"' | .name' "$WINE_METADATA_FILE" | sort -V -r | uniq) + + if [[ ${#group_versions[@]} -gt 0 ]]; then + # Prettify the group name (e.g., "proton_ge" -> "Proton Ge") + local pretty_key + pretty_key=$(echo "$key" | tr '_' ' ' | sed -e "s/\b\(.\)/\u\1/g") + + options+=("--- $pretty_key ---") + options+=("${group_versions[@]}") + ((total_versions_found+=${#group_versions[@]})) + fi + done + + if [[ $total_versions_found -eq 0 ]]; then print_warning "Не найдено подходящих версий WINE/Proton для архитектуры $WINEARCH." print_warning "Будет использована версия по умолчанию: $WH_WINE_USE" return fi - local options=("system" "${versions[@]}") + # --- Пользовательское меню с разделением на группы и пустыми строками --- + local selectable_options=("Отмена") + local display_groups=() + local current_group_items=() + local choice_idx=0 + + # Помощник для переноса текущей группы элементов в основной массив display_groups + flush_current_group() { + if ((${#current_group_items[@]} > 0)); then + # Объединяйте элементы с помощью уникального разделителя для последующего разделения + display_groups+=("$(IFS='@@@'; echo "${current_group_items[*]}")") + current_group_items=() + fi + } + + current_group_items+=(" 0) Отмена создания префикса") + + # Обработка массива основных параметров для создания групп + for opt in "${options[@]}"; do + if [[ "$opt" == "---"* ]]; then + flush_current_group + display_groups+=("$opt") # Добавьте заголовок как отдельный элемент + else + ((choice_idx++)) + current_group_items+=(" ${choice_idx}) $opt") + selectable_options+=("$opt") + fi + done + flush_current_group # Очистка последней группы print_info "Выберите версию WINE/Proton для $WINEARCH префикса:" - PS3="Ваш выбор: " - select opt in "Отмена" "${options[@]}"; do - if [[ "$REPLY" == "1" ]] || [[ "$opt" == "Отмена" ]]; then - print_info "Создание префикса отменено." - exit 0 - elif [[ -n "$opt" ]]; then - export WH_WINE_USE="$opt" + + # Показывать группы одну за другой + local first_block=true + for group_data in "${display_groups[@]}"; do + + if [[ "$group_data" == "---"* ]]; then + if [[ "$first_block" = false ]]; then + echo + fi + echo "$group_data" + else + # Это блок элементов для печати в столбцах + local items_to_print=() + IFS='@@@' read -r -a items_to_print <<< "$group_data" + + local num_items=${#items_to_print[@]} + local term_width=${COLUMNS:-80} + local max_len=0 + for item in "${items_to_print[@]}"; do + (( ${#item} > max_len )) && max_len=${#item} + done + + ((max_len+=2)) + local num_cols=$(( term_width / max_len )) + (( num_cols = num_cols > 0 ? num_cols : 1 )) + local num_rows=$(( (num_items + num_cols - 1) / num_cols )) + + for ((i=0; i= 0 && user_choice <= max_choice )); then + if [[ "$user_choice" == "0" ]]; then + print_info "Создание префикса отменено." + exit 0 + fi + local selected_opt="${selectable_options[$user_choice]}" + export WH_WINE_USE="$selected_opt" break else - print_error "Неверный выбор. Попробуйте еще раз." + print_error "Неверный выбор. Введите число от 0 до $max_choice." fi done } @@ -1737,15 +1819,15 @@ create_prefix() { print_info "Выберите тип создаваемого префикса:" echo " 0) Отмена создания префикса" - echo " 1) С рекомендуемыми библиотеками (по умолчанию)" - echo " 2) Чистый префикс (без библиотек)" + echo " 1) Чистый префикс (без библиотек)" + echo " 2) С рекомендуемыми библиотеками (по умолчанию)" echo local pfx_type_choice read -p "Ваш выбор [0-2] (по умолчанию 1): " pfx_type_choice case "${pfx_type_choice:-1}" in 0) print_info "Создание префикса отменено." ; exit 0 ;; - 1) ;; # Оставляем BASE_PFX пустым, чтобы init_wineprefix использовал значение по умолчанию - 2) export BASE_PFX="none" ;; + 1) export BASE_PFX="none" ;; + 2) ;; # Оставляем BASE_PFX пустым, чтобы init_wineprefix использовал значение по умолчанию *) fatal "Неверный выбор. Операция отменена." ;; esac