diff --git a/src/main.sh b/src/main.sh index 082e39e..9998eed 100755 --- a/src/main.sh +++ b/src/main.sh @@ -44,6 +44,9 @@ set -eu # Load list-generating methods . "sh/lists.sh" +# State management +. "sh/state.sh" + # FZF handlers . "sh/fzf.sh" @@ -133,10 +136,16 @@ tmpdir=$(mktemp -d) LOCKFILE="$tmpdir/lock" RESULTS="$tmpdir/results" PIDFILE="$tmpdir/pid" -STATEFILE="$tmpdir/state" -ARGSFILE="$tmpdir/state-args" trap 'rm -rf "$tmpdir"' EXIT INT -export LOCKFILE RESULTS PIDFILE STATEFILE ARGSFILE +export LOCKFILE RESULTS PIDFILE + +statedir=$(mktemp -d) +STATEFILE="$statedir/state" +ARGSFILE="$statedir/state-args" +STATEFILE_LAST="$statedir/state2" +ARGSFILE_LAST="$statedir/state-args2" +touch "$STATEFILE" "$ARGSFILE" "$STATEFILE_LAST" "$ARGSFILE_LAST" +export STATEFILE ARGSFILE STATEFILE_LAST ARGSFILE_LAST if [ "${1:-}" = "--ni-search-artist" ]; then $0 --internal-search "artist" "$2" @@ -167,35 +176,20 @@ export VIEW_ARTIST VIEW_RELEASEGROUP VIEW_RELEASE VIEW_SEARCH_ARTIST \ case "${1:-}" in "--artist") [ ! "${2:-}" ] && err "MusicBrainz Artist ID not specified (see --help)" && exit 1 - printf "%s#%s" "$VIEW_ARTIST" "$MODE_NORMAL" >"$STATEFILE" - printf "%s" "$2" >"$ARGSFILE" + state_init "$VIEW_ARTIST" "$MODE_NORMAL" "$2" ;; "--releasegroup") [ ! "${2:-}" ] && err "MusicBrainz Release-Group ID not specified (see --help)" && exit 1 - printf "%s#%s" "$VIEW_RELEASEGROUP" "$MODE_NORMAL" >"$STATEFILE" - printf "%s" "$2" >"$ARGSFILE" + state_init "$VIEW_RELEASEGROUP" "$MODE_NORMAL" "$2" ;; "--release") [ ! "${2:-}" ] && err "MusicBrainz Release ID not specified (see --help)" && exit 1 - printf "%s#%s" "$VIEW_RELEASE" "$MODE_NORMAL" >"$STATEFILE" - printf "%s" "$2" >"$ARGSFILE" - ;; -"--search-artist") - printf "%s#%s" "$VIEW_SEARCH_ARTIST" "$MODE_INSERT" >"$STATEFILE" - printf "%s" "${2:-}" >"$ARGSFILE" - ;; -"--search-album") - printf "%s#%s" "$VIEW_SEARCH_ALBUM" "$MODE_INSERT" >"$STATEFILE" - printf "%s" "${2:-}" >"$ARGSFILE" - ;; -"--artists" | "") - printf "%s#%s" "$VIEW_LIST_ARTISTS" "$MODE_NORMAL" >"$STATEFILE" - printf "%s" "" >"$ARGSFILE" - ;; -"--albums") - printf "%s#%s" "$VIEW_LIST_ALBUMS" "$MODE_NORMAL" >"$STATEFILE" - printf "%s" "" >"$ARGSFILE" + state_init "$VIEW_RELEASE" "$MODE_NORMAL" "$2" ;; +"--search-artist") state_init "$VIEW_SEARCH_ARTIST" "$MODE_INSERT" "${2:-}" ;; +"--search-album") state_init "$VIEW_SEARCH_ALBUM" "$MODE_INSERT" "${2:-}" ;; +"--artists" | "") state_init "$VIEW_LIST_ARTISTS" "$MODE_NORMAL" "" ;; +"--albums") state_init "$VIEW_LIST_ALBUMS" "$MODE_NORMAL" "" ;; *) err "Unknown option $1 (see --help)" exit 1 @@ -207,9 +201,9 @@ mpv_start # $KEYS_PLAY main loop while true; do - view=$(cut -d "#" -f 1 "$STATEFILE") - mode=$(cut -d "#" -f 2 "$STATEFILE") - args=$(cat "$ARGSFILE") + view=$(state_get_view) + mode=$(state_get_mode) + args=$(state_get_args) case "$view" in "$VIEW_SELECT_ARTIST") sel=$( @@ -219,7 +213,7 @@ while true; do --bind="$KEYS_HALFPAGE_DOWN,$KEYS_HALFPAGE_UP,\ $KEYS_BROWSE,\ $KEYS_FILTER_LOCAL:transform:$0 --fzf-key {2} {3} {4}" \ - -1 \ + -0 -1 \ --border="bold" \ --border-label="Select artist" \ --delimiter="\t" \ @@ -227,10 +221,9 @@ $KEYS_FILTER_LOCAL:transform:$0 --fzf-key {2} {3} {4}" \ --margin="5%,20%" \ --bind="$KEYS_FILTER_LOCAL:change-query($FORMAT_LOCAL )" \ --accept-nth="{3}" \ - --with-nth="{1}" + --with-nth="{1}" || true ) - printf "%s#%s" "$VIEW_ARTIST" "$mode" >"$STATEFILE" - printf "%s" "$sel" >"$ARGSFILE" + [ "$sel" ] && state_update "$VIEW_ARTIST" "$mode" "$sel" || state_revert ;; "$VIEW_PLAYLIST") list_playlist | diff --git a/src/sh/fzf.sh b/src/sh/fzf.sh index 4bc45a0..5a3135e 100644 --- a/src/sh/fzf.sh +++ b/src/sh/fzf.sh @@ -1,6 +1,6 @@ __set_prompt() { - view=$(cut -d "#" -f 1 "$STATEFILE") - mode=$(cut -d "#" -f 2 "$STATEFILE") + view=$(state_get_view) + mode=$(state_get_mode) case "$view" in "$VIEW_ARTIST") name="$(mb_artist "$args" | $JQ -r '.name')" @@ -27,9 +27,9 @@ __set_prompt() { # Reload data for FZF fzf_handle_reload() { - view=$(cut -d "#" -f 1 "$STATEFILE") - mode=$(cut -d "#" -f 2 "$STATEFILE") - args=$(cat "$ARGSFILE") + view=$(state_get_view) + mode=$(state_get_mode) + args=$(state_get_args) case "$view" in "$VIEW_ARTIST") list_releasegroups "$args" @@ -51,9 +51,9 @@ fzf_handle_reload() { # Handle for after loading data into FZF fzf_handle_load() { - view=$(cut -d "#" -f 1 "$STATEFILE") - mode=$(cut -d "#" -f 2 "$STATEFILE") - args=$(cat "$ARGSFILE") + view=$(state_get_view) + mode=$(state_get_mode) + args=$(state_get_args) case "$view" in "$VIEW_ARTIST") secsymb="$(printf "$FORMAT_TYPE_HAS_SECONDARY" "")" @@ -76,8 +76,7 @@ fzf_handle_load() { ;; "$VIEW_LIST_ALBUMS") ;; esac - printf "+change-query(%s)" "${QUERY:-}" - [ "${DISABLE_SEARCH:-}" ] && printf "+disable-search" || printf "+enable-search" + [ "${DISABLE_SEARCH:-}" ] && printf "+disable-search+change-query(%s)" "${QUERY:-"$FZF_QUERY"}" || printf "+enable-search+change-query(%s)" "${QUERY:-}" [ "${SHOW_PREVIEW:-}" ] && printf "+show-preview" || printf "+hide-preview" [ "${ENABLE_CHANGE:-}" ] && printf "+rebind(change)" || printf "+unbind(change)" __set_prompt @@ -85,9 +84,9 @@ fzf_handle_load() { # Print info string for FZF fzf_info() { - view=$(cut -d "#" -f 1 "$STATEFILE") - mode=$(cut -d "#" -f 2 "$STATEFILE") - args=$(cat "$ARGSFILE") + view=$(state_get_view) + mode=$(state_get_mode) + args=$(state_get_args) case "$view" in "$VIEW_SEARCH_ARTIST") echo "Search music artist on MusicBrainz" @@ -102,7 +101,7 @@ fzf_info() { echo "Search albums" ;; "$VIEW_SELECT_ARTIST") - echo "Select artist (WE SHOULDNT SEE THIS; THIS IS A BUG!)" + foo "Select artist (WE SHOULDNT SEE THIS; THIS IS A BUG!)" ;; *) if [ "$FZF_KEY" ]; then @@ -140,7 +139,7 @@ fzf_handle_change() { echo "$$" >"$PIDFILE" touch "$LOCKFILE" sleep 1 - view=$(cut -d "#" -f 1 "$STATEFILE") + view=$(state_get_view) if [ "$view" = "$VIEW_SEARCH_ARTIST" ]; then api_mb_search_artist "$FZF_QUERY" | $JQ -r '.artists[] | [ @@ -212,9 +211,9 @@ fzf_handle_key() { parentmbid="${1:-}" mbid="${2:-}" path="${3:-}" - view=$(cut -d "#" -f 1 "$STATEFILE") - mode=$(cut -d "#" -f 2 "$STATEFILE") - args=$(cat "$ARGSFILE") + view=$(state_get_view) + mode=$(state_get_mode) + args=$(state_get_args) # If we are in the insert mode, and the key pressed is an "input" key, then # put it and quit. @@ -237,6 +236,23 @@ fzf_handle_key() { return 0 ;; esac + + # Keys in insert mode only + case ",$KEYS_I_NORMAL," in + *",$FZF_KEY,"*) + case "$view" in + "$VIEW_PLAYLIST") ;; + *) + if [ "$mode" = "$MODE_INSERT" ]; then + state_update_keep_args "$view" "$MODE_NORMAL" + __set_prompt + else + printf "put(%s)" "$FZF_KEY" + fi + ;; + esac + ;; + esac fi # Handle key press @@ -289,10 +305,10 @@ fzf_handle_key() { "$VIEW_LIST_ARTISTS" | "$VIEW_SEARCH_ARTIST") VIEW_NEXT="$VIEW_ARTIST" ;; - "$VIEW_ARTIST") + "$VIEW_ARTIST" | "$VIEW_SEARCH_ALBUM") VIEW_NEXT="$VIEW_RELEASEGROUP" ;; - "$VIEW_RELEASEGROUP" | "$VIEW_LIST_ALBUMS" | "$VIEW_SEARCH_ALBUM") + "$VIEW_RELEASEGROUP" | "$VIEW_LIST_ALBUMS") VIEW_NEXT="$VIEW_RELEASE" ;; esac @@ -392,8 +408,14 @@ fzf_handle_key() { case "$view" in "$VIEW_SEARCH_ARTIST") VIEW_NEXT="$VIEW_LIST_ARTISTS" ;; "$VIEW_SEARCH_ALBUM") VIEW_NEXT="$VIEW_LIST_ALBUMS" ;; - "$VIEW_LIST_ARTISTS") VIEW_NEXT="$VIEW_SEARCH_ARTIST" ;; - "$VIEW_LIST_ALBUMS") VIEW_NEXT="$VIEW_SEARCH_ALBUM" ;; + "$VIEW_LIST_ARTISTS") + VIEW_NEXT="$VIEW_SEARCH_ARTIST" + MODE_NEXT="$MODE_INSERT" + ;; + "$VIEW_LIST_ALBUMS") + VIEW_NEXT="$VIEW_SEARCH_ALBUM" + MODE_NEXT="$MODE_INSERT" + ;; esac ;; esac @@ -447,15 +469,15 @@ fzf_handle_key() { esac # Keys in normal mode only - case ",$KEYS_N_DOWN," in - *",$FZF_KEY,"*) [ "$mode" = "$MODE_NORMAL" ] && printf "down" || printf "put(%s)" "$FZF_KEY" ;; - esac - case ",$KEYS_N_UP," in - *",$FZF_KEY,"*) [ "$mode" = "$MODE_NORMAL" ] && printf "up" || printf "put(%s)" "$FZF_KEY" ;; - esac - case ",$KEYS_N_OUT," in - *",$FZF_KEY,"*) - if [ "$mode" = "$MODE_NORMAL" ]; then + if [ "$mode" = "$MODE_NORMAL" ]; then + case ",$KEYS_N_DOWN," in + *",$FZF_KEY,"*) printf "down" ;; + esac + case ",$KEYS_N_UP," in + *",$FZF_KEY,"*) printf "up" ;; + esac + case ",$KEYS_N_OUT," in + *",$FZF_KEY,"*) case "$view" in "$VIEW_ARTIST") VIEW_NEXT="$VIEW_LIST_ARTISTS" @@ -475,118 +497,78 @@ fzf_handle_key() { ACCEPT=1 ;; esac - else - printf "put(%s)" "$FZF_KEY" - fi - ;; - esac - case ",$KEYS_N_IN," in - *",$FZF_KEY,"*) - if [ "$mode" = "$MODE_NORMAL" ]; then + ;; + esac + case ",$KEYS_N_IN," in + *",$FZF_KEY,"*) [ "$mbid" ] || return 0 VIEW_NEXT_ARGS="$mbid" case "$view" in "$VIEW_LIST_ARTISTS" | "$VIEW_SEARCH_ARTIST") VIEW_NEXT="$VIEW_ARTIST" ;; - "$VIEW_ARTIST") + "$VIEW_ARTIST" | "$VIEW_SEARCH_ALBUM") VIEW_NEXT="$VIEW_RELEASEGROUP" ;; - "$VIEW_RELEASEGROUP" | "$VIEW_LIST_ALBUMS" | "$VIEW_SEARCH_ALBUM") + "$VIEW_RELEASEGROUP" | "$VIEW_LIST_ALBUMS") VIEW_NEXT="$VIEW_RELEASE" ;; esac - else - printf "put(%s)" "$FZF_KEY" - fi - ;; - esac - case ",$KEYS_N_TOP," in - *",$FZF_KEY,"*) [ "$mode" = "$MODE_NORMAL" ] && printf "first" || printf "put(%s)" "$FZF_KEY" ;; - esac - case ",$KEYS_N_BOT," in - *",$FZF_KEY,"*) [ "$mode" = "$MODE_NORMAL" ] && printf "last" || printf "put(%s)" "$FZF_KEY" ;; - esac - case ",$KEYS_N_QUIT," in - *",$FZF_KEY,"*) - case "$view" in - "$VIEW_SELECT_ARTIST" | "$VIEW_PLAYLIST") - [ "$mode" = "$MODE_NORMAL" ] && printf "accept" || printf "put(%s)" "$FZF_KEY" - ;; - *) - [ "$mode" = "$MODE_NORMAL" ] && printf "abort" || printf "put(%s)" "$FZF_KEY" ;; esac - ;; - esac - case ",$KEYS_N_INSERT," in - *",$FZF_KEY,"*) - case "$view" in - "$VIEW_PLAYLIST") ;; - *) - if [ "$mode" = "$MODE_NORMAL" ]; then - printf "%s#%s" "$view" "$MODE_INSERT" >"$STATEFILE" + case ",$KEYS_N_TOP," in + *",$FZF_KEY,"*) printf "first" ;; + esac + case ",$KEYS_N_BOT," in + *",$FZF_KEY,"*) printf "last" ;; + esac + case ",$KEYS_N_QUIT," in + *",$FZF_KEY,"*) + case "$view" in + "$VIEW_SELECT_ARTIST" | "$VIEW_PLAYLIST") printf "accept" ;; + *) printf "abort" ;; + esac + ;; + esac + case ",$KEYS_N_INSERT," in + *",$FZF_KEY,"*) + case "$view" in + "$VIEW_PLAYLIST") ;; + *) + state_update_keep_args "$view" "$MODE_INSERT" __set_prompt - else - printf "put(%s)" "$FZF_KEY" - fi + ;; + esac ;; esac - ;; - esac - case ",$KEYS_N_TOGGLE_PLAY_PAUSE," in - *",$FZF_KEY,"*) [ "$mode" = "$MODE_NORMAL" ] && mpv_toggle_pause >/dev/null || printf "put(%s)" "$FZF_KEY" ;; - esac + case ",$KEYS_N_TOGGLE_PLAY_PAUSE," in + *",$FZF_KEY,"*) mpv_toggle_pause >/dev/null ;; + esac - case ",$KEYS_N_PLAY_NEXT," in - *",$FZF_KEY,"*) - if [ "$mode" = "$MODE_NORMAL" ]; then + case ",$KEYS_N_PLAY_NEXT," in + *",$FZF_KEY,"*) mpv_next >/dev/null [ "$view" = "$VIEW_PLAYLIST" ] && VIEW_NEXT="$VIEW_PLAYLIST" && ACCEPT=1 - else - printf "put(%s)" "$FZF_KEY" - fi - ;; - esac - case ",$KEYS_N_PLAY_PREV," in - *",$FZF_KEY,"*) - if [ "$mode" = "$MODE_NORMAL" ]; then - mpv_prev >/dev/null - [ "$view" = "$VIEW_PLAYLIST" ] && VIEW_NEXT="$VIEW_PLAYLIST" && ACCEPT=1 - else - printf "put(%s)" "$FZF_KEY" - fi - ;; - esac - case ",$KEYS_N_SEEK_FORWARD," in - *",$FZF_KEY,"*) "$mode" = "$MODE_NORMAL" ] && mpv_seek_forward >/dev/null || printf "put(%s)" "$FZF_KEY" ;; - esac - case ",$KEYS_N_SEEK_BACKWARD," in - *",$FZF_KEY,"*) "$mode" = "$MODE_NORMAL" ] && mpv_seek_backward >/dev/null || printf "put(%s)" "$FZF_KEY" ;; - esac - - # Keys in insert mode only - case ",$KEYS_I_NORMAL," in - *",$FZF_KEY,"*) - case "$view" in - "$VIEW_PLAYLIST") ;; - *) - if [ "$mode" = "$MODE_INSERT" ]; then - printf "%s#%s" "$view" "$MODE_NORMAL" >"$STATEFILE" - __set_prompt - else - printf "put(%s)" "$FZF_KEY" - fi ;; esac - ;; - esac + case ",$KEYS_N_PLAY_PREV," in + *",$FZF_KEY,"*) + mpv_prev >/dev/null + [ "$view" = "$VIEW_PLAYLIST" ] && VIEW_NEXT="$VIEW_PLAYLIST" && ACCEPT=1 + ;; + esac + case ",$KEYS_N_SEEK_FORWARD," in + *",$FZF_KEY,"*) mpv_seek_forward >/dev/null ;; + esac + case ",$KEYS_N_SEEK_BACKWARD," in + *",$FZF_KEY,"*) mpv_seek_backward >/dev/null ;; + esac + fi # Post processing [ "${QUERY:-}" ] && printf "+change-query(%s)" "$QUERY" if [ "${VIEW_NEXT:-}" ]; then - printf "%s#%s" "$VIEW_NEXT" "$mode" >"$STATEFILE" - printf "%s" "${VIEW_NEXT_ARGS:-}" >"$ARGSFILE" + state_update "$VIEW_NEXT" "${MODE_NEXT:-"$mode"}" "${VIEW_NEXT_ARGS:-}" [ "${ACCEPT:-}" ] && printf "+accept" || printf "+reload:%s" "$0 --fzf-reload" fi } diff --git a/src/sh/state.sh b/src/sh/state.sh new file mode 100644 index 0000000..af7b743 --- /dev/null +++ b/src/sh/state.sh @@ -0,0 +1,49 @@ +# Update state +# @argument $1: view +# @argument $2: mode +# @argument $3: arguments +state_update() { + mv "$STATEFILE" "$STATEFILE_LAST" + mv "$ARGSFILE" "$ARGSFILE_LAST" + printf "%s#%s" "${1:-}" "${2:-}" >"$STATEFILE" + printf "%s" "${3:-}" >"$ARGSFILE" +} + +# Initialize state +# @argument $1: view +# @argument $2: mode +# @argument $3: arguments +state_init() { + state_update "$1" "$2" "$3" + state_update "$1" "$2" "$3" +} + +# Update state and keep arguments +# @argument $1: view +# @argument $2: mode +state_update_keep_args() { + mv "$STATEFILE" "$STATEFILE_LAST" + cp "$ARGSFILE" "$ARGSFILE_LAST" + printf "%s#%s" "${1:-}" "${2:-}" >"$STATEFILE" +} + +# Go back to previous state +state_revert() { + cp "$STATEFILE_LAST" "$STATEFILE" + cp "$ARGSFILE_LAST" "$ARGSFILE" +} + +# Get view +state_get_view() { + cut -d "#" -f 1 "$STATEFILE" +} + +# Get mode +state_get_mode() { + cut -d "#" -f 2 "$STATEFILE" +} + +# Get args +state_get_args() { + cat "$ARGSFILE" +}