diff options
Diffstat (limited to 'src/lib/photo-list.source.sh')
| -rw-r--r-- | src/lib/photo-list.source.sh | 77 |
1 files changed, 77 insertions, 0 deletions
diff --git a/src/lib/photo-list.source.sh b/src/lib/photo-list.source.sh new file mode 100644 index 0000000..9e7ce72 --- /dev/null +++ b/src/lib/photo-list.source.sh @@ -0,0 +1,77 @@ +# Shared photo listing and random-pick primitives (task br0). Several modules +# need the same two low-level operations: "list the files in a dist photos +# directory, sorted" and "pick one seeded-random entry from a list". Before this +# module they were re-implemented in album-photo-select, image-pipeline and +# stats-render, each with the same find|sort idiom and the same collect / +# empty-check / random_index / print dance. Centralising them here removes that +# duplication while keeping behaviour identical at every call site. +# +# Home rationale: the consumers live in three otherwise-unrelated subsystems +# (album rendering, the image pipeline, the stats pages), so the helpers do not +# belong to any one of them -- putting them in, say, album-photo-select would +# make image-pipeline depend on album code. This small low-level module depends +# only on random_index (random.source.sh), _display_path (template.source.sh) +# and the $DIST_DIR global, so it is sourced early -- after random/template but +# before image-pipeline / album-* / stats-* -- so every definition precedes its +# uses. All libs are sourced before any code runs. + +# List the regular files directly inside "$DIST_DIR/<dir>", one basename per +# line, sorted. This is the canonical replacement for the recurring +# find "$DIST_DIR/<dir>" -maxdepth 1 -type f -printf '%f\n' | sort +# idiom. Stderr is left untouched so callers keep full control: a caller that +# wants the find error on a missing directory gets it, and one that wants it +# suppressed (the stats background loader) adds its own 2>/dev/null. This is the +# SORTED listing; album_photo_files deliberately keeps its own maybe_shuffle +# variant because the album's display order is the configurable shuffle, not a +# plain sort. +list_photos() { + local -r photos_dir="$1"; shift + + find "$DIST_DIR/$photos_dir" -maxdepth 1 -type f -printf '%f\n' | sort +} + +# Pick one seeded-random entry from an already-collected list, addressed by +# nameref, and print it WITHOUT a trailing newline. The namespace seeds the +# choice so a given RANDOM_SEED yields a stable pick. Returns 1 (printing +# nothing) when the list is empty, leaving the empty/error policy to the caller. +# This is the shared core of pick_random_photo / random_splash_photo / +# _stats_random_background / _stats_pick_background, so the random_index call +# (and thus selection determinism) lives in exactly one place. Each caller keeps +# its own namespace string, so seeding is unchanged from the former inline code. +_pick_random_from_list() { + local -r namespace="$1"; shift + local -n _list_ref="$1"; shift + local -i index + + if (( ${#_list_ref[@]} == 0 )); then + return 1 + fi + index=$(random_index "$namespace" "${#_list_ref[@]}") + printf '%s' "${_list_ref[index]}" +} + +# Pick one seeded-random photo from the sorted listing of "$DIST_DIR/<dir>". +# This is the canonical "random photo" picker (formerly album-render's +# randomphoto): it prints the chosen basename followed by a newline, and on an +# empty directory emits an error and returns 1. The selection namespace is +# "photo:<dir>:<ctx>" (ctx defaults to the directory name), matching the +# historical context exactly so determinism is unchanged. +pick_random_photo() { + local -r photos_dir="$1"; shift + local -r context="${1:-$photos_dir}" + local photo + local -a photos=() + + while IFS= read -r photo; do + photos+=("$photo") + done < <(list_photos "$photos_dir") + + if (( ${#photos[@]} == 0 )); then + printf 'ERROR: No photos found in %s\n' \ + "$(_display_path "$DIST_DIR/$photos_dir")" >&2 + return 1 + fi + + _pick_random_from_list "photo:$photos_dir:$context" photos + printf '\n' +} |
