#! /bin/bash ### 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. declare -a paths declare -i n=0 declare _command declare -i _goto=0 read_command_goto() { local buf printf ':' >&2 read -r buf printf '\n' >&2 if [[ "$buf" =~ ^[0-9]+$ ]]; then if [[ "$buf" -gt 0 && "$buf" -le "$n" ]]; then (( buf-- )) _goto="$buf" _command='CMD_GOTO' else printf 'Error: out of range: %s\n' "$buf" >&2 _command='CMD_UKNOWN' fi else printf 'Error: not an integer: %s\n' "$buf" >&2 _command='CMD_UKNOWN' fi } read_command() { local char read -rsn 1 char case "$char" in q | Q) _command='CMD_QUIT';; h | H) _command='CMD_MOVE_BACK';; l | L) _command='CMD_MOVE_FORWARD';; f | F) _command='CMD_FAVORITE_ADD';; r | R) _command='CMD_FAVORITE_REMOVE';; s | S) _command='CMD_SET_CURRENT';; z | Z) _command='CMD_FZF';; :) read_command_goto;; *) printf 'Error: unknown command: %s\n' "$char" >&2 _command='CMD_UKNOWN';; esac } paths_set() { local path while read -r path 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 printf '\n' >&2 } paths_set_from_dir_find() { paths_set < <(find "$1" -type f) } paths_set_from_favs() { paths_set < <(sort -k 2 "$FILE_WALLPAPER_FAVS" | awk '{sub("^" $1 " +", ""); print}') } 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 read_command case "$_command" in CMD_QUIT) feh --bg-scale "$(< "$FILE_WALLPAPER_CURR")" exit 0;; CMD_GOTO) i="$_goto";; CMD_MOVE_BACK) (( i = i == 0 ? (n - 1) : i - 1));; CMD_MOVE_FORWARD) (( i = (i + 1) % n ));; CMD_FAVORITE_ADD) printf 'Adding to favorites set: "%s"\n' "$path" >&2 wallpaper_fav "$path";; CMD_FAVORITE_REMOVE) printf 'Removing from favorites set: "%s"\n' "$path" >&2 digest=$(sha256sum "$path" | awk '{print $1}') grep -v "$digest" "$FILE_WALLPAPER_FAVS" \ | sort -u \ | sponge "$FILE_WALLPAPER_FAVS" ;; CMD_SET_CURRENT) printf 'Setting as current: "%s"\n' "$path" >&2 echo "$path" > "$FILE_WALLPAPER_CURR";; CMD_FZF) i=$( for j in "${!paths[@]}"; do printf '%d %s\n' "$((j + 1))" "${paths[j]}" done \ | fzf -e \ | awk '{print $1 - 1}' );; CMD_UKNOWN) continue;; esac done } help_print() { cat <&2 Navigation help: key | action ----+---------------------------------------------- q | quit h | move back l | move forward f | add to favorites r | remove from favorites s | set current z | fuzzy search for next file path :N | goto Nth image ----+---------------------------------------------- EOF } main() { case "$1" in f | fav) paths_set_from_favs;; d | dir) paths_set_from_dir_find "$2";; a | all) paths_set_from_dir_find "$DIR_WALLPAPERS";; '') paths_set_from_dir_find "$DIR_WALLPAPERS";; *) printf 'Error: unknown source "%s"\n' "$1" >&2 exit 1;; esac help_print paths_preview } main "$@"