Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Merge pull request #48 from phmongeau/fuzzy

Fuzzy Search plugin
  • Loading branch information...
commit 0d3064bae8ce442febeba9a23b8713432175a389 2 parents 201571b + a49dcb8
@sampsyo authored
Showing with 121 additions and 0 deletions.
  1. +101 −0 beetsplug/fuzzy_search.py
  2. +20 −0 docs/plugins/fuzzy_search.rst
View
101 beetsplug/fuzzy_search.py
@@ -0,0 +1,101 @@
+# This file is part of beets.
+# Copyright 2011, Philippe Mongeau.
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+
+"""Like beet list, but with fuzzy matching
+"""
+from beets.plugins import BeetsPlugin
+from beets.ui import Subcommand, decargs, print_
+from beets.util.functemplate import Template
+import difflib
+
+# THRESHOLD = 0.7
+
+
+def fuzzy_score(query, item):
+ return difflib.SequenceMatcher(a=query, b=item).quick_ratio()
+
+
+def is_match(query, item, album=False, verbose=False, threshold=0.7):
+ query = ' '.join(query)
+
+ if album:
+ values = [item.albumartist, item.album]
+ else:
+ values = [item.artist, item.album, item.title]
+
+ s = max(fuzzy_score(query.lower(), i.lower()) for i in values)
+ if s >= threshold:
+ return (True, s) if verbose else True
+ else:
+ return (False, s) if verbose else False
+
+
+def fuzzy_list(lib, config, opts, args):
+ query = decargs(args)
+ path = opts.path
+ fmt = opts.format
+ verbose = opts.verbose
+ threshold = float(opts.threshold)
+
+ if fmt is None:
+ # If no specific template is supplied, use a default
+ if opts.album:
+ fmt = u'$albumartist - $album'
+ else:
+ fmt = u'$artist - $album - $title'
+ template = Template(fmt)
+
+ if opts.album:
+ objs = lib.albums()
+ else:
+ objs = lib.items()
+
+ if opts.album:
+ for album in objs:
+ if is_match(query, album, album=True, threshold=threshold):
+ if path:
+ print_(album.item_dir())
+ else:
+ print_(album.evaluate_template(template))
+ if verbose:
+ print is_match(query, album, album=True, verbose=True)[1]
+ else:
+ for item in objs:
+ if is_match(query, item, threshold=threshold):
+ if path:
+ print_(item.path)
+ else:
+ print_(item.evaluate_template(template, lib))
+ if verbose:
+ print is_match(query, item, 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=0.7)
+fuzzy_cmd.func = fuzzy_list
+
+
+class Fuzzy(BeetsPlugin):
+ def commands(self):
+ return [fuzzy_cmd]
View
20 docs/plugins/fuzzy_search.rst
@@ -0,0 +1,20 @@
+Fuzzy Search Plugin
+=============
+
+The ``fuzzy_search`` plugin provides a command that search your library using
+fuzzy pattern matching. This can be useful if you want to find a track with complicated characters in the title.
+
+First, enable the plugin named ``fuzzy_search`` (see :doc:`/plugins/index`).
+You'll then be able to use the ``beet fuzzy`` command::
+
+ $ beet fuzzy Vareoldur
+ Sigur Rós - Valtari - Varðeldur
+
+The command has several options that resemble those for the ``beet list``
+command (see :doc:`/reference/cli`). To choose an album instead of a single
+track, use ``-a``; to print paths to items instead of metadata, use ``-p``; and
+to use a custom format for printing, use ``-f FORMAT``.
+
+The ``-t NUMBER`` option lets you specify how precise the fuzzy match has to be
+(default is 0.7). To make a fuzzier search, try ``beet fuzzy -t 0.5 Varoeldur``.
+A value of ``1`` will show only perfect matches and a value of ``0`` will match everything.
Please sign in to comment.
Something went wrong with that request. Please try again.