diff --git a/scripts/build.sh b/scripts/build.sh index 9786c9b..506e16b 100755 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -10,8 +10,10 @@ tmpdir=$(mktemp -d) echo "๐Ÿฅš ${GREEN}Internalize sourced files${OFF}" sed -E 's|\. "([^$].+)"$|cat src/\1|e' "$SRC" >"$tmpdir/1.sh" echo "๐Ÿ” ${GREEN}Internalize awk scripts${OFF}" -sed -E 's|@@include (.+)$|cat src/\1|e' "$tmpdir/1.sh" >"$NAME" -echo "๐Ÿฅš ${GREEN}Make executable and cleanup${OFF}" +sed -E 's|@@include (.+)$|cat src/\1|e' "$tmpdir/1.sh" >"$tmpdir/2.sh" +echo "๐Ÿฅš ${GREEN}Internalize awk libraries${OFF}" +sed -E 's|@include "(.+)"$|cat src/\1|e' "$tmpdir/2.sh" >"$NAME" +echo "๐Ÿ” ${GREEN}Make executable and cleanup${OFF}" chmod +x "$NAME" rm -rf "$tmpdir" echo "๐Ÿณ ${GREEN}Done:${OFF} Sucessfully built ${BOLD}${GREEN}$NAME${OFF}" diff --git a/src/awk/artists.awk b/src/awk/artists.awk index 843f119..4b67639 100644 --- a/src/awk/artists.awk +++ b/src/awk/artists.awk @@ -1,47 +1,63 @@ # List artists # -# parameter file_local_artists: This is an optional parameter with the path -# to a file with a MusicBrainz artist ID per -# line. -# parameter format_person: This is the format string for single person -# artists, which includes the <> -# placeholder. -# parameter format_disambiguation: This is the format string for the -# disambiguation part of the artist, with a -# placeholder <>. -# parameter format_group: This is as format_person, but for music -# groups. -# parameter format_local: String to indicate that there is some music -# locally available of an artist +# parameters: +# flagfile: path to a file with a MusicBrainz artist ID per line (optional) +# sortby: sort selector (see `src/sh/awk.sh`) +# +# theme parameters (see `src/sh/awk.sh` and `src/sh/theme.sh`) +# format Format string +# flag_local Flag for locally available music +# flag_nolocal Flag for locally unavailable music +# type_person Single-person artist indicator +# type_group Artist group indicator +# fmtname `printf` expression to transform artist names +# fmtdisambiguation `printf` expression to transform disambiguation # # This awk program takes as input a sequence of lines where the first item is # the MusicBrainz artist ID, the second item is the type of the artist -# ("Person" or "Group"), the third item is the name, and the forth item is a -# disambiguation string. +# ("Person" or "Group"), the third item is the name, the forth item is the sort +# string, and the fifth item is a disambiguation string. # -# The output of this script is a sequence of tab-delimited lines where the -# first item is the format_local string, if some music of that artist is -# locally accessible, and the empty string otherwise, the second item is the -# formatted artist string (formatted according to format_person or -# format_group), the third item is the constant string "0" indicating the -# parent MusicBrainz ID, and the last item is the MusicBrainz artist ID. +# The output of this script is a sequence of tab-delimited lines. The first +# `AV_FMT_CNT` lines are those that will be displayed to the user. The following lines are +# - Field intended for sorting +# - constant 0 (field intended for parent id) +# - MusicBrainz artist ID +# - 1 if some music of that artist is locally available + +@include "lib/awk/lib.awk" + BEGIN { OFS="\t" - local_artists[0] = 0 - delete local_artists[0] - if (file_local_artists) { - while ((getline < file_local_artists) == 1) - local_artists[$1] = 1 - close(file_local_artists) + flagged[0] = 0 + delete flagged[0] + if (flagfile) { + while ((getline < flagfile) == 1) + flagged[$1] = 1 + close(flagfile) } } { - gsub("&", "\\\\&") - name = $2 == "Group" ? format_group : format_person - l = local_artists[$1] ? format_local : "" - if ($4) - name = name " " format_disambiguation - sub("<>", $4, name) - sub("<>", $3, name) - print l, name, "0", $1 + # Read data + line = format + mbid = $1 + type = $2 + name = $3 ? sprintf(fmtname, escape($3)) : "" + sort = 0 + if (sortby) { + sort = sortby == "sort-artist-sortname" ? $4 : $3 + } + disa = $5 ? sprintf(fmtdisambiguation, escape($5)) : "" + # Transform data and fill placeholders + if (flagged[mbid]) + gsub("<>", flag_local, line) + else + gsub("<>", flag_nolocal, line) + if (type == "Group") + gsub("<>", type_group, line) + else + gsub("<>", type_person, line) + gsub("<>", name, line) + gsub("<>", disa, line) + print line, sort, "0", mbid, flagged[mbid] } diff --git a/src/awk/recordings.awk b/src/awk/recordings.awk index 09bb224..a90ece6 100644 --- a/src/awk/recordings.awk +++ b/src/awk/recordings.awk @@ -1,62 +1,62 @@ -# List recordings +# List release groups # -# parameter file_local_recordings: This is an optional parameter with the path -# to a file with a MusicBrainz recording ID -# per line. -# parameter format: The format of a recording line including the -# placeholders <> for medium number, -# < for for track number within a medium, -# <> for the title, <<artist>> for the -# artist string, and <<duration>> for the -# track duration. -# parameter format_local: String to indicate that the track is locally -# available -# parameter format_current: String to indicate that the track is -# "currently playing" -# parameter current_id: MusicBrainz track ID of a track to be marked -# as "currently playing" +# flagfile Path to a file with a MusicBrainz track ID per line, tab-delimited +# from the path to the decoration file (optional) +# +# theme parameters (see `src/sh/awk.sh` and `src/sh/theme.sh`) +# format Format string +# flag_local Flag for locally available music +# flag_nolocal Flag for locally unavailable music +# playing_yes Mark for currently playing track +# playing_no Mark for currently not playing track +# fmtmedia `printf` expression for media identifier +# fmtnr `printf` expression for track number +# fmttitle `printf` expression for title +# fmtartist `printf` expression for artist +# fmtduration `printf` expression track duration # # The input to this awk program is a sequence of lines containing the following fields: -# Field 1: The MusicBrainz ID of the release this track belongs to -# Field 2: MusicBrainz ID of this track -# Field 3: Number of media of theis release -# Field 4: Medium number of this track within the release -# Field 5: Track number of this track within the medium -# Field 6: Duration of this track in miliseconds -# Field 7: Title of this track -# Field 8: Artist of this track -# Field 9: Path to decoratoin file of this release +# Field 1: The MusicBrainz ID of the release this track belongs to +# Field 2: MusicBrainz ID of this track +# Field 3: Number of media of this release +# Field 4: Medium number of this track within the release +# Field 5: Track number of this track within the medium +# Field 6: Duration of this track in milliseconds +# Field 7: Title of this track +# Field 8: Artist of this track +# Field 9: Path to decoration file of this release +# Field 10: Empty outside of playlists, else "yes" if the track is currently +# being played, and something else otherwise. # -# The output is a sequence of tab-delimited lines containing the following fields: -# Field 1: Sort value (to sort the track within the release) -# Field 2: The string `format_local` if the track is locally available -# Field 3: The string `format_current` if the track has MusicBrainz ID `current_id` -# Field 4: The track line to be displayed according to `format` -# Field 5: The MusicBrainz ID of the release this track belongs to -# Field 6: The MusicBrainz ID of this track ":" separated from the path to the -# decoration file of this release +# The output of this script is a sequence of tab-delimited lines. The first +# `REC_FMT_CNT` fields are those that will be displayed to the user. The +# following fields are +# - Constant 0 (we will not sort) +# - MusicBrainz release ID if specified, else the constant "0" +# - MusicBrainz track ID +# - Path to decoration file if some music of that release is locally available + +@include "lib/awk/lib.awk" + BEGIN { OFS="\t" - local_recordings[0] = 0 - delete local_recordings[0] - if (file_local_recordings) { - while ((getline < file_local_recordings) == 1) - local_recordings[$1] = 1 - close(file_local_recordings) + flagged[0] = 0 + delete flagged[0] + if (flagfile) { + while ((getline < flagfile) == 1) + flagged[$1] = 1 + close(flagfile) } } { - parentid = $1 - id = $2 - medtot = $3 - med = $4 - nr = $5 + # Read data + line = format + releaseid = $1 + mbid = $2 + medtot = $3 + 0 + med = ($4 && medtot >= 2) ? sprintf(fmtmedia, escape($4)) : "" + nr = $5 ? sprintf(fmtnr, escape($5)) : "" dur = $6 - title = $7 - artist = $8 - deco = local_recordings[id] ? $9 : "" - gsub("&", "\\\\&", title) - gsub("&", "\\\\&", artist) # Parse duration if (dur) { dur = int(dur / 1000) @@ -70,17 +70,27 @@ BEGIN { } else { dur = "??:??" } - line = format - if (medtot == 1) - sub("<<med>>", "", line) + dur = sprintf(fmtduration, dur) + title = $7 ? sprintf(fmttitle, escape($7)) : "" + artist = $8 ? sprintf(fmtartist, escape($8)) : "" + if (flagged[mbid] && $9) + flagged[mbid] = $9 + current = $10 + # Transform data and fill placeholders + if (flagged[mbid]) + gsub("<<flag>>", flag_local, line) else - sub("<<med>>", med, line) - sub("<<nr>>", nr, line) - sub("<<title>>", title, line) - sub("<<artist>>", artist, line) - sub("<<duration>>", dur, line) - l = local_recordings[id] ? format_local : "" - c = id == current_id ? format_current : "" - sortk = med" "nr - print sortk, l, c, line, parentid, id ":" deco + gsub("<<flag>>", flag_nolocal, line) + gsub("<<media>>", med, line) + gsub("<<nr>>", nr, line) + gsub("<<title>>", title, line) + gsub("<<artist>>", artist, line) + gsub("<<duration>>", dur, line) + if (current) { + if (current == "yes") + gsub("<<playing>>", playing_yes, line) + else + gsub("<<playing>>", playing_no, line) + } + print line, "0", releaseid ? releaseid : "0", mbid, flagged[mbid] ? flagged[mbid] : (current ? $9 : "") } diff --git a/src/awk/releasegroups.awk b/src/awk/releasegroups.awk index f77f129..ba76859 100644 --- a/src/awk/releasegroups.awk +++ b/src/awk/releasegroups.awk @@ -1,48 +1,37 @@ # List release groups # -# parameter file_local_releasegroups: This is an optional parameter with the -# path to a file with a MusicBrainz -# release-group ID per line. -# parameter format_release: Format for the release title with a -# <<title>> placeholder. -# parameter format_release_w_artist: Same as `format_release` but with an -# additional <<artist>> placeholder. -# parameter format_year: Format string for the year part, with a -# <<year>> placeholder. -# parameter format_local: String to indicate that the track is -# locally available. -# parameter artist: Artist name to compare release-groups -# artist names against. If the names -# differ, then the format with <<artist>> -# placeholder is used (optional) -# parameter artistid MusicBrainz ID of the artist (optional). -# Then, there are several format strings that indicate the type of a release -# group. The types are implicit from the parameter names: -# parameter format_album -# parameter format_single -# parameter format_ep -# parameter format_broadcast -# parameter format_other -# Some release groups have also a secondary type. The presence of a secondary -# type is formatted using -# parameter format_secondary. -# The list of all secondary types (implicit from their variable names) are -# formatted using -# parameter format_secondary. -# Each of the secondary types is specified with (the type is implicit from the -# variable names) -# parameter format_compilation -# parameter format_soundtrack -# parameter format_spokenword -# parameter format_interview -# parameter format_audiobook -# parameter format_audiodrama -# parameter format_live -# parameter format_remix -# parameter format_djmix -# parameter format_mixtape -# parameter format_demo -# parameter format_fieldrec +# flagfile path to a file with a MusicBrainz release-group ID per line (optional) +# sortby sort selector (see `src/sh/awk.sh`) +# origartist Artist name to compare release-groups (optional) +# artistid MusicBrainz ID of the artist (optional) +# +# theme parameters (see `src/sh/awk.sh` and `src/sh/theme.sh`) +# format Format string +# flag_local Flag for locally available music +# flag_nolocal Flag for locally unavailable music +# type_single Single +# type_album LP +# type_ep EP +# type_broadcast Broadcast +# type_other Other type +# type_unknown Type unknown +# hassecondary_yes Release group has secondary type(s) +# hassecondary_no Release group does not have any secondary type +# fmtsecondary `printf` expression to display secondary type +# secondary_soundtrack ... +# secondary_spokenword ... +# secondary_interview ... +# secondary_audiobook ... +# secondary_audiodrama ... +# secondary_live ... +# secondary_remix ... +# secondary_djmix ... +# secondary_mixtape ... +# secondary_demo ... +# secondary_fieldrec ... +# fmttitle `printf` expression to transform title +# fmtartist `printf` expression to transform artist +# fmtyear `printf` expression to transform year # # The input to this awk program is a sequence of lines containing the following # fields: @@ -53,76 +42,83 @@ # Field 5: Title of the release group # Field 6: The artist as credited # -# The output is a sequence of tab-delimited lines with the fields: -# Field 1: Sort value to sort release groups -# Field 2: The flag `format_local` if the release group is accessible locally, -# and "" else. -# Field 3: Release-group type -# Field 4: Release-group string -# Field 5: Release-group year -# Field 6: Secondary types -# Field 7: MusicBrainz artist ID of the release group artist, if there is one, -# else "0" -# Field 8: MusicBrainz release-group ID +# The output of this script is a sequence of tab-delimited lines. The first +# `RGV_FMT_CNT` fields are those that will be displayed to the user. The +# following fields are +# - sort key (release year) +# - MusicBrainz artist ID if specified, else the constant "0" +# - MusicBrainz release-group ID +# - 1 if some music of that release group is locally available + +@include "lib/awk/lib.awk" + BEGIN { OFS="\t" - local_releasegroups[0] = 0 - delete local_releasegroups[0] - if (file_local_releasegroups) { - while ((getline < file_local_releasegroups) == 1) - local_releasegroups[$1] = 1 - close(file_local_releasegroups) + flagged[0] = 0 + delete flagged[0] + if (flagfile) { + while ((getline < flagfile) == 1) + flagged[$1] = 1 + close(flagfile) } } { - line_type = "" - line_sectype = "" - line_year = "" - gsub("&", "\\\\&") - id = $1 + # Read data + line = format + mbid = $1 type = $2 sectype = $3 - year = substr($4, 1, 4) + 0 - title = $5 - artistcredit = $6 - line_release = artist == artistcredit ? format_release : format_release_w_artist - l = local_releasegroups[$1] ? format_local : "" - switch (type) { - case "Single": line_type=format_single; break - case "Album": line_type=format_album; break - case "EP": line_type=format_ep; break - case "Broadcast": line_type=format_broadcast; break - case "Other": line_type=format_other; break - default: line_type="" + year = $4 ? sprintf(fmtyear, substr($4, 1, 4) + 0) : "" + title = $5 ? sprintf(fmttitle, escape($5)) : "" + artist = escape($6) != origartist ? sprintf(fmtartist, escape($6)) : "" + sort = $4 ? -$4 : 0 + sort = 0 + if (sortby) { + sort = sortby == "sort-rg-year" ? ($4 ? -$4 : 0) : $5 } + # Transform data and fill placeholders + if (flagged[mbid]) + gsub("<<flag>>", flag_local, line) + else + gsub("<<flag>>", flag_nolocal, line) + switch (type) { + case "Single": t = type_single; break + case "Album": t = type_album; break + case "EP": t = type_ep; break; + case "Broadcast": t = type_broadcast; break + case "Other": t = type_other; break + default: t = type_unknown; break + } + gsub("<<type>>", t, line) + if (sectype) + gsub("<<hassecondary>>", hassecondary_yes, line) + else + gsub("<<hassecondary>>", hassecondary_no, line) + gsub("<<title>>", title, line) + gsub("<<artist>>", artist, line) + gsub("<<year>>", year, line) + t = "" + s = "" split(sectype, a, ";") for (i in a) { - t="" switch (a[i]) { - case "Compilation": t=format_compilation; break - case "Soundtrack": t=format_soundtrack; break - case "Spokenword": t=format_spokenword; break - case "Interview": t=format_interview; break - case "Audiobook": t=format_audiobook; break - case "Audio drama": t=format_audiodrama; break - case "Live": t=format_live; break - case "Remix": t=format_remix; break - case "DJ-mix": t=format_djmix; break - case "Mixtape/Street": t=format_mixtape; break - case "Demo": t=format_demo; break - case "Field recording": t=fieldrec; break + case "Compilation": t = secondary_compilation; break + case "Soundtrack": t = secondary_soundtrack; break + case "Spokenword": t = secondary_spokenword; break + case "Interview": t = secondary_interview; break + case "Audiobook": t = secondary_audiobook; break + case "Audio drama": t = secondary_audiodrama; break + case "Live": t = secondary_live; break + case "Remix": t = secondary_remix; break + case "DJ-mix": t = secondary_djmix; break + case "Mixtape/Street": t = secondary_mixtape; break + case "Demo": t = secondary_demo; break + case "Field recording": t = secondary_fieldrec; break } if (t) - line_sectype=line_sectype ? line_sectype ", " t : t + s = s ? s ", " t : t } - if (sectype) { - line_type = sprintf(format_has_secondary, line_type) - line_sectype = sprintf(format_secondary, line_sectype) - } - sub("<<title>>", title, line_release) - sub("<<artist>>", artistcredit, line_release) - line_year = year ? format_year : "" - sub("<<year>>", year, line_year) - sortk = year ? year : 0 - print sortk, l, line_type, line_release, line_year, line_sectype, artistid ? artistid : "0", id + s = s ? sprintf(fmtsecondary, s) : "" + gsub("<<secondary>>", s, line) + print line, sort, artistid ? artistid : "0", mbid, flagged[mbid] } diff --git a/src/awk/releases.awk b/src/awk/releases.awk index d6edd99..88971b7 100644 --- a/src/awk/releases.awk +++ b/src/awk/releases.awk @@ -1,35 +1,31 @@ -# List releases +# List release groups # -# parameter file_local_releases: This is an optional parameter with the -# path to a file with a MusicBrainz -# release ID per line. -# parameter format_release: Format for the release with the -# placeholders <<status>>, <<tracks>>, -# <<media>>, <<year>>, <<country>>, and -# <<label>>. -# parameter format_release_title_artist: Format to specify title and artist, -# with the placeholders <<title>> and -# <<artist>>. -# parameter format_release_title: Format to specify the release title -# with a placeholder <<title>>. -# parameter format_release_artist: Format to specify the release artist -# with a placeholder <<artist>>. -# parameter format_local: String to indicate that the track is -# locally available. -# parameter rg_artist: Artist name of release group -# (optional) -# parameter rg_title: Title of release group (optional) -# parameter rgid: MusicBrainz release-group ID -# (optional) -# Then, there are several format strings that indicate the status of a release. -# The status are implicit from the parameter names: -# parameter release_official -# parameter release_promotion -# parameter release_bootleg -# parameter release_pseudo -# parameter release_withdrawn -# parameter release_expunged -# parameter release_cancelled +# flagfile path to a file with a MusicBrainz release ID per line, +# tab-delimited from the path to the decoration file +# (optional) +# origtitle Title of release group (optional) +# origartist Artist credit of release group (optional) +# releasegroupid MusicBrainz release-group ID (optional) +# +# theme parameters (see `src/sh/awk.sh` and `src/sh/theme.sh`) +# format Format string +# flag_local Flag for locally available music +# flag_nolocal Flag for locally unavailable music +# status_official Official release +# status_promo Promotional release +# status_bootleg Bootleg release +# status_pseudo Pseudo release +# status_withdrawn Withdrawn +# status_expunged Expunged release +# status_cancelled Cancelled release +# status_unknown Status of release is not specified +# fmttracks `printf` expression for track number +# fmtmedia `printf` expression for media number +# fmtyear `printf` expression for release year +# fmtcountry `printf` expression for release country +# fmtlabel `printf` expression for label +# fmttitle `printf` expression for release title +# fmtartist `printf` expression for release artist credits # # The input to this awk program is a sequence of lines containing the following # fields: @@ -44,68 +40,62 @@ # Field 9: Release title # Field 10: Artist as credited # -# The output is a sequence of tab-delimited lines with the fields: -# Field 1: Sort value to sort release groups -# Field 2: The flag `format_local` if the release is accessible locally, and "" -# else. -# Field 3: Release line -# Field 4: MusicBrainz release-group ID if present, else "0" -# Field 5: MusicBrainz release ID followed by ":" and then a path to the -# decoration file (if it exists) +# The output of this script is a sequence of tab-delimited lines. The first +# `RV_FMT_CNT` fields are those that will be displayed to the user. The +# following fields are +# - sort key (release year) +# - MusicBrainz release-group ID if specified, else the constant "0" +# - MusicBrainz release ID +# - Path to decoration file if some music of that release is locally available + +@include "lib/awk/lib.awk" + BEGIN { OFS="\t" - local_releases[0] = 0 - delete local_releases[0] - if (file_local_releases) { - while ((getline < file_local_releases) == 1) - local_releases[$1] = $2 - close(file_local_releases) + flagged[0] = 0 + delete flagged[0] + if (flagfile) { + while ((getline < flagfile) == 1) + flagged[$1] = $2 + close(flagfile) } } { - id = $1 + # Read data + line = format + mbid = $1 status = $2 - year = substr($3, 1, 4) + 0 - year = year == 0 ? "" : year + year = $3 ? sprintf(fmtyear, substr($3, 1, 4) + 0) : "" covercount = $4 - label = $5 - trackcnt = $6 - media = $7 - country = $8 - title = $9 - artist = $10 - switch (status) { - case "Official": line_status = release_official; break - case "Promotion": line_status = release_promotion; break - case "Bootleg": line_status = release_bootleg; break - case "Pseudo-release": line_status = release_pseudo; break - case "Withdrawn": line_status = release_withdrawn; break - case "Expunged": line_status = release_expunged; break - case "Cancelled": line_status = release_cancelled; break - default: line_status = "" - } - line = format_release - if (artist != rg_artist && title != rg_title) - line = line "\t" format_release_title_artist - else if (artist != rg_artist && title == rg_title) - line = line "\t" format_release_artist - else if (artist == rg_artist && title != rg_title) - line = line "\t" format_release_title + label = $5 ? sprintf(fmtlabel, escape($5)) : "" + tracks = $6 ? sprintf(fmttracks, escape($6)) : "" + media = $7 ? sprintf(fmtmedia, escape($7)) : "" + country = $8 ? sprintf(fmtcountry, escape($8)) : "" + title = escape($9) != origtitle ? sprintf(fmttitle, escape($9)) : "" + artist = escape($10) != origartist ? sprintf(fmtartist, escape($10)) : "" + sort = $3 + 0 + # Transform data and fill placeholders + if (flagged[mbid]) + gsub("<<flag>>", flag_local, line) else - line = line "\t" - - gsub("<<status>>", line_status, line) - gsub("<<year>>", year, line) - gsub("<<tracks>>", trackcnt, line) + gsub("<<flag>>", flag_nolocal, line) + switch (status) { + case "Official": s = status_official; break + case "Promotion": s = status_promotion; break + case "Bootleg": s = status_bootleg; break + case "Pseudo-release": s = status_pseudo; break + case "Withdrawn": s = status_withdrawn; break + case "Expunged": s = status_expunged; break + case "Cancelled": s = status_cancelled; break + default: s = status_unknown + } + gsub("<<status>>", s, line) + gsub("<<tracks>>", tracks, line) gsub("<<media>>", media, line) - gsub("&", "\\\\&", label) - gsub("<<label>>", label, line) - gsub("&", "\\\\&", title) - gsub("<<title>>", title, line) - gsub("&", "\\\\&", artist) - gsub("<<artist>>", artist, line) + gsub("<<year>>", year, line) gsub("<<country>>", country, line) - sortk = year ? year : 0 - l = local_releases[id] ? format_local : "" - print sortk, l, line, rgid ? rgid : "0", id ":" local_releases[id] + gsub("<<label>>", label, line) + gsub("<<title>>", title, line) + gsub("<<artist>>", artist, line) + print line, sort, releasegroupid ? releasegroupid : "0", mbid, flagged[mbid] ? flagged[mbid] : "" } diff --git a/src/lib/awk/lib.awk b/src/lib/awk/lib.awk new file mode 100644 index 0000000..6fb5883 --- /dev/null +++ b/src/lib/awk/lib.awk @@ -0,0 +1,7 @@ +# Awk methods commonly used + +# Escape string +function escape(s) { + gsub("&", "\\\\&", s) + return s +} diff --git a/src/main.sh b/src/main.sh index 44f3416..955054e 100755 --- a/src/main.sh +++ b/src/main.sh @@ -83,6 +83,21 @@ MODE_INSERT="show" # Load keys . "sh/keys.sh" +# Load configuration +. "sh/config.sh" + +# Load sorting methods +. "sh/sort.sh" + +# Load theme +. "sh/theme.sh" + +# Load tools +. "sh/tools.sh" + +# Load AWK scripts +. "sh/awk.sh" + # Command-line options that may only be used internally. # --lines # --playback @@ -126,6 +141,7 @@ case "${1:-}" in # @argument $3: MusicBrainz ID of current object # @argument $4: MusicBrainz ID of selected object # @argument $5: Path to decoration file + info "call to $*" shift playback "$@" exit 0 @@ -350,18 +366,6 @@ case "${1:-}" in ;; esac -# Load configuration -. "sh/config.sh" - -# Load theme -. "sh/theme.sh" - -# Load tools -. "sh/tools.sh" - -# Load AWK scripts -. "sh/awk.sh" - # Non-interactive user commands intended to the user. These commands do not # require temporary files, fzf, nor the mpv instance. case "${1:-}" in @@ -565,11 +569,11 @@ while true; do --border="bold" \ --border-label="Select artist" \ --preview-window="right,25%,border-left,wrap,<30(hidden)" \ - --preview="$0 --preview $VIEW_SELECT_ARTIST {3}" \ + --preview="$0 --preview $VIEW_SELECT_ARTIST {4}" \ --delimiter="\t" \ --prompt="$SEARCH_PROMPT" \ --margin="5%,20%" \ - --accept-nth="{3}" \ + --accept-nth="{4}" \ --with-nth="{1}" || true ) lines=$(echo "$sel" | wc -l) @@ -599,20 +603,20 @@ while true; do --bind="$KEYS_N_BOT:last" \ --bind="$KEYS_N_TOP:first" \ --bind="$KEYS_OUT,$KEYS_N_OUT,$KEYS_QUIT,$KEYS_N_QUIT:print($LASTVIEW)+print($LASTARG)+print($VIEW_PLAYLIST)+print()+accept" \ - --bind="$KEYS_SELECT_ARTIST:transform:$0 --action-gotoartist $MODE_NORMAL $VIEW_PLAYLIST {2} {3}" \ + --bind="$KEYS_SELECT_ARTIST:transform:$0 --action-gotoartist $MODE_NORMAL $VIEW_PLAYLIST {3} {4}" \ --bind="$KEYS_LIST_ARTISTS:print($VIEW_LIST_ARTISTS)+accept" \ --bind="$KEYS_LIST_ALBUMS:print($VIEW_LIST_ALBUMS)+accept" \ --bind="$KEYS_SEARCH_ARTIST:print($VIEW_SEARCH_ARTIST)+accept" \ --bind="$KEYS_SEARCH_ALBUM:print($VIEW_SEARCH_ALBUM)+accept" \ --bind="$KEYS_BROWSE:execute-silent:open \"https://musicbrainz.org/\track/{r3}\"" \ - --bind="$KEYS_OPEN:execute-silent:open \"\$(dirname {4})\"" \ - --bind="$KEYS_N_YANK:execute-silent:printf {3} | $CLIP)" \ - --bind="$KEYS_YANK_CURRENT:execute-silent:printf {2} | $CLIP" \ + --bind="$KEYS_OPEN:execute-silent:open \"\$(dirname {5})\"" \ + --bind="$KEYS_N_YANK:execute-silent:printf {4} | $CLIP)" \ + --bind="$KEYS_YANK_CURRENT:execute-silent:printf {3} | $CLIP" \ --bind="$KEYS_KEYBINDINGS:preview:$0 --show-keybindings $VIEW_PLAYLIST" \ --bind="$KEYS_SCROLL_PREVIEW_DOWN:preview-down" \ --bind="$KEYS_SCROLL_PREVIEW_UP:preview-up" \ --bind="$KEYS_PREVIEW_CLOSE:hide-preview" \ - --bind="$KEYS_PLAYBACK,$KEYS_N_PLAYBACK:transform($0 --playback $VIEW_PLAYLIST {2} {3} {4})+$FZF_RELOAD_PLAYLIST+$FZF_POS_PLAYLIST" \ + --bind="$KEYS_PLAYBACK,$KEYS_N_PLAYBACK:transform($0 --playback $VIEW_PLAYLIST {3} {4} {5})+$FZF_RELOAD_PLAYLIST+$FZF_POS_PLAYLIST" \ --bind="$KEYS_PLAYLIST_RELOAD:$FZF_RELOAD_PLAYLIST+$FZF_POS_PLAYLIST" \ --bind="$KEYS_PLAYLIST_REMOVE:execute-silent($0 --playlist $PLAYLIST_CMD_REMOVE)+$FZF_RELOAD_PLAYLIST" \ --bind="$KEYS_PLAYLIST_UP:execute-silent($0 --playlist $PLAYLIST_CMD_UP)+up+$FZF_RELOAD_PLAYLIST" \ @@ -625,7 +629,7 @@ while true; do --bind="$KEYS_PLAYLIST_GOTO_RELEASE:print($VIEW_RELEASE)+accept" \ --delimiter="\t" \ --with-nth="{1}" \ - --accept-nth="{2}" || true + --accept-nth="{3}" || true ) VIEW="$(echo "$sel" | head -1)" ARGS="$(echo "$sel" | head -2 | tail -1)" @@ -667,11 +671,11 @@ while true; do --bind="$KEYS_N_UP:transform:$IN_NORMAL_MODE && echo up || $PUT_FZF_KEY_LOGIC" \ --bind="$KEYS_N_BOT:transform:$IN_NORMAL_MODE && echo last || $PUT_FZF_KEY_LOGIC" \ --bind="$KEYS_N_TOP:transform:$IN_NORMAL_MODE && echo first || $PUT_FZF_KEY_LOGIC" \ - --bind="$KEYS_IN:transform:[ {3} ] && $0 --action-draw $FZF_CURRENT_MODE $FZF_CURRENT_VIEW {3} \"+1\"" \ - --bind="$KEYS_OUT:transform:[ {2} ] && $0 --action-draw $FZF_CURRENT_MODE $FZF_CURRENT_VIEW {2} \"-1\"" \ - --bind="$KEYS_N_IN:transform:$IN_NORMAL_MODE && ([ {3} ] && $0 --action-draw $FZF_CURRENT_MODE $FZF_CURRENT_VIEW {3} \"+1\") || $PUT_FZF_KEY_LOGIC" \ - --bind="$KEYS_N_OUT:transform:$IN_NORMAL_MODE && ([ {2} ] && $0 --action-draw $FZF_CURRENT_MODE $FZF_CURRENT_VIEW {2} \"-1\") || $PUT_FZF_KEY_LOGIC" \ - --bind="$KEYS_SELECT_ARTIST:transform:$0 --action-gotoartist $FZF_CURRENT_MODE $FZF_CURRENT_VIEW {2} {3}" \ + --bind="$KEYS_IN:transform:[ {4} ] && $0 --action-draw $FZF_CURRENT_MODE $FZF_CURRENT_VIEW {4} \"+1\"" \ + --bind="$KEYS_OUT:transform:[ {3} ] && $0 --action-draw $FZF_CURRENT_MODE $FZF_CURRENT_VIEW {3} \"-1\"" \ + --bind="$KEYS_N_IN:transform:$IN_NORMAL_MODE && ([ {4} ] && $0 --action-draw $FZF_CURRENT_MODE $FZF_CURRENT_VIEW {4} \"+1\") || $PUT_FZF_KEY_LOGIC" \ + --bind="$KEYS_N_OUT:transform:$IN_NORMAL_MODE && ([ {3} ] && $0 --action-draw $FZF_CURRENT_MODE $FZF_CURRENT_VIEW {3} \"-1\") || $PUT_FZF_KEY_LOGIC" \ + --bind="$KEYS_SELECT_ARTIST:transform:$0 --action-gotoartist $FZF_CURRENT_MODE $FZF_CURRENT_VIEW {3} {4}" \ --bind="$KEYS_LIST_ARTISTS:transform:$0 --action-draw \$FZF_INPUT_STATE $VIEW_LIST_ARTISTS" \ --bind="$KEYS_LIST_ALBUMS:transform:$0 --action-draw \$FZF_INPUT_STATE $VIEW_LIST_ALBUMS" \ --bind="$KEYS_SEARCH_ARTIST:transform:$0 --action-draw $MODE_INSERT $VIEW_SEARCH_ARTIST" \ @@ -690,7 +694,7 @@ $VIEW_SEARCH_ALBUM) $0 --action-draw $MODE_NORMAL $VIEW_LIST_ALBUMS ;; esac" \ --bind="$KEYS_FILTER:transform:$0 --action-filter $FZF_CURRENT_MODE $FZF_CURRENT_VIEW" \ --bind="$KEYS_BROWSE:execute-silent: -[ {3} ] || exit 0 +[ {4} ] || exit 0 case $FZF_CURRENT_VIEW in $VIEW_LIST_ARTISTS | $VIEW_SEARCH_ARTIST) t=artist ;; $VIEW_ARTIST | $VIEW_SEARCH_ALBUM | $VIEW_LIST_ALBUMS) t=release-group ;; @@ -699,25 +703,24 @@ case $FZF_CURRENT_VIEW in esac open \"https://musicbrainz.org/\$t/{r3}\"" \ --bind="$KEYS_OPEN:execute-silent: -[ {4} ] || exit 0 -open \"\$(dirname {4})\"" \ - --bind="$KEYS_N_YANK:transform:$IN_NORMAL_MODE && echo \"execute-silent(printf {3} | $CLIP)\" || $PUT_FZF_KEY_LOGIC" \ - --bind="$KEYS_YANK_CURRENT:execute-silent:printf {2} | $CLIP" \ - --bind="$KEYS_SHOW_PLAYLIST:transform:echo \"print($VIEW_PLAYLIST)+print()+print($FZF_CURRENT_VIEW)+print({2})+accept\"" \ +[ {5} ] || exit 0 +open \"\$(dirname {5})\"" \ + --bind="$KEYS_N_YANK:transform:$IN_NORMAL_MODE && echo \"execute-silent(printf {4} | $CLIP)\" || $PUT_FZF_KEY_LOGIC" \ + --bind="$KEYS_YANK_CURRENT:execute-silent:printf {3} | $CLIP" \ + --bind="$KEYS_SHOW_PLAYLIST:transform:echo \"print($VIEW_PLAYLIST)+print()+print($FZF_CURRENT_VIEW)+print({3})+accept\"" \ --bind="$KEYS_KEYBINDINGS:preview:$0 --show-keybindings $FZF_CURRENT_VIEW" \ - --bind="$KEYS_REFRESH:execute-silent($0 --remove-from-cache $FZF_CURRENT_VIEW {2} {3})+transform:$0 --action-draw $FZF_CURRENT_MODE $FZF_CURRENT_VIEW {2}" \ + --bind="$KEYS_REFRESH:execute-silent($0 --remove-from-cache $FZF_CURRENT_VIEW {3} {4})+transform:$0 --action-draw $FZF_CURRENT_MODE $FZF_CURRENT_VIEW {3}" \ --bind="$KEYS_QUIT:print($VIEW_QUIT)+accept" \ --bind="$KEYS_N_QUIT:transform:$IN_NORMAL_MODE && ($IN_LIST_ARTISTS_VIEW && echo \"print($VIEW_QUIT)+accept\" || $0 --action-draw $MODE_NORMAL $VIEW_LIST_ARTISTS) || $PUT_FZF_KEY_LOGIC" \ --bind="$KEYS_SCROLL_PREVIEW_DOWN:preview-down" \ --bind="$KEYS_SCROLL_PREVIEW_UP:preview-up" \ --bind="$KEYS_PREVIEW_OPEN:show-preview" \ --bind="$KEYS_PREVIEW_CLOSE:hide-preview" \ - --bind="$KEYS_PLAYBACK:transform:$0 --playback $FZF_CURRENT_VIEW {2} {3} {4}" \ - --bind="$KEYS_N_PLAYBACK:transform:$IN_NORMAL_MODE && $0 --playback $FZF_CURRENT_VIEW {2} {3} {4} || $PUT_FZF_KEY_LOGIC" \ - --bind="W:execute-silent:echo 1 >> /tmp/foo; echo $FZF_CURRENT_VIEW >> /tmp/foo; echo 2 >> /tmp/foo" \ + --bind="$KEYS_PLAYBACK:transform:$0 --playback $FZF_CURRENT_VIEW {3} {4} {5}" \ + --bind="$KEYS_N_PLAYBACK:transform:$IN_NORMAL_MODE && $0 --playback $FZF_CURRENT_VIEW {3} {4} {5} || $PUT_FZF_KEY_LOGIC" \ --bind="change:execute-silent($0 --mbsearch $FZF_CURRENT_VIEW &)+reload:$0 --lines $FZF_CURRENT_VIEW" \ --preview-window="right,25%,border-left,wrap,<30(hidden)" \ - --preview="$0 --preview $FZF_CURRENT_VIEW {3}" \ + --preview="$0 --preview $FZF_CURRENT_VIEW {4}" \ --delimiter="\t" \ --with-nth="{1}" || true ) diff --git a/src/sh/awk.sh b/src/sh/awk.sh index 0ae77df..aa1fbbc 100644 --- a/src/sh/awk.sh +++ b/src/sh/awk.sh @@ -1,5 +1,6 @@ # The code below is used together with `scripts/build.sh`to internalize the awk # scripts. See the awk sources for more information. + if [ ! "${AWK_LOADED:-}" ]; then AWK_ARTISTS=$( cat <<'EOF' @@ -31,3 +32,235 @@ EOF export AWK_LOADED=1 fi + +# Themed awk script to generate list of artists +# +# @argument $1: Sort specification (may be one of SORT_NO, SORT_NAME, +# SORT_SORTNAME) +awk_artists() { + case "${1:-}" in + "$SORT_ARTIST" | "$SORT_ARTIST_SORTNAME") s="$SORT_ALPHA" ;; + *) s="$SORT_NO" ;; + esac + cat | + awk \ + -F "\t" \ + -v sortby="${1:-}" \ + -v flagfile="${LOCALDATA_ARTISTS:-}" \ + -v format="$AV_FMT" \ + -v flag_local="$AV_FMT_FLAG_LOCAL" \ + -v flag_nolocal="$AV_FMT_FLAG_NO_LOCAL" \ + -v type_person="$AV_FMT_TYPE_PERSON" \ + -v type_group="$AV_FMT_TYPE_GROUP" \ + -v fmtname="$AV_FMT_NAME" \ + -v fmtdisambiguation="$AV_FMT_DISAMBIGUATION" \ + "$AWK_ARTISTS" | + column -t -s "$(printf '\t')" -R "$AV_FMT_RIGHTALIGN" -l "$AV_FMT_CNT" | + sort_list "$s" +} + +# Themed awk script to generate artist header +awk_artist_header() { + cat | + awk \ + -F "\t" \ + -v flagfile="${LOCALDATA_ARTISTS:-}" \ + -v format="$HEADER_ARTIST_FMT" \ + -v flag_local="$HEADER_ARTIST_FMT_FLAG_LOCAL" \ + -v flag_nolocal="$HEADER_ARTIST_FMT_FLAG_NO_LOCAL" \ + -v type_person="$HEADER_ARTIST_FMT_TYPE_PERSON" \ + -v type_group="$HEADER_ARTIST_FMT_TYPE_GROUP" \ + -v fmtname="$HEADER_ARTIST_FMT_NAME" \ + -v fmtdisambiguation="$HEADER_ARTIST_FMT_DISAMBIGUATION" \ + "$AWK_ARTISTS" | + column -t -s "$(printf '\t')" -R "$HEADER_ARTIST_FMT_RIGHTALIGN" -l "$HEADER_ARTIST_FMT_CNT" | + cut -d "$(printf '\t')" -f 1 +} + +# Themed awk script to generate list of release groups +# +# @argument $1: Sort specification (may be one of SORT_NO, SORT_RG_TITLE, +# SORT_RG_YEAR) +# @argument $2: MusicBrainz artist ID (optional) +# @argument $3: Artist credit name (optional) +awk_releasegroups() { + case "${1:-}" in + "$SORT_RG_TITLE") s="$SORT_ALPHA" ;; + "$SORT_RG_YEAR") s="$SORT_NUMERIC" ;; + *) s="$SORT_NO" ;; + esac + cat | + awk \ + -F "\t" \ + -v sortby="${1:-}" \ + -v artistid="${2:-}" \ + -v origartist="${3:-}" \ + -v flagfile="${LOCALDATA_RELEASEGROUPS:-}" \ + -v format="$RGV_FMT" \ + -v flag_local="$RGV_FMT_FLAG_LOCAL" \ + -v flag_nolocal="$RGV_FMT_FLAG_NO_LOCAL" \ + -v type_single="$RGV_FMT_TYPE_SINGLE" \ + -v type_album="$RGV_FMT_TYPE_ALBUM" \ + -v type_ep="$RGV_FMT_TYPE_EP" \ + -v type_broadcast="$RGV_FMT_TYPE_BROADCAST" \ + -v type_other="$RGV_FMT_TYPE_OTHER" \ + -v type_unknown="$RGV_FMT_TYPE_UNKNOWN" \ + -v hassecondary_yes="$RGV_FMT_HASSECONDARY_YES" \ + -v hassecondary_no="$RGV_FMT_HASSECONDARY_NO" \ + -v fmtsecondary="$RGV_FMT_SECONDARY" \ + -v secondary_soundtrack="$RGV_FMT_SECONDARY_SOUNDTRACK" \ + -v secondary_spokenword="$RGV_FMT_SECONDARY_SPOKENWORD" \ + -v secondary_interview="$RGV_FMT_SECONDARY_INTERVIEW" \ + -v secondary_audiobook="$RGV_FMT_SECONDARY_AUDIOBOOK" \ + -v secondary_audiodrama="$RGV_FMT_SECONDARY_AUDIODRAMA" \ + -v secondary_live="$RGV_FMT_SECONDARY_LIVE" \ + -v secondary_remix="$RGV_FMT_SECONDARY_REMIX" \ + -v secondary_djmix="$RGV_FMT_SECONDARY_DJMIX" \ + -v secondary_mixtape="$RGV_FMT_SECONDARY_MIXTAPE" \ + -v secondary_demo="$RGV_FMT_SECONDARY_DEMO" \ + -v secondary_fieldrec="$RGV_FMT_SECONDARY_FIELDREC" \ + -v fmttitle="$RGV_FMT_TITLE" \ + -v fmtartist="$RGV_FMT_ARTIST" \ + -v fmtyear="$RGV_FMT_YEAR" \ + "$AWK_RELEASEGROUPS" | + column -t -s "$(printf '\t')" -R "$RGV_FMT_RIGHTALIGN" -l "$RGV_FMT_CNT" | + sort_list "$s" +} + +# Themed awk script to generate release-group header +awk_releasegroup_header() { + cat | + awk \ + -F "\t" \ + -v flagfile="${LOCALDATA_RELEASEGROUPS:-}" \ + -v format="$HEADER_RG_FMT" \ + -v flag_local="$HEADER_RG_FMT_FLAG_LOCAL" \ + -v flag_nolocal="$HEADER_RG_FMT_FLAG_NO_LOCAL" \ + -v type_single="$HEADER_RG_FMT_TYPE_SINGLE" \ + -v type_album="$HEADER_RG_FMT_TYPE_ALBUM" \ + -v type_ep="$HEADER_RG_FMT_TYPE_EP" \ + -v type_broadcast="$HEADER_RG_FMT_TYPE_BROADCAST" \ + -v type_other="$HEADER_RG_FMT_TYPE_OTHER" \ + -v type_unknown="$HEADER_RG_FMT_TYPE_UNKNOWN" \ + -v hassecondary_yes="$HEADER_RG_FMT_HASSECONDARY_YES" \ + -v hassecondary_no="$HEADER_RG_FMT_HASSECONDARY_NO" \ + -v fmtsecondary="$HEADER_RG_FMT_SECONDARY" \ + -v secondary_soundtrack="$HEADER_RG_FMT_SECONDARY_SOUNDTRACK" \ + -v secondary_spokenword="$HEADER_RG_FMT_SECONDARY_SPOKENWORD" \ + -v secondary_interview="$HEADER_RG_FMT_SECONDARY_INTERVIEW" \ + -v secondary_audiobook="$HEADER_RG_FMT_SECONDARY_AUDIOBOOK" \ + -v secondary_audiodrama="$HEADER_RG_FMT_SECONDARY_AUDIODRAMA" \ + -v secondary_live="$HEADER_RG_FMT_SECONDARY_LIVE" \ + -v secondary_remix="$HEADER_RG_FMT_SECONDARY_REMIX" \ + -v secondary_djmix="$HEADER_RG_FMT_SECONDARY_DJMIX" \ + -v secondary_mixtape="$HEADER_RG_FMT_SECONDARY_MIXTAPE" \ + -v secondary_demo="$HEADER_RG_FMT_SECONDARY_DEMO" \ + -v secondary_fieldrec="$HEADER_RG_FMT_SECONDARY_FIELDREC" \ + -v fmttitle="$HEADER_RG_FMT_TITLE" \ + -v fmtartist="$HEADER_RG_FMT_ARTIST" \ + -v fmtyear="$HEADER_RG_FMT_YEAR" \ + "$AWK_RELEASEGROUPS" | + column -t -s "$(printf '\t')" -R "$HEADER_RG_FMT_RIGHTALIGN" -l "$HEADER_RG_FMT_CNT" | + cut -d "$(printf '\t')" -f 1 +} + +# Themed awk script to generate list of releases +# +# @argument $1: MusicBrainz release-group ID (optional) +# @argument $2: Title of release group (optional) +# @argument $3: Artist credit name of release group +awk_releases() { + cat | + awk \ + -F "\t" \ + -v releasegroupid="${1:-}" \ + -v origtitle="${2:-}" \ + -v origartist="${3:-}" \ + -v flagfile="${LOCALDATA_RELEASES:-}" \ + -v format="$RV_FMT" \ + -v flag_local="$RV_FMT_FLAG_LOCAL" \ + -v flag_nolocal="$RV_FMT_FLAG_NO_LOCAL" \ + -v status_official="$RV_FMT_STATUS_OFFICIAL" \ + -v status_promo="$RV_FMT_STATUS_PROMO" \ + -v status_bootleg="$RV_FMT_STATUS_BOOTLEG" \ + -v status_pseudo="$RV_FMT_STATUS_PSEUDO" \ + -v status_withdrawn="$RV_FMT_STATUS_WITHDRAWN" \ + -v status_expunged="$RV_FMT_STATUS_EXPUNGED" \ + -v status_cancelled="$RV_FMT_STATUS_CANCELLED" \ + -v status_unknown="$RV_FMT_STATUS_UNKNOWN" \ + -v fmttracks="$RV_FMT_TRACKS" \ + -v fmtmedia="$RV_FMT_MEDIA" \ + -v fmtyear="$RV_FMT_YEAR" \ + -v fmtcountry="$RV_FMT_COUNTRY" \ + -v fmtlabel="$RV_FMT_LABEL" \ + -v fmttitle="$RV_FMT_TITLE" \ + -v fmtartist="$RV_FMT_ARTIST" \ + "$AWK_RELEASES" | + column -t -s "$(printf '\t')" -R "$RV_FMT_RIGHTALIGN" -l "$RV_FMT_CNT" | + sort -t "$(printf '\t')" -k 2,2 +} + +# Themed awk script to generate release header +awk_release_header() { + cat | + awk \ + -F "\t" \ + -v flagfile="${LOCALDATA_RELEASES:-}" \ + -v format="$HEADER_R_FMT" \ + -v flag_local="$HEADER_R_FMT_FLAG_LOCAL" \ + -v flag_nolocal="$HEADER_R_FMT_FLAG_NO_LOCAL" \ + -v status_official="$HEADER_R_FMT_STATUS_OFFICIAL" \ + -v status_promo="$HEADER_R_FMT_STATUS_PROMO" \ + -v status_bootleg="$HEADER_R_FMT_STATUS_BOOTLEG" \ + -v status_pseudo="$HEADER_R_FMT_STATUS_PSEUDO" \ + -v status_withdrawn="$HEADER_R_FMT_STATUS_WITHDRAWN" \ + -v status_expunged="$HEADER_R_FMT_STATUS_EXPUNGED" \ + -v status_cancelled="$HEADER_R_FMT_STATUS_CANCELLED" \ + -v status_unknown="$HEADER_R_FMT_STATUS_UNKNOWN" \ + -v fmttracks="$HEADER_R_FMT_TRACKS" \ + -v fmtmedia="$HEADER_R_FMT_MEDIA" \ + -v fmtyear="$HEADER_R_FMT_YEAR" \ + -v fmtcountry="$HEADER_R_FMT_COUNTRY" \ + -v fmtlabel="$HEADER_R_FMT_LABEL" \ + -v fmttitle="$HEADER_R_FMT_TITLE" \ + -v fmtartist="$HEADER_R_FMT_ARTIST" \ + "$AWK_RELEASES" | + column -t -s "$(printf '\t')" -R "$HEADER_R_FMT_RIGHTALIGN" -l "$HEADER_R_FMT_CNT" | + cut -d "$(printf '\t')" -f 1 +} + +# Themed awk script to generate list of tracks +# +# @argument $1: Path to file with MusicBrainz track IDs "tab" decoration file +# of locally playable audio tracks (optional) +awk_recordings() { + cat | + awk \ + -F "\t" \ + -v flagfile="${1:-}" \ + -v format="$REC_FMT" \ + -v flag_local="$REC_FMT_FLAG_LOCAL" \ + -v flag_nolocal="$REC_FMT_FLAG_NO_LOCAL" \ + -v fmtmedia="$REC_FMT_MEDIA" \ + -v fmtnr="$REC_FMT_NR" \ + -v fmttitle="$REC_FMT_TITLE" \ + -v fmtartist="$REC_FMT_ARTIST" \ + -v fmtduration="$REC_FMT_DURATION" \ + "$AWK_RECORDINGS" | + column -t -s "$(printf '\t')" -R "$REC_FMT_RIGHTALIGN" -l "$REC_FMT_CNT" +} + +# Themed awk script to generate list of tracks for playlist view +awk_playlist() { + cat | + awk \ + -F "\t" \ + -v format="$PLYLST_FMT" \ + -v playing_yes="$PLYLST_FMT_PLAYING_YES" \ + -v playing_no="$PLYLST_FMT_PLAYING_NO" \ + -v fmttitle="$PLYLST_FMT_TITLE" \ + -v fmtartist="$PLYLST_FMT_ARTIST" \ + -v fmtduration="$PLYLST_FMT_DURATION" \ + "$AWK_RECORDINGS" | + column -t -s "$(printf '\t')" -R "$PLYLST_FMT_RIGHTALIGN" -l "$PLYLST_FMT_CNT" +} diff --git a/src/sh/config.sh b/src/sh/config.sh index 597944c..f8e1e05 100644 --- a/src/sh/config.sh +++ b/src/sh/config.sh @@ -11,6 +11,7 @@ # the respective key bindings. # - `src/sh/keys.sh`: Configuration of key bindings to certain actions # - `src/sh/theme.sh`: Configuration of theme +# - `src/sh/sort.sh`: List sorting CONFIGFILE_DEFAULT="$HOME/.config/$APP_NAME/config" CONFIGFILE="${CONFIGFILE:-"$CONFIGFILE_DEFAULT"}" [ "$CONFIGFILE" != "$CONFIGFILE_DEFAULT" ] && [ ! -f "$CONFIGFILE" ] && err "The configuration file manually specified with the environment variable CONFIGFILE=($CONFIGFILE) does not exist." && exit 1 diff --git a/src/sh/filter.sh b/src/sh/filter.sh index 068e643..2352d43 100644 --- a/src/sh/filter.sh +++ b/src/sh/filter.sh @@ -9,12 +9,12 @@ QUERY_LOCAL="${QUERY_LOCAL:-"$(printf "'%s'" "$FORMAT_LOCAL" | __clean_filter)"} # The following variables store preset strings derived from the theme (see # `src/sh/theme.sh`), and used in the assignment of the default filters. -q_has_seconary="$(printf "$FORMAT_TYPE_HAS_SECONDARY" "" | __clean_filter)" -q_album="$(printf "%s" "$FORMAT_TYPE_ALBUM" | __clean_filter)" -q_ep=$(printf "%s" "$FORMAT_TYPE_EP" | sed "s/${ESC}\[[0-9;]*[mK]//g" | sed "s/ /\\\ /g") -q_single=$(printf "%s" "$FORMAT_TYPE_SINGLE" | sed "s/${ESC}\[[0-9;]*[mK]//g" | sed "s/ /\\\ /g") -if printf "$RV_FORMAT" | grep -q "<<status>>"; then - q_official=$(printf "'%s'" "$FORMAT_STATUS_OFFICIAL" | sed "s/${ESC}\[[0-9;]*[mK]//g" | sed "s/ /\\\ /g") +q_has_seconary="$(printf "%s" "$RGV_FMT_HASSECONDARY_YES" | __clean_filter)" +q_album="$(printf "%s" "$RGV_FMT_TYPE_ALBUM" | __clean_filter)" +q_ep="$(printf "%s" "$RGV_FMT_TYPE_EP" | __clean_filter)" +q_single="$(printf "%s" "$RGV_FMT_TYPE_SINGLE" | __clean_filter)" +if printf "$RV_FMT" | grep -q "<<status>>"; then + q_official="$(printf "'%s'" "$RV_FMT_STATUS_OFFICIAL" | __clean_filter)" fi export QUERY_LOCAL diff --git a/src/sh/fzf.sh b/src/sh/fzf.sh index 3f5a01a..e9c4694 100644 --- a/src/sh/fzf.sh +++ b/src/sh/fzf.sh @@ -11,39 +11,43 @@ fzf_command_set_header() { "$VIEW_LIST_ARTISTS") header="Search locally available artist" ;; "$VIEW_LIST_ALBUMS") header="Search locally available album" ;; "$VIEW_ARTIST") - name="$(mb_artist "$mbid" | $JQ '.name')" - header=$(printf "$HEADER_ARTIST" "$name") + header="$( + mb_artist "$mbid" | + $JQ '[.id, type, .name, .disambiguation] | join("\t")' | + awk_artist_header + )" ;; "$VIEW_RELEASEGROUP") - title="$(mb_releasegroup "$mbid" | - $JQ '.title')" - artist="$(mb_releasegroup "$mbid" | - $JQ '."artist-credit" | map(([.name, .joinphrase]|join(""))) | join("")')" - header=$(printf "$HEADER_ARTIST_RELEASEGROUP" "$artist" "$title") + header="$( + mb_releasegroup "$mbid" | + $JQ '[ + .id, + ."primary-type", + (."secondary-types" // []|join(";")), + ."first-release-date", + .title, + (."artist-credit" | map(([.name, .joinphrase]|join(""))) | join("")) + ] | join("\t")' | + awk_releasegroup_header + )" ;; "$VIEW_RELEASE") - title="$(mb_release "$mbid" | - $JQ '.title')" - artist="$(mb_release "$mbid" | - $JQ '."artist-credit" | map(([.name, .joinphrase]|join(""))) | join("")')" - releaseinfo="$(mb_release "$mbid" | - $JQ '[ - .date[:4], - (."label-info" | map(.label.name) | unique | join(", ")), - (.media | map(."track-count") | add), - (.media | map(.format) | unique | join(", ")), - .country - ] | join("\t")' | - awk -F "\t" -v format="$HEADER_RELEASE_FORMAT" '{ - gsub("&", "\\\\&") - sub("<<year>>", $1, format) - sub("<<label>>", $2, format) - sub("<<tracks>>", $3, format) - sub("<<media>>", $4, format) - sub("<<country>>", $5, format) - print format - }')" - header=$(printf "$HEADER_RELEASE" "$artist" "$title" "$releaseinfo") + header="$( + mb_release "$mbid" | + $JQ '[ + .id, + .status, + .date, + ."cover-art-archive".count, + (."label-info" | map(.label.name) | unique | join(", ")), + (.media | map(."track-count") | add), + (.media | map(.format) | unique | join(", ")), + .country, + .title, + (."artist-credit" | map(([.name, .joinphrase]|join(""))) | join("")) + ] | join("\t")' | + awk_release_header + )" ;; esac printf "+change-header(%s)" "${header:-"???"}" diff --git a/src/sh/lists.sh b/src/sh/lists.sh index aa0e2fa..f3fc0f1 100644 --- a/src/sh/lists.sh +++ b/src/sh/lists.sh @@ -14,39 +14,7 @@ list_releasegroups() { .title, (."artist-credit" | map(([.name, .joinphrase]|join(""))) | join("")) ] | join("\t")' | - awk \ - -F "\t" \ - -v artist="$name" \ - -v artistid="$1" \ - -v file_local_releasegroups="${LOCALDATA_RELEASEGROUPS:-}" \ - -v format_release="$RGV_RELEASE" \ - -v format_release_w_artist="$RGV_RELEASE_W_ARTIST" \ - -v format_year="$RGV_YEAR" \ - -v format_album="$FORMAT_TYPE_ALBUM" \ - -v format_single="$FORMAT_TYPE_SINGLE" \ - -v format_ep="$FORMAT_TYPE_EP" \ - -v format_broadcast="$FORMAT_TYPE_BROADCAST" \ - -v format_other="$FORMAT_TYPE_OTHER" \ - -v format_has_secondary="$FORMAT_TYPE_HAS_SECONDARY" \ - -v format_secondary="$FORMAT_TYPE_SECONDARY" \ - -v format_compilation="$FORMAT_TYPE_SECONDARY_COMPILATION" \ - -v format_soundtrack="$FORMAT_TYPE_SECONDARY_SOUNDTRACK" \ - -v format_spokenword="$FORMAT_TYPE_SECONDARY_SPOKENWORD" \ - -v format_interview="$FORMAT_TYPE_SECONDARY_INTERVIEW" \ - -v format_audiobook="$FORMAT_TYPE_SECONDARY_AUDIOBOOK" \ - -v format_audiodrama="$FORMAT_TYPE_SECONDARY_AUDIODRAMA" \ - -v format_live="$FORMAT_TYPE_SECONDARY_LIVE" \ - -v format_remix="$FORMAT_TYPE_SECONDARY_REMIX" \ - -v format_djmix="$FORMAT_TYPE_SECONDARY_DJMIX" \ - -v format_mixtape="$FORMAT_TYPE_SECONDARY_MIXTAPE" \ - -v format_demo="$FORMAT_TYPE_SECONDARY_DEMO" \ - -v format_fieldrec="$FORMAT_TYPE_SECONDARY_FIELDREC" \ - -v format_local="$FORMAT_LOCAL" \ - "$AWK_RELEASEGROUPS" | - sort -n -r | - cut -d "$(printf '\t')" -f 2- | - column -t -s "$(printf '\t')" | - sed 's| \+\([0-9a-f-]\+\) \+\([0-9a-f-]\+\)$|\t\1\t\2|' + awk_releasegroups "$SORT_RG_DEFAULT" "$1" "$name" } # List releases in given relese group @@ -70,95 +38,18 @@ list_releases() { .title, (."artist-credit" | map(([.name, .joinphrase]|join(""))) | join("")) ] | join("\t")' | - awk \ - -F "\t" \ - -v file_local_releases="${LOCALDATA_RELEASES:-}" \ - -v release_official="$FORMAT_STATUS_OFFICIAL" \ - -v release_promotion="$FORMAT_STATUS_PROMO" \ - -v release_bootleg="$FORMAT_STATUS_BOOTLEG" \ - -v release_pseudo="$FORMAT_STATUS_PSEUDO" \ - -v release_withdrawn="$FORMAT_STATUS_WITHDRAWN" \ - -v release_expunged="$FORMAT_STATUS_EXPUNGED" \ - -v release_cancelled="$FORMAT_STATUS_CANCELLED" \ - -v format_release="$RV_FORMAT" \ - -v format_release_title_artist="$RV_TITLE_ARTIST" \ - -v format_release_title="$RV_TITLE" \ - -v format_release_artist="$RV_ARTIST" \ - -v rg_artist="$artist" \ - -v rg_title="$title" \ - -v rgid="$1" \ - -v format_local="$FORMAT_LOCAL" \ - "$AWK_RELEASES" | - sort -n -r | - cut -d "$(printf '\t')" -f 2- | - column -t -s "$(printf '\t')" | - sed 's| \+\([0-9a-f-]\+\) \+\([0-9a-f-]\+\):\(.*$\)$|\t\1\t\2\t\3|' + awk_releases "$1" "$title" "$artist" } # List recordings of given release # # argument $1: MusicBrainz release ID list_recordings() { - info "list recordings.." deco="$(grep "$1" "$LOCALDATA_RELEASES" | cut -d "$(printf '\t')" -f 2)" - info "deco=$deco" if [ "$deco" ]; then rectmp=$(mktemp) $JQ '.tracks | keys | join("\n")' "$deco" >"$rectmp" - info "rectmp=$rectmp" - info "$(cat "$rectmp")" fi - info "going to awk..." - info "$( - mb_release "$1" | - $JQ \ - --arg rid "$1" \ - --arg deco "$deco" \ - '.media | - length as $l | - .[] | - .position as $pos | - .tracks[] | [ - $rid, - .id, - $l, - $pos, - .number, - .length, - .recording.title, - (.recording."artist-credit" | map([.name, .joinphrase] | join("")) | join("")), - $deco - ] | - join("\t")' - )" - info "$( - mb_release "$1" | - $JQ \ - --arg rid "$1" \ - --arg deco "$deco" \ - '.media | - length as $l | - .[] | - .position as $pos | - .tracks[] | [ - $rid, - .id, - $l, - $pos, - .number, - .length, - .recording.title, - (.recording."artist-credit" | map([.name, .joinphrase] | join("")) | join("")), - $deco - ] | - join("\t")' | - awk \ - -F "\t" \ - -v file_local_recordings="${rectmp:-}" \ - -v format="$REC_FORMAT" \ - -v format_local="$FORMAT_LOCAL" \ - "$AWK_RECORDINGS" - )" mb_release "$1" | $JQ \ --arg rid "$1" \ @@ -179,16 +70,7 @@ list_recordings() { $deco ] | join("\t")' | - awk \ - -F "\t" \ - -v file_local_recordings="${rectmp:-}" \ - -v format="$REC_FORMAT" \ - -v format_local="$FORMAT_LOCAL" \ - "$AWK_RECORDINGS" | - sort -k1,1n -k2,2g | - cut -d "$(printf '\t')" -f 2- | - column -t -s "$(printf '\t')" -R 3,4,7 | - sed 's| \+\([0-9a-f-]\+\) \+\([0-9a-f-]\+\):\(.*$\)$|\t\1\t\2\t\3|' + awk_recordings "${rectmp:-}" if [ "${rectmp:-}" ] && [ -f "$rectmp" ]; then rm -f "$rectmp" fi @@ -210,15 +92,7 @@ list_local_releasegroups() { list_artists_from_json() { cat | $JQ 'map([.artist.id, .artist.type, .name] | join("\t")) | join("\n")' | - awk \ - -F "\t" \ - -v file_local_artists="${LOCALDATA_ARTISTS:-}" \ - -v format_person="$AV_PERSON" \ - -v format_group="$AV_GROUP" \ - -v format_disambiguation="$AV_DISAMBIGUATION" \ - -v format_local="$FORMAT_LOCAL" \ - "$AWK_ARTISTS" | - column -t -s "$(printf '\t')" -l 2 + awk_artists "$SORT_NO" } # Print playlist currently loaded @@ -227,27 +101,7 @@ list_playlist() { [ "$count" -eq 0 ] && return 0 mpvquery="" for i in $(seq 0 $((count - 1))); do - mpvquery="$mpvquery\${playlist/$i/current}\t\${playlist/$i/title}\n" + mpvquery="$mpvquery\${playlist/$i/title}\t\${playlist/$i/current}\n" done - mpvtmp=$(mktemp) - # Get playlist information from mpv - __mpv_get "$mpvquery" | grep '.' >"$mpvtmp" - # Get MusicBrainz Track ID of current recording - current_id=$(grep "^yes" "$mpvtmp" | cut -d "$(printf '\t')" -f 3) - # Get file to be used in file_local_recordings - rectmp=$(mktemp) - cut -d "$(printf '\t')" -f 3 "$mpvtmp" >"$rectmp" - # Get list - cut -d "$(printf '\t')" -f 2- "$mpvtmp" | - awk \ - -F "\t" \ - -v file_local_recordings="${rectmp:-}" \ - -v format="$REC_FORMAT_NO_NUMBER" \ - -v format_current="$FORMAT_CURRENT" \ - -v current_id="$current_id" \ - "$AWK_RECORDINGS" | - cut -d "$(printf '\t')" -f 2- | - column -t -s "$(printf '\t')" -R 5 | - sed 's| \+\([0-9a-f-]\+\) \+\([0-9a-f-]\+\):\(.*$\)$|\t\1\t\2\t\3|' - rm -f "$rectmp" "$mpvtmp" + __mpv_get "$mpvquery" | grep '.' | awk_playlist } diff --git a/src/sh/local.sh b/src/sh/local.sh index b9ee4a6..23530e3 100644 --- a/src/sh/local.sh +++ b/src/sh/local.sh @@ -225,6 +225,7 @@ __precompute_lists() { .id, .type, .name, + ."sort-name", .disambiguation, .["life-span"].begin, .["life-span"].end @@ -246,47 +247,8 @@ __precompute_lists() { # The resulting views are stored in the files `LOCALDATA_ARTISTS_VIEW` and # `LOCALDATA_RELEASEGROUPS_VIEW`. precompute_views() { - awk \ - -F "\t" \ - -v file_local_artists="${LOCALDATA_ARTISTS:-}" \ - -v format_person="$AV_PERSON" \ - -v format_group="$AV_GROUP" \ - -v format_disambiguation="$AV_DISAMBIGUATION" \ - -v format_local="$FORMAT_LOCAL" \ - "$AWK_ARTISTS" "$LOCALDATA_ARTISTS_LIST" | - sort | - column -t -s "$(printf '\t')" -l 2 >"$LOCALDATA_ARTISTS_VIEW" - #column -t -s "$(printf '\t')" | - #sed 's| \+\([0-9a-f-]\+\) \+\([0-9a-f-]\+\)$|\t\1\t\2|' >"$LOCALDATA_ARTISTS_VIEW" - awk \ - -F "\t" \ - -v file_local_releasegroups="${LOCALDATA_RELEASEGROUPS:-}" \ - -v format_release="$RGV_RELEASE" \ - -v format_release_w_artist="$RGV_RELEASE_W_ARTIST" \ - -v format_year="$RGV_YEAR" \ - -v format_album="$FORMAT_TYPE_ALBUM" \ - -v format_single="$FORMAT_TYPE_SINGLE" \ - -v format_ep="$FORMAT_TYPE_EP" \ - -v format_broadcast="$FORMAT_TYPE_BROADCAST" \ - -v format_other="$FORMAT_TYPE_OTHER" \ - -v format_has_secondary="$FORMAT_TYPE_HAS_SECONDARY" \ - -v format_secondary="$FORMAT_TYPE_SECONDARY" \ - -v format_compilation="$FORMAT_TYPE_SECONDARY_COMPILATION" \ - -v format_soundtrack="$FORMAT_TYPE_SECONDARY_SOUNDTRACK" \ - -v format_spokenword="$FORMAT_TYPE_SECONDARY_SPOKENWORD" \ - -v format_interview="$FORMAT_TYPE_SECONDARY_INTERVIEW" \ - -v format_audiobook="$FORMAT_TYPE_SECONDARY_AUDIOBOOK" \ - -v format_audiodrama="$FORMAT_TYPE_SECONDARY_AUDIODRAMA" \ - -v format_live="$FORMAT_TYPE_SECONDARY_LIVE" \ - -v format_remix="$FORMAT_TYPE_SECONDARY_REMIX" \ - -v format_djmix="$FORMAT_TYPE_SECONDARY_DJMIX" \ - -v format_mixtape="$FORMAT_TYPE_SECONDARY_MIXTAPE" \ - -v format_demo="$FORMAT_TYPE_SECONDARY_DEMO" \ - -v format_fieldrec="$FORMAT_TYPE_SECONDARY_FIELDREC" \ - -v format_local="$FORMAT_LOCAL" \ - "$AWK_RELEASEGROUPS" "$LOCALDATA_RELEASEGROUPS_LIST" | sort -n -r | - cut -d "$(printf '\t')" -f 2- | - column -t -s "$(printf '\t')" -l 5 >"$LOCALDATA_RELEASEGROUPS_VIEW" + awk_artists "$SORT_ARTIST_DEFAULT" <"$LOCALDATA_ARTISTS_LIST" >"$LOCALDATA_ARTISTS_VIEW" + awk_releasegroups "$SORT_RG_DEFAULT" <"$LOCALDATA_RELEASEGROUPS_LIST" >"$LOCALDATA_RELEASEGROUPS_VIEW" #column -t -s "$(printf '\t')" | #sed 's| \+\([0-9a-f-]\+\) \+\([0-9a-f-]\+\)$|\t\1\t\2|' >"$LOCALDATA_RELEASEGROUPS_VIEW" } diff --git a/src/sh/mb.sh b/src/sh/mb.sh index 929b582..bf9becc 100644 --- a/src/sh/mb.sh +++ b/src/sh/mb.sh @@ -180,8 +180,7 @@ mb_results_async() { sleep 1 done # Show results - column -t -s "$(printf '\t')" "$RESULTS" | - sed 's| \+\([0-9a-f-]\+\) \+\([0-9a-f-]\+\)$|\t\1\t\2|' + cat "$RESULTS" || true } # Initiate search on MusicBrainz @@ -200,30 +199,29 @@ mb_search_async() { rm -f "$PIDFILE" kill -9 "$pid" >/dev/null 2>&1 || true fi - # Stop, if no search string is given - [ "$FZF_QUERY" ] || exit 0 + # Clear search and stop if no search string is given + if [ ! "$FZF_QUERY" ]; then + rm -f "$RESULTS" + touch "$RESULTS" + exit 0 + fi # Store PID of current process echo "$$" >"$PIDFILE" touch "$LOCKFILE" sleep 1 if [ "$view" = "$VIEW_SEARCH_ARTIST" ]; then + info "search artist. results: $RESULTS" api_mb_search_artist "$FZF_QUERY" | $JQ '.artists[] | [ .id, .type, .name, + ."sort-name", .disambiguation, .["life-span"].begin, .["life-span"].end ] | join("\t")' | - awk \ - -F "\t" \ - -v file_local_artists="${LOCALDATA_ARTISTS:-}" \ - -v format_person="$AV_PERSON" \ - -v format_group="$AV_GROUP" \ - -v format_disambiguation="$AV_DISAMBIGUATION" \ - -v format_local="$FORMAT_LOCAL" \ - "$AWK_ARTISTS" >"$RESULTS" || + awk_artists "$SORT_NO" >"$RESULTS" || true else api_mb_search_releasegroup "$FZF_QUERY" | @@ -235,34 +233,7 @@ mb_search_async() { .title, (."artist-credit" | map(([.name, .joinphrase]|join(""))) | join("")) ] | join("\t")' | - awk \ - -F "\t" \ - -v file_local_releasegroups="${LOCALDATA_RELEASEGROUPS:-}" \ - -v format_release="$RGV_RELEASE" \ - -v format_release_w_artist="$RGV_RELEASE_W_ARTIST" \ - -v format_year="$RGV_YEAR" \ - -v format_album="$FORMAT_TYPE_ALBUM" \ - -v format_single="$FORMAT_TYPE_SINGLE" \ - -v format_ep="$FORMAT_TYPE_EP" \ - -v format_broadcast="$FORMAT_TYPE_BROADCAST" \ - -v format_other="$FORMAT_TYPE_OTHER" \ - -v format_has_secondary="$FORMAT_TYPE_HAS_SECONDARY" \ - -v format_secondary="$FORMAT_TYPE_SECONDARY" \ - -v format_compilation="$FORMAT_TYPE_SECONDARY_COMPILATION" \ - -v format_soundtrack="$FORMAT_TYPE_SECONDARY_SOUNDTRACK" \ - -v format_spokenword="$FORMAT_TYPE_SECONDARY_SPOKENWORD" \ - -v format_interview="$FORMAT_TYPE_SECONDARY_INTERVIEW" \ - -v format_audiobook="$FORMAT_TYPE_SECONDARY_AUDIOBOOK" \ - -v format_audiodrama="$FORMAT_TYPE_SECONDARY_AUDIODRAMA" \ - -v format_live="$FORMAT_TYPE_SECONDARY_LIVE" \ - -v format_remix="$FORMAT_TYPE_SECONDARY_REMIX" \ - -v format_djmix="$FORMAT_TYPE_SECONDARY_DJMIX" \ - -v format_mixtape="$FORMAT_TYPE_SECONDARY_MIXTAPE" \ - -v format_demo="$FORMAT_TYPE_SECONDARY_DEMO" \ - -v format_fieldrec="$FORMAT_TYPE_SECONDARY_FIELDREC" \ - -v format_local="$FORMAT_LOCAL" \ - "$AWK_RELEASEGROUPS" | - cut -d "$(printf '\t')" -f 2- >"$RESULTS" || + awk_releasegroups "$SORT_NO" >"$RESULTS" || true fi # Process ends now: Display and quit diff --git a/src/sh/mpv.sh b/src/sh/mpv.sh index 20d51c0..f97d7b4 100644 --- a/src/sh/mpv.sh +++ b/src/sh/mpv.sh @@ -50,7 +50,7 @@ mpv_playlist_position() { # Moves the track at the first index to the position of the track of the second # index. Also here, indices are 0 based. mpv_playlist_move() { - __mpv_command_with_args2 "playlist-move" "$1" "$2" >>/tmp/foo + __mpv_command_with_args2 "playlist-move" "$1" "$2" } # Remove all tracks from the playlist diff --git a/src/sh/playback.sh b/src/sh/playback.sh index 0fc50e6..bc1f9db 100644 --- a/src/sh/playback.sh +++ b/src/sh/playback.sh @@ -99,6 +99,7 @@ __generate_playlist() { # pressed is stored in the environment variable FZF_KEY and is resolved to # the playback command through the method `__playback_cmd_from_key`. playback() { + info "call to playback: $*" view=${1:-} mbid_current="${2:-}" mbid="${3:-}" @@ -107,6 +108,7 @@ playback() { case "$pbcmd" in "$PLAYBACK_CMD_PLAY") [ "$path" ] || exit 0 + info "play pressed" case "$view" in "$VIEW_ARTIST" | "$VIEW_SEARCH_ARTIST" | "$VIEW_SEARCH_ALBUM" | "$VIEW_LIST_ARTISTS" | "$VIEW_LIST_ALBUMS") info "not implemented" ;; "$VIEW_RELEASEGROUP") __generate_playlist "$mbid" "$path" | mpv_play_list >/dev/null ;; diff --git a/src/sh/sort.sh b/src/sh/sort.sh new file mode 100644 index 0000000..e0dd43b --- /dev/null +++ b/src/sh/sort.sh @@ -0,0 +1,44 @@ +# Sort methods for generated lists + +if [ ! "${SORT_LOADED:-}" ]; then + # Sort specifications + # + # - No sort + # - Alphabetic sort + # - Numeric sort + SORT_NO="no-sort" + SORT_ALPHA="sort-alpha" + SORT_NUMERIC="sort-numeric" + + # Artists may be sorted according to the name or the sort-name taken from + # MusicBrainz + SORT_ARTIST="sort-artist" + SORT_ARTIST_SORTNAME="sort-artist-sortname" + + # Release-groups may be sorted according to the release year or the title + SORT_RG_TITLE="sort-rg-title" + SORT_RG_YEAR="sort-rg-year" + export SORT_NO SORT_ALPHA SORT_NUMERIC SORT_ARTIST SORT_ARTIST_SORTNAME \ + SORT_RG_TITLE SORT_RG_YEAR + + # Configurable default sort + SORT_ARTIST_DEFAULT="${SORT_ARTIST_DEFAULT:-"$SORT_ARTIST"}" + SORT_RG_DEFAULT="${SORT_RG_DEFAULT:-"$SORT_RG_YEAR"}" + export SORT_ARTIST_DEFAULT SORT_RG_DEFAULT + + export SORT_LOADED=1 +fi + +# Sorting switches +# +# @argument $1: Sort specification (may be one of SORT_NO, SORT_ALPHA, +# SORT_NUMERIC) +# +# This method sorts the stream read from stdin. +sort_list() { + case "${1:-}" in + "$SORT_ALPHA") cat | sort -t "$(printf '\t')" -k 2,2 ;; + "$SORT_NUMERIC") cat | sort -t "$(printf '\t')" -k 2,2 -n ;; + *) cat ;; + esac +} diff --git a/src/sh/theme.sh b/src/sh/theme.sh index 30ed42a..40ed614 100644 --- a/src/sh/theme.sh +++ b/src/sh/theme.sh @@ -4,165 +4,327 @@ # # This theme requires fonts that support utf-8, colors, and emojis. -# Colors (internal only) -ESC=$(printf '\033') -BOLD="${ESC}[1m" -FAINT="${ESC}[2m" -UNDERLINE="${ESC}[4m" -CARTIST="${ESC}[38;5;209m" -CTITLE="${ESC}[38;5;229m" -CRELINFO="${ESC}[38;5;179m" -CYEAR="${ESC}[38;5;179m" -CDISAMB="$FAINT${ESC}[38;5;172m" -CNOTE="${ESC}[38;5;242m" -CXXX="${ESC}[38;5;109m" -CDESC="${ESC}[38;5;254m" -CLIFE="${ESC}[38;5;251m" -CKB="${ESC}[38;5;224m" -OFF="${ESC}[m" +if [ ! "${THEME_LOADED:-}" ]; then + # Colors (internal only) + ESC=$(printf '\033') + BOLD="${ESC}[1m" + FAINT="${ESC}[2m" + UNDERLINE="${ESC}[4m" + CARTIST="${ESC}[38;5;209m" + CTITLE="${ESC}[38;5;229m" + CRELINFO="${ESC}[38;5;179m" + CYEAR="${ESC}[38;5;179m" + CDISAMB="$FAINT${ESC}[38;5;172m" + CNOTE="${ESC}[38;5;242m" + CXXX="${ESC}[38;5;109m" + CDESC="${ESC}[38;5;254m" + CLIFE="${ESC}[38;5;251m" + CKB="${ESC}[38;5;224m" + OFF="${ESC}[m" -# Pointers -# ======== -# Sign that indicates the existence of audio files -FORMAT_LOCAL="${FORMAT_LOCAL:-"๐Ÿ”†"}" -# Pointer to the track currently playing (playlist) -FORMAT_CURRENT="${FORMAT_CURRENT:-"๐Ÿ‘‰"}" -export FORMAT_LOCAL FORMAT_CURRENT + # Pointers + # ======== + # Sign that indicates the existence of audio files + FORMAT_LOCAL="${FORMAT_LOCAL:-"๐Ÿ”†"}" + export FORMAT_LOCAL -# Input prompt -# ============= -# Search prompt -SEARCH_PROMPT=${SEARCH_PROMPT:-"๐Ÿ”Ž โŒช"} -export SEARCH_PROMPT + # Input prompt + # ============= + # General search prompt (for now only used when choosing one-of-many artist) + SEARCH_PROMPT=${SEARCH_PROMPT:-"๐Ÿ”Ž โŒช"} + export SEARCH_PROMPT -# Headers -# ======= -# Header that displays artist's name -HEADER_ARTIST="${HEADER_ARTIST:-"๐ŸŽค ${CARTIST}%s$OFF โŒช"}" -# Header that displays the release-group name after artist's -HEADER_ARTIST_RELEASEGROUP="${HEADER_ARTIST_RELEASEGROUP:-"๐ŸŽค ${CARTIST}%s$OFF ใ€‹${CTITLE}%s$OFF โŒช"}" -# Header that in addition to `HEADER_ARTIST_RELEASEGROUP` also shows some -# release information -HEADER_RELEASE="${HEADER_RELEASE:-"๐ŸŽค ${CARTIST}%s$OFF ใ€‹${CTITLE}%s$OFF โŒช%s"}" -# The release information is formatted as follows (placeholders implicit): -HEADER_RELEASE_FORMAT="${HEADER_RELEASE_FORMAT:-"${CRELINFO}<<tracks>> tx <<media>> $OFF|$CRELINFO <<label>> <<country>> <<year>>$OFF"}" -export HEADER_ARTIST HEADER_ARTIST_RELEASEGROUP HEADER_RELEASE HEADER_RELEASE_FORMAT + # General workings of format strings + # + # A format string (_FMT) contains placeholders, e.g., <<name>>. These + # placeholders are filled with the relevant information. A placeholder may + # occur zero times, once, or more than once. There are two types of + # placeholders: strings and items. A placeholder of type string comes with a + # variable containing a `printf` expression (_FMT_placeholder). This `printf` + # expression may be used to additionally modify the string passed. If the + # string passed is empty, then each corresponding placeholder is replaced + # with the empty string, i.e., the `printf` expression is bypassed. A + # placeholder of the alternative type (item) comes with a series of variables + # that encode constants to be used (_FMT_placeholder_XYZ). + # + # The items in the format string may be separated with "\t". This will induce + # a proper representation (using `column`). By default, all fields but the + # first are left aligned, and the first field is right aligned. This can be + # changed by setting the appropriate FMT_RIGHTALIGN variable. If that + # variable is empty, then the first field is right aligned. This means that + # at least one field must be right aligned. + # + # Artist view + # =========== + # <<flag>> item Indication for locally available audio files + # <<type>> item Indicator for single-person artist or group + # <<name>> string Artist name + # <<disambiguation>> string Disambiguation string + # + AV_FMT="${AV_FMT:-"<<flag>>\t<<type>> <<name>> <<disambiguation>>"}" + AV_FMT_CNT=$(($(printf "$AV_FMT" | tr -cd '\t' | wc -c) + 1)) + AV_FMT_RIGHTALIGN="${AV_FMT_RIGHTALIGN:-"1"}" + AV_FMT_FLAG_LOCAL="${AV_FMT_FLAG_LOCAL:-"$FORMAT_LOCAL"}" + AV_FMT_FLAG_NO_LOCAL="${AV_FMT_FLAG_NO_LOCAL:-""}" + AV_FMT_TYPE_PERSON="${AV_FMT_TYPE_PERSON:-๐Ÿง‘โ€๐ŸŽค}" + AV_FMT_TYPE_GROUP="${AV_FMT_TYPE_GROUP:-๐Ÿง‘โ€๐Ÿคโ€๐Ÿง‘}" + AV_FMT_NAME="${AV_FMT_NAME:-"${CARTIST}%s$OFF"}" + AV_FMT_DISAMBIGUATION="${AV_FMT_DISAMBIGUATION:-"${CDISAMB}(%s)$OFF"}" + export AV_FMT AV_FMT_CNT AV_FMT_RIGHTALIGN AV_FMT_FLAG_LOCAL \ + AV_FMT_FLAG_NO_LOCAL AV_FMT_TYPE_PERSON AV_FMT_TYPE_GROUP AV_FMT_NAME \ + AV_FMT_DISAMBIGUATION -# Artist view -# =========== -# Artist string for persons -AV_PERSON="${AV_PERSON:-"๐Ÿง‘โ€๐ŸŽค $CARTIST<<name>>$OFF"}" -# Artist string for groups -AV_GROUP="${AV_GROUP:-"๐Ÿง‘โ€๐Ÿคโ€๐Ÿง‘ $CARTIST<<name>>$OFF"}" -# Artist disambiguation string -AV_DISAMBIGUATION="${AV_DISAMBIGUATION:-"$CDISAMB(<<disambiguation>>)$OFF"}" -export AV_PERSON AV_GROUP AV_DISAMBIGUATION + # Release-group view + # ================== + # <<flag>> item Indication for locally available audio files + # <<type>> item Indicates the type + # <<hassecondary>> item Indicates if there is some secondary type or none + # <<secondary>> string List of secondary types + # <<title>> string Title of album + # <<artist>> string Artist of album + # <<year>> string Year of initial release + # TODO: The above <<secondary>> is of a joint item-string type; unify or document. + RGV_FMT="${RGV_FMT:-"<<flag>>\t<<type>>\t<<hassecondary>>\t<<title>><<artist>> <<year>> <<secondary>>"}" + RGV_FMT_CNT=$(($(printf "$RGV_FMT" | tr -cd '\t' | wc -c) + 1)) + RGV_FMT_RIGHTALIGN="${RGV_FMT_RIGHTALIGN:-"1"}" + RGV_FMT_FLAG_LOCAL="${RGV_FMT_FLAG_LOCAL:-"$FORMAT_LOCAL"}" + RGV_FMT_FLAG_NO_LOCAL="${RGV_FMT_FLAG_NO_LOCAL:-""}" + RGV_FMT_TYPE_SINGLE="${RGV_FMT_TYPE_SINGLE:-"SI ๐ŸŽถ"}" + RGV_FMT_TYPE_ALBUM="${RGV_FMT_TYPE_ALBUM:-"LP ๐Ÿ’ฝ"}" + RGV_FMT_TYPE_EP="${RGV_FMT_TYPE_EP:-"EP ๐Ÿ“€"}" + RGV_FMT_TYPE_BROADCAST="${RGV_FMT_TYPE_BROADCAST:-"BR ๐Ÿ“ป"}" + RGV_FMT_TYPE_OTHER="${RGV_FMT_TYPE_OTHER:-"OT โ”"}" + RGV_FMT_TYPE_UNKNOWN="${RGV_FMT_TYPE_UNKNOWN:-""}" + RGV_FMT_HASSECONDARY_YES="${RGV_FMT_HASSECONDARY_YES:-"โ˜ผ"}" + RGV_FMT_HASSECONDARY_NO="${RGV_FMT_HASSECONDARY_NO:-""}" + RGV_FMT_SECONDARY="${RGV_FMT_SECONDARY:-"${CNOTE}[โ˜ผ: %s]$OFF"}" + RGV_FMT_SECONDARY_SOUNDTRACK="${RGV_FMT_SECONDARY_SOUNDTRACK:-"๐ŸŽฌ soundtrack"}" + RGV_FMT_SECONDARY_SPOKENWORD="${RGV_FMT_SECONDARY_SPOKENWORD:-"๐Ÿ“– spokenword"}" + RGV_FMT_SECONDARY_INTERVIEW="${RGV_FMT_SECONDARY_INTERVIEW:-"๐Ÿ’ฌ interview"}" + RGV_FMT_SECONDARY_AUDIOBOOK="${RGV_FMT_SECONDARY_AUDIOBOOK:-"๐ŸŽง audiobook"}" + RGV_FMT_SECONDARY_AUDIODRAMA="${RGV_FMT_SECONDARY_AUDIODRAMA:-"๐ŸŽญ audio drama"}" + RGV_FMT_SECONDARY_LIVE="${RGV_FMT_SECONDARY_LIVE:-"๐ŸŽค live"}" + RGV_FMT_SECONDARY_REMIX="${RGV_FMT_SECONDARY_REMIX:-"๐Ÿ” remix"}" + RGV_FMT_SECONDARY_DJMIX="${RGV_FMT_SECONDARY_DJMIX:-"๐Ÿชฉ DJ-mix"}" + RGV_FMT_SECONDARY_MIXTAPE="${RGV_FMT_SECONDARY_MIXTAPE:-"๐Ÿ“ผ mixtape"}" + RGV_FMT_SECONDARY_DEMO="${RGV_FMT_SECONDARY_DEMO:-"๐Ÿงช demo"}" + RGV_FMT_SECONDARY_FIELDREC="${RGV_FMT_SECONDARY_FIELDREC:-"๐ŸŒฟ field recording"}" + RGV_FMT_TITLE="${RGV_FMT_TITLE:-"${CTITLE}%s$OFF"}" + RGV_FMT_ARTIST="${RGV_FMT_ARTIST:-" โ€” ${CARTIST}%s$OFF"}" + RGV_FMT_YEAR="${RGV_FMT_YEAR:-"${CYEAR}(%s)$OFF"}" + export RGV_FMT RGV_FMT_CNT RGV_FMT_RIGHTALIGN RGV_FMT_FLAG_LOCAL \ + RGV_FMT_FLAG_NO_LOCAL RGV_FMT_TYPE_SINGLE RGV_FMT_TYPE_ALBUM \ + RGV_FMT_TYPE_EP RGV_FMT_TYPE_BROADCAST RGV_FMT_TYPE_OTHER \ + RGV_FMT_TYPE_UNKNOWN RGV_FMT_HASSECONDARY_YES RGV_FMT_HASSECONDARY_NO \ + RGV_FMT_SECONDARY RGV_FMT_SECONDARY_SOUNDTRACK \ + RGV_FMT_SECONDARY_SPOKENWORD RGV_FMT_SECONDARY_INTERVIEW \ + RGV_FMT_SECONDARY_AUDIOBOOK RGV_FMT_SECONDARY_AUDIODRAMA \ + RGV_FMT_SECONDARY_LIVE RGV_FMT_SECONDARY_REMIX RGV_FMT_SECONDARY_DJMIX \ + RGV_FMT_SECONDARY_MIXTAPE RGV_FMT_SECONDARY_DEMO \ + RGV_FMT_SECONDARY_FIELDREC RGV_FMT_TITLE RGV_FMT_ARTIST RGV_FMT_YEAR -# Release-group view -# ================== -# Default release group string -RGV_RELEASE="${RGV_RELEASE:-"${CTITLE}<<title>>$OFF"}" -# Release group string if the artist name differs from the current artist -RGV_RELEASE_W_ARTIST="${RGV_RELEASE_W_ARTIST:-"${CTITLE}<<title>>$OFF โ€” ${CARTIST}<<artist>>$OFF"}" -# Year of the release group -RGV_YEAR="${RGV_YEAR:-"${CYEAR}(<<year>>)$OFF"}" -export RGV_RELEASE RGV_RELEASE_W_ARTIST RGV_YEAR + # Release view + # ============ + # <<flag>> item Indication for locally available audio files + # <<status>> item Release status + # <<tracks>> string Total number of track + # <<media>> string Media description + # <<year>> string Release year + # <<country>> string Release country + # <<label>> string Release label + # <<title>> string Optional titel string + # <<artist>> string Optional artist string + RV_FMT="${RV_FMT:-"<<flag>>\t<<status>>\t<<tracks>>\t<<media>>\t<<year>>\t<<country>>\t<<label>>\t<<title>> <<artist>>"}" + RV_FMT_CNT=$(($(printf "$RV_FMT" | tr -cd '\t' | wc -c) + 1)) + RV_FMT_RIGHTALIGN="${RV_FMT_RIGHTALIGN:-"1,3"}" + RV_FMT_FLAG_LOCAL="${RV_FMT_FLAG_LOCAL:-"$FORMAT_LOCAL"}" + RV_FMT_FLAG_NO_LOCAL="${RV_FMT_FLAG_NO_LOCAL:-""}" + RV_FMT_STATUS_OFFICIAL="${RV_FMT_STATUS_OFFICIAL:-"๐ŸŸข"}" + RV_FMT_STATUS_PROMO="${RV_FMT_STATUS_PROMO:-"๐Ÿ“ฃ"}" + RV_FMT_STATUS_BOOTLEG="${RV_FMT_STATUS_BOOTLEG:-"๐Ÿ’ฃ"}" + RV_FMT_STATUS_PSEUDO="${RV_FMT_STATUS_PSEUDO:-"๐ŸŒ€"}" + RV_FMT_STATUS_WITHDRAWN="${RV_FMT_STATUS_WITHDRAWN:-"๐Ÿ”™"}" + RV_FMT_STATUS_EXPUNGED="${RV_FMT_STATUS_EXPUNGED:-"๐Ÿงน"}" + RV_FMT_STATUS_CANCELLED="${RV_FMT_STATUS_CANCELLED:-"โŒ"}" + RV_FMT_STATUS_UNKNOWN="${RV_FMT_STATUS_UNKNOWN:-""}" + RV_FMT_TRACKS="${RV_FMT_TRACKS:-"${CXXX}%s tracks$OFF"}" + RV_FMT_MEDIA="${RV_FMT_MEDIA:-"${CXXX}%s$OFF"}" + RV_FMT_YEAR="${RV_FMT_YEAR:-"${CYEAR}%s$OFF"}" + RV_FMT_COUNTRY="${RV_FMT_COUNTRY:-"${CYEAR}%s$OFF"}" + RV_FMT_LABEL="${RV_FMT_LABEL:-"${CARTIST}%s$OFF"}" + RV_FMT_TITLE="${RV_FMT_TITLE:-"${FAINT}as$OFF ${CTITLE}%s$OFF"}" + RV_FMT_ARTIST="${RV_FMT_ARTIST:-"${FAINT}by$OFF ${CTITLE}%s$OFF"}" + export RV_FMT RV_FMT_CNT RV_FMT_RIGHTALIGN RV_FMT_FLAG_LOCAL \ + RV_FMT_FLAG_NO_LOCAL RV_FMT_STATUS_OFFICIAL RV_FMT_STATUS_PROMO \ + RV_FMT_STATUS_BOOTLEG RV_FMT_STATUS_PSEUDO RV_FMT_STATUS_WITHDRAWN \ + RV_FMT_STATUS_EXPUNGED RV_FMT_STATUS_CANCELLED RV_FMT_STATUS_UNKNOWN \ + RV_FMT_TRACKS RV_FMT_MEDIA RV_FMT_YEAR RV_FMT_COUNTRY RV_FMT_LABEL \ + RV_FMT_TITLE RV_FMT_ARTIST -# Release-group types -# =================== -# Album -FORMAT_TYPE_ALBUM="${FORMAT_TYPE_ALBUM:-"LP ๐Ÿ’ฝ"}" -# EP -FORMAT_TYPE_EP="${FORMAT_TYPE_EP:-"EP ๐Ÿ“€"}" -# Single -FORMAT_TYPE_SINGLE="${FORMAT_TYPE_SINGLE:-"SI ๐ŸŽถ"}" -# Broadcast -FORMAT_TYPE_BROADCAST="${FORMAT_TYPE_BROADCAST:-"BR ๐Ÿ“ป"}" -# Other -FORMAT_TYPE_OTHER="${FORMAT_TYPE_OTHER:-"OT โ”"}" -# Flag to indicate that the given release group has associated secondary types. -FORMAT_TYPE_HAS_SECONDARY="${FORMAT_TYPE_HAS_SECONDARY:-"%sโ˜ผ"}" -# Style to represent secondary types (takes one %s placeholder) -FORMAT_TYPE_SECONDARY="${FORMAT_TYPE_SECONDARY:-"${CNOTE}[โ˜ผ: %s]$OFF"}" -# Secondary types -FORMAT_TYPE_SECONDARY_COMPILATION="${FORMAT_TYPE_SECONDARY_COMPILATION:-"๐Ÿงฉ compilation"}" -FORMAT_TYPE_SECONDARY_SOUNDTRACK="${FORMAT_TYPE_SECONDARY_SOUNDTRACK:-"๐ŸŽฌ soundtrack"}" -FORMAT_TYPE_SECONDARY_SPOKENWORD="${FORMAT_TYPE_SECONDARY_SPOKENWORD:-"๐Ÿ“– spokenword"}" -FORMAT_TYPE_SECONDARY_INTERVIEW="${FORMAT_TYPE_SECONDARY_INTERVIEW:-"๐Ÿ’ฌ interview"}" -FORMAT_TYPE_SECONDARY_AUDIOBOOK="${FORMAT_TYPE_SECONDARY_AUDIOBOOK:-"๐ŸŽง audiobook"}" -FORMAT_TYPE_SECONDARY_AUDIODRAMA="${FORMAT_TYPE_SECONDARY_AUDIODRAMA:-"๐ŸŽญ audio drama"}" -FORMAT_TYPE_SECONDARY_LIVE="${FORMAT_TYPE_SECONDARY_LIVE:-"๐ŸŽค live"}" -FORMAT_TYPE_SECONDARY_REMIX="${FORMAT_TYPE_SECONDARY_REMIX:-"๐Ÿ” remix"}" -FORMAT_TYPE_SECONDARY_DJMIX="${FORMAT_TYPE_SECONDARY_DJMIX:-"๐Ÿชฉ DJ-mix"}" -FORMAT_TYPE_SECONDARY_MIXTAPE="${FORMAT_TYPE_SECONDARY_MIXTAPE:-"๐Ÿ“ผ mixtape"}" -FORMAT_TYPE_SECONDARY_DEMO="${FORMAT_TYPE_SECONDARY_DEMO:-"๐Ÿงช demo"}" -FORMAT_TYPE_SECONDARY_FIELDREC="${FORMAT_TYPE_SECONDARY_FIELDREC:-"๐ŸŒฟ field recording"}" -export FORMAT_TYPE_ALBUM FORMAT_TYPE_EP FORMAT_TYPE_SINGLE \ - FORMAT_TYPE_BROADCAST FORMAT_TYPE_OTHER FORMAT_TYPE_HAS_SECONDARY \ - FORMAT_TYPE_SECONDARY FORMAT_TYPE_SECONDARY_COMPILATION \ - FORMAT_TYPE_SECONDARY_SOUNDTRACK FORMAT_TYPE_SECONDARY_SPOKENWORD \ - FORMAT_TYPE_SECONDARY_INTERVIEW FORMAT_TYPE_SECONDARY_AUDIOBOOK \ - FORMAT_TYPE_SECONDARY_AUDIODRAMA FORMAT_TYPE_SECONDARY_LIVE \ - FORMAT_TYPE_SECONDARY_REMIX FORMAT_TYPE_SECONDARY_DJMIX \ - FORMAT_TYPE_SECONDARY_MIXTAPE FORMAT_TYPE_SECONDARY_DEMO \ - FORMAT_TYPE_SECONDARY_FIELDREC + # Recording view + # ============== + # <<flag>> item Indication for locally available audio files + # <<media>> string Media identifier + # <<nr>> string Track number within media + # <<title>> string Track title + # <<artist>> string Track artist + # <<duration>> string Track duration + REC_FMT="${REC_FMT:-"<<flag>>\t<<media>>\t<<nr>>\t<<title>>\t<<artist>>\t<<duration>>"}" + REC_FMT_CNT=$(($(printf "$REC_FMT" | tr -cd '\t' | wc -c) + 1)) + REC_FMT_RIGHTALIGN="${REC_FMT_RIGHTALIGN:-"1,2,3,6"}" + REC_FMT_FLAG_LOCAL="${REC_FMT_FLAG_LOCAL:-"$FORMAT_LOCAL"}" + REC_FMT_FLAG_NO_LOCAL="${REC_FMT_FLAG_NO_LOCAL:-""}" + REC_FMT_MEDIA="${REC_FMT_MEDIA:-"${CNOTE}${FAINT}%s$OFF"}" + REC_FMT_NR="${REC_FMT_NR:-"${CNOTE}%s$OFF"}" + REC_FMT_TITLE="${REC_FMT_TITLE:-"${CTITLE}%s$OFF"}" + REC_FMT_ARTIST="${REC_FMT_ARTIST:-"${CARTIST}%s$OFF"}" + REC_FMT_DURATION="${REC_FMT_DURATION:-"${CXXX}%s$OFF"}" + export REC_FMT REC_FMT_CNT REC_FMT_RIGHTALIGN REC_FMT_FLAG_LOCAL \ + REC_FMT_FLAG_NO_LOCAL REC_FMT_MEDIA REC_FMT_NR REC_FMT_TITLE \ + REC_FMT_ARTIST REC_FMT_DURATION -# Artist Preview -# ============== -# Main preview format. Takes two %s placeholder. The first is for the artist -# biography. The second for the life span. -APV_FORMAT="${APV_FORMAT:-"\n\n${CDESC}%s${OFF}\n\n${CLIFE}%s${OFF}"}" -# Specification of a date -APV_DATE="${APV_DATE:-"%s"}" -# Specification of a place -APV_PLACE="${APV_PLACE:-"%s"}" -# Specification of a date and a place (in that order) -APV_DATEPLACE="${APV_DATEPLACE:-"$APV_DATE, $APV_PLACE"}" -# String to represent when/where a person is born -APV_BORN="${APV_BORN:-"๐Ÿผ Born: %s"}" -# String to represent when/where a person died -APV_DIED="${APV_DIED:-"๐Ÿ•ฏ๏ธ Died: %s"}" -export APV_FORMAT APV_DATE APV_PLACE APV_DATEPLACE APV_BORN APV_DIED + # Recording view (playlist) + # ========================= + # <<playing>> item Mark for currently playing track + # <<title>> string Track title + # <<artist>> string Track artist + # <<duration>> string Track duration + PLYLST_FMT="${PLYLST_FMT:-"<<playing>>\t<<title>>\t<<artist>>\t<<duration>>"}" + PLYLST_FMT_CNT=$(($(printf "$PLYLST_FMT" | tr -cd '\t' | wc -c) + 1)) + PLYLST_FMT_RIGHTALIGN="${PLYLST_FMT_RIGHTALIGN:-"1"}" + PLYLST_FMT_PLAYING_YES="${PLYLST_FMT_PLAYING_YES:-"๐Ÿ‘‰"}" + PLYLST_FMT_PLAYING_NO="${PLYLST_FMT_PLAYING_NO:-""}" + PLYLST_FMT_TITLE="${PLYLST_FMT_TITLE:-"${CTITLE}%s$OFF"}" + PLYLST_FMT_ARTIST="${PLYLST_FMT_ARTIST:-"${CARTIST}%s$OFF"}" + PLYLST_FMT_DURATION="${PLYLST_FMT_DURATION:-"${CXXX}%s$OFF"}" + export PLYLST_FMT PLYLST_FMT_CNT PLYLST_FMT_RIGHTALIGN \ + PLYLST_FMT_PLAYING_YES PLYLST_FMT_PLAYING_NO PLYLST_FMT_TITLE \ + PLYLST_FMT_ARTIST PLYLST_FMT_DURATION -# Release view -# ============ -# Format of a string that represents a release. -RV_FORMAT="${RV_FORMAT:-"<<status>>\t${CXXX}<<tracks>> tracks\t<<media>>$OFF\t${CYEAR}<<year>>\t<<country>>$OFF\t${CARTIST}<<label>>$OFF"}" -# Additional string to display the release title and artist name -RV_TITLE_ARTIST="${RV_TITLE_ARTIST:-"${FAINT}as ${CTITLE}<<title>>$OFF by ${FAINT}${CARTIST}<<artist>>$OFF"}" -# Additional string to display the release title -RV_TITLE="${RV_TITLE:-"${FAINT}as ${CTITLE}<<title>>$OFF"}" -# Additional string to display the artist -RV_ARTIST="${RV_ARTIST:-"${FAINT}by ${CARTIST}<<artist>>$OFF"}" -export RV_FORMAT RV_TITLE_ARTIST RV_TITLE RV_ARTIST + # Headers + # ======= + # These header strings are based on the respective view and its fields + # defined above. + # + # Header that displays artist's name (based on artist view) + HEADER_ARTIST="${HEADER_ARTIST:-" ${CARTIST}%s$OFF "}" + HEADER_ARTIST_FMT="${HEADER_ARTIST_FMT:-"๐ŸŽค\t<<name>> โŒช"}" + HEADER_ARTIST_FMT_CNT=$(($(printf "$HEADER_ARTIST_FMT" | tr -cd '\t' | wc -c) + 1)) + HEADER_ARTIST_FMT_RIGHTALIGN="${HEADER_ARTIST_FMT_RIGHTALIGN:-"1"}" + HEADER_ARTIST_FMT_FLAG_LOCAL="${HEADER_ARTIST_FMT_FLAG_LOCAL:-"$AV_FMT_FLAG_LOCAL"}" + HEADER_ARTIST_FMT_FLAG_NO_LOCAL="${HEADER_ARTIST_FMT_FLAG_NO_LOCAL:-"$AV_FMT_FLAG_NO_LOCAL"}" + HEADER_ARTIST_FMT_TYPE_PERSON="${HEADER_ARTIST_FMT_TYPE_PERSON:-"$AV_FMT_TYPE_PERSON"}" + HEADER_ARTIST_FMT_TYPE_GROUP="${HEADER_ARTIST_FMT_TYPE_GROUP:-"$AV_FMT_TYPE_GROUP"}" + HEADER_ARTIST_FMT_NAME="${HEADER_ARTIST_FMT_NAME:-"$AV_FMT_NAME"}" + HEADER_ARTIST_FMT_DISAMBIGUATION="${HEADER_ARTIST_FMT_DISAMBIGUATION:-"$AV_FMT_DISAMBIGUATION"}" + export HEADER_ARTIST HEADER_ARTIST_FMT HEADER_ARTIST_FMT_CNT \ + HEADER_ARTIST_FMT_RIGHTALIGN HEADER_ARTIST_FMT_FLAG_LOCAL \ + HEADER_ARTIST_FMT_FLAG_NO_LOCAL HEADER_ARTIST_FMT_TYPE_PERSON \ + HEADER_ARTIST_FMT_TYPE_GROUP HEADER_ARTIST_FMT_NAME \ + HEADER_ARTIST_FMT_DISAMBIGUATION -# Release Status -# ============== -FORMAT_STATUS_OFFICIAL="${FORMAT_STATUS_OFFICIAL:-"๐ŸŸข"}" -FORMAT_STATUS_PROMO="${FORMAT_STATUS_PROMO:-"๐Ÿ“ฃ"}" -FORMAT_STATUS_BOOTLEG="${FORMAT_STATUS_BOOTLEG:-"๐Ÿ’ฃ"}" -FORMAT_STATUS_PSEUDO="${FORMAT_STATUS_PSEUDO:-"๐ŸŒ€"}" -FORMAT_STATUS_WITHDRAWN="${FORMAT_STATUS_WITHDRAWN:-"๐Ÿ”™"}" -FORMAT_STATUS_EXPUNGED="${FORMAT_STATUS_EXPUNGED:-"๐Ÿงน"}" -FORMAT_STATUS_CANCELLED="${FORMAT_STATUS_CANCELLED:-"โŒ"}" -export FORMAT_STATUS_OFFICIAL FORMAT_STATUS_PROMO FORMAT_STATUS_BOOTLEG \ - FORMAT_STATUS_PSEUDO FORMAT_STATUS_WITHDRAWN FORMAT_STATUS_EXPUNGED \ - FORMAT_STATUS_CANCELLED + # Header that displays the release-group (based on release-group view) + HEADER_RG_FMT="${HEADER_RG_FMT:-"๐ŸŽค\t<<artist>> ใ€‹<<title>> โŒช"}" + HEADER_RG_FMT_CNT=$(($(printf "$HEADER_RG_FMT" | tr -cd '\t' | wc -c) + 1)) + HEADER_RG_FMT_RIGHTALIGN="${HEADER_RG_FMT_RIGHTALIGN:-"1"}" + HEADER_RG_FMT_FLAG_LOCAL="${HEADER_RG_FMT_FLAG_LOCAL:-"$RGV_FMT_FLAG_LOCAL"}" + HEADER_RG_FMT_FLAG_NO_LOCAL="${HEADER_RG_FMT_FLAG_NO_LOCAL:-"$RGV_FMT_FLAG_NO_LOCAL"}" + HEADER_RG_FMT_TYPE_SINGLE="${HEADER_RG_FMT_TYPE_SINGLE:-"$RGV_FMT_TYPE_SINGLE"}" + HEADER_RG_FMT_TYPE_ALBUM="${HEADER_RG_FMT_TYPE_ALBUM:-"$RGV_FMT_TYPE_ALBUM"}" + HEADER_RG_FMT_TYPE_EP="${HEADER_RG_FMT_TYPE_EP:-"$RGV_FMT_TYPE_EP"}" + HEADER_RG_FMT_TYPE_BROADCAST="${HEADER_RG_FMT_TYPE_BROADCAST:-"$RGV_FMT_TYPE_BROADCAST"}" + HEADER_RG_FMT_TYPE_OTHER="${HEADER_RG_FMT_TYPE_OTHER:-"$RGV_FMT_TYPE_OTHER"}" + HEADER_RG_FMT_TYPE_UNKNOWN="${HEADER_RG_FMT_TYPE_UNKNOWN:-"$RGV_FMT_TYPE_UNKNOWN"}" + HEADER_RG_FMT_HASSECONDARY_YES="${HEADER_RG_FMT_HASSECONDARY_YES:-"$RGV_FMT_HASSECONDARY_YES"}" + HEADER_RG_FMT_HASSECONDARY_NO="${HEADER_RG_FMT_HASSECONDARY_NO:-"$RGV_FMT_HASSECONDARY_NO"}" + HEADER_RG_FMT_SECONDARY="${HEADER_RG_FMT_SECONDARY:-"$RGV_FMT_SECONDARY"}" + HEADER_RG_FMT_SECONDARY_SOUNDTRACK="${HEADER_RG_FMT_SECONDARY_SOUNDTRACK:-"$RGV_FMT_SECONDARY_SOUNDTRACK"}" + HEADER_RG_FMT_SECONDARY_SPOKENWORD="${HEADER_RG_FMT_SECONDARY_SPOKENWORD:-"$RGV_FMT_SECONDARY_SPOKENWORD"}" + HEADER_RG_FMT_SECONDARY_INTERVIEW="${HEADER_RG_FMT_SECONDARY_INTERVIEW:-"$RGV_FMT_SECONDARY_INTERVIEW"}" + HEADER_RG_FMT_SECONDARY_AUDIOBOOK="${HEADER_RG_FMT_SECONDARY_AUDIOBOOK:-"$RGV_FMT_SECONDARY_AUDIOBOOK"}" + HEADER_RG_FMT_SECONDARY_AUDIODRAMA="${HEADER_RG_FMT_SECONDARY_AUDIODRAMA:-"$RGV_FMT_SECONDARY_AUDIODRAMA"}" + HEADER_RG_FMT_SECONDARY_LIVE="${HEADER_RG_FMT_SECONDARY_LIVE:-"$RGV_FMT_SECONDARY_LIVE"}" + HEADER_RG_FMT_SECONDARY_REMIX="${HEADER_RG_FMT_SECONDARY_REMIX:-"$RGV_FMT_SECONDARY_REMIX"}" + HEADER_RG_FMT_SECONDARY_DJMIX="${HEADER_RG_FMT_SECONDARY_DJMIX:-"$RGV_FMT_SECONDARY_DJMIX"}" + HEADER_RG_FMT_SECONDARY_MIXTAPE="${HEADER_RG_FMT_SECONDARY_MIXTAPE:-"$RGV_FMT_SECONDARY_MIXTAPE"}" + HEADER_RG_FMT_SECONDARY_DEMO="${HEADER_RG_FMT_SECONDARY_DEMO:-"$RGV_FMT_SECONDARY_DEMO"}" + HEADER_RG_FMT_SECONDARY_FIELDREC="${HEADER_RG_FMT_SECONDARY_FIELDREC:-"$RGV_FMT_SECONDARY_FIELDREC"}" + HEADER_RG_FMT_TITLE="${HEADER_RG_FMT_TITLE:-"$RGV_FMT_TITLE"}" + HEADER_RG_FMT_ARTIST="${HEADER_RG_FMT_ARTIST:-"${CARTIST}%s$OFF"}" + HEADER_RG_FMT_YEAR="${HEADER_RG_FMT_YEAR:-"$RGV_FMT_YEAR"}" + export HEADER_RG_FMT HEADER_RG_FMT_CNT HEADER_RG_FMT_RIGHTALIGN \ + HEADER_RG_FMT_FLAG_LOCAL HEADER_RG_FMT_FLAG_NO_LOCAL \ + HEADER_RG_FMT_TYPE_SINGLE HEADER_RG_FMT_TYPE_ALBUM HEADER_RG_FMT_TYPE_EP \ + HEADER_RG_FMT_TYPE_BROADCAST HEADER_RG_FMT_TYPE_OTHER \ + HEADER_RG_FMT_TYPE_UNKNOWN HEADER_RG_FMT_HASSECONDARY_YES \ + HEADER_RG_FMT_HASSECONDARY_NO HEADER_RG_FMT_SECONDARY \ + HEADER_RG_FMT_SECONDARY_SOUNDTRACK HEADER_RG_FMT_SECONDARY_SPOKENWORD \ + HEADER_RG_FMT_SECONDARY_INTERVIEW HEADER_RG_FMT_SECONDARY_AUDIOBOOK \ + HEADER_RG_FMT_SECONDARY_AUDIODRAMA HEADER_RG_FMT_SECONDARY_LIVE \ + HEADER_RG_FMT_SECONDARY_REMIX HEADER_RG_FMT_SECONDARY_DJMIX \ + HEADER_RG_FMT_SECONDARY_MIXTAPE HEADER_RG_FMT_SECONDARY_DEMO \ + HEADER_RG_FMT_SECONDARY_FIELDREC HEADER_RG_FMT_TITLE HEADER_RG_FMT_ARTIST \ + HEADER_RG_FMT_YEAR -# Recording view -# ============== -# Format of a track in a release -REC_FORMAT="${REC_FORMAT:-"${CNOTE}${FAINT}<<med>>\t${CNOTE}<<nr>>$OFF\t${CTITLE}<<title>>\t${CARTIST}<<artist>>\t${CXXX}<<duration>>$OFF"}" -# Format of a track in the playlist -REC_FORMAT_NO_NUMBER="${REC_FORMAT_NO_NUMBER:-"${CTITLE}<<title>>\t${CARTIST}<<artist>>\t${CXXX}<<duration>>$OFF"}" -export REC_FORMAT REC_FORMAT_NO_NUMBER + # Header that displays the release (based on release view) + #HEADER_RELEASE="${HEADER_RELEASE:-" ${CARTIST}%s$OFF ใ€‹${CTITLE}%s$OFF โŒช%s"}" + #HEADER_RELEASE_FORMAT="${HEADER_RELEASE_FORMAT:-"${CRELINFO}<<tracks>> tx <<media>> $OFF|$CRELINFO <<label>> <<country>> <<year>>$OFF"}" + HEADER_R_FMT="${HEADER_R_FMT:-"๐ŸŽค\t<<artist>> ใ€‹<<title>> โŒช<<tracks>> ${CRELINFO}tx${OFF} <<media>> | <<label>> <<country>> <<year>>"}" + HEADER_R_FMT_CNT=$(($(printf "$HEADER_R_FMT" | tr -cd '\t' | wc -c) + 1)) + HEADER_R_FMT_RIGHTALIGN="${HEADER_R_FMT_RIGHTALIGN:-"1"}" + HEADER_R_FMT_FLAG_LOCAL="${HEADER_R_FMT_FLAG_LOCAL:-"$RV_FMT_FLAG_LOCAL"}" + HEADER_R_FMT_FLAG_NO_LOCAL="${HEADER_R_FMT_FLAG_NO_LOCAL:-"$RV_FMT_FLAG_NO_LOCAL"}" + HEADER_R_FMT_STATUS_OFFICIAL="${HEADER_R_FMT_STATUS_OFFICIAL:-"$RV_FMT_STATUS_OFFICIAL"}" + HEADER_R_FMT_STATUS_PROMO="${HEADER_R_FMT_STATUS_PROMO:-"$RV_FMT_STATUS_PROMO"}" + HEADER_R_FMT_STATUS_BOOTLEG="${HEADER_R_FMT_STATUS_BOOTLEG:-"$RV_FMT_STATUS_BOOTLEG"}" + HEADER_R_FMT_STATUS_PSEUDO="${HEADER_R_FMT_STATUS_PSEUDO:-"$RV_FMT_STATUS_PSEUDO"}" + HEADER_R_FMT_STATUS_WITHDRAWN="${HEADER_R_FMT_STATUS_WITHDRAWN:-"$RV_FMT_STATUS_WITHDRAWN"}" + HEADER_R_FMT_STATUS_EXPUNGED="${HEADER_R_FMT_STATUS_EXPUNGED:-"$RV_FMT_STATUS_EXPUNGED"}" + HEADER_R_FMT_STATUS_CANCELLED="${HEADER_R_FMT_STATUS_CANCELLED:-"$RV_FMT_STATUS_CANCELLED"}" + HEADER_R_FMT_STATUS_UNKNOWN="${HEADER_R_FMT_STATUS_UNKNOWN:-"$RV_FMT_STATUS_UNKNOWN"}" + HEADER_R_FMT_TRACKS="${HEADER_R_FMT_TRACKS:-"${CRELINFO}%s$OFF"}" + HEADER_R_FMT_MEDIA="${HEADER_R_FMT_MEDIA:-"${CRELINFO}%s$OFF"}" + HEADER_R_FMT_YEAR="${HEADER_R_FMT_YEAR:-"${CRELINFO}%s$OFF"}" + HEADER_R_FMT_COUNTRY="${HEADER_R_FMT_COUNTRY:-"${CRELINFO}%s$OFF"}" + HEADER_R_FMT_LABEL="${HEADER_R_FMT_LABEL:-"${CRELINFO}%s$OFF"}" + HEADER_R_FMT_TITLE="${HEADER_R_FMT_TITLE:-"${CTITLE}%s$OFF"}" + HEADER_R_FMT_ARTIST="${HEADER_R_FMT_ARTIST:-"${CARTIST}%s$OFF"}" + export HEADER_R_FMT HEADER_R_FMT_CNT HEADER_R_FMT_RIGHTALIGN \ + HEADER_R_FMT_FLAG_LOCAL HEADER_R_FMT_FLAG_NO_LOCAL \ + HEADER_R_FMT_STATUS_OFFICIAL HEADER_R_FMT_STATUS_PROMO \ + HEADER_R_FMT_STATUS_BOOTLEG HEADER_R_FMT_STATUS_PSEUDO \ + HEADER_R_FMT_STATUS_WITHDRAWN HEADER_R_FMT_STATUS_EXPUNGED \ + HEADER_R_FMT_STATUS_CANCELLED HEADER_R_FMT_STATUS_UNKNOWN \ + HEADER_R_FMT_TRACKS HEADER_R_FMT_MEDIA HEADER_R_FMT_YEAR \ + HEADER_R_FMT_COUNTRY HEADER_R_FMT_LABEL HEADER_R_FMT_TITLE \ + HEADER_R_FMT_ARTIST -# Keybinding themes -# ================= -# Format keybinding group -KBF_GROUP="${KBF_GROUP:-"${UNDERLINE}${CKB}%s$OFF"}" -# Format key -KBF_KEY="${KBF_KEY:-"${BOLD}${CKB}%s$OFF"}" -# Format description -KBF_DESC="${KBF_DESC:-"${CKB}%s$OFF"}" -export KBF_GROUP KBF_KEY KBF_DESC + # Artist Preview + # ============== + # Main preview format. Takes two %s placeholder. The first is for the artist + # biography. The second for the life span. + APV_FORMAT="${APV_FORMAT:-"\n\n${CDESC}%s${OFF}\n\n${CLIFE}%s${OFF}"}" + # Specification of a date + APV_DATE="${APV_DATE:-"%s"}" + # Specification of a place + APV_PLACE="${APV_PLACE:-"%s"}" + # Specification of a date and a place (in that order) + APV_DATEPLACE="${APV_DATEPLACE:-"$APV_DATE, $APV_PLACE"}" + # String to represent when/where a person is born + APV_BORN="${APV_BORN:-"๐Ÿผ Born: %s"}" + # String to represent when/where a person died + APV_DIED="${APV_DIED:-"๐Ÿ•ฏ๏ธ Died: %s"}" + export APV_FORMAT APV_DATE APV_PLACE APV_DATEPLACE APV_BORN APV_DIED + + # Keybinding themes + # ================= + # Format keybinding group + KBF_GROUP="${KBF_GROUP:-"${UNDERLINE}${CKB}%s$OFF"}" + # Format key + KBF_KEY="${KBF_KEY:-"${BOLD}${CKB}%s$OFF"}" + # Format description + KBF_DESC="${KBF_DESC:-"${CKB}%s$OFF"}" + export KBF_GROUP KBF_KEY KBF_DESC + + export THEME_LOADED=1 +fi