feat: enhance variant picker (#86)
* fix: variant display is more clear * fix: unable to install all variants * feat: select variants with ranges and exclusions
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
|
||||||
VERSION="0.6.9"
|
VERSION="0.6.10"
|
||||||
|
|
||||||
# --- Globals ---
|
# --- Globals ---
|
||||||
|
|
||||||
@@ -155,6 +155,81 @@ function remove_disabled_prefix() {
|
|||||||
echo "$disabled_file"
|
echo "$disabled_file"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function parse_indexes() {
|
||||||
|
_returned_indexes=()
|
||||||
|
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case "$1" in
|
||||||
|
"--range")
|
||||||
|
[[ -z "$2" ]] && { log ERROR "Function parse indexes: range is required"; exit 1; }
|
||||||
|
range="$2"; shift 2
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
input_indexes+=("$1")
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
# parse input_indexes 1-by-1
|
||||||
|
for index in "${input_indexes[@]}"; do
|
||||||
|
# normal index 5
|
||||||
|
if [[ "$index" =~ ^[0-9]+$ ]]; then
|
||||||
|
[[ $index -lt 1 || $index -gt $range ]] && { log ERROR "Function parse indexes: index $index out of range (1 -> $range)"; exit 1; }
|
||||||
|
_returned_indexes+=("$index")
|
||||||
|
# range index 1..5
|
||||||
|
elif [[ "$index" =~ ^[0-9]+\.\.[0-9]+$ ]]; then
|
||||||
|
# cut doesn't work with a delimiter of two characters
|
||||||
|
start=$(echo "$index" | cut -d. -f1)
|
||||||
|
end=$(echo "$index" | cut -d. -f3)
|
||||||
|
|
||||||
|
[[ $start -lt 1 || $end -lt 1 || $start -gt $range || $end -gt $range ]] && { log ERROR "Function parse indexes: range $index out of range (1 -> $range)"; exit 1; }
|
||||||
|
|
||||||
|
if [[ $start -le $end ]]; then
|
||||||
|
for ((i=start; i<=end; i++)); do
|
||||||
|
_returned_indexes+=("$i")
|
||||||
|
done
|
||||||
|
else
|
||||||
|
for ((i=start; i>=end; i--)); do
|
||||||
|
_returned_indexes+=("$i")
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
# remove index -5
|
||||||
|
elif [[ "$index" =~ ^-[0-9] ]]; then
|
||||||
|
index=${index#-} # remove the - sign
|
||||||
|
|
||||||
|
# if _returned_indexes is empty, populate it with every number from 1 to range
|
||||||
|
[[ ${#_returned_indexes[@]} -eq 0 ]] && for ((i=1; i<=range; i++)); do _returned_indexes+=("$i"); done
|
||||||
|
|
||||||
|
# if exclusion range
|
||||||
|
if [[ "$index" =~ ^[0-9]+\.\.[0-9]+$ ]]; then
|
||||||
|
start=$(echo "$index" | cut -d. -f1)
|
||||||
|
end=$(echo "$index" | cut -d. -f3)
|
||||||
|
|
||||||
|
[[ $start -lt 1 || $end -lt 1 || $start -gt $range || $end -gt $range ]] && { log ERROR "Function parse indexes: exclusion range $index out of range (1 -> $range)"; exit 1; }
|
||||||
|
|
||||||
|
if [[ $start -le $end ]]; then
|
||||||
|
for ((i=start; i<=end; i++)); do
|
||||||
|
_returned_indexes=("${_returned_indexes[@]/$i}") # remove index from array
|
||||||
|
done
|
||||||
|
else
|
||||||
|
for ((i=start; i>=end; i--)); do
|
||||||
|
_returned_indexes=("${_returned_indexes[@]/$i}") # remove index from array
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
# single exclusion
|
||||||
|
[[ $index -lt 1 || $index -gt $range ]] && { log ERROR "Function parse indexes: index $index out of range (1 -> $range)"; exit 1; }
|
||||||
|
|
||||||
|
_returned_indexes=("${_returned_indexes[@]/$index}") # remove index from array
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
log ERROR "Function parse indexes: invalid index $index"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
function get_mod_name_and_index() {
|
function get_mod_name_and_index() {
|
||||||
# if calling install multiple times in the same call of h2mm, the mod_index needs to be reset if it was -1
|
# if calling install multiple times in the same call of h2mm, the mod_index needs to be reset if it was -1
|
||||||
[[ $mod_index -eq -1 ]] && unset mod_index
|
[[ $mod_index -eq -1 ]] && unset mod_index
|
||||||
@@ -822,68 +897,95 @@ function mod_install() {
|
|||||||
|
|
||||||
# directory containing mod files
|
# directory containing mod files
|
||||||
if [[ -n "$mod_dir" ]]; then
|
if [[ -n "$mod_dir" ]]; then
|
||||||
|
# remove trailing slash if it exists
|
||||||
|
mod_dir="${mod_dir%/}"
|
||||||
|
|
||||||
# verify directory exists
|
# verify directory exists
|
||||||
[[ ! -d "$mod_dir" ]] && { log ERROR "Directory $mod_dir does not exist."; exit 1; }
|
[[ ! -d "$mod_dir" ]] && { log ERROR "Directory $mod_dir does not exist."; exit 1; }
|
||||||
|
|
||||||
# read every file from the directory
|
# read every file from the directory
|
||||||
readarray -d '' mod_files < <(find "$mod_dir" -type f -name "*.patch_*" -print0)
|
readarray -d '' mod_files < <(find "$mod_dir" -type f -name "*.patch_*" -print0)
|
||||||
|
|
||||||
# if the name is not specified, use the name of the directory, last sed for making nexusmods names not have numbers
|
# if the name is not specified, use the name of the directory, last sed for making nexusmods names not have numbers
|
||||||
if [[ -z "$mod_name" ]]; then
|
if [[ -z "$mod_name" ]]; then
|
||||||
mod_name=$(echo "$mod_dir" | sed 's:/*$::' | awk -F/ '{print $NF}' | sed -E 's/-[0-9]+-.*//')
|
mod_name=$(echo "$mod_dir" | sed 's:/*$::' | awk -F/ '{print $NF}' | sed -E 's/-[0-9]+-.*//')
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# check for mod variants and handle
|
# check for mod variants and handle
|
||||||
|
# if it's a tmp directory in the format /tmp/tmp.*/, we need to go mindepth 1 to avoid listing the tmp dir itself
|
||||||
|
[[ "$mod_dir" == /tmp/tmp.* ]] && mindepth=1 || mindepth=0
|
||||||
|
|
||||||
# if the mod directory contains more than 1 directory, it means there are multiple variants for the mod
|
# if the mod directory contains more than 1 directory, it means there are multiple variants for the mod
|
||||||
# prompt the user to choose which variant to install, or install multiple
|
# prompt the user to choose which variant to install, or install multiple
|
||||||
readarray -d '' all_dirs < <(find "$mod_dir" -mindepth 1 -type d -print0)
|
readarray -d '' all_dirs < <(find "$mod_dir" -mindepth $mindepth -type d -print0)
|
||||||
|
|
||||||
# filter so that we only have dirs that have *.patch_* files inside them
|
# filter so that we only have dirs that have *.patch_* files inside them
|
||||||
filtered_dirs=()
|
filtered_dirs=()
|
||||||
for dir in "${all_dirs[@]}"; do
|
for dir in "${all_dirs[@]}"; do
|
||||||
if find "$dir" -maxdepth 1 -type f -name "*.patch_*" -print -quit | grep -q .; then
|
if find "$dir" -type f -name "*.patch_*" -print -quit | grep -q .; then
|
||||||
filtered_dirs+=("$dir")
|
filtered_dirs+=("$dir")
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
if [[ ${#filtered_dirs[@]} -gt 1 ]]; then
|
if [[ ${#filtered_dirs[@]} -ne 0 ]]; then
|
||||||
log INFO "Multiple mod variants found for mod ${mod_name}."
|
log INFO "Multiple mod variants found for mod ${mod_name}:"
|
||||||
|
|
||||||
# print the variant name by display all the directories (and how they're nested)
|
# print the variant name by display all the directories (and how they're nested)
|
||||||
# first, take the basename of the directory/zip we're installing from
|
# first, take the basename of the directory/zip we're installing from
|
||||||
# then, make the variant name by removing the tmp dir name from the path (if it's a zip)
|
# then, make the variant name by removing the tmp dir name from the path (if it's a zip)
|
||||||
# finally, take out this name, if it exists
|
# finally, take out this name, if it exists
|
||||||
|
|
||||||
if [[ -n "$mod_zip" ]]; then
|
|
||||||
mod_file_name="$(get_basename "$mod_zip")"
|
|
||||||
else
|
|
||||||
mod_file_name="*"
|
|
||||||
fi
|
|
||||||
|
|
||||||
for i in "${!filtered_dirs[@]}"; do
|
for i in "${!filtered_dirs[@]}"; do
|
||||||
variant_name="${filtered_dirs[$i]#$mod_dir/}" # remote temp name in case its a zip
|
variant_name="${filtered_dirs[$i]}"
|
||||||
log INFO "$((i + 1)). ${variant_name#$mod_file_name/}" # remote the name of the zip/dir if it exists
|
|
||||||
|
# if mod_dir contains /tmp/tmp.*/* then remove the /tmp/tmp.*/ part and leave the rest, else just remove the mod_dir part
|
||||||
|
if [[ "$mod_dir" == /tmp/tmp.* ]]; then
|
||||||
|
variant_name="${variant_name#$mod_dir/*/}" # remove /tmp/tmp.* part
|
||||||
|
|
||||||
|
[[ $i == 0 && "$variant_name" == /tmp/tmp.* ]] && variant_name="$mod_name [base folder]"
|
||||||
|
else
|
||||||
|
variant_name="${variant_name#$mod_dir/}" # remove dir name before it
|
||||||
|
|
||||||
|
[[ $i == 0 && "$variant_name" == "$mod_dir" ]] && variant_name="$mod_name [base folder]"
|
||||||
|
fi
|
||||||
|
|
||||||
|
log INFO "$((i + 1)). $variant_name"
|
||||||
done
|
done
|
||||||
|
|
||||||
# prompt user to choose
|
# prompt user to choose
|
||||||
log PROMPT "Enter the number of the variant(s) to install (separated by space) or press Enter to install all: "
|
log INFO "Use spaces to separate multiple variants (1 2 4) or use ranges (2..5) or use exclusions (-3) or any combination of them (1 3..5 7..12 -10)."
|
||||||
|
log INFO "When only exclusions are present (-3) it means all variants except the excluded ones. You can also use exclusion ranges (-3..5)."
|
||||||
|
log PROMPT "Enter the combination of variants to install (or press Enter to install all variants): "
|
||||||
read -a variant_indices
|
read -a variant_indices
|
||||||
if [[ -n "${variant_indices[0]}" ]]; then
|
if [[ -n "${variant_indices[0]}" ]]; then
|
||||||
# clear mod_files
|
# clear mod_files
|
||||||
mod_files=()
|
mod_files=()
|
||||||
|
|
||||||
# get the files from the chosen variant
|
# use this variable for formatting the mod name
|
||||||
for index in "${variant_indices[@]}"; do
|
has_atleast_one_variant=false
|
||||||
[[ ! "$index" =~ ^[0-9]+$ ]] && { log ERROR "Invalid variant index."; exit 1; }
|
|
||||||
[[ $index -lt 1 || $index -gt ${#filtered_dirs[@]} ]] && { log ERROR "Variant index out of range."; exit 1; }
|
|
||||||
|
|
||||||
readarray -d '' variant_files < <(find "${filtered_dirs[$((index - 1))]}" -type f -name "*.patch_*" -print0)
|
parse_indexes --range ${#filtered_dirs[@]} "${variant_indices[@]}"
|
||||||
|
|
||||||
|
# get the files from the chosen variant
|
||||||
|
for index in "${_returned_indexes[@]}"; do
|
||||||
|
[[ -z "$index" ]] && continue
|
||||||
|
|
||||||
|
# read the files from the directory
|
||||||
|
readarray -d '' variant_files < <(find "${filtered_dirs[$((index - 1))]}" -maxdepth 1 -type f -name "*.patch_*" -print0)
|
||||||
|
|
||||||
# update mod_name to contain the variant name
|
# update mod_name to contain the variant name
|
||||||
mod_name="${mod_name} [$(basename "${filtered_dirs[$((index - 1))]}")]"
|
if [[ $has_atleast_one_variant == false ]]; then
|
||||||
|
mod_name="${mod_name} [$(basename "${filtered_dirs[$((index - 1))]}")"
|
||||||
|
has_atleast_one_variant=true
|
||||||
|
else
|
||||||
|
mod_name="${mod_name} - $(basename "${filtered_dirs[$((index - 1))]}")"
|
||||||
|
fi
|
||||||
|
|
||||||
# add the files to the mod_files array
|
# add the files to the mod_files array
|
||||||
mod_files+=("${variant_files[@]}")
|
mod_files+=("${variant_files[@]}")
|
||||||
done
|
done
|
||||||
|
|
||||||
|
[[ $has_atleast_one_variant == true ]] && mod_name="${mod_name}]"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|||||||
Reference in New Issue
Block a user