mirror of
https://github.com/beetbox/beets.git
synced 2025-12-27 11:02:43 +01:00
Merge pull request #284 from mrmachine/ui-improvements
UI improvements and consistency. Colorisation, indentation, position by importance, and highlight benign changes. 1. Consistently colorise parenthesis surrounding colorised text that is conditional (doesn't always appear) so that it stand out more. This includes the album info data source (when it's not MusicBrainz), the album disambiguation (sometimes there is none), and the partial match message. 2. Indent the album title when there isn't a change. Makes it stand out more from the file path(s) above and info line below, and is consistent with the indentation when there is an album or artist change. 3. When listing releases, colorise album disambiguation in light gray to distinguish it more clearly from the album title. Light gray seems like a good colour because it is subtle, and disambiguation is supplementary information (not green/success, red/error or yellow/warning). 4. Also when listing releases, display similarity before partial message and disambiguation last. This is in order of importance, and also similarity is always present while the others are conditional, and finally it is often the case where the album title is the same and only the disambiguation is different. Using this order keeps things lined up in this case and easier to visually compare similarity and disambiguation text. 5. Colorise benign track index changes (to/from per disc numbering) in yellow, without applying a match penalty. We should still display these because even though the track number is still correct/equivalent, beets will apply a change if the new tags are applied. 6. Don't display source unless it's not MusicBrainz. By default beets will only find matches in the MusicBrainz database. Only if a plugin is enabled can a different source be used, so not everybody needs to see this all the time.
This commit is contained in:
commit
22e895df83
2 changed files with 81 additions and 55 deletions
|
|
@ -196,6 +196,12 @@ def assign_items(items, tracks):
|
|||
extra_tracks = set(tracks) - set(mapping.values())
|
||||
return mapping, extra_items, extra_tracks
|
||||
|
||||
def track_index_changed(item, track_info):
|
||||
"""Returns True if the item and track info index is different. Tolerates
|
||||
per disc and per release numbering.
|
||||
"""
|
||||
return item.track not in (track_info.medium_index, track_info.index)
|
||||
|
||||
def track_distance(item, track_info, incl_artist=False):
|
||||
"""Determines the significance of a track metadata change. Returns a
|
||||
float in [0.0,1.0]. `incl_artist` indicates that a distance
|
||||
|
|
@ -230,7 +236,7 @@ def track_distance(item, track_info, incl_artist=False):
|
|||
|
||||
# Track index.
|
||||
if track_info.index and item.track:
|
||||
if item.track not in (track_info.index, track_info.medium_index):
|
||||
if track_index_changed(item, track_info):
|
||||
dist += TRACK_INDEX_WEIGHT
|
||||
dist_max += TRACK_INDEX_WEIGHT
|
||||
|
||||
|
|
@ -374,8 +380,8 @@ def _recommendation(results):
|
|||
rec = max_rec['tracklength']
|
||||
|
||||
# Track number differs.
|
||||
elif rec > max_rec['tracknumber'] and item.track not in \
|
||||
(track_info.index, track_info.medium_index):
|
||||
elif rec > max_rec['tracknumber'] and \
|
||||
track_index_changed(item, track_info):
|
||||
rec = max_rec['tracknumber']
|
||||
|
||||
return rec
|
||||
|
|
|
|||
|
|
@ -118,6 +118,25 @@ PARTIAL_MATCH_MESSAGE = u'(partial match!)'
|
|||
|
||||
# Importer utilities and support.
|
||||
|
||||
def disambig_string(info):
|
||||
"""Returns label, year and media disambiguation, if available.
|
||||
"""
|
||||
disambig = []
|
||||
if info.label:
|
||||
disambig.append(info.label)
|
||||
if info.year:
|
||||
disambig.append(unicode(info.year))
|
||||
if info.media:
|
||||
if info.mediums > 1:
|
||||
disambig.append(u'{0}x{1}'.format(
|
||||
info.mediums, info.media))
|
||||
else:
|
||||
disambig.append(info.media)
|
||||
if info.albumdisambig:
|
||||
disambig.append(info.albumdisambig)
|
||||
if disambig:
|
||||
return u', '.join(disambig)
|
||||
|
||||
def dist_string(dist):
|
||||
"""Formats a distance (a float) as a colorized similarity percentage
|
||||
string.
|
||||
|
|
@ -131,13 +150,6 @@ def dist_string(dist):
|
|||
out = ui.colorize('red', out)
|
||||
return out
|
||||
|
||||
def source_string(source):
|
||||
"""Colorize a data_source string.
|
||||
"""
|
||||
if source == 'MusicBrainz':
|
||||
return source
|
||||
return ui.colorize('yellow', source)
|
||||
|
||||
def show_change(cur_artist, cur_album, match):
|
||||
"""Print out a representation of the changes that will be made if an
|
||||
album's tags are changed according to `match`, which must be an AlbumMatch
|
||||
|
|
@ -155,22 +167,30 @@ def show_change(cur_artist, cur_album, match):
|
|||
|
||||
# Add a suffix if this is a partial match.
|
||||
if partial:
|
||||
out += u' ' + ui.colorize('yellow', PARTIAL_MATCH_MESSAGE)
|
||||
out += u' %s' % ui.colorize('yellow', PARTIAL_MATCH_MESSAGE)
|
||||
|
||||
print_(out)
|
||||
|
||||
def format_index(track_info):
|
||||
"""Return a string representing the track index of the given
|
||||
TrackInfo object.
|
||||
TrackInfo or Item object.
|
||||
"""
|
||||
if config['per_disc_numbering'].get(bool):
|
||||
if match.info.mediums > 1:
|
||||
return u'{0}-{1}'.format(track_info.medium,
|
||||
track_info.medium_index)
|
||||
else:
|
||||
return unicode(track_info.medium_index)
|
||||
if isinstance(track_info, autotag.hooks.TrackInfo):
|
||||
index = track_info.index
|
||||
medium_index = track_info.medium_index
|
||||
medium = track_info.medium
|
||||
mediums = match.info.mediums
|
||||
else:
|
||||
return unicode(track_info.index)
|
||||
index = medium_index = track_info.track
|
||||
medium = track_info.disc
|
||||
mediums = track_info.disctotal
|
||||
if config['per_disc_numbering'].get(bool):
|
||||
if mediums > 1:
|
||||
return u'{0}-{1}'.format(medium, medium_index)
|
||||
else:
|
||||
return unicode(medium_index)
|
||||
else:
|
||||
return unicode(index)
|
||||
|
||||
# Identify the album in question.
|
||||
if cur_artist != match.info.artist or \
|
||||
|
|
@ -190,16 +210,22 @@ def show_change(cur_artist, cur_album, match):
|
|||
print_("To:")
|
||||
show_album(artist_r, album_r)
|
||||
else:
|
||||
message = u"Tagging: %s - %s" % (match.info.artist, match.info.album)
|
||||
message = u"Tagging:\n %s - %s" % (match.info.artist,
|
||||
match.info.album)
|
||||
if match.extra_items or match.extra_tracks:
|
||||
message += u' ' + ui.colorize('yellow', PARTIAL_MATCH_MESSAGE)
|
||||
message += u' %s' % ui.colorize('yellow', PARTIAL_MATCH_MESSAGE)
|
||||
print_(message)
|
||||
|
||||
# Info line.
|
||||
print_('from {0}, similarity: {1}'.format(
|
||||
source_string(match.info.data_source),
|
||||
dist_string(match.distance),
|
||||
))
|
||||
info = []
|
||||
info.append('(Similarity: %s)' % dist_string(match.distance))
|
||||
if match.info.data_source != 'MusicBrainz':
|
||||
info.append(ui.colorize('yellow',
|
||||
'(%s)' % match.info.data_source))
|
||||
disambig = disambig_string(match.info)
|
||||
if disambig:
|
||||
info.append(ui.colorize('lightgray', '(%s)' % disambig))
|
||||
print_(' '.join(info))
|
||||
|
||||
# Tracks.
|
||||
pairs = match.mapping.items()
|
||||
|
|
@ -222,11 +248,20 @@ def show_change(cur_artist, cur_album, match):
|
|||
lhs_width = len(cur_title)
|
||||
|
||||
# Track number change.
|
||||
if item.track not in (track_info.index, track_info.medium_index):
|
||||
cur_track, new_track = unicode(item.track), format_index(track_info)
|
||||
lhs_track, rhs_track = ui.color_diff_suffix(cur_track, new_track)
|
||||
templ = ui.colorize('red', u' (#') + u'{0}' + \
|
||||
ui.colorize('red', u')')
|
||||
cur_track, new_track = format_index(item), format_index(track_info)
|
||||
if cur_track != new_track:
|
||||
if item.track in (track_info.index, track_info.medium_index):
|
||||
color = 'yellow'
|
||||
else:
|
||||
color = 'red'
|
||||
if (cur_track + new_track).count('-') == 1:
|
||||
lhs_track, rhs_track = ui.colorize(color, cur_track), \
|
||||
ui.colorize(color, new_track)
|
||||
else:
|
||||
lhs_track, rhs_track = ui.color_diff_suffix(cur_track,
|
||||
new_track)
|
||||
templ = ui.colorize(color, u' (#') + u'{0}' + \
|
||||
ui.colorize(color, u')')
|
||||
lhs += templ.format(lhs_track)
|
||||
rhs += templ.format(rhs_track)
|
||||
lhs_width += len(cur_track) + 4
|
||||
|
|
@ -401,35 +436,20 @@ def choose_candidate(candidates, singleton, rec, cur_artist=None,
|
|||
(cur_artist, cur_album))
|
||||
print_('Candidates:')
|
||||
for i, match in enumerate(candidates):
|
||||
line = '%i. %s - %s' % (i + 1, match.info.artist,
|
||||
match.info.album)
|
||||
|
||||
# Label, year and media disambiguation, if available.
|
||||
disambig = []
|
||||
if match.info.label:
|
||||
disambig.append(match.info.label)
|
||||
if match.info.year:
|
||||
disambig.append(unicode(match.info.year))
|
||||
if match.info.media:
|
||||
if match.info.mediums > 1:
|
||||
disambig.append(u'{0}x{1}'.format(
|
||||
match.info.mediums, match.info.media))
|
||||
else:
|
||||
disambig.append(match.info.media)
|
||||
if match.info.albumdisambig:
|
||||
disambig.append(match.info.albumdisambig)
|
||||
if disambig:
|
||||
line += u' [{0}]'.format(u', '.join(disambig))
|
||||
|
||||
line += ' (%s)' % dist_string(match.distance)
|
||||
line = ['%i. %s - %s (%s)' % (i + 1, match.info.artist,
|
||||
match.info.album,
|
||||
dist_string(match.distance))]
|
||||
|
||||
# Point out the partial matches.
|
||||
if match.extra_items or match.extra_tracks:
|
||||
warning = PARTIAL_MATCH_MESSAGE
|
||||
warning = ui.colorize('yellow', warning)
|
||||
line += u' %s' % warning
|
||||
line.append(ui.colorize('yellow',
|
||||
PARTIAL_MATCH_MESSAGE))
|
||||
|
||||
print_(line)
|
||||
disambig = disambig_string(match.info)
|
||||
if disambig:
|
||||
line.append(ui.colorize('lightgray', '(%s)' % disambig))
|
||||
|
||||
print_(' '.join(line))
|
||||
|
||||
# Ask the user for a choice.
|
||||
if singleton:
|
||||
|
|
|
|||
Loading…
Reference in a new issue