Browse Source

Merge branch '6AA4FD-patch-1'

DanielFGray 1 year ago
parent
commit
5ee418f597
1 changed files with 127 additions and 53 deletions
  1. 127
    53
      fzmp

+ 127
- 53
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,40 +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 ;;
148
+  esac
149
+}
150
+
151
+filter_by_genre() {
152
+  local choice
153
+  mapfile -t choice < <(mpc search -f '%genre%' genre '' | awk 'NF' | sort | uniq -ic | sort -rn |
154
+    fzf \
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*//')
158
+  (( ${#choice[@]} > 0 )) || die
159
+  case "${choice[0]}" in
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 ;;
184
+    enter) filter_by_album_from_artist "${choice[1]}" ;;
185
+    *) "$filter_by_genre" ;;
116 186
   esac
117 187
 }
118 188
 
119 189
 filter_by_artist() {
120 190
   local choice
121 191
   mapfile -t choice < <(mpc list artist |
122
-    sort -h |
123 192
     fzf \
124
-      --preview='mpc list album artist {}' \
125
-      --expect='f1,f3,enter')
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')
126 196
   (( ${#choice[@]} > 0 )) || die
127 197
   case "${choice[0]}" in
128
-    f1) filter_all_songs ;;
129
-    f3) filter_by_playlist ;;
130
-    enter) filter_by_album_from_artist "${choice[1]}" ;;
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 ;;
131 204
   esac
132 205
 }
133 206
 
@@ -135,17 +208,20 @@ filter_by_album_from_artist() {
135 208
   local album artist choice
136 209
   [[ -z "$1" ]] && filter_by_artist
137 210
   artist="$1"
138
-  mapfile -t choice < <(mpc search -f '[(%date%)\t][%album%]' artist "$artist" |
211
+  mapfile -t choice < <(mpc search -f '[(%date%)]\t[%album%]' artist "$artist" |
139 212
     sort -h | uniq |
140 213
     fzf --prompt="$artist > " \
141
-      --preview="album=\$(cut -f2 <<< {}); mpc search -f '[[[%track% - ][%title%]]|%file%]' artist \"$artist\" album \"\$album\"" \
142
-      --expect='f1,f3,enter' \
143
-      --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' |
144 217
       cut -f2)
145 218
   case "${choice[0]}" in
146
-    'f1') filter_all_songs ;;
147
-    '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 ;;
148 223
     'enter') filter_songs_from_album "$artist" "${choice[1]}" ;;
224
+    "$findadd_key") mpc findadd album "${choice[1]}" ;;
149 225
     *) filter_by_artist ;;
150 226
   esac
151 227
 }
@@ -160,13 +236,15 @@ filter_songs_from_album() {
160 236
       --multi \
161 237
       --with-nth='2..' \
162 238
       --delimiter='\t' \
163
-      --expect='f1,f3,enter' \
164
-      --bind='Ctrl-A:select-all' |
239
+      --expect='f1,f2,f3,enter' |
165 240
     cut -f1)
166 241
   case "${choice[0]}" in
167
-    'f1') filter_all_songs ;;
168
-    'f3') filter_by_playlist ;;
169
-    '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 ;;
170 248
     *) filter_by_album_from_artist "$artist" ;;
171 249
   esac
172 250
 }
@@ -180,22 +258,26 @@ filter_by_playlist() {
180 258
       ${current_song:+--header="now playing: ${current_song}"} \
181 259
       --delimiter='\t' \
182 260
       --with-nth='2..' \
183
-      --expect='f1,f2,>,<,ctrl-d,enter' |
261
+      --expect='f1,f2,f3,f4,>,<,ctrl-d,enter,ctrl-z' |
184 262
     cut -f1) || die
185 263
   case "${choice[0]}" in
186
-    'f1') filter_all_songs ;;
187
-    '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 ;;
188 268
     '>') mpc -q next; filter_by_playlist ;;
189 269
     '<') mpc -q prev; filter_by_playlist ;;
190
-    'ctrl-d') [[ -n "${choice[1]}" ]] && mpc -q del "${choice[@]:1}"; filter_by_playlist ;;
191
-    'enter') [[ -n "${choice[1]}" ]] && mpc -q play "${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  ;;
192 273
   esac
193 274
 }
194 275
 
195
-play_songs() {
276
+add_songs() {
196 277
   mapfile -t songs
197 278
   (( "${#songs[@]}" > 0 )) || die
198 279
   printf '%s\n' "${songs[@]}" | mpc -q add
280
+  [[ $1 == play ]] || return
199 281
   index=$(mpc playlist | wc -l)
200 282
   (( ${#songs[@]} > 1 )) &&
201 283
     index=$(( index - ${#songs[@]} + 1))
@@ -205,20 +287,12 @@ play_songs() {
205 287
 
206 288
 [[ -s "$config_file" ]] && parse_config_file < "$config_file"
207 289
 
208
-if (( verbose > 0 && ${#config_err[@]} > 0 )); then
209
-  err 'there were errors parsing config file:'
210
-  for e in "${config_err[@]}"; do
211
-    err "$e"
212
-  done
213
-fi
214
-
215 290
 while :; do
216 291
   case "$1" in
217 292
     -A|--all) default_filter='filter_all_songs'; shift ;;
218 293
     -a|--artist) default_filter='filter_by_artist'; shift ;;
219 294
     -p|--playlist) default_filter='filter_by_playlist'; shift ;;
220 295
     -h|--help) usage; exit ;;
221
-    -v|--verbose) (( verbose++ )); shift ;;
222 296
     *) break
223 297
   esac
224 298
 done

Loading…
Cancel
Save