-#! /bin/sh
+#! /bin/bash
-case "$1" in
- '') dir="$DIR_WALLPAPERS";;
- *) dir="$1";;
-esac
+### XXX Chose not to 'set -e' because arithmetic evaluation can cause a non-zero exit.
+### XXX Chose not to 'set -u' because unset params ($1, $2, ...) cause failures.
+### Solutions to the above are ugly.
-# XXX Apparently injecting a filepath with {} is bad: https://github.com/koalaman/shellcheck/wiki/SC2156
-#find "$dir" -type f -exec bash -c 'feh --bg-scale "{}"; read' \;
-find "$dir" -type f -exec bash -c 'feh --bg-scale "$1"; read' shell '{}' \;
+declare -a paths
+declare -i n=0
+
+read_command() {
+ local char
+
+ read -rsn 1 char
+ case "$char" in
+ q | Q) echo 'CMD_QUIT';;
+ h | H) echo 'CMD_MOVE_BACK';;
+ l | L) echo 'CMD_MOVE_FORWARD';;
+ f | F) echo 'CMD_FAVORITE';;
+ *) echo 'CMD_UKNOWN';;
+ esac
+}
+
+paths_find() {
+ local -r root_dir="$1"
+ local path
+
+ IFS=$'\n'
+ for path in $(find "$root_dir" -type f)
+ do
+ if file "$path" | grep 'image data' > /dev/null
+ then
+ (( n++ ))
+ # \r jumps to the beginning of the line:
+ printf '\rFound %d images.' "$n" >&2
+ paths["$(( n - 1 ))"]="$path"
+ fi
+ done
+ unset IFS
+ printf '\n' >&2
+}
+
+set_wallpaper() {
+ local -ri i="$1"
+ local -r path="$2"
+
+ printf '%d of %d %s\n' "$(( i + 1 ))" "$n" "$path"
+ feh --bg-scale "$path"
+}
+
+paths_preview() {
+ local -i i=0
+ local path="${paths[$i]}"
+
+ set_wallpaper "$i" "$path"
+
+ while :
+ do
+ if [[ "${paths[$i]}" != "$path" ]]
+ then
+ path="${paths[$i]}"
+ set_wallpaper "$i" "$path"
+ fi
+
+ case "$(read_command)" in
+ CMD_QUIT)
+ exit 0;;
+ CMD_MOVE_BACK)
+ (( i = i == 0 ? (n - 1) : i - 1));;
+ CMD_MOVE_FORWARD)
+ (( i = (i + 1) % n ));;
+ CMD_FAVORITE)
+ wallpaper_fav;;
+ CMD_UKNOWN)
+ continue;;
+ esac
+ done
+}
+
+main() {
+ local root_dir
+
+ case "$1" in
+ '') root_dir="$DIR_WALLPAPERS";;
+ *) root_dir="$1";;
+ esac
+
+ paths_find "$root_dir"
+ paths_preview
+}
+
+main "$@"