Files
add-synced-lyrics/lib/options.sh
T
2026-04-25 19:09:19 -05:00

179 lines
4.2 KiB
Bash

#!/usr/bin/env bash
# many functions are invoked via variables
# shellcheck disable=SC2329
usage() {
echo "${PROGNAME} [options]
OPTIONS:
-d, --dir process files in directory
-r, --recurse recursively process directory
-f, --file process one file
-n, --dry-run do not actually add synced lyrics,
just show the files that would be processed
-e, --eval output bash functions that can be directly processed
by eval for use with testing this script.
-i, --ignore ignore errors, and continue attempting to find lyrics
even in the case of errors
-h, --help show this output
--debug extra information useful for debugging"
exit "${EXIT_CODE:-1}"
}
set_default_options() {
DIR=${DIR:-}
FILE=${FILE:-}
RECURSE=${RECURSE:-false}
DRY_RUN=${DRY_RUN:-false}
IGNORE=${IGNORE:-false}
DEBUG=${DEBUG:-false}
# cache
CACHE_HOME="${XDG_CACHE_HOME:-"${HOME}/.cache"}"
CACHE_DIR="${CACHE_HOME}/add-synced-lyrics"
if [[ ! -d "${CACHE_DIR}" ]]; then
mkdir "${CACHE_DIR}" || return 1
fi
readonly MUSIC_EXTENSION_REGEX='.*\.(opus)$'
}
process_options() {
while [[ $# -gt 0 ]]; do
option="$1"
value="${2:-}"
case "${option}" in
-d | --dir)
if [[ ! -d "${value}" ]]; then
echo "directory ${value} does not exist"
usage
fi
readonly DIR="${value}"
shift 2
;;
-r | --recurse)
readonly RECURSE=true
shift 1
;;
-n | --dry-run)
readonly DRY_RUN=true
shift 1
;;
-i | --ignore)
readonly IGNORE=true
shift 1
;;
--debug)
readonly DEBUG=true
shift 1
;;
-e | --eval)
output_eval_functions
exit 0
;;
-f | --file)
if [[ ! -f "${value}" ]]; then
echo "file ${value} does not exist"
usage
fi
readonly FILE="${value}"
shift 2
;;
-h | --help)
EXIT_CODE=0 usage
;;
*)
echo "bad option"
usage
;;
esac
done
if [[ "${DIR:-}${FILE:-}" == '' ]]; then
echo "either --dir or --file must be used"
usage
fi
if [[ -n "${DIR}" && -n "${FILE}" ]]; then
echo "cannot process both directory and file"
usage
fi
if [[ "${RECURSE}" == true && -n "${FILE}" ]]; then
echo "--recurse can only be used with --dir"
usage
fi
}
_determine_inputs_fd() {
local fdCmd=(
fd
--type f
"${MUSIC_EXTENSION_REGEX}"
"${DIR}"
)
if [[ "${RECURSE}" == false ]]; then
fdCmd+=(--max-depth 1)
fi
mapfile -t INPUTS < <("${fdCmd[@]}" | sort)
}
_determine_inputs_find() {
local findCmd=(
find
"${DIR}"
)
if [[ "${RECURSE}" == false ]]; then
findCmd+=(-maxdepth 1)
fi
findCmd+=(
-regextype posix-extended
-regex "${MUSIC_EXTENSION_REGEX}"
-type f
)
mapfile -t INPUTS < <("${findCmd[@]}" | sort)
}
_determine_inputs_bash() {
local unsortedInputs=()
local pattern="${DIR}/*"
shopt -s nullglob globstar || return 1
[[ "${RECURSE}" == true ]] && pattern="${DIR}/**/*"
mapfile -t unsortedInputs < <(printf '%s\n' ${pattern})
local filteredInputs=()
for input in "${unsortedInputs[@]}"; do
[[ "${input}" =~ ${MUSIC_EXTENSION_REGEX} ]] || continue
filteredInputs+=("${input}")
done
mapfile -t INPUTS < <(printf '%s\n' "${filteredInputs[@]}" | sort)
}
determine_inputs() {
INPUTS=()
if [[ -n "${FILE}" ]]; then
INPUTS=("${FILE}")
elif have_cmd fd; then
_determine_inputs_fd || return 1
elif have_cmd find; then
_determine_inputs_find || return 1
else
_determine_inputs_bash || return 1
fi
if [[ "${#INPUTS[@]}" -eq 0 ]]; then
echo "no inputs found, something is wrong"
exit 1
fi
readonly INPUTS
}