From 1ef407672a5575f9a2f769b6e0456593d7899838 Mon Sep 17 00:00:00 2001 From: Diego Moreda Date: Tue, 24 Nov 2015 16:31:01 +0100 Subject: [PATCH] info: add item format and length format arguments * Add custom output formatting via a format string to InfoPlugin. The command accepts a formatting string via the "-f" parameter, which is handled by its CommonOptionsParser and applied during print_data(). * Modify the emitters in order to include an Item into the list of fields, that is formatted according to the format string if specified. * Add an argument to allow the user to choose if track lengths are displayed as raw floats or using a human-readable form (mm:ss), defaulting to human-readable form. --- beetsplug/info.py | 42 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 38 insertions(+), 4 deletions(-) diff --git a/beetsplug/info.py b/beetsplug/info.py index d6988d097..e8c6d987f 100644 --- a/beetsplug/info.py +++ b/beetsplug/info.py @@ -25,6 +25,7 @@ import re from beets.plugins import BeetsPlugin from beets import ui from beets import mediafile +from beets.library import Item from beets.util import displayable_path, normpath, syspath @@ -52,7 +53,11 @@ def tag_data_emitter(path): tags[field] = getattr(mf, field) tags['art'] = mf.art is not None tags['path'] = displayable_path(path) + # create a temporary Item to take advantage of __format__ + tags['item'] = Item(db=None, **tags) + return tags + return emitter @@ -65,6 +70,7 @@ def library_data_emitter(item): def emitter(): data = dict(item.formatted()) data['path'] = displayable_path(item.path) + data['item'] = item return data return emitter @@ -78,14 +84,36 @@ def update_summary(summary, tags): return summary -def print_data(data): +def print_data(data, fmt=None, human_length=True): + """Print, with optional formatting, the fields of a single item. + + If no format string `fmt` is passed, the entries on `data` are printed one + in each line, with the format 'field: value'. If `fmt` is not `None`, the + item is printed according to `fmt`, using the `Item.__format__` machinery. + + If `raw_length` is `True`, the `length` field is displayed using its raw + value (float with the number of seconds and miliseconds). If not, a human + readable form is displayed instead (mm:ss). + """ + item = data.pop('item', None) + if fmt: + # use fmt specified by the user, prettifying length if needed + if human_length and '$length' in fmt: + item['humanlength'] = ui.human_seconds_short(item.length) + fmt = fmt.replace('$length', '$humanlength') + ui.print_(format(item, fmt)) + return + path = data.pop('path', None) formatted = {} for key, value in data.iteritems(): if isinstance(value, list): formatted[key] = u'; '.join(value) if value is not None: - formatted[key] = value + if human_length and key == 'length': + formatted[key] = ui.human_seconds_short(float(value)) + else: + formatted[key] = value if len(formatted) == 0: return @@ -115,6 +143,10 @@ class InfoPlugin(BeetsPlugin): cmd.parser.add_option('-i', '--include-keys', default=[], action='append', dest='included_keys', help='comma separated list of keys to show') + cmd.parser.add_option('-r', '--raw-length', action='store_true', + default=False, + help='display length as seconds') + cmd.parser.add_format_option(target='item') return [cmd] def run(self, lib, opts, args): @@ -151,18 +183,20 @@ class InfoPlugin(BeetsPlugin): continue path = data.get('path') + item = data.get('item') data = key_filter(data) data['path'] = path # always show path + data['item'] = item # always include item, to avoid filtering if opts.summarize: update_summary(summary, data) else: if not first: ui.print_() - print_data(data) + print_data(data, opts.format, not opts.raw_length) first = False if opts.summarize: - print_data(summary) + print_data(summary, human_length=not opts.raw_length) def make_key_filter(include):