make fuzzy use PluginQuery instead of a subcommand

This commit is contained in:
Philippe Mongeau 2013-03-10 16:50:54 -04:00
parent f7ced33b8e
commit 7314bc0524

View file

@ -14,84 +14,32 @@
"""Like beet list, but with fuzzy matching """Like beet list, but with fuzzy matching
""" """
from beets.plugins import BeetsPlugin from beets.plugins import BeetsPlugin
from beets.library import PluginQuery
from beets.ui import Subcommand, decargs, print_obj from beets.ui import Subcommand, decargs, print_obj
from beets.util.functemplate import Template
from beets import config from beets import config
from beets import util
import difflib import difflib
class FuzzyQuery(PluginQuery):
def __init__(self, field, pattern):
super(FuzzyQuery, self).__init__(field, pattern)
# self.field = field
self.name = 'PLUGIN'
self.prefix = "~"
def fuzzy_score(queryMatcher, item): def match(self, pattern, val):
queryMatcher.set_seq1(item) if pattern is None:
return queryMatcher.quick_ratio() return False
val = util.as_string(val)
queryMatcher = difflib.SequenceMatcher(None, pattern, val)
return queryMatcher.quick_ratio() > 0.7
def is_match(queryMatcher, item, album=False, verbose=False, threshold=0.7): class FuzzyPlugin(BeetsPlugin):
if album:
values = [item.albumartist, item.album]
else:
values = [item.artist, item.album, item.title]
s = max(fuzzy_score(queryMatcher, i.lower()) for i in values)
if verbose:
return (s >= threshold, s)
else:
return s >= threshold
def fuzzy_list(lib, opts, args):
query = decargs(args)
query = ' '.join(query).lower()
queryMatcher = difflib.SequenceMatcher(b=query)
if opts.threshold is not None:
threshold = float(opts.threshold)
else:
threshold = config['fuzzy']['threshold'].as_number()
if opts.path:
fmt = '$path'
else:
fmt = opts.format
template = Template(fmt) if fmt else None
if opts.album:
objs = lib.albums()
else:
objs = lib.items()
items = filter(lambda i: is_match(queryMatcher, i, album=opts.album,
threshold=threshold), objs)
for item in items:
print_obj(item, lib, template)
if opts.verbose:
print(is_match(queryMatcher, item,
album=opts.album, verbose=True)[1])
fuzzy_cmd = Subcommand('fuzzy',
help='list items using fuzzy matching')
fuzzy_cmd.parser.add_option('-a', '--album', action='store_true',
help='choose an album instead of track')
fuzzy_cmd.parser.add_option('-p', '--path', action='store_true',
help='print the path of the matched item')
fuzzy_cmd.parser.add_option('-f', '--format', action='store',
help='print with custom format', default=None)
fuzzy_cmd.parser.add_option('-v', '--verbose', action='store_true',
help='output scores for matches')
fuzzy_cmd.parser.add_option('-t', '--threshold', action='store',
help='return result with a fuzzy score above threshold. \
(default is 0.7)', default=None)
fuzzy_cmd.func = fuzzy_list
class Fuzzy(BeetsPlugin):
def __init__(self): def __init__(self):
super(Fuzzy, self).__init__() super(FuzzyPlugin, self).__init__(self)
self.config.add({
'threshold': 0.7,
})
def commands(self): def queries(self):
return [fuzzy_cmd] return [FuzzyQuery]