From 46dacef79d7f923e8e07469cf017165c732ff84b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=84min=20Baumeler?= Date: Thu, 17 Jul 2025 11:59:42 +0200 Subject: [PATCH] imprv: mode handling --- fuzzique | 215 +++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 138 insertions(+), 77 deletions(-) diff --git a/fuzzique b/fuzzique index 412d43d..06176d5 100755 --- a/fuzzique +++ b/fuzzique @@ -2,19 +2,34 @@ set -eu -if [ "${1:-}" = "--info" ]; then +APP_NAME="fuzique" + +if [ "${1:-}" = "--prompt" ]; then shift file="$1" - rel=${file#"$ROOT/"} - artist=$(echo "$rel" | cut -d "/" -f 1) - release=$(echo "$rel" | cut -d "/" -f 2) - d=$(echo "$rel" | awk -F'/' '{ print NF }') - [ "$d" -eq 2 ] && printf ">> $AFMT" "$artist" - [ "$d" -eq 3 ] && printf ">> $AFMT >> $RFMT" "$artist" "$release" + shift + mode="$1" + case "$mode" in + "$MODE_SEARCH") + printf "search> " + ;; + "$MODE_BROWSE") + rel=${file#"$ROOT/"} + artist=$(echo "$rel" | cut -d "/" -f 1) + release=$(echo "$rel" | cut -d "/" -f 2) + d=$(echo "$rel" | awk -F'/' '{ print NF }') + [ "$d" -eq 2 ] && printf " $AFMT 〉 " "$artist" + [ "$d" -eq 3 ] && printf " $AFMT 》 $RFMT 〉 " "$artist" "$release" + ;; + "$MODE_PLAYLIST") + printf "" + ;; + esac exit 0 fi if [ "${1:-}" = "--preview" ]; then + echo "call to --preview" >>/tmp/foo shift file="$1" tags=$(ffprobe -v quiet -show_entries format -of json "$file" | jq) @@ -22,29 +37,39 @@ if [ "${1:-}" = "--preview" ]; then echo "## Lyrics" echo "" printf "%s" "$tags" | jq -C -r '.format.tags.LYRICS' - } | batcat --color always --number --language md + } | $CAT exit 0 fi if [ "${1:-}" = "--show-playlist" ]; then [ ! -S "${MPV_SOCKET:-}" ] && exit 1 count=$(echo "{ \"command\": [\"expand-text\",\"\${playlist/count}\"] }" | socat - "$MPV_SOCKET" | jq -r '.data') + if [ "$count" -eq 0 ]; then + printf "(empty playlist)\t\t%s\n" "$MODE_PLAYLIST" + exit 0 + fi for i in $(seq 0 $((count - 1))); do file=$(echo "{ \"command\": [\"expand-text\",\"\${playlist/$i/filename}\"] }" | socat - "$MPV_SOCKET" | jq -r '.data') curr=$(echo "{ \"command\": [\"expand-text\",\"\${playlist/$i/current}\"] }" | socat - "$MPV_SOCKET" | jq -r '.data') pnt=" " - [ "$curr" = "yes" ] && pnt="👉" + [ "$curr" = "yes" ] && pnt="$PLAYLIST_POINTER" artist=$(echo "$file" | rev | cut -d "/" -f 3 | rev) release=$(echo "$file" | rev | cut -d "/" -f 2 | rev) title=$(echo "$file" | rev | cut -d "/" -f 1 | rev | sed 's/\..*$//') artist=$(printf "$AFMT" "$artist") release=$(printf "$RFMT" "$release") title=$(printf "$TFMT" "$title") - printf "%s|%s|%s|%s\t%s\n" "$pnt" "$title" "$release" "$artist" "$file" - done | grep '.' | column -t -s '|' + printf "%s|%s|%s|%s\t%s\t%s\n" "$pnt" "$title" "$release" "$artist" "$file" "$MODE_PLAYLIST" + done | + grep '.' | + column -t -s '|' exit 0 fi +# Tools +command -v "fdfind" >/dev/null && FD="fdfind" || (err "Did not find \`fdfind\`." && exit 1) +command -v "fzf" >/dev/null && FZF="fzf" || (err "Did not find \`fzf\`." && exit 1) +command -v "mpv" >/dev/null && MPV="mpv" || (err "Did not find \`mpv\`." && exit 1) if command -v "bat" >/dev/null; then CAT="bat" elif command -v "batcat" >/dev/null; then @@ -91,66 +116,88 @@ EOF exit 0 fi -[ "${1:-}" ] && ROOT="$1" && shift -[ ! -d "${ROOT:-}" ] && echo "Faild to recognize music directory. Run $0 --help." && exit 1 +# Load configuration +[ "${1:-}" ] && ROOT="$(realpath "$1")" && shift ROOT=${ROOT%%/} -CACHE="$HOME/.cache/fuzzique" -ROOTHASH=$(echo "$ROOT" | sha1sum | cut -d ' ' -f 1) -CACHE="$CACHE/$ROOTHASH" +[ ! -d "${ROOT:-}" ] && echo "Faild to recognize music directory. Run $0 --help." && exit 1 DEPTH=$(echo "$ROOT" | awk -F'/' '{ print NF }') -FD=/usr/bin/fdfind -FZF=fzf -MPV=mpv -MPV_SOCKET="$(mktemp --suffix=.sock)" -ARTIST_COLOR='\033[38;5;202m' -RELEASE_COLOR='\033[38;5;208m' -TRACK_COLOR='\033[38;5;215m' + +# Cache support +ROOTHASH=$(echo "$ROOT" | sha1sum | cut -d ' ' -f 1) +CACHE_DIR="$HOME/.cache/$APP_NAME" +CACHE_FILE="$CACHE_DIR/$ROOTHASH" + +# Theme +ARTIST_COLOR=${ARTIST_COLOR:-'\033[38;5;202m'} +RELEASE_COLOR=${RELEASE_COLOR:-'\033[38;5;208m'} +TRACK_COLOR=${TRACK_COLOR:-'\033[38;5;215m'} OFF="\033[m" -AFMT="🎤 ${ARTIST_COLOR}%s${OFF}" -RFMT="💽 ${RELEASE_COLOR}%s${OFF}" -TFMT="🎵 ${TRACK_COLOR}%s${OFF}" -export ROOT MPV_SOCKET AFMT RFMT TFMT +AFMT="${AFTM:-"🎤 ${ARTIST_COLOR}%s${OFF}"}" +RFMT="${RFMT:-"💽 ${RELEASE_COLOR}%s${OFF}"}" +TFMT="${TFMT:-"🎵 ${TRACK_COLOR}%s${OFF}"}" +PLAYLIST_POINTER="${PLAYLIST_POINTER:-☞}" +#PLAYLIST_POINTER="${PLAYLIST_POINTER:-👉}" + +# Modes +MODE_BROWSE="B" +MODE_SEARCH="S" +MODE_PLAYLIST="P" + +# Make socket +MPV_SOCKET="$(mktemp --suffix=.sock)" + +# Export +export ROOT MPV_SOCKET AFMT RFMT TFMT PLAYLIST_POINTER MODE_SEARCH MODE_BROWSE MODE_PLAYLIST # Load -artists_file="$CACHE/artists" -release_file="$CACHE/release" -tracks_file="$CACHE/tracks" -if [ "${1:-}" = "--build-db" ] || [ ! -f "$artists_file" ]; then - rm -rf "$CACHE" - mkdir -p "$CACHE" - [ ! -d "$CACHE" ] && echo "Failed to create cache directory" && exit 1 +if [ "${1:-}" = "--reset-cache" ] || [ ! -f "$CACHE_FILE" ]; then + rm -f "$CACHE_FILE" + [ ! -d "$CACHE_DIR" ] && mkdir -p "$CACHE_DIR" { $FD --max-depth 2 --type d . "$ROOT" $FD --exact-depth 3 --type f -i -e "mp3" -e "mp4" -e "m4a" -e "ogg" -e "flac" -e "wav" . "$ROOT" } | - sort | - awk \ - -F'/' \ - -v afmt="$AFMT" \ - -v rfmt="$RFMT" \ - -v tfmt="$TFMT" \ - -v depth="$DEPTH" \ - -v artists_file="$artists_file" \ - -v release_file="$release_file" \ - -v tracks_file="$tracks_file" \ - 'BEGIN { - OFS="\t" - iartist = depth + 1 - irelease = depth + 2 - itrack = depth + 3 - } - NF >= depth + 1 { ar = sprintf(afmt, $iartist) } - NF >= depth + 2 { rl = sprintf(rfmt, $irelease) } - NF >= depth + 3 { tr = $itrack; gsub(/\..*$/, "", tr); tr = sprintf(tfmt, tr) } - NF == depth + 1 { print ar, $0 >> artists_file } - NF == depth + 2 { print rl, $0 >> release_file } - NF == depth + 3 { print tr, $0 >> tracks_file } - ' -# NF == depth + 1 { print ar, $0 >> artists_file } -# NF == depth + 2 { print rl "|" ar, $0 >> release_file } -# NF == depth + 3 { print tr "|" rl "|" ar, $0 >> tracks_file } + sort >"$CACHE_FILE" fi +# Parse +artists_file_browse=$(mktemp) +artists_file_search=$(mktemp) +release_file_browse=$(mktemp) +release_file_search=$(mktemp) +tracks_file_browse=$(mktemp) +tracks_file_search=$(mktemp) +awk \ + -F'/' \ + -v afmt="$AFMT" \ + -v rfmt="$RFMT" \ + -v tfmt="$TFMT" \ + -v depth="$DEPTH" \ + -v artists_file_browse="$artists_file_browse" \ + -v release_file_browse="$release_file_browse" \ + -v tracks_file_browse="$tracks_file_browse" \ + -v artists_file_search="$artists_file_search" \ + -v release_file_search="$release_file_search" \ + -v tracks_file_search="$tracks_file_search" \ + -v mode_browse="$MODE_BROWSE" \ + -v mode_search="$MODE_SEARCH" \ + 'BEGIN { + OFS="\t" + iartist = depth + 1 + irelease = depth + 2 + itrack = depth + 3 + } +NF >= depth + 1 { ar = sprintf(afmt, $iartist) } +NF >= depth + 2 { rl = sprintf(rfmt, $irelease) } +NF >= depth + 3 { tr = $itrack; gsub(/\..*$/, "", tr); tr = sprintf(tfmt, tr) } +NF == depth + 1 { print ar, $0, mode_browse >> artists_file_browse } +NF == depth + 2 { print rl, $0, mode_browse >> release_file_browse } +NF == depth + 3 { print tr, $0, mode_browse >> tracks_file_browse } +NF == depth + 1 { print ar, $0, mode_search >> artists_file_search } +NF == depth + 2 { print rl "|" ar, $0, mode_search >> release_file_search } +NF == depth + 3 { print tr "|" rl "|" ar, $0, mode_search >> tracks_file_search } +' <"$CACHE_FILE" + $MPV --no-config --no-terminal --input-ipc-server="$MPV_SOCKET" --idle & $FZF \ @@ -160,29 +207,43 @@ $FZF \ --delimiter="\t" \ --with-nth="{1}" \ --cycle \ - --info=inline-right \ - --info-command="$0 --info {2}" \ --bind="ctrl-d:half-page-down,ctrl-u:half-page-up" \ --bind="enter:execute:printf '{ \"command\": [\"loadfile\", \"%s\"] }\n' {2} | socat - \"$MPV_SOCKET\"" \ --bind="alt-enter:execute:printf '{ \"command\": [\"loadfile\", \"%s\", \"append-play\"] }\n' {2} | socat - \"$MPV_SOCKET\"" \ - --bind="alt-t:show-input+reload:cat \"$tracks_file\" | column -t -s '|' -E 0" \ - --bind="alt-r:show-input+reload:cat \"$release_file\" | column -t -s '|'" \ - --bind="alt-a:show-input+reload:cat \"$artists_file\" | column -t -s '|'" \ - --bind="ctrl-l:show-input+transform: - d=\$(echo {2} | awk -F'/' '{ print NF }') - [ \"\$d\" -eq \"$((DEPTH + 1))\" ] && echo \"reload:grep -F {2}/ \\\"$release_file\\\" | column -t -s '|' || true\" - [ \"\$d\" -eq \"$((DEPTH + 2))\" ] && echo \"reload:grep -F {2}/ \\\"$tracks_file\\\" | column -t -s '|' || true\" + --preview="$0 --preview {2}" \ + --bind="alt-1:reload:column -t -s '|' -E 0 \"$artists_file_search\"" \ + --bind="alt-2:reload:column -t -s '|' -E 0 \"$release_file_search\"" \ + --bind="alt-3:reload:column -t -s '|' -E 0 \"$tracks_file_search\"" \ + --bind="ctrl-p:reload:$0 --show-playlist" \ + --bind="load:transform: + echo \"l2:{}\" >> /tmp/foo + [ {3} = \"$MODE_SEARCH\" ] && printf \"+hide-preview\" || printf \"+show-preview\" + [ {3} = \"$MODE_PLAYLIST\" ] && printf \"+hide-input\" || printf \"+show-input\" + echo \"l3:{}\" >> /tmp/foo + printf \"+transform-prompt:$0 --prompt {2} {3}\" + echo \"l4:{}\" >> /tmp/foo + echo \"load ended..\" >> /tmp/foo " \ - --bind="ctrl-h:show-input+transform: + --bind="ctrl-l:transform: + printf \"clear-query+pos(1)\" + d=\$(echo {2} | awk -F'/' '{ print NF }') + [ \"\$d\" -eq \"$((DEPTH + 1))\" ] && echo \"+reload:grep -F {2}/ \\\"$release_file_browse\\\" | column -t -s '|' || true\" + [ \"\$d\" -eq \"$((DEPTH + 2))\" ] && echo \"+reload:grep -F {2}/ \\\"$tracks_file_browse\\\" | column -t -s '|' || true\" + " \ + --bind="ctrl-h:transform: + printf \"clear-query+pos(1)\" d=\$(echo {2} | awk -F'/' '{ print NF }') p=\$(echo {2} | rev | cut -d '/' -f 3- | rev) - [ \"\$d\" -eq \"$((DEPTH + 3))\" ] && echo \"reload:grep -F \\\"\$p/\\\" \\\"$release_file\\\" | column -t -s '|' || true\" - [ \"\$d\" -eq \"$((DEPTH + 2))\" ] && echo \"reload:grep -F \\\"\$p/\\\" \\\"$artists_file\\\" | column -t -s '|' || true\" + [ \"\$d\" -eq \"$((DEPTH + 3))\" ] && echo \"+reload:grep -F \\\"\$p/\\\" \\\"$release_file_browse\\\" | column -t -s '|' || true\" + [ \"\$d\" -eq \"$((DEPTH + 2))\" ] && echo \"+reload:grep -F \\\"\$p/\\\" \\\"$artists_file_browse\\\" | column -t -s '|' || true\" " \ - --bind="ctrl-p:hide-input+reload:$0 --show-playlist" \ - --preview="$0 --preview {2}" \ - --bind="alt-/:toggle-preview" \ - <"$artists_file" || true + <"$artists_file_search" || true printf '{ "command": ["quit"] }\n' | socat - "$MPV_SOCKET" -rm -f "$MPV_SOCKET" +rm -f "$MPV_SOCKET" \ + "$artists_file_browse" \ + "$artists_file_search" \ + "$release_file_browse" \ + "$release_file_search" \ + "$tracks_file_browse" \ + "$tracks_file_search"