diff --git a/beets/library.py b/beets/library.py index 1cfe87f0c..86fcf7c20 100644 --- a/beets/library.py +++ b/beets/library.py @@ -1453,7 +1453,9 @@ class DefaultTemplateFunctions(object): from "disam" is used in the string if one is sufficient to disambiguate the albums. Otherwise, a fallback opaque value is used. Both "keys" and "disam" should be given as - whitespace-separated lists of field names. + whitespace-separated lists of field names, while "bracket" is a + pair of characters to be used as brackets surrounding the + disambiguator or a white space to have no brackets. """ # Fast paths: no album, no item or library, or memoized value. if not self.item or not self.lib: @@ -1470,7 +1472,15 @@ class DefaultTemplateFunctions(object): bracket = bracket or '[]' keys = keys.split() disam = disam.split() - bracket = None if bracket is ' ' else list(bracket) + bracket = None if bracket == ' ' else list(bracket) + + # Assign a left and right bracket from bracket list. + if bracket: + bracket_l = bracket[0] + bracket_r = bracket[1] + else: + bracket_l = u'' + bracket_r = u'' album = self.lib.get_album(self.item) if not album: @@ -1504,18 +1514,17 @@ class DefaultTemplateFunctions(object): else: # No disambiguator distinguished all fields. - res = u' {1}{0}{2}'.format(album.id, bracket[0] if bracket else - u'', bracket[1] if bracket else u'') + res = u' {1}{0}{2}'.format(album.id, bracket_l, bracket_r) self.lib._memotable[memokey] = res return res # Flatten disambiguation value into a string. disam_value = album.formatted(True).get(disambiguator) - res = u' {1}{0}{2}'.format(disam_value, bracket[0] if bracket else u'', - bracket[1] if bracket else u'') - # Remove space and/or brackets if disambiguation value is empty - if bracket and res == u' ' + ''.join(bracket) or res.isspace(): + # Return empty string if disambiguator is empty. + if disam_value: + res = u' {1}{0}{2}'.format(disam_value, bracket_l, bracket_r) + else: res = u'' self.lib._memotable[memokey] = res diff --git a/docs/changelog.rst b/docs/changelog.rst index 4fa8aa50f..e2849c22d 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -17,6 +17,11 @@ New features: return the item info for the file at the given path, or 404. * The :doc:`/plugins/web` also has a new config option, ``include_paths``, which will cause paths to be included in item API responses if set to true. +* The ``%aunique`` template function for :ref:`aunique` now takes a third + argument that specifies which brackets to use around the disambiguator + value. The argument can be any two characters that represent the left and + right brackets. It defaults to `[]` and can also be a white space to turn off + bracketing. :bug:`2397` :bug:`2399` Fixes: diff --git a/docs/reference/pathformat.rst b/docs/reference/pathformat.rst index de1185ae0..873a51c5e 100644 --- a/docs/reference/pathformat.rst +++ b/docs/reference/pathformat.rst @@ -129,8 +129,10 @@ disambiguation behavior if you just use ``%aunique{}`` with no parameters in your path forms (as in the default path formats), but you can customize the disambiguation if, for example, you include the year by default in path formats. -The default characters used as brackets are ``[]``. If a single blank space is -used, then the disambiguator will not be surrounded by anything. +The default characters used as brackets are ``[]``. To change this, provide a +third argument to the ``%aunique`` function consisting of two characters: the left +and right brackets. Or, to turn off bracketing entirely, use a single blank +space. One caveat: When you import an album that is named identically to one already in your library, the *first* album—the one already in your library— will not diff --git a/test/test_library.py b/test/test_library.py index d2c21d5f6..9e1301880 100644 --- a/test/test_library.py +++ b/test/test_library.py @@ -730,6 +730,16 @@ class DisambiguationTest(_common.TestCase, PathFormattingMixin): self._setf(u'foo%aunique{albumartist album,albumtype}/$title') self._assert_dest(b'/base/foo [foo_bar]/the title', self.i1) + def test_drop_empty_disam_string(self): + album1 = self.lib.get_album(self.i1) + album1.year = None + album1.store() + self._assert_dest(b'/base/foo/the title', self.i1) + + def test_change_brackets(self): + self._setf(u'foo%aunique{albumartist album,year,()}/$title') + self._assert_dest(b'/base/foo (2001)/the title', self.i1) + class PluginDestinationTest(_common.TestCase): def setUp(self):