Browse Source

fix more things

DanielFGray 1 year ago
parent
commit
df23d83427
1 changed files with 128 additions and 67 deletions
  1. 128
    67
      fzmp

+ 128
- 67
fzmp View File

@@ -1,14 +1,5 @@
1 1
 #!/usr/bin/env bash
2 2
 
3
-declare -r esc=$'\033'
4
-declare -r c_reset="${esc}[0m"
5
-declare -r c_red="${esc}[31m"
6
-declare -r config_file="${XDG_CONFIG_DIR:-$HOME/.config}/fzmp/conf"
7
-declare verbose
8
-declare default_filter='filter_all_songs'
9
-declare track_format='[[[%artist% / ][[(%date%) ]%album% / ][[%track% - ][%title%]]]|%file%]'
10
-declare -a config_err
11
-
12 3
 usage() {
13 4
   LESS=-FEXR less <<'HELP'
14 5
 fzmp [OPTIONS]
@@ -21,7 +12,6 @@ fzmp [OPTIONS]
21 12
                    >   go to the next song in the playlist
22 13
                    <   go to the previous song in the playlist
23 14
                    C-d delete the selected songs from the playlist
24
-    -v --verbose   print errors when parsing the config file
25 15
     -h --help      print this help
26 16
 
27 17
   CONFIGURATION:
@@ -40,12 +30,42 @@ fzmp [OPTIONS]
40 30
 HELP
41 31
 }
42 32
 
33
+declare -r config_file="${XDG_CONFIG_DIR:-$HOME/.config}/fzmp/conf"
34
+declare default_filter='filter_by_playlist'
35
+declare track_format='[[[%artist% / ][[(%date%) ]%album% / ][[%track% - ][%title%]]]|%file%]'
36
+declare -a config_err
37
+
38
+declare playlist_view_key='f1'
39
+declare artist_view_key='f2'
40
+declare track_view_key='f3'
41
+declare genre_view_key='f4'
42
+declare findadd_key='ctrl-x'
43
+
44
+declare -A colors
45
+colors[red]=$(tput setaf 1)
46
+colors[green]=$(tput setaf 2)
47
+colors[blue]=$(tput setaf 4)
48
+colors[reset]=$(tput sgr0)
49
+
43 50
 is_running() {
44 51
   pgrep "$1" &> /dev/null
45 52
 }
46 53
 
54
+info() {
55
+  color green "$@" >&2
56
+}
57
+
58
+color() {
59
+  local c
60
+  c="$1"
61
+  shift
62
+  printf '%s' "${colors[$c]}"
63
+  printf '%s\n' "$@"
64
+  printf '%s' "${colors[reset]}"
65
+}
66
+
47 67
 err() {
48
-  printf "${c_red}%s${c_reset}\n" "$*" >&2
68
+  color red "$@" >&2
49 69
 }
50 70
 
51 71
 die() {
@@ -54,14 +74,14 @@ die() {
54 74
 }
55 75
 
56 76
 has() {
57
-  local verbose=0
77
+  local loud=0
58 78
   if [[ $1 == '-v' ]]; then
59
-    verbose=1
79
+    loud=1
60 80
     shift
61 81
   fi
62 82
   for c; do c="${c%% *}"
63 83
     if ! command -v "$c" &> /dev/null; then
64
-      (( verbose > 0 )) && err "$c not found"
84
+      (( loud > 0 )) && err "$c not found"
65 85
       return 1
66 86
     fi
67 87
   done
@@ -72,7 +92,7 @@ fzf() {
72 92
 }
73 93
 
74 94
 parse_config_file() {
75
-  local line key val nr=0
95
+  local line key val nr=0 e
76 96
   while IFS= read -r line; do
77 97
     (( ++nr ))
78 98
     [[ -z "$line" || "$line" = '#'* ]] && continue
@@ -94,41 +114,93 @@ parse_config_file() {
94 114
           esac
95 115
         else
96 116
           config_err+=( "unknown format \"$val\" in config file on line $nr" )
97
-        fi
98
-        ;;
117
+        fi ;;
118
+      playlist_view_key) playlist_view_key="$val" ;;
119
+      artist_view_key) artist_view_key="$val" ;;
120
+      track_view_key) track_view_key="$val" ;;
121
+      genre_view_key) genre_view_key="$val" ;;
122
+      findadd_key) findadd_key="$val" ;;
99 123
       *) config_err+=( "unknown key \"$key\" in config file on line $nr" )
100 124
     esac
101 125
   done
126
+  if (( ${#config_err[@]} > 0 )); then
127
+    err 'there were errors parsing config file:'
128
+    for e in "${config_err[@]}"; do
129
+      err "  $e"
130
+    done
131
+  fi
102 132
 }
103 133
 
104 134
 filter_all_songs() {
105 135
   local choice
106
-  mapfile -t choice < <( mpc search -f "%file%\t$track_format" filename '' |
136
+  mapfile -t choice < <(mpc search -f "%file%\t$track_format" filename '' |
107 137
     fzf --multi \
108 138
       --with-nth='2..' \
109 139
       --delimiter='\t' \
110
-      --expect='f2,f3,enter' |
140
+      --expect='f1,f2,f3,f4,enter' |
111 141
     cut -f1)
112 142
   case "${choice[0]}" in
113
-    'f2') filter_by_artist ;;
114
-    'f3') filter_by_playlist ;;
115
-    'enter') printf '%s\n' "${choice[@]:1}" | play_songs ;;
143
+    "$playlist_view_key") filter_by_playlist ;;
144
+    "$artist_view_key") filter_by_artist ;;
145
+    "$track_view_key") filter_all_songs ;;
146
+    "$genre_view_key") filter_by_genre ;;
147
+    'enter') printf '%s\n' "${choice[@]:1}" | add_songs play ;;
116 148
   esac
117 149
 }
118 150
 
119
-filter_by_artist() {
151
+filter_by_genre() {
120 152
   local choice
121
-  mapfile -t choice < <(mpc list albumartist |
122
-    sort -h |
153
+  mapfile -t choice < <(mpc search -f '%genre%' genre '' | awk 'NF' | sort | uniq -ic | sort -rn |
123 154
     fzf \
124
-      --preview='mpc list album artist {}' \
125
-      --expect='f1,f3,enter,ctrl-x')
155
+      --preview='mpc search -f "%artist%" genre {2..} | sort -u' \
156
+      --bind="$findadd_key:execute:mpc findadd genre {2..}" \
157
+      --expect='f1,f2,f3,f4,enter' | sed -r 's/^\s*[0-9]+\s*//')
126 158
   (( ${#choice[@]} > 0 )) || die
127 159
   case "${choice[0]}" in
128
-    f1) filter_all_songs ;;
129
-    f3) filter_by_playlist ;;
160
+    "$playlist_view_key") filter_by_playlist ;;
161
+    "$artist_view_key") filter_by_artist ;;
162
+    "$track_view_key") filter_all_songs ;;
163
+    "$genre_view_key") filter_by_genre ;;
164
+    enter) filter_by_artist_from_genre "${choice[1]}" ;;
165
+    *) $default_filter ;;
166
+  esac
167
+}
168
+
169
+filter_by_artist_from_genre() {
170
+  local artist genre choice
171
+  genre="$1"
172
+  mapfile -t choice < <(mpc search -f '%artist%' genre "$genre" | sort -u |
173
+    awk 'NF' | sort -u |
174
+    fzf \
175
+      --preview="mpc search -f '%album%\t%title%' artist {} | awk -F'\t' '{ if(album != \$1) { album=\$1; print album } printf \"  %s\n\", \$2 }'" \
176
+      --expect='f1,f2,f3,f4,enter' \
177
+      --bind="$findadd_key:execute:mpc findadd artist {}")
178
+  (( ${#choice[@]} > 0 )) || filter_by_genre
179
+  case "${choice[0]}" in
180
+    "$playlist_view_key") filter_by_playlist ;;
181
+    "$artist_view_key") filter_by_artist ;;
182
+    "$track_view_key") filter_all_songs ;;
183
+    "$genre_view_key") filter_by_genre ;;
130 184
     enter) filter_by_album_from_artist "${choice[1]}" ;;
131
-    ctrl-x) play_artist "${choice[1]}" ;;
185
+    *) "$filter_by_genre" ;;
186
+  esac
187
+}
188
+
189
+filter_by_artist() {
190
+  local choice
191
+  mapfile -t choice < <(mpc list artist |
192
+    fzf \
193
+      --preview="mpc search -f '%album%\t%title%' artist {} | awk -F'\t' '{ if(album != \$1) { album=\$1; print album } printf \"  %s\n\", \$2 }'" \
194
+      --bind="$findadd_key:execute:mpc findadd artist {}" \
195
+      --expect='f1,f2,f3,f4,enter')
196
+  (( ${#choice[@]} > 0 )) || die
197
+  case "${choice[0]}" in
198
+    "$playlist_view_key") filter_by_playlist ;;
199
+    "$artist_view_key") filter_by_artist ;;
200
+    "$track_view_key") filter_all_songs ;;
201
+    "$genre_view_key") filter_by_genre ;;
202
+    'enter') filter_by_album_from_artist "${choice[1]}" ;;
203
+    *) $default_filter ;;
132 204
   esac
133 205
 }
134 206
 
@@ -136,18 +208,20 @@ filter_by_album_from_artist() {
136 208
   local album artist choice
137 209
   [[ -z "$1" ]] && filter_by_artist
138 210
   artist="$1"
139
-  mapfile -t choice < <(mpc search -f '[[%album%]' albumartist "$artist" |
211
+  mapfile -t choice < <(mpc search -f '[(%date%)]\t[%album%]' artist "$artist" |
140 212
     sort -h | uniq |
141 213
     fzf --prompt="$artist > " \
142
-      --preview="album=\$(cut -f2 <<< {}); mpc search -f '[[[%track% - ][%title%]]|%file%]' artist \"$artist\" album \"\$album\"" \
143
-      --expect='f1,f3,enter,ctrl-x' \
144
-      --bind='Ctrl-A:select-all' |
214
+      --preview="mpc search -f '[[[%track% - ][%title%]]|%file%]' artist '$artist' album {2}" \
215
+      --expect="f1,f2,f3,f4,enter,$findadd_key" \
216
+      --delimiter='\t' |
145 217
       cut -f2)
146 218
   case "${choice[0]}" in
147
-    'f1') filter_all_songs ;;
148
-    'f3') filter_by_playlist ;;
219
+    "$playlist_view_key") filter_by_playlist ;;
220
+    "$artist_view_key") filter_by_artist ;;
221
+    "$track_view_key") filter_all_songs ;;
222
+    "$genre_view_key") filter_by_genre ;;
149 223
     'enter') filter_songs_from_album "$artist" "${choice[1]}" ;;
150
-    'ctrl-x') play_album "${choice[1]}" ;;
224
+    "$findadd_key") mpc findadd album "${choice[1]}" ;;
151 225
     *) filter_by_artist ;;
152 226
   esac
153 227
 }
@@ -162,13 +236,15 @@ filter_songs_from_album() {
162 236
       --multi \
163 237
       --with-nth='2..' \
164 238
       --delimiter='\t' \
165
-      --expect='f1,f3,enter' \
166
-      --bind='Ctrl-A:select-all' |
239
+      --expect='f1,f2,f3,enter' |
167 240
     cut -f1)
168 241
   case "${choice[0]}" in
169
-    'f1') filter_all_songs ;;
170
-    'f3') filter_by_playlist ;;
171
-    'enter') printf '%s\n' "${choice[@]:1}" | play_songs ;;
242
+    "$playlist_view_key") filter_by_playlist ;;
243
+    "$artist_view_key") filter_by_artist ;;
244
+    "$track_view_key") filter_all_songs ;;
245
+    "$genre_view_key") filter_by_genre ;;
246
+    'enter') filter_songs_from_album "$artist" "${choice[1]}" ;;
247
+    'enter') printf '%s\n' "${choice[@]:1}" | add_songs play ;;
172 248
     *) filter_by_album_from_artist "$artist" ;;
173 249
   esac
174 250
 }
@@ -182,23 +258,26 @@ filter_by_playlist() {
182 258
       ${current_song:+--header="now playing: ${current_song}"} \
183 259
       --delimiter='\t' \
184 260
       --with-nth='2..' \
185
-      --expect='f1,f2,>,<,ctrl-d,enter,del' |
261
+      --expect='f1,f2,f3,f4,>,<,ctrl-d,enter,ctrl-z' |
186 262
     cut -f1) || die
187 263
   case "${choice[0]}" in
188
-    'f1') filter_all_songs ;;
189
-    'f2') filter_by_artist ;;
264
+    "$playlist_view_key") filter_by_playlist ;;
265
+    "$artist_view_key") filter_by_artist ;;
266
+    "$track_view_key") filter_all_songs ;;
267
+    "$genre_view_key") filter_by_genre ;;
190 268
     '>') mpc -q next; filter_by_playlist ;;
191 269
     '<') mpc -q prev; filter_by_playlist ;;
192
-    'ctrl-d') [[ -n "${choice[1]}" ]] && mpc -q del "${choice[@]:1}"; filter_by_playlist ;;
193
-    'enter') [[ -n "${choice[1]}" ]] && mpc -q play "${choice[@]:1}"; filter_by_playlist ;;
194
-    'del') [[ -n "${choice[1]}" ]] && mpc -q del "${choice[@]:1}"; filter_by_playlist ;;
270
+    'ctrl-d') [[ -n "${choice[1]}" ]] && mpc -q del "${choice[@]:1}"& filter_by_playlist ;;
271
+    'enter') [[ -n "${choice[1]}" ]] && mpc -q play "${choice[@]:1}"& filter_by_playlist ;;
272
+    'ctrl-z') mpc clear; filter_by_artist  ;;
195 273
   esac
196 274
 }
197 275
 
198
-play_songs() {
276
+add_songs() {
199 277
   mapfile -t songs
200 278
   (( "${#songs[@]}" > 0 )) || die
201 279
   printf '%s\n' "${songs[@]}" | mpc -q add
280
+  [[ $1 == play ]] || return
202 281
   index=$(mpc playlist | wc -l)
203 282
   (( ${#songs[@]} > 1 )) &&
204 283
     index=$(( index - ${#songs[@]} + 1))
@@ -206,32 +285,14 @@ play_songs() {
206 285
   filter_by_playlist
207 286
 }
208 287
 
209
-play_artist() {
210
-    mpc findadd albumartist "$@"
211
-    filter_by_playlist
212
-}
213
-
214
-play_album() {
215
-    mpc findadd album "$@"
216
-    filter_by_playlist
217
-}
218
-
219 288
 [[ -s "$config_file" ]] && parse_config_file < "$config_file"
220 289
 
221
-if (( verbose > 0 && ${#config_err[@]} > 0 )); then
222
-  err 'there were errors parsing config file:'
223
-  for e in "${config_err[@]}"; do
224
-    err "$e"
225
-  done
226
-fi
227
-
228 290
 while :; do
229 291
   case "$1" in
230 292
     -A|--all) default_filter='filter_all_songs'; shift ;;
231 293
     -a|--artist) default_filter='filter_by_artist'; shift ;;
232 294
     -p|--playlist) default_filter='filter_by_playlist'; shift ;;
233 295
     -h|--help) usage; exit ;;
234
-    -v|--verbose) (( verbose++ )); shift ;;
235 296
     *) break
236 297
   esac
237 298
 done

Loading…
Cancel
Save